Вот один из способов:
грех (а) ^ 2 + соз (а) ^ 2 = 1 (пифагор)
cos (a) = sqrt (1 - sin (a) ^ 2))
Вам необходимо выяснить различные квадранты (т.е. знак cos () отдельно). Это невозможно, если все, что у вас есть, это значение sin () (разные углы могут иметь одинаковый sin (), но cos () отличается знаком).
Как отмечали другие люди, на практике таблица поиска может быть самой быстрой. Зависит от того, какая точность вам требуется. Это почти наверняка будет быстрее, чем ваша версия cos (asin ()), а квадратный корень также может быть оптимизирован на практике .
- SSE и ARM-NEON имеют инструкцию квадратного корня, но не имеют функций триггера.
- x87 имеет квадратный корень и sin / cos, но не имеет обратных функций sin / cos. Квадратный корень быстрее, чем грех / cos.
При использовании Visual Studio 2010 производительность этого метода примерно в 6 раз выше, чем у версии на основе триггеров (с опцией быстрой плавающей запятой) на моем ноутбуке Core i3 (около 20 нс на вызов). Давайте посмотрим на сгенерированный код:
Опция быстрой с плавающей запятой с использованием квадратного корня:
; 15 : return sqrt(1.0 - s*s);
movsd xmm1, QWORD PTR __real@3ff0000000000000
mulsd xmm0, xmm0
subsd xmm1, xmm0
sqrtsd xmm0, xmm1
Использование функций триггера:
; 22 : return cos(asin(s));
call ___libm_sse2_asin
jmp ___libm_sse2_cos
При переключении в точный режим с плавающей запятой сгенерированный код триггера использует различные функции (предположительно оптимизированные для SSE версии жертвуют точностью):
fld QWORD PTR _angle_sin$[esp+esi+65600]
call __CIasin
call __CIcos
fstp QWORD PTR _angle_cos$[esp+esi+65600]