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.