从罪中获得cos(a)的最佳方法(a)

lve*_*lla 7 c++ floating-point trigonometry

s一些(未知)角度"a"的正弦,获得"余弦"的最快方法是什么?

我知道两种不同的方式:

c = cos(asin(s));
Run Code Online (Sandbox Code Playgroud)

c = sqrt(1 - s*s);
Run Code Online (Sandbox Code Playgroud)

但我不知道函数cos(),asin()和sqrt()的实现如何在速度方面相互比较.一个人比另一个人快多快?它们在现代处理器中的实现之间是否存在显着差异,例如,在x86-64和带VFP的ARM之间?最后,什么是更好的解决方案?

编辑:由于现在已经有3个不相关的答案,让我澄清一下:我最初没有这个角度,我只有正弦.所以没有必要告诉我将角度旋转90度所以我将从另一个函数获得相同的值...

Guy*_*ton 8

这是一种方式:

sin(a)^ 2 + cos(a)^ 2 = 1(毕达哥拉斯)

cos(a)= sqrt(1 - sin(a)^ 2))

你需要找出不同的象限(即cos()的符号分开).如果您拥有的是sin()值(不同的角度可以具有相同的sin()但cos()因符号而异),则这是不可能的.

正如其他人所指出的,查找表实际上可能是最快的.取决于您需要的精度.这几乎肯定会比你的cos(asin())版本更快,并且平方根也可以在实践中进行优化.

  • SSE和ARM-NEON具有平方根指令但没有trig函数.
  • x87具有平方根和sin/cos但没有反sin/cos函数.平方根比sin/cos快.

使用Visual Studio 2010,此方法的性能比我的Core i3笔记本电脑上的基于trig的版本(具有快速浮点选项)快约6倍(每次调用大约20ns).我们来看看生成的代码:

快速浮点选项,使用平方根:

; 15   :     return sqrt(1.0 - s*s);

    movsd   xmm1, QWORD PTR __real@3ff0000000000000
    mulsd   xmm0, xmm0
    subsd   xmm1, xmm0
    sqrtsd  xmm0, xmm1
Run Code Online (Sandbox Code Playgroud)

使用trig函数:

; 22   :     return cos(asin(s));
call    ___libm_sse2_asin
jmp ___libm_sse2_cos
Run Code Online (Sandbox Code Playgroud)

切换到精确浮点模式时,生成的触发代码使用不同的功能(可能是SSE优化版本牺牲精度):

fld QWORD PTR _angle_sin$[esp+esi+65600]
call    __CIasin
call    __CIcos
fstp    QWORD PTR _angle_cos$[esp+esi+65600]
Run Code Online (Sandbox Code Playgroud)