FixedPoint.cpp
Go to the documentation of this file.
1 /* ========================================================================
2 * PROJECT: ARToolKitPlus
3 * ========================================================================
4 * This work is based on the original ARToolKit developed by
5 * Hirokazu Kato
6 * Mark Billinghurst
7 * HITLab, University of Washington, Seattle
8 * http://www.hitl.washington.edu/artoolkit/
9 *
10 * Copyright of the derived and new portions of this work
11 * (C) 2006 Graz University of Technology
12 *
13 * This framework is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This framework is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this framework; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * For further information please contact
28 * Dieter Schmalstieg
29 * <schmalstieg@icg.tu-graz.ac.at>
30 * Graz University of Technology,
31 * Institut for Computer Graphics and Vision,
32 * Inffeldgasse 16a, 8010 Graz, Austria.
33 * ========================================================================
34 ** @author Daniel Wagner
35 *
36 * $Id$
37 * @file
38  * ======================================================================== */
39 
40 
41 #include <math.h>
42 #include <assert.h>
43 #include <stdio.h>
44 
45 #include "FixedPoint.h"
46 
47 
48 namespace ARToolKitPlus {
49 
50 
51 #ifdef _USE_GENERIC_TRIGONOMETRIC_
52 
53 
54 // Select LUT size wisely: the number of bits chosen
55 // for SIN_LUT_SIZEBITS will quite closely resemble
56 // the number of correct bits look-ups will have...
57 // Memory footprint: 4*(2<<SIN_LUT_SIZEBITS) bytes
58 //
59 #define SIN_LUT_SIZEBITS 12 // maximum error for sin/cos for SIN_LUT_SIZEBITS=12: 0.000383
60 #define SIN_LUT_SIZE (1<<SIN_LUT_SIZEBITS)
61 #define SIN_LUT_BITS 28
62 
63 #define DOUBLE_PI 3.1415926535897932384626433832795
64 #define DOUBLE_PI_OVER_2 (DOUBLE_PI/2.0)
65 #define DOUBLE_3_PI_OVER_2 (3.0*DOUBLE_PI/2.0)
66 #define DOUBLE_2_PI (2.0*DOUBLE_PI)
67 #define DOUBLE_2_OVER_PI (2.0/DOUBLE_PI)
68 
69 #define FIXED28_PI FIXED_Float_To_Fixed_n(DOUBLE_PI, 28)
70 #define FIXED28_PI_OVER_2 FIXED_Float_To_Fixed_n(DOUBLE_PI_OVER_2, 28)
71 #define FIXED28_3_PI_OVER_2 FIXED_Float_To_Fixed_n(DOUBLE_3_PI_OVER_2, 28)
72 #define FIXED28_2_PI FIXED_Float_To_Fixed_n(DOUBLE_2_PI, 28)
73 #define FIXED28_2_OVER_PI FIXED_Float_To_Fixed_n(DOUBLE_2_OVER_PI, 28)
74 
75 
76 static I32 *sinLUT_28 = 0;
77 
78 
79 static I32*
80 createSinLUT(int nSize, int nBits)
81 {
82  I32* lut = new I32[nSize];
83 
84  for(int i=0; i<nSize; i++)
85  {
86  double phi = i*DOUBLE_PI_OVER_2/nSize;
87  double sinPhi = sin(phi);
88 
89  I32 sinPhiFixed = FIXED_Float_To_Fixed_n(sinPhi, nBits);
90  lut[i] = sinPhiFixed;
91  }
92 
93  return lut;
94 }
95 
96 
97 inline void
98 Fixed28_SinCos(I32 phi, I32 &sin, I32 &cos)
99 {
100  I32 quadrant, i;
101  bool negative = false;
102 
103  if(phi < 0)
104  {
105  negative = true;
106  phi = -phi;
107  }
108 
109  phi %= FIXED28_2_PI; // modulo clamps to range 0 to 2*Pi
110 
111  if(phi<FIXED28_PI_OVER_2)
112  quadrant = 0;
113  else if(phi<FIXED28_PI)
114  {
115  quadrant = 1;
116  phi=FIXED28_PI-phi;
117  }
118  else if(phi<FIXED28_3_PI_OVER_2)
119  {
120  quadrant = 2;
121  phi=phi-FIXED28_PI;
122  }
123  else
124  {
125  quadrant = 3;
126  phi=FIXED28_2_PI-phi;
127  }
128 
129  // scale from [0..1<<28] to [0..SIN_LUT_SIZE-1]
130  FIXED_MUL2(phi, FIXED28_2_OVER_PI, i, SIN_LUT_BITS);
131  i>>=(SIN_LUT_BITS-SIN_LUT_SIZEBITS);
132 
133  assert(i<SIN_LUT_SIZE);
134 
135  sin = sinLUT_28[i];
136  cos = sinLUT_28[SIN_LUT_SIZE-1-i];
137 
138  switch(quadrant)
139  {
140  case 0:
141  break;
142  case 1:
143  cos=-cos;
144  break;
145  case 2:
146  sin=-sin;
147  cos=-cos;
148  break;
149  case 3:
150  sin=-sin;
151  break;
152  }
153 
154  if(negative)
155  sin = -sin;
156 }
157 
158 
159 void
160 checkPrecisionSinCos()
161 {
162  double maxErrorSin=0.0, maxErrorCos=0.0;
163 
164  for(double phi=-5.0; phi<5.0; phi+=0.0001)
165  {
166  I32 fixedPhi = FIXED_Float_To_Fixed_n(phi, SIN_LUT_BITS);
167  I32 fixedSin,fixedCos;
168 
169  Fixed28_SinCos(fixedPhi, fixedSin,fixedCos);
170 
171  double doubleSin=sin(phi),doubleCos=cos(phi);
172  double doubleSinF=FIXED_Fixed_n_To_Float(fixedSin, SIN_LUT_BITS),
173  doubleCosF=FIXED_Fixed_n_To_Float(fixedCos, SIN_LUT_BITS);
174 
175  double diffSin = fabs(doubleSin-doubleSinF),
176  diffCos = fabs(doubleCos-doubleCosF);
177 
178  if(diffSin>maxErrorSin)
179  maxErrorSin=diffSin;
180 
181  if(diffCos>maxErrorCos)
182  maxErrorCos=diffCos;
183  }
184 
185  printf("Maximum error for sin() and cos(): %f %f\n", (float)maxErrorSin, (float)maxErrorCos);
186 }
187 
188 
189 void
190 Fixed28_Init()
191 {
192  if(!sinLUT_28)
193  sinLUT_28 = createSinLUT(SIN_LUT_SIZE, SIN_LUT_BITS);
194 }
195 
196 
197 void
198 Fixed28_Deinit()
199 {
200  delete sinLUT_28;
201 }
202 
203 
204 
205 #endif //_USE_GENERIC_TRIGONOMETRIC_
206 
207 
208 } // namespace ARToolKitPlus
#define FIXED_Fixed_n_To_Float(x, n)
Definition: FixedPoint.h:49
This file should only be compiled when using ARToolKitPlus as a DLL.
Definition: ar.h:60
#define FIXED_Float_To_Fixed_n(x, n)
Definition: FixedPoint.h:48


tuw_artoolkitplus
Author(s): Markus Bader
autogenerated on Sun Sep 4 2016 03:24:33