|
Fixed point math routines
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);
int fixtoi(fixed x);
int fixfloor(fixed x);
int fixceil(fixed x);
fixed ftofix(float x);
float fixtof(fixed x);
fixed fixmul(fixed x, fixed y); 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 fixmul().
fixed fixdiv(fixed x, fixed y);
fixed fixadd(fixed x, fixed y);
fixed fixsub(fixed x, fixed y); 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 fixsin(fixed x);
fixed fixcos(fixed x);
fixed fixtan(fixed x);
fixed fixasin(fixed x);
fixed fixacos(fixed x);
fixed fixatan(fixed x);
fixed fixatan2(fixed y, fixed x);
fixed fixsqrt(fixed x);
fixed fixhypot(fixed x, fixed y);
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 fixsqrt(x) will return the wrong result. You should use the overloaded sqrt(x) or x.sqrt() instead.
The fixed point functions used to be named with an "f" prefix instead of "fix", eg. fixsqrt() used to be fsqrt(), but were renamed due to conflicts with some libc implementations. This should not affect most existing code as there are backwards compatibility aliases. These aliases are static inline functions which map the old names to the new names, eg. fsqrt() calls fixsqrt(). You can disable the aliases by defining the preprocessor macro ALLEGRO_NO_FIX_ALIASES before including allegro.h.
|