• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Math.h

Go to the documentation of this file.
00001 // GMTL is (C) Copyright 2001-2010 by Allen Bierbaum
00002 // Distributed under the GNU Lesser General Public License 2.1 with an
00003 // addendum covering inlined code. (See accompanying files LICENSE and
00004 // LICENSE.addendum or http://www.gnu.org/copyleft/lesser.txt)
00005 
00006 #ifndef _GMTL_MATH_H_
00007 #define _GMTL_MATH_H_
00008 
00009 #include <math.h>
00010 #include <stdlib.h>
00011 #include <gmtl/Defines.h>
00012 #include <gmtl/Util/Assert.h>
00013 #include <gmtl/Util/StaticAssert.h>
00014 
00015 namespace gmtl
00016 {
00017 
00022 struct RotationOrderBase { enum { IS_ROTORDER = 1 }; };
00023 
00026 struct XYZ : public RotationOrderBase { enum { ID = 0 }; };
00027 
00030 struct ZYX : public RotationOrderBase { enum { ID = 1 }; };
00031 
00034 struct ZXY : public RotationOrderBase { enum { ID = 2 }; };
00035 
00036 namespace Math
00037 {
00042    const float TWO_PI = 6.28318530717958647692f;
00043    const float PI = 3.14159265358979323846f; //3.14159265358979323846264338327950288419716939937510;
00044    const float PI_OVER_2 = 1.57079632679489661923f;
00045    const float PI_OVER_4 = 0.78539816339744830962f;
00052 //----------------------------------------------------------------------------
00053 template <typename T>
00054 inline T abs( T iValue )
00055 {
00056     return static_cast<T>( iValue >= static_cast<T>(0) ? iValue : -iValue );
00057 }
00058 
00059 inline float abs(float iValue)
00060 {  return fabsf(iValue); }
00061 inline double abs(double iValue)
00062 {  return fabs(iValue); }
00063 inline int abs(int iValue)
00064 {  return ::abs(iValue); }
00065 inline long abs(long iValue)
00066 {  return labs(iValue); }
00067 
00068 //----------------------------------------------------------------------------
00069 template <typename T>
00070 inline T ceil( T fValue );
00071 inline float ceil( float fValue )
00072 {
00073 #ifdef NO_CEILF
00074    return float(::ceil(fValue));
00075 #else
00076    return float( ::ceilf( fValue ) );
00077 #endif
00078 }
00079 inline double ceil( double fValue )
00080 {
00081     return double( ::ceil( fValue ) );
00082 }
00083 //----------------------------------------------------------------------------
00084 template <typename T>
00085 inline T floor( T fValue ); // why do a floor of int?  shouldn't compile...
00086 inline float floor( float fValue )
00087 {
00088 #ifdef NO_FLOORF
00089    return float(::floor(fValue));
00090 #else
00091    return float( ::floorf( fValue ) );
00092 #endif
00093 }
00094 inline double floor( double fValue )
00095 {
00096     return double( ::floor( fValue ) );
00097 }
00098 //----------------------------------------------------------------------------
00099 template <typename T>
00100 inline int sign( T iValue )
00101 {
00102    if (iValue > static_cast<T>(0))
00103    {
00104       return 1;
00105    }
00106    else
00107    {
00108       if (iValue < static_cast<T>(0))
00109       {
00110          return -1;
00111       }
00112       else
00113       {
00114          return 0;
00115       }
00116    }
00117 }
00118 //----------------------------------------------------------------------------
00127 template <typename T>
00128 inline T zeroClamp( T value, T eps = static_cast<T>(0) )
00129 {
00130    return ( (gmtl::Math::abs(value) <= eps) ? static_cast<T>(0) : value );
00131 }
00132 
00133 //----------------------------------------------------------------------------
00134 // don't allow non-float types, because their ret val wont be correct
00135 // i.e. with int, the int retval will be rounded up or down.
00136 //      we'd need a float retval to do it right, but we can't specialize by ret
00137 template <typename T>
00138 inline T aCos( T fValue );
00139 inline float aCos( float fValue )
00140 {
00141     if ( -1.0f < fValue )
00142     {
00143         if ( fValue < 1.0f )
00144         {
00145 #ifdef NO_ACOSF
00146             return static_cast<float>(::acos(fValue));
00147 #else
00148             return static_cast<float>(::acosf(fValue));
00149 #endif
00150         }
00151         else
00152             return 0.0f;
00153     }
00154     else
00155     {
00156         return static_cast<float>(gmtl::Math::PI);
00157     }
00158 }
00159 inline double aCos( double fValue )
00160 {
00161     if ( -1.0 < fValue )
00162     {
00163         if ( fValue < 1.0 )
00164             return static_cast<double>(::acos(fValue));
00165         else
00166             return 0.0;
00167     }
00168     else
00169     {
00170         return static_cast<double>(gmtl::Math::PI);
00171     }
00172 }
00173 //----------------------------------------------------------------------------
00174 template <typename T>
00175 inline T aSin( T fValue );
00176 inline float aSin( float fValue )
00177 {
00178     if ( -1.0f < fValue )
00179     {
00180         if ( fValue < 1.0f )
00181         {
00182 #ifdef NO_ASINF
00183             return static_cast<float>(::asin(fValue));
00184 #else
00185             return static_cast<float>(::asinf(fValue));
00186 #endif
00187         }
00188         else
00189             return static_cast<float>(-gmtl::Math::PI_OVER_2);
00190     }
00191     else
00192     {
00193         return static_cast<float>(gmtl::Math::PI_OVER_2);
00194     }
00195 }
00196 inline double aSin( double fValue )
00197 {
00198     if ( -1.0 < fValue )
00199     {
00200         if ( fValue < 1.0 )
00201             return static_cast<double>(::asin(fValue));
00202         else
00203             return static_cast<double>(-gmtl::Math::PI_OVER_2);
00204     }
00205     else
00206     {
00207         return static_cast<double>(gmtl::Math::PI_OVER_2);
00208     }
00209 }
00210 //----------------------------------------------------------------------------
00211 template <typename T>
00212 inline T aTan( T fValue );
00213 inline double aTan( double fValue )
00214 {
00215     return ::atan( fValue );
00216 }
00217 inline float aTan( float fValue )
00218 {
00219 #ifdef NO_TANF
00220    return static_cast<float>(::atan(fValue));
00221 #else
00222    return static_cast<float>(::atanf(fValue));
00223 #endif
00224 }
00225 //----------------------------------------------------------------------------
00226 template <typename T>
00227 inline T aTan2( T fY, T fX );
00228 inline float aTan2( float fY, float fX )
00229 {
00230 #ifdef NO_ATAN2F
00231    return static_cast<float>(::atan2(fY, fX));
00232 #else
00233    return static_cast<float>(::atan2f(fY, fX));
00234 #endif
00235 }
00236 inline double aTan2( double fY, double fX )
00237 {
00238     return static_cast<double>(::atan2(fY, fX));
00239 }
00240 //----------------------------------------------------------------------------
00241 template <typename T>
00242 inline T cos( T fValue );
00243 inline float cos( float fValue )
00244 {
00245 #ifdef NO_COSF
00246    return static_cast<float>(::cos(fValue));
00247 #else
00248    return static_cast<float>(::cosf(fValue));
00249 #endif
00250 }
00251 inline double cos( double fValue )
00252 {
00253     return static_cast<double>(::cos(fValue));
00254 }
00255 //----------------------------------------------------------------------------
00256 template <typename T>
00257 inline T exp( T fValue );
00258 inline float exp( float fValue )
00259 {
00260 #ifdef NO_EXPF
00261    return static_cast<float>(::exp(fValue));
00262 #else
00263    return static_cast<float>(::expf(fValue));
00264 #endif
00265 }
00266 inline double exp( double fValue )
00267 {
00268     return static_cast<double>(::exp(fValue));
00269 }
00270 //----------------------------------------------------------------------------
00271 template <typename T>
00272 inline T log( T fValue );
00273 inline double log( double fValue )
00274 {
00275     return static_cast<double>(::log(fValue));
00276 }
00277 inline float log( float fValue )
00278 {
00279 #ifdef NO_LOGF
00280    return static_cast<float>(::log(fValue));
00281 #else
00282    return static_cast<float>(::logf(fValue));
00283 #endif
00284 }
00285 //----------------------------------------------------------------------------
00286 inline double pow( double fBase, double fExponent)
00287 {
00288     return static_cast<double>(::pow(fBase, fExponent));
00289 }
00290 inline float pow( float fBase, float fExponent)
00291 {
00292 #ifdef NO_POWF
00293    return static_cast<float>(::pow(fBase, fExponent));
00294 #else
00295    return static_cast<float>(::powf(fBase, fExponent));
00296 #endif
00297 }
00298 //----------------------------------------------------------------------------
00299 template <typename T>
00300 inline T sin( T fValue );
00301 inline double sin( double fValue )
00302 {
00303     return static_cast<double>(::sin(fValue));
00304 }
00305 inline float sin( float fValue )
00306 {
00307 #ifdef NO_SINF
00308    return static_cast<float>(::sin(fValue));
00309 #else
00310    return static_cast<float>(::sinf(fValue));
00311 #endif
00312 }
00313 //----------------------------------------------------------------------------
00314 template <typename T>
00315 inline T tan( T fValue );
00316 inline double tan( double fValue )
00317 {
00318     return static_cast<double>(::tan(fValue));
00319 }
00320 inline float tan( float fValue )
00321 {
00322 #ifdef NO_TANF
00323    return static_cast<float>(::tan(fValue));
00324 #else
00325    return static_cast<float>(::tanf(fValue));
00326 #endif
00327 }
00328 //----------------------------------------------------------------------------
00329 template <typename T>
00330 inline T sqr( T fValue )
00331 {
00332     return static_cast<T>(fValue * fValue);
00333 }
00334 //----------------------------------------------------------------------------
00335 template <typename T>
00336 inline T sqrt( T fValue )
00337 {
00338 #ifdef NO_SQRTF
00339    return static_cast<T>(::sqrt((static_cast<float>(fValue))));
00340 #else
00341    return static_cast<T>(::sqrtf((static_cast<float>(fValue))));
00342 #endif
00343 }
00344 inline double sqrt( double fValue )
00345 {
00346     return static_cast<double>(::sqrt(fValue));
00347 }
00348 
00351 inline float fastInvSqrt(float x)
00352 {
00353    GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00354                       Union_type_sizes_do_not_match);
00355 
00356    // Use an approach to data type reinterpretation that is safe with GCC
00357    // strict aliasing enabled. This is called type-punning, and it is valid
00358    // when done with a union where the value read (int_value) is different
00359    // than the one most recently written to (float_value).
00360    union
00361    {
00362       float float_value;
00363       int   int_value;
00364    } data;
00365 
00366    const float xhalf(0.5f*x);
00367    data.float_value = x;
00368    // This hides a good amount of math
00369    data.int_value = 0x5f3759df - (data.int_value >> 1);
00370    x = data.float_value;
00371    x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
00372    return x;
00373 }
00374 
00375 inline float fastInvSqrt2(float x)
00376 {
00377    GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00378                       Union_type_sizes_do_not_match);
00379 
00380    // Use an approach to data type reinterpretation that is safe with GCC
00381    // strict aliasing enabled. This is called type-punning, and it is valid
00382    // when done with a union where the value read (int_value) is different
00383    // than the one most recently written to (float_value).
00384    union
00385    {
00386       float float_value;
00387       int   int_value;
00388    } data;
00389 
00390    const float xhalf(0.5f*x);
00391    data.float_value = x;
00392    // This hides a good amount of math
00393    data.int_value = 0x5f3759df - (data.int_value >> 1);
00394    x = data.float_value;
00395    x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
00396    x = x*(1.5f - xhalf*x*x);
00397    return x;
00398 }
00399 
00400 inline float fastInvSqrt3(float x)
00401 {
00402    GMTL_STATIC_ASSERT(sizeof(float) == sizeof(int),
00403                       Union_type_sizes_do_not_match);
00404 
00405    // Use an approach to data type reinterpretation that is safe with GCC
00406    // strict aliasing enabled. This is called type-punning, and it is valid
00407    // when done with a union where the value read (int_value) is different
00408    // than the one most recently written to (float_value).
00409    union
00410    {
00411       float float_value;
00412       int   int_value;
00413    } data;
00414 
00415    const float xhalf(0.5f*x);
00416    data.float_value = x;
00417    // This hides a good amount of math
00418    data.int_value = 0x5f3759df - (data.int_value >> 1);
00419    x = data.float_value;
00420    x = x*(1.5f - xhalf*x*x);   // Repeat for more accuracy
00421    x = x*(1.5f - xhalf*x*x);
00422    x = x*(1.5f - xhalf*x*x);
00423    return x;
00424 }
00425 
00426 
00427 //----------------------------------------------------------------------------
00433 inline void seedRandom(unsigned int seed)
00434 {
00435    ::srand(seed);
00436 }
00437 
00441 inline float unitRandom()
00442 {
00443    return static_cast<float>(::rand()) / static_cast<float>(RAND_MAX);
00444 }
00445 
00449 inline float rangeRandom( float x1, float x2 )
00450 {
00451    float r = gmtl::Math::unitRandom();
00452    float size = x2 - x1;
00453    return static_cast<float>(r * size + x1);
00454 }
00455 
00456 /*
00457 float SymmetricRandom ()
00458 {
00459     return 2.0 * static_cast<float>(rand()) / static_cast<float>(RAND_MAX) - 1.0;
00460 }
00461 */
00462 //----------------------------------------------------------------------------
00463 
00464 inline float deg2Rad( float fVal )
00465 {
00466    return static_cast<float>(fVal * static_cast<float>(gmtl::Math::PI / 180.0));
00467 }
00468 inline double deg2Rad( double fVal )
00469 {
00470    return static_cast<double>(fVal * static_cast<double>(gmtl::Math::PI / 180.0));
00471 }
00472 
00473 inline float rad2Deg( float fVal )
00474 {
00475    return static_cast<float>(fVal * static_cast<float>(180.0 / gmtl::Math::PI));
00476 }
00477 inline double rad2Deg( double fVal )
00478 {
00479    return static_cast<float>(fVal * static_cast<double>(180.0 / gmtl::Math::PI));
00480 }
00481 //----------------------------------------------------------------------------
00482 
00487 template <class T>
00488 inline bool isEqual( const T& a, const T& b, const T& tolerance )
00489 {
00490    gmtlASSERT(tolerance >= static_cast<T>(0));
00491    return gmtl::Math::abs( a - b ) <= tolerance;
00492 }
00493 //----------------------------------------------------------------------------
00495 template <class T>
00496 inline T trunc( T val )
00497 {
00498    return static_cast<T>((val < static_cast<T>(0)) ?
00499                          gmtl::Math::ceil(val)     :
00500                          gmtl::Math::floor(val));
00501 }
00503 template <class T>
00504 inline T round( T p )
00505 {
00506    return static_cast<T>(gmtl::Math::floor(p + static_cast<T>(0.5)));
00507 }
00508 //----------------------------------------------------------------------------
00510 template <class T>
00511 inline T Min( const T& x, const T& y )
00512 {
00513    return ( x > y ) ? y : x;
00514 }
00516 template <class T>
00517 inline T Min( const T& x, const T& y, const T& z )
00518 {
00519    return Min( gmtl::Math::Min( x, y ), z );
00520 }
00522 template <class T>
00523 inline T Min( const T& w, const T& x, const T& y, const T& z )
00524 {
00525    return gmtl::Math::Min( gmtl::Math::Min( w, x ), gmtl::Math::Min( y, z ) );
00526 }
00527 
00529 template <class T>
00530 inline T Max( const T& x, const T& y )
00531 {
00532    return ( x > y ) ? x : y;
00533 }
00535 template <class T>
00536 inline T Max( const T& x, const T& y, const T& z )
00537 {
00538    return Max( gmtl::Math::Max( x, y ), z );
00539 }
00541 template <class T>
00542 inline T Max( const T& w, const T& x, const T& y, const T& z )
00543 {
00544    return gmtl::Math::Max( gmtl::Math::Max( w, x ), gmtl::Math::Max( y, z ) );
00545 }
00546 //----------------------------------------------------------------------------
00552 template<class T>
00553 inline T factorial(T rhs)
00554 {
00555    T lhs = static_cast<T>(1);
00556 
00557    for( T x = static_cast<T>(1); x <= rhs; ++x )
00558    {
00559       lhs *= x;
00560    }
00561 
00562    return lhs;
00563 }
00569 template <class T>
00570 inline T clamp( T number, T lo, T hi )
00571 {
00572    if (number > hi) number = hi;
00573    else if (number < lo) number = lo;
00574    return number;
00575 }
00576 
00586 template <class T, typename U>
00587 inline void lerp( T& result, const U& lerp, const T& a, const T& b )
00588 {
00589     T size = b - a;
00590     result = static_cast<U>(a) + (static_cast<U>(size) * lerp);
00591 }
00606 template <class T>
00607 inline bool quadraticFormula(T& r1, T& r2, const T& a, const T& b, const T& c)
00608 {
00609    const T q = b * b - static_cast<T>(4) * a * c;
00610 
00611    // the result has real roots
00612    if (q >= 0)
00613    {
00614       const T sq = gmtl::Math::sqrt(q);
00615       const T d = static_cast<T>(1) / (static_cast<T>(2) * a);
00616       r1 = (-b + sq) * d;
00617       r2 = (-b - sq) * d;
00618       return true;
00619    }
00620    // the result has complex roots
00621    else
00622    {
00623       return false;
00624    }
00625 }
00626 
00627 } // end namespace Math
00628 } // end namespace gmtl
00629 
00630 #endif

Generated on Sun Sep 19 2010 14:35:14 for GenericMathTemplateLibrary by  doxygen 1.7.1