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