Allegro provides some routines for working with fixed point numbers, and defines the type 'fixed' to be a signed 32 bit integer. The high word is used for the integer part and the low word for the fraction, giving a range of -32768 to 32767 and an accuracy of about four or five decimal places. Fixed point numbers can be assigned, compared, added, subtracted, negated and shifted (for multiplying or dividing by powers of two) using the normal integer operators, but you should take care to use the appropriate conversion routines when mixing fixed point with integer or floating point values. Writing 'fixed_point_1 + fixed_point_2' is ok, but 'fixed_point + integer' is not.
fixed itofix(int x);
Converts an integer to fixed point. This is the same thing as x<<16.
int fixtoi(fixed x);
Converts fixed point to integer, rounding as required. If you want to
avoid the rounding, use x>>16 instead.
fixed ftofix(float x);
Converts a floating point value to fixed point.
float fixtof(fixed x);
Converts fixed point to floating point.
fixed fmul(fixed x, fixed y);
A fixed point value can be multiplied or divided by an integer with the
normal '*' and '/' operators. To multiply two fixed point values, though,
you must use this function.
If an overflow or division by zero occurs, errno will be set and the maximum possible value will be returned, but errno is not cleared if the operation is successful. This means that if you are going to test for overflow you should set errno=0 before calling fmul().
fixed fdiv(fixed x, fixed y);
Fixed point division: see comments about fmul().
fixed fadd(fixed x, fixed y);
Although fixed point numbers can be added with the normal '+' integer
operator, that doesn't provide any protection against overflow. If
overflow is a problem, you should use this function instead. It is slower
than using integer operators, but if an overflow occurs it will clamp the
result, rather than just letting it wrap, and set errno.
fixed fsub(fixed x, fixed y);
Fixed point subtraction: see comments about fadd().
The fixed point square root, sin, cos, tan, inverse sin, and inverse cos functions are implemented using lookup tables, which are very fast but not particularly accurate. At the moment the inverse tan uses an iterative search on the tan table, so it is a lot slower than the others.
Angles are represented in a binary format with 256 equal to a full circle, 64 being a right angle and so on. This has the advantage that a simple bitwise 'and' can be used to keep the angle within the range zero to a full circle, eliminating all those tiresome 'if (angle >= 360)' checks.
fixed fsin(fixed x);
Lookup table sine.
fixed fcos(fixed x);
Lookup table cosine.
fixed ftan(fixed x);
Lookup table tangent.
fixed fasin(fixed x);
Lookup table inverse sine.
fixed facos(fixed x);
Lookup table inverse cosine.
fixed fatan(fixed x);
Fixed point inverse tangent.
fixed fatan2(fixed y, fixed x);
Fixed point version of the libc atan2() routine.
fixed fsqrt(fixed x);
Fixed point square root.
If you are programming in C++ you can ignore all the above and use the fix class instead, which overloads a lot of operators to provide automatic conversion to and from integer and floating point values, and calls the above routines as they are required. You should not mix the fix class with the fixed typedef though, because the compiler will mistake the fixed values for regular integers and insert unnecessary conversions. For example, if x is an object of class fix, calling fsqrt(x) will return the wrong result. You should use the overloaded sqrt(x) or x.sqrt() instead.