在很多情况下,我不仅需要正弦,还需要相同参数的余弦。
对于 C,sincos
在通用 unixm
数学库中有该函数。实际上,至少在 i386 上,这应该是一条汇编指令,fsincos
.
sincos, sincosf, sincosl - 同时计算 sin 和 cos
我猜这些好处是存在的,因为在计算正弦和余弦方面存在明显的重叠:sin(x)^2 + cos(x)^2 = 1
. 但是 AFAIK 尝试将其简化为 并没有回报cos = Math.sqrt(1 - sin*sin)
,因为该sqrt
功能的成本相似。
有没有办法在 Java 中获得同样的好处?我想我会为此付出代价double[]
;由于添加了垃圾收集,这可能会使所有努力都变得毫无意义。
或者 Hotspot 编译器是否足够聪明,可以识别出我需要两者,并将其编译为sincos
命令?我可以测试它是否识别它,并且我可以帮助它识别它吗,例如通过确保Math.sin
andMath.cos
命令在我的代码中是直接连续的?从 Java 语言的角度来看,这实际上是最有意义的:让编译器优化它以使用fsincos
汇编调用。
从一些汇编器文档中收集:
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
应该需要一个额外的pop,但这应该是1个时钟周期。假设 CPU 也没有对此进行优化,sincos
应该几乎是调用sin
两次的两倍(第二次计算余弦;所以我认为它需要做一个加法)。sqrt
在某些情况下可能更快,但正弦可以更快。
更新:我在 C 中做了一些实验,但没有定论。有趣的是,sincos
它似乎比sin
(没有)还要快一些,并且当您计算两者时,cos
GCC 编译器将使用- 所以它可以做我希望 Hotspot 做的事情(或者 Hotspot 也做?)。我还不能阻止编译器通过使用除了不使用. 然后它将回退到 C ,而不是.fsincos
sin
cos
fsincos
cos
sin
fsin