btScalar.h
Go to the documentation of this file.
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 #ifndef BT_SCALAR_H
16 #define BT_SCALAR_H
17 
18 #ifdef BT_MANAGED_CODE
19 //Aligned data types not supported in managed code
20 #pragma unmanaged
21 #endif
22 
23 #include <float.h>
24 #include <math.h>
25 #include <stdlib.h> //size_t for MSVC 6.0
26 #include <stdint.h>
27 
28 /* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
29 #define BT_BULLET_VERSION 279
30 
31 inline int32_t btGetVersion()
32 {
33  return BT_BULLET_VERSION;
34 }
35 
36 #if defined(DEBUG) || defined(_DEBUG)
37 #define BT_DEBUG
38 #endif
39 
40 #ifdef _WIN32
41 
42 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined(_MSC_VER) && _MSC_VER < 1300)
43 
44 #define SIMD_FORCE_INLINE inline
45 #define ATTRIBUTE_ALIGNED16(a) a
46 #define ATTRIBUTE_ALIGNED64(a) a
47 #define ATTRIBUTE_ALIGNED128(a) a
48 #else
49 //#define BT_HAS_ALIGNED_ALLOCATOR
50 #pragma warning(disable : 4324) // disable padding warning
51 // #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
52 // #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
53 // #pragma warning(disable:4786) // Disable the "debug name too long" warning
54 
55 #define SIMD_FORCE_INLINE __forceinline
56 #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
57 #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
58 #define ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
59 #ifdef _XBOX
60 #define BT_USE_VMX128
61 
62 #include <ppcintrinsics.h>
63 #define BT_HAVE_NATIVE_FSEL
64 #define btFsel(a, b, c) __fsel((a), (b), (c))
65 #else
66 
67 #if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(BT_USE_DOUBLE_PRECISION))
68 #define BT_USE_SSE
69 #include <emmintrin.h>
70 #endif
71 
72 #endif //_XBOX
73 
74 #endif //__MINGW32__
75 
76 #include <assert.h>
77 #ifdef BT_DEBUG
78 #define btAssert assert
79 #else
80 #define btAssert(x)
81 #endif
82 //btFullAssert is optional, slows down a lot
83 #define btFullAssert(x)
84 
85 #define btLikely(_c) _c
86 #define btUnlikely(_c) _c
87 
88 #else
89 
90 #if defined(__CELLOS_LV2__)
91 #define SIMD_FORCE_INLINE inline __attribute__((always_inline))
92 #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
93 #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
94 #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
95 #ifndef assert
96 #include <assert.h>
97 #endif
98 #ifdef BT_DEBUG
99 #ifdef __SPU__
100 #include <spu_printf.h>
101 #define printf spu_printf
102 #define btAssert(x) \
103  { \
104  if (!(x)) { \
105  printf("Assert " __FILE__ ":%u (" #x ")\n", __LINE__); \
106  spu_hcmpeq(0, 0); \
107  } \
108  }
109 #else
110 #define btAssert assert
111 #endif
112 
113 #else
114 #define btAssert(x)
115 #endif
116 //btFullAssert is optional, slows down a lot
117 #define btFullAssert(x)
118 
119 #define btLikely(_c) _c
120 #define btUnlikely(_c) _c
121 
122 #else
123 
124 #ifdef USE_LIBSPE2
125 
126 #define SIMD_FORCE_INLINE __inline
127 #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
128 #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
129 #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
130 #ifndef assert
131 #include <assert.h>
132 #endif
133 #ifdef BT_DEBUG
134 #define btAssert assert
135 #else
136 #define btAssert(x)
137 #endif
138 //btFullAssert is optional, slows down a lot
139 #define btFullAssert(x)
140 
141 #define btLikely(_c) __builtin_expect((_c), 1)
142 #define btUnlikely(_c) __builtin_expect((_c), 0)
143 
144 #else
145 //non-windows systems
146 
147 #if (defined(__APPLE__) && defined(__i386__) && (!defined(BT_USE_DOUBLE_PRECISION)))
148 #define BT_USE_SSE
149 #include <emmintrin.h>
150 
151 #define SIMD_FORCE_INLINE inline
152 #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
154 #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
155 #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
156 #ifndef assert
157 #include <assert.h>
158 #endif
159 
160 #if defined(DEBUG) || defined(_DEBUG)
161 #define btAssert assert
162 #else
163 #define btAssert(x)
164 #endif
165 
166 //btFullAssert is optional, slows down a lot
167 #define btFullAssert(x)
168 #define btLikely(_c) _c
169 #define btUnlikely(_c) _c
170 
171 #else
172 
173 #define SIMD_FORCE_INLINE inline
174 #define ATTRIBUTE_ALIGNED16(a) a
179 #define ATTRIBUTE_ALIGNED64(a) a
180 #define ATTRIBUTE_ALIGNED128(a) a
181 #ifndef assert
182 #include <assert.h>
183 #endif
184 
185 #if defined(DEBUG) || defined(_DEBUG)
186 #define btAssert assert
187 #else
188 #define btAssert(x)
189 #endif
190 
191 //btFullAssert is optional, slows down a lot
192 #define btFullAssert(x)
193 #define btLikely(_c) _c
194 #define btUnlikely(_c) _c
195 #endif //__APPLE__
196 
197 #endif // LIBSPE2
198 
199 #endif //__CELLOS_LV2__
200 #endif
201 
203 #if defined(BT_USE_DOUBLE_PRECISION)
204 typedef double btScalar;
205 //this number could be bigger in double precision
206 #define BT_LARGE_FLOAT 1e30
207 #else
208 typedef float btScalar;
209 //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
210 #define BT_LARGE_FLOAT 1e18f
211 #endif
212 
213 #define BT_DECLARE_ALIGNED_ALLOCATOR() \
214  SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
215  SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \
216  SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \
217  SIMD_FORCE_INLINE void operator delete(void*, void*) {} \
218  SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
219  SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \
220  SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \
221  SIMD_FORCE_INLINE void operator delete[](void*, void*) {}
222 
223 #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
224 
226 {
227  return sqrt(x);
228 }
229 SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
230 SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
231 SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
232 SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
234 {
235  if (x < btScalar(-1))
236  x = btScalar(-1);
237  if (x > btScalar(1))
238  x = btScalar(1);
239  return acos(x);
240 }
242 {
243  if (x < btScalar(-1))
244  x = btScalar(-1);
245  if (x > btScalar(1))
246  x = btScalar(1);
247  return asin(x);
248 }
249 SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
250 SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
251 SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
252 SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
253 SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return pow(x, y); }
254 SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
255 
256 #else
257 
259 {
260 #ifdef USE_APPROXIMATION
261  double x, z, tempf;
262  unsigned long* tfptr = ((unsigned long*)&tempf) + 1;
263 
264  tempf = y;
265  *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
266  x = tempf;
267  z = y * btScalar(0.5);
268  x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
269  x = (btScalar(1.5) * x) - (x * x) * (x * z);
270  x = (btScalar(1.5) * x) - (x * x) * (x * z);
271  x = (btScalar(1.5) * x) - (x * x) * (x * z);
272  x = (btScalar(1.5) * x) - (x * x) * (x * z);
273  return x * y;
274 #else
275  return sqrtf(y);
276 #endif
277 }
283 {
284  if (x < btScalar(-1))
285  x = btScalar(-1);
286  if (x > btScalar(1))
287  x = btScalar(1);
288  return acosf(x);
289 }
291 {
292  if (x < btScalar(-1))
293  x = btScalar(-1);
294  if (x > btScalar(1))
295  x = btScalar(1);
296  return asinf(x);
297 }
304 
305 #endif
306 
307 #define SIMD_2_PI btScalar(6.283185307179586232)
308 #define SIMD_PI (SIMD_2_PI * btScalar(0.5))
309 #define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25))
310 #define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
311 #define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
312 #define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
313 
314 #define btRecipSqrt(x) ((btScalar)(btScalar(1.0) / btSqrt(btScalar(x)))) /* reciprocal square root */
315 
316 #ifdef BT_USE_DOUBLE_PRECISION
317 #define SIMD_EPSILON DBL_EPSILON
318 #define SIMD_INFINITY DBL_MAX
319 #else
320 #define SIMD_EPSILON FLT_EPSILON
321 #define SIMD_INFINITY FLT_MAX
322 #endif
323 
325 {
326  btScalar coeff_1 = SIMD_PI / 4.0f;
327  btScalar coeff_2 = 3.0f * coeff_1;
328  btScalar abs_y = btFabs(y);
329  btScalar angle;
330  if (x >= 0.0f) {
331  btScalar r = (x - abs_y) / (x + abs_y);
332  angle = coeff_1 - coeff_1 * r;
333  }
334  else {
335  btScalar r = (x + abs_y) / (abs_y - x);
336  angle = coeff_2 - coeff_1 * r;
337  }
338  return (y < 0.0f) ? -angle : angle;
339 }
340 
342 
344 {
345  return (((a) <= eps) && !((a) < -eps));
346 }
348 {
349  return (!((a) <= eps));
350 }
351 
353 {
354  return x < btScalar(0.0) ? 1 : 0;
355 }
356 
359 
360 #define BT_DECLARE_HANDLE(name) \
361  typedef struct name##__ { \
362  int32_t unused; \
363  } * name
364 
365 #ifndef btFsel
367 {
368  return a >= 0 ? b : c;
369 }
370 #endif
371 #define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
372 
374 {
375  long int i = 1;
376  const char* p = (const char*)&i;
377  if (p[0] == 1) // Lowest address contains the least significant byte
378  return true;
379  else
380  return false;
381 }
382 
385 SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
386 {
387  // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
388  // Rely on positive value or'ed with its negative having sign bit on
389  // and zero value or'ed with its negative (which is still zero) having sign bit off
390  // Use arithmetic shift right, shifting the sign bit through all 32 bits
391  unsigned testNz = (unsigned)(((int32_t)condition | -(int32_t)condition) >> 31);
392  unsigned testEqz = ~testNz;
393  return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
394 }
395 SIMD_FORCE_INLINE int32_t btSelect(unsigned condition, int32_t valueIfConditionNonZero, int32_t valueIfConditionZero)
396 {
397  unsigned testNz = (unsigned)(((int32_t)condition | -(int32_t)condition) >> 31);
398  unsigned testEqz = ~testNz;
399  return static_cast<int32_t>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
400 }
401 SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
402 {
403 #ifdef BT_HAVE_NATIVE_FSEL
404  return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
405 #else
406  return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
407 #endif
408 }
409 
410 template <typename T>
411 SIMD_FORCE_INLINE void btSwap(T& a, T& b)
412 {
413  T tmp = a;
414  a = b;
415  b = tmp;
416 }
417 
418 //PCK: endian swapping functions
419 SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
420 {
421  return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
422 }
423 
424 SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
425 {
426  return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
427 }
428 
429 SIMD_FORCE_INLINE unsigned btSwapEndian(int32_t val)
430 {
431  return btSwapEndian((unsigned)val);
432 }
433 
434 SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
435 {
436  return btSwapEndian((unsigned short)val);
437 }
438 
446 {
447  uint32_t a = 0;
448  unsigned char* dst = (unsigned char*)&a;
449  unsigned char* src = (unsigned char*)&d;
450 
451  dst[0] = src[3];
452  dst[1] = src[2];
453  dst[2] = src[1];
454  dst[3] = src[0];
455  return a;
456 }
457 
458 // unswap using char pointers
460 {
461  float d = 0.0f;
462  unsigned char* src = (unsigned char*)&a;
463  unsigned char* dst = (unsigned char*)&d;
464 
465  dst[0] = src[3];
466  dst[1] = src[2];
467  dst[2] = src[1];
468  dst[3] = src[0];
469 
470  return d;
471 }
472 
473 // swap using char pointers
474 SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst)
475 {
476  unsigned char* src = (unsigned char*)&d;
477 
478  dst[0] = src[7];
479  dst[1] = src[6];
480  dst[2] = src[5];
481  dst[3] = src[4];
482  dst[4] = src[3];
483  dst[5] = src[2];
484  dst[6] = src[1];
485  dst[7] = src[0];
486 }
487 
488 // unswap using char pointers
489 SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char* src)
490 {
491  double d = 0.0;
492  unsigned char* dst = (unsigned char*)&d;
493 
494  dst[0] = src[7];
495  dst[1] = src[6];
496  dst[2] = src[5];
497  dst[3] = src[4];
498  dst[4] = src[3];
499  dst[5] = src[2];
500  dst[6] = src[1];
501  dst[7] = src[0];
502 
503  return d;
504 }
505 
506 // returns normalized value in range [-SIMD_PI, SIMD_PI]
508 {
509  angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
510  if (angleInRadians < -SIMD_PI) {
511  return angleInRadians + SIMD_2_PI;
512  }
513  else if (angleInRadians > SIMD_PI) {
514  return angleInRadians - SIMD_2_PI;
515  }
516  else {
517  return angleInRadians;
518  }
519 }
520 
523  btTypedObject(int32_t objectType)
524  : m_objectType(objectType)
525  {
526  }
527  int32_t m_objectType;
528  inline int32_t getObjectType() const
529  {
530  return m_objectType;
531  }
532 };
533 #endif //BT_SCALAR_H
SIMD_FORCE_INLINE float btUnswapEndianFloat(uint32_t a)
Definition: btScalar.h:459
SIMD_FORCE_INLINE btScalar btRadians(btScalar x)
Definition: btScalar.h:357
#define BT_BULLET_VERSION
Definition: btScalar.h:29
SIMD_FORCE_INLINE btScalar btExp(btScalar x)
Definition: btScalar.h:300
SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char *dst)
Definition: btScalar.h:474
#define SIMD_EPSILON
Definition: btScalar.h:320
SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
Definition: btScalar.h:290
SIMD_FORCE_INLINE const btScalar & x() const
Return the x value.
Definition: btVector3.h:275
int32_t getObjectType() const
Definition: btScalar.h:528
SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
Definition: btScalar.h:373
btTypedObject(int32_t objectType)
Definition: btScalar.h:523
SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
Definition: btScalar.h:324
SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
Definition: btScalar.h:282
SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src)
Definition: btScalar.h:489
SIMD_FORCE_INLINE btScalar btAtan(btScalar x)
Definition: btScalar.h:298
SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x)
Definition: btScalar.h:341
SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
Definition: btScalar.h:385
SIMD_FORCE_INLINE int32_t btIsNegative(btScalar x)
Definition: btScalar.h:352
SIMD_FORCE_INLINE btScalar btFabs(btScalar x)
Definition: btScalar.h:278
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:208
SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y)
Definition: btScalar.h:299
rudimentary class to provide type info
Definition: btScalar.h:522
SIMD_FORCE_INLINE btScalar btCos(btScalar x)
Definition: btScalar.h:279
SIMD_FORCE_INLINE const btScalar & y() const
Return the y value.
Definition: btVector3.h:277
int32_t btGetVersion()
Definition: btScalar.h:31
SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y)
Definition: btScalar.h:303
SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
Definition: btScalar.h:507
SIMD_FORCE_INLINE btScalar btDegrees(btScalar x)
Definition: btScalar.h:358
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:177
SIMD_FORCE_INLINE btScalar btSin(btScalar x)
Definition: btScalar.h:280
int32_t m_objectType
Definition: btScalar.h:527
#define SIMD_FORCE_INLINE
Definition: btScalar.h:173
SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
Definition: btScalar.h:347
SIMD_FORCE_INLINE void btSwap(T &a, T &b)
Definition: btScalar.h:411
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition: btVector3.h:279
#define SIMD_RADS_PER_DEG
Definition: btScalar.h:310
#define SIMD_PI
Definition: btScalar.h:308
SIMD_FORCE_INLINE btScalar btLog(btScalar x)
Definition: btScalar.h:301
SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y)
Definition: btScalar.h:302
SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
Definition: btScalar.h:258
SIMD_FORCE_INLINE uint32_t btSwapEndianFloat(float d)
btSwapFloat uses using char pointers to swap the endianness
Definition: btScalar.h:445
SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
Definition: btScalar.h:366
#define SIMD_2_PI
Definition: btScalar.h:307
SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
Definition: btScalar.h:343
SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
Definition: btScalar.h:419
SIMD_FORCE_INLINE btScalar btTan(btScalar x)
Definition: btScalar.h:281
#define SIMD_DEGS_PER_RAD
Definition: btScalar.h:311