Remove the "** FIXME: THIS DOES NOT ACTUALLY WORK YET" lines.
[synfig.git] / ETL / trunk / test / fixed.cpp
1 /*! ========================================================================
2 ** Extended Template and Library Test Suite
3 ** Fixed-Point Math 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 #define ETL_FIXED_BITS          12
25
26 #include <ETL/fixed>
27 #include <stdio.h>
28 #include <ETL/clock>
29
30 /* === M A C R O S ========================================================= */
31
32 #ifndef PI
33 # define PI (3.1415926535897932384626433832795029L)
34 #endif
35
36 #define ADD_SUB_TEST    20000000
37 #define MUL_TEST                10000000
38 #define DIV_TEST                1048573 // at 1048573, fixed point numbers wrap around to zero
39 using namespace etl;
40
41 /* === C L A S S E S ======================================================= */
42
43 template <class value_type>
44 struct speed_test
45 {
46         double add_sub_test(void)
47         {
48                 value_type a=1;
49                 value_type b=2;
50                 value_type c=3;
51                 int i;
52                 etl::clock MyTimer;
53                 MyTimer.reset();
54                 for(i=0;i<ADD_SUB_TEST;i++)
55                 {
56                         a+=a; a-=b; a-=c; a+=a;
57                         a+=a; a-=b; a-=c; a+=a;
58                         a+=a; a-=b; a-=c; a+=a;
59                         a+=a; a-=b; a-=c; a+=a;
60                         a+=a; a-=b; a-=c; a+=a;
61                         a+=a; a-=b; a-=c; a+=a;
62                         a+=a; a-=b; a-=c; a+=a;
63                 }
64
65                 fprintf(stderr, "[%1d]...", int(int(a)/1e9)+5); // so the compiler doesn't optimize everything out
66                 return MyTimer();
67         }
68
69         double mul_test(void)
70         {
71                 value_type a,b,c,d;
72                 a=value_type(2.25);
73                 b=value_type(2);
74                 c=value_type(4.5);
75                 d=value_type(1);
76                 const value_type one_and_a_half(static_cast<value_type>(1.5));
77                 int i;
78                 etl::clock MyTimer;
79                 MyTimer.reset();
80                 for(i=1;i<MUL_TEST;i++)
81                 {
82                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
83                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
84                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
85                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
86                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
87                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
88                         d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
89                 }
90
91                 fprintf(stderr, "[%1d]...", int(int(a)/1e9)+5); // so the compiler doesn't optimize everything out
92                 return MyTimer();
93         }
94
95         double div_test(void)
96         {
97                 value_type a(30);
98                 value_type b(40);
99                 value_type acc(0);
100                 int i, j;
101                 etl::clock MyTimer;
102                 MyTimer.reset();
103                 for(j=0;j<10;j++)
104                         for(i=1;i<DIV_TEST;i++)
105                         {
106                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
107                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
108                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
109                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
110                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
111                                 a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
112                         }
113
114                 fprintf(stderr, "[%1d]...", int(int(a)/1e9)+5); // so the compiler doesn't optimize everything out
115                 return MyTimer();
116         }
117 };
118
119 /* === P R O C E D U R E S ================================================= */
120
121 int basic_test(void)
122 {
123         int ret=0;
124
125         fixed a,b,c;
126         double d;
127
128         a=-1;
129         a=std::abs(a);
130         if(a!=fixed(1))
131         {
132                 fprintf(stderr,"fixed: abs() failure on line %d in "__FILE__".\n",__LINE__);
133                 ret++;
134         }
135
136         d=(double)(fixed(2.5)*fixed(3.0f)/7)-(2.5f*3.0f/7.0f);
137         fprintf(stderr,"fixed: 2.5 * 2 / 7 --- Difference: %f\n",d);
138         if(d<0.0)d=-d;
139         if( d>0.0005)
140         {
141                 fprintf(stderr,"fixed: Failed test on line %d in "__FILE__".\n",__LINE__);
142                 ret++;
143         }
144
145         a=1043;d=1043;
146         a/=27;d/=27;
147         a+=10.42;d+=10.42;
148         a/=6;d/=6;
149         a*=PI;d*=PI;
150         d-=(double)a;
151         fprintf(stderr,"fixed: ( 1043 / 27 + 10.42 ) / 6 * PI --- Difference: %f\n",d);
152         if(d<0.0)d=-d;
153 #ifdef ROUND_TO_NEAREST_INTEGER
154         if( d>0.0005)
155 #else
156         if( d>0.0025)
157 #endif
158         {
159                 fprintf(stderr,"fixed: Failed test on line %d in "__FILE__".\n",__LINE__);
160                 ret++;
161         }
162
163         return ret;
164 }
165
166 int char_test(void)
167 {
168         int ret=0;
169
170         fixed_base<unsigned char,8> fix;
171         double flt;
172
173         if(sizeof(fix)!=sizeof(unsigned char))
174         {
175                 ret++;
176                 fprintf(stderr,"fixed: Size of fixed_base<unsigned char,8> is wrong!\n");
177         }
178
179         flt=1.0;
180         fix=1.0;
181         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
182
183         flt*=0.7;
184         fix*=0.7;
185         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
186
187         flt*=0.7;
188         fix*=0.7;
189         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
190
191         flt*=0.7;
192         fix*=0.7;
193         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
194
195         flt*=0.7;
196         fix*=0.7;
197         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
198
199         flt*=0.7;
200         fix*=0.7;
201         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
202
203         //flt/=0.7;
204         //fix/=0.7;
205         //fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
206
207         flt+=0.3;
208         fix+=0.3;
209         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
210
211         flt*=2;
212         fix*=2;
213         fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
214
215
216         return ret;
217 }
218
219 /* === E N T R Y P O I N T ================================================= */
220
221 int main()
222 {
223         int error=0;
224
225         error+=basic_test();
226         error+=char_test();
227
228         speed_test<float> float_test;
229         speed_test<int> int_test;
230         speed_test<fixed> fixed_test;
231
232         {
233                 double flt,fix,inte;
234                 fprintf(stderr,"\nAddition/subtraction test...\n");
235
236                 fprintf(stderr,"  calculating float.....");
237                 flt=float_test.add_sub_test();
238                 fprintf(stderr,"   float time: %f sec\n",flt);
239
240                 fprintf(stderr,"  calculating fixed.....");
241                 fix=fixed_test.add_sub_test();
242                 fprintf(stderr,"   fixed time: %f sec\n",fix);
243
244                 fprintf(stderr,"  calculating integer...");
245                 inte=int_test.add_sub_test();
246                 fprintf(stderr," integer time: %f sec\n",inte);
247
248                 if(flt>fix)
249                         fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
250                 else
251                         fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
252
253         }
254
255         {
256                 double flt,fix,inte;
257                 fprintf(stderr,"\nProduct test...\n");
258                 fprintf(stderr,"  calculating float.....");
259                 flt=float_test.mul_test();
260                 fprintf(stderr,"   float time: %f sec\n",flt);
261                 fprintf(stderr,"  calculating fixed.....");
262                 fix=fixed_test.mul_test();
263                 fprintf(stderr,"   fixed time: %f sec\n",fix);
264                 fprintf(stderr,"  calculating integer...");
265                 inte=int_test.mul_test();
266                 fprintf(stderr," integer time: %f sec\n",inte);
267                 if(flt>fix)
268                         fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
269                 else
270                         fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
271         }
272
273         {
274                 double flt,fix,inte;
275                 fprintf(stderr,"\nDivision test...\n");
276                 fprintf(stderr,"  calculating float.....");
277                 flt=float_test.div_test();
278                 fprintf(stderr,"   float time: %f sec\n",flt);
279                 fprintf(stderr,"  calculating fixed.....");
280                 fix=fixed_test.div_test();
281                 fprintf(stderr,"   fixed time: %f sec\n",fix);
282                 fprintf(stderr,"  calculating integer...");
283                 inte=int_test.div_test();
284                 fprintf(stderr," integer time: %f sec\n",inte);
285                 if(flt>fix)
286                         fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
287                 else
288                         fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
289                 fprintf(stderr,"\n");
290         }
291
292         return error;
293 }