Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
Calc.h
Go to the documentation of this file.
1 //
4 
5 #ifndef _INC_Calc_H
6 #define _INC_Calc_H
7 #ifndef NO_PRAGMA_ONCE
8 #pragma once
9 #endif
10 #if _MSC_VER >= 1000
11 //#pragma warning(disable:4275) // stupid linkage warning.
12 #endif // _MSC_VER >= 1000
13 
14 #include "../GrayLibBase.h"
19 
20 #include <float.h>
21 #include <math.h>
22 
23 namespace GrayLib
24 {
26 
27  typedef float RADIANf_t;
28 
29  static const float k_FLT_MAX2 = ((float)INT_MAX);
30  static const float k_FLT_MIN2 = 0.0001f;
31 
32  typedef int Percent10_t;
33  static const Percent10_t k_Percent10_MAX = 1000;
34 
35  template< typename TYPE = double >
36  struct GRAYLIB_LINK cTypeF : public cTypeLimit<TYPE> // static
37  {
41 
42  // static const TYPE k_NaN; // #NAN // same for both float and double
43  // static const TYPE k_InfPos; // #INF INFINITY
44  // static const TYPE k_InfNeg; // #INF INFINITY
45  // #IND ??
46 
47  static const TYPE k_MinPos;
48  static const TYPE k_MaxSqrt;
49  static const TYPE k_Epsilon;
50 
52  static const TYPE k_PI;
53  static const TYPE k_PI2;
54  static const TYPE k_PIHalf;
55 
56  static const TYPE k_e;
57  static const TYPE k_Log2e;
58  static const TYPE k_Log10e;
59  static const TYPE k_Ln2;
60  static const TYPE k_Ln10;
61  };
62 
63  struct GRAYLIB_LINK CalcI // static
64  {
67 
68  template< typename TYPE >
69  static inline int Sign(TYPE a)
70  {
73  return((a > 0) ? 1 : ((a < 0) ? -1 : 0));
74  }
75  template< typename TYPE >
76  static inline bool IsInRange(TYPE n, TYPE low, TYPE high) noexcept
77  {
79  ASSERT(low <= high);
80  return(n >= low && n <= high);
81  }
82  template< typename TYPE >
83  static inline bool IsInBetween(TYPE n, TYPE a, TYPE b) noexcept
84  {
86  if (a <= b)
87  return IsInRange(n, a, b);
88  else
89  return IsInRange(n, b, a);
90  }
91  template< typename TYPE >
92  static inline TYPE Min(TYPE a, TYPE b) noexcept
93  {
95  return (a < b) ? a : b;
96  }
97  template< typename TYPE >
98  static inline TYPE Max(TYPE a, TYPE b) noexcept
99  {
101  return (a < b) ? b : a;
102  }
103  template< typename TYPE >
104  static inline TYPE Max3(TYPE a, TYPE b, TYPE c) noexcept
105  {
107  TYPE d = Max(a, b);
108  return Max(c, d);
109  }
110  template< typename TYPE >
111  static inline TYPE Clamp(TYPE value, TYPE low, TYPE high)
112  {
115  ASSERT(low <= high);
116  if (value < low)
117  return low;
118  if (value > high)
119  return high;
120  return value;
121  }
122  template< typename TYPE >
123  static inline void ClampRef(TYPE& rValue, TYPE low, TYPE high)
124  {
127  ASSERT(low <= high);
128  TYPE value = rValue;
129  if (value < low)
130  rValue = low;
131  else if (value > high)
132  rValue = high;
133  }
134  template< typename TYPE >
135  static inline bool IsNear(TYPE n1, TYPE n2, TYPE nDiff = (TYPE)k_FLT_MIN2) noexcept
136  {
137  // ASSERT( nDiff >= 0 );
138  return Abs(n1 - n2) <= nDiff ;
139  }
140  template< typename TYPE >
141  static inline TYPE Sqr(TYPE a) noexcept
142  {
144  return a * a ;
145  }
146 
147  template< typename TYPE >
148  static inline TYPE Abs(TYPE a) noexcept;
149  template< typename TYPE >
150  static inline TYPE Mod(TYPE a, TYPE b);
151 
152  template< typename TYPE >
153  static inline TYPE Wrap(TYPE nVal, TYPE nMod)
154  {
156  ASSERT(nMod > 0);
157  TYPE nTmp = Mod(nVal, nMod);
158  if (nTmp < 0)
159  {
160  return nTmp + nMod; // wrap back to positive.
161  }
162  return nTmp;
163  }
164 
165  // Numeric formulas
166  static inline bool IsSignDiff(int a, int b) noexcept
167  {
169  return ((a ^ b) < 0);
170  }
171 
172  template< typename TYPE >
174  {
180  for (;;)
181  {
182  if (y == 0)
183  return x;
184  x = Mod(x, y);
185  if (x == 0)
186  return y;
187  y = Mod(y, x);
188  }
189  }
190 
191  template <typename TYPE>
192  static inline TYPE MulDiv(TYPE a, TYPE b, TYPE c)
193  {
198  // ASSERT(c);
199  return((a*b) / c);
200  }
201 
202  template <typename TYPE>
203  static inline TYPE DivideUp(TYPE a, TYPE b)
204  {
206 #define DIVIDEUP(a,b) (((a) + ((b) - 1)) / (b)) // for use as a constant.
207  return DIVIDEUP(a, b);
208  }
209 
210  template <typename TYPE>
211  static inline TYPE AddC(TYPE a, TYPE b, bool& bCarry) noexcept
212  {
216  TYPE nResult = a + b;
217  if (bCarry) // Handle incoming carry.
218  {
219  nResult++;
220  bCarry = (nResult <= b); // handle the cases of 0xFFFF + 0xFFFF + 1 and 0xFFFF + 0 + 1
221  }
222  else
223  {
224  // If a rollover occurred, the result is less than either input.
225  bCarry = (nResult < b); // e.g. 0xFFFF + 1, 0 + 0, 0xFFFF + 0.
226  }
227  return nResult;
228  }
229 
230  template <typename TYPE>
231  static inline TYPE SubC(TYPE a, TYPE b, bool& bBorrow) noexcept
232  {
235  TYPE nResult = a - b;
236  if (bBorrow) // Handle an incoming borrow
237  {
238  nResult--;
239  bBorrow = (nResult >= a); // special handling for: 0xFFFF - 0xFFFF - 1, 0xFFFF - 0 - 1.
240  }
241  else
242  {
243  // If a reverse rollover occurred, the result is greater than the block from a.
244  bBorrow = (nResult > a); // Pass the borrow along
245  }
246  return nResult;
247  }
248 
249  // TODO
250  // http://stackoverflow.com/questions/13187629/gcc-intrinsic-for-extended-division-multiplication
251  // Mul2 = multiply with high and low results. void extmul(size_t a, size_t b, size_t *lo, size_t *hi);
252  // Div2 = divide with quotient and remainder returned. void extdiv(size_t a, size_t b, size_t *q, size_t *r);
253 
254  template <typename TYPE>
255  static inline bool ToBool(TYPE nVal) noexcept
256  {
258  return (nVal | ((TYPE)(-nVal))) >> ((sizeof(nVal) * 8) - 1); // to 0 or 1
259  }
260 
261  static int GRAYCALL Log2Est(UINT iVal);
262 
263  // return a percentage. e.g. iValDiff=0 returns a 50.0% chance.
264  static Percent10_t GRAYCALL GetSCurve(int iValDiff, int iValVarianceHalf);
265  static Percent10_t GRAYCALL GetBellCurve(int iValDiff, int iValVarianceHalf);
266  };
267 
268 #ifdef UNDER_CE // like _FNF(x)
269 #define _FFF(c) (float) c
270 #else
271 #define _FFF(c) c##f
272 #endif
273 
274  template<> inline float CalcI::Abs<float>(float a) noexcept
275  {
276  return ::fabsf(a);
277  }
278  template<> inline float CalcI::Mod<float>(float a, float b)
279  {
280  return ::fmodf(a, b);
281  }
282 
283  template<> inline double CalcI::Abs<double>(double a) noexcept
284  {
285  return ::fabs(a);
286  }
287  template<> inline double CalcI::Mod<double>(double a, double b)
288  {
290  return ::fmod(a, b);
291  }
292 
293  template<> inline int CalcI::Abs<int>(int a) noexcept
294  {
295  return labs(a);
296  }
297  template<> inline int CalcI::Mod<int>(int a, int b)
298  {
299  return a % b;
300  }
301 
302  template<> inline UINT CalcI::Abs<UINT>(UINT a) noexcept
303  {
305  return ::labs(a);
306  }
307  template<> inline UINT CalcI::Mod<UINT>(UINT a, UINT b)
308  {
309  return(a % b);
310  }
311 
312  template<> inline UINT16 CalcI::MulDiv<UINT16>(UINT16 a, UINT16 b, UINT16 c)
313  {
316  return (UINT16)(((UINT32)a*(UINT32)b) / c);
317  }
318 
319 #ifdef USE_INT64
320  template<> inline UINT32 CalcI::MulDiv<UINT32>(UINT32 a, UINT32 b, UINT32 c)
321  {
324  return (UINT32)(((UINT64)a*(UINT64)b) / c);
325  }
326 #endif
327 
328 #if 0 // defined(_MSC_VER) && defined(_M_AMD64)
329  template<> inline UINT64 CalcI::MulDiv<UINT64>(UINT64 a, UINT64 b, UINT64 c)
330  {
333 
334  UINT64 h;
335  UINT64 l = _umul128(a, b, &h);
336  if (h == 0)
337  {
338  return l / c;
339  }
340  // TODO / c
341  return 0;
342  }
343 #endif
344 
345  //****************************************************************************
346 
347  struct GRAYLIB_LINK Calc : public CalcI, public cTypeFloat // static
348  {
354 
355  template< typename TYPE >
356  static inline bool IsSignDiff(TYPE a, TYPE b) noexcept
357  {
359  return ((a >= 0) ^ (b >= 0)); // sign change
360  }
361 
362  template< typename TYPE >
363  static inline TYPE WrapRadians(TYPE nRadians) noexcept
364  {
368  return Wrap(nRadians, cTypeF<TYPE>::k_PI2);
369  }
370  template< typename TYPE >
371  static inline TYPE WrapRadiansSigned(TYPE nRadians) noexcept
372  {
375  TYPE nTmp = WrapRadians(nRadians);
376  if (nTmp > cTypeF<TYPE>::k_PI)
377  nTmp -= cTypeF<TYPE>::k_PI2;
378  return nTmp;
379  }
380  template< typename TYPE >
381  static inline TYPE GetDiffRadians(TYPE n1, TYPE n2) noexcept
382  {
385  return WrapRadiansSigned(n1 - n2);
386  }
387  template< typename TYPE >
388  static inline TYPE Degree2Radian(TYPE nDegree) noexcept
389  {
391  return (nDegree * (cTypeF<TYPE>::k_PI / (TYPE) 180.0));
392  }
393  template< typename TYPE >
394  static inline TYPE Radian2Degree(TYPE nRadians) noexcept
395  {
397  return (nRadians * ((TYPE) 180.0 / cTypeF<TYPE>::k_PI));
398  }
399  template< typename TYPE >
400  static inline TYPE Lerp(TYPE nVal1, TYPE nVal2, TYPE fRatio) noexcept
401  {
404  return(nVal1 + ((nVal2 - nVal1) * fRatio));
405  }
406 
407  template< typename TYPE >
408  static inline TYPE Round(TYPE a)
409  {
411  if (a < 0)
412  return Floor(a + (TYPE) 0.5);
413  else
414  return Ceil(a - (TYPE) 0.5);
415  }
416 
417  template< typename TYPE >
418  static inline bool IsInteger(TYPE a)
419  {
421  return a == Floor(a);
422  }
423 
425  template< typename TYPE >
426  static inline TYPE Floor(TYPE a);
427  template< typename TYPE >
428  static inline TYPE Ceil(TYPE a);
429  template< typename TYPE >
430  static inline TYPE Sqrt(TYPE a)
431  {
432  ASSERT(0); // No used for int type, etc.
433  return 0;
434  }
435 
436  template< typename TYPE >
437  static inline TYPE Sin(TYPE a);
438  template< typename TYPE >
439  static inline TYPE Cos(TYPE a);
440  template< typename TYPE >
441  static inline TYPE Tan(TYPE a);
442 
444  template< typename TYPE >
445  static inline void SinCos(TYPE a, TYPE& s, TYPE& c);
446 
447  template< typename TYPE >
448  static inline TYPE ASin(TYPE a);
449  template< typename TYPE >
450  static inline TYPE ACos(TYPE a);
451  template< typename TYPE >
452  static inline TYPE ATan(TYPE a);
453 
454  // The signs of the x and y parameters are used to determine the quadrant of the return values within the range of -p to p.
455  // The atan2 HLSL intrinsic function is well-defined for every point other than the origin, even if y equals 0 and x does not equal 0.
456  template< typename TYPE >
457  static inline TYPE ATan2(TYPE y, TYPE x);
458 
459  template< typename TYPE >
460  static inline TYPE Exp(TYPE a);
461  template< typename TYPE >
462  static inline TYPE Log(TYPE a);
463 
465  template< typename TYPE >
466  static inline TYPE Pow(TYPE nBase, TYPE nExp);
467 
468  template< typename TYPE >
469  static inline TYPE Pow10(TYPE x)
470  {
472  return Exp(cTypeF<TYPE>::k_Ln10 * x);
473  }
474  template< typename TYPE >
475  static inline TYPE Pow2(TYPE x)
476  {
478  return Exp(cTypeF<TYPE>::k_Ln2 * x);
479  }
480 
482  template< typename TYPE >
483  static inline TYPE Log10(TYPE a); // negative will throw ?
484 
485  template< typename TYPE >
486  static inline TYPE Log2(TYPE a)
487  {
488  // negative will throw ?
489  return Log(a) * cTypeF<TYPE>::k_Log2e;
490  }
491 
492  template< typename TYPE >
493  static inline TYPE LogN(TYPE x, TYPE b = 10)
494  {
496  return Log(x) / Log(b);
497  }
498 
500  };
501 
502  //***********************************************************
503 
504  template<> inline float Calc::Floor<float>(float a)
505  {
506  return _FFF(::floor)(a);
507  }
508  template<> inline float Calc::Ceil<float>(float a)
509  {
510  return _FFF(::ceil)(a);
511  }
512  template<> inline float Calc::Sqrt<float>(float a)
513  {
514  return _FFF(::sqrt)(a);
515  }
516  template<> inline float Calc::Sin<float>(float a)
517  {
518  // RADIANf_t
519  return _FFF(::sin)(a);
520  }
521  template<> inline float Calc::Cos<float>(float a)
522  {
523  // RADIANf_t
524  return _FFF(::cos)(a);
525  }
526  template<> inline float Calc::Tan<float>(float a)
527  {
528  // RADIANf_t
529  return _FFF(::tan)(a);
530  }
531  template<> inline void Calc::SinCos<float>(float a, float& s, float& c)
532  {
535 #if defined(_MSC_VER) && !defined(USE_64BIT)
536  __asm
537  {
538  fld[a]
539  mov eax, [c]
540  fsincos
541  mov ecx, [s]
542  fstp[eax]
543  fstp[ecx]
544  }
545 #else
546  s = _FFF(::sin)(a);
547  c = _FFF(::cos)(a);
548 #endif
549  }
550  template<> inline float Calc::ASin<float>(float a)
551  {
552  return _FFF(::asin)(a);
553  }
554  template<> inline float Calc::ACos<float>(float a)
555  {
556  return _FFF(::acos)(a);
557  }
558  template<> inline float Calc::ATan<float>(float a)
559  {
560  return _FFF(::atan)(a);
561  }
562  template<> inline float Calc::ATan2<float>(float y, float x)
563  {
564  return _FFF(::atan2)(y, x);
565  }
566  template<> inline float Calc::Log<float>(float a)
567  {
568  return _FFF(::log)(a);
569  }
570  template<> inline float Calc::Log10<float>(float a)
571  {
572  return _FFF(::log10)(a);
573  }
574  template<> inline float Calc::Exp<float>(float a)
575  {
576  return _FFF(::exp)(a);
577  }
578  template<> inline float Calc::Pow<float>(float a, float nExp)
579  {
580  return _FFF(::pow)(a, nExp);
581  }
582 
583 #undef _FFF
584 
585  //***********************************************************
586 
587  template<> inline double Calc::Floor<double>(double a)
588  {
589  return ::floor(a);
590  }
591  template<> inline double Calc::Ceil<double>(double a)
592  {
593  return ::ceil(a);
594  }
595  template<> inline double Calc::Sqrt<double>(double a)
596  {
597  return ::sqrt(a);
598  }
599  template<> inline double Calc::Sin<double>(double a)
600  {
601  return ::sin(a);
602  }
603  template<> inline double Calc::Cos<double>(double a)
604  {
605  return ::cos(a);
606  }
607  template<> inline double Calc::Tan<double>(double a)
608  {
609  return ::tan(a);
610  }
611  template<> inline void Calc::SinCos<double>(double a, double& s, double& c)
612  {
615 #if defined(_MSC_VER) && !defined(USE_64BIT)
616  __asm
617  {
618  fld qword ptr[a]
619  mov eax, dword ptr[c]
620  mov ebx, dword ptr[s]
621  fsincos
622  fstp qword ptr[eax]
623  fstp qword ptr[ebx]
624  }
625 #else
626  s = ::sin(a);
627  c = ::cos(a);
628 #endif
629  }
630  template<> inline double Calc::ASin<double>(double a)
631  {
632  return ::asin(a);
633  }
634  template<> inline double Calc::ACos<double>(double a)
635  {
636  return ::acos(a);
637  }
638  template<> inline double Calc::ATan<double>(double a)
639  {
640  return ::atan(a);
641  }
642  template<> inline double Calc::ATan2<double>(double y, double x)
643  {
644  return ::atan2(y, x);
645  }
646  template<> inline double Calc::Log<double>(double a)
647  {
648  return ::log(a);
649  }
650  template<> inline double Calc::Log10<double>(double a)
651  {
652  return ::log10(a);
653  }
654  template<> inline double Calc::Exp<double>(double a)
655  {
656  return ::exp(a);
657  }
658  template<> inline double Calc::Pow<double>(double a, double nExp)
659  {
660  return ::pow(a, nExp);
661  }
662 }
663 #endif // _INC_Calc_H
#define DIVIDEUP(a, b)
#define _FFF(c)
Definition: Calc.h:271
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define GRAYLIB_LINK
Definition: GrayLibBase.h:35
#define TYPE
Definition: StrT.cpp:38
#define ASSERT(exp)
Definition: cDebugAssert.h:87
Definition: cMesh.h:22
UNITTEST2_PREDEF(cQuadtree)
int Percent10_t
tenths of a percent. 0 to 1000 = 0 to 100.0
Definition: Calc.h:32
float RADIANf_t
type is float radians
Definition: Calc.h:27
Definition: Calc.h:64
static TYPE MulDiv(TYPE a, TYPE b, TYPE c)
Definition: Calc.h:192
static TYPE Max(TYPE a, TYPE b) noexcept
Definition: Calc.h:98
static bool IsInRange(TYPE n, TYPE low, TYPE high) noexcept
Definition: Calc.h:76
static TYPE SubC(TYPE a, TYPE b, bool &bBorrow) noexcept
Definition: Calc.h:231
static bool ToBool(TYPE nVal) noexcept
Definition: Calc.h:255
static bool IsInBetween(TYPE n, TYPE a, TYPE b) noexcept
Definition: Calc.h:83
static TYPE Wrap(TYPE nVal, TYPE nMod)
Definition: Calc.h:153
static TYPE Max3(TYPE a, TYPE b, TYPE c) noexcept
Definition: Calc.h:104
static TYPE Abs(TYPE a) noexcept
similar to ABS(n) macro. Does nothing for unsigned types.
static TYPE Mod(TYPE a, TYPE b)
a modulus b = remainder of a/b
static TYPE Min(TYPE a, TYPE b) noexcept
Definition: Calc.h:92
static void ClampRef(TYPE &rValue, TYPE low, TYPE high)
Definition: Calc.h:123
static TYPE GetGreatestCommonDivisor(TYPE x, TYPE y)
Definition: Calc.h:173
static bool IsNear(TYPE n1, TYPE n2, TYPE nDiff=(TYPE) k_FLT_MIN2) noexcept
Definition: Calc.h:135
static TYPE Clamp(TYPE value, TYPE low, TYPE high)
Definition: Calc.h:111
static TYPE Sqr(TYPE a) noexcept
Definition: Calc.h:141
static TYPE AddC(TYPE a, TYPE b, bool &bCarry) noexcept
Definition: Calc.h:211
static int Sign(TYPE a)
Definition: Calc.h:69
static bool IsSignDiff(int a, int b) noexcept
Definition: Calc.h:166
static TYPE DivideUp(TYPE a, TYPE b)
Definition: Calc.h:203
Definition: Calc.h:348
static TYPE Sin(TYPE a)
static TYPE ACos(TYPE a)
static TYPE GetDiffRadians(TYPE n1, TYPE n2) noexcept
Definition: Calc.h:381
static TYPE ATan(TYPE a)
static TYPE WrapRadiansSigned(TYPE nRadians) noexcept
Definition: Calc.h:371
static TYPE Tan(TYPE a)
static TYPE Floor(TYPE a)
get the closest whole integer. positive or negative values.
static TYPE Cos(TYPE a)
static TYPE WrapRadians(TYPE nRadians) noexcept
Definition: Calc.h:363
static TYPE Log10(TYPE a)
static bool IsInteger(TYPE a)
Definition: Calc.h:418
static TYPE Log2(TYPE a)
Definition: Calc.h:486
static TYPE Sqrt(TYPE a)
Definition: Calc.h:430
static TYPE Radian2Degree(TYPE nRadians) noexcept
Definition: Calc.h:394
static TYPE Pow2(TYPE x)
Definition: Calc.h:475
UNITTEST_FRIEND(Calc)
static void SinCos(TYPE a, TYPE &s, TYPE &c)
get both sin and cos at one time. a = Euler angle in radians
static TYPE Round(TYPE a)
Definition: Calc.h:408
static TYPE Degree2Radian(TYPE nDegree) noexcept
Definition: Calc.h:388
static TYPE Pow10(TYPE x)
Definition: Calc.h:469
static bool IsSignDiff(TYPE a, TYPE b) noexcept
Definition: Calc.h:356
static TYPE Exp(TYPE a)
static TYPE LogN(TYPE x, TYPE b=10)
Definition: Calc.h:493
static TYPE Pow(TYPE nBase, TYPE nExp)
pow(nBase,nExp) = exp( log(nBase) * nExp );
static TYPE Ceil(TYPE a)
static TYPE Lerp(TYPE nVal1, TYPE nVal2, TYPE fRatio) noexcept
Definition: Calc.h:400
static TYPE ATan2(TYPE y, TYPE x)
static TYPE ASin(TYPE a)
static TYPE Log(TYPE a)
Natural (e) log. // negative will throw ?
Definition: Calc.h:37
static const TYPE k_PIHalf
Half PI.
Definition: Calc.h:54
static const TYPE k_PI2
PI times 2. M_PI.
Definition: Calc.h:53
static const TYPE k_e
M_E = 2.718281828...
Definition: Calc.h:56
static const TYPE k_MaxSqrt
The square root of <= k_Max. Not Max+1.
Definition: Calc.h:48
static const TYPE k_Epsilon
smallest positive value such that (1.0+FLT_EPSILON != 1.0)
Definition: Calc.h:49
static const TYPE k_PI
PI as a float or double. like M_PI, D3DX_PI.
Definition: Calc.h:52
static const TYPE k_Log10e
M_LOG10E = log10(e) = 1/ln(10)
Definition: Calc.h:58
static const TYPE k_Ln10
M_LN10 = ln(10) = 1/log10(e)
Definition: Calc.h:60
static const TYPE k_MinPos
The min value that is positive and > 0. AKA FLT_MIN and DBL_MIN.
Definition: Calc.h:47
static const TYPE k_Ln2
M_LN2 = ln(2) = 1/log2(e)
Definition: Calc.h:59
static const TYPE k_Log2e
M_LOG2E = log2(e) = 1/ln(2)
Definition: Calc.h:57
Definition: cTypes.h:178
Definition: cTypes.h:152