Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

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

share|improve this question
1  
Have you had a look into CORDIC? –  Hagen von Eitzen Dec 6 '12 at 19:23
    
Yes, but the math is way too complex for me in order to implement. Haven't seen any simple implementation in C. –  Pablo Dec 6 '12 at 19:25

1 Answer 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)$.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.