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 Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Oct 24 12:41:57 2010 by Doxygen (1.6.2)