This source file includes following definitions.
- cordic
- cordic_abs
- cordic_sign
- muldivScaled
- mulScaled
- divScaled
- cathetus
- sincosCordic
- atanhypCordic
- sinCordic
- cosCordic
- tanCordic
- recCordic
- asinCordic
- acosCordic
- atanCordic
- polCordic
- sind
- cosd
- tand
- recd
- asind
- acosd
- atand
- pold
- sinr
- cosr
- tanr
- recr
- asinr
- acosr
- atanr
- polr
- fint
- fceil
- ffloor
- fround
- floatToFixed
- intToFixed
- fixedToInt
1
2
3
4
5
6
7
8
9
10
11
12 #include "stdlib.h"
13 #include "luaconf.h"
14 #include "math.h"
15 #include "cordic_math.h"
16
17 fixed atan_tab[][M] = {
18 {0x1921f, 0xed63, 0x7d6d, 0x3fab, 0x1ff5, 0xffe, 0x7ff, 0x3ff, 0x1ff},
19 {0x5a0000, 0x35214e, 0x1c128e, 0xe4002, 0x72715, 0x3946f, 0x1ca54, 0xe52d, 0x7297}
20 };
21 fixed INV_GAIN_CIRCLE[] = {0x136e9, 0x136e8};
22 fixed FULL_CIRCLE[] = {0xc90fd, 0x2d00000};
23 fixed HALF_CIRCLE[] = {0x6487e, 0x1680000};
24 fixed QUART_CIRCLE[] = {0x3243f, 0xb40000};
25 fixed ATAN_LIMIT = 0x36f602be;
26 fixed FIXED_MAX = 16383.99999;
27
28
29 static void cordic(tangle t, fcordic f, fixed *x, fixed *y, fixed *z) {
30 long *patan_tab = atan_tab[t];
31 long xstep, ystep, zstep = 1;
32 int i;
33 for (i = 0; i < N; ++i) {
34 xstep = *x >> i;
35 ystep = *y >> i;
36 if (i < M) {
37 zstep = *patan_tab;
38 ++patan_tab;
39 } else zstep >>= 1;
40 int f1 = (f) ? *y >= 0 : *z < 0;
41 *x = (f1) ? *x + ystep : *x - ystep;
42 *y = (f1) ? *y - xstep : *y + xstep;
43 *z = (f1) ? *z + zstep : *z - zstep;
44 }
45 }
46
47
48 static int cordic_abs(int a) {
49 if (a < -INT_MAX) a = -INT_MAX;
50 return abs(a);
51 }
52
53 static int cordic_sign(int a) {
54 return (a < 0)? -1 : 1;
55 }
56
57
58 LUALIB_API fixed muldivScaled(fixed a, fixed b, fixed c) {
59 double res;
60 if (c != 0) {
61 int sign = cordic_sign(a) * cordic_sign(b) / cordic_sign(c);
62 res = FLOAT(cordic_abs(a)) * FLOAT(cordic_abs(b)) / FLOAT(cordic_abs(c));
63 if (res > INT_MAX) {
64
65 res = INT_MAX;
66 } else { res = sign * res; }
67 } else {
68
69 res = 0;
70 }
71 return FIXED(res);
72 }
73
74 static fixed mulScaled(fixed a, fixed b) {
75 return muldivScaled(a, b, CORDIC_SCALE);
76 }
77
78 static fixed divScaled(fixed a, fixed b) {
79 return muldivScaled(CORDIC_SCALE, a, b);
80 }
81
82 static fixed cathetus(fixed x) {
83 return FIXED(sqrt((1 + FLOAT(x)) * (1 - FLOAT(x))));
84 }
85
86
87 static void sincosCordic(tangle t, fixed phi, fixed *sinphi, fixed *cosphi) {
88
89 phi = (phi % FULL_CIRCLE[t] + FULL_CIRCLE[t]) % FULL_CIRCLE[t];
90 int q = phi / QUART_CIRCLE[t] + 1;
91 switch(q) {
92 case 2: phi = HALF_CIRCLE[t] - phi; break;
93 case 3: phi = phi - HALF_CIRCLE[t]; break;
94 case 4: phi = FULL_CIRCLE[t] - phi; break;
95 }
96 fixed x = INV_GAIN_CIRCLE[t], y = 0, z = phi;
97 cordic(t, ROTATE, &x, &y, &z);
98
99 if ((q == 2) || (q == 3)) { x = -x; }
100 if ((q == 3) || (q == 4)) { y = -y; }
101 *sinphi = y;
102 *cosphi = x;
103 }
104
105
106 static void atanhypCordic(tangle t, fixed px, fixed py, fixed *phi, fixed *hyp) {
107
108 int fy = (py >= 0);
109 int q = 1;
110 if (px < 0) {
111 if (fy)
112 q = 2;
113 else
114 q = 3;
115 } else if (!fy) {
116 q = 4;
117 }
118 px = cordic_abs(px);
119 py = cordic_abs(py);
120
121 int f = 0;
122 while (px > ATAN_LIMIT || py > ATAN_LIMIT) {
123 px /= 2;
124 py /= 2;
125 f = 1;
126 }
127 if (px == 0 && py == 0) {
128
129 *phi = 0;
130 *hyp = 0;
131 } else {
132 fixed x = px, y = py, z = 0;
133 cordic(t, VECTOR, &x, &y, &z);
134
135 switch(q) {
136 case 2: z = HALF_CIRCLE[t] - z; break;
137 case 3: z = z - HALF_CIRCLE[t]; break;
138 case 4: z = -z; break;
139 }
140 *phi = z;
141 *hyp = (f)? 0 : x;
142 }
143 }
144
145
146 static fixed sinCordic(tangle t, fixed phi) {
147 fixed _sin, _cos;
148 sincosCordic(t, phi, &_sin, &_cos);
149 return _sin;
150 }
151
152 static fixed cosCordic(tangle t, fixed phi) {
153 fixed _sin, _cos;
154 sincosCordic(t, phi, &_sin, &_cos);
155 return _cos;
156 }
157
158 static fixed tanCordic(tangle t, fixed phi) {
159 fixed _sin, _cos;
160 sincosCordic(t, phi, &_sin, &_cos);
161 return divScaled(_sin, _cos);
162 }
163
164 static void recCordic(tangle t, fixed r, fixed theta, fixed *px, fixed *py) {
165 fixed _sin, _cos;
166 sincosCordic(t, theta, &_sin, &_cos);
167 *px = mulScaled(r, _cos);
168 *py = mulScaled(r, _sin);
169 }
170
171
172 static fixed asinCordic(tangle t, fixed x) {
173 fixed phi, hyp;
174 fixed _cos = cathetus(x);
175 atanhypCordic(t, _cos, x, &phi, &hyp);
176 return phi;
177 }
178
179 static fixed acosCordic(tangle t, fixed x) {
180 fixed phi, hyp;
181 fixed _sin = cathetus(x);
182 atanhypCordic(t, x, _sin, &phi, &hyp);
183 return phi;
184 }
185
186 static fixed atanCordic(tangle t, fixed x) {
187 fixed phi, hyp;
188 atanhypCordic(t, CORDIC_SCALE, x, &phi, &hyp);
189 return phi;
190 }
191
192 static void polCordic(tangle t, fixed px, fixed py, fixed *r, fixed *theta) {
193 fixed phi, hyp;
194 atanhypCordic(t, px, py, &phi, &hyp);
195 *theta = phi;
196 *r = mulScaled(hyp, INV_GAIN_CIRCLE[t]);
197 }
198
199
200
201 LUALIB_API fixed sind(fixed phi) {
202 return sinCordic(DEG, phi);
203 }
204
205 LUALIB_API fixed cosd(fixed phi) {
206 return cosCordic(DEG, phi);
207 }
208
209 LUALIB_API fixed tand(fixed phi) {
210 return tanCordic(DEG, phi);
211 }
212
213 LUALIB_API void recd(fixed r, fixed theta, fixed *px, fixed *py) {
214 recCordic(DEG, r, theta, px, py);
215 }
216
217 LUALIB_API fixed asind(fixed x) {
218 return asinCordic(DEG, x);
219 }
220
221 LUALIB_API fixed acosd(fixed x) {
222 return acosCordic(DEG, x);
223 }
224
225 LUALIB_API fixed atand(fixed x) {
226 return atanCordic(DEG, x);
227 }
228
229 LUALIB_API void pold(fixed px, fixed py, fixed *r, fixed *theta) {
230 polCordic(DEG, px, py, r, theta);
231 }
232
233
234 LUALIB_API fixed sinr(fixed phi) {
235 return sinCordic(RAD, phi);
236 }
237
238 LUALIB_API fixed cosr(fixed phi) {
239 return cosCordic(RAD, phi);
240 }
241
242 LUALIB_API fixed tanr(fixed phi) {
243 return tanCordic(RAD, phi);
244 }
245
246 LUALIB_API void recr(fixed r, fixed theta, fixed *px, fixed *py) {
247 recCordic(RAD, r, theta, px, py);
248 }
249
250 LUALIB_API fixed asinr(fixed x) {
251 return asinCordic(RAD, x);
252 }
253
254 LUALIB_API fixed acosr(fixed x) {
255 return acosCordic(RAD, x);
256 }
257
258 LUALIB_API fixed atanr(fixed x) {
259 return atanCordic(RAD, x);
260 }
261
262 LUALIB_API void polr(fixed px, fixed py, fixed *r, fixed *theta) {
263 polCordic(RAD, px, py, r, theta);
264 }
265
266
267 LUALIB_API fixed fint(fixed a) {
268 return cordic_sign(a) * (cordic_abs(a) & CORDIC_INTEGER);
269 }
270
271 LUALIB_API fixed fceil(fixed a) {
272 fixed int_a = fint(a);
273 return (a < 0 || a == int_a)? int_a: int_a + CORDIC_SCALE;
274 }
275
276 LUALIB_API fixed ffloor(fixed a) {
277 fixed int_a = fint(a);
278 return (a > 0 || a == int_a)? int_a: int_a - CORDIC_SCALE;
279 }
280
281 LUALIB_API fixed fround(fixed a) {
282 return ffloor(a + CORDIC_SCALE / 2);
283 }
284
285
286 LUALIB_API fixed floatToFixed(double a) {
287 int sign = 1;
288 if (a < 0) {
289 sign = -1;
290 a = -a;
291 }
292 if (a > FIXED_MAX) {
293
294 a = FIXED_MAX;
295 }
296 return a * CORDIC_SCALE * sign;
297 }
298
299 LUALIB_API fixed intToFixed(int4b a, int round) {
300 double res = cordic_abs(a);
301 if (round) res = res + 0.5;
302 res = res * CORDIC_SCALE / INT_SCALE;
303 if (res > INT_MAX) {
304
305 res = INT_MAX;
306 }
307 return cordic_sign(a) * res;
308 }
309
310 LUALIB_API int4b fixedToInt(fixed a, int round) {
311 double res = cordic_abs(a);
312 if (res > INT_MAX) {
313
314 res = INT_MAX;
315 }
316 res = res * INT_SCALE / CORDIC_SCALE;
317 if (round) res = res + 0.5;
318 return cordic_sign(a) * res;
319 }