1 /*! ========================================================================
2 ** Extended Template and Library Test Suite
3 ** Angle Class Test
4 ** $Id$
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 ** Copyright (c) 2008 Chris Moore
8 **
9 ** This package is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU General Public License as
11 ** published by the Free Software Foundation; either version 2 of
12 ** the License, or (at your option) any later version.
13 **
14 ** This package is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ** General Public License for more details.
18 **
19 ** === N O T E S ===========================================================
20 **
21 ** ========================================================================= */
22 
23 /* === H E A D E R S ======================================================= */
24 
25 #include <stdio.h>
26 #include <ETL/angle>
27 #include <ETL/fastangle>
28 #include <ETL/clock>
29 #include <ETL/bezier>
30 #include <ETL/hermite>
31 
32 /* === M A C R O S ========================================================= */
33 
34 ETL_FASTANGLE_INIT();
35 
36 using namespace std;
37 using namespace etl;
38 
39 /* === C L A S S E S ======================================================= */
40 
fastangle_test(void)41 int fastangle_test(void)
42 {
43 	int ret=0;
44 	float largest_error;
45 
46 	{
47 		angle theta;
48 		fastangle theta2;
49 		float error;
50 		largest_error=0.0f;
51 
52 		for(
53 			theta=angle::degrees(0),theta2=fastangle::degrees(0);
54 			theta<=angle::degrees(360);
55 			theta+=angle::degrees(10),theta2+=fastangle::degrees(10)
56 		)
57 		{
58 			error=(float)angle::sin(theta).get() -(float)fastangle::sin(theta2).get();
59 			/*
60 			fprintf(stderr,"angle: sin(%d)=%f ;\tfastangle: sin(%d)=%f ;\t diff: %f\n",
61 				(int)angle::degrees(theta),
62 				(float)angle::sin(theta),
63 				(int)fastangle::degrees(theta2),
64 				(float)fastangle::sin(theta2),
65 				error
66 				);
67 			*/
68 			if(error > largest_error)
69 				largest_error=error;
70 			if(error < -largest_error)
71 				largest_error=-error;
72 
73 		}
74 	}
75 	printf("fastangle: Largest SIN error: (+/-)%f\n",largest_error);
76 	if(largest_error>0.075)ret++;
77 
78 	{
79 		angle theta;
80 		fastangle theta2;
81 		float error;
82 		largest_error=0.0f;
83 
84 		for(
85 			theta=angle::degrees(0),theta2=fastangle::degrees(0);
86 			theta<=angle::degrees(360);
87 			theta+=angle::degrees(10),theta2+=fastangle::degrees(10)
88 		)
89 		{
90 			error=(float)angle::cos(theta).get() -(float)fastangle::cos(theta2).get();
91 			/*
92 			fprintf(stderr,"angle: cos(%d)=%f ;\tfastangle: cos(%d)=%f ;\t diff: %f\n",
93 				(int)angle::degrees(theta),
94 				(float)angle::cos(theta),
95 				(int)fastangle::degrees(theta2),
96 				(float)fastangle::cos(theta2),
97 				error
98 				);
99 			*/
100 			if(error > largest_error)
101 				largest_error=error;
102 			if(error < -largest_error)
103 				largest_error=-error;
104 
105 		}
106 	}
107 	printf("fastangle: Largest COS error: (+/-)%f\n",largest_error);
108 	if(largest_error>0.075)ret++;
109 
110 	{
111 		double val;
112 		float error;
113 		largest_error=0.0f;
114 
115 		for(
116 			val=-1.0f;
117 			val<1.0f;
118 			val+=0.01
119 		)
120 		{
121 			error=angle::radians(angle::sin(val)).get() -fastangle::radians(fastangle::sin(val)).get();
122 			/*
123 			fprintf(stderr,"angle: asin(%f)=%frad ;\tfastangle: asin(%f)=%frad ;\t diff: %f\n",
124 				val,
125 				(float)(angle::radians)angle::sin(val),
126 				val,
127 				(float)(fastangle::radians)fastangle::sin(val),
128 				error
129 				);
130 			*/
131 			if(error > largest_error)
132 				largest_error=error;
133 			if(error < -largest_error)
134 				largest_error=-error;
135 
136 		}
137 	}
138 	printf("fastangle: Largest ASIN error: (+/-)%frad\n",largest_error);
139 	if(largest_error>0.075)ret++;
140 
141 
142 	{
143 		double val;
144 		float error;
145 		largest_error=0.0f;
146 
147 		for(
148 			val=-1.0f;
149 			val<1.0f;
150 			val+=0.01
151 		)
152 		{
153 			error=angle::radians(angle::cos(val)).get() -fastangle::radians(fastangle::cos(val)).get();
154 			/*
155 			fprintf(stderr,"angle: acos(%f)=%frad ;\tfastangle: acos(%f)=%frad ;\t diff: %f\n",
156 				val,
157 				(float)(angle::radians)angle::cos(val),
158 				val,
159 				(float)(fastangle::radians)fastangle::cos(val),
160 				error
161 				);
162 			*/
163 			if(error > largest_error)
164 				largest_error=error;
165 			if(error < -largest_error)
166 				largest_error=-error;
167 
168 		}
169 	}
170 	printf("fastangle: Largest ACOS error: (+/-)%frad\n",largest_error);
171 	if(largest_error>0.075)ret++;
172 
173 
174 	{
175 		angle theta;
176 		fastangle theta2;
177 		float error;
178 		largest_error=0.0f;
179 
180 		for(
181 			theta=angle::degrees(0),theta2=fastangle::degrees(0);
182 			theta<angle::degrees(360);
183 			theta+=angle::degrees(38),theta2+=fastangle::degrees(38)
184 		)
185 		{
186 			error=angle::tan(theta).get() - fastangle::tan(theta2).get();
187 			/*
188 			fprintf(stderr,"angle: tan(%d)=%f ;\tfastangle: tan(%d)=%f ;\t diff: %f\n",
189 				(int)angle::degrees(theta),
190 				(float)angle::tan(theta),
191 				(int)fastangle::degrees(theta2),
192 				(float)fastangle::tan(theta2),
193 				error
194 				);
195 			*/
196 			if(error > largest_error)
197 				largest_error=error;
198 			if(error < -largest_error)
199 				largest_error=-error;
200 
201 		}
202 	}
203 	printf("fastangle: Largest TAN error: (+/-)%f\n",largest_error);
204 	if(largest_error>0.75)ret++;
205 
206 	{
207 		double val;
208 		float error;
209 		largest_error=0.0f;
210 
211 		for(
212 			val=-4.0f;
213 			val<4.0f;
214 			val+=0.1
215 		)
216 		{
217 			error=angle::radians(angle::tan(val)).get() -fastangle::radians(fastangle::tan(val)).get();
218 			/*
219 			fprintf(stderr,"angle: atan(%f)=%frad ;\tfastangle: atan(%f)=%frad ;\t diff: %f\n",
220 				val,
221 				(float)(angle::radians)angle::tan(val),
222 				val,
223 				(float)(fastangle::radians)fastangle::tan(val),
224 				error
225 				);
226 			*/
227 			if(error > largest_error)
228 				largest_error=error;
229 			if(error < -largest_error)
230 				largest_error=-error;
231 
232 		}
233 	}
234 	printf("fastangle: Largest ATAN error: (+/-)%frad\n",largest_error);
235 	if(largest_error>0.075)ret++;
236 
237 
238 	{
239 		angle theta;
240 		float error;
241 		largest_error=0.0f;
242 
243 		for(
244 			theta=angle::degrees(-179);
245 			theta<angle::degrees(180);
246 			theta+=angle::degrees(5)
247 		)
248 		{
249 			error=angle::radians(theta).get()-fastangle::radians(fastangle::tan(angle::sin(theta).get(),angle::cos(theta).get())).get();
250 			/*
251 			fprintf(stderr,"\tfastangle: atan2(%f, %f)=%fdeg (%f) ;\t diff: %frad\n",
252 				(float)angle::sin(theta),
253 				(float)angle::cos(theta),
254 				(float)(fastangle::degrees)fastangle::tan(angle::sin(theta),angle::cos(theta)),
255 				(float)(fastangle::degrees)fastangle::tan((float)angle::sin(theta)/(float)angle::cos(theta)),
256 				error
257 				);
258 			*/
259 			if(error > largest_error)
260 				largest_error=error;
261 			if(error < -largest_error)
262 				largest_error=-error;
263 
264 		}
265 	}
266 	printf("fastangle: Largest ATAN2 error: (+/-)%frad\n",largest_error);
267 	if(largest_error>0.075)ret++;
268 
269 	printf("constant tests: %f==%f\n",
270 		(float)angle::degrees(angle::tan(1.01)).get(),
271 		(float)fastangle::degrees(fastangle::tan(1.01)).get());
272 	printf("constant tests: %f==%f\n",
273 		(float)angle::degrees(angle::tan(-1.0)).get(),
274 		(float)fastangle::degrees(fastangle::tan(-1.0)).get());
275 
276 	return ret;
277 }
278 
279 template <class Angle>
angle_cos_speed_test(void)280 void angle_cos_speed_test(void)
281 {
282 	Angle a,b,c,d;
283 	float tmp,tmp2;
284 
285 	for(tmp=-1.0;tmp<1.0;tmp+=0.000002)
286 	{
287 		a=(typename Angle::cos)(tmp);
288 		b=(typename Angle::cos)(tmp);
289 		c=(typename Angle::cos)(tmp);
290 		d=(typename Angle::cos)(tmp);
291 		tmp2=((typename Angle::cos)(a)).get();
292 		tmp2=((typename Angle::cos)(b)).get();
293 		tmp2=((typename Angle::cos)(c)).get();
294 		tmp2=((typename Angle::cos)(d)).get();
295 	}
296 	if (tmp2 == 0) return; // disable unused warning
297 }
298 template <class Angle>
angle_sin_speed_test(void)299 void angle_sin_speed_test(void)
300 {
301 	Angle a,b,c,d;
302 	float tmp,tmp2;
303 
304 	for(tmp=-1.0;tmp<1.0;tmp+=0.000002)
305 	{
306 		a=(typename Angle::sin)(tmp);
307 		b=(typename Angle::sin)(tmp);
308 		c=(typename Angle::sin)(tmp);
309 		d=(typename Angle::sin)(tmp);
310 		tmp2=((typename Angle::sin)(a)).get();
311 		tmp2=((typename Angle::sin)(b)).get();
312 		tmp2=((typename Angle::sin)(c)).get();
313 		tmp2=((typename Angle::sin)(d)).get();
314 	}
315 	if (tmp2 == 0) return; // disable unused warning
316 }
317 template <class Angle>
angle_tan_speed_test(void)318 void angle_tan_speed_test(void)
319 {
320 	Angle a,b,c,d;
321 	float tmp,tmp2;
322 
323 	for(tmp=-1.0;tmp<1.0;tmp+=0.000002)
324 	{
325 		a=(typename Angle::tan)(tmp);
326 		b=(typename Angle::tan)(tmp);
327 		c=(typename Angle::tan)(tmp);
328 		d=(typename Angle::tan)(tmp);
329 		tmp2=((typename Angle::tan)(a)).get();
330 		tmp2=((typename Angle::tan)(b)).get();
331 		tmp2=((typename Angle::tan)(c)).get();
332 		tmp2=((typename Angle::tan)(d)).get();
333 	}
334 	if (tmp2 == 0) return; // disable unused warning
335 }
336 template <class Angle, class mytan>
angle_atan2_speed_test(void)337 void angle_atan2_speed_test(void)
338 {
339 	Angle a,b,c;
340 	float x,y;
341 
342 	for(y=-10.0;y<10.0;y+=0.05)
343 		for(x=-10.0;x<10.0;x+=0.05)
344 		{
345 			a=mytan(y,x);
346 			a=mytan(x,y);
347 			b=mytan(y,x);
348 			b=mytan(x,y);
349 			c=mytan(y,x);
350 			c=mytan(x,y);
351 			a=mytan(y,x);
352 			a=mytan(x,y);
353 			b=mytan(y,x);
354 			b=mytan(x,y);
355 			c=mytan(y,x);
356 			c=mytan(x,y);
357 		}
358 }
359 
fastangle_speed_test(void)360 int fastangle_speed_test(void)
361 {
362 	int ret=0;
363 	float
364 		angle_cos_time,
365 		fastangle_cos_time,
366 		angle_tan_time,
367 		fastangle_tan_time,
368 		angle_atan2_time,
369 		fastangle_atan2_time,
370 		angle_sin_time,
371 		fastangle_sin_time ;
372 
373 	etl::clock MyTimer;
374 
375 	MyTimer.reset();
376 	angle_cos_speed_test<angle>();
377 	angle_cos_time=MyTimer();
378 	printf("angle: Cosine test: %f seconds\n",angle_cos_time);
379 
380 	MyTimer.reset();
381 	angle_cos_speed_test<fastangle>();
382 	fastangle_cos_time=MyTimer();
383 	printf("fastangle: Cosine test: %f seconds\n",fastangle_cos_time);
384 	printf("fastangle is %.02f%% faster\n",(angle_cos_time/fastangle_cos_time)*100.0-100.0);
385 
386 	MyTimer.reset();
387 	angle_sin_speed_test<angle>();
388 	angle_sin_time=MyTimer();
389 	printf("angle: Sine test: %f seconds\n",angle_sin_time);
390 
391 	MyTimer.reset();
392 	angle_sin_speed_test<fastangle>();
393 	fastangle_sin_time=MyTimer();
394 	printf("fastangle: Sine test: %f seconds\n",fastangle_sin_time);
395 	printf("fastangle is %.02f%% faster\n",(angle_sin_time/fastangle_sin_time)*100.0-100.0);
396 
397 	MyTimer.reset();
398 	angle_tan_speed_test<angle>();
399 	angle_tan_time=MyTimer();
400 	printf("angle: Tangent test: %f seconds\n",angle_tan_time);
401 
402 	MyTimer.reset();
403 	angle_tan_speed_test<fastangle>();
404 	fastangle_tan_time=MyTimer();
405 	printf("fastangle: Tangent test: %f seconds\n",fastangle_tan_time);
406 	printf("fastangle is %.02f%% faster\n",(angle_tan_time/fastangle_tan_time)*100.0-100.0);
407 
408 	MyTimer.reset();
409 	angle_atan2_speed_test<angle,angle::tan>();
410 	angle_atan2_time=MyTimer();
411 	printf("angle: arcTangent2 test: %f seconds\n",angle_atan2_time);
412 
413 	MyTimer.reset();
414 	angle_atan2_speed_test<fastangle,fastangle::tan>();
415 	fastangle_atan2_time=MyTimer();
416 	printf("fastangle: arcTangent2 test: %f seconds\n",fastangle_atan2_time);
417 	printf("fastangle is %.02f%% faster\n",(angle_atan2_time/fastangle_atan2_time)*100.0-100.0);
418 
419 	return ret;
420 }
421 
angle_test()422 int angle_test()
423 {
424 	int ret=0;
425 	float dist;
426 
427 	dist=angle::deg(angle::deg(330).dist(angle::deg(30))).get();
428 	printf("angle: angular difference between 330deg and 30deg is %0.1fdeg\n",dist);
429 	if(floor(dist+0.5)!=300)
430 	{
431 		printf("angle: error: should be 300deg!\n");
432 		ret++;
433 	}
434 
435 	dist=angle::deg(angle::deg(30).dist(angle::deg(330))).get();
436 	printf("angle: angular difference between 30deg and 330deg is %0.1fdeg\n",dist);
437 	if(floor(dist+0.5)!=-300)
438 	{
439 		printf("angle: error: should be -300deg!\n");
440 		ret++;
441 	}
442 
443 	dist=angle::deg(angle::deg(30).dist(angle::deg(-30))).get();
444 	printf("angle: angular difference between 30deg and -30deg is %0.1fdeg\n",dist);
445 	if(floor(dist+0.5)!=60)
446 	{
447 		printf("angle: error: should be 60deg!\n");
448 		ret++;
449 	}
450 
451 	dist=angle::deg(angle::deg(-30).dist(angle::deg(30))).get();
452 	printf("angle: angular difference between -30deg and 30deg is %0.1fdeg\n",dist);
453 	if(floor(dist+0.5)!=-60)
454 	{
455 		printf("angle: error: should be -60deg!\n");
456 		ret++;
457 	}
458 
459 	dist=angle::deg(angle::deg(20).dist(angle::deg(195))).get();
460 	printf("angle: angular difference between 20deg and 195deg is %0.1fdeg\n",dist);
461 	if(floor(dist+0.5)!=-175)
462 	{
463 		printf("angle: error: should be -175deg!\n");
464 		ret++;
465 	}
466 
467 	dist=angle::deg(angle::deg(20).dist(angle::deg(205))).get();
468 	printf("angle: angular difference between 20deg and 205deg is %0.1fdeg\n",dist);
469 	if(floor(dist+0.5)!=-185)
470 	{
471 		printf("angle: error: should be -185deg!\n");
472 		ret++;
473 	}
474 
475 	int i;
476 
477 	for(i=-1000;i<1000;i++)
478 	{
479 		dist=angle::deg(angle::deg(20+i+360).dist(angle::deg(205+i-360))).get();
480 		if(floor(dist+0.5)!=535)
481 		{
482 			printf("angle: error: Badness at %d!\n",i);
483 			ret++;
484 		}
485 
486 	}
487 
488 	for(i=-1000;i<1000;i++)
489 	{
490 		dist=angle::deg(angle::deg(20+i-360).dist(angle::deg(195+i+360))).get();
491 		if(floor(dist+0.5)!=-895)
492 		{
493 			printf("angle: error: Badness at %d!\n",i);
494 			ret++;
495 		}
496 
497 	}
498 
499 
500 
501 	{
502 		float f;
503 		angle a(angle::deg(-2005));
504 		angle b(angle::deg(200));
505 
506 		affine_combo<angle> combo;
507 
508 		hermite<angle> hermie(a,b,b.dist(a),b.dist(a));
509 
510 		for(f=0;f<1.001;f+=0.1)
511 		{
512 			printf("@%f--affine_combo: %f hermie: %f\n",angle::deg(f).get(),angle::deg(combo(a,b,f)).get(),angle::deg(hermie(f)).get());
513 		}
514 
515 	}
516 
517 	return ret;
518 }
519 
520 /* === E N T R Y P O I N T ================================================= */
521 
main()522 int main()
523 {
524 	int error=0;
525 
526 	error+=fastangle_test();
527 	error+=fastangle_speed_test();
528 	error+=angle_test();
529 
530 	return error;
531 }
532