FixedPoint.cpp
Go to the documentation of this file.
00001 /* ========================================================================
00002 * PROJECT: ARToolKitPlus
00003 * ========================================================================
00004 * This work is based on the original ARToolKit developed by
00005 *   Hirokazu Kato
00006 *   Mark Billinghurst
00007 *   HITLab, University of Washington, Seattle
00008 * http://www.hitl.washington.edu/artoolkit/
00009 *
00010 * Copyright of the derived and new portions of this work
00011 *     (C) 2006 Graz University of Technology
00012 *
00013 * This framework is free software; you can redistribute it and/or modify
00014 * it under the terms of the GNU General Public License as published by
00015 * the Free Software Foundation; either version 2 of the License, or
00016 * (at your option) any later version.
00017 *
00018 * This framework is distributed in the hope that it will be useful,
00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 * GNU General Public License for more details.
00022 *
00023 * You should have received a copy of the GNU General Public License
00024 * along with this framework; if not, write to the Free Software
00025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 *
00027 * For further information please contact 
00028 *   Dieter Schmalstieg
00029 *   <schmalstieg@icg.tu-graz.ac.at>
00030 *   Graz University of Technology, 
00031 *   Institut for Computer Graphics and Vision,
00032 *   Inffeldgasse 16a, 8010 Graz, Austria.
00033 * ========================================================================
00034 ** @author   Daniel Wagner
00035 *
00036 * $Id$
00037 * @file
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 // Select LUT size wisely: the number of bits chosen
00055 // for SIN_LUT_SIZEBITS will quite closely resemble 
00056 // the number of correct bits look-ups will have...
00057 // Memory footprint: 4*(2<<SIN_LUT_SIZEBITS) bytes
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;                            // modulo clamps to range 0 to 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         // scale from [0..1<<28] to [0..SIN_LUT_SIZE-1]
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 }  // namespace ARToolKitPlus


v4r_artoolkitplus
Author(s): Markus Bader
autogenerated on Wed Aug 26 2015 16:41:52