1 /*
2 * anglechk.c
3 *
4 * Copyright 2007 Alam Arias <Alam.GBC@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <stdio.h>
22 #ifdef _MSC_VER
23 #include <assert.h>
24 #endif
25 #define NOASM
26 #include "../src/tables.h"
27 #define NO_M
28 #include "../src/m_fixed.c"
29 #define FIXEDPOINTCONV
30
31 // With angle_t,
32 // 360 deg = 2^32
33 // 45 deg = 2^29
34 // 1 deg = 2^29 / 45
35 // To convert an angle to a fixed-point number of degrees, then, use
36 // fixed = angle * FRACUNIT / ((1<<29) / 45)
37 // But, done literally like that, this will overflow.
38 // It's mathematically equivalent to
39 // fixed = angle * (1<<FRACBITS) / (1<<29) * 45
40 // fixed = 45 * angle * (1<<(FRACBITS-29))
41 // fixed = 45 * angle * (1>>(29-FRACBITS))
42 // fixed = (angle>>(29-FRACBITS)) * 45
43
44 #define ANGLE_TO_FIXED(a) (fixed_t)(((a)>>(29-FRACBITS))*45)
45 #define FIXED_TO_ANGLE(x) (angle_t)(((x)/45)<<(29-FRACBITS))
46
47 /*
48 Old code that failed if FRACBITS was not 16.
49 In particular, the use of FRACUNIT in the definition of ANGLE_F is completely
50 wrong. The value wanted actually happens to be 65536 due to the definition
51 of angle_t (it's specified so that 360 degrees = 2^32, to take advantage of
52 modular arithmetic). That 65536 has nothing whatsoever to do with the setting
53 of FRACUNIT.
54
55 #define ANGF_D 8192
56 #define ANGF_N 45
57 #define ANGLE_F (ANGF_N*FRACUNIT/ANGF_D)
58 #define FIXED_TO_ANGLE(x) (angle_t)FixedDiv(x, ANGLE_F) // angle_t = FixedDiv(fixed_t, ANGLE_F)
59 #define ANGLE_TO_FIXED(x) FixedMul((fixed_t)(x), ANGLE_F) // fixed_t = FixedMul(angle_t, ANGLE_F)
60 */
61
AngleFixed204(angle_t af)62 static fixed_t AngleFixed204(angle_t af)
63 {
64 const fixed_t cfn = 180*FRACUNIT;
65 if (af == 0)
66 return 0;
67 else if (af > ANGLE_180)
68 return cfn + ANGLE_TO_FIXED(af - ANGLE_180);
69 else if (af < ANGLE_180)
70 return ANGLE_TO_FIXED(af);
71 else return cfn;
72 }
73
FixedAngleC204(fixed_t fa,fixed_t factor)74 static inline angle_t FixedAngleC204(fixed_t fa, fixed_t factor)
75 {
76 #if 0 //FixedMod off?
77 const boolean neqda = da < 0, neqfa = fa < 0;
78 const fixed_t afactor = abs(factor);
79 angle_t ra = ANGLE_180;
80
81 if (factor == 0)
82 return FixedAngle204(fa);
83 else if (fa == 0)
84 return 0;
85
86 if (neqfactor)
87 {
88 const fixed_t maf = FixedDiv(afactor, ANGLE_F);
89 const fixed_t cfn = FixedMul(360*FRACUNIT, afactor), hcfn = (cfn/2);
90 const fixed_t fam = FixedMod(fa, cfn);
91
92 if (fam > hcfn)
93 ra = ANGLE_180 + (angle_t)FixedMul(fam - hcfn, maf);
94 else if (fam < hcfn)
95 ra = (angle_t)FixedMul(fam, maf);
96 }
97 else
98 {
99 const fixed_t maf = FixedMul(afactor, ANGLE_F);
100 const fixed_t cfn = FixedDiv(360*FRACUNIT, afactor), hcfn = (cfn/2);
101 const fixed_t fam = FixedMod(fa, cfn);
102
103 if (fam > hcfn)
104 ra = ANGLE_180 + (angle_t)FixedDiv(fam - hcfn, maf);
105 else if (fam < hcfn)
106 ra = (angle_t)FixedDiv(fam, maf);
107 }
108
109 if (neqfa)
110 ra = ANGLE_MAX-ra;
111
112 return ra;
113 #else
114 if (factor == 0)
115 return FixedAngle(fa);
116 else if (factor > 0)
117 return (angle_t)((FIXED_TO_FLOAT(fa)/FIXED_TO_FLOAT(factor))*(ANGLE_45/45));
118 else
119 return (angle_t)((FIXED_TO_FLOAT(fa)*FIXED_TO_FLOAT(-factor))*(ANGLE_45/45));
120 #endif
121 }
122
FixedAngle(fixed_t fa)123 angle_t FixedAngle(fixed_t fa)
124 {
125 #if 0 //FixedMod off?
126 const boolean neqfa = fa < 0;
127 const fixed_t cfn = 180*FRACUNIT;
128 const fixed_t fam = FixedMod(fa, 360*FRACUNIT);
129 angle_t ra = ANGLE_180;
130
131 if (fa == 0)
132 return 0;
133
134 if (fam > cfn)
135 ra = ANGLE_180+FIXED_TO_ANGLE(fam-cfn);
136 else if (fam < cfn)
137 ra = FIXED_TO_ANGLE(fam);
138
139 if (neqfa)
140 ra = ANGLE_MAX-ra;
141
142 return ra;
143 #else
144 return (angle_t)(FIXED_TO_FLOAT(fa)*(ANGLE_45/45));
145 #endif
146 }
147
AngleFixed205(angle_t af)148 fixed_t AngleFixed205(angle_t af)
149 {
150 #ifdef FIXEDPOINTCONV
151 angle_t wa = ANGLE_180;
152 fixed_t wf = 180*FRACUNIT;
153 fixed_t rf = 0*FRACUNIT;
154 //const angle_t adj = 0x2000;
155
156 //if (af < adj) // too small to notice
157 //return rf;
158
159 while (af)
160 {
161 while (af < wa)
162 {
163 wa /= 2;
164 wf /= 2;
165 }
166 rf += wf;
167 af -= wa;
168 }
169
170 return rf;
171 #else
172 const fixed_t cfn = 180*FRACUNIT;
173 if (af == 0)
174 return 0;
175 else if (af > ANGLE_180)
176 return cfn + ANGLE_TO_FIXED(af - ANGLE_180);
177 else if (af < ANGLE_180)
178 return ANGLE_TO_FIXED(af);
179 else return cfn;
180 #endif
181 }
182
183 #ifdef FIXEDPOINTCONV
AngleAdj(const fixed_t fa,const fixed_t wf,angle_t ra)184 static FUNCMATH angle_t AngleAdj(const fixed_t fa, const fixed_t wf,
185 angle_t ra)
186 {
187 const angle_t adj = 0x77;
188 const boolean fan = fa < 0;
189 const fixed_t sl = FixedDiv(fa, wf*2);
190 const fixed_t lb = FixedRem(fa, wf*2);
191 const fixed_t lo = (wf*2)-lb;
192
193 if (ra == 0)
194 {
195 if (lb == 0)
196 {
197 ra = FixedMul(FRACUNIT/512, sl);
198 if (ra > FRACUNIT/64)
199 return ANGLE_MAX-ra+1;
200 return ra;
201 }
202 else if (lb > 0)
203 return ANGLE_MAX-FixedMul(lo*FRACUNIT, adj)+1;
204 else
205 return ANGLE_MAX-FixedMul(lo*FRACUNIT, adj)+1;
206 }
207
208 if (fan)
209 return ANGLE_MAX-ra+1;
210 else
211 return ra;
212 }
213 #endif
214
FixedAngleC205(fixed_t fa,fixed_t factor)215 angle_t FixedAngleC205(fixed_t fa, fixed_t factor)
216 {
217 #ifdef FIXEDPOINTCONV
218 angle_t wa = ANGLE_180;
219 fixed_t wf = 180*FRACUNIT;
220 angle_t ra = 0;
221 const fixed_t cfa = fa;
222 fixed_t cwf = wf;
223
224 if (fa == 0)
225 return 0;
226
227 if (factor == 0)
228 return FixedAngle(fa);
229 else if (factor > 0)
230 cwf = wf = FixedMul(wf, factor);
231 else if (factor < 0)
232 cwf = wf = FixedDiv(wf, -factor);
233
234 fa = abs(fa);
235
236 while (fa)
237 {
238 while (fa < wf)
239 {
240 wa /= 2;
241 wf /= 2;
242 }
243 ra = ra + wa;
244 fa = fa - wf;
245 }
246
247 return AngleAdj(cfa, cwf, ra);
248 #else
249 if (factor == 0)
250 return FixedAngle(fa);
251
252 //fa = FixedMod(fa, 360*FRACUNIT);
253
254 if (factor > 0)
255 return (angle_t)((FIXED_TO_FLOAT(fa)/FIXED_TO_FLOAT(factor))*(ANGLE_45/45));
256 else
257 return (angle_t)((FIXED_TO_FLOAT(fa)*FIXED_TO_FLOAT(-factor))*(ANGLE_45/45));
258 #endif
259 }
260
FixedAngle205(fixed_t fa)261 angle_t FixedAngle205(fixed_t fa)
262 {
263 #ifdef FIXEDPOINTCONV
264 angle_t wa = ANGLE_180;
265 fixed_t wf = 180*FRACUNIT;
266 angle_t ra = 0;
267 const fixed_t cfa = fa;
268 const fixed_t cwf = wf;
269
270 if (fa == 0)
271 return 0;
272
273 fa = abs(fa);
274
275 while (fa)
276 {
277 while (fa < wf)
278 {
279 wa /= 2;
280 wf /= 2;
281 }
282 ra = ra + wa;
283 fa = fa - wf;
284 }
285
286 return AngleAdj(cfa, cwf, ra);
287 #else
288 //fa = FixedMod(fa, 360*FRACUNIT);
289
290 if (fa == 0)
291 return 0;
292
293 return (angle_t)(FIXED_TO_FLOAT(fa)*(ANGLE_45/45));
294 #endif
295 }
296
main(int argc,char ** argv)297 int main(int argc, char** argv)
298 {
299 fixed_t f, f204, f205;
300 INT64 a;
301 angle_t a204, a205;
302 fixed_t CF = 40*FRACUNIT;
303 int err = 0;
304 (void)argc;
305 (void)argv;
306
307 err = 0x29; //41
308
309 if (1)
310 for (a = 0; a < ANGLE_MAX; a += 0x1)
311 {
312 f204 = AngleFixed204((angle_t)a);
313 f205 = AngleFixed205((angle_t)a);
314 if (f204 != f205 && (abs(f204-f205) > err || f204 == 0 || f205 == 0))
315 {
316 printf("Angle: %u, %d, %d, %d\n", (angle_t)a, f204, f205, f204-f205);
317 //err = abs(f204-f205);
318 }
319 }
320
321 //err = FixedDiv(FRACUNIT, 120*FRACUNIT); // 547
322 err = FixedDiv(FRACUNIT, 62*FRACUNIT); //1059
323
324 if (1)
325 for (f = FRACUNIT*-720; f < FRACUNIT*720; f += 1)
326 {
327 a204 = FixedAngle(f);
328 a205 = FixedAngle205(f);
329 if (a204 != a205 && (abs(a204-a205) > err || a204 == 0 || a205 == 0))
330 {
331 printf("Fixed: %f, %u, %u, %d\n", FIXED_TO_FLOAT(f), a204, a205, a204-a205);
332 err = abs(a204-a205);
333 }
334 }
335
336 //err = FixedDiv(FRACUNIT, 316*FRACUNIT); //207
337 err = FixedDiv(FRACUNIT, 125*FRACUNIT); //526
338
339 if (1)
340 for (f = FixedMul(FRACUNIT*-720, CF); f < FixedMul(FRACUNIT*720, CF); f += FRACUNIT/16)
341 {
342 a204 = FixedAngleC204(f, CF);
343 a205 = FixedAngleC205(f, CF);
344 if (a204 != a205 && (abs(a204-a205) > err || a204 == 0 || a205 == 0))
345 {
346 printf("FixedC: %f, %u, %u, %d\n", FIXED_TO_FLOAT(f), a204, a205, a204-a205);
347 //err = abs(a204-a205);
348 }
349 }
350
351 return 0;
352 }
353
cpu_cpy(void * dest,const void * src,size_t n)354 static void *cpu_cpy(void *dest, const void *src, size_t n)
355 {
356 return memcpy(dest, src, n);
357 }
358
359 void *(*M_Memcpy)(void* dest, const void* src, size_t n) = cpu_cpy;
360
I_Error(const char * error,...)361 void I_Error(const char *error, ...)
362 {
363 (void)error;
364 exit(-1);
365 }
366