В качестве канонического примера рассмотрим проблему приведения аргумента для тригонометрических функций, как при вычислении x mod 2π в качестве первого шага вычисления sin(x). Проблема такого рода сложна тем, что вы не можете просто использовать fmod
, потому что y (2π в примере) непредставимо.
Я придумал простое решение, которое работает для произвольных значений y, а не только для 2π, и мне любопытно, как оно соотносится (по производительности) с типичными алгоритмами сокращения аргументов.
Основная идея состоит в том, чтобы сохранить таблицу, содержащую значение 2n mod y для каждого значения n в диапазоне log2(y) до максимально возможного показателя степени с плавающей запятой, а затем, используя линейность модульной арифметики, суммируйте значения в этой таблице по битам, которые установлены в значении x. Это составляет N ветвей и не более N добавлений, где N — количество битов мантиссы в вашем типе с плавающей запятой. Результат не обязательно меньше y, но он ограничен N*y, и процедуру можно применить снова, чтобы получить результат, ограниченный log2(N)*y, или fmod
можно просто использовать в этой точке с минимальной ошибкой.
Можно ли это улучшить? И работают ли типичные тригонометрические алгоритмы уменьшения аргумента для произвольного y или только для 2π?