Benchmarking Math.sin/cos isn't very useful. They should benchmark FloatMath.sin/cos, since that is what you would use on Android.

On a related note, I have experimented with fixed point and found it doesn't really make a difference. Just go ahead and use floats. If you are writing code that is going to be slow with float, it is going to be slow fixed, and your only recourse is to move it to native code (which is very easy, kudos to the Android team!).

On #3: sin(A + B) = sin(A) cos(B) + cos(A) sin(B), cos(A + B) = cos(A) cos(B) - sin(A) sin(B)One approach would be to multiply the input x by 2 * Pi * (1 << 24), mask off the bottom three bytes individually and do six lookups (total table space required: 256 * 6 entries, probably optimisable to 256*3 if you want to trade memory for some subtractions). 8 multiplications and 4 additions gets you sin x and cos x (or 6 multiplications and 3 additions if you only want one of them).With a bit more memory (16k entries if you're using 24 bits of the input) you can reduce that to four lookups, two multiplications, and one addition for sin, same for cos (although obv. if doing both you don't double the lookups).

I'd suggest timing random table reads (if possible) on the lowest end target. Many modern processors (including those used in embedded systems) will have large timing hits for reading from big tables and an approximation will be faster.

For approximations, truncated power series are pretty bad (bang for your buck) in float or fixed point. Think minimax, generalized pade, et al.

Nb: I think that you would be surprised on how precise and fast (addition and multiplication are usually very fast on any cpu) can be the taylor serie (the long version ) especially if you inline it (this avoid a method call), it can be nearly as fast as a lookup table (due to random array cache trouble and other performance problem with access to array), you should really give it a try.

EDIT : also another problem you may have with the lookup table is casting from floating point value to int (to index the lookup array) as casting from floating to fixed is damnly slow

yes sure series are truncated (they must be) but the good thing is that cosinus is symetrical and periodical, so you can always convert an input angle into the range 0 to 0.5*PI and found the result (using for example a modulo) and then it will just give you a smart result as you are always using something like the 'best range' for that serie.

ok you are right at first I missunderstood and read min & max and not minimax but .... this is finally the same in the particular case of cosinus as those minimax error will be more and more noticable if you get farther than 0, so clamping input into 0 to 0.5PI make them so small that the real Math.cos may introduce bigger error than the taylor serie, an example is given in the original source code where :

Riven, thanks for the lookup code (I was using modulus instead of masking...).

Your atan2 lookup, run on my desktop, takes about 1.6 times longer than the atan2 I posted above. However, yours is quite a bit more accurate. It is good to have options! Both are waaay faster (5+ times) than Math.atan2. That was the desktop, on the G1 I see (10k iterations with 20k precalculated random numbers):Math.atan2: 159.66797Riven's atan2: 58.86841Nate's atan2: 48.49243So, a smaller difference all around.

I played with Riven's lookup table and DzzD's low precision forumula. Benchmark code:

thanks for the test, any chance to get a high resolution test plz ? (up to F16)

but wow, I am realy suprised by lookup fastness

EDIT : hum seems that the rules have changed on Android with lookup table, I run your test again (but on a laptop, sry but dont have any Android device yet) using Riven lookup/Java/ and original taylor (but converted from double to float and up to F20)

Accuracy was just showing the accurate value from java.lang.Math and the inaccurate value from other algorithms. Riven greatly improved (and clarified) the benchmark! The time results are to give some (vague) idea of the speed improvement of using the less accurate algorithms.

On a desktop, this stuff is mostly moot, but it does end up mattering for the current Android phones, which I think is kind of fun.

You'd be surprised. Back in the 1.4 days when JNI was slooooooow doing trig was the major bottleneck in a game I was working on and it ended up being worthwhile porting the native implementations of sin and cos to Java.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org