1 /* 2 Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com 3 4 This software is provided 'as-is', without any express or implied warranty. 5 In no event will the authors be held liable for any damages arising from the use of this software. 6 Permission is granted to anyone to use this software for any purpose, 7 including commercial applications, and to alter it and redistribute it freely, 8 subject to the following restrictions: 9 10 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. 11 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 12 3. This notice may not be removed or altered from any source distribution. 13 */ 14 15 16 17 #ifndef BT_SCALAR_H 18 #define BT_SCALAR_H 19 20 #ifdef BT_MANAGED_CODE 21 //Aligned data types not supported in managed code 22 #pragma unmanaged 23 #endif 24 25 26 #include <math.h> 27 #include <stdlib.h>//size_t for MSVC 6.0 28 #include <float.h> 29 30 /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/ 31 #define BT_BULLET_VERSION 283 32 33 inline int btGetVersion() 34 { 35 return BT_BULLET_VERSION; 36 } 37 38 #if defined(DEBUG) || defined (_DEBUG) 39 #define BT_DEBUG 40 #endif 41 42 43 #ifdef _WIN32 44 45 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) 46 47 #define SIMD_FORCE_INLINE inline 48 #define ATTRIBUTE_ALIGNED16(a) a 49 #define ATTRIBUTE_ALIGNED64(a) a 50 #define ATTRIBUTE_ALIGNED128(a) a 51 #elif (_M_ARM) 52 #define SIMD_FORCE_INLINE __forceinline 53 #define ATTRIBUTE_ALIGNED16(a) __declspec() a 54 #define ATTRIBUTE_ALIGNED64(a) __declspec() a 55 #define ATTRIBUTE_ALIGNED128(a) __declspec () a 56 #else 57 //#define BT_HAS_ALIGNED_ALLOCATOR 58 #pragma warning(disable : 4324) // disable padding warning 59 // #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. 60 // #pragma warning(disable:4996) //Turn off warnings about deprecated C routines 61 // #pragma warning(disable:4786) // Disable the "debug name too long" warning 62 63 #define SIMD_FORCE_INLINE __forceinline 64 #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a 65 #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a 66 #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a 67 #ifdef _XBOX 68 #define BT_USE_VMX128 69 70 #include <ppcintrinsics.h> 71 #define BT_HAVE_NATIVE_FSEL 72 #define btFsel(a,b,c) __fsel((a),(b),(c)) 73 #else 74 75 #if defined (_M_ARM) 76 //Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however) 77 #elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION)) 78 #if _MSC_VER>1400 79 #define BT_USE_SIMD_VECTOR3 80 #endif 81 82 #define BT_USE_SSE 83 #ifdef BT_USE_SSE 84 85 #if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default) 86 #define BT_ALLOW_SSE4 87 #endif //(_MSC_FULL_VER >= 160040219) 88 89 //BT_USE_SSE_IN_API is disabled under Windows by default, because 90 //it makes it harder to integrate Bullet into your application under Windows 91 //(structured embedding Bullet structs/classes need to be 16-byte aligned) 92 //with relatively little performance gain 93 //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries 94 //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage) 95 //#define BT_USE_SSE_IN_API 96 #endif //BT_USE_SSE 97 #include <emmintrin.h> 98 #endif 99 100 #endif//_XBOX 101 102 #endif //__MINGW32__ 103 104 #ifdef BT_DEBUG 105 #ifdef _MSC_VER 106 #include <stdio.h> 107 #define btAssert(x) { if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);__debugbreak(); }} 108 #else//_MSC_VER 109 #include <assert.h> 110 #define btAssert assert 111 #endif//_MSC_VER 112 #else 113 #define btAssert(x) 114 #endif 115 //btFullAssert is optional, slows down a lot 116 #define btFullAssert(x) 117 118 #define btLikely(_c) _c 119 #define btUnlikely(_c) _c 120 121 #else 122 123 #if defined (__CELLOS_LV2__) 124 #define SIMD_FORCE_INLINE inline __attribute__((always_inline)) 125 #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 126 #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 127 #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 128 #ifndef assert 129 #include <assert.h> 130 #endif 131 #ifdef BT_DEBUG 132 #ifdef __SPU__ 133 #include <spu_printf.h> 134 #define printf spu_printf 135 #define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}} 136 #else 137 #define btAssert assert 138 #endif 139 140 #else 141 #define btAssert(x) 142 #endif 143 //btFullAssert is optional, slows down a lot 144 #define btFullAssert(x) 145 146 #define btLikely(_c) _c 147 #define btUnlikely(_c) _c 148 149 #else 150 151 #ifdef USE_LIBSPE2 152 153 #define SIMD_FORCE_INLINE __inline 154 #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 155 #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 156 #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 157 #ifndef assert 158 #include <assert.h> 159 #endif 160 #ifdef BT_DEBUG 161 #define btAssert assert 162 #else 163 #define btAssert(x) 164 #endif 165 //btFullAssert is optional, slows down a lot 166 #define btFullAssert(x) 167 168 169 #define btLikely(_c) __builtin_expect((_c), 1) 170 #define btUnlikely(_c) __builtin_expect((_c), 0) 171 172 173 #else 174 //non-windows systems 175 176 #if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION))) 177 #include <TargetConditionals.h> 178 #if (defined (__i386__) || defined (__x86_64__)) && (!(TARGET_IPHONE_SIMULATOR)) 179 //#define BT_USE_SIMD_VECTOR3 180 //#define BT_USE_SSE 181 //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries 182 //if apps run into issues, we will disable the next line 183 //#define BT_USE_SSE_IN_API 184 #ifdef BT_USE_SSE 185 // include appropriate SSE level 186 #if defined (__SSE4_1__) 187 #include <smmintrin.h> 188 #elif defined (__SSSE3__) 189 #include <tmmintrin.h> 190 #elif defined (__SSE3__) 191 #include <pmmintrin.h> 192 #else 193 #include <emmintrin.h> 194 #endif 195 #endif //BT_USE_SSE 196 #elif defined( __ARM_NEON__ ) 197 #ifdef __clang__ 198 #define BT_USE_NEON 1 199 #define BT_USE_SIMD_VECTOR3 200 201 #if defined BT_USE_NEON && defined (__clang__) 202 #include <arm_neon.h> 203 #endif//BT_USE_NEON 204 #endif //__clang__ 205 #endif//__arm__ 206 207 #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline)) 208 ///@todo: check out alignment methods for other platforms/compilers 209 #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 210 #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 211 #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 212 #ifndef assert 213 #include <assert.h> 214 #endif 215 216 #if defined(DEBUG) || defined (_DEBUG) 217 #if defined (__i386__) || defined (__x86_64__) 218 #include <stdio.h> 219 #define btAssert(x)\ 220 {\ 221 if(!(x))\ 222 {\ 223 printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\ 224 asm volatile ("int3");\ 225 }\ 226 } 227 #else//defined (__i386__) || defined (__x86_64__) 228 #define btAssert assert 229 #endif//defined (__i386__) || defined (__x86_64__) 230 #else//defined(DEBUG) || defined (_DEBUG) 231 #define btAssert(x) 232 #endif//defined(DEBUG) || defined (_DEBUG) 233 234 //btFullAssert is optional, slows down a lot 235 #define btFullAssert(x) 236 #define btLikely(_c) _c 237 #define btUnlikely(_c) _c 238 239 #else 240 241 #define SIMD_FORCE_INLINE inline 242 ///@todo: check out alignment methods for other platforms/compilers 243 ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) 244 ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64))) 245 ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) 246 #define ATTRIBUTE_ALIGNED16(a) a 247 #define ATTRIBUTE_ALIGNED64(a) a 248 #define ATTRIBUTE_ALIGNED128(a) a 249 #ifndef assert 250 #include <assert.h> 251 #endif 252 253 #if defined(DEBUG) || defined (_DEBUG) 254 #define btAssert assert 255 #else 256 #define btAssert(x) 257 #endif 258 259 //btFullAssert is optional, slows down a lot 260 #define btFullAssert(x) 261 #define btLikely(_c) _c 262 #define btUnlikely(_c) _c 263 #endif //__APPLE__ 264 265 #endif // LIBSPE2 266 267 #endif //__CELLOS_LV2__ 268 #endif 269 270 271 ///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. 272 #if defined(BT_USE_DOUBLE_PRECISION) 273 274 typedef double btScalar; 275 //this number could be bigger in double precision 276 #define BT_LARGE_FLOAT 1e30 277 #else 278 279 typedef float btScalar; 280 //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX 281 #define BT_LARGE_FLOAT 1e18f 282 #endif 283 284 #ifdef BT_USE_SSE 285 typedef __m128 btSimdFloat4; 286 #endif//BT_USE_SSE 287 288 #if defined (BT_USE_SSE) 289 //#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE) 290 #ifdef _WIN32 291 292 #ifndef BT_NAN 293 static int btNanMask = 0x7F800001; 294 #define BT_NAN (*(float*)&btNanMask) 295 #endif 296 297 #ifndef BT_INFINITY 298 static int btInfinityMask = 0x7F800000; 299 #define BT_INFINITY (*(float*)&btInfinityMask) 300 inline int btGetInfinityMask()//suppress stupid compiler warning 301 { 302 return btInfinityMask; 303 } 304 #endif 305 306 //use this, in case there are clashes (such as xnamath.h) 307 #ifndef BT_NO_SIMD_OPERATOR_OVERLOADS 308 inline __m128 operator + (const __m128 A, const __m128 B) 309 { 310 return _mm_add_ps(A, B); 311 } 312 313 inline __m128 operator - (const __m128 A, const __m128 B) 314 { 315 return _mm_sub_ps(A, B); 316 } 317 318 inline __m128 operator * (const __m128 A, const __m128 B) 319 { 320 return _mm_mul_ps(A, B); 321 } 322 #endif //BT_NO_SIMD_OPERATOR_OVERLOADS 323 324 #define btCastfTo128i(a) (_mm_castps_si128(a)) 325 #define btCastfTo128d(a) (_mm_castps_pd(a)) 326 #define btCastiTo128f(a) (_mm_castsi128_ps(a)) 327 #define btCastdTo128f(a) (_mm_castpd_ps(a)) 328 #define btCastdTo128i(a) (_mm_castpd_si128(a)) 329 #define btAssign128(r0,r1,r2,r3) _mm_setr_ps(r0,r1,r2,r3) 330 331 #else//_WIN32 332 333 #define btCastfTo128i(a) ((__m128i)(a)) 334 #define btCastfTo128d(a) ((__m128d)(a)) 335 #define btCastiTo128f(a) ((__m128) (a)) 336 #define btCastdTo128f(a) ((__m128) (a)) 337 #define btCastdTo128i(a) ((__m128i)(a)) 338 #define btAssign128(r0,r1,r2,r3) (__m128){r0,r1,r2,r3} 339 #define BT_INFINITY INFINITY 340 #define BT_NAN NAN 341 #endif//_WIN32 342 #else 343 344 #ifdef BT_USE_NEON 345 #include <arm_neon.h> 346 347 typedef float32x4_t btSimdFloat4; 348 #define BT_INFINITY INFINITY 349 #define BT_NAN NAN 350 #define btAssign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3} 351 #else//BT_USE_NEON 352 353 #ifndef BT_INFINITY 354 struct btInfMaskConverter 355 { 356 union { 357 float mask; 358 int intmask; 359 }; 360 btInfMaskConverter(int mask=0x7F800000) 361 :intmask(mask) 362 { 363 } 364 }; 365 static btInfMaskConverter btInfinityMask = 0x7F800000; 366 #define BT_INFINITY (btInfinityMask.mask) 367 inline int btGetInfinityMask()//suppress stupid compiler warning 368 { 369 return btInfinityMask.intmask; 370 } 371 #endif 372 #endif//BT_USE_NEON 373 374 #endif //BT_USE_SSE 375 376 #ifdef BT_USE_NEON 377 #include <arm_neon.h> 378 379 typedef float32x4_t btSimdFloat4; 380 #define BT_INFINITY INFINITY 381 #define BT_NAN NAN 382 #define btAssign128(r0,r1,r2,r3) (float32x4_t){r0,r1,r2,r3} 383 #endif 384 385 386 387 388 389 #define BT_DECLARE_ALIGNED_ALLOCATOR() \ 390 SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 391 SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ 392 SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ 393 SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ 394 SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ 395 SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ 396 SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ 397 SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ 398 399 400 401 #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) 402 403 SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } 404 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } 405 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } 406 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } 407 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } 408 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1)) x=btScalar(1); return acos(x); } 409 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (x<btScalar(-1)) x=btScalar(-1); if (x>btScalar(1)) x=btScalar(1); return asin(x); } 410 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } 411 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } 412 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } 413 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } 414 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } 415 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); } 416 417 #else 418 419 SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 420 { 421 #ifdef USE_APPROXIMATION 422 #ifdef __LP64__ 423 float xhalf = 0.5f*y; 424 int i = *(int*)&y; 425 i = 0x5f375a86 - (i>>1); 426 y = *(float*)&i; 427 y = y*(1.5f - xhalf*y*y); 428 y = y*(1.5f - xhalf*y*y); 429 y = y*(1.5f - xhalf*y*y); 430 y=1/y; 431 return y; 432 #else 433 double x, z, tempf; 434 unsigned long *tfptr = ((unsigned long *)&tempf) + 1; 435 tempf = y; 436 *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ 437 x = tempf; 438 z = y*btScalar(0.5); 439 x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ 440 x = (btScalar(1.5)*x)-(x*x)*(x*z); 441 x = (btScalar(1.5)*x)-(x*x)*(x*z); 442 x = (btScalar(1.5)*x)-(x*x)*(x*z); 443 x = (btScalar(1.5)*x)-(x*x)*(x*z); 444 return x*y; 445 #endif 446 #else 447 return sqrtf(y); 448 #endif 449 } 450 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } 451 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } 452 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } 453 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } 454 SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 455 if (x<btScalar(-1)) 456 x=btScalar(-1); 457 if (x>btScalar(1)) 458 x=btScalar(1); 459 return acosf(x); 460 } 461 SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 462 if (x<btScalar(-1)) 463 x=btScalar(-1); 464 if (x>btScalar(1)) 465 x=btScalar(1); 466 return asinf(x); 467 } 468 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } 469 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } 470 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } 471 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } 472 SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } 473 SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); } 474 475 #endif 476 477 #define SIMD_PI btScalar(3.1415926535897932384626433832795029) 478 #define SIMD_2_PI (btScalar(2.0) * SIMD_PI) 479 #define SIMD_HALF_PI (SIMD_PI * btScalar(0.5)) 480 #define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) 481 #define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) 482 #define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) 483 484 #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ 485 #define btRecip(x) (btScalar(1.0)/btScalar(x)) 486 487 #ifdef BT_USE_DOUBLE_PRECISION 488 #define SIMD_EPSILON DBL_EPSILON 489 #define SIMD_INFINITY DBL_MAX 490 #define BT_ONE 1.0 491 #define BT_ZERO 0.0 492 #define BT_TWO 2.0 493 #define BT_HALF 0.5 494 #else 495 #define SIMD_EPSILON FLT_EPSILON 496 #define SIMD_INFINITY FLT_MAX 497 #define BT_ONE 1.0f 498 #define BT_ZERO 0.0f 499 #define BT_TWO 2.0f 500 #define BT_HALF 0.5f 501 #endif 502 503 SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 504 { 505 btScalar coeff_1 = SIMD_PI / 4.0f; 506 btScalar coeff_2 = 3.0f * coeff_1; 507 btScalar abs_y = btFabs(y); 508 btScalar angle; 509 if (x >= 0.0f) { 510 btScalar r = (x - abs_y) / (x + abs_y); 511 angle = coeff_1 - coeff_1 * r; 512 } else { 513 btScalar r = (x + abs_y) / (abs_y - x); 514 angle = coeff_2 - coeff_1 * r; 515 } 516 return (y < 0.0f) ? -angle : angle; 517 } 518 519 SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } 520 521 SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { 522 return (((a) <= eps) && !((a) < -eps)); 523 } 524 SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { 525 return (!((a) <= eps)); 526 } 527 528 529 SIMD_FORCE_INLINE int btIsNegative(btScalar x) { 530 return x < btScalar(0.0) ? 1 : 0; 531 } 532 533 SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } 534 SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } 535 536 #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name 537 538 #ifndef btFsel 539 SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) 540 { 541 return a >= 0 ? b : c; 542 } 543 #endif 544 #define btFsels(a,b,c) (btScalar)btFsel(a,b,c) 545 546 547 SIMD_FORCE_INLINE bool btMachineIsLittleEndian() 548 { 549 long int i = 1; 550 const char *p = (const char *) &i; 551 if (p[0] == 1) // Lowest address contains the least significant byte 552 return true; 553 else 554 return false; 555 } 556 557 558 559 ///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 560 ///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html 561 SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 562 { 563 // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero 564 // Rely on positive value or'ed with its negative having sign bit on 565 // and zero value or'ed with its negative (which is still zero) having sign bit off 566 // Use arithmetic shift right, shifting the sign bit through all 32 bits 567 unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 568 unsigned testEqz = ~testNz; 569 return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 570 } 571 SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) 572 { 573 unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); 574 unsigned testEqz = ~testNz; 575 return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 576 } 577 SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) 578 { 579 #ifdef BT_HAVE_NATIVE_FSEL 580 return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); 581 #else 582 return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 583 #endif 584 } 585 586 template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b) 587 { 588 T tmp = a; 589 a = b; 590 b = tmp; 591 } 592 593 594 //PCK: endian swapping functions 595 SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) 596 { 597 return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); 598 } 599 600 SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) 601 { 602 return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); 603 } 604 605 SIMD_FORCE_INLINE unsigned btSwapEndian(int val) 606 { 607 return btSwapEndian((unsigned)val); 608 } 609 610 SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) 611 { 612 return btSwapEndian((unsigned short) val); 613 } 614 615 ///btSwapFloat uses using char pointers to swap the endianness 616 ////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values 617 ///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. 618 ///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. 619 ///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. 620 ///so instead of returning a float/double, we return integer/long long integer 621 SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) 622 { 623 unsigned int a = 0; 624 unsigned char *dst = (unsigned char *)&a; 625 unsigned char *src = (unsigned char *)&d; 626 627 dst[0] = src[3]; 628 dst[1] = src[2]; 629 dst[2] = src[1]; 630 dst[3] = src[0]; 631 return a; 632 } 633 634 // unswap using char pointers 635 SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 636 { 637 float d = 0.0f; 638 unsigned char *src = (unsigned char *)&a; 639 unsigned char *dst = (unsigned char *)&d; 640 641 dst[0] = src[3]; 642 dst[1] = src[2]; 643 dst[2] = src[1]; 644 dst[3] = src[0]; 645 646 return d; 647 } 648 649 650 // swap using char pointers 651 SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) 652 { 653 unsigned char *src = (unsigned char *)&d; 654 655 dst[0] = src[7]; 656 dst[1] = src[6]; 657 dst[2] = src[5]; 658 dst[3] = src[4]; 659 dst[4] = src[3]; 660 dst[5] = src[2]; 661 dst[6] = src[1]; 662 dst[7] = src[0]; 663 664 } 665 666 // unswap using char pointers 667 SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 668 { 669 double d = 0.0; 670 unsigned char *dst = (unsigned char *)&d; 671 672 dst[0] = src[7]; 673 dst[1] = src[6]; 674 dst[2] = src[5]; 675 dst[3] = src[4]; 676 dst[4] = src[3]; 677 dst[5] = src[2]; 678 dst[6] = src[1]; 679 dst[7] = src[0]; 680 681 return d; 682 } 683 684 template<typename T> 685 SIMD_FORCE_INLINE void btSetZero(T* a, int n) 686 { 687 T* acurr = a; 688 size_t ncurr = n; 689 while (ncurr > 0) 690 { 691 *(acurr++) = 0; 692 --ncurr; 693 } 694 } 695 696 697 SIMD_FORCE_INLINE btScalar btLargeDot(const btScalar *a, const btScalar *b, int n) 698 { 699 btScalar p0,q0,m0,p1,q1,m1,sum; 700 sum = 0; 701 n -= 2; 702 while (n >= 0) { 703 p0 = a[0]; q0 = b[0]; 704 m0 = p0 * q0; 705 p1 = a[1]; q1 = b[1]; 706 m1 = p1 * q1; 707 sum += m0; 708 sum += m1; 709 a += 2; 710 b += 2; 711 n -= 2; 712 } 713 n += 2; 714 while (n > 0) { 715 sum += (*a) * (*b); 716 a++; 717 b++; 718 n--; 719 } 720 return sum; 721 } 722 723 724 // returns normalized value in range [-SIMD_PI, SIMD_PI] 725 SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 726 { 727 angleInRadians = btFmod(angleInRadians, SIMD_2_PI); 728 if(angleInRadians < -SIMD_PI) 729 { 730 return angleInRadians + SIMD_2_PI; 731 } 732 else if(angleInRadians > SIMD_PI) 733 { 734 return angleInRadians - SIMD_2_PI; 735 } 736 else 737 { 738 return angleInRadians; 739 } 740 } 741 742 743 744 ///rudimentary class to provide type info 745 struct btTypedObject 746 { 747 btTypedObject(int objectType) 748 :m_objectType(objectType) 749 { 750 } 751 int m_objectType; 752 inline int getObjectType() const 753 { 754 return m_objectType; 755 } 756 }; 757 758 759 760 ///align a pointer to the provided alignment, upwards 761 template <typename T>T* btAlignPointer(T* unalignedPtr, size_t alignment) 762 { 763 764 struct btConvertPointerSizeT 765 { 766 union 767 { 768 T* ptr; 769 size_t integer; 770 }; 771 }; 772 btConvertPointerSizeT converter; 773 774 775 const size_t bit_mask = ~(alignment - 1); 776 converter.ptr = unalignedPtr; 777 converter.integer += alignment-1; 778 converter.integer &= bit_mask; 779 return converter.ptr; 780 } 781 782 783 #endif //BT_SCALAR_H 784