LCOV - code coverage report
Current view: top level - usr/include/irrlicht - irrMath.h (source / functions) Hit Total Coverage
Test: report Lines: 26 32 81.2 %
Date: 2015-07-11 18:23:49 Functions: 16 22 72.7 %

          Line data    Source code
       1             : // Copyright (C) 2002-2012 Nikolaus Gebhardt
       2             : // This file is part of the "Irrlicht Engine".
       3             : // For conditions of distribution and use, see copyright notice in irrlicht.h
       4             : 
       5             : #ifndef __IRR_MATH_H_INCLUDED__
       6             : #define __IRR_MATH_H_INCLUDED__
       7             : 
       8             : #include "IrrCompileConfig.h"
       9             : #include "irrTypes.h"
      10             : #include <math.h>
      11             : #include <float.h>
      12             : #include <stdlib.h> // for abs() etc.
      13             : #include <limits.h> // For INT_MAX / UINT_MAX
      14             : 
      15             : #if defined(_IRR_SOLARIS_PLATFORM_) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) || defined (_WIN32_WCE)
      16             :         #define sqrtf(X) (irr::f32)sqrt((irr::f64)(X))
      17             :         #define sinf(X) (irr::f32)sin((irr::f64)(X))
      18             :         #define cosf(X) (irr::f32)cos((irr::f64)(X))
      19             :         #define asinf(X) (irr::f32)asin((irr::f64)(X))
      20             :         #define acosf(X) (irr::f32)acos((irr::f64)(X))
      21             :         #define atan2f(X,Y) (irr::f32)atan2((irr::f64)(X),(irr::f64)(Y))
      22             :         #define ceilf(X) (irr::f32)ceil((irr::f64)(X))
      23             :         #define floorf(X) (irr::f32)floor((irr::f64)(X))
      24             :         #define powf(X,Y) (irr::f32)pow((irr::f64)(X),(irr::f64)(Y))
      25             :         #define fmodf(X,Y) (irr::f32)fmod((irr::f64)(X),(irr::f64)(Y))
      26             :         #define fabsf(X) (irr::f32)fabs((irr::f64)(X))
      27             :         #define logf(X) (irr::f32)log((irr::f64)(X))
      28             : #endif
      29             : 
      30             : #ifndef FLT_MAX
      31             : #define FLT_MAX 3.402823466E+38F
      32             : #endif
      33             : 
      34             : #ifndef FLT_MIN
      35             : #define FLT_MIN 1.17549435e-38F
      36             : #endif
      37             : 
      38             : namespace irr
      39             : {
      40             : namespace core
      41             : {
      42             : 
      43             :         //! Rounding error constant often used when comparing f32 values.
      44             : 
      45             :         const s32 ROUNDING_ERROR_S32 = 0;
      46             : #ifdef __IRR_HAS_S64
      47             :         const s64 ROUNDING_ERROR_S64 = 0;
      48             : #endif
      49             :         const f32 ROUNDING_ERROR_f32 = 0.000001f;
      50             :         const f64 ROUNDING_ERROR_f64 = 0.00000001;
      51             : 
      52             : #ifdef PI // make sure we don't collide with a define
      53             : #undef PI
      54             : #endif
      55             :         //! Constant for PI.
      56             :         const f32 PI            = 3.14159265359f;
      57             : 
      58             :         //! Constant for reciprocal of PI.
      59             :         const f32 RECIPROCAL_PI = 1.0f/PI;
      60             : 
      61             :         //! Constant for half of PI.
      62             :         const f32 HALF_PI       = PI/2.0f;
      63             : 
      64             : #ifdef PI64 // make sure we don't collide with a define
      65             : #undef PI64
      66             : #endif
      67             :         //! Constant for 64bit PI.
      68             :         const f64 PI64          = 3.1415926535897932384626433832795028841971693993751;
      69             : 
      70             :         //! Constant for 64bit reciprocal of PI.
      71             :         const f64 RECIPROCAL_PI64 = 1.0/PI64;
      72             : 
      73             :         //! 32bit Constant for converting from degrees to radians
      74             :         const f32 DEGTORAD = PI / 180.0f;
      75             : 
      76             :         //! 32bit constant for converting from radians to degrees (formally known as GRAD_PI)
      77             :         const f32 RADTODEG   = 180.0f / PI;
      78             : 
      79             :         //! 64bit constant for converting from degrees to radians (formally known as GRAD_PI2)
      80             :         const f64 DEGTORAD64 = PI64 / 180.0;
      81             : 
      82             :         //! 64bit constant for converting from radians to degrees
      83             :         const f64 RADTODEG64 = 180.0 / PI64;
      84             : 
      85             :         //! Utility function to convert a radian value to degrees
      86             :         /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
      87             :         \param radians  The radians value to convert to degrees.
      88             :         */
      89             :         inline f32 radToDeg(f32 radians)
      90             :         {
      91             :                 return RADTODEG * radians;
      92             :         }
      93             : 
      94             :         //! Utility function to convert a radian value to degrees
      95             :         /** Provided as it can be clearer to write radToDeg(X) than RADTODEG * X
      96             :         \param radians  The radians value to convert to degrees.
      97             :         */
      98             :         inline f64 radToDeg(f64 radians)
      99             :         {
     100             :                 return RADTODEG64 * radians;
     101             :         }
     102             : 
     103             :         //! Utility function to convert a degrees value to radians
     104             :         /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
     105             :         \param degrees  The degrees value to convert to radians.
     106             :         */
     107             :         inline f32 degToRad(f32 degrees)
     108             :         {
     109             :                 return DEGTORAD * degrees;
     110             :         }
     111             : 
     112             :         //! Utility function to convert a degrees value to radians
     113             :         /** Provided as it can be clearer to write degToRad(X) than DEGTORAD * X
     114             :         \param degrees  The degrees value to convert to radians.
     115             :         */
     116             :         inline f64 degToRad(f64 degrees)
     117             :         {
     118             :                 return DEGTORAD64 * degrees;
     119             :         }
     120             : 
     121             :         //! returns minimum of two values. Own implementation to get rid of the STL (VS6 problems)
     122             :         template<class T>
     123    27723084 :         inline const T& min_(const T& a, const T& b)
     124             :         {
     125    27723084 :                 return a < b ? a : b;
     126             :         }
     127             : 
     128             :         //! returns minimum of three values. Own implementation to get rid of the STL (VS6 problems)
     129             :         template<class T>
     130             :         inline const T& min_(const T& a, const T& b, const T& c)
     131             :         {
     132             :                 return a < b ? min_(a, c) : min_(b, c);
     133             :         }
     134             : 
     135             :         //! returns maximum of two values. Own implementation to get rid of the STL (VS6 problems)
     136             :         template<class T>
     137    27723338 :         inline const T& max_(const T& a, const T& b)
     138             :         {
     139    27723338 :                 return a < b ? b : a;
     140             :         }
     141             : 
     142             :         //! returns maximum of three values. Own implementation to get rid of the STL (VS6 problems)
     143             :         template<class T>
     144             :         inline const T& max_(const T& a, const T& b, const T& c)
     145             :         {
     146             :                 return a < b ? max_(b, c) : max_(a, c);
     147             :         }
     148             : 
     149             :         //! returns abs of two values. Own implementation to get rid of STL (VS6 problems)
     150             :         template<class T>
     151             :         inline T abs_(const T& a)
     152             :         {
     153             :                 return a < (T)0 ? -a : a;
     154             :         }
     155             : 
     156             :         //! returns linear interpolation of a and b with ratio t
     157             :         //! \return: a if t==0, b if t==1, and the linear interpolation else
     158             :         template<class T>
     159             :         inline T lerp(const T& a, const T& b, const f32 t)
     160             :         {
     161             :                 return (T)(a*(1.f-t)) + (b*t);
     162             :         }
     163             : 
     164             :         //! clamps a value between low and high
     165             :         template <class T>
     166    27723299 :         inline const T clamp (const T& value, const T& low, const T& high)
     167             :         {
     168    27723299 :                 return min_ (max_(value,low), high);
     169             :         }
     170             : 
     171             :         //! swaps the content of the passed parameters
     172             :         // Note: We use the same trick as boost and use two template arguments to
     173             :         // avoid ambiguity when swapping objects of an Irrlicht type that has not
     174             :         // it's own swap overload. Otherwise we get conflicts with some compilers
     175             :         // in combination with stl.
     176             :         template <class T1, class T2>
     177             :         inline void swap(T1& a, T2& b)
     178             :         {
     179             :                 T1 c(a);
     180             :                 a = b;
     181             :                 b = c;
     182             :         }
     183             : 
     184             :         //! returns if a equals b, taking possible rounding errors into account
     185           0 :         inline bool equals(const f64 a, const f64 b, const f64 tolerance = ROUNDING_ERROR_f64)
     186             :         {
     187           0 :                 return (a + tolerance >= b) && (a - tolerance <= b);
     188             :         }
     189             : 
     190             :         //! returns if a equals b, taking possible rounding errors into account
     191      881622 :         inline bool equals(const f32 a, const f32 b, const f32 tolerance = ROUNDING_ERROR_f32)
     192             :         {
     193      881622 :                 return (a + tolerance >= b) && (a - tolerance <= b);
     194             :         }
     195             : 
     196             :         union FloatIntUnion32
     197             :         {
     198             :                 FloatIntUnion32(float f1 = 0.0f) : f(f1) {}
     199             :                 // Portable sign-extraction
     200             :                 bool sign() const { return (i >> 31) != 0; }
     201             : 
     202             :                 irr::s32 i;
     203             :                 irr::f32 f;
     204             :         };
     205             : 
     206             :         //! We compare the difference in ULP's (spacing between floating-point numbers, aka ULP=1 means there exists no float between).
     207             :         //\result true when numbers have a ULP <= maxUlpDiff AND have the same sign.
     208             :         inline bool equalsByUlp(f32 a, f32 b, int maxUlpDiff)
     209             :         {
     210             :                 // Based on the ideas and code from Bruce Dawson on
     211             :                 // http://www.altdevblogaday.com/2012/02/22/comparing-floating-point-numbers-2012-edition/
     212             :                 // When floats are interpreted as integers the two nearest possible float numbers differ just
     213             :                 // by one integer number. Also works the other way round, an integer of 1 interpreted as float
     214             :                 // is for example the smallest possible float number.
     215             : 
     216             :                 FloatIntUnion32 fa(a);
     217             :                 FloatIntUnion32 fb(b);
     218             : 
     219             :                 // Different signs, we could maybe get difference to 0, but so close to 0 using epsilons is better.
     220             :                 if ( fa.sign() != fb.sign() )
     221             :                 {
     222             :                         // Check for equality to make sure +0==-0
     223             :                         if (fa.i == fb.i)
     224             :                                 return true;
     225             :                         return false;
     226             :                 }
     227             : 
     228             :                 // Find the difference in ULPs.
     229             :                 int ulpsDiff = abs_(fa.i- fb.i);
     230             :                 if (ulpsDiff <= maxUlpDiff)
     231             :                         return true;
     232             : 
     233             :                 return false;
     234             :         }
     235             : 
     236             : #if 0
     237             :         //! returns if a equals b, not using any rounding tolerance
     238             :         inline bool equals(const s32 a, const s32 b)
     239             :         {
     240             :                 return (a == b);
     241             :         }
     242             : 
     243             :         //! returns if a equals b, not using any rounding tolerance
     244             :         inline bool equals(const u32 a, const u32 b)
     245             :         {
     246             :                 return (a == b);
     247             :         }
     248             : #endif
     249             :         //! returns if a equals b, taking an explicit rounding tolerance into account
     250   125346872 :         inline bool equals(const s32 a, const s32 b, const s32 tolerance = ROUNDING_ERROR_S32)
     251             :         {
     252   125346872 :                 return (a + tolerance >= b) && (a - tolerance <= b);
     253             :         }
     254             : 
     255             :         //! returns if a equals b, taking an explicit rounding tolerance into account
     256        4884 :         inline bool equals(const u32 a, const u32 b, const s32 tolerance = ROUNDING_ERROR_S32)
     257             :         {
     258        4884 :                 return (a + tolerance >= b) && (a - tolerance <= b);
     259             :         }
     260             : 
     261             : #ifdef __IRR_HAS_S64
     262             :         //! returns if a equals b, taking an explicit rounding tolerance into account
     263             :         inline bool equals(const s64 a, const s64 b, const s64 tolerance = ROUNDING_ERROR_S64)
     264             :         {
     265             :                 return (a + tolerance >= b) && (a - tolerance <= b);
     266             :         }
     267             : #endif
     268             : 
     269             :         //! returns if a equals zero, taking rounding errors into account
     270             :         inline bool iszero(const f64 a, const f64 tolerance = ROUNDING_ERROR_f64)
     271             :         {
     272             :                 return fabs(a) <= tolerance;
     273             :         }
     274             : 
     275             :         //! returns if a equals zero, taking rounding errors into account
     276     1426243 :         inline bool iszero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
     277             :         {
     278     1426243 :                 return fabsf(a) <= tolerance;
     279             :         }
     280             : 
     281             :         //! returns if a equals not zero, taking rounding errors into account
     282             :         inline bool isnotzero(const f32 a, const f32 tolerance = ROUNDING_ERROR_f32)
     283             :         {
     284             :                 return fabsf(a) > tolerance;
     285             :         }
     286             : 
     287             :         //! returns if a equals zero, taking rounding errors into account
     288             :         inline bool iszero(const s32 a, const s32 tolerance = 0)
     289             :         {
     290             :                 return ( a & 0x7ffffff ) <= tolerance;
     291             :         }
     292             : 
     293             :         //! returns if a equals zero, taking rounding errors into account
     294             :         inline bool iszero(const u32 a, const u32 tolerance = 0)
     295             :         {
     296             :                 return a <= tolerance;
     297             :         }
     298             : 
     299             : #ifdef __IRR_HAS_S64
     300             :         //! returns if a equals zero, taking rounding errors into account
     301             :         inline bool iszero(const s64 a, const s64 tolerance = 0)
     302             :         {
     303             :                 return abs_(a) <= tolerance;
     304             :         }
     305             : #endif
     306             : 
     307             :         inline s32 s32_min(s32 a, s32 b)
     308             :         {
     309             :                 const s32 mask = (a - b) >> 31;
     310             :                 return (a & mask) | (b & ~mask);
     311             :         }
     312             : 
     313             :         inline s32 s32_max(s32 a, s32 b)
     314             :         {
     315             :                 const s32 mask = (a - b) >> 31;
     316             :                 return (b & mask) | (a & ~mask);
     317             :         }
     318             : 
     319             :         inline s32 s32_clamp (s32 value, s32 low, s32 high)
     320             :         {
     321             :                 return s32_min(s32_max(value,low), high);
     322             :         }
     323             : 
     324             :         /*
     325             :                 float IEEE-754 bit represenation
     326             : 
     327             :                 0      0x00000000
     328             :                 1.0    0x3f800000
     329             :                 0.5    0x3f000000
     330             :                 3      0x40400000
     331             :                 +inf   0x7f800000
     332             :                 -inf   0xff800000
     333             :                 +NaN   0x7fc00000 or 0x7ff00000
     334             :                 in general: number = (sign ? -1:1) * 2^(exponent) * 1.(mantissa bits)
     335             :         */
     336             : 
     337             :         typedef union { u32 u; s32 s; f32 f; } inttofloat;
     338             : 
     339             :         #define F32_AS_S32(f)           (*((s32 *) &(f)))
     340             :         #define F32_AS_U32(f)           (*((u32 *) &(f)))
     341             :         #define F32_AS_U32_POINTER(f)   ( ((u32 *) &(f)))
     342             : 
     343             :         #define F32_VALUE_0             0x00000000
     344             :         #define F32_VALUE_1             0x3f800000
     345             :         #define F32_SIGN_BIT            0x80000000U
     346             :         #define F32_EXPON_MANTISSA      0x7FFFFFFFU
     347             : 
     348             :         //! code is taken from IceFPU
     349             :         //! Integer representation of a floating-point value.
     350             : #ifdef IRRLICHT_FAST_MATH
     351             :         #define IR(x)                           ((u32&)(x))
     352             : #else
     353             :         inline u32 IR(f32 x) {inttofloat tmp; tmp.f=x; return tmp.u;}
     354             : #endif
     355             : 
     356             :         //! Absolute integer representation of a floating-point value
     357             :         #define AIR(x)                          (IR(x)&0x7fffffff)
     358             : 
     359             :         //! Floating-point representation of an integer value.
     360             : #ifdef IRRLICHT_FAST_MATH
     361             :         #define FR(x)                           ((f32&)(x))
     362             : #else
     363             :         inline f32 FR(u32 x) {inttofloat tmp; tmp.u=x; return tmp.f;}
     364             :         inline f32 FR(s32 x) {inttofloat tmp; tmp.s=x; return tmp.f;}
     365             : #endif
     366             : 
     367             :         //! integer representation of 1.0
     368             :         #define IEEE_1_0                        0x3f800000
     369             :         //! integer representation of 255.0
     370             :         #define IEEE_255_0                      0x437f0000
     371             : 
     372             : #ifdef IRRLICHT_FAST_MATH
     373             :         #define F32_LOWER_0(f)          (F32_AS_U32(f) >  F32_SIGN_BIT)
     374             :         #define F32_LOWER_EQUAL_0(f)    (F32_AS_S32(f) <= F32_VALUE_0)
     375             :         #define F32_GREATER_0(f)        (F32_AS_S32(f) >  F32_VALUE_0)
     376             :         #define F32_GREATER_EQUAL_0(f)  (F32_AS_U32(f) <= F32_SIGN_BIT)
     377             :         #define F32_EQUAL_1(f)          (F32_AS_U32(f) == F32_VALUE_1)
     378             :         #define F32_EQUAL_0(f)          ( (F32_AS_U32(f) & F32_EXPON_MANTISSA ) == F32_VALUE_0)
     379             : 
     380             :         // only same sign
     381             :         #define F32_A_GREATER_B(a,b)    (F32_AS_S32((a)) > F32_AS_S32((b)))
     382             : 
     383             : #else
     384             : 
     385             :         #define F32_LOWER_0(n)          ((n) <  0.0f)
     386             :         #define F32_LOWER_EQUAL_0(n)    ((n) <= 0.0f)
     387             :         #define F32_GREATER_0(n)        ((n) >  0.0f)
     388             :         #define F32_GREATER_EQUAL_0(n)  ((n) >= 0.0f)
     389             :         #define F32_EQUAL_1(n)          ((n) == 1.0f)
     390             :         #define F32_EQUAL_0(n)          ((n) == 0.0f)
     391             :         #define F32_A_GREATER_B(a,b)    ((a) > (b))
     392             : #endif
     393             : 
     394             : 
     395             : #ifndef REALINLINE
     396             :         #ifdef _MSC_VER
     397             :                 #define REALINLINE __forceinline
     398             :         #else
     399             :                 #define REALINLINE inline
     400             :         #endif
     401             : #endif
     402             : 
     403             : #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
     404             : 
     405             :         // 8-bit bools in borland builder
     406             : 
     407             :         //! conditional set based on mask and arithmetic shift
     408             :         REALINLINE u32 if_c_a_else_b ( const c8 condition, const u32 a, const u32 b )
     409             :         {
     410             :                 return ( ( -condition >> 7 ) & ( a ^ b ) ) ^ b;
     411             :         }
     412             : 
     413             :         //! conditional set based on mask and arithmetic shift
     414             :         REALINLINE u32 if_c_a_else_0 ( const c8 condition, const u32 a )
     415             :         {
     416             :                 return ( -condition >> 31 ) & a;
     417             :         }
     418             : #else
     419             : 
     420             :         //! conditional set based on mask and arithmetic shift
     421             :         REALINLINE u32 if_c_a_else_b ( const s32 condition, const u32 a, const u32 b )
     422             :         {
     423             :                 return ( ( -condition >> 31 ) & ( a ^ b ) ) ^ b;
     424             :         }
     425             : 
     426             :         //! conditional set based on mask and arithmetic shift
     427             :         REALINLINE u16 if_c_a_else_b ( const s16 condition, const u16 a, const u16 b )
     428             :         {
     429             :                 return ( ( -condition >> 15 ) & ( a ^ b ) ) ^ b;
     430             :         }
     431             : 
     432             :         //! conditional set based on mask and arithmetic shift
     433             :         REALINLINE u32 if_c_a_else_0 ( const s32 condition, const u32 a )
     434             :         {
     435             :                 return ( -condition >> 31 ) & a;
     436             :         }
     437             : #endif
     438             : 
     439             :         /*
     440             :                 if (condition) state |= m; else state &= ~m;
     441             :         */
     442             :         REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
     443             :         {
     444             :                 // 0, or any postive to mask
     445             :                 //s32 conmask = -condition >> 31;
     446             :                 state ^= ( ( -condition >> 31 ) ^ state ) & mask;
     447             :         }
     448             : 
     449    83354372 :         inline f32 round_( f32 x )
     450             :         {
     451    83354372 :                 return floorf( x + 0.5f );
     452             :         }
     453             : 
     454             :         REALINLINE void clearFPUException ()
     455             :         {
     456             : #ifdef IRRLICHT_FAST_MATH
     457             :                 return;
     458             : #ifdef feclearexcept
     459             :                 feclearexcept(FE_ALL_EXCEPT);
     460             : #elif defined(_MSC_VER)
     461             :                 __asm fnclex;
     462             : #elif defined(__GNUC__) && defined(__x86__)
     463             :                 __asm__ __volatile__ ("fclex \n\t");
     464             : #else
     465             : #  warn clearFPUException not supported.
     466             : #endif
     467             : #endif
     468             :         }
     469             : 
     470             :         // calculate: sqrt ( x )
     471     3212705 :         REALINLINE f32 squareroot(const f32 f)
     472             :         {
     473     3212705 :                 return sqrtf(f);
     474             :         }
     475             : 
     476             :         // calculate: sqrt ( x )
     477             :         REALINLINE f64 squareroot(const f64 f)
     478             :         {
     479             :                 return sqrt(f);
     480             :         }
     481             : 
     482             :         // calculate: sqrt ( x )
     483       82897 :         REALINLINE s32 squareroot(const s32 f)
     484             :         {
     485       82897 :                 return static_cast<s32>(squareroot(static_cast<f32>(f)));
     486             :         }
     487             : 
     488             : #ifdef __IRR_HAS_S64
     489             :         // calculate: sqrt ( x )
     490             :         REALINLINE s64 squareroot(const s64 f)
     491             :         {
     492             :                 return static_cast<s64>(squareroot(static_cast<f64>(f)));
     493             :         }
     494             : #endif
     495             : 
     496             :         // calculate: 1 / sqrt ( x )
     497     8866291 :         REALINLINE f64 reciprocal_squareroot(const f64 x)
     498             :         {
     499     8866291 :                 return 1.0 / sqrt(x);
     500             :         }
     501             : 
     502             :         // calculate: 1 / sqrtf ( x )
     503           0 :         REALINLINE f32 reciprocal_squareroot(const f32 f)
     504             :         {
     505             : #if defined ( IRRLICHT_FAST_MATH )
     506             :         #if defined(_MSC_VER)
     507             :                 // SSE reciprocal square root estimate, accurate to 12 significant
     508             :                 // bits of the mantissa
     509             :                 f32 recsqrt;
     510             :                 __asm rsqrtss xmm0, f           // xmm0 = rsqrtss(f)
     511             :                 __asm movss recsqrt, xmm0       // return xmm0
     512             :                 return recsqrt;
     513             : 
     514             : /*
     515             :                 // comes from Nvidia
     516             :                 u32 tmp = (u32(IEEE_1_0 << 1) + IEEE_1_0 - *(u32*)&x) >> 1;
     517             :                 f32 y = *(f32*)&tmp;
     518             :                 return y * (1.47f - 0.47f * x * y * y);
     519             : */
     520             :         #else
     521             :                 return 1.f / sqrtf(f);
     522             :         #endif
     523             : #else // no fast math
     524           0 :                 return 1.f / sqrtf(f);
     525             : #endif
     526             :         }
     527             : 
     528             :         // calculate: 1 / sqrtf( x )
     529             :         REALINLINE s32 reciprocal_squareroot(const s32 x)
     530             :         {
     531             :                 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
     532             :         }
     533             : 
     534             :         // calculate: 1 / x
     535     1426243 :         REALINLINE f32 reciprocal( const f32 f )
     536             :         {
     537             : #if defined (IRRLICHT_FAST_MATH)
     538             : 
     539             :                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
     540             :                 // bi ts of the mantissa
     541             :                 // One Newtown-Raphson Iteration:
     542             :                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
     543             :                 f32 rec;
     544             :                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
     545             :                 __asm movss xmm1, f               // xmm1 = f
     546             :                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
     547             :                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
     548             :                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
     549             :                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
     550             :                                                                                   //        - f * rcpss(f) * rcpss(f)
     551             :                 __asm movss rec, xmm0             // return xmm0
     552             :                 return rec;
     553             : 
     554             : 
     555             :                 //! i do not divide through 0.. (fpu expection)
     556             :                 // instead set f to a high value to get a return value near zero..
     557             :                 // -1000000000000.f.. is use minus to stay negative..
     558             :                 // must test's here (plane.normal dot anything ) checks on <= 0.f
     559             :                 //u32 x = (-(AIR(f) != 0 ) >> 31 ) & ( IR(f) ^ 0xd368d4a5 ) ^ 0xd368d4a5;
     560             :                 //return 1.f / FR ( x );
     561             : 
     562             : #else // no fast math
     563     1426243 :                 return 1.f / f;
     564             : #endif
     565             :         }
     566             : 
     567             :         // calculate: 1 / x
     568             :         REALINLINE f64 reciprocal ( const f64 f )
     569             :         {
     570             :                 return 1.0 / f;
     571             :         }
     572             : 
     573             : 
     574             :         // calculate: 1 / x, low precision allowed
     575             :         REALINLINE f32 reciprocal_approxim ( const f32 f )
     576             :         {
     577             : #if defined( IRRLICHT_FAST_MATH)
     578             : 
     579             :                 // SSE Newton-Raphson reciprocal estimate, accurate to 23 significant
     580             :                 // bi ts of the mantissa
     581             :                 // One Newtown-Raphson Iteration:
     582             :                 // f(i+1) = 2 * rcpss(f) - f * rcpss(f) * rcpss(f)
     583             :                 f32 rec;
     584             :                 __asm rcpss xmm0, f               // xmm0 = rcpss(f)
     585             :                 __asm movss xmm1, f               // xmm1 = f
     586             :                 __asm mulss xmm1, xmm0            // xmm1 = f * rcpss(f)
     587             :                 __asm mulss xmm1, xmm0            // xmm2 = f * rcpss(f) * rcpss(f)
     588             :                 __asm addss xmm0, xmm0            // xmm0 = 2 * rcpss(f)
     589             :                 __asm subss xmm0, xmm1            // xmm0 = 2 * rcpss(f)
     590             :                                                                                   //        - f * rcpss(f) * rcpss(f)
     591             :                 __asm movss rec, xmm0             // return xmm0
     592             :                 return rec;
     593             : 
     594             : 
     595             : /*
     596             :                 // SSE reciprocal estimate, accurate to 12 significant bits of
     597             :                 f32 rec;
     598             :                 __asm rcpss xmm0, f             // xmm0 = rcpss(f)
     599             :                 __asm movss rec , xmm0          // return xmm0
     600             :                 return rec;
     601             : */
     602             : /*
     603             :                 register u32 x = 0x7F000000 - IR ( p );
     604             :                 const f32 r = FR ( x );
     605             :                 return r * (2.0f - p * r);
     606             : */
     607             : #else // no fast math
     608             :                 return 1.f / f;
     609             : #endif
     610             :         }
     611             : 
     612             : 
     613           0 :         REALINLINE s32 floor32(f32 x)
     614             :         {
     615             : #ifdef IRRLICHT_FAST_MATH
     616             :                 const f32 h = 0.5f;
     617             : 
     618             :                 s32 t;
     619             : 
     620             : #if defined(_MSC_VER)
     621             :                 __asm
     622             :                 {
     623             :                         fld     x
     624             :                         fsub    h
     625             :                         fistp   t
     626             :                 }
     627             : #elif defined(__GNUC__)
     628             :                 __asm__ __volatile__ (
     629             :                         "fsub %2 \n\t"
     630             :                         "fistpl %0"
     631             :                         : "=m" (t)
     632             :                         : "t" (x), "f" (h)
     633             :                         : "st"
     634             :                         );
     635             : #else
     636             : #  warn IRRLICHT_FAST_MATH not supported.
     637             :                 return (s32) floorf ( x );
     638             : #endif
     639             :                 return t;
     640             : #else // no fast math
     641           0 :                 return (s32) floorf ( x );
     642             : #endif
     643             :         }
     644             : 
     645             : 
     646             :         REALINLINE s32 ceil32 ( f32 x )
     647             :         {
     648             : #ifdef IRRLICHT_FAST_MATH
     649             :                 const f32 h = 0.5f;
     650             : 
     651             :                 s32 t;
     652             : 
     653             : #if defined(_MSC_VER)
     654             :                 __asm
     655             :                 {
     656             :                         fld     x
     657             :                         fadd    h
     658             :                         fistp   t
     659             :                 }
     660             : #elif defined(__GNUC__)
     661             :                 __asm__ __volatile__ (
     662             :                         "fadd %2 \n\t"
     663             :                         "fistpl %0 \n\t"
     664             :                         : "=m"(t)
     665             :                         : "t"(x), "f"(h)
     666             :                         : "st"
     667             :                         );
     668             : #else
     669             : #  warn IRRLICHT_FAST_MATH not supported.
     670             :                 return (s32) ceilf ( x );
     671             : #endif
     672             :                 return t;
     673             : #else // not fast math
     674             :                 return (s32) ceilf ( x );
     675             : #endif
     676             :         }
     677             : 
     678             : 
     679             : 
     680    83354378 :         REALINLINE s32 round32(f32 x)
     681             :         {
     682             : #if defined(IRRLICHT_FAST_MATH)
     683             :                 s32 t;
     684             : 
     685             : #if defined(_MSC_VER)
     686             :                 __asm
     687             :                 {
     688             :                         fld   x
     689             :                         fistp t
     690             :                 }
     691             : #elif defined(__GNUC__)
     692             :                 __asm__ __volatile__ (
     693             :                         "fistpl %0 \n\t"
     694             :                         : "=m"(t)
     695             :                         : "t"(x)
     696             :                         : "st"
     697             :                         );
     698             : #else
     699             : #  warn IRRLICHT_FAST_MATH not supported.
     700             :                 return (s32) round_(x);
     701             : #endif
     702             :                 return t;
     703             : #else // no fast math
     704    83354378 :                 return (s32) round_(x);
     705             : #endif
     706             :         }
     707             : 
     708             :         inline f32 f32_max3(const f32 a, const f32 b, const f32 c)
     709             :         {
     710             :                 return a > b ? (a > c ? a : c) : (b > c ? b : c);
     711             :         }
     712             : 
     713             :         inline f32 f32_min3(const f32 a, const f32 b, const f32 c)
     714             :         {
     715             :                 return a < b ? (a < c ? a : c) : (b < c ? b : c);
     716             :         }
     717             : 
     718             :         inline f32 fract ( f32 x )
     719             :         {
     720             :                 return x - floorf ( x );
     721             :         }
     722             : 
     723             : } // end namespace core
     724             : } // end namespace irr
     725             : 
     726             : #ifndef IRRLICHT_FAST_MATH
     727             :         using irr::core::IR;
     728             :         using irr::core::FR;
     729             : #endif
     730             : 
     731             : #endif
     732             : 

Generated by: LCOV version 1.11