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.
Unfortunately the only advantage of fixed point math routines is that you
don't require a floating point coprocessor to use them. This was great in the
time period of i386 and i486 machines, but stopped being so useful with the
coming of the Pentium class of processors. From Pentium onwards, CPUs have
increased their strength in floating point operations, equaling or even
surpassing integer math performance.
Depending on the type of operations your program may need, using floating
point types may be faster than fixed types if you are targeting a specific
machine class. Allegro comes with a test program in the `allegro/tests'
directory. Its `Misc' menu contains a basic profile test which can give you
an idea of the speed difference between fixed and float types for a few basic
operations on your machine. However, don't forget to profile your program in
real life conditions, tight loop benchmarks are after all artificial.
Fixed point math is considered "add-on" material and is kept only for
backwards compatibility. Whenever a future release of Allegro breaks backwards
compatibility, fixed point math will likely be moved to a separate add-on
package for the very few users who still find it convenient and useful, and
Allegro functions using fixed point math will use other types.
- itofix - Converts an integer to fixed point.
- fixtoi - Converts a fixed point to integer with rounding.
- fixfloor - Returns the greatest integer not greater than x.
- fixceil - Returns the smallest integer not less than x.
- ftofix - Converts a floating point value to fixed point.
- fixtof - Converts a fixed point to floating point.
- fixmul - Multiplies two fixed point values together.
- fixdiv - Fixed point division.
- fixadd - Safe function to add fixed point numbers clamping overflow.
- fixsub - Safe function to subtract fixed point numbers clamping underflow.
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. Note that on
machines with very good floating point processors using these functions could
be slower in real life code due to cache misses: it may be faster to wait
a few extra cicles for a floating point sine result rather than wait for the
CPU to fetch the precalculated table from main memory. Always profile your
code.
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.
- fixtorad_r - Constant to convert angles in fixed point format to radians.
- radtofix_r - Constant to convert radians to fixed point angles.
- fixsin - Fixed point sine of binary angles.
- fixcos - Fixed point cosine of binary angles.
- fixtan - Fixed point tangent of binary angles.
- fixasin - Fixed point inverse sine lookup table.
- fixacos - Fixed point inverse cosine lookup table.
- fixatan - Fixed point inverse tangent lookup table.
- fixatan2 - Fixed point version of the libc atan2() routine.
- fixsqrt - Fixed point square root.
- fixhypot - Fixed point hypotenuse.
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.
On top of that, the Fix class may be slower than using directly the C
functions because of implicit internal conversions from one type to another
which you otherwise could avoid or minimise. Finally, this is the only bit
of C++ in the whole Allegro library, and the developers are certainly going
to move it into add-on space in the next version of Allegro which breaks
source backwards compatibility.