As an example, here's an expression that computes
x*a+y*b+z*c using the
Beartronics FP library available on SourceForge.
FP.Mul(x,a)+FP.Mul(y,b)+FP.Mul(z,c)
The above expression is common in 3-D game code to scale, rotate and translate points according to a transformation matrix. If you inline the FP arithmetic code in the expression to get rid of the FP calls, you'd end up with code like this (all FP numbers are considered to be 16.16 bits):
((((int)((((long)x) * ((long)a)) >> 16))+
((int)((((long)y) * ((long)b)) >> 16)))+
((int)((((long)z) * ((long)c)) >> 16)))
The multiplications in the preceding code cast the operands to longs (because a 16.16 number multiplied by another 16.16 number yields a 32.32 number that has 64 bits), perform the multiplication and shift the 32.32 result back to 16.16 (the 16 most and the 16 least significant bits are lost).
A Performance Comparison
Now some speed test results. The numbers below show the time spent, in milliseconds, to compute the example expression 1,000,000 times, with the FP library and with inlined FP code. The tests were run five times each and the results presented here are the mean. The time spent to run an empty loop 1,000,000 times is also presented:
FP library 135,536
Inline 16,728
Empty loop 2,516
| Author's Note: The programs were run with the J2ME Wireless Toolkit version 2.1. I measured the empty loop time to be able to compare the time spent just in the expression, removing the time spent on the loop increment, compare, and jump. |
Discounting the time to run the empty loop, you can see that the inlined code runs in about one tenth of the time required by the code with FP library calls! From a pure performance perspective, the inlining was definitely worth the effort. The only problem is that translating such expressions to inlined FP arithmetic is a complicated process. Any error in that process can lead to bugs that are very difficult to catch.
Wouldn't it be nice if you could
automatically convert an expression to use inlined FP arithmetic? Fortunately, now you can.
Converting Expressions Automatically
You can convert any FP expression to use inlined FP. To do that you need a lexical analyzer, a parser, and a code generator that spits out inlined FP arithmetic.
The
code that accompanies this article contains a command-line expression parser called "FPComp." FPComp reads an expression supplied as an argument and outputs Java code with the FP operations inlined. It assumes that all numbers and identifiers are FP numbers in the 16.16 format and that all function calls take FP expressions as arguments and return an FP value, unless you use the
-i option.
Figure 1 shows two usage examples.
 | |
| Figure 1. FPComp In Interactive Mode: When you pass FPComp an expression, it returns the expression written in inlined code, which you would then insert in place of the original expression in your code. |
To use FPComp in interactive mode, you can simply copy the returned inlined code and paste it in place of your original expression.
| Warning: Don't forget to save a copy of the original expression inside a comment; the expressions generated by FPComp can get very cryptic and you won't be able to easily recall what it is supposed to do. |