00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00032 #include "common.h"
00033 #include "test/test.h"
00034 #include "../fix.h"
00035
00036 #include <stdio.h>
00037 #include <math.h>
00038 #include <malloc.h>
00039
00040
00041
00042
00043
00044
00045
00046 #define PI (double)3.1415926535897932384626433832795
00047 #define SIN(angle) ((double)65536.0*sin((double)angle*PI*(double)2.0/(double)65536.0))
00048
00049 static void TestSin()
00050 {
00051 for(int value=-0x10000; value<=0x10000; value++)
00052 {
00053 int n = Fix::Sin(value);
00054 double ref = SIN(value);
00055 double error = (double)n-ref;
00056 TEST(error>=-0.56 && error<=0.56);
00057 }
00058 }
00059
00060
00061 #define COS(angle) ((double)65536.0*cos((double)angle*PI*(double)2.0/(double)65536.0))
00062
00063 static void TestCos()
00064 {
00065 for(int value=-0x10000; value<=0x10000; value++)
00066 {
00067 int n = Fix::Cos(value);
00068 double ref = COS(value);
00069 double error = (double)n-ref;
00070 TEST(error>=-0.56 && error<=0.56);
00071 }
00072 }
00073
00074
00075 #define ASIN(value) ((double)65536.0/(PI*(double)2.0)*asin((double)value/(double)65536.0))
00076
00077 static void TestASin()
00078 {
00079 int n;
00080 for(int value=-0x10000; value<=0x10000; value++)
00081 {
00082 n = Fix::ASin(value);
00083 double ref = ASIN(value);
00084 double error = (double)n-ref;
00085 TEST(error>=-0.56 && error<=0.56);
00086 }
00087
00088 n = Fix::ASin(-0x10001);
00089 TEST(n==-0x4000);
00090 n = Fix::ASin(-0x10010);
00091 TEST(n==-0x4000);
00092 n = Fix::ASin(0x80000000);
00093 TEST(n==-0x4000);
00094
00095 n = Fix::ASin(0x10001);
00096 TEST(n==0x4000);
00097 n = Fix::ASin(0x10010);
00098 TEST(n==0x4000);
00099 n = Fix::ASin(0x7fffffff);
00100 TEST(n==0x4000);
00101 }
00102
00103
00104 #define ACOS(value) ((double)65536.0/(PI*(double)2.0)*acos((double)value/(double)65536.0))
00105
00106 static void TestACos()
00107 {
00108 int n;
00109 for(int value=-0x10000; value<=0x10000; value++)
00110 {
00111 n = Fix::ACos(value);
00112 double error = (double)n-ACOS(value);
00113 TEST(error>=-0.56 && error<=0.56);
00114 }
00115
00116 n = Fix::ACos(-0x10001);
00117 TEST(n==0x8000);
00118 n = Fix::ACos(-0x10010);
00119 TEST(n==0x8000);
00120 n = Fix::ACos(0x80000000);
00121 TEST(n==0x8000);
00122
00123 n = Fix::ACos(0x10001);
00124 TEST(n==0);
00125 n = Fix::ACos(0x10010);
00126 TEST(n==0);
00127 n = Fix::ACos(0x7fffffff);
00128 TEST(n==0);
00129 }
00130
00131
00132 static inline uint32_t Random(uint32_t& seed)
00133 {
00134 seed = seed*69069+1;
00135 return seed;
00136 }
00137 #define RANDOM Random(seed)
00138
00139
00140 static inline void AddCheck(int a,int b)
00141 {
00142 int n = Fix::Add(a,b);
00143 double ref = ((double)a+(double)b);
00144 if(ref>=32768.0*65536.0)
00145 ref = 32768.0*65536.0-1;
00146 else if(ref<-32768.0*65536.0)
00147 ref = -32768.0*65536.0;
00148 double error = (double)n-ref;
00149 TEST(error>=-0.5 && error<=0.5);
00150 }
00151
00152
00153 static void TestAdd()
00154 {
00155 uint32_t seed = 1;
00156 int i;
00157 for(i=0x100000; i>0; i--)
00158 AddCheck(RANDOM,RANDOM);
00159 }
00160
00161
00162 static inline void SubCheck(int a,int b)
00163 {
00164 int n = Fix::Sub(a,b);
00165 double ref = ((double)a-(double)b);
00166 if(ref>=32768.0*65536.0)
00167 ref = 32768.0*65536.0-1;
00168 else if(ref<-32768.0*65536.0)
00169 ref = -32768.0*65536.0;
00170 double error = (double)n-ref;
00171 TEST(error>=-0.5 && error<=0.5);
00172 }
00173
00174
00175 static void TestSub()
00176 {
00177 uint32_t seed = 1;
00178 int i;
00179 for(i=0x100000; i>0; i--)
00180 AddCheck(RANDOM,RANDOM);
00181 }
00182
00183
00184 static inline void MulCheck(int a,int b)
00185 {
00186 int n = Fix::Mul(a,b);
00187 double ref = ((double)a*(double)b/65536.0);
00188 if(ref>=32768.0*65536.0)
00189 ref = 32768.0*65536.0-1;
00190 else if(ref<-32768.0*65536.0)
00191 ref = -32768.0*65536.0;
00192 double error = (double)n-ref;
00193 TEST(error>=-0.5 && error<=0.5);
00194 }
00195
00196
00197 static void TestMul()
00198 {
00199 uint32_t seed = 1;
00200 int i;
00201 for(i=0x100000; i>0; i--)
00202 MulCheck(RANDOM,RANDOM);
00203 for(i=-0x10000; i<=0x10000; i++)
00204 {
00205 for(int n=10; n>0; n--)
00206 {
00207 MulCheck(i,RANDOM);
00208 MulCheck(RANDOM,i);
00209 }
00210 }
00211 for(i=-0x7fff0000; i<=0x7fffffff-0x10000; i+=0x10000)
00212 {
00213 for(int n=10; n>0; n--)
00214 {
00215 MulCheck(i,RANDOM);
00216 MulCheck(RANDOM,i);
00217 }
00218 }
00219 for(i=-0x7fff8000; i<=0x7fffffff-0x10000; i+=0x10000)
00220 {
00221 for(int n=10; n>0; n--)
00222 {
00223 MulCheck(i,RANDOM);
00224 MulCheck(RANDOM,i);
00225 }
00226 }
00227 for(i=-0x7fff8001; i<=0x7fffffff-0x10000; i+=0x10000)
00228 {
00229 for(int n=10; n>0; n--)
00230 {
00231 MulCheck(i,RANDOM);
00232 MulCheck(RANDOM,i);
00233 }
00234 }
00235 for(i=-0x7fff7fff; i<=0x7fffffff-0x10000; i+=0x10000)
00236 {
00237 for(int n=10; n>0; n--)
00238 {
00239 MulCheck(i,RANDOM);
00240 MulCheck(RANDOM,i);
00241 }
00242 }
00243 for(i=-0x7fff0001; i<=0x7fffffff-0x10000; i+=0x10000)
00244 {
00245 for(int n=10; n>0; n--)
00246 {
00247 MulCheck(i,RANDOM);
00248 MulCheck(RANDOM,i);
00249 }
00250 }
00251 }
00252
00253
00254 static inline void MulNSCheck(int a,int b)
00255 {
00256 int n = Fix::MulNS(a,b);
00257 double ref = ((double)a*(double)b/65536.0);
00258 if(ref>=32768.0*65536.0)
00259 return;
00260 else if(ref<-32768.0*65536.0)
00261 return;
00262 double error = (double)n-ref;
00263 TEST(error>=-0.5 && error<=0.5);
00264 }
00265
00266
00267 static void TestMulNS()
00268 {
00269 uint32_t seed = 1;
00270 int i;
00271 for(i=0x100000; i>0; i--)
00272 MulNSCheck(RANDOM,RANDOM);
00273 for(i=-0x10000; i<=0x10000; i++)
00274 {
00275 for(int n=10; n>0; n--)
00276 {
00277 MulNSCheck(i,RANDOM);
00278 MulNSCheck(RANDOM,i);
00279 }
00280 }
00281 for(i=-0x7fff0000; i<=0x7fffffff-0x10000; i+=0x10000)
00282 {
00283 for(int n=10; n>0; n--)
00284 {
00285 MulNSCheck(i,RANDOM);
00286 MulNSCheck(RANDOM,i);
00287 }
00288 }
00289 for(i=-0x7fff8000; i<=0x7fffffff-0x10000; i+=0x10000)
00290 {
00291 for(int n=10; n>0; n--)
00292 {
00293 MulNSCheck(i,RANDOM);
00294 MulNSCheck(RANDOM,i);
00295 }
00296 }
00297 for(i=-0x7fff8001; i<=0x7fffffff-0x10000; i+=0x10000)
00298 {
00299 for(int n=10; n>0; n--)
00300 {
00301 MulNSCheck(i,RANDOM);
00302 MulNSCheck(RANDOM,i);
00303 }
00304 }
00305 for(i=-0x7fff7fff; i<=0x7fffffff-0x10000; i+=0x10000)
00306 {
00307 for(int n=10; n>0; n--)
00308 {
00309 MulNSCheck(i,RANDOM);
00310 MulNSCheck(RANDOM,i);
00311 }
00312 }
00313 for(i=-0x7fff0001; i<=0x7fffffff-0x10000; i+=0x10000)
00314 {
00315 for(int n=10; n>0; n--)
00316 {
00317 MulNSCheck(i,RANDOM);
00318 MulNSCheck(RANDOM,i);
00319 }
00320 }
00321 }
00322
00323
00324 static inline void DivCheck(int a,int b)
00325 {
00326 int n = Fix::Div(a,b);
00327 double ref = ((double)a*65536.0/(double)b);
00328 if(ref>=32768.0*65536.0)
00329 ref = 32768.0*65536.0-1;
00330 else if(ref<-32768.0*65536.0)
00331 ref = -32768.0*65536.0;
00332 double error = (double)n-ref;
00333 TEST(error>=-1 && error<=1);
00334 }
00335
00336
00337 static void TestDiv()
00338 {
00339 Fix::Div(0xf1b231d1,0xffff1b24);
00340 uint32_t seed = 1;
00341 int i;
00342 for(i=0x100000; i>0; i--)
00343 DivCheck(RANDOM,RANDOM);
00344 for(i=-0x10000; i<=0x10000; i++)
00345 {
00346 for(int n=10; n>0; n--)
00347 {
00348 DivCheck(i,RANDOM);
00349 DivCheck(RANDOM,i);
00350 }
00351 }
00352 for(i=(int)-0x80000000; i<=0x7fffffff-0x10000; i+=0x10000)
00353 {
00354 for(int n=10; n>0; n--)
00355 {
00356 DivCheck(i,RANDOM);
00357 DivCheck(RANDOM,i);
00358 }
00359 }
00360 for(i=-0x7fff8000; i<=0x7fffffff-0x10000; i+=0x10000)
00361 {
00362 for(int n=10; n>0; n--)
00363 {
00364 DivCheck(i,RANDOM);
00365 DivCheck(RANDOM,i);
00366 }
00367 }
00368 for(i=-0x7fff8001; i<=0x7fffffff-0x10000; i+=0x10000)
00369 {
00370 for(int n=10; n>0; n--)
00371 {
00372 DivCheck(i,RANDOM);
00373 DivCheck(RANDOM,i);
00374 }
00375 }
00376 for(i=-0x7fff7fff; i<=0x7fffffff-0x10000; i+=0x10000)
00377 {
00378 for(int n=10; n>0; n--)
00379 {
00380 DivCheck(i,RANDOM);
00381 DivCheck(RANDOM,i);
00382 }
00383 }
00384 for(i=-0x7fff0001; i<=0x7fffffff-0x10000; i+=0x10000)
00385 {
00386 for(int n=10; n>0; n--)
00387 {
00388 DivCheck(i,RANDOM);
00389 DivCheck(RANDOM,i);
00390 }
00391 }
00392 }
00393
00394
00395 static inline void SqrtCheck(unsigned a)
00396 {
00397 int n = Fix::Sqrt(a);
00398 double ref = pow((double)a/(double)65536.0,(double)0.5)*(double)65536.0;
00399 if(ref>=65536.0*65536.0)
00400 ref = 65536.0*65536.0-1;
00401 double error = (double)n-ref;
00402 TEST(error>=-0.5 && error<=0.5);
00403 }
00404
00405
00406 static void TestSqrt()
00407 {
00408 uint32_t seed = 1;
00409 int i;
00410 for(i=0x100000; i>0; i--)
00411 SqrtCheck(RANDOM);
00412 }
00413
00414
00415 #define E ((double)2.7182818284590452353602874713527)
00416 #define DOUBLE_LOG2(value) ((double)65536.0*log((double)value/(double)65536.0)/log((double)2.0))
00417
00418 static inline void Log2Check(unsigned a)
00419 {
00420 int n = Fix::Log2(a);
00421 double ref = DOUBLE_LOG2(a);
00422 if(ref<-32768.0*65536.0)
00423 ref = -32768.0*65536.0;
00424 double error = (double)n-ref;
00425 TEST(error>=-0.55 && error<=0.55);
00426 }
00427
00428
00429 static void TestLog2()
00430 {
00431 uint32_t seed = 1;
00432 int i;
00433 for(i=0x100000; i>0; i--)
00434 Log2Check(RANDOM);
00435 for(i=0; i<32; i++)
00436 Log2Check(1<<i);
00437 Log2Check(0);
00438 }
00439
00440
00441
00442 #define EXP2(value) ((double)65536.0*pow((double)2,(double)value/(double)65536.0))
00443
00444 static void TestExp2()
00445 {
00446 for(int a=-17*0x10000; a<=16*0x10000; a++)
00447 {
00448 unsigned n = Fix::Exp2(a);
00449 double ref = EXP2(a);
00450 if(ref>=65536.0*65536.0)
00451 ref = 65536.0*65536.0-1;
00452 double error = (double)n-ref;
00453 TEST(error>=-0.75 && error<=0.75);
00454 }
00455 }
00456
00457
00458 #define TAN(angle) ((double)65536.0*tan((double)angle*PI*(double)2.0/(double)65536.0))
00459
00460 static void TestTan()
00461 {
00462 for(int value=-0x10000; value<=0x10000; value++)
00463 {
00464 int n = Fix::Tan(value);
00465 double ref=TAN(value);
00466 if(ref>=(double)32768*(double)65536)
00467 ref = (double)32768*(double)65536-(double)1;
00468 if(ref<(double)-32768*(double)65536)
00469 ref = (double)-32768*(double)65536;
00470 double error = (double)n-ref;
00471 TEST(error>=-0.66 && error<=0.66);
00472 }
00473 }
00474
00475
00476 #define ATAN(value) ((double)65536.0/PI/(double)2.0*atan((double)value/(double)65536.0))
00477
00478 static void TestATan()
00479 {
00480 for(int value=-0x10000; value<=0x10000*0x10; value++)
00481 {
00482 int n = Fix::ATan(value);
00483 TEST(n!=0x4000);
00484 double ref = ATAN(value);
00485 double error = (double)n-ref;
00486 TEST(error>=-0.59 && error<=0.59);
00487 }
00488 }
00489
00490
00491 static void TestRandom()
00492 {
00493 uint32_t seed = 0;
00494 fix first = Fix::Random(seed);
00495 fix n;
00496 uint32_t i=0xffffffffu;
00497 do
00498 {
00499 TEST((n=Fix::Random(seed))!=first);
00500 }
00501 while(--i);
00502 TEST((n=Fix::Random(seed))==first);
00503
00504 for(i=0; i<32; i++)
00505 {
00506 ufix range = 1<<i;
00507 for(int j=1<<20; j>=0; j--)
00508 {
00509 TEST(Fix::Random(seed,range)<range);
00510 }
00511 }
00512 }
00513
00514
00515
00516
00517
00518
00519
00520 void TestFix()
00521 {
00522 TestAdd();
00523 TestSub();
00524 TestMul();
00525 TestMulNS();
00526 TestDiv();
00527 TestSqrt();
00528 TestLog2();
00529 TestExp2();
00530 TestSin();
00531 TestCos();
00532 TestTan();
00533 TestASin();
00534 TestACos();
00535 TestATan();
00536 TestRandom();
00537 }