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