ScummVM API documentation
dgTypes.h
1 /* Copyright (c) <2003-2011> <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 AFX_DGTYPES__42YH_HY78GT_YHJ63Y__INCLUDED_
23 #define AFX_DGTYPES__42YH_HY78GT_YHJ63Y__INCLUDED_
24 
25 #include "common/scummsys.h"
26 
27 //************************************************************
28 #define __USE_CPU_FOUND__
29 
30 #define DG_MAXIMUN_THREADS 8
31 
32 #ifdef _DEBUG
33 // #define __ENABLE_SANITY_CHECK
34 #endif
35 
36 #ifdef DLL_DECLSPEC
37 #undef DLL_DECLSPEC
38 #endif
39 
40 #define DG_INLINE FORCEINLINE
41 
42 #ifdef _MSC_VER
43 #define DG_MSC_VECTOR_ALIGMENT __declspec(align(16))
44 #define DG_GCC_VECTOR_ALIGMENT
45 #else
46 #define DG_MSC_VECTOR_ALIGMENT
47 #define DG_GCC_VECTOR_ALIGMENT __attribute__((aligned(16)))
48 #endif
49 
50 typedef int8 dgInt8;
51 typedef uint8 dgUnsigned8;
52 
53 typedef int16 dgInt16;
54 typedef uint16 dgUnsigned16;
55 
56 typedef int32 dgInt32;
57 typedef uint32 dgUnsigned32;
58 
59 typedef int64 dgInt64;
60 typedef uint64 dgUnsigned64;
61 
62 typedef double dgFloat64;
63 
64 #ifdef __USE_DOUBLE_PRECISION__
65 typedef double dgFloat32;
66 #else
67 typedef float dgFloat32;
68 #endif
69 
70 class dgTriplex {
71 public:
72  dgFloat32 m_x;
73  dgFloat32 m_y;
74  dgFloat32 m_z;
75 };
76 
77 #define dgPI dgFloat32(3.14159f)
78 #define dgPI2 dgFloat32(dgPI * 2.0f)
79 #define dgEXP dgFloat32(2.71828f)
80 #define dgEPSILON dgFloat32(1.0e-5f)
81 #define dgGRAVITY dgFloat32(9.8f)
82 #define dgDEG2RAD dgFloat32(dgPI / 180.0f)
83 #define dgRAD2DEG dgFloat32(180.0f / dgPI)
84 #define dgKMH2MPSEC dgFloat32(0.278f)
85 
86 class dgVector;
87 class dgBigVector;
88 
89 #ifdef _WIN32
90 #define dgApi __cdecl
91 
92 #ifdef _WIN64
93 #define dgNaked
94 #else
95 #define dgNaked __declspec(naked)
96 #endif
97 #else
98 #define dgApi
99 #define dgNaked
100 #endif
101 
102 #define dgCheckFloat(x) (isfinite(x) && !isnan(x))
103 // Assertions have been disabled because they fired in areas
104 // were there are no visible defects. They can be re-enabled when
105 // debugging specific issues.
106 // #define NEWTON_ASSERT(x) assert(x);
107 #define NEWTON_ASSERT(x)
108 
109 DG_INLINE dgInt32 exp_2(dgInt32 x) {
110  dgInt32 exp;
111 
112  for (exp = -1; x; x >>= 1) {
113  exp++;
114  }
115 
116  return exp;
117 }
118 
119 template<class T>
120 DG_INLINE T ClampValue(T val, T min, T max) {
121  if (val < min) {
122  return min;
123  }
124 
125  if (val > max) {
126  return max;
127  }
128 
129  return val;
130 }
131 
132 template<class T>
133 DG_INLINE T GetMin(T A, T B) {
134  if (B < A) {
135  A = B;
136  }
137 
138  return A;
139 }
140 
141 template<class T>
142 DG_INLINE T GetMax(T A, T B) {
143  if (B > A) {
144  A = B;
145  }
146 
147  return A;
148 }
149 
150 template<class T>
151 DG_INLINE T GetMin(T A, T B, T C) {
152  return GetMin(GetMin(A, B), C);
153 }
154 
155 template<class T>
156 DG_INLINE T GetMax(T A, T B, T C) {
157  return GetMax(GetMax(A, B), C);
158 }
159 
160 template<class T>
161 DG_INLINE void Swap(T &A, T &B) {
162  T tmp(A);
163  A = B;
164  B = tmp;
165 }
166 
167 template<class T>
168 DG_INLINE T GetSign(T A) {
169  T sign(1.0f);
170 
171  if (A < T(0.0f)) {
172  sign = T(-1.0f);
173  }
174 
175  return sign;
176 }
177 
178 template<class T>
179 dgInt32 dgBinarySearch(T const *array, dgInt32 elements, dgInt32 entry) {
180  dgInt32 index0;
181  dgInt32 index1;
182  dgInt32 index2;
183  dgInt32 entry1;
184 
185  index0 = 0;
186  index2 = elements - 1;
187 
188  while ((index2 - index0) > 1) {
189  index1 = (index0 + index2) >> 1;
190  entry1 = array[index1].m_Key;
191 
192  if (entry1 == entry) {
193  NEWTON_ASSERT(array[index1].m_Key <= entry);
194  NEWTON_ASSERT(array[index1 + 1].m_Key >= entry);
195 
196  return index1;
197  } else if (entry < entry1) {
198  index2 = index1;
199  } else {
200  index0 = index1;
201  }
202  }
203 
204  if (array[index0].m_Key > index0) {
205  index0--;
206  }
207 
208  NEWTON_ASSERT(array[index0].m_Key <= entry);
209  NEWTON_ASSERT(array[index0 + 1].m_Key >= entry);
210 
211  return index0;
212 }
213 
214 template<class T>
215 void dgRadixSort(T *const array,
216  T *const tmpArray,
217  dgInt32 elements,
218  dgInt32 radixPass,
219  dgInt32(*getRadixKey)(const T *const A, void *const context),
220  void *const context = NULL) {
221  dgInt32 scanCount[256];
222  dgInt32 histogram[256][4];
223 
224  NEWTON_ASSERT(radixPass >= 1);
225  NEWTON_ASSERT(radixPass <= 4);
226 
227  memset(histogram, 0, sizeof(histogram));
228 
229  for (dgInt32 i = 0; i < elements; i++) {
230  dgInt32 key = getRadixKey(&array[i], context);
231 
232  for (dgInt32 j = 0; j < radixPass; j++) {
233  dgInt32 radix = (key >> (j << 3)) & 0xff;
234  histogram[radix][j] = histogram[radix][j] + 1;
235  }
236  }
237 
238  for (dgInt32 radix = 0; radix < radixPass; radix += 2) {
239  scanCount[0] = 0;
240 
241  for (dgInt32 i = 1; i < 256; i++) {
242  scanCount[i] = scanCount[i - 1] + histogram[i - 1][radix];
243  }
244 
245  dgInt32 radixShift = radix << 3;
246 
247  for (dgInt32 i = 0; i < elements; i++) {
248  dgInt32 key = (getRadixKey(&array[i], context) >> radixShift) & 0xff;
249  dgInt32 index = scanCount[key];
250  tmpArray[index] = array[i];
251  scanCount[key] = index + 1;
252  }
253 
254  if ((radix + 1) < radixPass) {
255  scanCount[0] = 0;
256 
257  for (dgInt32 i = 1; i < 256; i++) {
258  scanCount[i] = scanCount[i - 1] + histogram[i - 1][radix + 1];
259  }
260 
261  dgInt32 radixShift2 = (radix + 1) << 3;
262 
263  for (dgInt32 i = 0; i < elements; i++) {
264  dgInt32 key = (getRadixKey(&array[i], context) >> radixShift2) & 0xff;
265  dgInt32 index = scanCount[key];
266  array[index] = tmpArray[i];
267  scanCount[key] = index + 1;
268  }
269  } else {
270  memcpy(array, tmpArray, elements * sizeof(T));
271  }
272  }
273 
274 #ifdef _DEBUG
275  for (dgInt32 i = 0; i < (elements - 1); i++) {
276  NEWTON_ASSERT(getRadixKey(&array[i], context) <= getRadixKey(&array[i + 1], context));
277  }
278 #endif
279 }
280 
281 template<class T>
282 void dgSort(T *const array,
283  dgInt32 elements,
284  dgInt32(*compare)(const T *const A, const T *const B, void *const context),
285  void *const context = NULL) {
286  dgInt32 stride = 8;
287  dgInt32 stack[1024][2];
288 
289  stack[0][0] = 0;
290  stack[0][1] = elements - 1;
291  dgInt32 stackIndex = 1;
292 
293  while (stackIndex) {
294  stackIndex--;
295  dgInt32 lo = stack[stackIndex][0];
296  dgInt32 hi = stack[stackIndex][1];
297 
298  if ((hi - lo) > stride) {
299  dgInt32 i = lo;
300  dgInt32 j = hi;
301  T val(array[(lo + hi) >> 1]);
302 
303  do {
304  while (compare(&array[i], &val, context) < 0)
305  i++;
306  while (compare(&array[j], &val, context) > 0)
307  j--;
308 
309  if (i <= j) {
310  T tmp(array[i]);
311  array[i] = array[j];
312  array[j] = tmp;
313  i++;
314  j--;
315  }
316  } while (i <= j);
317 
318  if (i < hi) {
319  stack[stackIndex][0] = i;
320  stack[stackIndex][1] = hi;
321  stackIndex++;
322  }
323 
324  if (lo < j) {
325  stack[stackIndex][0] = lo;
326  stack[stackIndex][1] = j;
327  stackIndex++;
328  }
329  NEWTON_ASSERT(stackIndex < dgInt32(sizeof(stack) / (2 * sizeof(stack[0][0]))));
330  }
331  }
332 
333  stride = stride * 2;
334 
335  if (elements < stride) {
336  stride = elements;
337  }
338 
339  for (dgInt32 i = 1; i < stride; i++) {
340  if (compare(&array[0], &array[i], context) > 0) {
341  T tmp(array[0]);
342  array[0] = array[i];
343  array[i] = tmp;
344  }
345  }
346 
347  for (dgInt32 i = 1; i < elements; i++) {
348  dgInt32 j = i;
349  T tmp(array[i]);
350 
351  // for (; j && (compare (&array[j - 1], &tmp, context) > 0); j --) {
352  for (; compare(&array[j - 1], &tmp, context) > 0; j--) {
353  NEWTON_ASSERT(j > 0);
354  array[j] = array[j - 1];
355  }
356 
357  array[j] = tmp;
358  }
359 
360 #ifdef _DEBUG
361  for (dgInt32 i = 0; i < (elements - 1); i++) {
362  NEWTON_ASSERT(compare(&array[i], &array[i + 1], context) <= 0);
363  }
364 #endif
365 }
366 
367 template<class T>
368 void dgSortIndirect(T **const array,
369  dgInt32 elements,
370  dgInt32(*compare)(const T *const A, const T *const B, void *const context),
371  void *const context = NULL) {
372  dgInt32 stride = 8;
373  dgInt32 stack[1024][2];
374 
375  stack[0][0] = 0;
376  stack[0][1] = elements - 1;
377  dgInt32 stackIndex = 1;
378 
379  while (stackIndex) {
380  stackIndex--;
381  dgInt32 lo = stack[stackIndex][0];
382  dgInt32 hi = stack[stackIndex][1];
383 
384  if ((hi - lo) > stride) {
385  dgInt32 i = lo;
386  dgInt32 j = hi;
387  T *val(array[(lo + hi) >> 1]);
388 
389  do {
390  while (compare(array[i], val, context) < 0)
391  i++;
392  while (compare(array[j], val, context) > 0)
393  j--;
394 
395  if (i <= j) {
396  T *tmp(array[i]);
397  array[i] = array[j];
398  array[j] = tmp;
399  i++;
400  j--;
401  }
402  } while (i <= j);
403 
404  if (i < hi) {
405  stack[stackIndex][0] = i;
406  stack[stackIndex][1] = hi;
407  stackIndex++;
408  }
409 
410  if (lo < j) {
411  stack[stackIndex][0] = lo;
412  stack[stackIndex][1] = j;
413  stackIndex++;
414  }
415  NEWTON_ASSERT(stackIndex < dgInt32(sizeof(stack) / (2 * sizeof(stack[0][0]))));
416  }
417  }
418 
419  stride = stride * 2;
420 
421  if (elements < stride) {
422  stride = elements;
423  }
424 
425  for (dgInt32 i = 1; i < stride; i++) {
426  if (compare(&array[0], &array[i], context) > 0) {
427  T tmp(array[0]);
428  array[0] = array[i];
429  array[i] = tmp;
430  }
431  }
432 
433  for (dgInt32 i = 1; i < elements; i++) {
434  dgInt32 j = i;
435  T *tmp(array[i]);
436 
437  // for (; j && (compare (array[j - 1], tmp, context) > 0); j --) {
438  for (; compare(array[j - 1], tmp, context) > 0; j--) {
439  NEWTON_ASSERT(j > 0);
440  array[j] = array[j - 1];
441  }
442 
443  array[j] = tmp;
444  }
445 
446 #ifdef _DEBUG
447  for (dgInt32 i = 0; i < (elements - 1); i++) {
448  NEWTON_ASSERT(compare(array[i], array[i + 1], context) <= 0);
449  }
450 #endif
451 }
452 
453 #ifdef __USE_DOUBLE_PRECISION__
454 union dgFloatSign {
455  struct {
456  dgInt32 m_dommy;
457  dgInt32 m_iVal;
458 
459  } m_integer;
460 
461  dgFloat64 m_fVal;
462 };
463 #else
464 union dgFloatSign {
465  struct s {
466  dgInt32 m_iVal;
467 
468  } m_integer;
469 
470  dgFloat32 m_fVal;
471 };
472 #endif
473 
474 union dgDoubleInt {
475  dgInt64 m_int;
476  dgFloat64 m_float;
477 };
478 
479 void GetMinMax(dgVector &Min,
480  dgVector &Max,
481  const dgFloat32 *const vArray,
482  dgInt32 vCount,
483  dgInt32 StrideInBytes);
484 
485 void GetMinMax(dgBigVector &Min,
486  dgBigVector &Max,
487  const dgFloat64 *const vArray,
488  dgInt32 vCount,
489  dgInt32 strideInBytes);
490 
491 dgInt32 dgVertexListToIndexList(dgFloat32 *const vertexList,
492  dgInt32 strideInBytes,
493  dgInt32 floatSizeInBytes,
494  dgInt32 unsignedSizeInBytes,
495  dgInt32 vertexCount,
496  dgInt32 *const indexListOut,
497  dgFloat32 tolerance = dgEPSILON);
498 
499 dgInt32 dgVertexListToIndexList(dgFloat64 *const vertexList,
500  dgInt32 strideInBytes,
501  dgInt32 compareCount,
502  dgInt32 vertexCount,
503  dgInt32 *const indexListOut,
504  dgFloat64 tolerance = dgEPSILON);
505 
506 enum dgCpuClass {
507  dgNoSimdPresent = 0,
508  dgSimdPresent
509  // dgSimdPresent_3,
510 };
511 
512 #define PointerToInt(x) ((size_t)x)
513 #define IntToPointer(x) ((void *)(size_t(x)))
514 
515 DG_INLINE dgFloat32 dgAbsf(dgFloat32 x) {
516 #if 0
517  dgDoubleInt val;
518  val.m_float = x;
519  val.m_intH &= ~(dgUnsigned64(1) << 31);
520  NEWTON_ASSERT(val.m_float == fabs(x));
521 
522  return dgFloat32(val.m_float);
523 #else
524  // according to Intel this is better because is doe not read after write
525  return (x >= dgFloat32(0.0f)) ? x : -x;
526 #endif
527 }
528 
529 #ifndef __USE_DOUBLE_PRECISION__
530 DG_INLINE dgInt32 dgFastInt(dgFloat64 x) {
531  dgInt32 i = dgInt32(x);
532 
533  if (dgFloat64(i) > x) {
534  i--;
535  }
536 
537  return i;
538 }
539 #endif
540 
541 DG_INLINE dgInt32 dgFastInt(dgFloat32 x) {
542 #if 0
543  volatile dgDoubleInt val;
544  volatile dgDoubleInt round;
545  const dgFloat64 conversionMagicConst = ((dgFloat64(dgInt64(1) << 52)) * dgFloat64(1.5f));
546  val.m_float = dgFloat64(x) + conversionMagicConst;
547  round.m_float = x - dgFloat64(val.m_intL);
548  dgInt32 ret = val.m_intL + (round.m_intH >> 31);
549  NEWTON_ASSERT(ret == dgInt32(floor(x)));
550 
551  return ret;
552 #else
553  dgInt32 i = dgInt32(x);
554 
555  if (dgFloat32(i) > x) {
556  i--;
557  }
558 
559  return i;
560 #endif
561 }
562 
563 DG_INLINE dgFloat32 dgFloor(dgFloat32 x) {
564 #ifdef _MSC_VER
565  dgFloat32 ret = dgFloat32(dgFastInt(x));
566  NEWTON_ASSERT(ret == floor(x));
567 
568  return ret;
569 #else
570  return floor(x);
571 #endif
572 }
573 
574 DG_INLINE dgFloat32 dgCeil(dgFloat32 x) {
575 #ifdef _MSC_VER
576  dgFloat32 ret = dgFloor(x);
577 
578  if (ret < x) {
579  ret += dgFloat32(1.0f);
580  }
581 
582  NEWTON_ASSERT(ret == ceil(x));
583 
584  return ret;
585 #else
586  return ceil(x);
587 #endif
588 }
589 
590 #define dgSqrt(x) dgFloat32(sqrt(x))
591 #define dgRsqrt(x) (dgFloat32(1.0f) / dgSqrt(x))
592 #define dgSin(x) dgFloat32(sin(x))
593 #define dgCos(x) dgFloat32(cos(x))
594 #define dgAsin(x) dgFloat32(asin(x))
595 #define dgAcos(x) dgFloat32(acos(x))
596 #define dgAtan2(x, y) dgFloat32(atan2(x, y))
597 #define dgLog(x) dgFloat32(log(x))
598 #define dgPow(x, y) dgFloat32(pow(x, y))
599 #define dgFmod(x, y) dgFloat32(fmod(x, y))
600 
601 typedef dgUnsigned32(dgApi *OnGetPerformanceCountCallback)();
602 
603 dgCpuClass dgApi dgGetCpuType();
604 
605 inline dgInt32 dgAtomicAdd(dgInt32 *const addend, dgInt32 amount) {
606  return *addend += amount;
607 }
608 
609 #endif
Definition: dgTypes.h:474
Definition: dgVector.h:86
Definition: dgTypes.h:464
Definition: dgTypes.h:465
Definition: dgVector.h:104
Definition: dgTypes.h:70