Ocean
Numeric.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_NUMERIC_H
9 #define META_OCEAN_MATH_NUMERIC_H
10 
11 #include "ocean/math/Math.h"
12 
13 #include "ocean/base/DataType.h"
14 
15 #include <cfloat>
16 #include <climits>
17 #include <cmath>
18 #include <complex>
19 #include <cstdlib>
20 #include <limits>
21 
22 namespace Ocean
23 {
24 
25 // Forward declaration.
26 template <typename T> class NumericT;
27 
28 /**
29  * Definition of a Numeric class.
30  * @see NumericT
31  * @ingroup math
32  */
34 
35 /**
36  * Definition of a Numeric class with double values.
37  * @see NumericT
38  * @ingroup math
39  */
41 
42 /**
43  * Definition of a Numeric class with float values.
44  * @see NumericT
45  * @ingroup math
46  */
48 
49 /**
50  * This class provides basic numeric functionalities.
51  * @tparam T Data type of the numeric elements
52  * @see Numeric, NumericF, NumericD.
53  * @ingroup math
54  */
55 template <typename T>
56 class NumericT
57 {
58  public:
59 
60  /**
61  * Returns PI which is equivalent to 180 degree.
62  * @return PI
63  */
64  static constexpr T pi();
65 
66  /**
67  * Returns 2*PI which is equivalent to 360 degree.
68  * @return 2*PI
69  */
70  static constexpr T pi2();
71 
72  /**
73  * Returns PI/2 which is equivalent to 90 degree.
74  * @return PI/2
75  */
76  static constexpr T pi_2();
77 
78  /**
79  * Returns PI/3 which is equivalent to 60 degree.
80  * @return PI/3
81  */
82  static constexpr T pi_3();
83 
84  /**
85  * Returns PI/4 which is equivalent to 45 degree.
86  * @return PI/4
87  */
88  static constexpr T pi_4();
89 
90  /**
91  * Returns the square of PI i.e., PI^2.
92  * @return PI^2
93  */
94  static constexpr T squarePi();
95 
96  /**
97  * Returns the square of two PI i.e., (2*PI)^2.
98  * @return (2*PI)^2
99  */
100  static constexpr T squarePi2();
101 
102  /**
103  * Returns the square of PI half i.e., (PI/2)^2.
104  * @return (PI/2)^2
105  */
106  static constexpr T squarePi_2();
107 
108  /**
109  * Returns the euler's number.
110  * @return Euler's number
111  */
112  static constexpr T e();
113 
114  /**
115  * Returns a small epsilon.
116  * @return Small epsilon
117  */
118  static constexpr T eps();
119 
120  /**
121  * Returns a weak epsilon.
122  * @return Weak epsilon
123  */
124  static constexpr T weakEps();
125 
126  /**
127  * Returns the absolute value of a given value.
128  * Beware some values do not have a corresponding absolute value e.g., -128 for (8bit signed chars), -32768 for (16bit signed chars), and so on.
129  * @param value The value for which the absolute value will be returned
130  * @return Absolute value
131  * @see secureAbs().
132  */
133  static inline T abs(const T value);
134 
135  /**
136  * Returns the absolute value of a given value while the return value is guaranteed to be the absolute value of the input value.
137  * This function returns the unsigned data type T (if possible) and ensures that the absolute value of the minimal integer value is correct.
138  * @param value The value for which the absolute value will be returned
139  * @return Absolute value
140  * @see abs().
141  */
142  static inline typename UnsignedTyper<T>::Type secureAbs(const T value);
143 
144  /**
145  * Returns the square of a given value.
146  * @param value The value to return the square from
147  * @return Square value
148  */
149  static constexpr inline T sqr(const T value);
150 
151  /**
152  * Returns the sum of given values.
153  * @param values The values to return the sum from
154  * @param number The number of given values
155  * @return Sum of elements
156  */
157  static inline T sum(const T* values, const size_t number);
158 
159  /**
160  * Returns the summed squares of a given values.
161  * @param values The values to return the summed squares from
162  * @param number The number of given values
163  * @return Summed squared result
164  */
165  static inline T summedSqr(const T* values, const size_t number);
166 
167  /**
168  * Returns the square distance between two values.
169  * @param value0 First value
170  * @param value1 Second value
171  * @return Square distance
172  */
173  static constexpr inline T sqrDistance(const T value0, const T value1);
174 
175  /**
176  * Returns the square root of a given value.
177  * @param value The value to return the square root from, with range [0, infinity)
178  * @return Square root
179  */
180  static inline T sqrt(const T value);
181 
182  /**
183  * Returns the square root of a given value.
184  * @param value The value to return the square root from
185  * @return Square root
186  */
187  static inline std::complex<T> sqrt(const std::complex<T>& value);
188 
189  /**
190  * Returns the sine of a given value.
191  * @param value The value to return the sine from, with range (-infinity, infinity)
192  * @return Sine value
193  */
194  static inline T sin(const T value);
195 
196  /**
197  * Returns the cosine of a given value.
198  * @param value The value to return the cosine from, with range (-infinity, infinity)
199  * @return Cosine value
200  */
201  static inline T cos(const T value);
202 
203  /**
204  * Returns the tangent of a given value.
205  * @param value The value to return the tangent from, with range (-infinity, infinity)
206  * @return Tangent value
207  */
208  static inline T tan(const T value);
209 
210  /**
211  * Returns the arcsine of a given value.
212  * @param value The value to return the arc sine from, with range [-1, 1]
213  * @return Arcsine value, with range [-PI/2, PI/2]
214  */
215  static inline T asin(const T value);
216 
217  /**
218  * Returns the arccosine of a given value.
219  * @param value The value to return the arc cosine from, with range [-1, 1]
220  * @return Arccosine value in radian, with range [0, PI]
221  */
222  static inline T acos(const T value);
223 
224  /**
225  * Returns the arctangent of a given value.
226  * @param value The value to return the arctangent from
227  * @return Arctangent value, with range [-PI/2, PI/2]
228  */
229  static inline T atan(const T value);
230 
231  /**
232  * Returns the arctangent of a given value in radian.
233  * @param y Opposite value, must not be zero if x is zero
234  * @param x Adjacent value, must not be zero if y is zero
235  * @return Arctangent value, with range [-PI, PI]
236  */
237  static inline T atan2(const T y, const T x);
238 
239  /**
240  * Returns the base-e exponential function of a given value.
241  * @param value The value to determine the exponential value for, with range (-infinity, infinity)
242  * @return Exponential value
243  */
244  static inline T exp(const T value);
245 
246  /**
247  * Returns the natural logarithm of a given value (the logarithm to the base e).
248  * @param value The value to return the logarithm for, with range (0, infinity)
249  * @return Natural logarithm
250  */
251  static inline T log(const T value);
252 
253  /**
254  * Returns the natural logarithm of a given value plus 1 (the logarithm to the base e).
255  * This function has better precision than log(1 + value) when value is close to 0.
256  * @param value Input for which logarithm of (1 + value) will be returned, with range (-1, infinity)
257  * @return Natural logarithm
258  */
259  static inline T log1p(const T value);
260 
261  /**
262  * Returns the logarithm to base 2 of a given value.
263  * @param value The value to return the logarithm for, with range (0, infinity)
264  * @return Logarithm to base 2
265  */
266  static inline T log2(const T value);
267 
268  /**
269  * Returns the logarithm to base 10 of a given value.
270  * @param value The value to return the logarithm for, with range (0, infinity)
271  * @return Logarithm to base 10
272  */
273  static inline T log10(const T value);
274 
275  /**
276  * Returns the floating-point remainder of a given value.
277  * @param valueA Value to return the floating-point remainder from
278  * @param valueB Divisor value
279  * @return Floating-point remainder
280  */
281  static inline T fmod(const T valueA, const T valueB);
282 
283  /**
284  * Returns the dot product for two vectors.
285  * @param vectorA The first vector, can be nullptr if size is 0
286  * @param vectorB The second vector, can be nullptr if size is 0
287  * @param size The size/dimension of both vector (the number of elements each vector holds), with range [0, infinity)
288  * @return The resulting dot product
289  */
290  static inline T dot(const T* vectorA, const T* vectorB, const size_t size);
291 
292  /**
293  * Adjusts an arbitrary angle into the range of [0.0, 2PI).
294  * @param angle The angle to be adjusted, defined in radian, with range (-infinity, infinity)
295  * @return Adjusted angle with range [0.0, 2PI)
296  */
297  static inline T angleAdjustPositive(const T angle);
298 
299  /**
300  * Adjusts an arbitrary angle into the range of [0.0, PI).
301  * @param angle The angle to be adjusted, defined in radian, with range (-infinity, infinity)
302  * @return Adjusted angle with range [0.0, PI)
303  */
304  static inline T angleAdjustPositiveHalf(const T angle);
305 
306  /**
307  * Adjusts an arbitrary angle into the range of (-PI, PI].
308  * @param angle The angle to be adjusted, defined in radian, with range (-infinity, infinity)
309  * @return Adjusted angle with range (-PI, PI]
310  */
311  static inline T angleAdjustNull(const T angle);
312 
313  /**
314  * Returns whether two angles represent the same angle up to a small epsilon.
315  * @param angleA First angle specified in radian, with range (-infinity, infinity)
316  * @param angleB Second angle specified in radian, with range (-infinity, infinity)
317  * @return True, if so
318  */
319  static inline bool angleIsEqual(const T angleA, const T angleB);
320 
321  /**
322  * Returns whether two angles represent the same angle up to a weak epsilon.
323  * @param angleA First angle specified in radian, with range (-infinity, infinity)
324  * @param angleB Second angle specified in radian, with range (-infinity, infinity)
325  * @return True, if so
326  */
327  static inline bool angleIsWeakEqual(const T angleA, const T angleB);
328 
329  /**
330  * Returns whether two angles represent the same angle up to a given epsilon.
331  * @param angleA First angle specified in radian, with range (-infinity, infinity)
332  * @param angleB Second angle specified in radian, with range (-infinity, infinity)
333  * @param epsilon Accuracy epsilon in radian, with range [0, infinity)
334  * @return True, if so
335  */
336  static inline bool angleIsEqual(const T angleA, const T angleB, const T epsilon);
337 
338  /**
339  * Returns whether the angular difference (distance) between two angles is smaller than a specified threshold.
340  * @param angleA First angle specified in radian, with range (-infinity, infinity)
341  * @param angleB Second angle specified in radian, with range (-infinity, infinity)
342  * @param threshold Positive angular threshold in radian with range [0, PI)
343  * @return True, if so
344  */
345  static inline bool angleIsBelowThreshold(const T angleA, const T angleB, const T threshold);
346 
347  /**
348  * Returns the angular difference (distance between two angles).
349  * @param angleA First angle specified in radian, with range (-infinity, infinity)
350  * @param angleB Second angle specified in radian, with range (-infinity, infinity)
351  * @return Absolute distance between both angles, in radian
352  */
353  static inline T angleDistance(const T angleA, const T angleB);
354 
355  /**
356  * Returns x raised to the power of y.
357  * @param x X value, with range (-infinity, infinity), must not be negative if y < 1
358  * @param y Y value, with range (-infinity, infinity)
359  * @return The power result
360  */
361  static inline T pow(const T x, const T y);
362 
363  /**
364  * Returns x raised to the power of y.
365  * @param x X value
366  * @param y Y value
367  * @return The power result
368  */
369  static inline std::complex<T> pow(const std::complex<T>& x, const T y);
370 
371  /**
372  * Returns x raised to the power of y while y is an integer.
373  * @param x X value, with range [0, infinity)
374  * @param y Y value, with range (-infinity, infinity)
375  * @return The power result
376  */
377  static constexpr T integerPow(const T x, const unsigned int y);
378 
379  /**
380  * Returns the factorial for a given value.
381  * @param value The value for that the factorial will be determined, with range [0, infinity) for floating point types; with range [0, 12] for 32 bit integer types
382  * @return Resulting factorial, with range [0, infinity)
383  */
384  static constexpr inline T factorial(const T& value);
385 
386  /**
387  * Returns the binomial coefficient for two binomial parameters.
388  * This function calculates: n! / (k! * (n - k)!).<br>
389  * @param n Upper binomial coefficient parameter, with range [0, infinity)
390  * @param k Lower binomial coefficient parameter, with range [0, n]
391  * @return Resulting binomial coefficient
392  */
393  static constexpr inline T binomialCoefficient(const T& n, const T& k);
394 
395  /**
396  * Returns the smallest integer value that is not less than the given value.
397  * @param value The value to handle, with range (-infinity, infinity)
398  * @return Smallest integer value
399  */
400  static inline T ceil(const T value);
401 
402  /**
403  * Returns the largest integer value that is not greater than the given value.
404  * @param value The value to handle, with range (-infinity, infinity)
405  * @return Largest integer value
406  */
407  static inline T floor(const T value);
408 
409  /**
410  * Returns the rounded 32 bit integer value of a given value.
411  * The function applies a symmetric rounding:
412  * <pre>
413  * Input: -1.50 -1.49 -0.50 -0.49 | 0.49 0.50 1.49 1.50
414  * Output: -2 -1 -1 0 | 0 1 1 2
415  *
416  * So that for positive integer x:
417  * x <- [x - 0.5, x + 0.5)
418  *
419  * and for negative integer x:
420  * x <- (x - 0.5, x + 0.5]
421  * </pre>
422  * @param value The value to handle, with range (-infinity, infinity)
423  * @return Rounded value
424  */
425  static constexpr inline int32_t round32(const T value);
426 
427  /**
428  * Returns the rounded 64 bit integer value of a given value.
429  * The function applies a symmetric rounding:
430  * <pre>
431  * Input: -1.50 -1.49 -0.50 -0.49 | 0.49 0.50 1.49 1.50
432  * Output: -2 -1 -1 0 | 0 1 1 2
433  *
434  * So that for positive integer x:
435  * x <- [x - 0.5, x + 0.5)
436  *
437  * and for negative integer x:
438  * x <- (x - 0.5, x + 0.5]
439  * </pre>
440  * @param value The value to handle, with range (-infinity, infinity)
441  * @return Rounded value
442  */
443  static constexpr inline int64_t round64(const T value);
444 
445  /**
446  * Returns the ratio between two values if the denominator is not equal a small epsilon.
447  * @param nominator The nominator of the resulting ratio
448  * @param denominator The denominator of the resulting ratio
449  * @param fallback The fallback value if the denominator is equal eps()
450  * @return The ratio between both values, the 'fallback' if the denominator is equal eps()
451  */
452  static constexpr inline T ratio(const T nominator, const T denominator, const T fallback = T(1));
453 
454  /**
455  * Returns whether a value is smaller than or equal to a small epsilon.
456  * @param value The value to check, with range (-infinity, infinity)
457  * @return True, if so
458  */
459  static constexpr inline bool isEqualEps(const T value);
460 
461  /**
462  * Returns whether a complex value is smaller than or equal to a small epsilon.
463  * @param value Complex value to check
464  * @return True, if so
465  */
466  static constexpr inline bool isEqualEps(const std::complex<T>& value);
467 
468  /**
469  * Returns whether a value is smaller than or equal to a weak epsilon.
470  * @param value The value to check, with range (-infinity, infinity)
471  * @return True, if so
472  */
473  static constexpr inline bool isWeakEqualEps(const T value);
474 
475  /**
476  * Returns whether a complex value is smaller than or equal to a weak epsilon.
477  * @param value Complex value to check
478  * @return True, if so
479  */
480  static constexpr inline bool isWeakEqualEps(const std::complex<T>& value);
481 
482  /**
483  * Returns whether a value is not smaller than or equal to a small epsilon.
484  * @param value The value to check, with range (-infinity, infinity)
485  * @return True, if so
486  */
487  static constexpr inline bool isNotEqualEps(const T value);
488 
489  /**
490  * Returns whether a complex value is not smaller than or equal to a small epsilon.
491  * @param value Complex value to check
492  * @return True, if so
493  */
494  static constexpr inline bool isNotEqualEps(const std::complex<T>& value);
495 
496  /**
497  * Returns whether a value is not smaller than or equal to a weak epsilon.
498  * @param value The value to check, with range (-infinity, infinity)
499  * @return True, if so
500  */
501  static constexpr inline bool isNotWeakEqualEps(const T value);
502 
503  /**
504  * Returns whether a complex value is not smaller than or equal to a weak epsilon.
505  * @param value Complex value to check
506  * @return True, if so
507  */
508  static constexpr inline bool isNotWeakEqualEps(const std::complex<T>& value);
509 
510  /**
511  * Returns whether two values are equal up to a small epsilon.
512  * @param first The first value to check, with range (-infinity, infinity)
513  * @param second The second value to check, with range (-infinity, infinity)
514  * @return True, if so
515  */
516  static inline bool isEqual(const T first, const T second);
517 
518  /**
519  * Returns whether two complex values are equal up to a small epsilon.
520  * @param first The first value to check
521  * @param second The second value to check
522  * @return True, if so
523  */
524  static inline bool isEqual(const std::complex<T>& first, const std::complex<T>& second);
525 
526  /**
527  * Returns whether two values a equal up to a weak epsilon.
528  * @param first The first value to check, with range (-infinity, infinity)
529  * @param second The second value to check, with range (-infinity, infinity)
530  * @return True, if so
531  */
532  static inline bool isWeakEqual(const T first, const T second);
533 
534  /**
535  * Returns whether two complex values are equal up to a weak epsilon.
536  * @param first The first value to check
537  * @param second The second value to check
538  * @return True, if so
539  */
540  static inline bool isWeakEqual(const std::complex<T>& first, const std::complex<T>& second);
541 
542  /**
543  * Returns whether two values are equal up to a given epsilon.
544  * @param first The first value to check, with range (-infinity, infinity)
545  * @param second The second value to check, with range (-infinity, infinity)
546  * @param epsilon Accuracy epsilon, with range [0, infinity)
547  * @return True, if so
548  */
549  static inline bool isEqual(const T first, const T second, const T epsilon);
550 
551  /**
552  * Returns whether two complex values are equal up to a given epsilon.
553  * @param first The first value to check
554  * @param second The second value to check
555  * @param epsilon Accuracy epsilon, with range [0, infinity)
556  * @return True, if so
557  */
558  static inline bool isEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon);
559 
560  /**
561  * Returns whether two values are equal up to a dynamic epsilon which is adjusted due to the magnitude of both values and the reference magnitude.
562  * The reference magnitude (provided as template parameter) corresponds to the provided reference epsilon.<br>
563  * That means that if the magnitude of both values to compare is equal to the defined reference magnitude the given epsilon value is used for comparison.<br>
564  * Otherwise the given epsilon is increased by 10 times the difference between the magnitude of the values and the reference magnitude, the epsilon value will not be decreased if the actual magnitude is smaller than the reference magnitude.
565  * @param first The first value to check, with range (-infinity, infinity)
566  * @param second The second value to check, with range (-infinity, infinity)
567  * @param referenceEpsilon The accuracy epsilon for the specified magnitude, with range [0, infinity)
568  * @return True, if so
569  * @tparam tMagnitude The reference magnitude for which the specified epsilon must hold so that both values count as equal, with range [-20, 20]
570  */
571  template <int tMagnitude>
572  static inline bool isEqual(const T first, const T second, const T referenceEpsilon);
573 
574  /**
575  * Returns whether two values are not equal up to a small epsilon.
576  * @param first The first value to check, with range (-infinity, infinity)
577  * @param second The second value to check, with range (-infinity, infinity)
578  * @return True, if so
579  */
580  static inline bool isNotEqual(const T first, const T second);
581 
582  /**
583  * Returns whether two complex values are not equal up to a small epsilon.
584  * @param first The first value to check
585  * @param second The second value to check
586  * @return True, if so
587  */
588  static inline bool isNotEqual(const std::complex<T>& first, const std::complex<T>& second);
589 
590  /**
591  * Returns whether two values are not equal up to a weak epsilon.
592  * @param first The first value to check, with range (-infinity, infinity)
593  * @param second The second value to check, with range (-infinity, infinity)
594  * @return True, if so
595  */
596  static inline bool isNotWeakEqual(const T first, const T second);
597 
598  /**
599  * Returns whether two complex values are not equal up to a weak epsilon.
600  * @param first The first value to check
601  * @param second The second value to check
602  * @return True, if so
603  */
604  static inline bool isNotWeakEqual(const std::complex<T>& first, const std::complex<T>& second);
605 
606  /**
607  * Returns whether two values are not equal up to a given epsilon.
608  * @param first The first value to check, with range (-infinity, infinity)
609  * @param second The second value to check, with range (-infinity, infinity)
610  * @param epsilon Accuracy epsilon, with range [0, infinity)
611  * @return True, if so
612  */
613  static inline bool isNotEqual(const T first, const T second, const T epsilon);
614 
615  /**
616  * Returns whether two complex values are not equal up to a given epsilon.
617  * @param first The first value to check
618  * @param second The second value to check
619  * @param epsilon Accuracy epsilon, with range [0, infinity)
620  * @return True, if so
621  */
622  static inline bool isNotEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon);
623 
624  /**
625  * Returns whether a value lies between a given range up to a provided epsilon border.
626  * @param lower The lower border, with range (-infinity, infinity)
627  * @param value The value to check, with range (-infinity, infinity)
628  * @param upper The upper border, with range [lower, infinity)
629  * @param epsilon Accuracy epsilon, with range [0, infinity)
630  * @return True, if so
631  */
632  static constexpr bool isInsideRange(const T lower, const T value, const T upper, const T epsilon = NumericT<T>::eps());
633 
634  /**
635  * Returns whether a value lies between a given range up to a weak epsilon border.
636  * @param lower The lower border, with range (-infinity, infinity)
637  * @param value The value to check, with range (-infinity, infinity)
638  * @param upper The upper border, with range [lower, infinity)
639  * @return True, if so
640  */
641  static constexpr bool isInsideWeakRange(const T lower, const T value, const T upper);
642 
643  /**
644  * Returns whether a parameter lies on or below a given border tolerating a small epsilon.
645  * @param value The value to check, with range (-infinity, infinity)
646  * @param upper The upper border, with range (-infinity, infinity)
647  * @param epsilon Accuracy epsilon, with range [0, infinity)
648  * @return True, if 'value <= upper + epsilon'
649  */
650  static constexpr bool isBelow(const T value, const T upper, const T epsilon = NumericT<T>::eps());
651 
652  /**
653  * Returns whether a parameter lies on or above a given border tolerating a small epsilon.
654  * @param value The value to check, with range (-infinity, infinity)
655  * @param lower The lower border, with range (-infinity, infinity)
656  * @param epsilon Accuracy epsilon, with range [0, infinity)
657  * @return True, if 'lower - epsilon <= value'
658  */
659  static constexpr bool isAbove(const T value, const T lower, const T epsilon = NumericT<T>::eps());
660 
661  /**
662  * Returns a value which is not a number (nan).
663  * @return The nan value
664  */
665  static constexpr T nan();
666 
667  /**
668  * Returns whether a given value is not a number.
669  * @param value The value to check
670  * @return True, if so
671  */
672  static inline bool isNan(const T value);
673 
674  /**
675  * Returns whether a given value is not a number.
676  * @param value The value to check
677  * @return True, if so
678  */
679  static inline bool isNan(const std::complex<T>& value);
680 
681  /**
682  * Returns a value which is positive infinity.
683  * @return Positive infinity
684  */
685  static constexpr T inf();
686 
687  /**
688  * Returns whether a given value is positive or negative infinity.
689  * Only floating point values can be infinity.
690  * @param value The value to check
691  * @return True, if so
692  */
693  static inline bool isInf(const T value);
694 
695  /**
696  * Returns whether a given value is positive or negative infinity.
697  * Only floating point values can be infinity.
698  * @param value The value to check
699  * @return True, if so
700  */
701  static inline bool isInf(const std::complex<T>& value);
702 
703  /**
704  * Returns whether a given value of an arbitrary data type fits into the value range of 'T'.
705  * Below the behavior for individual data types:
706  * <pre>
707  * T TValue return
708  * A A true
709  * float float true
710  * double double true
711  * uint8_t int8_t >= 0
712  * int8_t uint8_t <= 127
713  * uint8_t uint16_t true
714  * uint8_t uint32_t true
715  * ...
716  * float Integral false
717  * double Integral false
718  * Integral float false
719  * Integral double false
720  * </pre>
721  * @param value The value to check, with range (-infinity, infinity)
722  * @return True, if value fits into 'T', or 'T' is same as 'TValue'
723  * @tparam TValue The data type of the given value
724  */
725  template <typename TValue>
726  static inline bool isInsideValueRange(const TValue& value);
727 
728  /**
729  * Converts deg to rad.
730  * @param deg Angle in deg, with range (-infinity, infinity)
731  * @return Angle in radian
732  */
733  static constexpr inline T deg2rad(const T deg);
734 
735  /**
736  * Converts rad to deg.
737  * @param rad Angle in radian, with range (-infinity, infinity)
738  * @return Angle in deg
739  */
740  static constexpr inline T rad2deg(const T rad);
741 
742  /**
743  * Returns the max scalar value.
744  * @return Max value
745  */
746  static constexpr inline T maxValue();
747 
748  /**
749  * Returns the min scalar value.
750  * @return Min value
751  */
752  static constexpr inline T minValue();
753 
754  /**
755  * Returns the sign of a given value by either returning -1, 0, or +1.
756  * Negative values have return value -1, 0 has return value 0, and positive values have return value +1.
757  * @param value The value for which the sign will be returned
758  */
759  static constexpr inline T sign(const T& value);
760 
761  /**
762  * Copies the sign of a given value to another one.
763  * @param signReceiver First value receiving the sign from the second value
764  * @param signProvider Second value providing the sign for the first one
765  * @return First value with the sign of the second one
766  */
767  static constexpr inline T copySign(const T signReceiver, const T signProvider);
768 
769  /**
770  * Copies the inverted sign of a given value to another one.
771  * @param signReceiver First value receiving the inverted sign from the second value
772  * @param signProvider Second value providing the inverted sign for the first one
773  * @return First value with the inverted sign of the second one
774  */
775  static constexpr inline T invertSign(const T signReceiver, const T signProvider);
776 
777  /**
778  * Returns the length of the hypotenuse of a given right-angled triangle.
779  * This function avoids the calculation of square values of a and b.
780  * @param a Length of the first leg
781  * @param b Length of the second leg
782  * @return (a^2 + b^2)^0.5
783  */
784  static T pythagoras(const T a, const T b);
785 
786  /**
787  * Returns a value of the univariate Gaussian distribution centered around the origin.
788  * @param x Value to return the Gaussian distribution value for
789  * @param sigma The sigma parameter defining the standard deviation of the Gaussian distribution, with range (0, infinity)
790  * @return Function value
791  */
792  static inline T gaussianDistribution(const T x, const T sigma);
793 
794  /**
795  * Returns a value of the univariate Gaussian distribution centered around a given position x0.
796  * @param x Value to return the Gaussian distribution value for
797  * @param x0 X value for the center of the Gaussian distribution
798  * @param sigma The sigma parameter defining the standard deviation of the Gaussian distribution, with range (0, infinity)
799  * @return Function value
800  */
801  static inline T gaussianDistribution(const T x, const T x0, const T sigma);
802 
803  /**
804  * Returns a value of the normalized univariate Gaussian distribution centered around the origin.
805  * As the result is normalized, the resulting Gaussian distribution value is 1 at the origin.<br>
806  * @param x Value to return the Gaussian distribution value for
807  * @param sigma The sigma parameter defining the standard deviation of the Gaussian distribution, with range (0, infinity)
808  * @return Function value
809  */
810  static inline T normalizedGaussianDistribution(const T x, const T sigma);
811 
812  /**
813  * Returns a value of the normalized univariate Gaussian distribution around a given position x0.
814  * As the result is normalized, the resulting Gaussian distribution value is 1 at the given position x0.<br>
815  * @param x Value to return the Gaussian distribution value for
816  * @param x0 X value for the center of the Gaussian distribution
817  * @param sigma The sigma parameter defining the standard deviation of the Gaussian distribution, with range (0, infinity)
818  * @return Function value
819  */
820  static inline T normalizedGaussianDistribution(const T x, const T x0, const T sigma);
821 
822  /**
823  * Returns a value of the bivariate Gaussian distribution centered around the origin.
824  * @param x X value for the function
825  * @param y Y value for the function
826  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
827  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
828  * @return Function value
829  */
830  static inline T gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY);
831 
832  /**
833  * Returns a value of the bivariate Gaussian distribution centered around a given position (x0, y0).
834  * @param x X value for the function
835  * @param y Y value for the function
836  * @param x0 X value for the center of the Gaussian distribution
837  * @param y0 Y value for the center of the Gaussian distribution
838  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
839  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
840  * @return Function value
841  */
842  static inline T gaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY);
843 
844  /**
845  * Returns a value of the normalized bivariate Gaussian distribution centered around the origin.
846  * As the result is normalized, the resulting Gaussian distribution value is 1 at the origin.<br>
847  * @param x X value for the function
848  * @param y Y value for the function
849  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
850  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
851  * @return Function value
852  */
853  static inline T normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY);
854 
855  /**
856  * Returns a value of the normalized bivariate Gaussian distribution centered around a given position (x0, y0).
857  * As the result is normalized, the resulting Gaussian distribution value is 1 at the given position (x0, y0).<br>
858  * @param x X value for the function
859  * @param y Y value for the function
860  * @param x0 X value for the center of the Gaussian distribution
861  * @param y0 Y value for the center of the Gaussian distribution
862  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
863  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
864  * @return Function value
865  */
866  static inline T normalizedGaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY);
867 
868  /**
869  * Returns a value of the trivariate Gaussian distribution centered around the origin.
870  * @param x X value for the function
871  * @param y Y value for the function
872  * @param z Z value for the function
873  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
874  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
875  * @param sigmaZ Sigma parameter defining the standard deviation for the z-axis of the Gaussian distribution, with range (0, infinity)
876  * @return Function value
877  */
878  static inline T gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ);
879 
880  /**
881  * Returns a value of the trivariate Gaussian distribution centered around a given position (x0, y0, z0).
882  * @param x X value for the function
883  * @param y Y value for the function
884  * @param z Z value for the function
885  * @param x0 X value for the center of the Gaussian distribution
886  * @param y0 Y value for the center of the Gaussian distribution
887  * @param z0 Z value for the center of the Gaussian distribution
888  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
889  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
890  * @param sigmaZ Sigma parameter defining the standard deviation for the z-axis of the Gaussian distribution, with range (0, infinity)
891  * @return Function value
892  */
893  static inline T gaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ);
894 
895  /**
896  * Returns a value of the normalized trivariate Gaussian distribution centered around the origin.
897  * As the result is normalized, the resulting Gaussian distribution value is 1 at the origin.<br>
898  * @param x X value for the function
899  * @param y Y value for the function
900  * @param z Z value for the function
901  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
902  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
903  * @param sigmaZ Sigma parameter defining the standard deviation for the z-axis of the Gaussian distribution, with range (0, infinity)
904  * @return Function value
905  */
906  static inline T normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ);
907 
908  /**
909  * Returns a value of the normalized trivariate Gaussian distribution centered around a given position (x0, y0, z0).
910  * As the result is normalized, the resulting Gaussian distribution value is 1 at the given position (x0, y0, z0).<br>
911  * @param x X value for the function
912  * @param y Y value for the function
913  * @param z Z value for the function
914  * @param x0 X value for the center of the Gaussian distribution
915  * @param y0 Y value for the center of the Gaussian distribution
916  * @param z0 Z value for the center of the Gaussian distribution
917  * @param sigmaX Sigma parameter defining the standard deviation for the x-axis of the Gaussian distribution, with range (0, infinity)
918  * @param sigmaY Sigma parameter defining the standard deviation for the y-axis of the Gaussian distribution, with range (0, infinity)
919  * @param sigmaZ Sigma parameter defining the standard deviation for the z-axis of the Gaussian distribution, with range (0, infinity)
920  * @return Function value
921  */
922  static inline T normalizedGaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ);
923 };
924 
925 template <typename T>
926 constexpr T NumericT<T>::pi()
927 {
928  return T(3.1415926535897932384626433832795);
929 }
930 
931 template <typename T>
932 constexpr T NumericT<T>::pi2()
933 {
934  return T(6.283185307179586476925286766559);
935 }
936 
937 template <typename T>
938 constexpr T NumericT<T>::pi_2()
939 {
940  return T(1.5707963267948966192313216916395);
941 }
942 
943 template <typename T>
944 constexpr T NumericT<T>::pi_3()
945 {
946  return T(1.0471975511965977461542144610932);
947 }
948 
949 template <typename T>
950 constexpr T NumericT<T>::pi_4()
951 {
952  return T(0.78539816339744830961566084581988);
953 }
954 
955 template <typename T>
957 {
958  return T(9.8696044010893586188344909998762);
959 }
960 
961 template <typename T>
963 {
964  return T(39.478417604357434475337963999505);
965 }
966 
967 template <typename T>
969 {
970  return T(2.4674011002723396547086227499667);
971 }
972 
973 template <typename T>
974 constexpr T NumericT<T>::e()
975 {
976  return T(2.71828182845904523536);
977 }
978 
979 /**
980  * Specialization of NumericT::eps().
981  * @see NumericT::eps().
982  */
983 template <>
984 constexpr double NumericT<double>::eps()
985 {
986  return 1e-12;
987 }
988 
989 /**
990  * Specialization of NumericT::eps().
991  * @see NumericT::eps().
992  */
993 template <>
994 constexpr float NumericT<float>::eps()
995 {
996  return 1e-6f;
997 }
998 
999 /**
1000  * Specialization of NumericT::eps().
1001  * @see NumericT::eps().
1002  */
1003 template <>
1004 constexpr signed char NumericT<signed char>::eps()
1005 {
1006  return 0;
1007 }
1008 
1009 /**
1010  * Specialization of NumericT::eps().
1011  * @see NumericT::eps().
1012  */
1013 template <>
1014 constexpr unsigned char NumericT<unsigned char>::eps()
1015 {
1016  return 0u;
1017 }
1018 
1019 /**
1020  * Specialization of NumericT::eps().
1021  * @see NumericT::eps().
1022  */
1023 template <>
1024 constexpr short NumericT<short>::eps()
1025 {
1026  return 0;
1027 }
1028 
1029 /**
1030  * Specialization of NumericT::eps().
1031  * @see NumericT::eps().
1032  */
1033 template <>
1034 constexpr unsigned short NumericT<unsigned short>::eps()
1035 {
1036  return 0u;
1037 }
1038 
1039 /**
1040  * Specialization of NumericT::eps().
1041  * @see NumericT::eps().
1042  */
1043 template <>
1044 constexpr int NumericT<int>::eps()
1045 {
1046  return 0;
1047 }
1048 
1049 /**
1050  * Specialization of NumericT::eps().
1051  * @see NumericT::eps().
1052  */
1053 template <>
1054 constexpr unsigned int NumericT<unsigned int>::eps()
1055 {
1056  return 0u;
1057 }
1058 
1059 /**
1060  * Specialization of NumericT::eps().
1061  * @see NumericT::eps().
1062  */
1063 template <>
1064 constexpr long NumericT<long>::eps()
1065 {
1066  return 0l;
1067 }
1068 
1069 /**
1070  * Specialization of NumericT::eps().
1071  * @see NumericT::eps().
1072  */
1073 template <>
1074 constexpr unsigned long NumericT<unsigned long>::eps()
1075 {
1076  return 0ul;
1077 }
1078 
1079 /**
1080  * Specialization of NumericT::eps().
1081  * @see NumericT::eps().
1082  */
1083 template <>
1084 constexpr long long NumericT<long long>::eps()
1085 {
1086  return 0ll;
1087 }
1088 
1089 /**
1090  * Specialization of NumericT::eps().
1091  * @see NumericT::eps().
1092  */
1093 template <>
1094 constexpr unsigned long long NumericT<unsigned long long>::eps()
1095 {
1096  return 0ull;
1097 }
1098 
1099 /**
1100  * Specialization of NumericT::weakEps().
1101  * @see NumericT::weakEps().
1102  */
1103 template <>
1104 constexpr double NumericT<double>::weakEps()
1105 {
1106  return 1e-6;
1107 }
1108 
1109 /**
1110  * Specialization of NumericT::weakEps().
1111  * @see NumericT::weakEps().
1112  */
1113 template <>
1114 constexpr float NumericT<float>::weakEps()
1115 {
1116  return 1e-3f;
1117 }
1118 
1119 /**
1120  * Specialization of NumericT::weakEps().
1121  * @see NumericT::weakEps().
1122  */
1123 template <>
1124 constexpr signed char NumericT<signed char>::weakEps()
1125 {
1126  return 0;
1127 }
1128 
1129 /**
1130  * Specialization of NumericT::weakEps().
1131  * @see NumericT::weakEps().
1132  */
1133 template <>
1134 constexpr unsigned char NumericT<unsigned char>::weakEps()
1135 {
1136  return 0u;
1137 }
1138 
1139 /**
1140  * Specialization of NumericT::weakEps().
1141  * @see NumericT::weakEps().
1142  */
1143 template <>
1144 constexpr short NumericT<short>::weakEps()
1145 {
1146  return 0;
1147 }
1148 
1149 /**
1150  * Specialization of NumericT::weakEps().
1151  * @see NumericT::weakEps().
1152  */
1153 template <>
1154 constexpr unsigned short NumericT<unsigned short>::weakEps()
1155 {
1156  return 0u;
1157 }
1158 
1159 /**
1160  * Specialization of NumericT::weakEps().
1161  * @see NumericT::weakEps().
1162  */
1163 template <>
1164 constexpr int NumericT<int>::weakEps()
1165 {
1166  return 0;
1167 }
1168 
1169 /**
1170  * Specialization of NumericT::weakEps().
1171  * @see NumericT::weakEps().
1172  */
1173 template <>
1174 constexpr unsigned int NumericT<unsigned int>::weakEps()
1175 {
1176  return 0u;
1177 }
1178 
1179 /**
1180  * Specialization of NumericT::weakEps().
1181  * @see NumericT::weakEps().
1182  */
1183 template <>
1184 constexpr long NumericT<long>::weakEps()
1185 {
1186  return 0l;
1187 }
1188 
1189 /**
1190  * Specialization of NumericT::weakEps().
1191  * @see NumericT::weakEps().
1192  */
1193 template <>
1194 constexpr unsigned long NumericT<unsigned long>::weakEps()
1195 {
1196  return 0ul;
1197 }
1198 
1199 /**
1200  * Specialization of NumericT::weakEps().
1201  * @see NumericT::weakEps().
1202  */
1203 template <>
1204 constexpr long long NumericT<long long>::weakEps()
1205 {
1206  return 0ll;
1207 }
1208 
1209 /**
1210  * Specialization of NumericT::weakEps().
1211  * @see NumericT::weakEps().
1212  */
1213 template <>
1214 constexpr unsigned long long NumericT<unsigned long long>::weakEps()
1215 {
1216  return 0ull;
1217 }
1218 
1219 template <typename T>
1220 inline T NumericT<T>::abs(const T value)
1221 {
1222  return ::abs(value);
1223 }
1224 
1225 /**
1226  * Specialization of NumericT::abs().
1227  * @see NumericT::abs().
1228  */
1229 template <>
1230 inline signed char NumericT<signed char>::abs(const signed char value)
1231 {
1232  ocean_assert(value != std::numeric_limits<signed char>::lowest() && "The absolute value of -128 is 128 but then casted to -128");
1233 
1234  return (signed char)(::abs(value));
1235 }
1236 
1237 /**
1238  * Specialization of NumericT::abs().
1239  * @see NumericT::abs().
1240  */
1241 template <>
1242 inline unsigned char NumericT<unsigned char>::abs(const unsigned char value)
1243 {
1244  return value;
1245 }
1246 
1247 /**
1248  * Specialization of NumericT::abs().
1249  * @see NumericT::abs().
1250  */
1251 template <>
1252 inline short NumericT<short>::abs(const short value)
1253 {
1254  ocean_assert(value != std::numeric_limits<short>::lowest() && "The absolute value of -32768 is 32768 but then casted to -32768");
1255 
1256  return short(::abs(value));
1257 }
1258 
1259 /**
1260  * Specialization of NumericT::abs().
1261  * @see NumericT::abs().
1262  */
1263 template <>
1264 inline unsigned short NumericT<unsigned short>::abs(const unsigned short value)
1265 {
1266  return value;
1267 }
1268 
1269 /**
1270  * Specialization of NumericT::abs().
1271  * @see NumericT::abs().
1272  */
1273 template <>
1274 inline int NumericT<int>::abs(const int value)
1275 {
1276  ocean_assert(value != std::numeric_limits<int>::lowest());
1277 
1278  return ::abs(value);
1279 }
1280 
1281 /**
1282  * Specialization of NumericT::abs().
1283  * @see NumericT::abs().
1284  */
1285 template <>
1286 inline unsigned int NumericT<unsigned int>::abs(const unsigned int value)
1287 {
1288  return value;
1289 }
1290 
1291 /**
1292  * Specialization of NumericT::abs().
1293  * @see NumericT::abs().
1294  */
1295 template <>
1296 inline long NumericT<long>::abs(const long value)
1297 {
1298  ocean_assert(value != std::numeric_limits<long>::lowest());
1299 
1300  return ::labs(value);
1301 }
1302 
1303 /**
1304  * Specialization of NumericT::abs().
1305  * @see NumericT::abs().
1306  */
1307 template <>
1308 inline unsigned long NumericT<unsigned long>::abs(const unsigned long value)
1309 {
1310  return value;
1311 }
1312 
1313 /**
1314  * Specialization of NumericT::abs().
1315  * @see NumericT::abs().
1316  */
1317 template <>
1318 inline long long NumericT<long long>::abs(const long long value)
1319 {
1320  ocean_assert(value != std::numeric_limits<long long>::lowest());
1321 
1322  return ::llabs(value);
1323 }
1324 
1325 /**
1326  * Specialization of NumericT::abs().
1327  * @see NumericT::abs().
1328  */
1329 template <>
1330 inline unsigned long long NumericT<unsigned long long>::abs(const unsigned long long value)
1331 {
1332  return value;
1333 }
1334 
1335 /**
1336  * Specialization of NumericT::abs().
1337  * @see NumericT::abs().
1338  */
1339 template <>
1340 inline double NumericT<double>::abs(const double value)
1341 {
1342  return fabs(value);
1343 }
1344 
1345 /**
1346  * Specialization of NumericT::abs().
1347  * @see NumericT::abs().
1348  */
1349 template <>
1350 inline float NumericT<float>::abs(const float value)
1351 {
1352  return fabsf(value);
1353 }
1354 
1355 template <typename T>
1356 inline typename UnsignedTyper<T>::Type NumericT<T>::secureAbs(const T value)
1357 {
1358  return typename UnsignedTyper<T>::Type(::abs(value));
1359 }
1360 
1361 /**
1362  * Specialization of NumericT::secureAbs().
1363  * @see NumericT::secureAbs().
1364  */
1365 template <>
1366 inline unsigned char NumericT<signed char>::secureAbs(const signed char value)
1367 {
1368  return (unsigned char)(::abs(int(value)));
1369 }
1370 
1371 /**
1372  * Specialization of NumericT::secureAbs().
1373  * @see NumericT::secureAbs().
1374  */
1375 template <>
1376 inline unsigned char NumericT<unsigned char>::secureAbs(const unsigned char value)
1377 {
1378  return value;
1379 }
1380 
1381 /**
1382  * Specialization of NumericT::secureAbs().
1383  * @see NumericT::secureAbs().
1384  */
1385 template <>
1386 inline unsigned short NumericT<short>::secureAbs(const short value)
1387 {
1388  return (unsigned short)::abs(int(value));
1389 }
1390 
1391 /**
1392  * Specialization of NumericT::secureAbs().
1393  * @see NumericT::secureAbs().
1394  */
1395 template <>
1396 inline unsigned short NumericT<unsigned short>::secureAbs(const unsigned short value)
1397 {
1398  return value;
1399 }
1400 
1401 /**
1402  * Specialization of NumericT::secureAbs().
1403  * @see NumericT::secureAbs().
1404  */
1405 template <>
1406 inline unsigned int NumericT<int>::secureAbs(const int value)
1407 {
1408  if (value == std::numeric_limits<int>::lowest())
1409  {
1410  // -2147483648 -> +2147483648
1411  return (unsigned int)(std::numeric_limits<int>::max()) + 1u;
1412  }
1413 
1414  return (unsigned int)(::abs(value));
1415 }
1416 
1417 /**
1418  * Specialization of NumericT::secureAbs().
1419  * @see NumericT::secureAbs().
1420  */
1421 template <>
1422 inline unsigned int NumericT<unsigned int>::secureAbs(const unsigned int value)
1423 {
1424  return value;
1425 }
1426 
1427 /**
1428  * Specialization of NumericT::secureAbs().
1429  * @see NumericT::secureAbs().
1430  */
1431 template <>
1432 inline unsigned long NumericT<long>::secureAbs(const long value)
1433 {
1434  ocean_assert((unsigned long)::llabs(std::numeric_limits<long>::max()) == (unsigned long)(-(std::numeric_limits<long>::lowest() + 1l)));
1435  return (unsigned long)::llabs(value);
1436 }
1437 
1438 /**
1439  * Specialization of NumericT::secureAbs().
1440  * @see NumericT::secureAbs().
1441  */
1442 template <>
1443 inline unsigned long NumericT<unsigned long>::secureAbs(const unsigned long value)
1444 {
1445  return value;
1446 }
1447 
1448 /**
1449  * Specialization of NumericT::secureAbs().
1450  * @see NumericT::secureAbs().
1451  */
1452 template <>
1453 inline unsigned long long NumericT<long long>::secureAbs(const long long value)
1454 {
1455  if (value == std::numeric_limits<long long>::lowest())
1456  {
1457  // -9223372036854775808 -> +9223372036854775808
1458  return (unsigned long long)(std::numeric_limits<long long>::max()) + 1ull;
1459  }
1460 
1461  return (unsigned long long)(::llabs(value));
1462 }
1463 
1464 /**
1465  * Specialization of NumericT::secureAbs().
1466  * @see NumericT::secureAbs().
1467  */
1468 template <>
1469 inline unsigned long long NumericT<unsigned long long>::secureAbs(const unsigned long long value)
1470 {
1471  return value;
1472 }
1473 
1474 /**
1475  * Specialization of NumericT::secureAbs().
1476  * @see NumericT::secureAbs().
1477  */
1478 template <>
1479 inline double NumericT<double>::secureAbs(const double value)
1480 {
1481  return abs(value);
1482 }
1483 
1484 /**
1485  * Specialization of NumericT::secureAbs().
1486  * @see NumericT::secureAbs().
1487  */
1488 template <>
1489 inline float NumericT<float>::secureAbs(const float value)
1490 {
1491  return abs(value);
1492 }
1493 
1494 template <typename T>
1495 constexpr inline T NumericT<T>::sqr(const T value)
1496 {
1497  return value * value;
1498 }
1499 
1500 template <typename T>
1501 inline T NumericT<T>::sum(const T* values, const size_t number)
1502 {
1503  T result = T(0);
1504 
1505  for (size_t n = 0; n < number; ++n)
1506  {
1507  result += values[n];
1508  }
1509 
1510  return result;
1511 }
1512 
1513 template <typename T>
1514 inline T NumericT<T>::summedSqr(const T* values, const size_t number)
1515 {
1516  T result = T(0);
1517 
1518  for (size_t n = 0; n < number; ++n)
1519  {
1520  result += sqr(values[n]);
1521  }
1522 
1523  return result;
1524 }
1525 
1526 template <typename T>
1527 constexpr inline T NumericT<T>::sqrDistance(const T value0, const T value1)
1528 {
1529  return sqr(value0 - value1);
1530 }
1531 
1532 template <typename T>
1533 inline T NumericT<T>::sqrt(const T value)
1534 {
1535  ocean_assert(value >= T(0));
1536  return T(::sqrt(value));
1537 }
1538 
1539 /**
1540  * Specialization of NumericT::sqrt().
1541  * @see NumericT::sqrt().
1542  */
1543 template <>
1544 inline float NumericT<float>::sqrt(const float value)
1545 {
1546  ocean_assert(value >= 0.0f);
1547  return ::sqrtf(value);
1548 }
1549 
1550 /**
1551  * Specialization of NumericT::sqrt().
1552  * @see NumericT::sqrt().
1553  */
1554 template <>
1555 inline int NumericT<int>::sqrt(const int value)
1556 {
1557  ocean_assert(value >= 0);
1558  return int(::sqrtf(float(value)));
1559 }
1560 
1561 template <typename T>
1562 inline std::complex<T> NumericT<T>::sqrt(const std::complex<T>& value)
1563 {
1564  return std::sqrt<T>(value);
1565 }
1566 
1567 template <typename T>
1568 inline T NumericT<T>::sin(const T value)
1569 {
1570  return ::sin(value);
1571 }
1572 
1573 /**
1574  * Specialization of NumericT::sin().
1575  * @see NumericT::sin().
1576  */
1577 template <>
1578 inline float NumericT<float>::sin(const float value)
1579 {
1580  return sinf(value);
1581 }
1582 
1583 template <typename T>
1584 inline T NumericT<T>::cos(const T value)
1585 {
1586  return ::cos(value);
1587 }
1588 
1589 /**
1590  * Specialization of NumericT::cos().
1591  * @see NumericT::cos().
1592  */
1593 template <>
1594 inline float NumericT<float>::cos(const float value)
1595 {
1596  return cosf(value);
1597 }
1598 
1599 template <typename T>
1600 inline T NumericT<T>::tan(const T value)
1601 {
1602  return ::tan(value);
1603 }
1604 
1605 /**
1606  * Specialization of NumericT::tan().
1607  * @see NumericT::tan().
1608  */
1609 template <>
1610 inline float NumericT<float>::tan(const float value)
1611 {
1612  return tanf(value);
1613 }
1614 
1615 template <typename T>
1616 inline T NumericT<T>::atan(const T value)
1617 {
1618  return ::atan(value);
1619 }
1620 
1621 /**
1622  * Specialization of NumericT::atan().
1623  * @see NumericT::atan().
1624  */
1625 template <>
1626 inline float NumericT<float>::atan(const float value)
1627 {
1628  return atanf(value);
1629 }
1630 
1631 template <typename T>
1632 inline T NumericT<T>::atan2(const T y, const T x)
1633 {
1635 
1636  const T angle = ::atan2(y, x);
1637  ocean_assert(angle >= -NumericT<T>::pi() && angle <= NumericT<T>::pi());
1638 
1639  return angle;
1640 }
1641 
1642 template <typename T>
1643 inline T NumericT<T>::exp(const T value)
1644 {
1645  return ::exp(value);
1646 }
1647 
1648 template <>
1649 inline float NumericT<float>::exp(const float value)
1650 {
1651  return ::expf(value);
1652 }
1653 
1654 template <typename T>
1655 inline T NumericT<T>::log(const T value)
1656 {
1657  ocean_assert(value > 0);
1658  return ::log(value);
1659 }
1660 
1661 template <>
1662 inline float NumericT<float>::log(const float value)
1663 {
1664  ocean_assert(value > 0);
1665  return ::logf(value);
1666 }
1667 
1668 template <typename T>
1669 inline T NumericT<T>::log1p(const T value)
1670 {
1671  ocean_assert(value > -1);
1672  return ::log1p(value);
1673 }
1674 
1675 template <>
1676 inline float NumericT<float>::log1p(const float value)
1677 {
1678  ocean_assert(value > -1);
1679  return ::log1pf(value);
1680 }
1681 
1682 template <typename T>
1683 inline T NumericT<T>::log2(const T value)
1684 {
1685  ocean_assert(value > 0);
1686 
1687 #if (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION >= 1800) || (OCEAN_CLANG_VERSION >= 30300 && (!defined(__ANDROID__) || !__ANDROID__))
1688  return ::log2(value);
1689 #else
1690  return ::log(value) * 1.44269504088896340736; // 1 / ln(2)
1691 #endif
1692 }
1693 
1694 /**
1695  * Specialization of NumericT::log2().
1696  * @see NumericT::log2().
1697  */
1698 template <>
1699 inline float NumericT<float>::log2(const float value)
1700 {
1701  ocean_assert(value > 0);
1702 
1703 #if (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION >= 1800) || (OCEAN_CLANG_VERSION >= 30300 && (!defined(__ANDROID__) || !__ANDROID__))
1704  return ::log2f(value);
1705 #else
1706  return ::logf(value) * 1.44269504088896340736f; // 1 / ln(2)
1707 #endif
1708 }
1709 
1710 template <typename T>
1711 inline T NumericT<T>::log10(const T value)
1712 {
1713  ocean_assert(value > 0);
1714  return ::log10(value);
1715 }
1716 
1717 template <>
1718 inline float NumericT<float>::log10(const float value)
1719 {
1720  ocean_assert(value > 0);
1721  return ::log10f(value);
1722 }
1723 
1724 /**
1725  * Specialization of NumericT::atan2().
1726  * @see NumericT::atan2().
1727  */
1728 template <>
1729 inline float NumericT<float>::atan2(const float y, const float x)
1730 {
1731  return atan2f(y, x);
1732 }
1733 
1734 template <typename T>
1735 inline T NumericT<T>::fmod(const T valueA, const T valueB)
1736 {
1737  return ::fmod(valueA, valueB);
1738 }
1739 
1740 /**
1741  * Specialization of NumericT::fmod().
1742  * @see NumericT::fmod().
1743  */
1744 template <>
1745 inline float NumericT<float>::fmod(const float valueA, const float valueB)
1746 {
1747  return fmodf(valueA, valueB);
1748 }
1749 
1750 template <typename T>
1751 inline T NumericT<T>::dot(const T* vectorA, const T* vectorB, const size_t size)
1752 {
1753  T result = T(0);
1754 
1755  for (size_t n = 0; n < size; ++n)
1756  {
1757  result += vectorA[n] * vectorB[n];
1758  }
1759 
1760  return result;
1761 }
1762 
1763 template <typename T>
1764 inline T NumericT<T>::angleAdjustPositive(const T angle)
1765 {
1766  const T adjusted = fmod(angle, pi2());
1767 
1768  if (adjusted < 0)
1769  {
1770  ocean_assert((std::is_same<T, float>::value) || (pi2() + adjusted >= 0 && pi2() + adjusted < pi2()));
1771  return pi2() + adjusted;
1772  }
1773 
1774  ocean_assert(adjusted >= 0 && adjusted < pi2());
1775  return adjusted;
1776 }
1777 
1778 template <typename T>
1780 {
1781  const T adjusted = fmod(angle, pi());
1782 
1783  if (adjusted < 0)
1784  {
1785  ocean_assert(pi() + adjusted >= 0 && pi() + adjusted < pi());
1786  return pi() + adjusted;
1787  }
1788 
1789  ocean_assert(adjusted >= 0 && adjusted < pi());
1790  return adjusted;
1791 }
1792 
1793 template <typename T>
1794 inline T NumericT<T>::angleAdjustNull(const T angle)
1795 {
1796  if (angle > -pi() && angle <= pi())
1797  {
1798  return angle;
1799  }
1800 
1801  const T adjusted = fmod(angle, pi2());
1802 
1803  if (isAbove(adjusted, pi()))
1804  {
1805  ocean_assert(adjusted - pi2() > -pi() - eps() && adjusted - pi2() <= pi() + eps());
1806  return adjusted - pi2();
1807  }
1808  else if (isBelow(adjusted, -pi()))
1809  {
1810  ocean_assert(adjusted + pi2() > -pi() - eps() && adjusted + pi2() <= pi() + eps());
1811  return adjusted + pi2();
1812  }
1813 
1814  ocean_assert(adjusted > -pi() && adjusted <= pi());
1815  return adjusted;
1816 }
1817 
1818 template <typename T>
1819 inline bool NumericT<T>::angleIsEqual(const T angleA, const T angleB)
1820 {
1821  return isEqualEps(angleDistance(angleA, angleB));
1822 }
1823 
1824 template <typename T>
1825 inline bool NumericT<T>::angleIsWeakEqual(const T angleA, const T angleB)
1826 {
1827  return isWeakEqualEps(angleDistance(angleA, angleB));
1828 }
1829 
1830 template <typename T>
1831 inline bool NumericT<T>::angleIsEqual(const T angleA, const T angleB, const T epsilon)
1832 {
1833  ocean_assert(epsilon >= T(0));
1834  return isEqual(angleDistance(angleA, angleB), T(0), epsilon);
1835 }
1836 
1837 template <typename T>
1838 inline bool NumericT<T>::angleIsBelowThreshold(const T angleA, const T angleB, const T threshold)
1839 {
1840  ocean_assert(threshold < pi());
1841 
1842  return isBelow(abs(angleAdjustNull(angleA - angleB)), threshold);
1843 }
1844 
1845 template <typename T>
1846 inline T NumericT<T>::angleDistance(const T angleA, const T angleB)
1847 {
1848  const T distance = abs(angleAdjustPositive(angleA) - angleAdjustPositive(angleB));
1849  ocean_assert(distance < NumericT<T>::pi2());
1850 
1851  if (distance < NumericT<T>::pi())
1852  {
1853  return distance;
1854  }
1855 
1856  return NumericT<T>::pi2() - distance;
1857 }
1858 
1859 template <typename T>
1860 inline T NumericT<T>::pow(const T x, const T y)
1861 {
1862  return ::pow(x, y);
1863 }
1864 
1865 template <typename T>
1866 inline std::complex<T> NumericT<T>::pow(const std::complex<T>& x, const T y)
1867 {
1868  return std::pow<T>(x, y);
1869 }
1870 
1871 /**
1872  * Specialization of NumericT::pow().
1873  * @see NumericT::pow().
1874  */
1875 template <>
1876 inline float NumericT<float>::pow(const float x, const float y)
1877 {
1878  return powf(x, y);
1879 }
1880 
1881 template <typename T>
1882 constexpr T NumericT<T>::integerPow(const T x, const unsigned int y)
1883 {
1884  return y == 0u ? T(1) : x * integerPow(x, y - 1u);
1885 }
1886 
1887 template <typename T>
1888 constexpr inline T NumericT<T>::factorial(const T& value)
1889 {
1890  ocean_assert(value >= 0);
1891  ocean_assert(T((long long)(value)) == value);
1892 
1893  if (value <= 1)
1894  {
1895  return T(1);
1896  }
1897 
1898  T result = T(2);
1899 
1900  for (unsigned int n = 3u; n <= (unsigned int)value; ++n)
1901  {
1902  ocean_assert(std::numeric_limits<T>::max() / T(n) >= result);
1903  result *= T(n);
1904  }
1905 
1906  return result;
1907 }
1908 
1909 template <>
1910 constexpr inline unsigned int NumericT<unsigned int>::factorial(const unsigned int& value)
1911 {
1912  switch (value)
1913  {
1914  case 0u:
1915  case 1u:
1916  return 1u;
1917 
1918  case 2u:
1919  return 2u;
1920 
1921  case 3u:
1922  return 6u;
1923 
1924  case 4u:
1925  return 24u;
1926 
1927  case 5u:
1928  return 120u;
1929 
1930  case 6u:
1931  return 720u;
1932 
1933  case 7u:
1934  return 5040u;
1935 
1936  case 8u:
1937  return 40320u;
1938 
1939  case 9u:
1940  return 362880u;
1941 
1942  case 10u:
1943  return 3628800u;
1944 
1945  case 11u:
1946  return 39916800u;
1947 
1948  case 12u:
1949  return 479001600u;
1950  }
1951 
1952  ocean_assert(false && "Invalid factorial value!");
1953  return 1u;
1954 }
1955 
1956 template <typename T>
1957 constexpr inline T NumericT<T>::binomialCoefficient(const T& n, const T& k)
1958 {
1959  ocean_assert(n >= 0 && k >= 0);
1960  ocean_assert(T((long long)(n)) == n);
1961  ocean_assert(T((long long)(k)) == k);
1962 
1963  if (n <= T(1) || k == T(0) || n == k)
1964  {
1965  return T(1);
1966  }
1967 
1968  ocean_assert(k < n);
1969 
1970  T result = n - k + T(1);
1971 
1972  for (unsigned int i = (unsigned int)(n - k) + 2u; i <= (unsigned int)n; ++i)
1973  {
1974  ocean_assert(std::numeric_limits<T>::max() / T(i) >= result);
1975  result *= T(i);
1976  }
1977 
1978  for (unsigned int i = 2u; i <= (unsigned int)k; ++i)
1979  {
1980  ocean_assert((result / T(i)) * T(i) == result);
1981  result /= T(i);
1982  }
1983 
1984  return result;
1985 }
1986 
1987 template <typename T>
1988 inline T NumericT<T>::ceil(const T value)
1989 {
1990  static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
1991 
1992  return value;
1993 }
1994 
1995 /**
1996  * Specialization of NumericT::ceil().
1997  * @see NumericT::ceil().
1998  */
1999 template <>
2000 inline float NumericT<float>::ceil(const float value)
2001 {
2002  return ::ceilf(value);
2003 }
2004 
2005 /**
2006  * Specialization of NumericT::ceil().
2007  * @see NumericT::ceil().
2008  */
2009 template <>
2010 inline double NumericT<double>::ceil(const double value)
2011 {
2012  return ::ceil(value);
2013 }
2014 
2015 /**
2016  * Specialization of NumericT::ceil().
2017  * @see NumericT::ceil().
2018  */
2019 template <>
2020 inline long double NumericT<long double>::ceil(const long double value)
2021 {
2022  return ::ceill(value);
2023 }
2024 
2025 template <typename T>
2026 inline T NumericT<T>::floor(const T value)
2027 {
2028  static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
2029 
2030  return value;
2031 }
2032 
2033 /**
2034  * Specialization of NumericT::floor().
2035  * @see NumericT::floor().
2036  */
2037 template <>
2038 inline float NumericT<float>::floor(const float value)
2039 {
2040  return ::floorf(value);
2041 }
2042 
2043 /**
2044  * Specialization of NumericT::floor().
2045  * @see NumericT::floor().
2046  */
2047 template <>
2048 inline double NumericT<double>::floor(const double value)
2049 {
2050  return ::floor(value);
2051 }
2052 
2053 /**
2054  * Specialization of NumericT::floor().
2055  * @see NumericT::floor().
2056  */
2057 template <>
2058 inline long double NumericT<long double>::floor(const long double value)
2059 {
2060  return ::floorl(value);
2061 }
2062 
2063 template <typename T>
2064 constexpr inline int32_t NumericT<T>::round32(const T value)
2065 {
2066  return int32_t(value + copySign(T(0.5), value));
2067 }
2068 
2069 template <typename T>
2070 constexpr inline int64_t NumericT<T>::round64(const T value)
2071 {
2072  return int64_t(value + copySign(T(0.5), value));
2073 }
2074 
2075 template <typename T>
2076 constexpr inline T NumericT<T>::ratio(const T nominator, const T denominator, const T fallback)
2077 {
2078  if (isEqualEps(denominator))
2079  {
2080  return fallback;
2081  }
2082 
2083  return nominator / denominator;
2084 }
2085 
2086 template <typename T>
2087 constexpr inline bool NumericT<T>::isEqualEps(const T value)
2088 {
2089  ocean_assert(isNan(value) == false);
2090  ocean_assert((fabs(value) <= eps()) == (-eps() <= value && value <= eps()));
2091 
2092  return -eps() <= value && value <= eps();
2093 }
2094 
2095 template <>
2096 constexpr inline bool NumericT<signed char>::isEqualEps(const signed char value)
2097 {
2098  return value == (signed char)(0);
2099 }
2100 
2101 template <>
2102 constexpr inline bool NumericT<unsigned char>::isEqualEps(const unsigned char value)
2103 {
2104  return value == (unsigned char)(0);
2105 }
2106 
2107 template <>
2108 constexpr inline bool NumericT<short>::isEqualEps(const short value)
2109 {
2110  return value == short(0);
2111 }
2112 
2113 template <>
2114 constexpr inline bool NumericT<unsigned short>::isEqualEps(const unsigned short value)
2115 {
2116  return value == (unsigned short)(0);
2117 }
2118 
2119 template <>
2120 constexpr inline bool NumericT<int>::isEqualEps(const int value)
2121 {
2122  return value == 0;
2123 }
2124 
2125 template <>
2126 constexpr inline bool NumericT<unsigned int>::isEqualEps(const unsigned int value)
2127 {
2128  return value == 0u;
2129 }
2130 
2131 template <>
2132 constexpr inline bool NumericT<long>::isEqualEps(const long value)
2133 {
2134  return value == 0l;
2135 }
2136 
2137 template <>
2138 constexpr inline bool NumericT<unsigned long>::isEqualEps(const unsigned long value)
2139 {
2140  return value == 0ul;
2141 }
2142 
2143 template <>
2144 constexpr inline bool NumericT<long long>::isEqualEps(const long long value)
2145 {
2146  return value == 0ll;
2147 }
2148 
2149 template <>
2150 constexpr inline bool NumericT<unsigned long long>::isEqualEps(const unsigned long long value)
2151 {
2152  return value == 0ull;
2153 }
2154 
2155 template <typename T>
2156 constexpr inline bool NumericT<T>::isEqualEps(const std::complex<T>& value)
2157 {
2158  return isEqualEps(value.real()) && isEqualEps(value.imag());
2159 }
2160 
2161 template <typename T>
2162 constexpr inline bool NumericT<T>::isWeakEqualEps(const T value)
2163 {
2164  ocean_assert(isNan(value) == false);
2165  ocean_assert((fabs(value) <= weakEps()) == (-weakEps() <= value && value <= weakEps()));
2166 
2167  return -weakEps() <= value && value <= weakEps();
2168 }
2169 
2170 template <>
2171 constexpr inline bool NumericT<signed char>::isWeakEqualEps(const signed char value)
2172 {
2173  return value == (signed char)(0);
2174 }
2175 
2176 template <>
2177 constexpr inline bool NumericT<unsigned char>::isWeakEqualEps(const unsigned char value)
2178 {
2179  return value == (unsigned char)(0);
2180 }
2181 
2182 template <>
2183 constexpr inline bool NumericT<short>::isWeakEqualEps(const short value)
2184 {
2185  return value == short(0);
2186 }
2187 
2188 template <>
2189 constexpr inline bool NumericT<unsigned short>::isWeakEqualEps(const unsigned short value)
2190 {
2191  return value == (unsigned short)(0);
2192 }
2193 
2194 template <>
2195 constexpr inline bool NumericT<int>::isWeakEqualEps(const int value)
2196 {
2197  return value == 0;
2198 }
2199 
2200 template <>
2201 constexpr inline bool NumericT<unsigned int>::isWeakEqualEps(const unsigned int value)
2202 {
2203  return value == 0u;
2204 }
2205 
2206 template <>
2207 constexpr inline bool NumericT<long>::isWeakEqualEps(const long value)
2208 {
2209  return value == 0l;
2210 }
2211 
2212 template <>
2213 constexpr inline bool NumericT<unsigned long>::isWeakEqualEps(const unsigned long value)
2214 {
2215  return value == 0ul;
2216 }
2217 
2218 template <>
2219 constexpr inline bool NumericT<long long>::isWeakEqualEps(const long long value)
2220 {
2221  return value == 0ll;
2222 }
2223 
2224 template <>
2225 constexpr inline bool NumericT<unsigned long long>::isWeakEqualEps(const unsigned long long value)
2226 {
2227  return value == 0ull;
2228 }
2229 
2230 template <typename T>
2231 constexpr inline bool NumericT<T>::isWeakEqualEps(const std::complex<T>& value)
2232 {
2233  return isWeakEqualEps(value.real()) && isWeakEqualEps(value.imag());
2234 }
2235 
2236 template <typename T>
2237 constexpr inline bool NumericT<T>::isNotEqualEps(const T value)
2238 {
2239  ocean_assert(isNan(value) == false);
2240  ocean_assert((fabs(value) > eps()) == (value > eps() || value < -eps()));
2241 
2242  return value > eps() || value < -eps();
2243 }
2244 
2245 template <>
2246 constexpr inline bool NumericT<signed char>::isNotEqualEps(const signed char value)
2247 {
2248  return value != (signed char)(0);
2249 }
2250 
2251 template <>
2252 constexpr inline bool NumericT<unsigned char>::isNotEqualEps(const unsigned char value)
2253 {
2254  return value != (unsigned char)(0);
2255 }
2256 
2257 template <>
2258 constexpr inline bool NumericT<short>::isNotEqualEps(const short value)
2259 {
2260  return value != short(0);
2261 }
2262 
2263 template <>
2264 constexpr inline bool NumericT<unsigned short>::isNotEqualEps(const unsigned short value)
2265 {
2266  return value != (unsigned short)(0);
2267 }
2268 
2269 template <>
2270 constexpr inline bool NumericT<int>::isNotEqualEps(const int value)
2271 {
2272  return value != 0;
2273 }
2274 
2275 template <>
2276 constexpr inline bool NumericT<unsigned int>::isNotEqualEps(const unsigned int value)
2277 {
2278  return value != 0u;
2279 }
2280 
2281 template <>
2282 constexpr inline bool NumericT<long>::isNotEqualEps(const long value)
2283 {
2284  return value != 0l;
2285 }
2286 
2287 template <>
2288 constexpr inline bool NumericT<unsigned long>::isNotEqualEps(const unsigned long value)
2289 {
2290  return value != 0ul;
2291 }
2292 
2293 template <>
2294 constexpr inline bool NumericT<long long>::isNotEqualEps(const long long value)
2295 {
2296  return value != 0ll;
2297 }
2298 
2299 template <>
2300 constexpr inline bool NumericT<unsigned long long>::isNotEqualEps(const unsigned long long value)
2301 {
2302  return value != 0ull;
2303 }
2304 
2305 template <typename T>
2306 constexpr inline bool NumericT<T>::isNotEqualEps(const std::complex<T>& value)
2307 {
2308  return value.real() > eps() || value.real() < -eps() || value.imag() > eps() || value.imag() < -eps();
2309 }
2310 
2311 template <typename T>
2312 constexpr inline bool NumericT<T>::isNotWeakEqualEps(const T value)
2313 {
2314  ocean_assert((fabs(value) > weakEps()) == (value > weakEps() || value < -weakEps()));
2315 
2316  return value > weakEps() || value < -weakEps();
2317 }
2318 
2319 template <>
2320 constexpr inline bool NumericT<signed char>::isNotWeakEqualEps(const signed char value)
2321 {
2322  return value != (signed char)(0);
2323 }
2324 
2325 template <>
2326 constexpr inline bool NumericT<unsigned char>::isNotWeakEqualEps(const unsigned char value)
2327 {
2328  return value != (unsigned char)(0);
2329 }
2330 
2331 template <>
2332 constexpr inline bool NumericT<short>::isNotWeakEqualEps(const short value)
2333 {
2334  return value != short(0);
2335 }
2336 
2337 template <>
2338 constexpr inline bool NumericT<unsigned short>::isNotWeakEqualEps(const unsigned short value)
2339 {
2340  return value != (unsigned short)(0);
2341 }
2342 
2343 template <>
2344 constexpr inline bool NumericT<int>::isNotWeakEqualEps(const int value)
2345 {
2346  return value != 0;
2347 }
2348 
2349 template <>
2350 constexpr inline bool NumericT<unsigned int>::isNotWeakEqualEps(const unsigned int value)
2351 {
2352  return value != 0u;
2353 }
2354 
2355 template <>
2356 constexpr inline bool NumericT<long>::isNotWeakEqualEps(const long value)
2357 {
2358  return value != 0l;
2359 }
2360 
2361 template <>
2362 constexpr inline bool NumericT<unsigned long>::isNotWeakEqualEps(const unsigned long value)
2363 {
2364  return value != 0ul;
2365 }
2366 
2367 template <>
2368 constexpr inline bool NumericT<long long>::isNotWeakEqualEps(const long long value)
2369 {
2370  return value != 0ll;
2371 }
2372 
2373 template <>
2374 constexpr inline bool NumericT<unsigned long long>::isNotWeakEqualEps(const unsigned long long value)
2375 {
2376  return value != 0ull;
2377 }
2378 
2379 template <typename T>
2380 constexpr inline bool NumericT<T>::isNotWeakEqualEps(const std::complex<T>& value)
2381 {
2382  return value.real() > weakEps() || value.real() < -weakEps() || value.imag() > weakEps() || value.imag() < -weakEps();
2383 }
2384 
2385 template <typename T>
2386 inline bool NumericT<T>::isEqual(const T first, const T second)
2387 {
2388  return fabs(first - second) <= eps();
2389 }
2390 
2391 template <>
2392 inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second)
2393 {
2394  return first == second;
2395 }
2396 
2397 template <>
2398 inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second)
2399 {
2400  return first == second;
2401 }
2402 
2403 template <>
2404 inline bool NumericT<short>::isEqual(const short first, const short second)
2405 {
2406  return first == second;
2407 }
2408 
2409 template <>
2410 inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second)
2411 {
2412  return first == second;
2413 }
2414 
2415 template <>
2416 inline bool NumericT<int>::isEqual(const int first, const int second)
2417 {
2418  return first == second;
2419 }
2420 
2421 template <>
2422 inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second)
2423 {
2424  return first == second;
2425 }
2426 
2427 template <>
2428 inline bool NumericT<long>::isEqual(const long first, const long second)
2429 {
2430  return first == second;
2431 }
2432 
2433 template <>
2434 inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second)
2435 {
2436  return first == second;
2437 }
2438 
2439 template <>
2440 inline bool NumericT<long long>::isEqual(const long long first, const long long second)
2441 {
2442  return first == second;
2443 }
2444 
2445 template <>
2446 inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second)
2447 {
2448  return first == second;
2449 }
2450 
2451 template <typename T>
2452 inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second)
2453 {
2454  return isEqual(first.real(), second.real()) && isEqual(first.imag(), second.imag());
2455 }
2456 
2457 template <typename T>
2458 inline bool NumericT<T>::isEqual(const T first, const T second, const T epsilon)
2459 {
2460  ocean_assert(epsilon >= T(0));
2461  return NumericT<T>::abs(first - second) <= epsilon;
2462 }
2463 
2464 template <>
2465 inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second, const signed char epsilon)
2466 {
2467  ocean_assert(epsilon >= (signed char)(0));
2468  return std::abs(first - second) <= epsilon;
2469 }
2470 
2471 template <>
2472 inline bool NumericT<short>::isEqual(const short first, const short second, const short epsilon)
2473 {
2474  ocean_assert(epsilon >= short(0));
2475  return std::abs(first - second) <= epsilon;
2476 }
2477 
2478 template <>
2479 inline bool NumericT<int>::isEqual(const int first, const int second, const int epsilon)
2480 {
2481  ocean_assert(epsilon >= 0);
2482  return std::abs(first - second) <= epsilon;
2483 }
2484 
2485 template <>
2486 inline bool NumericT<long>::isEqual(const long first, const long second, const long epsilon)
2487 {
2488  ocean_assert(epsilon >= long(0));
2489  return std::abs(first - second) <= epsilon;
2490 }
2491 
2492 template <>
2493 inline bool NumericT<long long>::isEqual(const long long first, const long long second, const long long epsilon)
2494 {
2495  ocean_assert(epsilon >= 0ll);
2496  return std::abs(first - second) <= epsilon;
2497 }
2498 
2499 template <>
2500 inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2501 {
2502  if (first > second)
2503  {
2504  return first - second <= epsilon;
2505  }
2506  else
2507  {
2508  return second - first <= epsilon;
2509  }
2510 }
2511 
2512 template <>
2513 inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2514 {
2515  if (first > second)
2516  {
2517  return first - second <= epsilon;
2518  }
2519  else
2520  {
2521  return second - first <= epsilon;
2522  }
2523 }
2524 
2525 template <>
2526 inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2527 {
2528  if (first > second)
2529  {
2530  return first - second <= epsilon;
2531  }
2532  else
2533  {
2534  return second - first <= epsilon;
2535  }
2536 }
2537 
2538 template <>
2539 inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2540 {
2541  if (first > second)
2542  {
2543  return first - second <= epsilon;
2544  }
2545  else
2546  {
2547  return second - first <= epsilon;
2548  }
2549 }
2550 
2551 template <>
2552 inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2553 {
2554  if (first > second)
2555  {
2556  return first - second <= epsilon;
2557  }
2558  else
2559  {
2560  return second - first <= epsilon;
2561  }
2562 }
2563 
2564 template <typename T>
2565 inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2566 {
2567  ocean_assert(epsilon >= T(0));
2568  return isEqual(first.real(), second.real(), epsilon) && isEqual(first.imag(), second.imag(), epsilon);
2569 }
2570 
2571 template <typename T>
2572 inline bool NumericT<T>::isWeakEqual(const T first, const T second)
2573 {
2574  return NumericT<T>::abs(first - second) <= weakEps();
2575 }
2576 
2577 template <>
2578 inline bool NumericT<int>::isWeakEqual(const int first, const int second)
2579 {
2580  return first == second;
2581 }
2582 
2583 template <typename T>
2584 inline bool NumericT<T>::isWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2585 {
2586  return isWeakEqual(first.real(), second.real()) && isWeakEqual(first.imag(), second.imag());
2587 }
2588 
2589 template <typename T>
2590 template <int tMagnitude>
2591 inline bool NumericT<T>::isEqual(const T first, const T second, const T referenceEpsilon)
2592 {
2593  static_assert(tMagnitude >= -20 && tMagnitude <= 20, "Invalid reference magnitude");
2594  ocean_assert(referenceEpsilon >= T(0));
2595 
2596  const T maximalAbsValue = max(NumericT<T>::abs(first), NumericT<T>::abs(second));
2597 
2598  // we ensure that the max value is not 0 (due to the following log)
2599  if (isEqualEps(maximalAbsValue))
2600  {
2601  return NumericT<T>::isEqual(first, second, referenceEpsilon);
2602  }
2603 
2604  const int offsetMagnitude = int(max(NumericT<float>::ceil(NumericT<float>::log10(float(maximalAbsValue))), float(tMagnitude))) - tMagnitude;
2605  ocean_assert(offsetMagnitude >= 0);
2606 
2607  const T adjustedEpsilon = referenceEpsilon * NumericT<T>::pow(10, T(offsetMagnitude));
2608 
2609  return isEqual(first, second, adjustedEpsilon);
2610 }
2611 
2612 template <typename T>
2613 inline bool NumericT<T>::isNotEqual(const T first, const T second)
2614 {
2615  return fabs(first - second) > eps();
2616 }
2617 
2618 template <>
2619 inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second)
2620 {
2621  return first != second;
2622 }
2623 
2624 template <>
2625 inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second)
2626 {
2627  return first != second;
2628 }
2629 
2630 template <>
2631 inline bool NumericT<short>::isNotEqual(const short first, const short second)
2632 {
2633  return first != second;
2634 }
2635 
2636 template <>
2637 inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second)
2638 {
2639  return first != second;
2640 }
2641 
2642 template <>
2643 inline bool NumericT<int>::isNotEqual(const int first, const int second)
2644 {
2645  return first != second;
2646 }
2647 
2648 template <>
2649 inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second)
2650 {
2651  return first != second;
2652 }
2653 
2654 template <>
2655 inline bool NumericT<long>::isNotEqual(const long first, const long second)
2656 {
2657  return first != second;
2658 }
2659 
2660 template <>
2661 inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second)
2662 {
2663  return first != second;
2664 }
2665 
2666 
2667 template <>
2668 inline bool NumericT<long long>::isNotEqual(const long long first, const long long second)
2669 {
2670  return first != second;
2671 }
2672 
2673 template <>
2674 inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second)
2675 {
2676  return first != second;
2677 }
2678 
2679 template <typename T>
2680 inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second)
2681 {
2682  return isNotEqual(first.real(), second.real()) || isNotEqual(first.imag(), second.imag());
2683 }
2684 
2685 template <typename T>
2686 inline bool NumericT<T>::isNotWeakEqual(const T first, const T second)
2687 {
2688  return fabs(first - second) > weakEps();
2689 }
2690 
2691 template <>
2692 inline bool NumericT<signed char>::isNotWeakEqual(const signed char first, const signed char second)
2693 {
2694  return first != second;
2695 }
2696 
2697 template <>
2698 inline bool NumericT<unsigned char>::isNotWeakEqual(const unsigned char first, const unsigned char second)
2699 {
2700  return first != second;
2701 }
2702 
2703 template <>
2704 inline bool NumericT<short>::isNotWeakEqual(const short first, const short second)
2705 {
2706  return first != second;
2707 }
2708 
2709 template <>
2710 inline bool NumericT<unsigned short>::isNotWeakEqual(const unsigned short first, const unsigned short second)
2711 {
2712  return first != second;
2713 }
2714 
2715 template <>
2716 inline bool NumericT<int>::isNotWeakEqual(const int first, const int second)
2717 {
2718  return first != second;
2719 }
2720 
2721 template <>
2722 inline bool NumericT<unsigned int>::isNotWeakEqual(const unsigned int first, const unsigned int second)
2723 {
2724  return first != second;
2725 }
2726 
2727 template <>
2728 inline bool NumericT<long>::isNotWeakEqual(const long first, const long second)
2729 {
2730  return first != second;
2731 }
2732 
2733 template <>
2734 inline bool NumericT<unsigned long>::isNotWeakEqual(const unsigned long first, const unsigned long second)
2735 {
2736  return first != second;
2737 }
2738 
2739 template <>
2740 inline bool NumericT<long long>::isNotWeakEqual(const long long first, const long long second)
2741 {
2742  return first != second;
2743 }
2744 
2745 template <>
2746 inline bool NumericT<unsigned long long>::isNotWeakEqual(const unsigned long long first, const unsigned long long second)
2747 {
2748  return first != second;
2749 }
2750 
2751 template <typename T>
2752 inline bool NumericT<T>::isNotWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2753 {
2754  return isNotWeakEqual(first.real(), second.real()) || isNotWeakEqual(first.imag(), second.imag());
2755 }
2756 
2757 template <typename T>
2758 inline bool NumericT<T>::isNotEqual(const T first, const T second, const T epsilon)
2759 {
2760  ocean_assert(epsilon >= 0);
2761  return fabs(first - second) > epsilon;
2762 }
2763 
2764 template <>
2765 inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second, const signed char epsilon)
2766 {
2767  ocean_assert(epsilon >= (signed char)(0));
2768  return std::abs(first - second) > epsilon;
2769 }
2770 
2771 template <>
2772 inline bool NumericT<short>::isNotEqual(const short first, const short second, const short epsilon)
2773 {
2774  ocean_assert(epsilon >= short(0));
2775  return std::abs(first - second) > epsilon;
2776 }
2777 
2778 template <>
2779 inline bool NumericT<int>::isNotEqual(const int first, const int second, const int epsilon)
2780 {
2781  ocean_assert(epsilon >= 0);
2782  return std::abs(first - second) > epsilon;
2783 }
2784 
2785 template <>
2786 inline bool NumericT<long>::isNotEqual(const long first, const long second, const long epsilon)
2787 {
2788  ocean_assert(epsilon >= long(0));
2789  return std::abs(first - second) > epsilon;
2790 }
2791 
2792 template <>
2793 inline bool NumericT<long long>::isNotEqual(const long long first, const long long second, const long long epsilon)
2794 {
2795  ocean_assert(epsilon >= 0ll);
2796  return std::abs(first - second) > epsilon;
2797 }
2798 
2799 template <>
2800 inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2801 {
2802  if (first > second)
2803  {
2804  return first - second > epsilon;
2805  }
2806  else
2807  {
2808  return second - first > epsilon;
2809  }
2810 }
2811 
2812 template <>
2813 inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2814 {
2815  if (first > second)
2816  {
2817  return first - second > epsilon;
2818  }
2819  else
2820  {
2821  return second - first > epsilon;
2822  }
2823 }
2824 
2825 template <>
2826 inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2827 {
2828  if (first > second)
2829  {
2830  return first - second > epsilon;
2831  }
2832  else
2833  {
2834  return second - first > epsilon;
2835  }
2836 }
2837 
2838 template <>
2839 inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2840 {
2841  if (first > second)
2842  {
2843  return first - second > epsilon;
2844  }
2845  else
2846  {
2847  return second - first > epsilon;
2848  }
2849 }
2850 
2851 template <>
2852 inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2853 {
2854  if (first > second)
2855  {
2856  return first - second > epsilon;
2857  }
2858  else
2859  {
2860  return second - first > epsilon;
2861  }
2862 }
2863 
2864 template <typename T>
2865 inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2866 {
2867  ocean_assert(epsilon >= 0);
2868  return isNotEqual(first.real(), second.real(), epsilon) || isNotEqual(first.imag(), second.imag(), epsilon);
2869 }
2870 
2871 template <typename T>
2872 constexpr bool NumericT<T>::isInsideRange(const T lower, const T value, const T upper, const T epsilon)
2873 {
2874  ocean_assert(lower <= upper);
2875  ocean_assert(epsilon >= T(0));
2876 
2877  return value >= lower - epsilon && value <= upper + epsilon;
2878 }
2879 
2880 template <typename T>
2881 constexpr bool NumericT<T>::isInsideWeakRange(const T lower, const T value, const T upper)
2882 {
2883  return isInsideRange(lower, value, upper, weakEps());
2884 }
2885 
2886 template <typename T>
2887 inline T NumericT<T>::asin(const T value)
2888 {
2889  ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2890 
2891  return ::asin(max(T(-1), min(T(1), value)));
2892 }
2893 
2894 /**
2895  * Specialization of NumericT::asin().
2896  * @see NumericT::asin().
2897  */
2898 template <>
2899 inline float NumericT<float>::asin(const float value)
2900 {
2901  ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2902 
2903  return asinf(max(-1.0f, min(1.0f, value)));
2904 }
2905 
2906 template <typename T>
2907 inline T NumericT<T>::acos(const T value)
2908 {
2909  ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2910 
2911  return ::acos(max(T(-1), min(T(1), value)));
2912 }
2913 
2914 /**
2915  * Specialization of NumericT::acos().
2916  * @see NumericT::acos().
2917  */
2918 template <>
2919 inline float NumericT<float>::acos(const float value)
2920 {
2921  ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2922 
2923  return acosf(max(-1.0f, min(1.0f, value)));
2924 }
2925 
2926 template <typename T>
2927 constexpr bool NumericT<T>::isBelow(const T value, const T upper, const T epsilon)
2928 {
2929  static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2930 
2931  ocean_assert(epsilon >= T(0));
2932 
2933  return value <= upper + epsilon;
2934 }
2935 
2936 template <typename T>
2937 constexpr bool NumericT<T>::isAbove(const T value, const T lower, const T epsilon)
2938 {
2939  static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2940 
2941  ocean_assert(epsilon >= T(0));
2942 
2943  return lower - epsilon <= value;
2944 }
2945 
2946 template <typename T>
2947 constexpr inline T NumericT<T>::nan()
2948 {
2949  static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
2950 
2951  if constexpr (std::is_same<T, float>::value)
2952  {
2953  static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
2954 
2955  constexpr uint32_t integerValue = 0x7FC00000u;
2956 
2957  float floatValue = 0.0f;
2958  memcpy(&floatValue, &integerValue, sizeof(integerValue));
2959 
2960  return T(floatValue);
2961  }
2962  else
2963  {
2964  static_assert(std::is_same<T, double>::value, "Invalid data type!");
2965  static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
2966 
2967  constexpr uint64_t integerValue = 0x7FF8000000000000ull;
2968 
2969  double doubleValue = 0.0;
2970  memcpy(&doubleValue, &integerValue, sizeof(integerValue));
2971 
2972  return T(doubleValue);
2973  }
2974 }
2975 
2976 template <>
2977 inline bool NumericT<float>::isNan(const float value)
2978 {
2979  // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
2980  // thus implementing a custom check
2981 
2982  static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
2983 
2984  // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
2985 
2986  uint32_t tmpValue;
2987  memcpy(&tmpValue, &value, sizeof(tmpValue));
2988 
2989  constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
2990  constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
2991 
2992  const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
2993  const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0u;
2994 
2995  return allExponentBitsAreOne && mantissaIsNotZero;
2996 }
2997 
2998 template <>
2999 inline bool NumericT<double>::isNan(const double value)
3000 {
3001  // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3002  // thus implementing a custom check
3003 
3004  static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3005 
3006  // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3007 
3008  uint64_t tmpValue;
3009  memcpy(&tmpValue, &value, sizeof(tmpValue));
3010 
3011  constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3012  constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3013 
3014  const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3015  const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0ull;
3016 
3017  return allExponentBitsAreOne && mantissaIsNotZero;
3018 }
3019 
3020 template <typename T>
3021 inline bool NumericT<T>::isNan(const T /*value*/)
3022 {
3023  // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3024  // thus implementing a custom check
3025 
3026  ocean_assert(std::is_floating_point<T>::value == false);
3027  return false;
3028 }
3029 
3030 template <typename T>
3031 inline bool NumericT<T>::isNan(const std::complex<T>& value)
3032 {
3033  return NumericT<T>::isNan(value.real()) || NumericT<T>::isNan(value.imag());
3034 }
3035 
3036 template <typename T>
3037 constexpr inline T NumericT<T>::inf()
3038 {
3039  static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
3040 
3041  if constexpr (std::is_same<T, float>::value)
3042  {
3043  static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
3044 
3045  constexpr uint32_t integerValue = 0x7F800000u;
3046 
3047  float floatValue = 0.0f;
3048  memcpy(&floatValue, &integerValue, sizeof(integerValue));
3049 
3050  return T(floatValue);
3051  }
3052  else
3053  {
3054  static_assert(std::is_same<T, double>::value, "Invalid data type!");
3055  static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
3056 
3057  constexpr uint64_t integerValue = 0x7FF0000000000000ull;
3058 
3059  double doubleValue = 0.0;
3060  memcpy(&doubleValue, &integerValue, sizeof(integerValue));
3061 
3062  return T(doubleValue);
3063  }
3064 }
3065 
3066 template <>
3067 inline bool NumericT<float>::isInf(const float value)
3068 {
3069  // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3070  // thus implementing a custom check
3071 
3072  static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
3073 
3074  // IEEE 754: all exponents are encoded as 1, and the mantissa is zero
3075 
3076  uint32_t tmpValue;
3077  memcpy(&tmpValue, &value, sizeof(tmpValue));
3078 
3079  constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
3080  constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
3081 
3082  const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3083  const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0u;
3084 
3085  return allExponentBitsAreOne && allMantissaBitsAreZero;
3086 }
3087 
3088 template <>
3089 inline bool NumericT<double>::isInf(const double value)
3090 {
3091  // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3092  // thus implementing a custom check
3093 
3094  static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3095 
3096  // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3097 
3098  uint64_t tmpValue;
3099  memcpy(&tmpValue, &value, sizeof(tmpValue));
3100 
3101  constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3102  constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3103 
3104  const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3105  const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0ull;
3106 
3107  return allExponentBitsAreOne && allMantissaBitsAreZero;
3108 }
3109 
3110 template <typename T>
3111 inline bool NumericT<T>::isInf(const T /*value*/)
3112 {
3113  // with compiler optimizations, `std::isinf()` will not work anymore (the compiler simply skips the check),
3114  // thus implementing a custom check
3115 
3116  ocean_assert(std::is_floating_point<T>::value == false);
3117  return false;
3118 }
3119 
3120 template <>
3121 inline bool NumericT<long double>::isInf(const long double value)
3122 {
3123  return std::isinf(value);
3124 }
3125 
3126 template <typename T>
3127 inline bool NumericT<T>::isInf(const std::complex<T>& value)
3128 {
3129  return NumericT<T>::isInf(value.real()) || NumericT<T>::isInf(value.imag());
3130 }
3131 
3132 template <typename T>
3133 template <typename TValue>
3134 inline bool NumericT<T>::isInsideValueRange(const TValue& value)
3135 {
3136  if constexpr (std::is_same<T, TValue>::value)
3137  {
3138  // e.g., [int8_t, int8_t], [uint8_t, uint8_t], [float, float], ...
3139 
3140  return true;
3141  }
3142 
3143  if constexpr (std::is_floating_point<T>::value && std::is_floating_point<TValue>::value)
3144  {
3145  // either [float, double], or [double, float]
3146 
3147  // float/double values fit in each other (however, may be casted to inf)
3148 
3149  return true;
3150  }
3151 
3152  if constexpr (std::is_integral<T>::value && std::is_integral<TValue>::value)
3153  {
3154  // e.g., int8_t, uint8_t, int16_t, ...
3155 
3156  if constexpr (std::is_signed<T>::value == std::is_signed<TValue>::value)
3157  {
3158  // e.g., [int8_t, int16_t], [int16_t, int8_t], [int32_t, int64_t], ...
3159 
3160  if constexpr (sizeof(TValue) <= sizeof(T))
3161  {
3162  // e.g., [int16_t, int8_t], [uint64_t, uint8_t], ...
3163 
3164  return true;
3165  }
3166  else
3167  {
3168  ocean_assert(sizeof(T) < sizeof(TValue));
3169 
3170  // e.g., [int8_t, int16_t], [uint8_t, uint64_t], ...
3171 
3172  return TValue(NumericT<T>::minValue()) <= value && value <= TValue(NumericT<T>::maxValue());
3173  }
3174  }
3175 
3176  if constexpr (std::is_signed<T>::value)
3177  {
3178  ocean_assert(!std::is_signed<TValue>::value);
3179 
3180  // e.g., [int8_t, uint8_t], [int32_t, uint8_t], [int64_t, uint16_t], [int8_t, uint64_t], ...
3181 
3182  if constexpr (sizeof(TValue) < sizeof(T))
3183  {
3184  // e.g., [int16_t, uint8_t], [int64_t, uint16_t], ...
3185 
3186  return true;
3187  }
3188 
3189  // e.g., [int8_t, uint8_t], [int8_t, uint32_t], ...
3190 
3191  return value <= TValue(NumericT<T>::maxValue());
3192  }
3193 
3194  if constexpr (std::is_signed<TValue>::value)
3195  {
3196  ocean_assert(!std::is_signed<T>::value);
3197 
3198  // e.g., [uint8_t, int8_t], [uint32_t, int8_t], [uint64_t, int16_t], [uint8_t, int64_t], ...
3199 
3200  if (value < TValue(0))
3201  {
3202  return false;
3203  }
3204 
3205  if constexpr (sizeof(TValue) < sizeof(T))
3206  {
3207  // e.g., [uint16_t, int8_t], [uint_64_t, int16_t], ...
3208 
3209  return true;
3210  }
3211  else if constexpr (sizeof(TValue) == sizeof(T))
3212  {
3213  // e.g., [uint8_t, int8_t], [uint32_t, int32_t], [uint64_t, int64_t], ...
3214 
3215  ocean_assert(value >= TValue(0));
3216 
3217  return true;
3218  }
3219 
3220  // e.g., [uint8_t, int16_t], [uint32_t, int64_t], ...
3221 
3222  ocean_assert(value >= TValue(0));
3223 
3224  return value <= TValue(NumericT<T>::maxValue());
3225  }
3226  }
3227 
3228  return false;
3229 }
3230 
3231 template <typename T>
3232 constexpr inline T NumericT<T>::deg2rad(const T deg)
3233 {
3234  return deg * T(0.017453292519943295769236907684886);
3235 }
3236 
3237 template <typename T>
3238 constexpr inline T NumericT<T>::rad2deg(const T rad)
3239 {
3240  return rad * T(57.295779513082320876798154814105);
3241 }
3242 
3243 template <typename T>
3244 constexpr inline T NumericT<T>::maxValue()
3245 {
3246  return std::numeric_limits<T>::max();
3247 }
3248 
3249 template <typename T>
3250 constexpr inline T NumericT<T>::minValue()
3251 {
3252  return std::numeric_limits<T>::lowest();
3253 }
3254 
3255 template <typename T>
3256 constexpr inline T NumericT<T>::sign(const T& value)
3257 {
3258  static_assert(std::numeric_limits<T>::is_signed, "T must be a signed data type!");
3259 
3260  return T((T(0) < value) - (value < T(0)));
3261 }
3262 
3263 template <typename T>
3264 constexpr inline T NumericT<T>::copySign(const T signReceiver, const T signProvider)
3265 {
3266  if (signProvider >= 0)
3267  {
3268  return abs(signReceiver);
3269  }
3270 
3271  return -abs(signReceiver);
3272 }
3273 
3274 #if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3275 
3276 /**
3277  * Specialization of NumericT::copySign().
3278  * @see NumericT::copySign().
3279  */
3280 template <>
3281 constexpr inline double NumericT<double>::copySign(const double first, const double second)
3282 {
3283  const unsigned long long value = ((*(unsigned long long*)&first) & 0x7FFFFFFFFFFFFFFFll)
3284  | ((*(unsigned long long*)&second) & 0x8000000000000000ll);
3285 
3286 #ifdef OCEAN_DEBUG
3287 
3288  ocean_assert(sizeof(unsigned long long) == sizeof(double));
3289 
3290  const double result = *(double*)&value;
3291 
3292  double testValue = 0;
3293 
3294  if (second >= 0.0)
3295  testValue = NumericT<double>::abs(first);
3296  else
3297  testValue = -NumericT<double>::abs(first);
3298 
3299  ocean_assert(result == testValue || second == 0.0);
3300 
3301 #endif
3302 
3303  return *(double*)&value;
3304 }
3305 
3306 /**
3307  * Specialization of NumericT::copySign().
3308  * @see NumericT::copySign().
3309  */
3310 template <>
3311 constexpr inline float NumericT<float>::copySign(const float first, const float second)
3312 {
3313  const unsigned int value = ((*(unsigned int*)&first) & 0x7FFFFFFF) | ((*(unsigned int*)&second) & 0x80000000);
3314 
3315 #ifdef OCEAN_DEBUG
3316 
3317  ocean_assert(sizeof(unsigned int) == sizeof(float));
3318 
3319  const float result = *(float*)&value;
3320 
3321  float testValue = 0;
3322 
3323  if (second >= 0.0f)
3324  testValue = NumericT<float>::abs(first);
3325  else
3326  testValue = -NumericT<float>::abs(first);
3327 
3328  ocean_assert(result == testValue || second == 0.0);
3329 
3330 #endif
3331 
3332  return *(float*)&value;
3333 }
3334 
3335 #endif // #if 0
3336 
3337 template <typename T>
3338 constexpr inline T NumericT<T>::invertSign(const T signReceiver, const T signProvider)
3339 {
3340  if (signProvider < 0)
3341  {
3342  return abs(signReceiver);
3343  }
3344 
3345  return -abs(signReceiver);
3346 }
3347 
3348 #if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3349 
3350 /**
3351  * Specialization of NumericT::invertSign().
3352  * @see NumericT::invertedSign().
3353  */
3354 template <>
3355 constexpr inline double NumericT<double>::invertSign(const double first, const double second)
3356 {
3357  const unsigned long long value = ((*(unsigned long long*)&first) & 0x7FFFFFFFFFFFFFFFll)
3358  | ((~*(unsigned long long*)&second) & 0x8000000000000000ll);
3359 
3360 #ifdef OCEAN_DEBUG
3361 
3362  ocean_assert(sizeof(unsigned long long) == sizeof(double));
3363 
3364  const double result = *(double*)&value;
3365 
3366  double testValue = 0;
3367 
3368  if (second < 0)
3369  testValue = NumericT<double>::abs(first);
3370  else
3371  testValue = -NumericT<double>::abs(first);
3372 
3373  ocean_assert(result == testValue);
3374 
3375 #endif
3376 
3377 
3378  return *(double*)&value;
3379 }
3380 
3381 /**
3382  * Specialization of NumericT::invertSign().
3383  * @see NumericT::invertSign().
3384  */
3385 template <>
3386 constexpr inline float NumericT<float>::invertSign(const float first, const float second)
3387 {
3388  const unsigned int value = ((*(unsigned int*)&first) & 0x7FFFFFFF) | ((~*(unsigned int*)&second) & 0x80000000);
3389 
3390 #ifdef OCEAN_DEBUG
3391 
3392  ocean_assert(sizeof(unsigned int) == sizeof(float));
3393 
3394  const float result = *(float*)&value;
3395 
3396  double testValue = 0;
3397 
3398  if (second < 0)
3399  testValue = NumericT<float>::abs(first);
3400  else
3401  testValue = -NumericT<float>::abs(first);
3402 
3403  ocean_assert(result == testValue);
3404 
3405 #endif
3406 
3407  return *(float*)&value;
3408 }
3409 
3410 #endif // #if 0
3411 
3412 template <typename T>
3413 T NumericT<T>::pythagoras(const T a, const T b)
3414 {
3415  const T absA = NumericT<T>::abs(a);
3416  const T absB = NumericT<T>::abs(b);
3417 
3418  if (absA > absB)
3419  {
3420  const T factor = absB / absA;
3421  return absA * sqrt(1 + factor * factor);
3422  }
3423  else if (absB != 0)
3424  {
3425  const T factor = absA / absB;
3426  return absB * sqrt(1 + factor * factor);
3427  }
3428 
3429  return 0;
3430 }
3431 
3432 template <typename T>
3433 inline T NumericT<T>::gaussianDistribution(const T x, const T sigma)
3434 {
3435  ocean_assert(sigma > eps());
3436 
3437  const T inverseSigma = T(1) / sigma;
3438 
3439  return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3440 }
3441 
3442 template <typename T>
3443 inline T NumericT<T>::gaussianDistribution(const T x, const T x0, const T sigma)
3444 {
3445  ocean_assert(sigma > eps());
3446 
3447  const T inverseSigma = T(1) / sigma;
3448  const T x_x0 = x - x0;
3449 
3450  return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3451 }
3452 
3453 template <typename T>
3454 inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T sigma)
3455 {
3456  ocean_assert(sigma > eps());
3457 
3458  const T inverseSigma = T(1) / sigma;
3459 
3460  return NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3461 }
3462 
3463 template <typename T>
3464 inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T x0, const T sigma)
3465 {
3466  ocean_assert(sigma > eps());
3467 
3468  const T inverseSigma = T(1) / sigma;
3469  const T x_x0 = x - x0;
3470 
3471  return NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3472 }
3473 
3474 template <typename T>
3475 inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3476 {
3477  ocean_assert(sigmaX > eps() && sigmaY > eps());
3478 
3479  const T inverseSigmaX = T(1) / sigmaX;
3480  const T inverseSigmaY = T(1) / sigmaY;
3481 
3482  return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3483 }
3484 
3485 template <typename T>
3486 inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3487 {
3488  ocean_assert(sigmaX > eps() && sigmaY > eps());
3489 
3490  const T inverseSigmaX = T(1) / sigmaX;
3491  const T inverseSigmaY = T(1) / sigmaY;
3492 
3493  const T x_x0 = x - x0;
3494  const T y_y0 = y - y0;
3495 
3496  return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3497 }
3498 
3499 template <typename T>
3500 inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3501 {
3502  ocean_assert(sigmaX > eps() && sigmaY > eps());
3503 
3504  const T inverseSigmaX = T(1) / sigmaX;
3505  const T inverseSigmaY = T(1) / sigmaY;
3506 
3507  return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3508 }
3509 
3510 template <typename T>
3511 inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3512 {
3513  ocean_assert(sigmaX > eps() && sigmaY > eps());
3514 
3515  const T inverseSigmaX = T(1) / sigmaX;
3516  const T inverseSigmaY = T(1) / sigmaY;
3517 
3518  const T x_x0 = x - x0;
3519  const T y_y0 = y - y0;
3520 
3521  return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3522 }
3523 
3524 template <typename T>
3525 inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3526 {
3527  ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3528 
3529  const T inverseSigmaX = T(1) / sigmaX;
3530  const T inverseSigmaY = T(1) / sigmaY;
3531  const T inverseSigmaZ = T(1) / sigmaZ;
3532 
3533  return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3534  * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3535 }
3536 
3537 template <typename T>
3538 inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ)
3539 {
3540  ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3541 
3542  const T inverseSigmaX = T(1) / sigmaX;
3543  const T inverseSigmaY = T(1) / sigmaY;
3544  const T inverseSigmaZ = T(1) / sigmaZ;
3545 
3546  const T x_x0 = x - x0;
3547  const T y_y0 = y - y0;
3548  const T z_z0 = z - z0;
3549 
3550  return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3551  * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3552 }
3553 
3554 template <typename T>
3555 inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3556 {
3557  ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3558 
3559  const T inverseSigmaX = T(1) / sigmaX;
3560  const T inverseSigmaY = T(1) / sigmaY;
3561  const T inverseSigmaZ = T(1) / sigmaZ;
3562 
3563  return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3564 }
3565 
3566 template <typename T>
3567 inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ)
3568 {
3569  ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3570 
3571  const T inverseSigmaX = T(1) / sigmaX;
3572  const T inverseSigmaY = T(1) / sigmaY;
3573  const T inverseSigmaZ = T(1) / sigmaZ;
3574 
3575  const T x_x0 = x - x0;
3576  const T y_y0 = y - y0;
3577  const T z_z0 = z - z0;
3578 
3579  return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3580 }
3581 
3582 }
3583 
3584 #endif // META_OCEAN_MATH_NUMERIC_H
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static T angleAdjustPositive(const T angle)
Adjusts an arbitrary angle into the range of [0.0, 2PI).
Definition: Numeric.h:1764
static constexpr T deg2rad(const T deg)
Converts deg to rad.
Definition: Numeric.h:3232
static constexpr bool isNotWeakEqualEps(const T value)
Returns whether a value is not smaller than or equal to a weak epsilon.
Definition: Numeric.h:2312
static constexpr T minValue()
Returns the min scalar value.
Definition: Numeric.h:3250
static constexpr T pi2()
Returns 2*PI which is equivalent to 360 degree.
Definition: Numeric.h:932
static constexpr T sign(const T &value)
Returns the sign of a given value by either returning -1, 0, or +1.
Definition: Numeric.h:3256
static constexpr T weakEps()
Returns a weak epsilon.
static constexpr bool isInsideRange(const T lower, const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a value lies between a given range up to a provided epsilon border.
Definition: Numeric.h:2872
static constexpr T pi_2()
Returns PI/2 which is equivalent to 90 degree.
Definition: Numeric.h:938
static T log(const T value)
Returns the natural logarithm of a given value (the logarithm to the base e).
Definition: Numeric.h:1655
static T exp(const T value)
Returns the base-e exponential function of a given value.
Definition: Numeric.h:1643
static T log1p(const T value)
Returns the natural logarithm of a given value plus 1 (the logarithm to the base e).
Definition: Numeric.h:1669
static constexpr T e()
Returns the euler's number.
Definition: Numeric.h:974
static T atan(const T value)
Returns the arctangent of a given value.
Definition: Numeric.h:1616
static T atan2(const T y, const T x)
Returns the arctangent of a given value in radian.
Definition: Numeric.h:1632
static constexpr T sqrDistance(const T value0, const T value1)
Returns the square distance between two values.
Definition: Numeric.h:1527
static T sin(const T value)
Returns the sine of a given value.
Definition: Numeric.h:1568
static bool isInf(const T value)
Returns whether a given value is positive or negative infinity.
Definition: Numeric.h:3111
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition: Numeric.h:1860
static constexpr T pi_4()
Returns PI/4 which is equivalent to 45 degree.
Definition: Numeric.h:950
static bool isNan(const T value)
Returns whether a given value is not a number.
Definition: Numeric.h:3021
static T abs(const T value)
Returns the absolute value of a given value.
Definition: Numeric.h:1220
static constexpr T factorial(const T &value)
Returns the factorial for a given value.
Definition: Numeric.h:1888
static constexpr T pi()
Returns PI which is equivalent to 180 degree.
Definition: Numeric.h:926
static T log10(const T value)
Returns the logarithm to base 10 of a given value.
Definition: Numeric.h:1711
static constexpr T squarePi2()
Returns the square of two PI i.e., (2*PI)^2.
Definition: Numeric.h:962
static constexpr bool isAbove(const T value, const T lower, const T epsilon=NumericT< T >::eps())
Returns whether a parameter lies on or above a given border tolerating a small epsilon.
Definition: Numeric.h:2937
static bool isWeakEqual(const T first, const T second)
Returns whether two values a equal up to a weak epsilon.
Definition: Numeric.h:2572
static T normalizedGaussianDistribution(const T x, const T sigma)
Returns a value of the normalized univariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3454
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition: Numeric.h:2064
static T sum(const T *values, const size_t number)
Returns the sum of given values.
Definition: Numeric.h:1501
static constexpr bool isWeakEqualEps(const T value)
Returns whether a value is smaller than or equal to a weak epsilon.
Definition: Numeric.h:2162
static T sqrt(const T value)
Returns the square root of a given value.
Definition: Numeric.h:1533
static T pythagoras(const T a, const T b)
Returns the length of the hypotenuse of a given right-angled triangle.
Definition: Numeric.h:3413
static T fmod(const T valueA, const T valueB)
Returns the floating-point remainder of a given value.
Definition: Numeric.h:1735
static T angleAdjustNull(const T angle)
Adjusts an arbitrary angle into the range of (-PI, PI].
Definition: Numeric.h:1794
static bool angleIsBelowThreshold(const T angleA, const T angleB, const T threshold)
Returns whether the angular difference (distance) between two angles is smaller than a specified thre...
Definition: Numeric.h:1838
static constexpr T eps()
Returns a small epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition: Numeric.h:2386
static constexpr bool isBelow(const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a parameter lies on or below a given border tolerating a small epsilon.
Definition: Numeric.h:2927
static T gaussianDistribution(const T x, const T sigma)
Returns a value of the univariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3433
static T gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
Returns a value of the bivariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3475
static constexpr T ratio(const T nominator, const T denominator, const T fallback=T(1))
Returns the ratio between two values if the denominator is not equal a small epsilon.
Definition: Numeric.h:2076
static constexpr T nan()
Returns a value which is not a number (nan).
Definition: Numeric.h:2947
static constexpr T squarePi_2()
Returns the square of PI half i.e., (PI/2)^2.
Definition: Numeric.h:968
static T floor(const T value)
Returns the largest integer value that is not greater than the given value.
Definition: Numeric.h:2026
static constexpr T integerPow(const T x, const unsigned int y)
Returns x raised to the power of y while y is an integer.
Definition: Numeric.h:1882
static constexpr T squarePi()
Returns the square of PI i.e., PI^2.
Definition: Numeric.h:956
static T tan(const T value)
Returns the tangent of a given value.
Definition: Numeric.h:1600
static T normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
Returns a value of the normalized trivariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3555
static UnsignedTyper< T >::Type secureAbs(const T value)
Returns the absolute value of a given value while the return value is guaranteed to be the absolute v...
Definition: Numeric.h:1356
static T ceil(const T value)
Returns the smallest integer value that is not less than the given value.
Definition: Numeric.h:1988
static constexpr int64_t round64(const T value)
Returns the rounded 64 bit integer value of a given value.
Definition: Numeric.h:2070
static bool angleIsEqual(const T angleA, const T angleB)
Returns whether two angles represent the same angle up to a small epsilon.
Definition: Numeric.h:1819
static constexpr T pi_3()
Returns PI/3 which is equivalent to 60 degree.
Definition: Numeric.h:944
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
static T angleAdjustPositiveHalf(const T angle)
Adjusts an arbitrary angle into the range of [0.0, PI).
Definition: Numeric.h:1779
static constexpr bool isInsideWeakRange(const T lower, const T value, const T upper)
Returns whether a value lies between a given range up to a weak epsilon border.
Definition: Numeric.h:2881
static T normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
Returns a value of the normalized bivariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3500
static bool isEqual(const T first, const T second, const T referenceEpsilon)
Returns whether two values are equal up to a dynamic epsilon which is adjusted due to the magnitude o...
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition: Numeric.h:2087
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition: Numeric.h:3264
static constexpr T rad2deg(const T rad)
Converts rad to deg.
Definition: Numeric.h:3238
static T cos(const T value)
Returns the cosine of a given value.
Definition: Numeric.h:1584
static T gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
Returns a value of the trivariate Gaussian distribution centered around the origin.
Definition: Numeric.h:3525
static T dot(const T *vectorA, const T *vectorB, const size_t size)
Returns the dot product for two vectors.
Definition: Numeric.h:1751
static bool isInsideValueRange(const TValue &value)
Returns whether a given value of an arbitrary data type fits into the value range of 'T'.
Definition: Numeric.h:3134
static T acos(const T value)
Returns the arccosine of a given value.
Definition: Numeric.h:2907
static constexpr T invertSign(const T signReceiver, const T signProvider)
Copies the inverted sign of a given value to another one.
Definition: Numeric.h:3338
static constexpr T inf()
Returns a value which is positive infinity.
Definition: Numeric.h:3037
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition: Numeric.h:2237
static bool angleIsWeakEqual(const T angleA, const T angleB)
Returns whether two angles represent the same angle up to a weak epsilon.
Definition: Numeric.h:1825
static T angleDistance(const T angleA, const T angleB)
Returns the angular difference (distance between two angles).
Definition: Numeric.h:1846
static bool isNotEqual(const T first, const T second)
Returns whether two values are not equal up to a small epsilon.
Definition: Numeric.h:2613
static T summedSqr(const T *values, const size_t number)
Returns the summed squares of a given values.
Definition: Numeric.h:1514
static T log2(const T value)
Returns the logarithm to base 2 of a given value.
Definition: Numeric.h:1683
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
static T asin(const T value)
Returns the arcsine of a given value.
Definition: Numeric.h:2887
static bool isNotWeakEqual(const T first, const T second)
Returns whether two values are not equal up to a weak epsilon.
Definition: Numeric.h:2686
static constexpr T binomialCoefficient(const T &n, const T &k)
Returns the binomial coefficient for two binomial parameters.
Definition: Numeric.h:1957
T Type
Definition of the unsigned data type, if existing.
Definition: DataType.h:339
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition: base/Utilities.h:1029
NumericT< Scalar > Numeric
Definition of a Numeric class.
Definition: Numeric.h:26
NumericT< float > NumericF
Definition of a Numeric class with float values.
Definition: Numeric.h:47
NumericT< double > NumericD
Definition of a Numeric class with double values.
Definition: Numeric.h:40
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15