Version 7 (modified by 11 years ago) (diff) | ,
---|
Trigonometric functions
Our research notes about implementation of fast trigonometric functions.
Minimax polynomial for sin(x)
Absolute error
Suppose we want to approximate sin(x) on [-π/2; π/2] with a polynomial P(x) such that the absolute error is never more than E:
![\[\max_{x \in [-\pi/2, \pi/2]}{\big\vert\sin(x) - P(x)\big\vert} = E\]](https://lolengine.net/tracmath/50bf2af936404bc3c5d2ae7e8d7b7c1aa16424ed.png)
We know sin(x) is an odd function, so instead we look for a polynomial Q(x) such that P(x) = xQ(x²), and we reduce the range to positive values:
![\[\max_{x \in [0, \pi/2]}{\big\vert\sin(x) - xQ(x^2)\big\vert} = E\]](https://lolengine.net/tracmath/6cbc045e2ff3a430d90ce099ecf093f840cb2413.png)
Substitute y for x²:
![\[\max_{x \in [0, \pi^2/4]}{\big\lvert\sin(\sqrt{y}) - \sqrt{y}Q(y)\big\rvert} = E\]](https://lolengine.net/tracmath/98fb6ebde15ad5a6537070e0bc9fa505b7de91bf.png)
Divide through by √y:
![\[\max_{x \in [0, \pi^2/4]}{\dfrac{\bigg\lvert\dfrac{\sin(\sqrt{y})}{\sqrt{y}} - Q(y)\bigg\rvert}{\dfrac{1}{|\sqrt{y}|}}} = E\]](https://lolengine.net/tracmath/b0ca6cb34a118eda510fc268ab69eed119158f31.png)
If we want to force the asymptotic behaviour at x=0, we substitute Q(y) with 1+yR(y):
![\[\max_{x \in [0, \pi^2/4]}{\dfrac{\bigg\lvert\dfrac{\sin(\sqrt{y})}{\sqrt{y}} - 1 - yR(y)\bigg\rvert}{\dfrac{1}{|\sqrt{y}|}}} = E\]](https://lolengine.net/tracmath/2be3e58a3ae7d0b172ef0681e0a5f6004e0feb7c.png)
Divide through by y:
![\[\max_{x \in [0, \pi^2/4]}{\dfrac{\bigg\lvert\dfrac{\sin(\sqrt{y})-\sqrt{y}}{y\sqrt{y}} - R(y)\bigg\rvert}{\dfrac{1}{|y\sqrt{y}|}}} = E\]](https://lolengine.net/tracmath/b58b761a5c50bc0232ff6e75e1cc16516e0d501e.png)
We then use the following code:
static real myfun(real const &y) { real x = sqrt(y); return (sin(x) - x) / (x * y); } static real myerr(real const &y) { return re(y * sqrt(y)); } RemezSolver<6> solver; solver.Run(real::R_1 >> 400, real::R_PI_2 * real::R_PI_2, myfun, myerr, 15);
These are the resulting R, Q and P:

With the following coefficients:
a0 = -1.66666666666658080941942898789420724e-1; a1 = +8.33333333326271609442503773834687308e-3; a2 = -1.98412698200591143928364634696492885e-4; a3 = +2.75573160733868922065738227278330896e-6; a4 = -2.50518513021429359590028300127165228e-8; a5 = +1.60472959182597740337401201006549498e-10; a6 = -7.36458957326227991327065122848667046e-13;
Relative error
Searching for relative error instead:
![\[\max_{x \in [-\pi/2, \pi/2]}{\dfrac{\big\vert\sin(x) - P(x)\big\vert}{|\sin(x)|}} = E\]](https://lolengine.net/tracmath/73b424552c9726639834f81ebdfc58f3633e3852.png)
Using the same method as for absolute error, we get:
![\[\max_{x \in [0, \pi^2/4]}{\dfrac{\bigg\lvert\dfrac{\sin(\sqrt{y})-\sqrt{y}}{y\sqrt{y}} - R(y)\bigg\rvert}{\bigg\lvert\dfrac{\sin(y)}{y\sqrt{y}}\bigg\rvert}} = E\]](https://lolengine.net/tracmath/f3bcdde5ab43583f582f4898fffac4531caed757.png)
static real myfun(real const &y) { real x = sqrt(y); return (sin(x) - x) / (x * y); } static real myerr(real const &y) { real x = sqrt(y); return sin(x) / (x * y); } RemezSolver<6> solver; solver.Run(real::R_1 >> 400, real::R_PI_2 * real::R_PI_2, myfun, myerr, 15);
a0 = -1.666666666666666587374325845020415990185e-1; a1 = +8.333333333333133768001243698120735518527e-3; a2 = -1.984126984109960366729319073763957206143e-4; a3 = +2.755731915499171528179303925040423384803e-6; a4 = -2.505209340355388148617179634180834358690e-8; a5 = +1.605725287696319345779134635418774782711e-10; a6 = -7.535968124281960435283756562793611388136e-13;