Ускорение тригонометрических и прочих функций в bc
Интересно, что вся стандартная библиотека (подключаемая через ключ -l) для bc написана нативно. С одной стороны, это
Я тут потихоньку ускоряю одну из своих программ на bc, но все «низко висящие фрукты» я уже подобрал. Добрался до тригонометрических функций. Во внутренней библиотеке косинус выражается через синус, так что, если ускорить синус, то ускорится сразу и косинус.
Посмотрел разные реализации, в итоге портировал функцию, которую взял из одной из статей на «Хабре», получилось так (используется многочлен Чебышёва):
define mod(a, b) {
auto s, m
s = scale; scale = 0; m = a$ % b$; scale = s; return m
}
define s(x) {
auto sign, xf, per, xx, y
x *= 0.63661977236758134308
if (sign = (x < 0)) x = -x
xf = x$
x -= xf
if (mod(xf, 2)) x = 1 - x
per = mod(xf / 2, 2)
xx = x * x
y = x * (1.5707903005870776 + xx * (-0.6458858977085938 + \
xx*(0.07941798513358536 - 0.0043223880120647346 * xx)))
if (sign != per) return -y
return y
}Расхождение со встроенной в bc реализацией начинается в седьмом знаке, это более чем достаточно для меня, зато вычисление синуса ускорилось больше, чем в четыре раза.
Добавлено позднее: ещё я заменил функцию нахождения логарифма по основанию десять. Логарифмом я находил количество разрядов числа, чтобы потом вывести его на экран, так что его легко было заменить на цикл с подсчётом порядка делением. Разница в производительности — больше, чем в 60 раз. Код теперь выглядит так:
define cnt_digits(x) {
auto i, s
s = scale; scale = 0
for (i = 0; x /= 10; i++){}
scale = s; return i
}
Комментарии 8
//Добавлено//: Не выдержал, попробовал. В производительности разница в восемь раз, но будет ли достаточной точность для игры — непонятно, надо будет пробовать. Расхождение для некоторых вычисляемых значений у меня получилось ≈ 5,5, это как будто многовато.