Home | Namespaces | Hierarchy | Alphabetical List | Class list | Files | Namespace Members | Class members | File members | Tutorials

irrMath.h

Go to the documentation of this file.
00001 // Copyright (C) 2002-2010 Nikolaus Gebhardt
00002 // This file is part of the "Irrlicht Engine".
00003 // For conditions of distribution and use, see copyright notice in irrlicht.h
00004 
00005 #ifndef __IRR_MATH_H_INCLUDED__
00006 #define __IRR_MATH_H_INCLUDED__
00007 
00008 #include "IrrCompileConfig.h"
00009 #include "irrTypes.h"
00010 #include <math.h>
00011 #include <float.h>
00012 #include <stdlib.h> // for abs() etc.
00013 #include <limits.h> // For INT_MAX / UINT_MAX
00014 
00015 #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE)
00016         #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X))
00017         #define sinf(X) (irr::f32)sin((irr::f64)(X))
00018         #define cosf(X) (irr::f32)cos((irr::f64)(X))
00019         #define asinf(X) (irr::f32)asin((irr::f64)(X))
00020         #define acosf(X) (irr::f32)acos((irr::f64)(X))
00021         #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y))
00022         #define ceilf(X) (irr::f32)ceil((irr::f64)(X))
00023         #define floorf(X) (irr::f32)floor((irr::f64)(X))
00024         #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y))
00025         #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y))
00026         #define fabsf(X) (irr::f32)fabs((irr::f64)(X))
00027         #define logf(X) (irr::f32)log((irr::f64)(X))
00028 #endif
00029 
00030 #ifndef FLT_MAX
00031 #define FLT_MAX 3.402823466E+38F
00032 #endif
00033 
00034 namespace irr
00035 {
00036 namespace core
00037 {
00038 
00040 
00041         const s32 ROUNDING_ERROR_S32 = 0;
00042         const f32 ROUNDING_ERROR_f32 = 0.000001f;
00043         const f64 ROUNDING_ERROR_f64 = 0.00000001;
00044 
00045 #ifdef PI // make sure we don't collide with a define
00046 #undef PI
00047 #endif
00049         const f32 PI            = 3.14159265359f;
00050 
00052         const f32 RECIPROCAL_PI = 1.0f/PI;
00053 
00055         const f32 HALF_PI       = PI/2.0f;
00056 
00057 #ifdef PI64 // make sure we don't collide with a define
00058 #undef PI64
00059 #endif
00061         const f64 PI64          = 3.1415926535897932384626433832795028841971693993751;
00062 
00064         const f64 RECIPROCAL_PI64 = 1.0/PI64;
00065 
00067         const f32 DEGTORAD = PI / 180.0f;
00068 
00070         const f32 RADTODEG   = 180.0f / PI;
00071 
00073         const f64 DEGTORAD64 = PI64 / 180.0;
00074 
00076         const f64 RADTODEG64 = 180.0 / PI64;
00077 
00079 
00082         inline f32 radToDeg(f32 radians)
00083         {
00084                 return RADTODEG * radians;
00085         }
00086 
00088 
00091         inline f64 radToDeg(f64 radians)
00092         {
00093                 return RADTODEG64 * radians;
00094         }
00095 
00097 
00100         inline f32 degToRad(f32 degrees)
00101         {
00102                 return DEGTORAD * degrees;
00103         }
00104 
00106 
00109         inline f64 degToRad(f64 degrees)
00110         {
00111                 return DEGTORAD64 * degrees;
00112         }
00113 
00115         template<class T>
00116         inline const T& min_(const T& a, const T& b)
00117         {
00118                 return a < b ? a : b;
00119         }
00120 
00122         template<class T>
00123         inline const T& min_(const T& a, const T& b, const T& c)
00124         {
00125                 return a < b ? min_(a, c) : min_(b, c);
00126         }
00127 
00129         template<class T>
00130         inline const T& max_(const T& a, const T& b)
00131         {
00132                 return a < b ? b : a;
00133         }
00134 
00136         template<class T>
00137         inline const T& max_(const T& a, const T& b, const T& c)
00138         {
00139                 return a < b ? max_(b, c) : max_(a, c);
00140         }
00141 
00143         template<class T>
00144         inline T abs_(const T& a)
00145         {
00146                 return a < (T)0 ? -a : a;
00147         }
00148 
00151         template<class T>
00152         inline T lerp(const T& a, const T& b, const f32 t)
00153         {
00154                 return (T)(a*(1.f-t)) + (b*t);
00155         }
00156 
00158         template <class T>
00159         inline const T clamp (const T& value, const T& low, const T& high)
00160         {
00161                 return min_ (max_(value,low), high);
00162         }
00163 
00165         // Note: We use the same trick as boost and use two template arguments to
00166         // avoid ambiguity when swapping objects of an Irrlicht type that has not
00167         // it's own swap overload. Otherwise we get conflicts with some compilers
00168         // in combination with stl.
00169         template <class T1, class T2>
00170         inline void swap(T1& a, T2& b)
00171         {
00172                 T1 c(a);
00173                 a = b;
00174                 b = c;
00175         }
00176 
00178         inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
00179         {
00180                 return (a + tolerance >= b) && (a - tolerance <= b);
00181         }
00182 
00184         inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
00185         {
00186                 return (a + tolerance >= b) && (a - tolerance <= b);
00187         }
00188 #if 0
00190         inline bool equals(const s32 a, const s32 b)
00191         {
00192                 return (a == b);
00193         }
00194 
00196         inline bool equals(const u32 a, const u32 b)
00197         {
00198                 return (a == b);
00199         }
00200 #endif
00202         inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00203         {
00204                 return (a + tolerance >= b) && (a - tolerance <= b);
00205         }
00206 
00208         inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00209         {
00210                 return (a + tolerance >= b) && (a - tolerance <= b);
00211         }
00212 
00213 
00215         inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
00216         {
00217                 return fabs(a) <= tolerance;
00218         }
00219 
00221         inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00222         {
00223                 return fabsf(a) <= tolerance;
00224         }
00225 
00227         inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00228         {
00229                 return fabsf(a) > tolerance;
00230         }
00231 
00233         inline bool iszero(const s32 a, const s32 tolerance = 0)
00234         {
00235                 return ( a & 0x7ffffff ) <= tolerance;
00236         }
00237 
00239         inline bool iszero(const u32 a, const u32 tolerance = 0)
00240         {
00241                 return a <= tolerance;
00242         }
00243 
00244         inline s32 s32_min(s32 a, s32 b)
00245         {
00246                 const s32 mask = (a - b) >> 31;
00247                 return (a & mask) | (b & ~mask);
00248         }
00249 
00250         inline s32 s32_max(s32 a, s32 b)
00251         {
00252                 const s32 mask = (a - b) >> 31;
00253                 return (b & mask) | (a & ~mask);
00254         }
00255 
00256         inline s32 s32_clamp (s32 value, s32 low, s32 high)
00257         {
00258                 return s32_min(s32_max(value,low), high);
00259         }
00260 
00261         /*
00262                 float IEEE-754 bit represenation
00263 
00264                 0      0x00000000
00265                 1.0    0x3f800000
00266                 0.5    0x3f000000
00267                 3      0x40400000
00268                 +inf   0x7f800000
00269                 -inf   0xff800000
00270                 +NaN   0x7fc00000 or 0x7ff00000
00271                 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
00272         */
00273 
00274         typedef union { u32 u; s32 s; f32 f; } inttofloat;
00275 
00276         #define F32_AS_S32(f)           (*((s32 *) &(f)))
00277         #define F32_AS_U32(f)           (*((u32 *) &(f)))
00278         #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
00279 
00280         #define F32_VALUE_0             0x00000000
00281         #define F32_VALUE_1             0x3f800000
00282         #define F32_SIGN_BIT            0x80000000U
00283         #define F32_EXPON_MANTISSA      0x7FFFFFFFU
00284 
00287 #ifdef IRRLICHT_FAST_MATH
00288         #define IR(x)                           ((u32&)(x))
00289 #else
00290         inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
00291 #endif
00292 
00294         #define AIR(x)                          (IR(x)&0x7fffffff)
00295 
00297 #ifdef IRRLICHT_FAST_MATH
00298         #define FR(x)                           ((f32&)(x))
00299 #else
00300         inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
00301         inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
00302 #endif
00303 
00305         #define IEEE_1_0                        0x3f800000
00307         #define IEEE_255_0                      0x437f0000
00308 
00309 #ifdef IRRLICHT_FAST_MATH
00310         #define F32_LOWER_0(f)          (F32_AS_U32(f) >  F32_SIGN_BIT)
00311         #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
00312         #define F32_GREATER_0(f)        (F32_AS_S32(f) >  F32_VALUE_0)
00313         #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
00314         #define F32_EQUAL_1(f)          (F32_AS_U32(f) == F32_VALUE_1)
00315         #define F32_EQUAL_0(f)          ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
00316 
00317         // only same sign
00318         #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
00319 
00320 #else
00321 
00322         #define F32_LOWER_0(n)          ((n) <  0.0f)
00323         #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
00324         #define F32_GREATER_0(n)        ((n) >  0.0f)
00325         #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
00326         #define F32_EQUAL_1(n)          ((n) == 1.0f)
00327         #define F32_EQUAL_0(n)          ((n) == 0.0f)
00328         #define F32_A_GREATER_B(a,b)    ((a) > (b))
00329 #endif
00330 
00331 
00332 #ifndef REALINLINE
00333         #ifdef _MSC_VER
00334                 #define REALINLINE __forceinline
00335         #else
00336                 #define REALINLINE inline
00337         #endif
00338 #endif
00339 
00340 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
00341 
00342         // 8-bit bools in borland builder
00343 
00345         REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
00346         {
00347                 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
00348         }
00349 
00351         REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
00352         {
00353                 return ( -condition >> 31 ) & a;
00354         }
00355 #else
00356 
00358         REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
00359         {
00360                 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
00361         }
00362 
00364         REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
00365         {
00366                 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
00367         }
00368 
00370         REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
00371         {
00372                 return ( -condition >> 31 ) & a;
00373         }
00374 #endif
00375 
00376         /*
00377                 if (condition) state |= m; else state &= ~m;
00378         */
00379         REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00380         {
00381                 // 0, or any postive to mask
00382                 //s32 conmask = -condition >> 31;
00383                 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
00384         }
00385 
00386         inline f32 round_( f32 x )
00387         {
00388                 return floorf( x + 0.5f );
00389         }
00390 
00391         REALINLINE void clearFPUException ()
00392         {
00393 #ifdef IRRLICHT_FAST_MATH
00394                 return;
00395 #ifdef feclearexcept
00396                 feclearexcept(FE_ALL_EXCEPT);
00397 #elif defined(_MSC_VER)
00398                 __asm fnclex;
00399 #elif defined(__GNUC__) && defined(__x86__)
00400                 __asm__ __volatile__ ("fclex \n\t");
00401 #else
00402 #  warn clearFPUException not supported.
00403 #endif
00404 #endif
00405         }
00406 
00407         // calculate: sqrt ( x )
00408         REALINLINE f32 squareroot(const f32 f)
00409         {
00410                 return sqrtf(f);
00411         }
00412 
00413         // calculate: sqrt ( x )
00414         REALINLINE f64 squareroot(const f64 f)
00415         {
00416                 return sqrt(f);
00417         }
00418 
00419         // calculate: sqrt ( x )
00420         REALINLINE s32 squareroot(const s32 f)
00421         {
00422                 return static_cast<s32>(squareroot(static_cast<f32>(f)));
00423         }
00424 
00425         // calculate: 1 / sqrt ( x )
00426         REALINLINE f64 reciprocal_squareroot(const f64 x)
00427         {
00428                 return 1.0 / sqrt(x);
00429         }
00430 
00431         // calculate: 1 / sqrtf ( x )
00432         REALINLINE f32 reciprocal_squareroot(const f32 f)
00433         {
00434 #if defined ( IRRLICHT_FAST_MATH )
00435         #if defined(_MSC_VER)
00436                 // SSE reciprocal square root estimate, accurate to 12 significant
00437                 // bits of the mantissa
00438                 f32 recsqrt;
00439                 __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
00440                 __asm movss recsqrt, xmm0       // return xmm0
00441                 return recsqrt;
00442 
00443 /*
00444                 // comes from Nvidia
00445                 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
00446                 f32 y = *(f32*)&tmp;
00447                 return y * (1.47f - 0.47f * x * y * y);
00448 */
00449         #else
00450                 return 1.f / sqrtf(f);
00451         #endif
00452 #else // no fast math
00453                 return 1.f / sqrtf(f);
00454 #endif
00455         }
00456 
00457         // calculate: 1 / sqrtf( x )
00458         REALINLINE s32 reciprocal_squareroot(const s32 x)
00459         {
00460                 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00461         }
00462 
00463         // calculate: 1 / x
00464         REALINLINE f32 reciprocal( const f32 f )
00465         {
00466 #if defined (IRRLICHT_FAST_MATH)
00467 
00468                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00469                 // bi ts of the mantissa
00470                 // One Newtown-Raphson Iteration:
00471                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00472                 f32 rec;
00473                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00474                 __asm movss xmm1, f               // xmm1 = f
00475                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00476                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00477                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00478                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
00479                                                                                   //        - f * rcpss(f) * rcpss(f)
00480                 __asm movss rec, xmm0             // return xmm0
00481                 return rec;
00482 
00483 
00485                 // instead set f to a high value to get a return value near zero..
00486                 // -1000000000000.f.. is use minus to stay negative..
00487                 // must test's here (plane.normal dot anything ) checks on <= 0.f
00488                 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
00489                 //return 1.f / FR ( x );
00490 
00491 #else // no fast math
00492                 return 1.f / f;
00493 #endif
00494         }
00495 
00496         // calculate: 1 / x
00497         REALINLINE f64 reciprocal ( const f64 f )
00498         {
00499                 return 1.0 / f;
00500         }
00501 
00502 
00503         // calculate: 1 / x, low precision allowed
00504         REALINLINE f32 reciprocal_approxim ( const f32 f )
00505         {
00506 #if defined( IRRLICHT_FAST_MATH)
00507 
00508                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00509                 // bi ts of the mantissa
00510                 // One Newtown-Raphson Iteration:
00511                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00512                 f32 rec;
00513                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00514                 __asm movss xmm1, f               // xmm1 = f
00515                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00516                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00517                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00518                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
00519                                                                                   //        - f * rcpss(f) * rcpss(f)
00520                 __asm movss rec, xmm0             // return xmm0
00521                 return rec;
00522 
00523 
00524 /*
00525                 // SSE reciprocal estimate, accurate to 12 significant bits of
00526                 f32 rec;
00527                 __asm rcpss xmm0, f             // xmm0 = rcpss(f)
00528                 __asm movss rec , xmm0          // return xmm0
00529                 return rec;
00530 */
00531 /*
00532                 register u32 x = 0x7F000000 - IR ( p );
00533                 const f32 r = FR ( x );
00534                 return r * (2.0f - p * r);
00535 */
00536 #else // no fast math
00537                 return 1.f / f;
00538 #endif
00539         }
00540 
00541 
00542         REALINLINE s32 floor32(f32 x)
00543         {
00544 #ifdef IRRLICHT_FAST_MATH
00545                 const f32 h = 0.5f;
00546 
00547                 s32 t;
00548 
00549 #if defined(_MSC_VER)
00550                 __asm
00551                 {
00552                         fld     x
00553                         fsub    h
00554                         fistp   t
00555                 }
00556 #elif defined(__GNUC__)
00557                 __asm__ __volatile__ (
00558                         "fsub %2 \n\t"
00559                         "fistpl %0"
00560                         : "=m" (t)
00561                         : "t" (x), "f" (h)
00562                         : "st"
00563                         );
00564 #else
00565 #  warn IRRLICHT_FAST_MATH not supported.
00566                 return (s32) floorf ( x );
00567 #endif
00568                 return t;
00569 #else // no fast math
00570                 return (s32) floorf ( x );
00571 #endif
00572         }
00573 
00574 
00575         REALINLINE s32 ceil32 ( f32 x )
00576         {
00577 #ifdef IRRLICHT_FAST_MATH
00578                 const f32 h = 0.5f;
00579 
00580                 s32 t;
00581 
00582 #if defined(_MSC_VER)
00583                 __asm
00584                 {
00585                         fld     x
00586                         fadd    h
00587                         fistp   t
00588                 }
00589 #elif defined(__GNUC__)
00590                 __asm__ __volatile__ (
00591                         "fadd %2 \n\t"
00592                         "fistpl %0 \n\t"
00593                         : "=m"(t)
00594                         : "t"(x), "f"(h)
00595                         : "st"
00596                         );
00597 #else
00598 #  warn IRRLICHT_FAST_MATH not supported.
00599                 return (s32) ceilf ( x );
00600 #endif
00601                 return t;
00602 #else // not fast math
00603                 return (s32) ceilf ( x );
00604 #endif
00605         }
00606 
00607 
00608 
00609         REALINLINE s32 round32(f32 x)
00610         {
00611 #if defined(IRRLICHT_FAST_MATH)
00612                 s32 t;
00613 
00614 #if defined(_MSC_VER)
00615                 __asm
00616                 {
00617                         fld   x
00618                         fistp t
00619                 }
00620 #elif defined(__GNUC__)
00621                 __asm__ __volatile__ (
00622                         "fistpl %0 \n\t"
00623                         : "=m"(t)
00624                         : "t"(x)
00625                         : "st"
00626                         );
00627 #else
00628 #  warn IRRLICHT_FAST_MATH not supported.
00629                 return (s32) round_(x);
00630 #endif
00631                 return t;
00632 #else // no fast math
00633                 return (s32) round_(x);
00634 #endif
00635         }
00636 
00637         inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
00638         {
00639                 return a > b ? (a > c ? a : c) : (b > c ? b : c);
00640         }
00641 
00642         inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
00643         {
00644                 return a < b ? (a < c ? a : c) : (b < c ? b : c);
00645         }
00646 
00647         inline f32 fract ( f32 x )
00648         {
00649                 return x - floorf ( x );
00650         }
00651 
00652 } // end namespace core
00653 } // end namespace irr
00654 
00655 #ifndef IRRLICHT_FAST_MATH
00656         using irr::core::IR;
00657         using irr::core::FR;
00658 #endif
00659 
00660 #endif
00661 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Oct 24 12:41:57 2010 by Doxygen (1.6.2)