In a lot of situations I not only need the sine, but also the cosine of the same parameter.
For C, there is the sincos
function in the common unix m
math library. And actually, at least on i386, this should be a single assembly instruction, fsincos
.
sincos, sincosf, sincosl - calculate sin and cos simultaneously
I guess these benefits exist because there is an obvious overlap in computing sine and cosine: sin(x)^2 + cos(x)^2 = 1
. But AFAIK it does not pay off to try to shortcut this as cos = Math.sqrt(1 - sin*sin)
, as the sqrt
function comes at a similar cost.
Is there any way to reap the same benefits in Java? I guess I'm going to pay a price for a double[]
then; which maybe makes all the efforts moot because of the added garbage collection.
Or is the Hotspot compiler smart enough to recognize that I need both, and will compile this to a sincos
command? Can I test whether it recognizes it, and can I help it recognizing this, e.g. by making sure the Math.sin
and Math.cos
commands are directly successive in my code? This would actually make the most sense from a Java language point of view: having the comiler optimize this to use the fsincos
assembly call.
Collected from some assembler documentation:
Variations 8087 287 387 486 Pentium
fsin - - 122-771 257-354 16-126 NP
fsincos - - 194-809 292-365 17-137 NP
Additional cycles required if operand > pi/4 (~3.141/4 = ~.785)
sqrt 180-186 180-186 122-129 83-87 70 NP
fsincos
should need an extra pop, but that should come at 1 clock cycle. Assuming that the CPU also does not optimize this, sincos
should be almost twice as fast as calling sin
twice (second time to compute cosine; so i figure it will need to do an addition). sqrt
could be faster in some situations, but sine can be faster.
Update: I've done some experiments in C, but they are inconclusive. Interestingly enough, sincos
seems to be even slightly faster than sin
(without cos
), and the GCC compiler will use fsincos
when you compute both sin
and cos
- so it does what I'd like Hotspot to do (or does Hotspot, too?). I could not yet prevent the compiler from outsmarting me by using fsincos
except by not using cos
. It will then fall back to a C sin
, not fsin
.