00001
00002
00003
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>
00013 #include <limits.h>
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
00259
00260
00261
00262
00263
00264
00265
00266
00267
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
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
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
00374
00375 REALINLINE void setbit_cond ( u32 &state, s32 condition, u32 mask )
00376 {
00377
00378
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
00404 REALINLINE f32 squareroot(const f32 f)
00405 {
00406 return sqrtf(f);
00407 }
00408
00409
00410 REALINLINE f64 squareroot(const f64 f)
00411 {
00412 return sqrt(f);
00413 }
00414
00415
00416 REALINLINE s32 squareroot(const s32 f)
00417 {
00418 return static_cast<s32>(squareroot(static_cast<f32>(f)));
00419 }
00420
00421
00422 REALINLINE f64 reciprocal_squareroot(const f64 x)
00423 {
00424 return 1.0 / sqrt(x);
00425 }
00426
00427
00428 REALINLINE f32 reciprocal_squareroot(const f32 f)
00429 {
00430 #if defined ( IRRLICHT_FAST_MATH )
00431 #if defined(_MSC_VER)
00432
00433
00434 f32 recsqrt;
00435 __asm rsqrtss xmm0, f
00436 __asm movss recsqrt, xmm0
00437 return recsqrt;
00438
00439
00440
00441
00442
00443
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
00454 REALINLINE s32 reciprocal_squareroot(const s32 x)
00455 {
00456 return static_cast<s32>(reciprocal_squareroot(static_cast<f32>(x)));
00457 }
00458
00459
00460 REALINLINE f32 reciprocal( const f32 f )
00461 {
00462 #if defined (IRRLICHT_FAST_MATH)
00463
00464
00465
00466
00467
00468 f32 rec;
00469 __asm rcpss xmm0, f
00470 __asm movss xmm1, f
00471 __asm mulss xmm1, xmm0
00472 __asm mulss xmm1, xmm0
00473 __asm addss xmm0, xmm0
00474 __asm subss xmm0, xmm1
00475
00476 __asm movss rec, xmm0
00477 return rec;
00478
00479
00481
00482
00483
00484
00485
00486
00487 #else // no fast math
00488 return 1.f / f;
00489 #endif
00490 }
00491
00492
00493 REALINLINE f64 reciprocal ( const f64 f )
00494 {
00495 return 1.0 / f;
00496 }
00497
00498
00499
00500 REALINLINE f32 reciprocal_approxim ( const f32 f )
00501 {
00502 #if defined( IRRLICHT_FAST_MATH)
00503
00504
00505
00506
00507
00508 f32 rec;
00509 __asm rcpss xmm0, f
00510 __asm movss xmm1, f
00511 __asm mulss xmm1, xmm0
00512 __asm mulss xmm1, xmm0
00513 __asm addss xmm0, xmm0
00514 __asm subss xmm0, xmm1
00515
00516 __asm movss rec, xmm0
00517 return rec;
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
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 }
00649 }
00650
00651 #ifndef IRRLICHT_FAST_MATH
00652 using irr::core::IR;
00653 using irr::core::FR;
00654 #endif
00655
00656 #endif
00657