Blender V2.61 - r43446

btScalar.h

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2003-2009 Erwin Coumans  http://bullet.googlecode.com
00003 
00004 This software is provided 'as-is', without any express or implied warranty.
00005 In no event will the authors be held liable for any damages arising from the use of this software.
00006 Permission is granted to anyone to use this software for any purpose, 
00007 including commercial applications, and to alter it and redistribute it freely, 
00008 subject to the following restrictions:
00009 
00010 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00011 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00012 3. This notice may not be removed or altered from any source distribution.
00013 */
00014 
00015 
00016 
00017 #ifndef SIMD___SCALAR_H
00018 #define SIMD___SCALAR_H
00019 
00020 #ifdef BT_MANAGED_CODE
00021 //Aligned data types not supported in managed code
00022 #pragma unmanaged
00023 #endif
00024 
00025 
00026 #include <math.h>
00027 #include <stdlib.h>//size_t for MSVC 6.0
00028 #include <cstdlib>
00029 #include <cfloat>
00030 #include <float.h>
00031 
00032 /* SVN $Revision: 35500 $ on $Date: 2011-03-12 21:34:17 +0100 (Sat, 12 Mar 2011) $ from http://bullet.googlecode.com*/
00033 #define BT_BULLET_VERSION 278
00034 
00035 inline int  btGetVersion()
00036 {
00037     return BT_BULLET_VERSION;
00038 }
00039 
00040 #if defined(DEBUG) || defined (_DEBUG)
00041 #define BT_DEBUG
00042 #endif
00043 
00044 
00045 #ifdef _WIN32
00046 
00047         #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
00048 
00049             #define SIMD_FORCE_INLINE inline
00050             #define ATTRIBUTE_ALIGNED16(a) a
00051             #define ATTRIBUTE_ALIGNED64(a) a
00052             #define ATTRIBUTE_ALIGNED128(a) a
00053         #else
00054             //#define BT_HAS_ALIGNED_ALLOCATOR
00055             #pragma warning(disable : 4324) // disable padding warning
00056 //          #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
00057 //          #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
00058 //          #pragma warning(disable:4786) // Disable the "debug name too long" warning
00059 
00060             #define SIMD_FORCE_INLINE __forceinline
00061             #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
00062             #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
00063             #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
00064         #ifdef _XBOX
00065             #define BT_USE_VMX128
00066 
00067             #include <ppcintrinsics.h>
00068             #define BT_HAVE_NATIVE_FSEL
00069             #define btFsel(a,b,c) __fsel((a),(b),(c))
00070         #else
00071 
00072 #if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
00073             #define BT_USE_SSE
00074             #include <emmintrin.h>
00075 #endif
00076 
00077         #endif//_XBOX
00078 
00079         #endif //__MINGW32__
00080 
00081         #include <assert.h>
00082 #ifdef BT_DEBUG
00083         #define btAssert assert
00084 #else
00085         #define btAssert(x)
00086 #endif
00087         //btFullAssert is optional, slows down a lot
00088         #define btFullAssert(x)
00089 
00090         #define btLikely(_c)  _c
00091         #define btUnlikely(_c) _c
00092 
00093 #else
00094     
00095 #if defined (__CELLOS_LV2__)
00096         #define SIMD_FORCE_INLINE inline __attribute__((always_inline))
00097         #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
00098         #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
00099         #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
00100         #ifndef assert
00101         #include <assert.h>
00102         #endif
00103 #ifdef BT_DEBUG
00104 #ifdef __SPU__
00105 #include <spu_printf.h>
00106 #define printf spu_printf
00107     #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
00108 #else
00109     #define btAssert assert
00110 #endif
00111     
00112 #else
00113         #define btAssert(x)
00114 #endif
00115         //btFullAssert is optional, slows down a lot
00116         #define btFullAssert(x)
00117 
00118         #define btLikely(_c)  _c
00119         #define btUnlikely(_c) _c
00120 
00121 #else
00122 
00123 #ifdef USE_LIBSPE2
00124 
00125         #define SIMD_FORCE_INLINE __inline
00126         #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
00127         #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
00128         #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
00129         #ifndef assert
00130         #include <assert.h>
00131         #endif
00132 #ifdef BT_DEBUG
00133         #define btAssert assert
00134 #else
00135         #define btAssert(x)
00136 #endif
00137         //btFullAssert is optional, slows down a lot
00138         #define btFullAssert(x)
00139 
00140 
00141         #define btLikely(_c)   __builtin_expect((_c), 1)
00142         #define btUnlikely(_c) __builtin_expect((_c), 0)
00143         
00144 
00145 #else
00146     //non-windows systems
00147 
00148 #if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION)))
00149     #define BT_USE_SSE
00150     #include <emmintrin.h>
00151 
00152     #define SIMD_FORCE_INLINE inline
00153 
00154     #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
00155     #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
00156     #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
00157     #ifndef assert
00158     #include <assert.h>
00159     #endif
00160 
00161     #if defined(DEBUG) || defined (_DEBUG)
00162         #define btAssert assert
00163     #else
00164         #define btAssert(x)
00165     #endif
00166 
00167     //btFullAssert is optional, slows down a lot
00168     #define btFullAssert(x)
00169     #define btLikely(_c)  _c
00170     #define btUnlikely(_c) _c
00171 
00172 #else
00173 
00174         #define SIMD_FORCE_INLINE inline
00175 
00176 
00177 
00178 
00179         #define ATTRIBUTE_ALIGNED16(a) a
00180         #define ATTRIBUTE_ALIGNED64(a) a
00181         #define ATTRIBUTE_ALIGNED128(a) a
00182         #ifndef assert
00183         #include <assert.h>
00184         #endif
00185 
00186 #if defined(DEBUG) || defined (_DEBUG)
00187         #define btAssert assert
00188 #else
00189         #define btAssert(x)
00190 #endif
00191 
00192         //btFullAssert is optional, slows down a lot
00193         #define btFullAssert(x)
00194         #define btLikely(_c)  _c
00195         #define btUnlikely(_c) _c
00196 #endif //__APPLE__ 
00197 
00198 #endif // LIBSPE2
00199 
00200 #endif  //__CELLOS_LV2__
00201 #endif
00202 
00203 
00205 #if defined(BT_USE_DOUBLE_PRECISION)
00206 typedef double btScalar;
00207 //this number could be bigger in double precision
00208 #define BT_LARGE_FLOAT 1e30
00209 #else
00210 typedef float btScalar;
00211 //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
00212 #define BT_LARGE_FLOAT 1e18f
00213 #endif
00214 
00215 
00216 
00217 #define BT_DECLARE_ALIGNED_ALLOCATOR() \
00218    SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
00219    SIMD_FORCE_INLINE void  operator delete(void* ptr)         { btAlignedFree(ptr); }   \
00220    SIMD_FORCE_INLINE void* operator new(size_t, void* ptr)   { return ptr; }   \
00221    SIMD_FORCE_INLINE void  operator delete(void*, void*)      { }   \
00222    SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
00223    SIMD_FORCE_INLINE void  operator delete[](void* ptr)         { btAlignedFree(ptr); }   \
00224    SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr)   { return ptr; }   \
00225    SIMD_FORCE_INLINE void  operator delete[](void*, void*)      { }   \
00226 
00227 
00228 
00229 #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
00230         
00231 SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
00232 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
00233 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
00234 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
00235 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
00236 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1))  x=btScalar(1); return acos(x); }
00237 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1))  x=btScalar(1); return asin(x); }
00238 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
00239 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
00240 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
00241 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
00242 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
00243 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }
00244 
00245 #else
00246         
00247 SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 
00248 { 
00249 #ifdef USE_APPROXIMATION
00250     double x, z, tempf;
00251     unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
00252 
00253     tempf = y;
00254     *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
00255     x =  tempf;
00256     z =  y*btScalar(0.5);
00257     x = (btScalar(1.5)*x)-(x*x)*(x*z);         /* iteration formula     */
00258     x = (btScalar(1.5)*x)-(x*x)*(x*z);
00259     x = (btScalar(1.5)*x)-(x*x)*(x*z);
00260     x = (btScalar(1.5)*x)-(x*x)*(x*z);
00261     x = (btScalar(1.5)*x)-(x*x)*(x*z);
00262     return x*y;
00263 #else
00264     return sqrtf(y); 
00265 #endif
00266 }
00267 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
00268 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
00269 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
00270 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
00271 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 
00272     if (x<btScalar(-1)) 
00273         x=btScalar(-1); 
00274     if (x>btScalar(1))  
00275         x=btScalar(1);
00276     return acosf(x); 
00277 }
00278 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 
00279     if (x<btScalar(-1)) 
00280         x=btScalar(-1); 
00281     if (x>btScalar(1))  
00282         x=btScalar(1);
00283     return asinf(x); 
00284 }
00285 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
00286 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
00287 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
00288 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
00289 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); }
00290 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
00291     
00292 #endif
00293 
00294 #define SIMD_2_PI         btScalar(6.283185307179586232)
00295 #define SIMD_PI           (SIMD_2_PI * btScalar(0.5))
00296 #define SIMD_HALF_PI      (SIMD_2_PI * btScalar(0.25))
00297 #define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
00298 #define SIMD_DEGS_PER_RAD  (btScalar(360.0) / SIMD_2_PI)
00299 #define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
00300 
00301 #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x))))      /* reciprocal square root */
00302 
00303 
00304 #ifdef BT_USE_DOUBLE_PRECISION
00305 #define SIMD_EPSILON      DBL_EPSILON
00306 #define SIMD_INFINITY     DBL_MAX
00307 #else
00308 #define SIMD_EPSILON      FLT_EPSILON
00309 #define SIMD_INFINITY     FLT_MAX
00310 #endif
00311 
00312 SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 
00313 {
00314     btScalar coeff_1 = SIMD_PI / 4.0f;
00315     btScalar coeff_2 = 3.0f * coeff_1;
00316     btScalar abs_y = btFabs(y);
00317     btScalar angle;
00318     if (x >= 0.0f) {
00319         btScalar r = (x - abs_y) / (x + abs_y);
00320         angle = coeff_1 - coeff_1 * r;
00321     } else {
00322         btScalar r = (x + abs_y) / (abs_y - x);
00323         angle = coeff_2 - coeff_1 * r;
00324     }
00325     return (y < 0.0f) ? -angle : angle;
00326 }
00327 
00328 SIMD_FORCE_INLINE bool      btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
00329 
00330 SIMD_FORCE_INLINE bool  btEqual(btScalar a, btScalar eps) {
00331     return (((a) <= eps) && !((a) < -eps));
00332 }
00333 SIMD_FORCE_INLINE bool  btGreaterEqual (btScalar a, btScalar eps) {
00334     return (!((a) <= eps));
00335 }
00336 
00337 
00338 SIMD_FORCE_INLINE int       btIsNegative(btScalar x) {
00339     return x < btScalar(0.0) ? 1 : 0;
00340 }
00341 
00342 SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
00343 SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
00344 
00345 #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
00346 
00347 #ifndef btFsel
00348 SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
00349 {
00350     return a >= 0 ? b : c;
00351 }
00352 #endif
00353 #define btFsels(a,b,c) (btScalar)btFsel(a,b,c)
00354 
00355 
00356 SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
00357 {
00358    long int i = 1;
00359    const char *p = (const char *) &i;
00360    if (p[0] == 1)  // Lowest address contains the least significant byte
00361        return true;
00362    else
00363        return false;
00364 }
00365 
00366 
00367 
00370 SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 
00371 {
00372     // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
00373     // Rely on positive value or'ed with its negative having sign bit on
00374     // and zero value or'ed with its negative (which is still zero) having sign bit off 
00375     // Use arithmetic shift right, shifting the sign bit through all 32 bits
00376     unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
00377     unsigned testEqz = ~testNz;
00378     return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 
00379 }
00380 SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
00381 {
00382     unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
00383     unsigned testEqz = ~testNz; 
00384     return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
00385 }
00386 SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
00387 {
00388 #ifdef BT_HAVE_NATIVE_FSEL
00389     return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
00390 #else
00391     return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 
00392 #endif
00393 }
00394 
00395 template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b)
00396 {
00397     T tmp = a;
00398     a = b;
00399     b = tmp;
00400 }
00401 
00402 
00403 //PCK: endian swapping functions
00404 SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
00405 {
00406     return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8)  | ((val & 0x000000ff) << 24));
00407 }
00408 
00409 SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
00410 {
00411     return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
00412 }
00413 
00414 SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
00415 {
00416     return btSwapEndian((unsigned)val);
00417 }
00418 
00419 SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
00420 {
00421     return btSwapEndian((unsigned short) val);
00422 }
00423 
00430 SIMD_FORCE_INLINE unsigned int  btSwapEndianFloat(float d)
00431 {
00432     unsigned int a = 0;
00433     unsigned char *dst = (unsigned char *)&a;
00434     unsigned char *src = (unsigned char *)&d;
00435 
00436     dst[0] = src[3];
00437     dst[1] = src[2];
00438     dst[2] = src[1];
00439     dst[3] = src[0];
00440     return a;
00441 }
00442 
00443 // unswap using char pointers
00444 SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 
00445 {
00446     float d = 0.0f;
00447     unsigned char *src = (unsigned char *)&a;
00448     unsigned char *dst = (unsigned char *)&d;
00449 
00450     dst[0] = src[3];
00451     dst[1] = src[2];
00452     dst[2] = src[1];
00453     dst[3] = src[0];
00454 
00455     return d;
00456 }
00457 
00458 
00459 // swap using char pointers
00460 SIMD_FORCE_INLINE void  btSwapEndianDouble(double d, unsigned char* dst)
00461 {
00462     unsigned char *src = (unsigned char *)&d;
00463 
00464     dst[0] = src[7];
00465     dst[1] = src[6];
00466     dst[2] = src[5];
00467     dst[3] = src[4];
00468     dst[4] = src[3];
00469     dst[5] = src[2];
00470     dst[6] = src[1];
00471     dst[7] = src[0];
00472 
00473 }
00474 
00475 // unswap using char pointers
00476 SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 
00477 {
00478     double d = 0.0;
00479     unsigned char *dst = (unsigned char *)&d;
00480 
00481     dst[0] = src[7];
00482     dst[1] = src[6];
00483     dst[2] = src[5];
00484     dst[3] = src[4];
00485     dst[4] = src[3];
00486     dst[5] = src[2];
00487     dst[6] = src[1];
00488     dst[7] = src[0];
00489 
00490     return d;
00491 }
00492 
00493 // returns normalized value in range [-SIMD_PI, SIMD_PI]
00494 SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 
00495 {
00496     angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
00497     if(angleInRadians < -SIMD_PI)
00498     {
00499         return angleInRadians + SIMD_2_PI;
00500     }
00501     else if(angleInRadians > SIMD_PI)
00502     {
00503         return angleInRadians - SIMD_2_PI;
00504     }
00505     else
00506     {
00507         return angleInRadians;
00508     }
00509 }
00510 
00512 struct btTypedObject
00513 {
00514     btTypedObject(int objectType)
00515         :m_objectType(objectType)
00516     {
00517     }
00518     int m_objectType;
00519     inline int getObjectType() const
00520     {
00521         return m_objectType;
00522     }
00523 };
00524 #endif //SIMD___SCALAR_H