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-2009 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) (f32)sqrt((f64)(X))
00017         #define sinf(X) (f32)sin((f64)(X))
00018         #define cosf(X) (f32)cos((f64)(X))
00019         #define asinf(X) (f32)asin((f64)(X))
00020         #define acosf(X) (f32)acos((f64)(X))
00021         #define atan2f(X,Y) (f32)atan2((f64)(X),(f64)(Y))
00022         #define ceilf(X) (f32)ceil((f64)(X))
00023         #define floorf(X) (f32)floor((f64)(X))
00024         #define powf(X,Y) (f32)pow((f64)(X),(f64)(Y))
00025         #define fmodf(X,Y) (f32)fmod((f64)(X),(f64)(Y))
00026         #define fabsf(X) (f32)fabs((f64)(X))
00027         #define logf(X) (f32)log((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 = 1;
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         inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
00166         {
00167                 return (a + tolerance >= b) && (a - tolerance <= b);
00168         }
00169 
00171         inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
00172         {
00173                 return (a + tolerance >= b) && (a - tolerance <= b);
00174         }
00175 #if 0
00177         inline bool equals(const s32 a, const s32 b)
00178         {
00179                 return (a == b);
00180         }
00181 
00183         inline bool equals(const u32 a, const u32 b)
00184         {
00185                 return (a == b);
00186         }
00187 #endif
00189         inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00190         {
00191                 return (a + tolerance >= b) && (a - tolerance <= b);
00192         }
00193 
00195         inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
00196         {
00197                 return (a + tolerance >= b) && (a - tolerance <= b);
00198         }
00199 
00200 
00202         inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
00203         {
00204                 return fabs(a) <= tolerance;
00205         }
00206 
00208         inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00209         {
00210                 return fabsf(a) <= tolerance;
00211         }
00212 
00214         inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
00215         {
00216                 return fabsf(a) > tolerance;
00217         }
00218 
00220         inline bool iszero(const s32 a, const s32 tolerance = 0)
00221         {
00222                 return ( a & 0x7ffffff ) <= tolerance;
00223         }
00224 
00226         inline bool iszero(const u32 a, const u32 tolerance = 0)
00227         {
00228                 return a <= tolerance;
00229         }
00230 
00231         inline s32 s32_min(s32 a, s32 b)
00232         {
00233                 const s32 mask = (a - b) >> 31;
00234                 return (a & mask) | (b & ~mask);
00235         }
00236 
00237         inline s32 s32_max(s32 a, s32 b)
00238         {
00239                 const s32 mask = (a - b) >> 31;
00240                 return (b & mask) | (a & ~mask);
00241         }
00242 
00243         inline s32 s32_clamp (s32 value, s32 low, s32 high)
00244         {
00245                 return s32_min(s32_max(value,low), high);
00246         }
00247 
00248         /*
00249                 float IEEE-754 bit represenation
00250 
00251                 0      0x00000000
00252                 1.0    0x3f800000
00253                 0.5    0x3f000000
00254                 3      0x40400000
00255                 +inf   0x7f800000
00256                 -inf   0xff800000
00257                 +NaN   0x7fc00000 or 0x7ff00000
00258                 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
00259         */
00260 
00261         typedef union { u32 u; s32 s; f32 f; } inttofloat;
00262 
00263         #define F32_AS_S32(f)           (*((s32 *) &(f)))
00264         #define F32_AS_U32(f)           (*((u32 *) &(f)))
00265         #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
00266 
00267         #define F32_VALUE_0             0x00000000
00268         #define F32_VALUE_1             0x3f800000
00269         #define F32_SIGN_BIT            0x80000000U
00270         #define F32_EXPON_MANTISSA      0x7FFFFFFFU
00271 
00274 #ifdef IRRLICHT_FAST_MATH
00275         #define IR(x)                           ((u32&)(x))
00276 #else
00277         inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
00278 #endif
00279 
00281         #define AIR(x)                          (IR(x)&0x7fffffff)
00282 
00284 #ifdef IRRLICHT_FAST_MATH
00285         #define FR(x)                           ((f32&)(x))
00286 #else
00287         inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
00288         inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
00289 #endif
00290 
00292         #define IEEE_1_0                        0x3f800000
00294         #define IEEE_255_0                      0x437f0000
00295 
00296 #ifdef IRRLICHT_FAST_MATH
00297         #define F32_LOWER_0(f)          (F32_AS_U32(f) >  F32_SIGN_BIT)
00298         #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
00299         #define F32_GREATER_0(f)        (F32_AS_S32(f) >  F32_VALUE_0)
00300         #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
00301         #define F32_EQUAL_1(f)          (F32_AS_U32(f) == F32_VALUE_1)
00302         #define F32_EQUAL_0(f)          ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
00303 
00304         // only same sign
00305         #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
00306 
00307 #else
00308 
00309         #define F32_LOWER_0(n)          ((n) <  0.0f)
00310         #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
00311         #define F32_GREATER_0(n)        ((n) >  0.0f)
00312         #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
00313         #define F32_EQUAL_1(n)          ((n) == 1.0f)
00314         #define F32_EQUAL_0(n)          ((n) == 0.0f)
00315         #define F32_A_GREATER_B(a,b)    ((a) > (b))
00316 #endif
00317 
00318 
00319 #ifndef REALINLINE
00320         #ifdef _MSC_VER
00321                 #define REALINLINE __forceinline
00322         #else
00323                 #define REALINLINE inline
00324         #endif
00325 #endif
00326 
00327 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
00328 
00329         // 8-bit bools in borland builder
00330 
00332         REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
00333         {
00334                 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
00335         }
00336 
00338         REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
00339         {
00340                 return ( -condition >> 31 ) & a;
00341         }
00342 #else
00343 
00345         REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
00346         {
00347                 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
00348         }
00349 
00351         REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
00352         {
00353                 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
00354         }
00355 
00357         REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
00358         {
00359                 return ( -condition >> 31 ) & a;
00360         }
00361 #endif
00362 
00363         /*
00364                 if (condition) state |= m; else state &= ~m;
00365         */
00366         REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00367         {
00368                 // 0, or any postive to mask
00369                 //s32 conmask = -condition >> 31;
00370                 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
00371         }
00372 
00373         inline f32 round_( f32 x )
00374         {
00375                 return floorf( x + 0.5f );
00376         }
00377 
00378         REALINLINE void clearFPUException ()
00379         {
00380 #ifdef IRRLICHT_FAST_MATH
00381                 return;
00382 #ifdef feclearexcept
00383                 feclearexcept(FE_ALL_EXCEPT);
00384 #elif defined(_MSC_VER)
00385                 __asm fnclex;
00386 #elif defined(__GNUC__) && defined(__x86__)
00387                 __asm__ __volatile__ ("fclex \n\t");
00388 #else
00389 #  warn clearFPUException not supported.
00390 #endif
00391 #endif
00392         }
00393 
00394         // calculate: sqrt ( x )
00395         REALINLINE f32 squareroot(const f32 f)
00396         {
00397                 return sqrtf(f);
00398         }
00399 
00400         // calculate: sqrt ( x )
00401         REALINLINE f64 squareroot(const f64 f)
00402         {
00403                 return sqrt(f);
00404         }
00405 
00406         // calculate: sqrt ( x )
00407         REALINLINE s32 squareroot(const s32 f)
00408         {
00409                 return static_cast<s32>(squareroot(static_cast<f32>(f)));
00410         }
00411 
00412         // calculate: 1 / sqrt ( x )
00413         REALINLINE f64 reciprocal_squareroot(const f64 x)
00414         {
00415                 return 1.0 / sqrt(x);
00416         }
00417 
00418         // calculate: 1 / sqrtf ( x )
00419         REALINLINE f32 reciprocal_squareroot(const f32 f)
00420         {
00421 #if defined ( IRRLICHT_FAST_MATH )
00422         #if defined(_MSC_VER)
00423                 // SSE reciprocal square root estimate, accurate to 12 significant
00424                 // bits of the mantissa
00425                 f32 recsqrt;
00426                 __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
00427                 __asm movss recsqrt, xmm0       // return xmm0
00428                 return recsqrt;
00429 
00430 /*
00431                 // comes from Nvidia
00432                 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
00433                 f32 y = *(f32*)&tmp;
00434                 return y * (1.47f - 0.47f * x * y * y);
00435 */
00436         #else
00437                 return 1.f / sqrtf(f);
00438         #endif
00439 #else // no fast math
00440                 return 1.f / sqrtf(f);
00441 #endif
00442         }
00443 
00444         // calculate: 1 / sqrtf( x )
00445         REALINLINE s32 reciprocal_squareroot(const s32 x)
00446         {
00447                 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00448         }
00449 
00450         // calculate: 1 / x
00451         REALINLINE f32 reciprocal( const f32 f )
00452         {
00453 #if defined (IRRLICHT_FAST_MATH)
00454 
00455                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00456                 // bi ts of the mantissa
00457                 // One Newtown-Raphson Iteration:
00458                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00459                 f32 rec;
00460                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00461                 __asm movss xmm1, f               // xmm1 = f
00462                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00463                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00464                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00465                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f) 
00466                                                                                   //        - f * rcpss(f) * rcpss(f)
00467                 __asm movss rec, xmm0             // return xmm0
00468                 return rec;
00469 
00470 
00472                 // instead set f to a high value to get a return value near zero..
00473                 // -1000000000000.f.. is use minus to stay negative..
00474                 // must test's here (plane.normal dot anything ) checks on <= 0.f
00475                 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
00476                 //return 1.f / FR ( x );
00477 
00478 #else // no fast math
00479                 return 1.f / f;
00480 #endif
00481         }
00482 
00483         // calculate: 1 / x
00484         REALINLINE f64 reciprocal ( const f64 f )
00485         {
00486                 return 1.0 / f;
00487         }
00488 
00489 
00490         // calculate: 1 / x, low precision allowed
00491         REALINLINE f32 reciprocal_approxim ( const f32 f )
00492         {
00493 #if defined( IRRLICHT_FAST_MATH)
00494 
00495                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
00496                 // bi ts of the mantissa
00497                 // One Newtown-Raphson Iteration:
00498                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
00499                 f32 rec;
00500                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
00501                 __asm movss xmm1, f               // xmm1 = f
00502                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
00503                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
00504                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
00505                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f) 
00506                                                                                   //        - f * rcpss(f) * rcpss(f)
00507                 __asm movss rec, xmm0             // return xmm0
00508                 return rec;
00509 
00510 
00511 /*
00512                 // SSE reciprocal estimate, accurate to 12 significant bits of
00513                 f32 rec;
00514                 __asm rcpss xmm0, f             // xmm0 = rcpss(f)
00515                 __asm movss rec , xmm0          // return xmm0
00516                 return rec;
00517 */
00518 /*
00519                 register u32 x = 0x7F000000 - IR ( p );
00520                 const f32 r = FR ( x );
00521                 return r * (2.0f - p * r);
00522 */
00523 #else // no fast math
00524                 return 1.f / f;
00525 #endif
00526         }
00527 
00528 
00529         REALINLINE s32 floor32(f32 x)
00530         {
00531 #ifdef IRRLICHT_FAST_MATH
00532                 const f32 h = 0.5f;
00533 
00534                 s32 t;
00535 
00536 #if defined(_MSC_VER)
00537                 __asm
00538                 {
00539                         fld     x
00540                         fsub    h
00541                         fistp   t
00542                 }
00543 #elif defined(__GNUC__)
00544                 __asm__ __volatile__ (
00545                         "fsub %2 \n\t"
00546                         "fistpl %0"
00547                         : "=m" (t)
00548                         : "t" (x), "f" (h)
00549                         : "st"
00550                         );
00551 #else
00552 #  warn IRRLICHT_FAST_MATH not supported.
00553                 return (s32) floorf ( x );
00554 #endif
00555                 return t;
00556 #else // no fast math
00557                 return (s32) floorf ( x );
00558 #endif
00559         }
00560 
00561 
00562         REALINLINE s32 ceil32 ( f32 x )
00563         {
00564 #ifdef IRRLICHT_FAST_MATH
00565                 const f32 h = 0.5f;
00566 
00567                 s32 t;
00568 
00569 #if defined(_MSC_VER)
00570                 __asm
00571                 {
00572                         fld     x
00573                         fadd    h
00574                         fistp   t
00575                 }
00576 #elif defined(__GNUC__)
00577                 __asm__ __volatile__ (
00578                         "fadd %2 \n\t"
00579                         "fistpl %0 \n\t"
00580                         : "=m"(t)
00581                         : "t"(x), "f"(h)
00582                         : "st"
00583                         );
00584 #else
00585 #  warn IRRLICHT_FAST_MATH not supported.
00586                 return (s32) ceilf ( x );
00587 #endif
00588                 return t;
00589 #else // not fast math
00590                 return (s32) ceilf ( x );
00591 #endif
00592         }
00593 
00594 
00595 
00596         REALINLINE s32 round32(f32 x)
00597         {
00598 #if defined(IRRLICHT_FAST_MATH)
00599                 s32 t;
00600 
00601 #if defined(_MSC_VER)
00602                 __asm
00603                 {
00604                         fld   x
00605                         fistp t
00606                 }
00607 #elif defined(__GNUC__)
00608                 __asm__ __volatile__ (
00609                         "fistpl %0 \n\t"
00610                         : "=m"(t)
00611                         : "t"(x)
00612                         : "st"
00613                         );
00614 #else
00615 #  warn IRRLICHT_FAST_MATH not supported.
00616                 return (s32) round_(x);
00617 #endif
00618                 return t;
00619 #else // no fast math
00620                 return (s32) round_(x);
00621 #endif
00622         }
00623 
00624         inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
00625         {
00626                 return a > b ? (a > c ? a : c) : (b > c ? b : c);
00627         }
00628 
00629         inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
00630         {
00631                 return a < b ? (a < c ? a : c) : (b < c ? b : c);
00632         }
00633 
00634         inline f32 fract ( f32 x )
00635         {
00636                 return x - floorf ( x );
00637         }
00638 
00639 } // end namespace core
00640 } // end namespace irr
00641 
00642 #ifndef IRRLICHT_FAST_MATH
00643         using irr::core::IR;
00644         using irr::core::FR;
00645 #endif
00646 
00647 #endif
00648 

The Irrlicht Engine
The Irrlicht Engine Documentation © 2003-2009 by Nikolaus Gebhardt. Generated on Sun Jan 10 09:24:04 2010 by Doxygen (1.5.6)