# fastest way to get a theta from cartesian co-ordinates

Hello, all. I needed to do fast ArcTangent computation. I came up with 2 methods to calculate this.
one is using arduino’s atan() function, and the other using a lookup table. I’m wondering which will take the least cycles to execute
example 1: Atan()

``````double CartesianToPolarT(double x, double y) {
return x > 0 ? pow(tan(x / y), -1) : PI + pow(tan(x / y), -1);
}
``````

example 2: lookup table

``````double atanLookup[] = {
-1.4877,-1.4873,-1.487,-1.4866,-1.4863,-1.4859,-1.4855,-1.4852,-1.4848,-1.4844,
-1.4841,-1.4837,-1.4833,-1.4829,-1.4825,-1.4821,-1.4817,-1.4813,-1.4809,-1.4805,
-1.4801,-1.4797,-1.4793,-1.4789,-1.4785,-1.478,-1.4776,-1.4772,-1.4767,-1.4763,
-1.4758,-1.4754,-1.4749,-1.4745,-1.474,-1.4735,-1.4731,-1.4726,-1.4721,-1.4716,
-1.4711,-1.4706,-1.4701,-1.4696,-1.4691,-1.4686,-1.4681,-1.4675,-1.467,-1.4665,
-1.4659,-1.4654,-1.4648,-1.4642,-1.4637,-1.4631,-1.4625,-1.4619,-1.4613,-1.4607,
-1.4601,-1.4595,-1.4589,-1.4583,-1.4576,-1.457,-1.4564,-1.4557,-1.455,-1.4544,
-1.4537,-1.453,-1.4523,-1.4516,-1.4509,-1.4502,-1.4494,-1.4487,-1.448,-1.4472,
-1.4464,-1.4457,-1.4449,-1.4441,-1.4433,-1.4425,-1.4416,-1.4408,-1.44,-1.4391,
-1.4382,-1.4374,-1.4365,-1.4356,-1.4347,-1.4337,-1.4328,-1.4318,-1.4309,-1.4299,
-1.4289,-1.4279,-1.4269,-1.4258,-1.4248,-1.4237,-1.4226,-1.4215,-1.4204,-1.4193,
-1.4181,-1.417,-1.4158,-1.4146,-1.4134,-1.4121,-1.4109,-1.4096,-1.4083,-1.407,
-1.4056,-1.4043,-1.4029,-1.4015,-1.4001,-1.3986,-1.3971,-1.3956,-1.3941,-1.3925,
-1.3909,-1.3893,-1.3877,-1.386,-1.3843,-1.3826,-1.3808,-1.379,-1.3772,-1.3753,
-1.3734,-1.3715,-1.3695,-1.3675,-1.3654,-1.3633,-1.3612,-1.359,-1.3567,-1.3545,
-1.3521,-1.3497,-1.3473,-1.3448,-1.3423,-1.3397,-1.3371,-1.3343,-1.3316,-1.3287,
-1.3258,-1.3228,-1.3198,-1.3167,-1.3135,-1.3102,-1.3068,-1.3034,-1.2998,-1.2962,
-1.2925,-1.2887,-1.2847,-1.2807,-1.2766,-1.2723,-1.2679,-1.2634,-1.2588,-1.254,
-1.249,-1.244,-1.2387,-1.2333,-1.2278,-1.222,-1.2161,-1.21,-1.2036,-1.1971,
-1.1903,-1.1833,-1.176,-1.1685,-1.1607,-1.1526,-1.1442,-1.1354,-1.1264,-1.117,
-1.1071,-1.0969,-1.0863,-1.0752,-1.0637,-1.0517,-1.0391,-1.0259,-1.0122,-0.9978,
-0.9828,-0.967,-0.9505,-0.9332,-0.9151,-0.8961,-0.8761,-0.8551,-0.833,-0.8098,
-0.7854,-0.7598,-0.7328,-0.7045,-0.6747,-0.6435,-0.6107,-0.5764,-0.5404,-0.5028,
-0.4636,-0.4229,-0.3805,-0.3367,-0.2915,-0.245,-0.1974,-0.1489,-0.0997,-0.05,
0,0.05,0.0997,0.1489,0.1974,0.245,0.2915,0.3367,0.3805,0.4229,
0.4636,0.5028,0.5404,0.5764,0.6107,0.6435,0.6747,0.7045,0.7328,0.7598,
0.7854,0.8098,0.833,0.8551,0.8761,0.8961,0.9151,0.9332,0.9505,0.967,
0.9828,0.9978,1.0122,1.0259,1.0391,1.0517,1.0637,1.0752,1.0863,1.0969,
1.1071,1.117,1.1264,1.1354,1.1442,1.1526,1.1607,1.1685,1.176,1.1833,
1.1903,1.1971,1.2036,1.21,1.2161,1.222,1.2278,1.2333,1.2387,1.244,
1.249,1.254,1.2588,1.2634,1.2679,1.2723,1.2766,1.2807,1.2847,1.2887,
1.2925,1.2962,1.2998,1.3034,1.3068,1.3102,1.3135,1.3167,1.3198,1.3228,
1.3258,1.3287,1.3316,1.3343,1.3371,1.3397,1.3423,1.3448,1.3473,1.3497,
1.3521,1.3545,1.3567,1.359,1.3612,1.3633,1.3654,1.3675,1.3695,1.3715,
1.3734,1.3753,1.3772,1.379,1.3808,1.3826,1.3843,1.386,1.3877,1.3893,
1.3909,1.3925,1.3941,1.3956,1.3971,1.3986,1.4001,1.4015,1.4029,1.4043,
1.4056,1.407,1.4083,1.4096,1.4109,1.4121,1.4134,1.4146,1.4158,1.417,
1.4181,1.4193,1.4204,1.4215,1.4226,1.4237,1.4248,1.4258,1.4269,1.4279,
1.4289,1.4299,1.4309,1.4318,1.4328,1.4337,1.4347,1.4356,1.4365,1.4374,
1.4382,1.4391,1.44,1.4408,1.4416,1.4425,1.4433,1.4441,1.4449,1.4457,
1.4464,1.4472,1.448,1.4487,1.4494,1.4502,1.4509,1.4516,1.4523,1.453,
1.4537,1.4544,1.455,1.4557,1.4564,1.457,1.4576,1.4583,1.4589,1.4595,
1.4601,1.4607,1.4613,1.4619,1.4625,1.4631,1.4637,1.4642,1.4648,1.4654,
1.4659,1.4665,1.467,1.4675,1.4681,1.4686,1.4691,1.4696,1.4701,1.4706,
1.4711,1.4716,1.4721,1.4726,1.4731,1.4735,1.474,1.4745,1.4749,1.4754,
1.4758,1.4763,1.4767,1.4772,1.4776,1.478,1.4785,1.4789,1.4793,1.4797,
1.4801,1.4805,1.4809,1.4813,1.4817,1.4821,1.4825,1.4829,1.4833,1.4837,
1.4841,1.4844,1.4848,1.4852,1.4855,1.4859,1.4863,1.4866,1.487,1.4873,
};
double deltaAtanLookup = 0.05;

