| Irrlicht 3D Engine |

irrMath.h
Go to the documentation of this file.

    00001 // Copyright (C) 2002-2012 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 #ifndef FLT_MIN
    00035 #define FLT_MIN 1.17549435e-38F
    00036 #endif
    00037
    00038 namespace irr
    00039 {
    00040 namespace core
    00041 {
    00042
    00044
    00045     const s32 ROUNDING_ERROR_S32 = 0;
    00046 #ifdef __IRR_HAS_S64
    00047     const s64 ROUNDING_ERROR_S64 = 0;
    00048 #endif
    00049     const f32 ROUNDING_ERROR_f32 = 0.000001f;
    00050     const f64 ROUNDING_ERROR_f64 = 0.00000001;
    00051
    00052 #ifdef PI // make sure we don't collide with a define
    00053 #undef PI
    00054 #endif
    00055
    00056     const f32 PI        = 3.14159265359f;
    00057
    00059     const f32 RECIPROCAL_PI = 1.0f/PI;
    00060
    00062     const f32 HALF_PI   = PI/2.0f;
    00063
    00064 #ifdef PI64 // make sure we don't collide with a define
    00065 #undef PI64
    00066 #endif
    00067
    00068     const f64 PI64      = 3.1415926535897932384626433832795028841971693993751;
    00069
    00071     const f64 RECIPROCAL_PI64 = 1.0/PI64;
    00072
    00074     const f32 DEGTORAD = PI / 180.0f;
    00075
    00077     const f32 RADTODEG   = 180.0f / PI;
    00078
    00080     const f64 DEGTORAD64 = PI64 / 180.0;
    00081
    00083     const f64 RADTODEG64 = 180.0 / PI64;
    00084
    00086
    00089     inline f32 radToDeg(f32 radians)
    00090     {
    00091         return RADTODEG * radians;
    00092     }
    00093
    00095
    00098     inline f64 radToDeg(f64 radians)
    00099     {
    00100         return RADTODEG64 * radians;
    00101     }
    00102
    00104
    00107     inline f32 degToRad(f32 degrees)
    00108     {
    00109         return DEGTORAD * degrees;
    00110     }
    00111
    00113
    00116     inline f64 degToRad(f64 degrees)
    00117     {
    00118         return DEGTORAD64 * degrees;
    00119     }
    00120
    00122     template<class T>
    00123     inline const T& min_(const T& a, const T& b)
    00124     {
    00125         return a < b ? a : b;
    00126     }
    00127
    00129     template<class T>
    00130     inline const T& min_(const T& a, const T& b, const T& c)
    00131     {
    00132         return a < b ? min_(a, c) : min_(b, c);
    00133     }
    00134
    00136     template<class T>
    00137     inline const T& max_(const T& a, const T& b)
    00138     {
    00139         return a < b ? b : a;
    00140     }
    00141
    00143     template<class T>
    00144     inline const T& max_(const T& a, const T& b, const T& c)
    00145     {
    00146         return a < b ? max_(b, c) : max_(a, c);
    00147     }
    00148
    00150     template<class T>
    00151     inline T abs_(const T& a)
    00152     {
    00153         return a < (T)0 ? -a : a;
    00154     }
    00155
    00158     template<class T>
    00159     inline T lerp(const T& a, const T& b, const f32 t)
    00160     {
    00161         return (T)(a*(1.f-t)) + (b*t);
    00162     }
    00163
    00165     template <class T>
    00166     inline const T clamp (const T& value, const T& low, const T& high)
    00167     {
    00168         return min_ (max_(value,low), high);
    00169     }
    00170
    00172     // Note: We use the same trick as boost and use two template arguments to
    00173     // avoid ambiguity when swapping objects of an Irrlicht type that has not
    00174     // it's own swap overload. Otherwise we get conflicts with some compilers
    00175     // in combination with stl.
    00176     template <class T1, class T2>
    00177     inline void swap(T1& a, T2& b)
    00178     {
    00179         T1 c(a);
    00180         a = b;
    00181         b = c;
    00182     }
    00183
    00185     inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
    00186     {
    00187         return (a + tolerance >= b) && (a - tolerance <= b);
    00188     }
    00189
    00191     inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
    00192     {
    00193         return (a + tolerance >= b) && (a - tolerance <= b);
    00194     }
    00195
    00196     union FloatIntUnion32
    00197     {
    00198         FloatIntUnion32(float f1 = 0.0f) : f(f1) {}
    00199         // Portable sign-extraction
    00200         bool sign() const { return (i >> 31) != 0; }
    00201
    00202         irr::s32 i;
    00203         irr::f32 f;
    00204     };
    00205
    00207     //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign.
    00208     inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff)
    00209     {
    00210         // Based on the ideas and code from Bruce Dawson on
    00211         // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/
    00212         // When floats are interpreted as integers the two nearest possible float numbers differ just
    00213         // by one integer number. Also works the other way round, an integer of 1 interpreted as float
    00214         // is for example the smallest possible float number.
    00215
    00216         FloatIntUnion32 fa(a);
    00217         FloatIntUnion32 fb(b);
    00218
    00219         // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better.
    00220         if ( fa.sign() != fb.sign() )
    00221         {
    00222             // Check for equality to make sure +0==-0
    00223             if (fa.i == fb.i)
    00224                 return true;
    00225             return false;
    00226         }
    00227
    00228         // Find the difference in ULPs.
    00229         int ulpsDiff = abs_(fa.i- fb.i);
    00230         if (ulpsDiff <= maxUlpDiff)
    00231             return true;
    00232
    00233         return false;
    00234     }
    00235
    00236 #if 0
    00237
    00238     inline bool equals(const s32 a, const s32 b)
    00239     {
    00240         return (a == b);
    00241     }
    00242
    00244     inline bool equals(const u32 a, const u32 b)
    00245     {
    00246         return (a == b);
    00247     }
    00248 #endif
    00249
    00250     inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
    00251     {
    00252         return (a + tolerance >= b) && (a - tolerance <= b);
    00253     }
    00254
    00256     inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
    00257     {
    00258         return (a + tolerance >= b) && (a - tolerance <= b);
    00259     }
    00260
    00261 #ifdef __IRR_HAS_S64
    00262
    00263     inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
    00264     {
    00265         return (a + tolerance >= b) && (a - tolerance <= b);
    00266     }
    00267 #endif
    00268
    00270     inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
    00271     {
    00272         return fabs(a) <= tolerance;
    00273     }
    00274
    00276     inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
    00277     {
    00278         return fabsf(a) <= tolerance;
    00279     }
    00280
    00282     inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
    00283     {
    00284         return fabsf(a) > tolerance;
    00285     }
    00286
    00288     inline bool iszero(const s32 a, const s32 tolerance = 0)
    00289     {
    00290         return ( a & 0x7ffffff ) <= tolerance;
    00291     }
    00292
    00294     inline bool iszero(const u32 a, const u32 tolerance = 0)
    00295     {
    00296         return a <= tolerance;
    00297     }
    00298
    00299 #ifdef __IRR_HAS_S64
    00300
    00301     inline bool iszero(const s64 a, const s64 tolerance = 0)
    00302     {
    00303         return abs_(a) <= tolerance;
    00304     }
    00305 #endif
    00306
    00307     inline s32 s32_min(s32 a, s32 b)
    00308     {
    00309         const s32 mask = (a - b) >> 31;
    00310         return (a & mask) | (b & ~mask);
    00311     }
    00312
    00313     inline s32 s32_max(s32 a, s32 b)
    00314     {
    00315         const s32 mask = (a - b) >> 31;
    00316         return (b & mask) | (a & ~mask);
    00317     }
    00318
    00319     inline s32 s32_clamp (s32 value, s32 low, s32 high)
    00320     {
    00321         return s32_min(s32_max(value,low), high);
    00322     }
    00323
    00324     /*
    00325         float IEEE-754 bit represenation
    00326
    00327         0      0x00000000
    00328         1.0    0x3f800000
    00329         0.5    0x3f000000
    00330         3      0x40400000
    00331         +inf   0x7f800000
    00332         -inf   0xff800000
    00333         +NaN   0x7fc00000 or 0x7ff00000
    00334         in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
    00335     */
    00336
    00337     typedef union { u32 u; s32 s; f32 f; } inttofloat;
    00338
    00339     #define F32_AS_S32(f)       (*((s32 *) &(f)))
    00340     #define F32_AS_U32(f)       (*((u32 *) &(f)))
    00341     #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
    00342
    00343     #define F32_VALUE_0     0x00000000
    00344     #define F32_VALUE_1     0x3f800000
    00345     #define F32_SIGN_BIT        0x80000000U
    00346     #define F32_EXPON_MANTISSA  0x7FFFFFFFU
    00347
    00350 #ifdef IRRLICHT_FAST_MATH
    00351     #define IR(x)                           ((u32&)(x))
    00352 #else
    00353     inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
    00354 #endif
    00355
    00357     #define AIR(x)              (IR(x)&0x7fffffff)
    00358
    00360 #ifdef IRRLICHT_FAST_MATH
    00361     #define FR(x)                           ((f32&)(x))
    00362 #else
    00363     inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
    00364     inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
    00365 #endif
    00366
    00368     #define IEEE_1_0            0x3f800000
    00369
    00370     #define IEEE_255_0          0x437f0000
    00371
    00372 #ifdef IRRLICHT_FAST_MATH
    00373     #define F32_LOWER_0(f)      (F32_AS_U32(f) >  F32_SIGN_BIT)
    00374     #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
    00375     #define F32_GREATER_0(f)    (F32_AS_S32(f) >  F32_VALUE_0)
    00376     #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
    00377     #define F32_EQUAL_1(f)      (F32_AS_U32(f) == F32_VALUE_1)
    00378     #define F32_EQUAL_0(f)      ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
    00379
    00380     // only same sign
    00381     #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
    00382
    00383 #else
    00384
    00385     #define F32_LOWER_0(n)      ((n) <  0.0f)
    00386     #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
    00387     #define F32_GREATER_0(n)    ((n) >  0.0f)
    00388     #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
    00389     #define F32_EQUAL_1(n)      ((n) == 1.0f)
    00390     #define F32_EQUAL_0(n)      ((n) == 0.0f)
    00391     #define F32_A_GREATER_B(a,b)    ((a) > (b))
    00392 #endif
    00393
    00394
    00395 #ifndef REALINLINE
    00396     #ifdef _MSC_VER
    00397         #define REALINLINE __forceinline
    00398     #else
    00399         #define REALINLINE inline
    00400     #endif
    00401 #endif
    00402
    00403 #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
    00404
    00405     // 8-bit bools in borland builder
    00406
    00408     REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
    00409     {
    00410         return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
    00411     }
    00412
    00414     REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
    00415     {
    00416         return ( -condition >> 31 ) & a;
    00417     }
    00418 #else
    00419
    00421     REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
    00422     {
    00423         return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
    00424     }
    00425
    00427     REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
    00428     {
    00429         return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
    00430     }
    00431
    00433     REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
    00434     {
    00435         return ( -condition >> 31 ) & a;
    00436     }
    00437 #endif
    00438
    00439     /*
    00440         if (condition) state |= m; else state &= ~m;
    00441     */
    00442     REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
    00443     {
    00444         // 0, or any postive to mask
    00445         //s32 conmask = -condition >> 31;
    00446         state ^= ( ( -condition >> 31 ) ^ state ) & mask;
    00447     }
    00448
    00449     inline f32 round_( f32 x )
    00450     {
    00451         return floorf( x + 0.5f );
    00452     }
    00453
    00454     REALINLINE void clearFPUException ()
    00455     {
    00456 #ifdef IRRLICHT_FAST_MATH
    00457         return;
    00458 #ifdef feclearexcept
    00459         feclearexcept(FE_ALL_EXCEPT);
    00460 #elif defined(_MSC_VER)
    00461         __asm fnclex;
    00462 #elif defined(__GNUC__) && defined(__x86__)
    00463         __asm__ __volatile__ ("fclex \n\t");
    00464 #else
    00465 #  warn clearFPUException not supported.
    00466 #endif
    00467 #endif
    00468     }
    00469
    00470     // calculate: sqrt ( x )
    00471     REALINLINE f32 squareroot(const f32 f)
    00472     {
    00473         return sqrtf(f);
    00474     }
    00475
    00476     // calculate: sqrt ( x )
    00477     REALINLINE f64 squareroot(const f64 f)
    00478     {
    00479         return sqrt(f);
    00480     }
    00481
    00482     // calculate: sqrt ( x )
    00483     REALINLINE s32 squareroot(const s32 f)
    00484     {
    00485         return static_cast<s32>(squareroot(static_cast<f32>(f)));
    00486     }
    00487
    00488 #ifdef __IRR_HAS_S64
    00489     // calculate: sqrt ( x )
    00490     REALINLINE s64 squareroot(const s64 f)
    00491     {
    00492         return static_cast<s64>(squareroot(static_cast<f64>(f)));
    00493     }
    00494 #endif
    00495
    00496     // calculate: 1 / sqrt ( x )
    00497     REALINLINE f64 reciprocal_squareroot(const f64 x)
    00498     {
    00499         return 1.0 / sqrt(x);
    00500     }
    00501
    00502     // calculate: 1 / sqrtf ( x )
    00503     REALINLINE f32 reciprocal_squareroot(const f32 f)
    00504     {
    00505 #if defined ( IRRLICHT_FAST_MATH )
    00506     #if defined(_MSC_VER)
    00507         // SSE reciprocal square root estimate, accurate to 12 significant
    00508         // bits of the mantissa
    00509         f32 recsqrt;
    00510         __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
    00511         __asm movss recsqrt, xmm0       // return xmm0
    00512         return recsqrt;
    00513
    00514 /*
    00515         // comes from Nvidia
    00516         u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
    00517         f32 y = *(f32*)&tmp;
    00518         return y * (1.47f - 0.47f * x * y * y);
    00519 */
    00520     #else
    00521         return 1.f / sqrtf(f);
    00522     #endif
    00523 #else // no fast math
    00524         return 1.f / sqrtf(f);
    00525 #endif
    00526     }
    00527
    00528     // calculate: 1 / sqrtf( x )
    00529     REALINLINE s32 reciprocal_squareroot(const s32 x)
    00530     {
    00531         return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
    00532     }
    00533
    00534     // calculate: 1 / x
    00535     REALINLINE f32 reciprocal( const f32 f )
    00536     {
    00537 #if defined (IRRLICHT_FAST_MATH)
    00538
    00539         // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
    00540         // bi ts of the mantissa
    00541         // One Newtown-Raphson Iteration:
    00542         // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
    00543         f32 rec;
    00544         __asm rcpss xmm0, f               // xmm0 = rcpss(f)
    00545         __asm movss xmm1, f               // xmm1 = f
    00546         __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
    00547         __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
    00548         __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
    00549         __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
    00550                                           //        - f * rcpss(f) * rcpss(f)
    00551         __asm movss rec, xmm0             // return xmm0
    00552         return rec;
    00553
    00554
    00556         // instead set f to a high value to get a return value near zero..
    00557         // -1000000000000.f.. is use minus to stay negative..
    00558         // must test's here (plane.normal dot anything ) checks on <= 0.f
    00559         //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
    00560         //return 1.f / FR ( x );
    00561
    00562 #else // no fast math
    00563         return 1.f / f;
    00564 #endif
    00565     }
    00566
    00567     // calculate: 1 / x
    00568     REALINLINE f64 reciprocal ( const f64 f )
    00569     {
    00570         return 1.0 / f;
    00571     }
    00572
    00573
    00574     // calculate: 1 / x, low precision allowed
    00575     REALINLINE f32 reciprocal_approxim ( const f32 f )
    00576     {
    00577 #if defined( IRRLICHT_FAST_MATH)
    00578
    00579         // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
    00580         // bi ts of the mantissa
    00581         // One Newtown-Raphson Iteration:
    00582         // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
    00583         f32 rec;
    00584         __asm rcpss xmm0, f               // xmm0 = rcpss(f)
    00585         __asm movss xmm1, f               // xmm1 = f
    00586         __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
    00587         __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
    00588         __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
    00589         __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
    00590                                           //        - f * rcpss(f) * rcpss(f)
    00591         __asm movss rec, xmm0             // return xmm0
    00592         return rec;
    00593
    00594
    00595 /*
    00596         // SSE reciprocal estimate, accurate to 12 significant bits of
    00597         f32 rec;
    00598         __asm rcpss xmm0, f             // xmm0 = rcpss(f)
    00599         __asm movss rec , xmm0          // return xmm0
    00600         return rec;
    00601 */
    00602 /*
    00603         register u32 x = 0x7F000000 - IR ( p );
    00604         const f32 r = FR ( x );
    00605         return r * (2.0f - p * r);
    00606 */
    00607 #else // no fast math
    00608         return 1.f / f;
    00609 #endif
    00610     }
    00611
    00612
    00613     REALINLINE s32 floor32(f32 x)
    00614     {
    00615 #ifdef IRRLICHT_FAST_MATH
    00616         const f32 h = 0.5f;
    00617
    00618         s32 t;
    00619
    00620 #if defined(_MSC_VER)
    00621         __asm
    00622         {
    00623             fld x
    00624             fsub    h
    00625             fistp   t
    00626         }
    00627 #elif defined(__GNUC__)
    00628         __asm__ __volatile__ (
    00629             "fsub %2 \n\t"
    00630             "fistpl %0"
    00631             : "=m" (t)
    00632             : "t" (x), "f" (h)
    00633             : "st"
    00634             );
    00635 #else
    00636 #  warn IRRLICHT_FAST_MATH not supported.
    00637         return (s32) floorf ( x );
    00638 #endif
    00639         return t;
    00640 #else // no fast math
    00641         return (s32) floorf ( x );
    00642 #endif
    00643     }
    00644
    00645
    00646     REALINLINE s32 ceil32 ( f32 x )
    00647     {
    00648 #ifdef IRRLICHT_FAST_MATH
    00649         const f32 h = 0.5f;
    00650
    00651         s32 t;
    00652
    00653 #if defined(_MSC_VER)
    00654         __asm
    00655         {
    00656             fld x
    00657             fadd    h
    00658             fistp   t
    00659         }
    00660 #elif defined(__GNUC__)
    00661         __asm__ __volatile__ (
    00662             "fadd %2 \n\t"
    00663             "fistpl %0 \n\t"
    00664             : "=m"(t)
    00665             : "t"(x), "f"(h)
    00666             : "st"
    00667             );
    00668 #else
    00669 #  warn IRRLICHT_FAST_MATH not supported.
    00670         return (s32) ceilf ( x );
    00671 #endif
    00672         return t;
    00673 #else // not fast math
    00674         return (s32) ceilf ( x );
    00675 #endif
    00676     }
    00677
    00678
    00679
    00680     REALINLINE s32 round32(f32 x)
    00681     {
    00682 #if defined(IRRLICHT_FAST_MATH)
    00683         s32 t;
    00684
    00685 #if defined(_MSC_VER)
    00686         __asm
    00687         {
    00688             fld   x
    00689             fistp t
    00690         }
    00691 #elif defined(__GNUC__)
    00692         __asm__ __volatile__ (
    00693             "fistpl %0 \n\t"
    00694             : "=m"(t)
    00695             : "t"(x)
    00696             : "st"
    00697             );
    00698 #else
    00699 #  warn IRRLICHT_FAST_MATH not supported.
    00700         return (s32) round_(x);
    00701 #endif
    00702         return t;
    00703 #else // no fast math
    00704         return (s32) round_(x);
    00705 #endif
    00706     }
    00707
    00708     inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
    00709     {
    00710         return a > b ? (a > c ? a : c) : (b > c ? b : c);
    00711     }
    00712
    00713     inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
    00714     {
    00715         return a < b ? (a < c ? a : c) : (b < c ? b : c);
    00716     }
    00717
    00718     inline f32 fract ( f32 x )
    00719     {
    00720         return x - floorf ( x );
    00721     }
    00722
    00723 } // end namespace core
    00724 } // end namespace irr
    00725
    00726 #ifndef IRRLICHT_FAST_MATH
    00727     using irr::core::IR;
    00728     using irr::core::FR;
    00729 #endif
    00730
    00731 #endif
    00732