Как реализуется arctan?
многие реализации библиотеки идут глубоко вниз к fpatan instuction для всех arc-функций. Как реализуется FPATAN? Предполагая, что у нас есть знак 1 бит, M бит мантиссы и n бит экспоненты, каков алгоритм получения арктангенса этого числа? Должен быть такой алгоритм, так как это делает FPU.
3 ответов
тригонометрические функции имеют довольно уродливые реализации, которые являются хакерскими и делают много битной скрипки. Я думаю, что будет довольно сложно найти здесь кого-то, кто сможет объяснить алгоритм, который фактически используется.
вот реализация atan2: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ieee754/dbl-64/e_atan2.c;h=a287ca6656b210c77367eec3c46d72f18476d61d;hb=HEAD
Edit: на самом деле я нашел этот: http://www.netlib.org/fdlibm/e_atan2.c что намного проще следовать, но, вероятно, медленнее из-за этого (?).
FPU делает все это в некоторых схемах, поэтому CPU не должен делать всю эту работу.
реализации инструкций FPATAN в процессорах x86 обычно являются собственностью. Чтобы вычислить арктан или другие (обратные) тригонометрические функции, общие алгоритмы следуют трехэтапному процессу:
- уменьшение аргументов для сопоставления полного входного домена с узким интервалом
- вычисление аппроксимации ядра на узком интервале (интервал первичной аппроксимации)
- расширение промежуточного результата на основе аргумента сокращение для получения конечного результата
уменьшение аргумента обычно основано на известных тригонометрических тождествах, которые можно искать в различных стандартных ссылках, таких как MathWorld (http://mathworld.wolfram.com/InverseTangent.html). Для вычисления арктана обычно используются идентификаторы
- арктан (- x) = - арктан (x)
- арктан(1/x) = 0,5 * Пи - арктан (x) [x > 0]
- равенства arctg (х) = равенства arctg(с) + арктан ((x - c) / (1 + x*c))
обратите внимание, что последнее тождество поддается построению таблицы значений arctan (i/2n), i = 1...2n, что позволяет использовать произвольно узкий интервал первичной аппроксимации за счет дополнительного хранения таблицы. Это классический программный компромисс между пространством и временем.
аппроксимация на основном интервале обычно является минимаксной полиномиальной аппроксимацией достаточная степень. Рациональные аппроксимации обычно не конкурентоспособны на современном оборудовании из-за высокой стоимости деления с плавающей запятой, а также страдают от дополнительной численной ошибки из-за вычисления двух полиномов плюс ошибка, вносимая делением.
коэффициенты для минимаксных полиномиальных аппроксимаций обычно вычисляются с использованием алгоритма Ремеза (http://en.wikipedia.org/wiki/Remez_algorithm). Такие инструменты, как Maple и Mathematica встроенные средства для вычисления таких приближений. Точность полиномиальных аппроксимаций можно улучшить, убедившись, что все коэффициенты являются точно представимыми машинными числами. Единственный инструмент, о котором я знаю, имеет встроенное средство для этого, - это Sollya (http://sollya.gforge.inria.fr/), который предлагает
резюме: это трудно. Кроме того, Эрик Постпишил и Стивен Кэнон, которые иногда болтаются так, очень хороши в этом.
обычный подход для многих специальных функций выглядит следующим образом:
- обрабатывать NaNs, бесконечности и подписанные нули как особые случаи.
- если число настолько велико, что результат округляется до
M_PI
, returnM_PI
. Назовем этот порогM
. - если есть какой-либо аргумент-сокращение идентичности, используйте это, чтобы привести аргумент в более приятный диапазон. (это может быть сложно: For
sin
иcos
, это означает, что вы выбираете несколько из точно значение 2pi, так что вы приземлитесь в правильном диапазоне.) - разбить
[0,M)
в конечное число интервалов. Используйте Чебышева аппроксимация чтобы равенства arctg достаточно высокого порядка на каждом интервале. (Это делается в автономном режиме, и это обычно источник всех магических чисел, которые вы видите в этих реализации. Кроме того, можно немного подтянуть приближение Чебышева, используя алгоритм обмена Ремеза, но я не знаю ни одного случая, когда это очень помогает.) - выясните, в каком интервале находится аргумент (используя
if
s и прочее или просто трюк с индексированием таблицы), и оцените серию Чебышева на этом интервале.
несколько свойств особенно желательно здесь:
- на
arctan
реализация должна быть монотонно, то есть еслиx < y
, потомarctan(x) <= arctan(y)
. - на
arctan
реализация всегда должна возвращать ответ в пределах 1 ulp правильного ответа. Обратите внимание, что это относительная ошибка.
не совсем просто оценить ряд Чебышева, чтобы эти два свойства сохранялись. Трюки, где два double
s используются для представления различных частей одного значения, которые являются общими здесь. Тогда, вероятно, есть какая-то работа, чтобы показать, что реализация монотонна. Кроме того, около нуля, приближение Тейлора к arctan
вместо приближения Чебышева - - - вы после относительной ошибки и оценки ряда с использованием правила Хорнера должны работать.
если вы ищете atan
реализация для чтения, fdlibm кажется менее неприятным, чем тот, который в настоящее время в glibc. Уменьшение аргумента, по-видимому, основано на идентификаторе trig tan(a+b) = (tan(a) + tan(b)) / (1 - tan(a) tan(b))
, используя 0.5
, 1
или 1.5
на tan(a)
as соответствующий.