Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

FixPoint.i

Go to the documentation of this file.
00001 /*
00002  *  FixPoint.i
00003  *
00004  *  Provides fixpoint arithmetic (for use in SID.cpp)
00005  *  You need to define FIXPOINT_PREC (number of fractional bits) and
00006  *  ldSINTAB (ld of the size of the sinus table) as well M_PI
00007  *  _before_ including this file.
00008  *  Requires at least 32bit ints!
00009  *  (C) 1997 Andreas Dehmel
00010  */
00011 
00012 
00013 #define FIXPOINT_BITS   32
00014 // Sign-bit
00015 #define FIXPOINT_SIGN   (1<<(FIXPOINT_BITS-1))
00016 
00017 
00018 /*
00019  *  Elementary functions for the FixPoint class
00020  */
00021 
00022 // Multiplies two fixpoint numbers, result is a fixpoint number.
00023 static inline int fixmult(int x, int y)
00024 {
00025   register unsigned int a,b;
00026   register bool sign;
00027 
00028   sign = (x ^ y) < 0;
00029   if (x < 0) {x = -x;}
00030   if (y < 0) {y = -y;}
00031   // a, b : integer part; x, y : fractional part. All unsigned now (for shift right)!!!
00032   a = (((unsigned int)x) >> FIXPOINT_PREC); x &= ~(a << FIXPOINT_PREC);
00033   b = (((unsigned int)y) >> FIXPOINT_PREC); y &= ~(b << FIXPOINT_PREC);
00034   x = ((a*b) << FIXPOINT_PREC) + (a*y + b*x) +
00035       ((unsigned int)((x*y) + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC);
00036 #ifdef FIXPOINT_SIGN
00037   if (x < 0) {x ^= FIXPOINT_SIGN;}
00038 #endif
00039   if (sign) {x = -x;}
00040   return(x);
00041 }
00042 
00043 
00044 // Multiplies a fixpoint number with an integer, result is a 32 bit (!) integer in
00045 // contrast to using the standard member-functions which can provide only (32-FIXPOINT_PREC)
00046 // valid bits.
00047 static inline int intmult(int x, int y) // x is fixpoint, y integer
00048 {
00049   register unsigned int i,j;
00050   register bool sign;
00051 
00052   sign = (x ^ y) < 0;
00053   if (x < 0) {x = -x;}
00054   if (y < 0) {y = -y;}
00055   i = (((unsigned int)x) >> 16); x &= ~(i << 16);       // split both into 16.16 parts
00056   j = (((unsigned int)y) >> 16); y &= ~(j << 16);
00057 #if FIXPOINT_PREC <= 16
00058   // This '32' is independent of the number of bits used, it's due to the 16 bit shift
00059   i = ((i*j) << (32 - FIXPOINT_PREC)) + ((i*y + j*x) << (16 - FIXPOINT_PREC)) +
00060       ((unsigned int)(x*y + (1 << (FIXPOINT_PREC - 1))) >> FIXPOINT_PREC);
00061 #else
00062   {
00063     register unsigned int h;
00064 
00065     h = (i*y + j*x);
00066     i = ((i*j) << (32 - FIXPOINT_PREC)) + (h >> (FIXPOINT_PREC - 16));
00067     h &= ((1 << (FIXPOINT_PREC - 16)) - 1); x *= y;
00068     i += (x >> FIXPOINT_PREC); x &= ((1 << FIXPOINT_PREC) - 1);
00069     i += (((h + (x >> 16)) + (1 << (FIXPOINT_PREC - 17))) >> (FIXPOINT_PREC - 16));
00070   }
00071 #endif
00072 #ifdef FIXPOINT_SIGN
00073   if (i < 0) {i ^= FIXPOINT_SIGN;}
00074 #endif
00075   if (sign) {i = -i;}
00076   return(i);
00077 }
00078 
00079 
00080 // Computes the product of a fixpoint number with itself.
00081 static inline int fixsquare(int x)
00082 {
00083   register unsigned int a;
00084 
00085   if (x < 0) {x = -x;}
00086   a = (((unsigned int)x) >> FIXPOINT_PREC); x &= ~(a << FIXPOINT_PREC);
00087   x = ((a*a) << FIXPOINT_PREC) + ((a*x) << 1) +
00088       ((unsigned int)((x*x) + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC);
00089 #ifdef FIXPOINT_SIGN
00090   if (x < 0) {x ^= FIXPOINT_SIGN;}
00091 #endif
00092   return(x);
00093 }
00094 
00095 
00096 // Computes the square root of a fixpoint number.
00097 static inline int fixsqrt(int x)
00098 {
00099   register int test, step;
00100 
00101   if (x < 0) return(-1); if (x == 0) return(0);
00102   step = (x <= (1<<FIXPOINT_PREC)) ? (1<<FIXPOINT_PREC) : (1<<((FIXPOINT_BITS - 2 + FIXPOINT_PREC)>>1));
00103   test = 0;
00104   while (step != 0)
00105   {
00106     register int h;
00107 
00108     h = fixsquare(test + step);
00109     if (h <= x) {test += step;}
00110     if (h == x) break;
00111     step >>= 1;
00112   }
00113   return(test);
00114 }
00115 
00116 
00117 // Divides a fixpoint number by another fixpoint number, yielding a fixpoint result.
00118 static inline int fixdiv(int x, int y)
00119 {
00120   register int res, mask;
00121   register bool sign;
00122 
00123   sign = (x ^ y) < 0;
00124   if (x < 0) {x = -x;}
00125   if (y < 0) {y = -y;}
00126   mask = (1<<FIXPOINT_PREC); res = 0;
00127   while (x > y) {y <<= 1; mask <<= 1;}
00128   while (mask != 0)
00129   {
00130     if (x >= y) {res |= mask; x -= y;}
00131     mask >>= 1; y >>= 1;
00132   }
00133 #ifdef FIXPOINT_SIGN
00134   if (res < 0) {res ^= FIXPOINT_SIGN;}
00135 #endif
00136   if (sign) {res = -res;}
00137   return(res);
00138 }
00139 
00140 
00141 
00142 
00143 
00144 /*
00145  *  The C++ Fixpoint class. By no means exhaustive...
00146  *  Since it contains only one int data, variables of type FixPoint can be
00147  *  passed directly rather than as a reference.
00148  */
00149 
00150 class FixPoint
00151 {
00152 private:
00153   int x;
00154 
00155 public:
00156   FixPoint(void);
00157   FixPoint(int y);
00158   ~FixPoint(void);
00159 
00160   // conversions
00161   int Value(void);
00162   int round(void);
00163   operator int(void);
00164 
00165   // unary operators
00166   FixPoint sqrt(void);
00167   FixPoint sqr(void);
00168   FixPoint abs(void);
00169   FixPoint operator+(void);
00170   FixPoint operator-(void);
00171   FixPoint operator++(void);
00172   FixPoint operator--(void);
00173 
00174   // binary operators
00175   int imul(int y);
00176   FixPoint operator=(FixPoint y);
00177   FixPoint operator=(int y);
00178   FixPoint operator+(FixPoint y);
00179   FixPoint operator+(int y);
00180   FixPoint operator-(FixPoint y);
00181   FixPoint operator-(int y);
00182   FixPoint operator/(FixPoint y);
00183   FixPoint operator/(int y);
00184   FixPoint operator*(FixPoint y);
00185   FixPoint operator*(int y);
00186   FixPoint operator+=(FixPoint y);
00187   FixPoint operator+=(int y);
00188   FixPoint operator-=(FixPoint y);
00189   FixPoint operator-=(int y);
00190   FixPoint operator*=(FixPoint y);
00191   FixPoint operator*=(int y);
00192   FixPoint operator/=(FixPoint y);
00193   FixPoint operator/=(int y);
00194   FixPoint operator<<(int y);
00195   FixPoint operator>>(int y);
00196   FixPoint operator<<=(int y);
00197   FixPoint operator>>=(int y);
00198 
00199   // conditional operators
00200   bool operator<(FixPoint y);
00201   bool operator<(int y);
00202   bool operator<=(FixPoint y);
00203   bool operator<=(int y);
00204   bool operator>(FixPoint y);
00205   bool operator>(int y);
00206   bool operator>=(FixPoint y);
00207   bool operator>=(int y);
00208   bool operator==(FixPoint y);
00209   bool operator==(int y);
00210   bool operator!=(FixPoint y);
00211   bool operator!=(int y);
00212 };
00213 
00214 
00215 /*
00216  *  int gets treated differently according to the case:
00217  *
00218  *  a) Equations (=) or condition checks (==, <, <= ...): raw int (i.e. no conversion)
00219  *  b) As an argument for an arithmetic operation: conversion to fixpoint by shifting
00220  *
00221  *  Otherwise loading meaningful values into FixPoint variables would be very awkward.
00222  */
00223 
00224 FixPoint::FixPoint(void) {x = 0;}
00225 
00226 FixPoint::FixPoint(int y) {x = y;}
00227 
00228 FixPoint::~FixPoint(void) {;}
00229 
00230 inline int FixPoint::Value(void) {return(x);}
00231 
00232 inline int FixPoint::round(void) {return((x + (1 << (FIXPOINT_PREC-1))) >> FIXPOINT_PREC);}
00233 
00234 inline FixPoint::operator int(void) {return(x);}
00235 
00236 
00237 // unary operators
00238 inline FixPoint FixPoint::sqrt(void) {return(fixsqrt(x));}
00239 
00240 inline FixPoint FixPoint::sqr(void) {return(fixsquare(x));}
00241 
00242 inline FixPoint FixPoint::abs(void) {return((x < 0) ? -x : x);}
00243 
00244 inline FixPoint FixPoint::operator+(void) {return(x);}
00245 
00246 inline FixPoint FixPoint::operator-(void) {return(-x);}
00247 
00248 inline FixPoint FixPoint::operator++(void) {x += (1 << FIXPOINT_PREC); return x;}
00249 
00250 inline FixPoint FixPoint::operator--(void) {x -= (1 << FIXPOINT_PREC); return x;}
00251 
00252 
00253 // binary operators
00254 inline int FixPoint::imul(int y) {return(intmult(x,y));}
00255 
00256 inline FixPoint FixPoint::operator=(FixPoint y) {x = y.Value(); return x;}
00257 
00258 inline FixPoint FixPoint::operator=(int y) {x = y; return x;}
00259 
00260 inline FixPoint FixPoint::operator+(FixPoint y) {return(x + y.Value());}
00261 
00262 inline FixPoint FixPoint::operator+(int y) {return(x + (y << FIXPOINT_PREC));}
00263 
00264 inline FixPoint FixPoint::operator-(FixPoint y) {return(x - y.Value());}
00265 
00266 inline FixPoint FixPoint::operator-(int y) {return(x - (y << FIXPOINT_PREC));}
00267 
00268 inline FixPoint FixPoint::operator/(FixPoint y) {return(fixdiv(x,y.Value()));}
00269 
00270 inline FixPoint FixPoint::operator/(int y) {return(x/y);}
00271 
00272 inline FixPoint FixPoint::operator*(FixPoint y) {return(fixmult(x,y.Value()));}
00273 
00274 inline FixPoint FixPoint::operator*(int y) {return(x*y);}
00275 
00276 inline FixPoint FixPoint::operator+=(FixPoint y) {x += y.Value(); return x;}
00277 
00278 inline FixPoint FixPoint::operator+=(int y) {x += (y << FIXPOINT_PREC); return x;}
00279 
00280 inline FixPoint FixPoint::operator-=(FixPoint y) {x -= y.Value(); return x;}
00281 
00282 inline FixPoint FixPoint::operator-=(int y) {x -= (y << FIXPOINT_PREC); return x;}
00283 
00284 inline FixPoint FixPoint::operator*=(FixPoint y) {x = fixmult(x,y.Value()); return x;}
00285 
00286 inline FixPoint FixPoint::operator*=(int y) {x *= y; return x;}
00287 
00288 inline FixPoint FixPoint::operator/=(FixPoint y) {x = fixdiv(x,y.Value()); return x;}
00289 
00290 inline FixPoint FixPoint::operator/=(int y) {x /= y; return x;}
00291 
00292 inline FixPoint FixPoint::operator<<(int y) {return(x << y);}
00293 
00294 inline FixPoint FixPoint::operator>>(int y) {return(x >> y);}
00295 
00296 inline FixPoint FixPoint::operator<<=(int y) {x <<= y; return x;}
00297 
00298 inline FixPoint FixPoint::operator>>=(int y) {x >>= y; return x;}
00299 
00300 
00301 // conditional operators
00302 inline bool FixPoint::operator<(FixPoint y) {return(x < y.Value());}
00303 
00304 inline bool FixPoint::operator<(int y) {return(x < y);}
00305 
00306 inline bool FixPoint::operator<=(FixPoint y) {return(x <= y.Value());}
00307 
00308 inline bool FixPoint::operator<=(int y) {return(x <= y);}
00309 
00310 inline bool FixPoint::operator>(FixPoint y) {return(x > y.Value());}
00311 
00312 inline bool FixPoint::operator>(int y) {return(x > y);}
00313 
00314 inline bool FixPoint::operator>=(FixPoint y) {return(x >= y.Value());}
00315 
00316 inline bool FixPoint::operator>=(int y) {return(x >= y);}
00317 
00318 inline bool FixPoint::operator==(FixPoint y) {return(x == y.Value());}
00319 
00320 inline bool FixPoint::operator==(int y) {return(x == y);}
00321 
00322 inline bool FixPoint::operator!=(FixPoint y) {return(x != y.Value());}
00323 
00324 inline bool FixPoint::operator!=(int y) {return(x != y);}
00325 
00326 
00327 
00328 /*
00329  *  In case the first argument is an int (i.e. member-operators not applicable):
00330  *  Not supported: things like int/FixPoint. The same difference in conversions
00331  *  applies as mentioned above.
00332  */
00333 
00334 
00335 // binary operators
00336 inline FixPoint operator+(int x, FixPoint y) {return((x << FIXPOINT_PREC) + y.Value());}
00337 
00338 inline FixPoint operator-(int x, FixPoint y) {return((x << FIXPOINT_PREC) - y.Value());}
00339 
00340 inline FixPoint operator*(int x, FixPoint y) {return(x*y.Value());}
00341 
00342 
00343 // conditional operators
00344 inline bool operator==(int x, FixPoint y) {return(x == y.Value());}
00345 
00346 inline bool operator!=(int x, FixPoint y) {return(x != y.Value());}
00347 
00348 inline bool operator<(int x, FixPoint y) {return(x < y.Value());}
00349 
00350 inline bool operator<=(int x, FixPoint y) {return(x <= y.Value());}
00351 
00352 inline bool operator>(int x, FixPoint y) {return(x > y.Value());}
00353 
00354 inline bool operator>=(int x, FixPoint y) {return(x >= y.Value());}
00355 
00356 
00357 
00358 /*
00359  *  For more convenient creation of constant fixpoint numbers from constant floats.
00360  */
00361 
00362 #define FixNo(n)        (FixPoint)((int)(n*(1<<FIXPOINT_PREC)))
00363 
00364 
00365 
00366 
00367 
00368 
00369 /*
00370  *  Stuff re. the sinus table used with fixpoint arithmetic
00371  */
00372 
00373 #ifndef __SYMBIAN32__
00374 
00376 FixPoint SinTable[(1<<ldSINTAB)];
00377 
00378 
00379 #define FIXPOINT_SIN_COS_GENERIC \
00380   if (angle >= 3*(1<<ldSINTAB)) {return(-SinTable[(1<<(ldSINTAB+2)) - angle]);}\
00381   if (angle >= 2*(1<<ldSINTAB)) {return(-SinTable[angle - 2*(1<<ldSINTAB)]);}\
00382   if (angle >= (1<<ldSINTAB)) {return(SinTable[2*(1<<ldSINTAB) - angle]);}\
00383   return(SinTable[angle]);
00384 
00385 
00386 // sin and cos: angle is fixpoint number 0 <= angle <= 2 (*PI)
00387 static inline FixPoint fixsin(FixPoint x)
00388 {
00389   int angle = x;
00390 
00391   angle = (angle >> (FIXPOINT_PREC - ldSINTAB - 1)) & ((1<<(ldSINTAB+2))-1);
00392   FIXPOINT_SIN_COS_GENERIC
00393 }
00394 
00395 
00396 static inline FixPoint fixcos(FixPoint x)
00397 {
00398   int angle = x;
00399 
00400   // cos(x) = sin(x+PI/2)
00401   angle = (angle + (1<<(FIXPOINT_PREC-1)) >> (FIXPOINT_PREC - ldSINTAB - 1)) & ((1<<(ldSINTAB+2))-1);
00402   FIXPOINT_SIN_COS_GENERIC
00403 }
00404 
00405 
00406 static inline void InitFixSinTab(void)
00407 {
00408   int i;
00409   float step;
00410 
00411   for (i=0, step=0; i<(1<<ldSINTAB); i++, step+=0.5/(1<<ldSINTAB))
00412   {
00413     SinTable[i] = FixNo(sin(M_PI * step));
00414   }
00415 }
00416 
00417 #endif // !__SYMBIAN32__

Generated on Tue Feb 8 04:07:55 2005 for E32frodo by doxygen 1.3.3