$search
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$ on $Date$ from http://bullet.googlecode.com*/ 00033 #define BT_BULLET_VERSION 276 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 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 #define btAssert assert 00105 #else 00106 #define btAssert(x) 00107 #endif 00108 //btFullAssert is optional, slows down a lot 00109 #define btFullAssert(x) 00110 00111 #define btLikely(_c) _c 00112 #define btUnlikely(_c) _c 00113 00114 #else 00115 00116 #ifdef USE_LIBSPE2 00117 00118 #define SIMD_FORCE_INLINE __inline 00119 #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 00120 #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 00121 #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 00122 #ifndef assert 00123 #include <assert.h> 00124 #endif 00125 #ifdef BT_DEBUG 00126 #define btAssert assert 00127 #else 00128 #define btAssert(x) 00129 #endif 00130 //btFullAssert is optional, slows down a lot 00131 #define btFullAssert(x) 00132 00133 00134 #define btLikely(_c) __builtin_expect((_c), 1) 00135 #define btUnlikely(_c) __builtin_expect((_c), 0) 00136 00137 00138 #else 00139 //non-windows systems 00140 00141 #if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION))) 00142 #define BT_USE_SSE 00143 #include <emmintrin.h> 00144 00145 #define SIMD_FORCE_INLINE inline 00146 00147 #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 00148 #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 00149 #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 00150 #ifndef assert 00151 #include <assert.h> 00152 #endif 00153 00154 #if defined(DEBUG) || defined (_DEBUG) 00155 #define btAssert assert 00156 #else 00157 #define btAssert(x) 00158 #endif 00159 00160 //btFullAssert is optional, slows down a lot 00161 #define btFullAssert(x) 00162 #define btLikely(_c) _c 00163 #define btUnlikely(_c) _c 00164 00165 #else 00166 00167 #define SIMD_FORCE_INLINE inline 00168 00169 00170 00171 00172 #define ATTRIBUTE_ALIGNED16(a) a 00173 #define ATTRIBUTE_ALIGNED64(a) a 00174 #define ATTRIBUTE_ALIGNED128(a) a 00175 #ifndef assert 00176 #include <assert.h> 00177 #endif 00178 00179 #if defined(DEBUG) || defined (_DEBUG) 00180 #define btAssert assert 00181 #else 00182 #define btAssert(x) 00183 #endif 00184 00185 //btFullAssert is optional, slows down a lot 00186 #define btFullAssert(x) 00187 #define btLikely(_c) _c 00188 #define btUnlikely(_c) _c 00189 #endif //__APPLE__ 00190 00191 #endif // LIBSPE2 00192 00193 #endif //__CELLOS_LV2__ 00194 #endif 00195 00196 00198 #if defined(BT_USE_DOUBLE_PRECISION) 00199 typedef double btScalar; 00200 //this number could be bigger in double precision 00201 #define BT_LARGE_FLOAT 1e30 00202 #else 00203 typedef float btScalar; 00204 //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX 00205 #define BT_LARGE_FLOAT 1e18f 00206 #endif 00207 00208 00209 00210 #define BT_DECLARE_ALIGNED_ALLOCATOR() \ 00211 SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 00212 SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ 00213 SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ 00214 SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ 00215 SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 00216 SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ 00217 SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ 00218 SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ 00219 00220 00221 00222 #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) 00223 00224 SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } 00225 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } 00226 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } 00227 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } 00228 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } 00229 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1)) x=btScalar(1); return acos(x); } 00230 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1)) x=btScalar(1); return asin(x); } 00231 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } 00232 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } 00233 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } 00234 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } 00235 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } 00236 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); } 00237 00238 #else 00239 00240 SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 00241 { 00242 #ifdef USE_APPROXIMATION 00243 double x, z, tempf; 00244 unsigned long *tfptr = ((unsigned long *)&tempf) + 1; 00245 00246 tempf = y; 00247 *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ 00248 x = tempf; 00249 z = y*btScalar(0.5); /* hoist out the “/2” */ 00250 x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ 00251 x = (btScalar(1.5)*x)-(x*x)*(x*z); 00252 x = (btScalar(1.5)*x)-(x*x)*(x*z); 00253 x = (btScalar(1.5)*x)-(x*x)*(x*z); 00254 x = (btScalar(1.5)*x)-(x*x)*(x*z); 00255 return x*y; 00256 #else 00257 return sqrtf(y); 00258 #endif 00259 } 00260 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } 00261 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } 00262 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } 00263 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } 00264 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 00265 if (x<btScalar(-1)) 00266 x=btScalar(-1); 00267 if (x>btScalar(1)) 00268 x=btScalar(1); 00269 return acosf(x); 00270 } 00271 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 00272 if (x<btScalar(-1)) 00273 x=btScalar(-1); 00274 if (x>btScalar(1)) 00275 x=btScalar(1); 00276 return asinf(x); 00277 } 00278 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } 00279 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } 00280 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } 00281 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } 00282 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } 00283 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); } 00284 00285 #endif 00286 00287 #define SIMD_2_PI btScalar(6.283185307179586232) 00288 #define SIMD_PI (SIMD_2_PI * btScalar(0.5)) 00289 #define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25)) 00290 #define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) 00291 #define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) 00292 #define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) 00293 00294 #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ 00295 00296 00297 #ifdef BT_USE_DOUBLE_PRECISION 00298 #define SIMD_EPSILON DBL_EPSILON 00299 #define SIMD_INFINITY DBL_MAX 00300 #else 00301 #define SIMD_EPSILON FLT_EPSILON 00302 #define SIMD_INFINITY FLT_MAX 00303 #endif 00304 00305 SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 00306 { 00307 btScalar coeff_1 = SIMD_PI / 4.0f; 00308 btScalar coeff_2 = 3.0f * coeff_1; 00309 btScalar abs_y = btFabs(y); 00310 btScalar angle; 00311 if (x >= 0.0f) { 00312 btScalar r = (x - abs_y) / (x + abs_y); 00313 angle = coeff_1 - coeff_1 * r; 00314 } else { 00315 btScalar r = (x + abs_y) / (abs_y - x); 00316 angle = coeff_2 - coeff_1 * r; 00317 } 00318 return (y < 0.0f) ? -angle : angle; 00319 } 00320 00321 SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } 00322 00323 SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { 00324 return (((a) <= eps) && !((a) < -eps)); 00325 } 00326 SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { 00327 return (!((a) <= eps)); 00328 } 00329 00330 00331 SIMD_FORCE_INLINE int btIsNegative(btScalar x) { 00332 return x < btScalar(0.0) ? 1 : 0; 00333 } 00334 00335 SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } 00336 SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } 00337 00338 #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name 00339 00340 #ifndef btFsel 00341 SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) 00342 { 00343 return a >= 0 ? b : c; 00344 } 00345 #endif 00346 #define btFsels(a,b,c) (btScalar)btFsel(a,b,c) 00347 00348 00349 SIMD_FORCE_INLINE bool btMachineIsLittleEndian() 00350 { 00351 long int i = 1; 00352 const char *p = (const char *) &i; 00353 if (p[0] == 1) // Lowest address contains the least significant byte 00354 return true; 00355 else 00356 return false; 00357 } 00358 00359 00360 00363 SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 00364 { 00365 // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero 00366 // Rely on positive value or'ed with its negative having sign bit on 00367 // and zero value or'ed with its negative (which is still zero) having sign bit off 00368 // Use arithmetic shift right, shifting the sign bit through all 32 bits 00369 unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 00370 unsigned testEqz = ~testNz; 00371 return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 00372 } 00373 SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) 00374 { 00375 unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 00376 unsigned testEqz = ~testNz; 00377 return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 00378 } 00379 SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) 00380 { 00381 #ifdef BT_HAVE_NATIVE_FSEL 00382 return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); 00383 #else 00384 return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 00385 #endif 00386 } 00387 00388 template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b) 00389 { 00390 T tmp = a; 00391 a = b; 00392 b = tmp; 00393 } 00394 00395 00396 //PCK: endian swapping functions 00397 SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) 00398 { 00399 return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); 00400 } 00401 00402 SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) 00403 { 00404 return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); 00405 } 00406 00407 SIMD_FORCE_INLINE unsigned btSwapEndian(int val) 00408 { 00409 return btSwapEndian((unsigned)val); 00410 } 00411 00412 SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) 00413 { 00414 return btSwapEndian((unsigned short) val); 00415 } 00416 00423 SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) 00424 { 00425 unsigned int a = 0; 00426 unsigned char *dst = (unsigned char *)&a; 00427 unsigned char *src = (unsigned char *)&d; 00428 00429 dst[0] = src[3]; 00430 dst[1] = src[2]; 00431 dst[2] = src[1]; 00432 dst[3] = src[0]; 00433 return a; 00434 } 00435 00436 // unswap using char pointers 00437 SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 00438 { 00439 float d = 0.0f; 00440 unsigned char *src = (unsigned char *)&a; 00441 unsigned char *dst = (unsigned char *)&d; 00442 00443 dst[0] = src[3]; 00444 dst[1] = src[2]; 00445 dst[2] = src[1]; 00446 dst[3] = src[0]; 00447 00448 return d; 00449 } 00450 00451 00452 // swap using char pointers 00453 SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) 00454 { 00455 unsigned char *src = (unsigned char *)&d; 00456 00457 dst[0] = src[7]; 00458 dst[1] = src[6]; 00459 dst[2] = src[5]; 00460 dst[3] = src[4]; 00461 dst[4] = src[3]; 00462 dst[5] = src[2]; 00463 dst[6] = src[1]; 00464 dst[7] = src[0]; 00465 00466 } 00467 00468 // unswap using char pointers 00469 SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 00470 { 00471 double d = 0.0; 00472 unsigned char *dst = (unsigned char *)&d; 00473 00474 dst[0] = src[7]; 00475 dst[1] = src[6]; 00476 dst[2] = src[5]; 00477 dst[3] = src[4]; 00478 dst[4] = src[3]; 00479 dst[5] = src[2]; 00480 dst[6] = src[1]; 00481 dst[7] = src[0]; 00482 00483 return d; 00484 } 00485 00486 // returns normalized value in range [-SIMD_PI, SIMD_PI] 00487 SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 00488 { 00489 angleInRadians = btFmod(angleInRadians, SIMD_2_PI); 00490 if(angleInRadians < -SIMD_PI) 00491 { 00492 return angleInRadians + SIMD_2_PI; 00493 } 00494 else if(angleInRadians > SIMD_PI) 00495 { 00496 return angleInRadians - SIMD_2_PI; 00497 } 00498 else 00499 { 00500 return angleInRadians; 00501 } 00502 } 00503 00505 struct btTypedObject 00506 { 00507 btTypedObject(int objectType) 00508 :m_objectType(objectType) 00509 { 00510 } 00511 int m_objectType; 00512 inline int getObjectType() const 00513 { 00514 return m_objectType; 00515 } 00516 }; 00517 #endif //SIMD___SCALAR_H