double lowerLimit = -12;

double CartesianToPolarT(double x, double y) {
double ratio = x / y;
double looked = 0;
if(ratio < -12){
looked = -PI/2;
}else if(ratio > 12){
looked = PI/2;
}else{
double index = (ratio-lowerLimit)/deltaAtanLookup;
double leftover = index - (int) index;
looked = atanLookup[(int)index]+leftover*(atanLookup[(int)index]-atanLookup[(int)index+1]);
}
return x > 0 ? looked : PI + looked;
}
``````

Time it using micros().

arduino atan function sweep of 120000 calculations:
738052 us
lookup function sweep of 120000 calculations:
738052 us
I kid you not, it’s exactly the same.
here is the sample code:

``````double atanLookup[] = {
-1.4877,-1.4873,-1.487,-1.4866,-1.4863,-1.4859,-1.4855,-1.4852,-1.4848,-1.4844,
-1.4841,-1.4837,-1.4833,-1.4829,-1.4825,-1.4821,-1.4817,-1.4813,-1.4809,-1.4805,
-1.4801,-1.4797,-1.4793,-1.4789,-1.4785,-1.478,-1.4776,-1.4772,-1.4767,-1.4763,
-1.4758,-1.4754,-1.4749,-1.4745,-1.474,-1.4735,-1.4731,-1.4726,-1.4721,-1.4716,
-1.4711,-1.4706,-1.4701,-1.4696,-1.4691,-1.4686,-1.4681,-1.4675,-1.467,-1.4665,
-1.4659,-1.4654,-1.4648,-1.4642,-1.4637,-1.4631,-1.4625,-1.4619,-1.4613,-1.4607,
-1.4601,-1.4595,-1.4589,-1.4583,-1.4576,-1.457,-1.4564,-1.4557,-1.455,-1.4544,
-1.4537,-1.453,-1.4523,-1.4516,-1.4509,-1.4502,-1.4494,-1.4487,-1.448,-1.4472,
-1.4464,-1.4457,-1.4449,-1.4441,-1.4433,-1.4425,-1.4416,-1.4408,-1.44,-1.4391,
-1.4382,-1.4374,-1.4365,-1.4356,-1.4347,-1.4337,-1.4328,-1.4318,-1.4309,-1.4299,
-1.4289,-1.4279,-1.4269,-1.4258,-1.4248,-1.4237,-1.4226,-1.4215,-1.4204,-1.4193,
-1.4181,-1.417,-1.4158,-1.4146,-1.4134,-1.4121,-1.4109,-1.4096,-1.4083,-1.407,
-1.4056,-1.4043,-1.4029,-1.4015,-1.4001,-1.3986,-1.3971,-1.3956,-1.3941,-1.3925,
-1.3909,-1.3893,-1.3877,-1.386,-1.3843,-1.3826,-1.3808,-1.379,-1.3772,-1.3753,
-1.3734,-1.3715,-1.3695,-1.3675,-1.3654,-1.3633,-1.3612,-1.359,-1.3567,-1.3545,
-1.3521,-1.3497,-1.3473,-1.3448,-1.3423,-1.3397,-1.3371,-1.3343,-1.3316,-1.3287,
-1.3258,-1.3228,-1.3198,-1.3167,-1.3135,-1.3102,-1.3068,-1.3034,-1.2998,-1.2962,
-1.2925,-1.2887,-1.2847,-1.2807,-1.2766,-1.2723,-1.2679,-1.2634,-1.2588,-1.254,
-1.249,-1.244,-1.2387,-1.2333,-1.2278,-1.222,-1.2161,-1.21,-1.2036,-1.1971,
-1.1903,-1.1833,-1.176,-1.1685,-1.1607,-1.1526,-1.1442,-1.1354,-1.1264,-1.117,
-1.1071,-1.0969,-1.0863,-1.0752,-1.0637,-1.0517,-1.0391,-1.0259,-1.0122,-0.9978,
-0.9828,-0.967,-0.9505,-0.9332,-0.9151,-0.8961,-0.8761,-0.8551,-0.833,-0.8098,
-0.7854,-0.7598,-0.7328,-0.7045,-0.6747,-0.6435,-0.6107,-0.5764,-0.5404,-0.5028,
-0.4636,-0.4229,-0.3805,-0.3367,-0.2915,-0.245,-0.1974,-0.1489,-0.0997,-0.05,
0,0.05,0.0997,0.1489,0.1974,0.245,0.2915,0.3367,0.3805,0.4229,
0.4636,0.5028,0.5404,0.5764,0.6107,0.6435,0.6747,0.7045,0.7328,0.7598,
0.7854,0.8098,0.833,0.8551,0.8761,0.8961,0.9151,0.9332,0.9505,0.967,
0.9828,0.9978,1.0122,1.0259,1.0391,1.0517,1.0637,1.0752,1.0863,1.0969,
1.1071,1.117,1.1264,1.1354,1.1442,1.1526,1.1607,1.1685,1.176,1.1833,
1.1903,1.1971,1.2036,1.21,1.2161,1.222,1.2278,1.2333,1.2387,1.244,
1.249,1.254,1.2588,1.2634,1.2679,1.2723,1.2766,1.2807,1.2847,1.2887,
1.2925,1.2962,1.2998,1.3034,1.3068,1.3102,1.3135,1.3167,1.3198,1.3228,
1.3258,1.3287,1.3316,1.3343,1.3371,1.3397,1.3423,1.3448,1.3473,1.3497,
1.3521,1.3545,1.3567,1.359,1.3612,1.3633,1.3654,1.3675,1.3695,1.3715,
1.3734,1.3753,1.3772,1.379,1.3808,1.3826,1.3843,1.386,1.3877,1.3893,
1.3909,1.3925,1.3941,1.3956,1.3971,1.3986,1.4001,1.4015,1.4029,1.4043,
1.4056,1.407,1.4083,1.4096,1.4109,1.4121,1.4134,1.4146,1.4158,1.417,
1.4181,1.4193,1.4204,1.4215,1.4226,1.4237,1.4248,1.4258,1.4269,1.4279,
1.4289,1.4299,1.4309,1.4318,1.4328,1.4337,1.4347,1.4356,1.4365,1.4374,
1.4382,1.4391,1.44,1.4408,1.4416,1.4425,1.4433,1.4441,1.4449,1.4457,
1.4464,1.4472,1.448,1.4487,1.4494,1.4502,1.4509,1.4516,1.4523,1.453,
1.4537,1.4544,1.455,1.4557,1.4564,1.457,1.4576,1.4583,1.4589,1.4595,
1.4601,1.4607,1.4613,1.4619,1.4625,1.4631,1.4637,1.4642,1.4648,1.4654,
1.4659,1.4665,1.467,1.4675,1.4681,1.4686,1.4691,1.4696,1.4701,1.4706,
1.4711,1.4716,1.4721,1.4726,1.4731,1.4735,1.474,1.4745,1.4749,1.4754,
1.4758,1.4763,1.4767,1.4772,1.4776,1.478,1.4785,1.4789,1.4793,1.4797,
1.4801,1.4805,1.4809,1.4813,1.4817,1.4821,1.4825,1.4829,1.4833,1.4837,
1.4841,1.4844,1.4848,1.4852,1.4855,1.4859,1.4863,1.4866,1.487,1.4873,
};
double deltaAtanLookup = 0.05;

