Go to the documentation of this file.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 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 #include <math.h>
00042 #include <assert.h>
00043 #include <stdio.h>
00044 
00045 #include "FixedPoint.h"
00046 
00047 
00048 namespace ARToolKitPlus {
00049 
00050 
00051 #ifdef _USE_GENERIC_TRIGONOMETRIC_
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 #define SIN_LUT_SIZEBITS 12                                             // maximum error for sin/cos for SIN_LUT_SIZEBITS=12: 0.000383
00060 #define SIN_LUT_SIZE (1<<SIN_LUT_SIZEBITS)
00061 #define SIN_LUT_BITS 28
00062 
00063 #define DOUBLE_PI 3.1415926535897932384626433832795
00064 #define DOUBLE_PI_OVER_2 (DOUBLE_PI/2.0)
00065 #define DOUBLE_3_PI_OVER_2 (3.0*DOUBLE_PI/2.0)
00066 #define DOUBLE_2_PI (2.0*DOUBLE_PI)
00067 #define DOUBLE_2_OVER_PI (2.0/DOUBLE_PI)
00068 
00069 #define FIXED28_PI FIXED_Float_To_Fixed_n(DOUBLE_PI, 28)
00070 #define FIXED28_PI_OVER_2 FIXED_Float_To_Fixed_n(DOUBLE_PI_OVER_2, 28)
00071 #define FIXED28_3_PI_OVER_2 FIXED_Float_To_Fixed_n(DOUBLE_3_PI_OVER_2, 28)
00072 #define FIXED28_2_PI FIXED_Float_To_Fixed_n(DOUBLE_2_PI, 28)
00073 #define FIXED28_2_OVER_PI FIXED_Float_To_Fixed_n(DOUBLE_2_OVER_PI, 28)
00074 
00075 
00076 static I32 *sinLUT_28 = 0;
00077 
00078 
00079 static I32*
00080 createSinLUT(int nSize, int nBits)
00081 {
00082         I32* lut = new I32[nSize];
00083 
00084         for(int i=0; i<nSize; i++)
00085         {
00086                 double phi = i*DOUBLE_PI_OVER_2/nSize;
00087                 double sinPhi = sin(phi);
00088 
00089                 I32 sinPhiFixed = FIXED_Float_To_Fixed_n(sinPhi, nBits);
00090                 lut[i] = sinPhiFixed;
00091         }
00092 
00093         return lut;
00094 }
00095 
00096 
00097 inline void
00098 Fixed28_SinCos(I32 phi, I32 &sin, I32 &cos)
00099 {
00100         I32 quadrant, i;
00101         bool negative = false;
00102 
00103         if(phi < 0)
00104         {
00105                 negative = true;
00106                 phi = -phi;
00107         }
00108 
00109         phi %= FIXED28_2_PI;                            
00110 
00111         if(phi<FIXED28_PI_OVER_2)
00112                 quadrant = 0;
00113         else if(phi<FIXED28_PI)
00114         {
00115                 quadrant = 1;
00116                 phi=FIXED28_PI-phi;
00117         }
00118         else if(phi<FIXED28_3_PI_OVER_2)
00119         {
00120                 quadrant = 2;
00121                 phi=phi-FIXED28_PI;
00122         }
00123         else
00124         {
00125                 quadrant = 3;
00126                 phi=FIXED28_2_PI-phi;
00127         }
00128 
00129         
00130         FIXED_MUL2(phi, FIXED28_2_OVER_PI, i, SIN_LUT_BITS);
00131         i>>=(SIN_LUT_BITS-SIN_LUT_SIZEBITS);
00132 
00133         assert(i<SIN_LUT_SIZE);
00134 
00135         sin = sinLUT_28[i];
00136         cos = sinLUT_28[SIN_LUT_SIZE-1-i];
00137 
00138         switch(quadrant)
00139         {
00140         case 0:
00141                 break;
00142         case 1:
00143                 cos=-cos;
00144                 break;
00145         case 2:
00146                 sin=-sin;
00147                 cos=-cos;
00148                 break;
00149         case 3:
00150                 sin=-sin;
00151                 break;  
00152         }
00153 
00154         if(negative)
00155                 sin = -sin;
00156 }
00157 
00158 
00159 void
00160 checkPrecisionSinCos()
00161 {
00162         double maxErrorSin=0.0, maxErrorCos=0.0;
00163 
00164         for(double phi=-5.0; phi<5.0; phi+=0.0001)
00165         {
00166                 I32 fixedPhi = FIXED_Float_To_Fixed_n(phi, SIN_LUT_BITS);
00167                 I32 fixedSin,fixedCos;
00168 
00169                 Fixed28_SinCos(fixedPhi, fixedSin,fixedCos);
00170 
00171                 double  doubleSin=sin(phi),doubleCos=cos(phi);
00172                 double  doubleSinF=FIXED_Fixed_n_To_Float(fixedSin, SIN_LUT_BITS),
00173                                 doubleCosF=FIXED_Fixed_n_To_Float(fixedCos, SIN_LUT_BITS);
00174 
00175                 double  diffSin = fabs(doubleSin-doubleSinF),
00176                                 diffCos = fabs(doubleCos-doubleCosF);
00177 
00178                 if(diffSin>maxErrorSin)
00179                         maxErrorSin=diffSin;
00180 
00181                 if(diffCos>maxErrorCos)
00182                         maxErrorCos=diffCos;
00183         }
00184 
00185         printf("Maximum error for sin() and cos(): %f  %f\n", (float)maxErrorSin, (float)maxErrorCos);
00186 }
00187 
00188 
00189 void
00190 Fixed28_Init()
00191 {
00192         if(!sinLUT_28)
00193                 sinLUT_28 = createSinLUT(SIN_LUT_SIZE, SIN_LUT_BITS);
00194 }
00195 
00196 
00197 void
00198 Fixed28_Deinit()
00199 {
00200         delete sinLUT_28;
00201 }
00202 
00203 
00204 
00205 #endif //_USE_GENERIC_TRIGONOMETRIC_
00206 
00207 
00208 }