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);

Converts an integer to fixed point. This is the same thing as x<<16.
See also: fixtoi, ftofix, fixtof.
int fixtoi(fixed x);

Converts fixed point to integer, rounding as required.
See also: itofix, ftofix, fixtof, fixfloor, fixceil.
int fixfloor(fixed x);

Returns the greatest integer not greater than x. That is, it rounds towards negative infinity.
See also: fixtoi, fixceil.
int fixceil(fixed x);

Returns the smallest integer not less than x. That is, it rounds towards positive infinity.
See also: fixtoi, fixfloor.
fixed ftofix(double x);

Converts a floating point value to fixed point.
See also: fixtof, itofix, fixtoi.
double fixtof(fixed x);

Converts fixed point to floating point.
See also: ftofix, itofix, fixtoi.
fixed fixmul(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 fixmul().

See also: fixadd, fixsub, fixdiv.
fixed fixdiv(fixed x, fixed y);

Fixed point division: see comments about fixmul().
See also: fixadd, fixsub, fixmul.
fixed fixadd(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.
See also: fixsub, fixmul, fixdiv.
fixed fixsub(fixed x, fixed y);

Fixed point subtraction: see comments about fixadd().
See also: fixadd, fixmul, fixdiv.

Fixed point trig

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.


extern const fixed fixtorad_r;

This constant gives a ratio which can be used to convert a number in fixed point angle format to a number in radians: if 'y' is an angle in fixed point angle format then use: 'x = fixmul(y, fixtorad_r);' to get its value 'x' in radians.
See also: fixmul, radtofix_r.
extern const fixed radtofix_r;

This constant gives a ratio which can be used to convert a number in radians to a number in fixed point angle format: if 'x' is an angle in radians, then use: 'y = fixmul(x, radtofix_r);' to get its value 'y' in fixed point angle format.
See also: fixmul, fixtorad_r.
fixed fixsin(fixed x);

Lookup table sine.
See also: Fixed point trig.
fixed fixcos(fixed x);

Lookup table cosine.
See also: Fixed point trig.
fixed fixtan(fixed x);

Lookup table tangent.
See also: Fixed point trig.
fixed fixasin(fixed x);

Lookup table inverse sine.
See also: Fixed point trig.
fixed fixacos(fixed x);

Lookup table inverse cosine.
See also: Fixed point trig.
fixed fixatan(fixed x);

Fixed point inverse tangent.
See also: Fixed point trig.
fixed fixatan2(fixed y, fixed x);

Fixed point version of the libc atan2() routine.
See also: Fixed point trig.
fixed fixsqrt(fixed x);

Fixed point square root.
See also: Fixed point trig.
fixed fixhypot(fixed x, fixed y);

Fixed point hypotenuse (returns the square root of x*x + y*y).
See also: Fixed point trig.

Fix class

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.



Back to contents