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