double lowerLimit = -12;

void setup() {
// put your setup code here, to run once:
Serial.begin(19200);
}

void loop() {
long start = micros();
for(double d = -12; d <12; d+=0.0001){
CartesianToPolarT1(d);//change between 1 and 2 for different timings
}
Serial.println(micros()-start);
delay(250);

}
double CartesianToPolarT1(double x) {
double y = 1;
double ratio = x / y;
double looked = 0;
if(ratio < -12){
looked = -PI/2;
}else if(ratio > 12){
looked = PI/2;
}else{
double index = (ratio-lowerLimit)/deltaAtanLookup;
double leftover = index - (int) index;
looked = atanLookup[(int)index]+leftover*(atanLookup[(int)index]-atanLookup[(int)index+1]);
}
return x > 0 ? looked : PI + looked;
}
double CartesianToPolarT2(double x, double y) {
return x > 0 ? pow(tan(x / y), -1) : PI + pow(tan(x / y), -1);
}
``````

What is this function? (Hint: not atan() ).

``````pow(tan(x / y), -1)
``````

jremington:
What is this function? (Hint: not atan() ).

``````pow(tan(x / y), -1)
``````

That's inverse tangent.

No. That is 1/tan(x/y)

atan() or atan2() is the inverse tangent or arctangent.

