# User:Hirogen2/VectorAngle StaticLookup

Before I noticed there was the `VectorAngle` function, I actually implemented it myself. Posted here for historic purposes, and perhaps to spark ideas for how to add complex functions with ACS alone. ACS being Turing-complete is an important factor `:-)`  —j.eng 21:47, 26 May 2009 (UTC)

`VectorAngle`, at its core, calculats `atan(dy/dx)`, with a bit of extra logic to handle cases like dx=0. Since ACS does not offer an `atan` function, nor is it feasible to use any of the fancy math (imaginary numbers! integrals! infinite series! continued fractions! all expensive computations! see Wikipedia for details...). The simplest way is to use a static coarse-granularity lookup table. I chose a resolution somewhere near 1° (the “`fixed`” datatype has a resolution of 1/256 °). This is acceptable, as is the cost of space involved with this. Due to the periodicity of trigonometric functions, a reduced number of values need only be stored (e.g. 90 instead of 360).

## atan implementation

```int tan_table[90] = {
/*   0° */ 0.0000,
/*   1° */ 0.0174,
/*   2° */ 0.0349,
/*   3° */ 0.0524,
/*   4° */ 0.0699,
/*   5° */ 0.0874,
/*   6° */ 0.1051,
/*   7° */ 0.1227,
/*   8° */ 0.1405,
/*   9° */ 0.1583,
/*  10° */ 0.1763,
/*  11° */ 0.1943,
/*  12° */ 0.2125,
/*  13° */ 0.2308,
/*  14° */ 0.2493,
/*  15° */ 0.2679,
/*  16° */ 0.2867,
/*  17° */ 0.3057,
/*  18° */ 0.3249,
/*  19° */ 0.3443,
/*  20° */ 0.3639,
/*  21° */ 0.3838,
/*  22° */ 0.4040,
/*  23° */ 0.4244,
/*  24° */ 0.4452,
/*  25° */ 0.4663,
/*  26° */ 0.4877,
/*  27° */ 0.5095,
/*  28° */ 0.5317,
/*  29° */ 0.5543,
/*  30° */ 0.5773,
/*  31° */ 0.6008,
/*  32° */ 0.6248,
/*  33° */ 0.6494,
/*  34° */ 0.6745,
/*  35° */ 0.7002,
/*  36° */ 0.7265,
/*  37° */ 0.7535,
/*  38° */ 0.7812,
/*  39° */ 0.8097,
/*  40° */ 0.8391,
/*  41° */ 0.8692,
/*  42° */ 0.9004,
/*  43° */ 0.9325,
/*  44° */ 0.9656,
/*  45° */ 1.0000,
/*  46° */ 1.0355,
/*  47° */ 1.0723,
/*  48° */ 1.1106,
/*  49° */ 1.1503,
/*  50° */ 1.1917,
/*  51° */ 1.2348,
/*  52° */ 1.2799,
/*  53° */ 1.3270,
/*  54° */ 1.3763,
/*  55° */ 1.4281,
/*  56° */ 1.4825,
/*  57° */ 1.5398,
/*  58° */ 1.6003,
/*  59° */ 1.6642,
/*  60° */ 1.7320,
/*  61° */ 1.8040,
/*  62° */ 1.8807,
/*  63° */ 1.9626,
/*  64° */ 2.0503,
/*  65° */ 2.1445,
/*  66° */ 2.2460,
/*  67° */ 2.3558,
/*  68° */ 2.4750,
/*  69° */ 2.6050,
/*  70° */ 2.7474,
/*  71° */ 2.9042,
/*  72° */ 3.0776,
/*  73° */ 3.2708,
/*  74° */ 3.4874,
/*  75° */ 3.7320,
/*  76° */ 4.0107,
/*  77° */ 4.3314,
/*  78° */ 4.7046,
/*  79° */ 5.1445,
/*  80° */ 5.6712,
/*  81° */ 6.3137,
/*  82° */ 7.1153,
/*  83° */ 8.1443,
/*  84° */ 9.5143,
/*  85° */ 11.4300,
/*  86° */ 14.3006,
/*  87° */ 19.0811,
/*  88° */ 28.6362,
/*  89° */ 57.2899,
};

function int abs(int x)
{
if (x < 0)
return -x;
return x;
}

function int atan_lookup(/*fixed*/ int value)
{
int low = 0, mid, high = 90, cand = -1;

while (low < high) {
mid = low + ((high - low) / 2);
if (cand == -1 ||
abs(tan_table[mid] - value) < abs(tan_table[cand] - value))
cand = mid;

if (tan_table[mid] < value)
low = mid + 1;
else
high = mid;
}
return cand;
}
```

A binary search is used for faster lookup than a linear search. Lookup is already expensive enough because ACS is interpreted.

## VectorAngle implementation

It got called “pointangle” because the C function in the Doom source is called “`R_PointAngle2`”.

```function /*fixed*/ int pointangle(/*fixed*/ int dx, /*fixed*/ int dy)
{
/*fixed*/ int y;
int deg;

if (dx == 0) {
if (dy >= 0)
return 0.25;
else
return 0.75;
}

y = FixedDiv(dy, dx);
if (dy > 0) {
if (dx > 0)
deg = atan_lookup(y);
else