I only noticed the integer limitation, not the do-not-divide one.
There still is a simple solution: implement arctan2 using CORDIC. A simple web search on CORDIC and atan2 should provide a number of interesting results. Note that this version returns only the angle, not the distance, since the distance is not needed.
For example:
Code:
/* Array of atan2(1, 1<<i)*2147483648/(2*Pi).
* This yields 2147483648 = 360 degrees.
*/
const int iangle[] = {
268435456, /* 45.00000000000000000000 degrees */
158466703, /* 26.56505117707799001892 degrees */
83729454, /* 14.03624346792647692439 degrees */
42502378, /* 7.12501634890179769144 degrees */
21333666, /* 3.57633437499735151732 degrees */
10677233, /* 1.78991060824606940116 degrees */
5339919, /* 0.89517371021107439155 degrees */
2670123, /* 0.44761417086055305115 degrees */
1335082, /* 0.22381050036853808449 degrees */
667543, /* 0.11190567706620689614 degrees */
333772, /* 0.05595289189380366762 degrees */
166886, /* 0.02797645261700367619 degrees */
83443, /* 0.01398822714226501639 degrees */
41722, /* 0.00699411367535291827 degrees */
20861, /* 0.00349705685070401126 degrees */
10430, /* 0.00174852842698044954 degrees */
5215, /* 0.00087426421369378026 degrees */
2608, /* 0.00043713210687233457 degrees */
1304, /* 0.00021856605343934784 degrees */
652, /* 0.00010928302672007150 degrees */
326, /* 0.00005464151336008544 degrees */
163, /* 0.00002732075668004893 degrees */
81, /* 0.00001366037834002524 degrees */
41, /* 0.00000683018917001272 degrees */
20, /* 0.00000341509458500637 degrees */
10, /* 0.00000170754729250319 degrees */
5, /* 0.00000085377364625159 degrees */
3, /* 0.00000042688682312580 degrees */
1, /* 0.00000021344341156290 degrees */
1, /* 0.00000010672170578145 degrees */
0
};
static int iatan2(int y, int x)
{
size_t i = 0;
int angle, direction;
/* Which half-plane? */
if (y < 0) {
x = -x;
y = -y;
angle = -1073741824;
} else
angle = 0;
/* Which quadrant? */
if (x < 0) {
x = -x;
angle += 1073741824;
direction = -1;
} else
direction = +1;
/* Which octant? */
if (y > x) {
const int oldy = y;
y = x;
x = oldy;
angle += direction * 536870912;
direction = -direction;
}
/* Along axis? */
if (y == 0)
return angle;
/* Diagonal? */
if (y == x)
return angle + direction * 268435456;
/* Scale, for optimum results. x > y > 0.
* If coordinates are < 32768 in magnitude,
* you could just multiply by 32768.
*/
while (x < 268435456) {
x *= 2;
y *= 2;
}
/* Adjust direction. */
if (direction < 0)
y = -y;
/* CORDIC for angle, 0 < y < x. */
while (iangle[i]) {
const int oldx = x;
const int oldy = y;
if (y > 0) {
x += (oldy >> i);
y -= (oldx >> i);
angle += iangle[i++];
} else
if (y < 0) {
x -= (oldy >> i);
y += (oldx >> i);
angle -= iangle[i++];
} else
break;
}
return angle;
}
iatan2(y,x) yields angles [-536870912, 536870912], analogously to atan2(y,x) returning angles [-Pi, Pi], so each unit is 360/1073741824 degrees; one degree is about 2982616 units.
For x=-32768..32768, y=-32768..32768, the absolute error in angles is -13 to 13 units; i.e. the error of iatan2(y,x) is less than 0.00000436 degrees.
By the way, this is NOT optimized code. This, too, is in public domain, so you can do whatever you want with it.