theta = atan2(y,x)

alright new timing: 738053

``````double atanLookup[] = {
-1.4877,-1.4873,-1.487,-1.4866,-1.4863,-1.4859,-1.4855,-1.4852,-1.4848,-1.4844,
-1.4841,-1.4837,-1.4833,-1.4829,-1.4825,-1.4821,-1.4817,-1.4813,-1.4809,-1.4805,
-1.4801,-1.4797,-1.4793,-1.4789,-1.4785,-1.478,-1.4776,-1.4772,-1.4767,-1.4763,
-1.4758,-1.4754,-1.4749,-1.4745,-1.474,-1.4735,-1.4731,-1.4726,-1.4721,-1.4716,
-1.4711,-1.4706,-1.4701,-1.4696,-1.4691,-1.4686,-1.4681,-1.4675,-1.467,-1.4665,
-1.4659,-1.4654,-1.4648,-1.4642,-1.4637,-1.4631,-1.4625,-1.4619,-1.4613,-1.4607,
-1.4601,-1.4595,-1.4589,-1.4583,-1.4576,-1.457,-1.4564,-1.4557,-1.455,-1.4544,
-1.4537,-1.453,-1.4523,-1.4516,-1.4509,-1.4502,-1.4494,-1.4487,-1.448,-1.4472,
-1.4464,-1.4457,-1.4449,-1.4441,-1.4433,-1.4425,-1.4416,-1.4408,-1.44,-1.4391,
-1.4382,-1.4374,-1.4365,-1.4356,-1.4347,-1.4337,-1.4328,-1.4318,-1.4309,-1.4299,
-1.4289,-1.4279,-1.4269,-1.4258,-1.4248,-1.4237,-1.4226,-1.4215,-1.4204,-1.4193,
-1.4181,-1.417,-1.4158,-1.4146,-1.4134,-1.4121,-1.4109,-1.4096,-1.4083,-1.407,
-1.4056,-1.4043,-1.4029,-1.4015,-1.4001,-1.3986,-1.3971,-1.3956,-1.3941,-1.3925,
-1.3909,-1.3893,-1.3877,-1.386,-1.3843,-1.3826,-1.3808,-1.379,-1.3772,-1.3753,
-1.3734,-1.3715,-1.3695,-1.3675,-1.3654,-1.3633,-1.3612,-1.359,-1.3567,-1.3545,
-1.3521,-1.3497,-1.3473,-1.3448,-1.3423,-1.3397,-1.3371,-1.3343,-1.3316,-1.3287,
-1.3258,-1.3228,-1.3198,-1.3167,-1.3135,-1.3102,-1.3068,-1.3034,-1.2998,-1.2962,
-1.2925,-1.2887,-1.2847,-1.2807,-1.2766,-1.2723,-1.2679,-1.2634,-1.2588,-1.254,
-1.249,-1.244,-1.2387,-1.2333,-1.2278,-1.222,-1.2161,-1.21,-1.2036,-1.1971,
-1.1903,-1.1833,-1.176,-1.1685,-1.1607,-1.1526,-1.1442,-1.1354,-1.1264,-1.117,
-1.1071,-1.0969,-1.0863,-1.0752,-1.0637,-1.0517,-1.0391,-1.0259,-1.0122,-0.9978,
-0.9828,-0.967,-0.9505,-0.9332,-0.9151,-0.8961,-0.8761,-0.8551,-0.833,-0.8098,
-0.7854,-0.7598,-0.7328,-0.7045,-0.6747,-0.6435,-0.6107,-0.5764,-0.5404,-0.5028,
-0.4636,-0.4229,-0.3805,-0.3367,-0.2915,-0.245,-0.1974,-0.1489,-0.0997,-0.05,
0,0.05,0.0997,0.1489,0.1974,0.245,0.2915,0.3367,0.3805,0.4229,
0.4636,0.5028,0.5404,0.5764,0.6107,0.6435,0.6747,0.7045,0.7328,0.7598,
0.7854,0.8098,0.833,0.8551,0.8761,0.8961,0.9151,0.9332,0.9505,0.967,
0.9828,0.9978,1.0122,1.0259,1.0391,1.0517,1.0637,1.0752,1.0863,1.0969,
1.1071,1.117,1.1264,1.1354,1.1442,1.1526,1.1607,1.1685,1.176,1.1833,
1.1903,1.1971,1.2036,1.21,1.2161,1.222,1.2278,1.2333,1.2387,1.244,
1.249,1.254,1.2588,1.2634,1.2679,1.2723,1.2766,1.2807,1.2847,1.2887,
1.2925,1.2962,1.2998,1.3034,1.3068,1.3102,1.3135,1.3167,1.3198,1.3228,
1.3258,1.3287,1.3316,1.3343,1.3371,1.3397,1.3423,1.3448,1.3473,1.3497,
1.3521,1.3545,1.3567,1.359,1.3612,1.3633,1.3654,1.3675,1.3695,1.3715,
1.3734,1.3753,1.3772,1.379,1.3808,1.3826,1.3843,1.386,1.3877,1.3893,
1.3909,1.3925,1.3941,1.3956,1.3971,1.3986,1.4001,1.4015,1.4029,1.4043,
1.4056,1.407,1.4083,1.4096,1.4109,1.4121,1.4134,1.4146,1.4158,1.417,
1.4181,1.4193,1.4204,1.4215,1.4226,1.4237,1.4248,1.4258,1.4269,1.4279,
1.4289,1.4299,1.4309,1.4318,1.4328,1.4337,1.4347,1.4356,1.4365,1.4374,
1.4382,1.4391,1.44,1.4408,1.4416,1.4425,1.4433,1.4441,1.4449,1.4457,
1.4464,1.4472,1.448,1.4487,1.4494,1.4502,1.4509,1.4516,1.4523,1.453,
1.4537,1.4544,1.455,1.4557,1.4564,1.457,1.4576,1.4583,1.4589,1.4595,
1.4601,1.4607,1.4613,1.4619,1.4625,1.4631,1.4637,1.4642,1.4648,1.4654,
1.4659,1.4665,1.467,1.4675,1.4681,1.4686,1.4691,1.4696,1.4701,1.4706,
1.4711,1.4716,1.4721,1.4726,1.4731,1.4735,1.474,1.4745,1.4749,1.4754,
1.4758,1.4763,1.4767,1.4772,1.4776,1.478,1.4785,1.4789,1.4793,1.4797,
1.4801,1.4805,1.4809,1.4813,1.4817,1.4821,1.4825,1.4829,1.4833,1.4837,
1.4841,1.4844,1.4848,1.4852,1.4855,1.4859,1.4863,1.4866,1.487,1.4873,
};
double deltaAtanLookup = 0.05;

