0
$\begingroup$

I am trying to optimize sin/cos for my MCU in order to calculate geo distance. This part of formula particularly is using trigonometry:

double e = (MyTan( lat2 / 2 + quarter_pi ) / MyTan( lat1 / 2 + quarter_pi )); 

So I tried to build my own sin/cos lookup tables for -PI to PI as follows:

#define PARTPERDEGREE 10 double mysinlut[PARTPERDEGREE * 90 + 1]; double mycoslut[PARTPERDEGREE * 90 + 1]; void MySinCosCreate() {     int i;     double angle, angleinc;      // Each degree also divided into 10 parts     angleinc = (M_PI / 180) / PARTPERDEGREE;     for (i = 0, angle = 0.0; i <= (PARTPERDEGREE * 90 + 1); ++i, angle += angleinc)     {         mysinlut[i] = sin(angle);     }      angleinc = (M_PI / 180) / PARTPERDEGREE;     for (i = 0, angle = 0.0; i <= (PARTPERDEGREE * 90 + 1); ++i, angle += angleinc)     {         mycoslut[i] = cos(angle);     } }    double MySin(double rad) {    int ix;    int sign = 1;      if(rad > (M_PI / 2))         rad = M_PI / 2 - (rad - M_PI / 2);     if(rad < -(M_PI / 2))        rad = -M_PI / 2 - (rad + M_PI / 2);     if(rad < 0)    {         sign = -1;         rad *= -1;    }     ix = (rad * 180) / M_PI * PARTPERDEGREE;     return sign * mysinlut[ix]; }  double MyCos(double rad) {    int ix;    int sign = 1;       if(rad > M_PI / 2)     {         rad = M_PI / 2 - (rad - M_PI / 2);         sign = -1;     }     else if(rad < -(M_PI / 2))     {         rad = M_PI / 2 + (rad + M_PI / 2);         sign = -1;     }     else if(rad > -M_PI / 2 && rad < M_PI / 2)     {            rad = abs(rad);         sign = 1;     }      ix = (rad * 180) / M_PI * PARTPERDEGREE;      return sign * mycoslut[ix]; }  double MyTan(double rad) {     return MySin(rad) / MyCos(rad); } 

You can see the resolution of table is 10 parts per degree. I can increase it little, but it doesn't help much and it looks like I need some interpolation. Could anyone suggest some practical improvements to my functions to have better results? Below is graph of 234 different results of the e. Blue series are with ideal sin/cos and red are from LUT.

enter image description here

  • 0
    Yes, but the math is way too complex for me in order to implement. Haven't seen any simple implementation in C.2012-12-06

1 Answers 1

1

Good rational approximations for $\sin(x)$ and $\cos(x)$ on $[0, \pi/4]$ are

-.41498e-8+(1.000000515+(-.105463955e-4+(-.1665856017+(-.297181298e-3  +(.8894256955e-2-.5282205803e-3*x)*x)*x)*x)*x)*x 

and

1.000000002+(-.2053e-6+(-.4999959817+(-.2922839e-4+(.4176577023e-1 +(-.163891331e-3-.1275240287e-2*x)*x)*x)*x)*x)*x 

with maximum absolute errors approximately $.415 \times 10^{-8}$ and $.2 \times 10^{-8}$ respectively. You can use these to calculate $\sin(x)$ or $\cos(x)$ for any $x$: e.g. if $\pi/4 \le x \le \pi/2$ then $\sin(x) = \cos(\pi/2 - x)$ and $\cos(x) = \sin(\pi/2-x)$.