Newton Dynamics  4.00
ndUtils.h
1 /* Copyright (c) <2003-2022> <Julio Jerez, Newton Game Dynamics>
2 *
3 * This software is provided 'as-is', without any express or implied
4 * warranty. In no event will the authors be held liable for any damages
5 * arising from the use of this software.
6 *
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 *
11 * 1. The origin of this software must not be misrepresented; you must not
12 * claim that you wrote the original software. If you use this software
13 * in a product, an acknowledgment in the product documentation would be
14 * appreciated but is not required.
15 *
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 *
19 * 3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #ifndef __ND_UTILS_H__
23 #define __ND_UTILS_H__
24 
25 #include "ndCoreStdafx.h"
26 #include "ndTypes.h"
27 #include "ndStack.h"
28 #include "ndMemory.h"
29 
30 // assume this function returns memory aligned to 16 bytes
31 #define ndAlloca(type, count) (type*) alloca (sizeof (type) * (count))
32 
33 inline ndInt32 ndExp2 (ndInt32 x)
34 {
35  ndInt32 exp = -1;
36  for (; x; x >>= 1)
37  {
38  exp ++;
39  }
40  return exp;
41 }
42 
43 inline ndInt32 ndBitReversal(ndInt32 v, ndInt32 base)
44 {
45  ndInt32 x = 0;
46  ndInt32 power = ndExp2 (base) - 1;
47  do
48  {
49  x += (v & 1) << power;
50  v >>= 1;
51  power--;
52  } while (v);
53  ndAssert(x < base);
54  return x;
55 }
56 
57 template <class T>
58 inline T ndMod(T val, T mod)
59 {
60  return T(fmod(T(val), T(mod)));
61 }
62 
63 template <class T>
64 inline T ndMin(T A, T B)
65 {
66  return (A < B) ? A : B;
67 }
68 
69 template <class T>
70 inline T ndMax(T A, T B)
71 {
72  return (A > B) ? A : B;
73 }
74 
75 template <class T>
76 inline T ndClamp(T val, T min, T max)
77 {
78  return ndMax (min, ndMin (max, val));
79 }
80 
81 template <class T>
82 inline void ndSwap(T& A, T& B)
83 {
84  T tmp (A);
85  A = B;
86  B = tmp;
87 }
88 
89 template <class T>
90 inline T ndAbs(T A)
91 {
92  // according to Intel this is better because is does not read after write
93  return (A >= T(0)) ? A : -A;
94 }
95 
96 template <class T>
97 inline T ndSign(T A)
98 {
99  return (A >= T(0)) ? T(1) : T(-1);
100 }
101 
102 template <class T>
103 inline bool ndAreEqual(T A, T B, T tol)
104 {
105  // deal with too small and de normal values.
106  if ((ndAbs(A) < tol) && (ndAbs(B) < tol))
107  {
108  return true;
109  }
110 
111  ndInt32 exp0;
112  ndFloat64 mantissa0 = frexp(ndFloat64 (A), &exp0);
113 
114  ndInt32 exp1;
115  ndFloat64 mantissa1 = frexp(ndFloat64(B), &exp1);
116  if (ndAbs(exp0 - exp1) > 1)
117  {
118  return false;
119  }
120  if (exp0 != exp1)
121  {
122  if (exp0 > exp1)
123  {
124  mantissa0 *= ndFloat32(2.0f);
125  }
126  else
127  {
128  mantissa1 *= ndFloat32(2.0f);
129  }
130  }
131  return ndAbs(mantissa0 - mantissa1) < tol;
132 }
133 
135 template <class T>
136 inline T ndAnglesAdd (T angleInRadiand1, T angleInRadiand0)
137 {
138  T s1 = T(ndSin(angleInRadiand1));
139  T c1 = T(ndCos(angleInRadiand1));
140  T s0 = T(ndSin(angleInRadiand0));
141  T c0 = T(ndCos(angleInRadiand0));
142 
143  T s = s1 * c0 + s0 * c1;
144  T c = c1 * c0 - s0 * s1;
145  return T(ndAtan2(s, c));
146 }
147 
148 #ifndef _MSC_VER
149  #define _stricmp(x,y) strcasecmp(x,y)
150 #endif
151 
152 inline void strtolwr(char* const string)
153 {
154  for (char * cp = string; *cp; ++cp)
155  {
156  if ((*cp >= 'A') && (*cp <= 'Z'))
157  {
158  *cp += 'a' - 'A';
159  }
160  }
161 }
162 
164 D_CORE_API ndUnsigned64 ndGetTimeInMicroseconds();
165 
169 D_CORE_API ndFloat64 ndRoundToFloat(ndFloat64 val);
170 
173 D_CORE_API void ndThreadYield();
174 
176 D_CORE_API ndInt32 ndVertexListToIndexList(ndFloat64* const vertexList, ndInt32 strideInBytes, ndInt32 compareCount, ndInt32 vertexCount, ndInt32* const indexListOut, ndFloat64 tolerance = ndEpsilon);
177 
179 template <class T>
180 ndInt32 ndVertexListToIndexList(T* const vertexList, ndInt32 strideInBytes, ndInt32 compareCount, ndInt32 vertexCount, ndInt32* const indexListOut, T tolerance = ndEpsilon)
181 {
182  ndInt32 stride = ndInt32(strideInBytes / sizeof(T));
183  ndStack<ndFloat64> pool(vertexCount * stride);
184 
185  ndFloat64* const data = &pool[0];
186  for (ndInt32 i = 0; i < vertexCount; ++i)
187  {
188  ndFloat64* const dst = &data[i * stride];
189  const T* const src = &vertexList[i * stride];
190  for (ndInt32 j = 0; j < stride; ++j)
191  {
192  dst[j] = src[j];
193  }
194  }
195 
196  ndInt32 count = ndVertexListToIndexList(data, ndInt32(stride * sizeof(ndFloat64)), compareCount, vertexCount, indexListOut, ndFloat64(tolerance));
197  for (ndInt32 i = 0; i < count; ++i)
198  {
199  const ndFloat64* const src = &data[i * stride];
200  T* const dst = &vertexList[i * stride];
201  for (ndInt32 j = 0; j < stride; ++j)
202  {
203  dst[j] = T(src[j]);
204  }
205  }
206 
207  return count;
208 }
209 
212 {
213  public:
214  ndSpinLock()
215  #ifndef D_USE_THREAD_EMULATION
216  :m_lock(0)
217  #endif
218  {
219  }
220 
221  void Lock()
222  {
223  #ifndef D_USE_THREAD_EMULATION
224  ndInt32 exp = 1;
225  for (ndUnsigned32 test = 0; !m_lock.compare_exchange_weak(test, 1); test = 0)
226  {
227  Delay(exp);
228  }
229  #endif
230  }
231 
232  void Unlock()
233  {
234  #ifndef D_USE_THREAD_EMULATION
235  m_lock.store(0);
236  #endif
237  }
238 
239  #ifndef D_USE_THREAD_EMULATION
240  private:
241  D_CORE_API void Delay(ndInt32& exp);
242  ndAtomic<ndUnsigned32> m_lock;
243  #endif
244 };
245 
248 {
249  public:
250  ndScopeSpinLock(ndSpinLock& spinLock)
251  :m_spinLock(spinLock)
252  {
253  m_spinLock.Lock();
254  }
255 
256  ~ndScopeSpinLock()
257  {
258  m_spinLock.Unlock();
259  }
260 
261  ndSpinLock& m_spinLock;
262 };
263 
266 {
267  public:
268  //#define D_FLOAT_EXCEPTIONS_MASK (EM_INVALID | EM_DENORMAL | EM_ZERODIVIDE)
269  #if defined (WIN32) || defined(_WIN32)
270  #define D_FLOAT_EXCEPTIONS_MASK (EM_INVALID | EM_DENORMAL)
271  #else
272  #define D_FLOAT_EXCEPTIONS_MASK (FE_INVALID | FE_INEXACT)
273  #endif
274 
275  D_CORE_API ndFloatExceptions(ndUnsigned32 mask = D_FLOAT_EXCEPTIONS_MASK);
276  D_CORE_API ~ndFloatExceptions();
277 
278  private:
279  ndUnsigned32 m_floatMask;
280  ndUnsigned32 m_simdMask;
281 };
282 
283 
284 #endif
285 
ndSpinLock
Simple spin lock for synchronizing threads for very short period of time.
Definition: ndUtils.h:212
ndStack
Definition: ndStack.h:53
ndFloatExceptions
Set cpu floating point exceptions, the original exception state is restored when the destructor is ca...
Definition: ndUtils.h:266
ndScopeSpinLock
Simple scope based spin lock.
Definition: ndUtils.h:248
ndAtomic< ndUnsigned32 >