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 }