fixtest.cpp

Go to the documentation of this file.
00001 /*
00002 This program is distributed under the terms of the 'MIT license'. The text
00003 of this licence follows...
00004 
00005 Copyright (c) 2004-2009 J.D.Medhurst (a.k.a. Tixy)
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023 THE SOFTWARE.
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 // Individual test functions
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 // Top level test function
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     }

Generated by  doxygen 1.6.1