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