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

| The Irrlicht Engine Documentation © 2003-2010 by Nikolaus Gebhardt. Generated on Sun Feb 14 13:06:57 2010 by Doxygen (1.6.2)