Here is one way:
sin (a) ^ 2 + cos (a) ^ 2 = 1 (pythagoras)
cos (a) = sqrt (1 - sin (a) ^ 2))
You need to figure out the different quadrants (i.e. the cos () sign separately). This is not possible if all you have is sin () (different angles may have the same sin (), but cos () is different in sign).
As other people have noted, a checklist in practice may be the fastest. Depends on what accuracy you require. It will almost certainly be faster than the version of your cos (asin ()), and the square root can also be optimized in practice.
- SSE and ARM-NEON have a square root instruction, but no trigger functions.
- x87 has the square root and sin / cos, but does not have the inverse sin / cos functions. The square root is faster than sin / cos.
Using Visual Studio 2010, the performance of this method is about 6 times higher than the trigger-based version (with the fast floating-point option) on my Core i3 laptop (about 20 ns per call). Let's look at the generated code:
Quick floating point option using square root:
; 15 : return sqrt(1.0 - s*s); movsd xmm1, QWORD PTR __real@3ff0000000000000 mulsd xmm0, xmm0 subsd xmm1, xmm0 sqrtsd xmm0, xmm1
Using trigger functions:
; 22 : return cos(asin(s)); call ___libm_sse2_asin jmp ___libm_sse2_cos
When switching to the exact floating point mode, the generated trigger code uses different functions (presumably SSE-optimized versions sacrifice accuracy):
fld QWORD PTR _angle_sin$[esp+esi+65600] call __CIasin call __CIcos fstp QWORD PTR _angle_cos$[esp+esi+65600]
source share