double lowerLimit = -12;

void setup() {
// put your setup code here, to run once:
Serial.begin(19200);
}

void loop() {
long start = micros();
for(double d = -12; d <12; d+=0.0001){
CartesianToPolarT1(d);//change between 1 and 2 for different timings
}
Serial.println(micros()-start);
delay(250);

}
double CartesianToPolarT1(double x) {
double y = 1;
double ratio = x / y;
double looked = 0;
if(ratio < -12){
looked = -PI/2;
}else if(ratio > 12){
looked = PI/2;
}else{
double index = (ratio-lowerLimit)/deltaAtanLookup;
double leftover = index - (int) index;
looked = atanLookup[(int)index]+leftover*(atanLookup[(int)index]-atanLookup[(int)index+1]);
}
return x > 0 ? looked : PI + looked;
}
double CartesianToPolarT2(double x, double y) {
return x > 0 ? atan(x / y) : PI + atan(x / y);

}
``````
``````pow(tan(x / y), -1) : PI + pow(tan(x / y), -1);
``````

I am pretty sure that pow(x, -1) is MUCH slower than (1.0/x)

(But as others have pointed out arctan (sometimes written as “tan-1(x)” is not at all the same thing as “(tan(x))-1”)
(back to your trig book with you! arctan(x) is “the angle whose tangent is x”)