28 Rutinas matemáticas de punto fijo



Allegro trae algunas rutinas para trabajar con números de punto fijo, y define el tipo 'fixed' como un entero de 32 bits con signo. La parte alta es usada por el valor del entero y la parte baja es usada por el valor de la fracción, dando un rango de valores de -32768 a 32767 y un detalle de unos 4 o 5 decimales. Los números de punto fijo pueden ser asignados, comparados, añadidos, substraídos, negados y desplazados (para multiplicar o dividir por potencias de 2) usando los operadores de enteros normales, pero tendría que tener cuidado de usar las rutinas de conversión apropiadas cuando combine números de punto fijo con enteros o números de coma flotante. Escribir 'punto_fijo_1 + punto_fijo_2' esta bien, pero 'punto_fijo + entero' no esta bien.

fixed itofix(int x);
Convierte un valor de entero a punto fijo. Esto es lo mismo que x<<16.

int fixtoi(fixed x);
Convierte un valor de punto fijo a entero, redondeando. Si quieres evitar el redondeo, usa x>>16.

fixed ftofix(float x);
Convierte un valor de coma flotante a punto fijo.

float fixtof(fixed x);
Convierte un valor de punto fijo a coma flotante.

fixed fmul(fixed x, fixed y);
Un valor de punto fijo puede ser multiplicado o dividido por un entero con los operadores normales '*' y '/'. Sin embargo, para multiplicar dos valores de punto fijo necesita usar esta función.

Si hay desbordamiento o división por cero, errno será activado y el valor máximo posible será devuelto, pero errno no es limpiado si la operación es realizada con éxito. Esto significa que si va a comprobar un desbordamiento de división, debería poner errno=0 antes de llamar a fmul().

fixed fdiv(fixed x, fixed y);
División de valores de punto fijo: mire fmul().

fixed fadd(fixed x, fixed y);
A pesar de que los números de punto fijo pueden ser añadidos con el operador normal de enteros '+', eso no le da protección contra desbordamientos. Si el desbordamiento es un problema, debería usar esta función. Es mas lenta que los operadores de enteros, pero si hay un desbordamiento de división, ajustará el tamaño del resultado en vez de dejarlo al azar, y activara errno.

fixed fsub(fixed x, fixed y);
Resta de números en punto fijo: mire fadd().

Las funciones de raíz cuadrada, seno, coseno, tangente, cosecante y secante están implementadas usando tablas precalculadas, que son muy rápidas pero no muy exactas. Por ahora, la cotangente realiza una búsqueda iterativa en la tabla de la tangente, por lo que es mas lenta que las otras.

Los ángulos están representados en formato binario con 256 siendo igual al círculo completo, 64 es un cuarto de ángulo y así sucesivamente. Esto tiene la ventaja de que un 'and' a nivel de bits puede ser usado para que el ángulo quede entre cero y el círculo completo, eliminando esos tests cansinos 'if (angle >= 360)'.

fixed fsin(fixed x);
Mira la tabla precalculada del seno.

fixed fcos(fixed x);
Mira la tabla precalculada del coseno.

fixed ftan(fixed x);
Mira la tabla precalculada de la tangente.

fixed fasin(fixed x);
Mira la tabla de la cosecante.

fixed facos(fixed x);
Mira la tabla de la secante.

fixed fatan(fixed x);
Cotangente de punto fijo.

fixed fatan2(fixed y, fixed x);
Versión de punto fijo de la rutina atan2() de libc.

fixed fsqrt(fixed x);
Raíz cuadrada de punto fijo.



Si está programando en C++ puede ignorar todo lo de arriba y usar la clase "fija", que sobrecarga muchos operadores para proveer conversión automática desde y hacia valores enteros y de coma flotante, y llama las rutinas de arriba cuando se necesitan. Sin embargo no debería mezclar la clase "fija" con los typedefs de punto fijo, ya que el compilador tratará los valores de punto fijo como enteros regulares e insertará conversiones innecesarias. Por ejemplo, si x es un objeto de clase fija, llamar fsqrt(x) devolverá un resultado erróneo. Debería usar sqrt(x) o x.swrt() en vez de eso.




Volver al Indice