Use LinkableValueNode members functions when possible in the derived valuenodes.
[synfig.git] / ETL / 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 ** 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
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>
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 }
297 template <class Angle>
298 void angle_sin_speed_test(void)
299 {
300         Angle a,b,c,d;
301         float tmp,tmp2;
302
303         for(tmp=-1.0;tmp<1.0;tmp+=0.000002)
304         {
305                 a=(typename Angle::sin)(tmp);
306                 b=(typename Angle::sin)(tmp);
307                 c=(typename Angle::sin)(tmp);
308                 d=(typename Angle::sin)(tmp);
309                 tmp2=((typename Angle::sin)(a)).get();
310                 tmp2=((typename Angle::sin)(b)).get();
311                 tmp2=((typename Angle::sin)(c)).get();
312                 tmp2=((typename Angle::sin)(d)).get();
313         }
314 }
315 template <class Angle>
316 void angle_tan_speed_test(void)
317 {
318         Angle a,b,c,d;
319         float tmp,tmp2;
320
321         for(tmp=-1.0;tmp<1.0;tmp+=0.000002)
322         {
323                 a=(typename Angle::tan)(tmp);
324                 b=(typename Angle::tan)(tmp);
325                 c=(typename Angle::tan)(tmp);
326                 d=(typename Angle::tan)(tmp);
327                 tmp2=((typename Angle::tan)(a)).get();
328                 tmp2=((typename Angle::tan)(b)).get();
329                 tmp2=((typename Angle::tan)(c)).get();
330                 tmp2=((typename Angle::tan)(d)).get();
331         }
332 }
333 template <class Angle, class mytan>
334 void angle_atan2_speed_test(void)
335 {
336         Angle a,b,c;
337         float x,y;
338
339         for(y=-10.0;y<10.0;y+=0.05)
340                 for(x=-10.0;x<10.0;x+=0.05)
341                 {
342                         a=mytan(y,x);
343                         a=mytan(x,y);
344                         b=mytan(y,x);
345                         b=mytan(x,y);
346                         c=mytan(y,x);
347                         c=mytan(x,y);
348                         a=mytan(y,x);
349                         a=mytan(x,y);
350                         b=mytan(y,x);
351                         b=mytan(x,y);
352                         c=mytan(y,x);
353                         c=mytan(x,y);
354                 }
355 }
356
357 int fastangle_speed_test(void)
358 {
359         int ret=0;
360         float
361                 angle_cos_time,
362                 fastangle_cos_time,
363                 angle_tan_time,
364                 fastangle_tan_time,
365                 angle_atan2_time,
366                 fastangle_atan2_time,
367                 angle_sin_time,
368                 fastangle_sin_time ;
369
370         etl::clock MyTimer;
371
372         MyTimer.reset();
373         angle_cos_speed_test<angle>();
374         angle_cos_time=MyTimer();
375         printf("angle: Cosine test: %f seconds\n",angle_cos_time);
376
377         MyTimer.reset();
378         angle_cos_speed_test<fastangle>();
379         fastangle_cos_time=MyTimer();
380         printf("fastangle: Cosine test: %f seconds\n",fastangle_cos_time);
381         printf("fastangle is %.02f%% faster\n",(angle_cos_time/fastangle_cos_time)*100.0-100.0);
382
383         MyTimer.reset();
384         angle_sin_speed_test<angle>();
385         angle_sin_time=MyTimer();
386         printf("angle: Sine test: %f seconds\n",angle_sin_time);
387
388         MyTimer.reset();
389         angle_sin_speed_test<fastangle>();
390         fastangle_sin_time=MyTimer();
391         printf("fastangle: Sine test: %f seconds\n",fastangle_sin_time);
392         printf("fastangle is %.02f%% faster\n",(angle_sin_time/fastangle_sin_time)*100.0-100.0);
393
394         MyTimer.reset();
395         angle_tan_speed_test<angle>();
396         angle_tan_time=MyTimer();
397         printf("angle: Tangent test: %f seconds\n",angle_tan_time);
398
399         MyTimer.reset();
400         angle_tan_speed_test<fastangle>();
401         fastangle_tan_time=MyTimer();
402         printf("fastangle: Tangent test: %f seconds\n",fastangle_tan_time);
403         printf("fastangle is %.02f%% faster\n",(angle_tan_time/fastangle_tan_time)*100.0-100.0);
404
405         MyTimer.reset();
406         angle_atan2_speed_test<angle,angle::tan>();
407         angle_atan2_time=MyTimer();
408         printf("angle: arcTangent2 test: %f seconds\n",angle_atan2_time);
409
410         MyTimer.reset();
411         angle_atan2_speed_test<fastangle,fastangle::tan>();
412         fastangle_atan2_time=MyTimer();
413         printf("fastangle: arcTangent2 test: %f seconds\n",fastangle_atan2_time);
414         printf("fastangle is %.02f%% faster\n",(angle_atan2_time/fastangle_atan2_time)*100.0-100.0);
415
416         return ret;
417 }
418
419 int angle_test()
420 {
421         int ret=0;
422         float dist;
423
424         dist=angle::deg(angle::deg(330).dist(angle::deg(30))).get();
425         printf("angle: angular difference between 330deg and 30deg is %0.1fdeg\n",dist);
426         if(floor(dist+0.5)!=300)
427         {
428                 printf("angle: error: should be 300deg!\n");
429                 ret++;
430         }
431
432         dist=angle::deg(angle::deg(30).dist(angle::deg(330))).get();
433         printf("angle: angular difference between 30deg and 330deg is %0.1fdeg\n",dist);
434         if(floor(dist+0.5)!=-300)
435         {
436                 printf("angle: error: should be -300deg!\n");
437                 ret++;
438         }
439
440         dist=angle::deg(angle::deg(30).dist(angle::deg(-30))).get();
441         printf("angle: angular difference between 30deg and -30deg is %0.1fdeg\n",dist);
442         if(floor(dist+0.5)!=60)
443         {
444                 printf("angle: error: should be 60deg!\n");
445                 ret++;
446         }
447
448         dist=angle::deg(angle::deg(-30).dist(angle::deg(30))).get();
449         printf("angle: angular difference between -30deg and 30deg is %0.1fdeg\n",dist);
450         if(floor(dist+0.5)!=-60)
451         {
452                 printf("angle: error: should be -60deg!\n");
453                 ret++;
454         }
455
456         dist=angle::deg(angle::deg(20).dist(angle::deg(195))).get();
457         printf("angle: angular difference between 20deg and 195deg is %0.1fdeg\n",dist);
458         if(floor(dist+0.5)!=-175)
459         {
460                 printf("angle: error: should be -175deg!\n");
461                 ret++;
462         }
463
464         dist=angle::deg(angle::deg(20).dist(angle::deg(205))).get();
465         printf("angle: angular difference between 20deg and 205deg is %0.1fdeg\n",dist);
466         if(floor(dist+0.5)!=-185)
467         {
468                 printf("angle: error: should be -185deg!\n");
469                 ret++;
470         }
471
472         int i;
473
474         for(i=-1000;i<1000;i++)
475         {
476                 dist=angle::deg(angle::deg(20+i+360).dist(angle::deg(205+i-360))).get();
477                 if(floor(dist+0.5)!=535)
478                 {
479                         printf("angle: error: Badness at %d!\n",i);
480                         ret++;
481                 }
482
483         }
484
485         for(i=-1000;i<1000;i++)
486         {
487                 dist=angle::deg(angle::deg(20+i-360).dist(angle::deg(195+i+360))).get();
488                 if(floor(dist+0.5)!=-895)
489                 {
490                         printf("angle: error: Badness at %d!\n",i);
491                         ret++;
492                 }
493
494         }
495
496
497
498         {
499                 float f;
500                 angle a(angle::deg(-2005));
501                 angle b(angle::deg(200));
502
503                 affine_combo<angle> combo;
504
505                 hermite<angle> hermie(a,b,b.dist(a),b.dist(a));
506
507                 for(f=0;f<1.001;f+=0.1)
508                 {
509                         printf("@%f--affine_combo: %f hermie: %f\n",angle::deg(f).get(),angle::deg(combo(a,b,f)).get(),angle::deg(hermie(f)).get());
510                 }
511
512         }
513
514         return ret;
515 }
516
517 /* === E N T R Y P O I N T ================================================= */
518
519 int main()
520 {
521         int error=0;
522
523         error+=fastangle_test();
524         error+=fastangle_speed_test();
525         error+=angle_test();
526
527         return error;
528 }