Как реализуется 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 обычно являются собственностью. Чтобы вычислить арктан или другие (обратные) тригонометрические функции, общие алгоритмы следуют трехэтапному процессу:

  1. уменьшение аргументов для сопоставления полного входного домена с узким интервалом
  2. вычисление аппроксимации ядра на узком интервале (интервал первичной аппроксимации)
  3. расширение промежуточного результата на основе аргумента сокращение для получения конечного результата

уменьшение аргумента обычно основано на известных тригонометрических тождествах, которые можно искать в различных стандартных ссылках, таких как 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, return M_PI. Назовем этот порог M.
  • если есть какой-либо аргумент-сокращение идентичности, используйте это, чтобы привести аргумент в более приятный диапазон. (это может быть сложно: For sin и cos, это означает, что вы выбираете несколько из точно значение 2pi, так что вы приземлитесь в правильном диапазоне.)
  • разбить [0,M) в конечное число интервалов. Используйте Чебышева аппроксимация чтобы равенства arctg достаточно высокого порядка на каждом интервале. (Это делается в автономном режиме, и это обычно источник всех магических чисел, которые вы видите в этих реализации. Кроме того, можно немного подтянуть приближение Чебышева, используя алгоритм обмена Ремеза, но я не знаю ни одного случая, когда это очень помогает.)
  • выясните, в каком интервале находится аргумент (используя ifs и прочее или просто трюк с индексированием таблицы), и оцените серию Чебышева на этом интервале.

несколько свойств особенно желательно здесь:

  • на arctan реализация должна быть монотонно, то есть если x < y, потом arctan(x) <= arctan(y).
  • на arctan реализация всегда должна возвращать ответ в пределах 1 ulp правильного ответа. Обратите внимание, что это относительная ошибка.

не совсем просто оценить ряд Чебышева, чтобы эти два свойства сохранялись. Трюки, где два doubles используются для представления различных частей одного значения, которые являются общими здесь. Тогда, вероятно, есть какая-то работа, чтобы показать, что реализация монотонна. Кроме того, около нуля, приближение Тейлора к 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 соответствующий.