nux-0.9.48

NuxCore/Math/MathUtility.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #ifndef MATHUTILITY_H
00024 #define MATHUTILITY_H
00025 
00026 #include <cstdio>
00027 #include <cstdlib>
00028 #include <cstdarg>
00029 #include <cmath>
00030 #include <cstring>
00031 #include <ctime>
00032 
00033 #include "Constants.h"
00034 
00035 namespace nux
00036 {
00037   template<typename T> inline T Square (const T A)
00038   {
00039     return A * A;
00040   }
00041   template<typename T> inline T Clamp (const T X, const T min_value, const T max_value)
00042   {
00043     return X < min_value ? min_value : X < max_value ? X : max_value;
00044   }
00045 
00046   template<typename T> inline T ClampUp (const T X, const T min_value)
00047   {
00048     return X < min_value ? min_value : X;
00049   }
00050 
00051   template<typename T> inline T ClampDown (const T X, const T max_value)
00052   {
00053     return X > max_value ? max_value : X;
00054   }
00055 
00056   template<typename T> inline T Align (const T Ptr, int Alignment)
00057   {
00058     return (T) (((NUX_POINTER) Ptr + Alignment - 1) & ~ (Alignment - 1));
00059   }
00060 
00061   //Bitwise rotation on the left.
00062   template<typename T> inline const T Rol (const T &a, const unsigned int n = 1)
00063   {
00064     return (a << n) | (a >> ((sizeof (T) << 3) - n));
00065   }
00066   //Bitwise rotation on the right.
00067   template<typename T> inline const T Ror (const T &a, const unsigned int n = 1)
00068   {
00069     return (a >> n) | (a << ((sizeof (T) << 3) - n));
00070   }
00071 
00072   // Exchange the values of variables a and b
00073   template<typename T> inline void Swap (T &a, T &b)
00074   {
00075     const T t = a;
00076     a = b;
00077     b = t;
00078   }
00079   template<typename T> inline void Swap (T &a1, T &b1, T &a2, T &b2)
00080   {
00081     Swap (a1, b1);
00082     Swap (a2, b2);
00083   }
00084   template<typename T> inline void Swap (T &a1, T &b1, T &a2, T &b2, T &a3, T &b3)
00085   {
00086     Swap (a1, b1, a2, b2);
00087     Swap (a3, b3);
00088   }
00089   template<typename T> inline void Swap (T &a1, T &b1, T &a2, T &b2, T &a3, T &b3, T &a4, T &b4)
00090   {
00091     Swap (a1, b1, a2, b2, a3, b3);
00092     Swap (a4, b4);
00093   }
00094   template<typename T> inline void Swap (T &a1, T &b1, T &a2, T &b2, T &a3, T &b3, T &a4, T &b4, T &a5, T &b5)
00095   {
00096     Swap (a1, b1, a2, b2, a3, b3, a4, b4);
00097     Swap (a5, b5);
00098   }
00099   template<typename T> inline void Swap (T &a1, T &b1, T &a2, T &b2, T &a3, T &b3, T &a4, T &b4, T &a5, T &b5, T &a6, T &b6)
00100   {
00101     Swap (a1, b1, a2, b2, a3, b3, a4, b4, a5, b5);
00102     Swap (a6, b6);
00103   }
00104 
00106   template<typename T> inline const T Abs (const T &a)
00107   {
00108     return a >= 0 ? a : -a;
00109   }
00111   template<typename T> inline const T &Min (const T &a, const T &b)
00112   {
00113     return a <= b ? a : b;
00114   }
00116   template<typename T> inline const T &Min (const T &a, const T &b, const T &c)
00117   {
00118     return Min<T> (Min<T> (a, b), c);
00119   }
00121   template<typename T> inline const T &Min (const T &a, const T &b, const T &c, const T &d)
00122   {
00123     return Min<T> (Min<T> (Min<T> (a, b), c), d);
00124   }
00126   template<typename T> inline const T &Max (const T &a, const T &b)
00127   {
00128     return a >= b ? a : b;
00129   }
00131   template<typename T> inline const T &Max (const T &a, const T &b, const T &c)
00132   {
00133     return Max<T> (Max<T> (a, b), c);
00134   }
00136   template<typename T> inline const T &Max (const T &a, const T &b, const T &c, const T &d)
00137   {
00138     return Max<T> (Max<T> (a, b, c), d);
00139   }
00140   
00141   template<typename T> inline T Max3 (const T A, const T B, const T C)
00142   {
00143     return Max<T> (Max<T> (A, B), C);
00144   }
00145 
00146   template<typename T> inline T Min3 (const T A, const T B, const T C)
00147   {
00148     return Min<T> (Min<T> (A, B), C);
00149   }
00150   
00152   template<typename T> inline T Sign (const T &x)
00153   {
00154     return (x < 0) ? -1 : (x == 0 ? 0 : 1);
00155   }
00156 
00157 
00158   template<typename T> inline T Modulo (const T &x, const T &m)
00159   {
00160     return x - m * (T) std::floor ((double) x / m);
00161   }
00162 
00163   inline int ModuloInt (const int x, const int m)
00164   {
00165     return x >= 0 ? x % m : (x % m ? m + x % m : 0);
00166   }
00167 
00168   template<typename T> inline T MinMod (const T &a, const T &b)
00169   {
00170     return a * b <= 0 ? 0 : (a > 0 ? (a < b ? a : b) : (a < b ? b : a));
00171   }
00172 
00174 
00177   inline double Random()
00178   {
00179     return (double) std::rand() / RAND_MAX;
00180   }
00181 
00183 
00186   inline double CRandom()
00187   {
00188     return 1 - 2 * (std::rand() / RAND_MAX);
00189   }
00190 
00192 
00195   inline double RandomGaussian()
00196   {
00197     return std::sqrt (-2 * std::log ((double) (1e-10 + (1 - 2e-10) * std::rand()))) * std::cos ((double) (2 * 3.14f/*Const::pi*/*std::rand()));
00198   }
00199 
00200   inline unsigned int RandomUInt()
00201   {
00202     return std::rand();
00203   }
00204 
00205   inline unsigned int RandomUInt (unsigned int max_random)
00206   {
00207     return std::rand() % max_random;
00208   }
00209 
00210   inline t_size DiffPointer (void *Ptr0, void *Ptr1)
00211   {
00212     if ((t_size) Ptr0 >= (t_size) Ptr1) return (t_size) ((t_size) Ptr0 - (t_size) Ptr1);
00213 
00214     return (t_size) ((t_size) Ptr1 - (t_size) Ptr0);
00215   }
00216   // Dangerous to use!
00217   template<typename T> inline T SubstractPointer (void *Ptr, t_size Value)
00218   {
00219     return (T) (((t_size) Ptr) - Value);
00220   }
00221   template<typename T> inline T AddPointer (void *Ptr, t_size Value)
00222   {
00223     return (T) (((t_size) Ptr) + Value);
00224   }
00225 
00227 
00230   template<typename T> inline T RoundUp (T Value, int Alignment)
00231   {
00232     return (Value + (Alignment - 1)) & ~ (Alignment - 1);
00233   }
00234 
00236 
00239   template<typename T> inline T RoundDown (T Value, int Alignment)
00240   {
00241     return ((Value) & ~ (Alignment - 1));
00242   }
00243 
00245 
00248   template<typename T> inline bool IsAligned (T Value, int Alignment)
00249   {
00250     return (((Value) & ~ (Alignment - 1)) == 0);
00251   }
00252 
00257   inline t_u16 ReverseByteOrdering (t_u16 value)
00258   {
00259     t_u16 temp;
00260     t_u8 *src = (t_u8 *) &value;
00261     t_u8 *dest = (t_u8 *) &temp;
00262 
00263     dest[0] = src[1];
00264     dest[1] = src[0];
00265 
00266     return temp;
00267   }
00268 
00273   inline t_u32 ReverseByteOrdering (t_u32 value)
00274   {
00275     t_u32 temp;
00276     t_u8 *src = (t_u8 *) &value;
00277     t_u8 *dest = (t_u8 *) &temp;
00278 
00279     dest[0] = src[3];
00280     dest[1] = src[2];
00281     dest[2] = src[1];
00282     dest[3] = src[0];
00283 
00284     return temp;
00285   }
00286 
00291   inline t_u64 ReverseByteOrdering (t_u64 value)
00292   {
00293     t_u64 temp;
00294     t_u8 *src = (t_u8 *) &value;
00295     t_u8 *dest = (t_u8 *) &temp;
00296 
00297     dest[0] = src[7];
00298     dest[1] = src[6];
00299     dest[2] = src[5];
00300     dest[3] = src[4];
00301     dest[4] = src[3];
00302     dest[5] = src[2];
00303     dest[6] = src[1];
00304     dest[7] = src[0];
00305 
00306     return temp;
00307   }
00308 
00309   // Bit Hack
00310 
00311   // Determining if an integer is a power of 2
00312   // http://graphics.stanford.edu/~seander/bithacks.html
00313   inline bool IsPowerOf2 (unsigned int n)
00314   {
00315     // The algorithm does not 0 consider 0 a power of two. (this is right)
00316     return ! (n & (n - 1)) && n;
00317   }
00318 
00319   // Compute the next highest power of 2 of 32-bit v
00320   // http://graphics.stanford.edu/~seander/bithacks.html
00321   inline unsigned int NextPowerOfTwo (unsigned int x)
00322   {
00323     x = x - 1;
00324     x = x | (x >> 1);
00325     x = x | (x >> 2);
00326     x = x | (x >> 4);
00327     x = x | (x >> 8);
00328     x = x | (x >> 16);
00329     return x + 1;
00330   }
00331 
00332   inline unsigned int GetLowerPowerOfTwoExponent (unsigned int x)
00333   {
00334     int count = 0;
00335 
00336     while (x > 1)
00337     {
00338       x >>= 1;
00339       count++;
00340     }
00341 
00342     return count;
00343   }
00344 
00345   inline unsigned int PowerOfTwo (int i)
00346   {
00347     int e = 0;
00348     unsigned int power = 1;
00349 
00350     while (e < i)
00351     {
00352       power = power << 1;
00353       e++;
00354     }
00355 
00356     return power;
00357   }
00358 
00359   // ClearLSBBit(0x01001100) = 0x01001000
00360   inline unsigned int Hak32_ClearLSBBit (unsigned int N)
00361   {
00362     return N & (N - 1);
00363   }
00364 
00365   // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
00366   // Hak32_CountNumBits(0x01001100) = 3
00367   inline unsigned int Hak32_CountNumBits (unsigned int N)
00368   {
00369     unsigned int v = N; // count the number of bits set in v
00370     unsigned int c; // c accumulates the total bits set in v
00371 
00372     for (c = 0; v; c++)
00373     {
00374       v &= v - 1; // clear the least significant bit set
00375     }
00376 
00377     return c;
00378   }
00379 
00380   // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan : Compute parity in parallel
00381   inline unsigned int Hak32_BitParity (unsigned int N)
00382   {
00383     unsigned int v = N;  // word value to compute the parity of
00384     v ^= v >> 16;
00385     v ^= v >> 8;
00386     v ^= v >> 4;
00387     v &= 0xf;
00388     return (0x6996 >> v) & 1;
00389   }
00390 
00391 #define HAK32_SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
00392 
00393   // Return true if the CPU is little endian
00394   inline bool Hak32_CPULittleEndian()
00395   {
00396     const int x = 1;
00397     return ((unsigned char *) &x) [0] ? true : false;
00398   }
00399 
00400   // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
00401   // Find the log base 10 of an N-bit integer in O(lg(N))
00402   inline unsigned int Hak32_Log2 (unsigned int N)
00403   {
00404     unsigned int v = N; // find the log base 2 of 32-bit v
00405     int r;          // result goes here
00406 
00407     static const int MultiplyDeBruijnBitPosition[32] =
00408     {
00409       0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
00410       31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
00411     };
00412 
00413     v |= v >> 1; // first round down to power of 2
00414     v |= v >> 2;
00415     v |= v >> 4;
00416     v |= v >> 8;
00417     v |= v >> 16;
00418     v = (v >> 1) + 1;
00419 
00420     r = MultiplyDeBruijnBitPosition[static_cast<unsigned int> (v * 0x077CB531UL) >> 27];
00421     return r;
00422   }
00423 
00424   // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
00425   // Find the log base 2 of an N-bit integer in O(lg(N))
00426   inline unsigned int Hak32_Log10 (unsigned int N)
00427   {
00428     unsigned int v = N; // non-zero 32-bit integer value to compute the log base 10 of
00429     int r;          // result goes here
00430     int t;          // temporary
00431 
00432     static unsigned int const PowersOf10[] =
00433     {
00434       1, 10, 100, 1000, 10000, 100000,
00435       1000000, 10000000, 100000000, 1000000000
00436     };
00437 
00438     t = (Hak32_Log2 (v) + 1) * 1233 >> 12; // (use a lg2 method from above)
00439     r = t - (v < PowersOf10[t]);
00440 
00441     return r;
00442   }
00443 
00444   // http://graphics.stanford.edu/~seander/bithacks.html
00445   // Count the consecutive zero bits (trailing) on the right by binary search
00446   inline unsigned int Hack32_TrailingZeroRight (unsigned int N)
00447   {
00448     unsigned int v = N;     // 32-bit word input to count zero bits on right
00449     unsigned int c;     // c will be the number of zero bits on the right,
00450     // so if v is 1101000 (base 2), then c will be 3
00451     // NOTE: if 0 == v, then c = 31.
00452     if (v & 0x1)
00453     {
00454       // special case for odd v (assumed to happen half of the time)
00455       c = 0;
00456     }
00457     else
00458     {
00459       c = 1;
00460 
00461       if ((v & 0xffff) == 0)
00462       {
00463         v >>= 16;
00464         c += 16;
00465       }
00466 
00467       if ((v & 0xff) == 0)
00468       {
00469         v >>= 8;
00470         c += 8;
00471       }
00472 
00473       if ((v & 0xf) == 0)
00474       {
00475         v >>= 4;
00476         c += 4;
00477       }
00478 
00479       if ((v & 0x3) == 0)
00480       {
00481         v >>= 2;
00482         c += 2;
00483       }
00484 
00485       c -= v & 0x1;
00486     }
00487 
00488     return c;
00489   }
00490 
00491 }
00492 
00493 #endif // MATHUTILITY_H