Ocean
Loading...
Searching...
No Matches
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
22namespace Ocean
23{
24
25// Forward declaration.
26template <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 */
55template <typename T>
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
925template <typename T>
926constexpr T NumericT<T>::pi()
927{
928 return T(3.1415926535897932384626433832795);
929}
930
931template <typename T>
932constexpr T NumericT<T>::pi2()
933{
934 return T(6.283185307179586476925286766559);
935}
936
937template <typename T>
938constexpr T NumericT<T>::pi_2()
939{
940 return T(1.5707963267948966192313216916395);
941}
942
943template <typename T>
944constexpr T NumericT<T>::pi_3()
945{
946 return T(1.0471975511965977461542144610932);
947}
948
949template <typename T>
950constexpr T NumericT<T>::pi_4()
951{
952 return T(0.78539816339744830961566084581988);
953}
954
955template <typename T>
957{
958 return T(9.8696044010893586188344909998762);
959}
960
961template <typename T>
963{
964 return T(39.478417604357434475337963999505);
965}
966
967template <typename T>
969{
970 return T(2.4674011002723396547086227499667);
971}
972
973template <typename T>
974constexpr T NumericT<T>::e()
975{
976 return T(2.71828182845904523536);
977}
978
979/**
980 * Specialization of NumericT::eps().
981 * @see NumericT::eps().
982 */
983template <>
984constexpr double NumericT<double>::eps()
985{
986 return 1e-12;
987}
988
989/**
990 * Specialization of NumericT::eps().
991 * @see NumericT::eps().
992 */
993template <>
994constexpr float NumericT<float>::eps()
995{
996 return 1e-6f;
997}
998
999/**
1000 * Specialization of NumericT::eps().
1001 * @see NumericT::eps().
1002 */
1003template <>
1004constexpr signed char NumericT<signed char>::eps()
1005{
1006 return 0;
1007}
1008
1009/**
1010 * Specialization of NumericT::eps().
1011 * @see NumericT::eps().
1012 */
1013template <>
1014constexpr unsigned char NumericT<unsigned char>::eps()
1015{
1016 return 0u;
1017}
1018
1019/**
1020 * Specialization of NumericT::eps().
1021 * @see NumericT::eps().
1022 */
1023template <>
1024constexpr short NumericT<short>::eps()
1025{
1026 return 0;
1027}
1028
1029/**
1030 * Specialization of NumericT::eps().
1031 * @see NumericT::eps().
1032 */
1033template <>
1034constexpr unsigned short NumericT<unsigned short>::eps()
1035{
1036 return 0u;
1037}
1038
1039/**
1040 * Specialization of NumericT::eps().
1041 * @see NumericT::eps().
1042 */
1043template <>
1044constexpr int NumericT<int>::eps()
1045{
1046 return 0;
1047}
1048
1049/**
1050 * Specialization of NumericT::eps().
1051 * @see NumericT::eps().
1052 */
1053template <>
1054constexpr unsigned int NumericT<unsigned int>::eps()
1055{
1056 return 0u;
1057}
1058
1059/**
1060 * Specialization of NumericT::eps().
1061 * @see NumericT::eps().
1062 */
1063template <>
1064constexpr long NumericT<long>::eps()
1065{
1066 return 0l;
1067}
1068
1069/**
1070 * Specialization of NumericT::eps().
1071 * @see NumericT::eps().
1072 */
1073template <>
1074constexpr unsigned long NumericT<unsigned long>::eps()
1075{
1076 return 0ul;
1077}
1078
1079/**
1080 * Specialization of NumericT::eps().
1081 * @see NumericT::eps().
1082 */
1083template <>
1084constexpr long long NumericT<long long>::eps()
1085{
1086 return 0ll;
1087}
1088
1089/**
1090 * Specialization of NumericT::eps().
1091 * @see NumericT::eps().
1092 */
1093template <>
1094constexpr 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 */
1103template <>
1105{
1106 return 1e-6;
1107}
1108
1109/**
1110 * Specialization of NumericT::weakEps().
1111 * @see NumericT::weakEps().
1112 */
1113template <>
1115{
1116 return 1e-3f;
1117}
1118
1119/**
1120 * Specialization of NumericT::weakEps().
1121 * @see NumericT::weakEps().
1122 */
1123template <>
1124constexpr signed char NumericT<signed char>::weakEps()
1125{
1126 return 0;
1127}
1128
1129/**
1130 * Specialization of NumericT::weakEps().
1131 * @see NumericT::weakEps().
1132 */
1133template <>
1134constexpr unsigned char NumericT<unsigned char>::weakEps()
1135{
1136 return 0u;
1137}
1138
1139/**
1140 * Specialization of NumericT::weakEps().
1141 * @see NumericT::weakEps().
1142 */
1143template <>
1145{
1146 return 0;
1147}
1148
1149/**
1150 * Specialization of NumericT::weakEps().
1151 * @see NumericT::weakEps().
1152 */
1153template <>
1154constexpr unsigned short NumericT<unsigned short>::weakEps()
1155{
1156 return 0u;
1157}
1158
1159/**
1160 * Specialization of NumericT::weakEps().
1161 * @see NumericT::weakEps().
1162 */
1163template <>
1165{
1166 return 0;
1167}
1168
1169/**
1170 * Specialization of NumericT::weakEps().
1171 * @see NumericT::weakEps().
1172 */
1173template <>
1174constexpr unsigned int NumericT<unsigned int>::weakEps()
1175{
1176 return 0u;
1177}
1178
1179/**
1180 * Specialization of NumericT::weakEps().
1181 * @see NumericT::weakEps().
1182 */
1183template <>
1185{
1186 return 0l;
1187}
1188
1189/**
1190 * Specialization of NumericT::weakEps().
1191 * @see NumericT::weakEps().
1192 */
1193template <>
1194constexpr unsigned long NumericT<unsigned long>::weakEps()
1195{
1196 return 0ul;
1197}
1198
1199/**
1200 * Specialization of NumericT::weakEps().
1201 * @see NumericT::weakEps().
1202 */
1203template <>
1204constexpr long long NumericT<long long>::weakEps()
1205{
1206 return 0ll;
1207}
1208
1209/**
1210 * Specialization of NumericT::weakEps().
1211 * @see NumericT::weakEps().
1212 */
1213template <>
1214constexpr unsigned long long NumericT<unsigned long long>::weakEps()
1215{
1216 return 0ull;
1217}
1218
1219template <typename T>
1220inline 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 */
1229template <>
1230inline 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 */
1241template <>
1242inline 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 */
1251template <>
1252inline 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 */
1263template <>
1264inline 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 */
1273template <>
1274inline 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 */
1285template <>
1286inline 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 */
1295template <>
1296inline 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 */
1307template <>
1308inline 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 */
1317template <>
1318inline 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 */
1329template <>
1330inline 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 */
1339template <>
1340inline 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 */
1349template <>
1350inline float NumericT<float>::abs(const float value)
1351{
1352 return fabsf(value);
1353}
1354
1355template <typename T>
1357{
1358 return typename UnsignedTyper<T>::Type(::abs(value));
1359}
1360
1361/**
1362 * Specialization of NumericT::secureAbs().
1363 * @see NumericT::secureAbs().
1364 */
1365template <>
1366inline 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 */
1375template <>
1376inline 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 */
1385template <>
1386inline 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 */
1395template <>
1396inline 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 */
1405template <>
1406inline 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 */
1421template <>
1422inline 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 */
1431template <>
1432inline 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 */
1442template <>
1443inline 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 */
1452template <>
1453inline 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 */
1468template <>
1469inline 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 */
1478template <>
1479inline 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 */
1488template <>
1489inline float NumericT<float>::secureAbs(const float value)
1490{
1491 return abs(value);
1492}
1493
1494template <typename T>
1495constexpr inline T NumericT<T>::sqr(const T value)
1496{
1497 return value * value;
1498}
1499
1500template <typename T>
1501inline 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
1513template <typename T>
1514inline 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
1526template <typename T>
1527constexpr inline T NumericT<T>::sqrDistance(const T value0, const T value1)
1528{
1529 return sqr(value0 - value1);
1530}
1531
1532template <typename T>
1533inline 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 */
1543template <>
1544inline 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 */
1554template <>
1555inline int NumericT<int>::sqrt(const int value)
1556{
1557 ocean_assert(value >= 0);
1558 return int(::sqrtf(float(value)));
1559}
1560
1561template <typename T>
1562inline std::complex<T> NumericT<T>::sqrt(const std::complex<T>& value)
1563{
1564 return std::sqrt<T>(value);
1565}
1566
1567template <typename T>
1568inline 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 */
1577template <>
1578inline float NumericT<float>::sin(const float value)
1579{
1580 return sinf(value);
1581}
1582
1583template <typename T>
1584inline 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 */
1593template <>
1594inline float NumericT<float>::cos(const float value)
1595{
1596 return cosf(value);
1597}
1598
1599template <typename T>
1600inline 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 */
1609template <>
1610inline float NumericT<float>::tan(const float value)
1611{
1612 return tanf(value);
1613}
1614
1615template <typename T>
1616inline 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 */
1625template <>
1626inline float NumericT<float>::atan(const float value)
1627{
1628 return atanf(value);
1629}
1630
1631template <typename T>
1632inline 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
1642template <typename T>
1643inline T NumericT<T>::exp(const T value)
1644{
1645 return ::exp(value);
1646}
1647
1648template <>
1649inline float NumericT<float>::exp(const float value)
1650{
1651 return ::expf(value);
1652}
1653
1654template <typename T>
1655inline T NumericT<T>::log(const T value)
1656{
1657 ocean_assert(value > 0);
1658 return ::log(value);
1659}
1660
1661template <>
1662inline float NumericT<float>::log(const float value)
1663{
1664 ocean_assert(value > 0);
1665 return ::logf(value);
1666}
1667
1668template <typename T>
1669inline T NumericT<T>::log1p(const T value)
1670{
1671 ocean_assert(value > -1);
1672 return ::log1p(value);
1673}
1674
1675template <>
1676inline float NumericT<float>::log1p(const float value)
1677{
1678 ocean_assert(value > -1);
1679 return ::log1pf(value);
1680}
1681
1682template <typename T>
1683inline 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 */
1698template <>
1699inline 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
1710template <typename T>
1711inline T NumericT<T>::log10(const T value)
1712{
1713 ocean_assert(value > 0);
1714 return ::log10(value);
1715}
1716
1717template <>
1718inline 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 */
1728template <>
1729inline float NumericT<float>::atan2(const float y, const float x)
1730{
1731 return atan2f(y, x);
1732}
1733
1734template <typename T>
1735inline 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 */
1744template <>
1745inline float NumericT<float>::fmod(const float valueA, const float valueB)
1746{
1747 return fmodf(valueA, valueB);
1748}
1749
1750template <typename T>
1751inline 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
1763template <typename T>
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
1778template <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
1793template <typename T>
1794inline 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
1818template <typename T>
1819inline bool NumericT<T>::angleIsEqual(const T angleA, const T angleB)
1820{
1821 return isEqualEps(angleDistance(angleA, angleB));
1822}
1823
1824template <typename T>
1825inline bool NumericT<T>::angleIsWeakEqual(const T angleA, const T angleB)
1826{
1827 return isWeakEqualEps(angleDistance(angleA, angleB));
1828}
1829
1830template <typename T>
1831inline 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
1837template <typename T>
1838inline 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
1845template <typename T>
1846inline 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
1859template <typename T>
1860inline T NumericT<T>::pow(const T x, const T y)
1861{
1862 return ::pow(x, y);
1863}
1864
1865template <typename T>
1866inline 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 */
1875template <>
1876inline float NumericT<float>::pow(const float x, const float y)
1877{
1878 return powf(x, y);
1879}
1880
1881template <typename T>
1882constexpr 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
1887template <typename T>
1888constexpr inline T NumericT<T>::factorial(const T& value)
1889{
1890 ocean_assert(value >= 0);
1891 ocean_assert(T(int64_t(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(maxValue() / T(n) >= result);
1903 result *= T(n);
1904 }
1905
1906 return result;
1907}
1908
1909template <>
1910constexpr 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 default:
1952 break;
1953 }
1954
1955 ocean_assert(false && "Invalid factorial value!");
1956 return 1u;
1957}
1958
1959template <typename T>
1960constexpr inline T NumericT<T>::binomialCoefficient(const T& n, const T& k)
1961{
1962 ocean_assert(n >= 0 && k >= 0);
1963 ocean_assert(T(int64_t(n)) == n);
1964 ocean_assert(T(int64_t(k)) == k);
1965
1966 if (n <= T(1) || k == T(0) || n == k)
1967 {
1968 return T(1);
1969 }
1970
1971 ocean_assert(k < n);
1972
1973 T result = n - k + T(1);
1974
1975 for (unsigned int i = (unsigned int)(n - k) + 2u; i <= (unsigned int)(n); ++i)
1976 {
1977 ocean_assert(maxValue() / T(i) >= result);
1978 result *= T(i);
1979 }
1980
1981 for (unsigned int i = 2u; i <= (unsigned int)(k); ++i)
1982 {
1983 ocean_assert((result / T(i)) * T(i) == result);
1984 result /= T(i);
1985 }
1986
1987 return result;
1988}
1989
1990template <typename T>
1991inline T NumericT<T>::ceil(const T value)
1992{
1993 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
1994
1995 return value;
1996}
1997
1998/**
1999 * Specialization of NumericT::ceil().
2000 * @see NumericT::ceil().
2001 */
2002template <>
2003inline float NumericT<float>::ceil(const float value)
2004{
2005 return ::ceilf(value);
2006}
2007
2008/**
2009 * Specialization of NumericT::ceil().
2010 * @see NumericT::ceil().
2011 */
2012template <>
2013inline double NumericT<double>::ceil(const double value)
2014{
2015 return ::ceil(value);
2016}
2017
2018/**
2019 * Specialization of NumericT::ceil().
2020 * @see NumericT::ceil().
2021 */
2022template <>
2023inline long double NumericT<long double>::ceil(const long double value)
2024{
2025 return ::ceill(value);
2026}
2027
2028template <typename T>
2029inline T NumericT<T>::floor(const T value)
2030{
2031 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
2032
2033 return value;
2034}
2035
2036/**
2037 * Specialization of NumericT::floor().
2038 * @see NumericT::floor().
2039 */
2040template <>
2041inline float NumericT<float>::floor(const float value)
2042{
2043 return ::floorf(value);
2044}
2045
2046/**
2047 * Specialization of NumericT::floor().
2048 * @see NumericT::floor().
2049 */
2050template <>
2051inline double NumericT<double>::floor(const double value)
2052{
2053 return ::floor(value);
2054}
2055
2056/**
2057 * Specialization of NumericT::floor().
2058 * @see NumericT::floor().
2059 */
2060template <>
2061inline long double NumericT<long double>::floor(const long double value)
2062{
2063 return ::floorl(value);
2064}
2065
2066template <typename T>
2067constexpr inline int32_t NumericT<T>::round32(const T value)
2068{
2069 return int32_t(value + copySign(T(0.5), value));
2070}
2071
2072template <typename T>
2073constexpr inline int64_t NumericT<T>::round64(const T value)
2074{
2075 return int64_t(value + copySign(T(0.5), value));
2076}
2077
2078template <typename T>
2079constexpr inline T NumericT<T>::ratio(const T nominator, const T denominator, const T fallback)
2080{
2081 if (isEqualEps(denominator))
2082 {
2083 return fallback;
2084 }
2085
2086 return nominator / denominator;
2087}
2088
2089template <typename T>
2090constexpr inline bool NumericT<T>::isEqualEps(const T value)
2091{
2092 ocean_assert(isNan(value) == false);
2093 ocean_assert((fabs(value) <= eps()) == (-eps() <= value && value <= eps()));
2094
2095 return -eps() <= value && value <= eps();
2096}
2097
2098template <>
2099constexpr inline bool NumericT<signed char>::isEqualEps(const signed char value)
2100{
2101 return value == (signed char)(0);
2102}
2103
2104template <>
2105constexpr inline bool NumericT<unsigned char>::isEqualEps(const unsigned char value)
2106{
2107 return value == (unsigned char)(0);
2108}
2109
2110template <>
2111constexpr inline bool NumericT<short>::isEqualEps(const short value)
2112{
2113 return value == short(0);
2114}
2115
2116template <>
2117constexpr inline bool NumericT<unsigned short>::isEqualEps(const unsigned short value)
2118{
2119 return value == (unsigned short)(0);
2120}
2121
2122template <>
2123constexpr inline bool NumericT<int>::isEqualEps(const int value)
2124{
2125 return value == 0;
2126}
2127
2128template <>
2129constexpr inline bool NumericT<unsigned int>::isEqualEps(const unsigned int value)
2130{
2131 return value == 0u;
2132}
2133
2134template <>
2135constexpr inline bool NumericT<long>::isEqualEps(const long value)
2136{
2137 return value == 0l;
2138}
2139
2140template <>
2141constexpr inline bool NumericT<unsigned long>::isEqualEps(const unsigned long value)
2142{
2143 return value == 0ul;
2144}
2145
2146template <>
2147constexpr inline bool NumericT<long long>::isEqualEps(const long long value)
2148{
2149 return value == 0ll;
2150}
2151
2152template <>
2153constexpr inline bool NumericT<unsigned long long>::isEqualEps(const unsigned long long value)
2154{
2155 return value == 0ull;
2156}
2157
2158template <typename T>
2159constexpr inline bool NumericT<T>::isEqualEps(const std::complex<T>& value)
2160{
2161 return isEqualEps(value.real()) && isEqualEps(value.imag());
2162}
2163
2164template <typename T>
2165constexpr inline bool NumericT<T>::isWeakEqualEps(const T value)
2166{
2167 ocean_assert(isNan(value) == false);
2168 ocean_assert((fabs(value) <= weakEps()) == (-weakEps() <= value && value <= weakEps()));
2169
2170 return -weakEps() <= value && value <= weakEps();
2171}
2172
2173template <>
2174constexpr inline bool NumericT<signed char>::isWeakEqualEps(const signed char value)
2175{
2176 return value == (signed char)(0);
2177}
2178
2179template <>
2180constexpr inline bool NumericT<unsigned char>::isWeakEqualEps(const unsigned char value)
2181{
2182 return value == (unsigned char)(0);
2183}
2184
2185template <>
2186constexpr inline bool NumericT<short>::isWeakEqualEps(const short value)
2187{
2188 return value == short(0);
2189}
2190
2191template <>
2192constexpr inline bool NumericT<unsigned short>::isWeakEqualEps(const unsigned short value)
2193{
2194 return value == (unsigned short)(0);
2195}
2196
2197template <>
2198constexpr inline bool NumericT<int>::isWeakEqualEps(const int value)
2199{
2200 return value == 0;
2201}
2202
2203template <>
2204constexpr inline bool NumericT<unsigned int>::isWeakEqualEps(const unsigned int value)
2205{
2206 return value == 0u;
2207}
2208
2209template <>
2210constexpr inline bool NumericT<long>::isWeakEqualEps(const long value)
2211{
2212 return value == 0l;
2213}
2214
2215template <>
2216constexpr inline bool NumericT<unsigned long>::isWeakEqualEps(const unsigned long value)
2217{
2218 return value == 0ul;
2219}
2220
2221template <>
2222constexpr inline bool NumericT<long long>::isWeakEqualEps(const long long value)
2223{
2224 return value == 0ll;
2225}
2226
2227template <>
2228constexpr inline bool NumericT<unsigned long long>::isWeakEqualEps(const unsigned long long value)
2229{
2230 return value == 0ull;
2231}
2232
2233template <typename T>
2234constexpr inline bool NumericT<T>::isWeakEqualEps(const std::complex<T>& value)
2235{
2236 return isWeakEqualEps(value.real()) && isWeakEqualEps(value.imag());
2237}
2238
2239template <typename T>
2240constexpr inline bool NumericT<T>::isNotEqualEps(const T value)
2241{
2242 ocean_assert(isNan(value) == false);
2243 ocean_assert((fabs(value) > eps()) == (value > eps() || value < -eps()));
2244
2245 return value > eps() || value < -eps();
2246}
2247
2248template <>
2249constexpr inline bool NumericT<signed char>::isNotEqualEps(const signed char value)
2250{
2251 return value != (signed char)(0);
2252}
2253
2254template <>
2255constexpr inline bool NumericT<unsigned char>::isNotEqualEps(const unsigned char value)
2256{
2257 return value != (unsigned char)(0);
2258}
2259
2260template <>
2261constexpr inline bool NumericT<short>::isNotEqualEps(const short value)
2262{
2263 return value != short(0);
2264}
2265
2266template <>
2267constexpr inline bool NumericT<unsigned short>::isNotEqualEps(const unsigned short value)
2268{
2269 return value != (unsigned short)(0);
2270}
2271
2272template <>
2273constexpr inline bool NumericT<int>::isNotEqualEps(const int value)
2274{
2275 return value != 0;
2276}
2277
2278template <>
2279constexpr inline bool NumericT<unsigned int>::isNotEqualEps(const unsigned int value)
2280{
2281 return value != 0u;
2282}
2283
2284template <>
2285constexpr inline bool NumericT<long>::isNotEqualEps(const long value)
2286{
2287 return value != 0l;
2288}
2289
2290template <>
2291constexpr inline bool NumericT<unsigned long>::isNotEqualEps(const unsigned long value)
2292{
2293 return value != 0ul;
2294}
2295
2296template <>
2297constexpr inline bool NumericT<long long>::isNotEqualEps(const long long value)
2298{
2299 return value != 0ll;
2300}
2301
2302template <>
2303constexpr inline bool NumericT<unsigned long long>::isNotEqualEps(const unsigned long long value)
2304{
2305 return value != 0ull;
2306}
2307
2308template <typename T>
2309constexpr inline bool NumericT<T>::isNotEqualEps(const std::complex<T>& value)
2310{
2311 return value.real() > eps() || value.real() < -eps() || value.imag() > eps() || value.imag() < -eps();
2312}
2313
2314template <typename T>
2315constexpr inline bool NumericT<T>::isNotWeakEqualEps(const T value)
2316{
2317 ocean_assert((fabs(value) > weakEps()) == (value > weakEps() || value < -weakEps()));
2318
2319 return value > weakEps() || value < -weakEps();
2320}
2321
2322template <>
2323constexpr inline bool NumericT<signed char>::isNotWeakEqualEps(const signed char value)
2324{
2325 return value != (signed char)(0);
2326}
2327
2328template <>
2329constexpr inline bool NumericT<unsigned char>::isNotWeakEqualEps(const unsigned char value)
2330{
2331 return value != (unsigned char)(0);
2332}
2333
2334template <>
2335constexpr inline bool NumericT<short>::isNotWeakEqualEps(const short value)
2336{
2337 return value != short(0);
2338}
2339
2340template <>
2341constexpr inline bool NumericT<unsigned short>::isNotWeakEqualEps(const unsigned short value)
2342{
2343 return value != (unsigned short)(0);
2344}
2345
2346template <>
2347constexpr inline bool NumericT<int>::isNotWeakEqualEps(const int value)
2348{
2349 return value != 0;
2350}
2351
2352template <>
2353constexpr inline bool NumericT<unsigned int>::isNotWeakEqualEps(const unsigned int value)
2354{
2355 return value != 0u;
2356}
2357
2358template <>
2359constexpr inline bool NumericT<long>::isNotWeakEqualEps(const long value)
2360{
2361 return value != 0l;
2362}
2363
2364template <>
2365constexpr inline bool NumericT<unsigned long>::isNotWeakEqualEps(const unsigned long value)
2366{
2367 return value != 0ul;
2368}
2369
2370template <>
2371constexpr inline bool NumericT<long long>::isNotWeakEqualEps(const long long value)
2372{
2373 return value != 0ll;
2374}
2375
2376template <>
2377constexpr inline bool NumericT<unsigned long long>::isNotWeakEqualEps(const unsigned long long value)
2378{
2379 return value != 0ull;
2380}
2381
2382template <typename T>
2383constexpr inline bool NumericT<T>::isNotWeakEqualEps(const std::complex<T>& value)
2384{
2385 return value.real() > weakEps() || value.real() < -weakEps() || value.imag() > weakEps() || value.imag() < -weakEps();
2386}
2387
2388template <typename T>
2389inline bool NumericT<T>::isEqual(const T first, const T second)
2390{
2391 return fabs(first - second) <= eps();
2392}
2393
2394template <>
2395inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second)
2396{
2397 return first == second;
2398}
2399
2400template <>
2401inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second)
2402{
2403 return first == second;
2404}
2405
2406template <>
2407inline bool NumericT<short>::isEqual(const short first, const short second)
2408{
2409 return first == second;
2410}
2411
2412template <>
2413inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second)
2414{
2415 return first == second;
2416}
2417
2418template <>
2419inline bool NumericT<int>::isEqual(const int first, const int second)
2420{
2421 return first == second;
2422}
2423
2424template <>
2425inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second)
2426{
2427 return first == second;
2428}
2429
2430template <>
2431inline bool NumericT<long>::isEqual(const long first, const long second)
2432{
2433 return first == second;
2434}
2435
2436template <>
2437inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second)
2438{
2439 return first == second;
2440}
2441
2442template <>
2443inline bool NumericT<long long>::isEqual(const long long first, const long long second)
2444{
2445 return first == second;
2446}
2447
2448template <>
2449inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second)
2450{
2451 return first == second;
2452}
2453
2454template <typename T>
2455inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second)
2456{
2457 return isEqual(first.real(), second.real()) && isEqual(first.imag(), second.imag());
2458}
2459
2460template <typename T>
2461inline bool NumericT<T>::isEqual(const T first, const T second, const T epsilon)
2462{
2463 ocean_assert(epsilon >= T(0));
2464 return NumericT<T>::abs(first - second) <= epsilon;
2465}
2466
2467template <>
2468inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second, const signed char epsilon)
2469{
2470 ocean_assert(epsilon >= (signed char)(0));
2471 return std::abs(first - second) <= epsilon;
2472}
2473
2474template <>
2475inline bool NumericT<short>::isEqual(const short first, const short second, const short epsilon)
2476{
2477 ocean_assert(epsilon >= short(0));
2478 return std::abs(first - second) <= epsilon;
2479}
2480
2481template <>
2482inline bool NumericT<int>::isEqual(const int first, const int second, const int epsilon)
2483{
2484 ocean_assert(epsilon >= 0);
2485 return std::abs(first - second) <= epsilon;
2486}
2487
2488template <>
2489inline bool NumericT<long>::isEqual(const long first, const long second, const long epsilon)
2490{
2491 ocean_assert(epsilon >= long(0));
2492 return std::abs(first - second) <= epsilon;
2493}
2494
2495template <>
2496inline bool NumericT<long long>::isEqual(const long long first, const long long second, const long long epsilon)
2497{
2498 ocean_assert(epsilon >= 0ll);
2499 return std::abs(first - second) <= epsilon;
2500}
2501
2502template <>
2503inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2504{
2505 if (first > second)
2506 {
2507 return first - second <= epsilon;
2508 }
2509 else
2510 {
2511 return second - first <= epsilon;
2512 }
2513}
2514
2515template <>
2516inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2517{
2518 if (first > second)
2519 {
2520 return first - second <= epsilon;
2521 }
2522 else
2523 {
2524 return second - first <= epsilon;
2525 }
2526}
2527
2528template <>
2529inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2530{
2531 if (first > second)
2532 {
2533 return first - second <= epsilon;
2534 }
2535 else
2536 {
2537 return second - first <= epsilon;
2538 }
2539}
2540
2541template <>
2542inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2543{
2544 if (first > second)
2545 {
2546 return first - second <= epsilon;
2547 }
2548 else
2549 {
2550 return second - first <= epsilon;
2551 }
2552}
2553
2554template <>
2555inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2556{
2557 if (first > second)
2558 {
2559 return first - second <= epsilon;
2560 }
2561 else
2562 {
2563 return second - first <= epsilon;
2564 }
2565}
2566
2567template <typename T>
2568inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2569{
2570 ocean_assert(epsilon >= T(0));
2571 return isEqual(first.real(), second.real(), epsilon) && isEqual(first.imag(), second.imag(), epsilon);
2572}
2573
2574template <typename T>
2575inline bool NumericT<T>::isWeakEqual(const T first, const T second)
2576{
2577 return NumericT<T>::abs(first - second) <= weakEps();
2578}
2579
2580template <>
2581inline bool NumericT<int>::isWeakEqual(const int first, const int second)
2582{
2583 return first == second;
2584}
2585
2586template <typename T>
2587inline bool NumericT<T>::isWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2588{
2589 return isWeakEqual(first.real(), second.real()) && isWeakEqual(first.imag(), second.imag());
2590}
2591
2592template <typename T>
2593template <int tMagnitude>
2594inline bool NumericT<T>::isEqual(const T first, const T second, const T referenceEpsilon)
2595{
2596 static_assert(tMagnitude >= -20 && tMagnitude <= 20, "Invalid reference magnitude");
2597 ocean_assert(referenceEpsilon >= T(0));
2598
2599 const T maximalAbsValue = max(NumericT<T>::abs(first), NumericT<T>::abs(second));
2600
2601 // we ensure that the max value is not 0 (due to the following log)
2602 if (isEqualEps(maximalAbsValue))
2603 {
2604 return NumericT<T>::isEqual(first, second, referenceEpsilon);
2605 }
2606
2607 const int offsetMagnitude = int(max(NumericT<float>::ceil(NumericT<float>::log10(float(maximalAbsValue))), float(tMagnitude))) - tMagnitude;
2608 ocean_assert(offsetMagnitude >= 0);
2609
2610 const T adjustedEpsilon = referenceEpsilon * NumericT<T>::pow(10, T(offsetMagnitude));
2611
2612 return isEqual(first, second, adjustedEpsilon);
2613}
2614
2615template <typename T>
2616inline bool NumericT<T>::isNotEqual(const T first, const T second)
2617{
2618 return fabs(first - second) > eps();
2619}
2620
2621template <>
2622inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second)
2623{
2624 return first != second;
2625}
2626
2627template <>
2628inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second)
2629{
2630 return first != second;
2631}
2632
2633template <>
2634inline bool NumericT<short>::isNotEqual(const short first, const short second)
2635{
2636 return first != second;
2637}
2638
2639template <>
2640inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second)
2641{
2642 return first != second;
2643}
2644
2645template <>
2646inline bool NumericT<int>::isNotEqual(const int first, const int second)
2647{
2648 return first != second;
2649}
2650
2651template <>
2652inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second)
2653{
2654 return first != second;
2655}
2656
2657template <>
2658inline bool NumericT<long>::isNotEqual(const long first, const long second)
2659{
2660 return first != second;
2661}
2662
2663template <>
2664inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second)
2665{
2666 return first != second;
2667}
2668
2669
2670template <>
2671inline bool NumericT<long long>::isNotEqual(const long long first, const long long second)
2672{
2673 return first != second;
2674}
2675
2676template <>
2677inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second)
2678{
2679 return first != second;
2680}
2681
2682template <typename T>
2683inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second)
2684{
2685 return isNotEqual(first.real(), second.real()) || isNotEqual(first.imag(), second.imag());
2686}
2687
2688template <typename T>
2689inline bool NumericT<T>::isNotWeakEqual(const T first, const T second)
2690{
2691 return fabs(first - second) > weakEps();
2692}
2693
2694template <>
2695inline bool NumericT<signed char>::isNotWeakEqual(const signed char first, const signed char second)
2696{
2697 return first != second;
2698}
2699
2700template <>
2701inline bool NumericT<unsigned char>::isNotWeakEqual(const unsigned char first, const unsigned char second)
2702{
2703 return first != second;
2704}
2705
2706template <>
2707inline bool NumericT<short>::isNotWeakEqual(const short first, const short second)
2708{
2709 return first != second;
2710}
2711
2712template <>
2713inline bool NumericT<unsigned short>::isNotWeakEqual(const unsigned short first, const unsigned short second)
2714{
2715 return first != second;
2716}
2717
2718template <>
2719inline bool NumericT<int>::isNotWeakEqual(const int first, const int second)
2720{
2721 return first != second;
2722}
2723
2724template <>
2725inline bool NumericT<unsigned int>::isNotWeakEqual(const unsigned int first, const unsigned int second)
2726{
2727 return first != second;
2728}
2729
2730template <>
2731inline bool NumericT<long>::isNotWeakEqual(const long first, const long second)
2732{
2733 return first != second;
2734}
2735
2736template <>
2737inline bool NumericT<unsigned long>::isNotWeakEqual(const unsigned long first, const unsigned long second)
2738{
2739 return first != second;
2740}
2741
2742template <>
2743inline bool NumericT<long long>::isNotWeakEqual(const long long first, const long long second)
2744{
2745 return first != second;
2746}
2747
2748template <>
2749inline bool NumericT<unsigned long long>::isNotWeakEqual(const unsigned long long first, const unsigned long long second)
2750{
2751 return first != second;
2752}
2753
2754template <typename T>
2755inline bool NumericT<T>::isNotWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2756{
2757 return isNotWeakEqual(first.real(), second.real()) || isNotWeakEqual(first.imag(), second.imag());
2758}
2759
2760template <typename T>
2761inline bool NumericT<T>::isNotEqual(const T first, const T second, const T epsilon)
2762{
2763 ocean_assert(epsilon >= 0);
2764 return fabs(first - second) > epsilon;
2765}
2766
2767template <>
2768inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second, const signed char epsilon)
2769{
2770 ocean_assert(epsilon >= (signed char)(0));
2771 return std::abs(first - second) > epsilon;
2772}
2773
2774template <>
2775inline bool NumericT<short>::isNotEqual(const short first, const short second, const short epsilon)
2776{
2777 ocean_assert(epsilon >= short(0));
2778 return std::abs(first - second) > epsilon;
2779}
2780
2781template <>
2782inline bool NumericT<int>::isNotEqual(const int first, const int second, const int epsilon)
2783{
2784 ocean_assert(epsilon >= 0);
2785 return std::abs(first - second) > epsilon;
2786}
2787
2788template <>
2789inline bool NumericT<long>::isNotEqual(const long first, const long second, const long epsilon)
2790{
2791 ocean_assert(epsilon >= long(0));
2792 return std::abs(first - second) > epsilon;
2793}
2794
2795template <>
2796inline bool NumericT<long long>::isNotEqual(const long long first, const long long second, const long long epsilon)
2797{
2798 ocean_assert(epsilon >= 0ll);
2799 return std::abs(first - second) > epsilon;
2800}
2801
2802template <>
2803inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2804{
2805 if (first > second)
2806 {
2807 return first - second > epsilon;
2808 }
2809 else
2810 {
2811 return second - first > epsilon;
2812 }
2813}
2814
2815template <>
2816inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2817{
2818 if (first > second)
2819 {
2820 return first - second > epsilon;
2821 }
2822 else
2823 {
2824 return second - first > epsilon;
2825 }
2826}
2827
2828template <>
2829inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2830{
2831 if (first > second)
2832 {
2833 return first - second > epsilon;
2834 }
2835 else
2836 {
2837 return second - first > epsilon;
2838 }
2839}
2840
2841template <>
2842inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2843{
2844 if (first > second)
2845 {
2846 return first - second > epsilon;
2847 }
2848 else
2849 {
2850 return second - first > epsilon;
2851 }
2852}
2853
2854template <>
2855inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2856{
2857 if (first > second)
2858 {
2859 return first - second > epsilon;
2860 }
2861 else
2862 {
2863 return second - first > epsilon;
2864 }
2865}
2866
2867template <typename T>
2868inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2869{
2870 ocean_assert(epsilon >= 0);
2871 return isNotEqual(first.real(), second.real(), epsilon) || isNotEqual(first.imag(), second.imag(), epsilon);
2872}
2873
2874template <typename T>
2875constexpr bool NumericT<T>::isInsideRange(const T lower, const T value, const T upper, const T epsilon)
2876{
2877 ocean_assert(lower <= upper);
2878 ocean_assert(epsilon >= T(0));
2879
2880 return value >= lower - epsilon && value <= upper + epsilon;
2881}
2882
2883template <typename T>
2884constexpr bool NumericT<T>::isInsideWeakRange(const T lower, const T value, const T upper)
2885{
2886 return isInsideRange(lower, value, upper, weakEps());
2887}
2888
2889template <typename T>
2890inline T NumericT<T>::asin(const T value)
2891{
2892 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2893
2894 return ::asin(max(T(-1), min(T(1), value)));
2895}
2896
2897/**
2898 * Specialization of NumericT::asin().
2899 * @see NumericT::asin().
2900 */
2901template <>
2902inline float NumericT<float>::asin(const float value)
2903{
2904 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2905
2906 return asinf(max(-1.0f, min(1.0f, value)));
2907}
2908
2909template <typename T>
2910inline T NumericT<T>::acos(const T value)
2911{
2912 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2913
2914 return ::acos(max(T(-1), min(T(1), value)));
2915}
2916
2917/**
2918 * Specialization of NumericT::acos().
2919 * @see NumericT::acos().
2920 */
2921template <>
2922inline float NumericT<float>::acos(const float value)
2923{
2924 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2925
2926 return acosf(max(-1.0f, min(1.0f, value)));
2927}
2928
2929template <typename T>
2930constexpr bool NumericT<T>::isBelow(const T value, const T upper, const T epsilon)
2931{
2932 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2933
2934 ocean_assert(epsilon >= T(0));
2935
2936 return value <= upper + epsilon;
2937}
2938
2939template <typename T>
2940constexpr bool NumericT<T>::isAbove(const T value, const T lower, const T epsilon)
2941{
2942 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2943
2944 ocean_assert(epsilon >= T(0));
2945
2946 return lower - epsilon <= value;
2947}
2948
2949template <typename T>
2950constexpr inline T NumericT<T>::nan()
2951{
2952 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
2953
2954 if constexpr (std::is_same<T, float>::value)
2955 {
2956 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
2957
2958 constexpr uint32_t integerValue = 0x7FC00000u;
2959
2960 float floatValue = 0.0f;
2961 memcpy(&floatValue, &integerValue, sizeof(integerValue));
2962
2963 return T(floatValue);
2964 }
2965 else
2966 {
2967 static_assert(std::is_same<T, double>::value, "Invalid data type!");
2968 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
2969
2970 constexpr uint64_t integerValue = 0x7FF8000000000000ull;
2971
2972 double doubleValue = 0.0;
2973 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
2974
2975 return T(doubleValue);
2976 }
2977}
2978
2979template <>
2980inline bool NumericT<float>::isNan(const float value)
2981{
2982 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
2983 // thus implementing a custom check
2984
2985 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
2986
2987 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
2988
2989 uint32_t tmpValue;
2990 memcpy(&tmpValue, &value, sizeof(tmpValue));
2991
2992 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
2993 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
2994
2995 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
2996 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0u;
2997
2998 return allExponentBitsAreOne && mantissaIsNotZero;
2999}
3000
3001template <>
3002inline bool NumericT<double>::isNan(const double value)
3003{
3004 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3005 // thus implementing a custom check
3006
3007 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3008
3009 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3010
3011 uint64_t tmpValue;
3012 memcpy(&tmpValue, &value, sizeof(tmpValue));
3013
3014 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3015 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3016
3017 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3018 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0ull;
3019
3020 return allExponentBitsAreOne && mantissaIsNotZero;
3021}
3022
3023template <typename T>
3024inline bool NumericT<T>::isNan(const T /*value*/)
3025{
3026 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3027 // thus implementing a custom check
3028
3029 ocean_assert(std::is_floating_point<T>::value == false);
3030 return false;
3031}
3032
3033template <typename T>
3034inline bool NumericT<T>::isNan(const std::complex<T>& value)
3035{
3036 return NumericT<T>::isNan(value.real()) || NumericT<T>::isNan(value.imag());
3037}
3038
3039template <typename T>
3040constexpr inline T NumericT<T>::inf()
3041{
3042 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
3043
3044 if constexpr (std::is_same<T, float>::value)
3045 {
3046 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
3047
3048 constexpr uint32_t integerValue = 0x7F800000u;
3049
3050 float floatValue = 0.0f;
3051 memcpy(&floatValue, &integerValue, sizeof(integerValue));
3052
3053 return T(floatValue);
3054 }
3055 else
3056 {
3057 static_assert(std::is_same<T, double>::value, "Invalid data type!");
3058 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
3059
3060 constexpr uint64_t integerValue = 0x7FF0000000000000ull;
3061
3062 double doubleValue = 0.0;
3063 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
3064
3065 return T(doubleValue);
3066 }
3067}
3068
3069template <>
3070inline bool NumericT<float>::isInf(const float value)
3071{
3072 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3073 // thus implementing a custom check
3074
3075 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
3076
3077 // IEEE 754: all exponents are encoded as 1, and the mantissa is zero
3078
3079 uint32_t tmpValue;
3080 memcpy(&tmpValue, &value, sizeof(tmpValue));
3081
3082 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
3083 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
3084
3085 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3086 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0u;
3087
3088 return allExponentBitsAreOne && allMantissaBitsAreZero;
3089}
3090
3091template <>
3092inline bool NumericT<double>::isInf(const double value)
3093{
3094 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3095 // thus implementing a custom check
3096
3097 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3098
3099 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3100
3101 uint64_t tmpValue;
3102 memcpy(&tmpValue, &value, sizeof(tmpValue));
3103
3104 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3105 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3106
3107 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3108 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0ull;
3109
3110 return allExponentBitsAreOne && allMantissaBitsAreZero;
3111}
3112
3113template <typename T>
3114inline bool NumericT<T>::isInf(const T /*value*/)
3115{
3116 // with compiler optimizations, `std::isinf()` will not work anymore (the compiler simply skips the check),
3117 // thus implementing a custom check
3118
3119 ocean_assert(std::is_floating_point<T>::value == false);
3120 return false;
3121}
3122
3123template <>
3124inline bool NumericT<long double>::isInf(const long double value)
3125{
3126 return std::isinf(value);
3127}
3128
3129template <typename T>
3130inline bool NumericT<T>::isInf(const std::complex<T>& value)
3131{
3132 return NumericT<T>::isInf(value.real()) || NumericT<T>::isInf(value.imag());
3133}
3134
3135template <typename T>
3136template <typename TValue>
3137inline bool NumericT<T>::isInsideValueRange(const TValue& value)
3138{
3139 if constexpr (std::is_same<T, TValue>::value)
3140 {
3141 // e.g., [int8_t, int8_t], [uint8_t, uint8_t], [float, float], ...
3142
3143 return true;
3144 }
3145
3146 if constexpr (std::is_floating_point<T>::value && std::is_floating_point<TValue>::value)
3147 {
3148 // either [float, double], or [double, float]
3149
3150 // float/double values fit in each other (however, may be casted to inf)
3151
3152 return true;
3153 }
3154
3155 if constexpr (std::is_integral<T>::value && std::is_integral<TValue>::value)
3156 {
3157 // e.g., int8_t, uint8_t, int16_t, ...
3158
3159 if constexpr (std::is_signed<T>::value == std::is_signed<TValue>::value)
3160 {
3161 // e.g., [int8_t, int16_t], [int16_t, int8_t], [int32_t, int64_t], ...
3162
3163 if constexpr (sizeof(TValue) <= sizeof(T))
3164 {
3165 // e.g., [int16_t, int8_t], [uint64_t, uint8_t], ...
3166
3167 return true;
3168 }
3169 else
3170 {
3171 ocean_assert(sizeof(T) < sizeof(TValue));
3172
3173 // e.g., [int8_t, int16_t], [uint8_t, uint64_t], ...
3174
3175 return TValue(NumericT<T>::minValue()) <= value && value <= TValue(NumericT<T>::maxValue());
3176 }
3177 }
3178
3179 if constexpr (std::is_signed<T>::value)
3180 {
3181 ocean_assert(!std::is_signed<TValue>::value);
3182
3183 // e.g., [int8_t, uint8_t], [int32_t, uint8_t], [int64_t, uint16_t], [int8_t, uint64_t], ...
3184
3185 if constexpr (sizeof(TValue) < sizeof(T))
3186 {
3187 // e.g., [int16_t, uint8_t], [int64_t, uint16_t], ...
3188
3189 return true;
3190 }
3191
3192 // e.g., [int8_t, uint8_t], [int8_t, uint32_t], ...
3193
3194 return value <= TValue(NumericT<T>::maxValue());
3195 }
3196
3197 if constexpr (std::is_signed<TValue>::value)
3198 {
3199 ocean_assert(!std::is_signed<T>::value);
3200
3201 // e.g., [uint8_t, int8_t], [uint32_t, int8_t], [uint64_t, int16_t], [uint8_t, int64_t], ...
3202
3203 if (value < TValue(0))
3204 {
3205 return false;
3206 }
3207
3208 if constexpr (sizeof(TValue) < sizeof(T))
3209 {
3210 // e.g., [uint16_t, int8_t], [uint_64_t, int16_t], ...
3211
3212 return true;
3213 }
3214 else if constexpr (sizeof(TValue) == sizeof(T))
3215 {
3216 // e.g., [uint8_t, int8_t], [uint32_t, int32_t], [uint64_t, int64_t], ...
3217
3218 ocean_assert(value >= TValue(0));
3219
3220 return true;
3221 }
3222
3223 // e.g., [uint8_t, int16_t], [uint32_t, int64_t], ...
3224
3225 ocean_assert(value >= TValue(0));
3226
3227 return value <= TValue(NumericT<T>::maxValue());
3228 }
3229 }
3230
3231 return false;
3232}
3233
3234template <typename T>
3235constexpr inline T NumericT<T>::deg2rad(const T deg)
3236{
3237 return deg * T(0.017453292519943295769236907684886);
3238}
3239
3240template <typename T>
3241constexpr inline T NumericT<T>::rad2deg(const T rad)
3242{
3243 return rad * T(57.295779513082320876798154814105);
3244}
3245
3246template <typename T>
3247constexpr inline T NumericT<T>::maxValue()
3248{
3249 return std::numeric_limits<T>::max();
3250}
3251
3252template <typename T>
3253constexpr inline T NumericT<T>::minValue()
3254{
3255 return std::numeric_limits<T>::lowest();
3256}
3257
3258template <typename T>
3259constexpr inline T NumericT<T>::sign(const T& value)
3260{
3261 static_assert(std::numeric_limits<T>::is_signed, "T must be a signed data type!");
3262
3263 return T((T(0) < value) - (value < T(0)));
3264}
3265
3266template <typename T>
3267constexpr inline T NumericT<T>::copySign(const T signReceiver, const T signProvider)
3268{
3269 if (signProvider >= 0)
3270 {
3271 return abs(signReceiver);
3272 }
3273
3274 return -abs(signReceiver);
3275}
3276
3277#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3278
3279/**
3280 * Specialization of NumericT::copySign().
3281 * @see NumericT::copySign().
3282 */
3283template <>
3284constexpr inline double NumericT<double>::copySign(const double first, const double second)
3285{
3286 const uint64_t value = ((*(uint64_t*)&first) & 0x7FFFFFFFFFFFFFFFull)
3287 | ((*(uint64_t*)&second) & 0x8000000000000000ull);
3288
3289#ifdef OCEAN_DEBUG
3290
3291 ocean_assert(sizeof(uint64_t) == sizeof(double));
3292
3293 const double result = *(double*)(&value);
3294
3295 double testValue = 0;
3296
3297 if (second >= 0.0)
3298 {
3299 testValue = NumericT<double>::abs(first);
3300 }
3301 else
3302 {
3303 testValue = -NumericT<double>::abs(first);
3304 }
3305
3306 ocean_assert(result == testValue || second == 0.0);
3307
3308#endif
3309
3310 return *(double*)&value;
3311}
3312
3313/**
3314 * Specialization of NumericT::copySign().
3315 * @see NumericT::copySign().
3316 */
3317template <>
3318constexpr inline float NumericT<float>::copySign(const float first, const float second)
3319{
3320 const uint32_t value = ((*(uint32_t*)&first) & 0x7FFFFFFFu) | ((*(uint32_t*)&second) & 0x80000000u);
3321
3322#ifdef OCEAN_DEBUG
3323
3324 ocean_assert(sizeof(uint32_t) == sizeof(float));
3325
3326 const float result = *(float*)(&value);
3327
3328 float testValue = 0;
3329
3330 if (second >= 0.0f)
3331 {
3332 testValue = NumericT<float>::abs(first);
3333 }
3334 else
3335 {
3336 testValue = -NumericT<float>::abs(first);
3337 }
3338
3339 ocean_assert(result == testValue || second == 0.0);
3340
3341#endif
3342
3343 return *(float*)&value;
3344}
3345
3346#endif // #if 0
3347
3348template <typename T>
3349constexpr inline T NumericT<T>::invertSign(const T signReceiver, const T signProvider)
3350{
3351 if (signProvider < 0)
3352 {
3353 return abs(signReceiver);
3354 }
3355
3356 return -abs(signReceiver);
3357}
3358
3359#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3360
3361/**
3362 * Specialization of NumericT::invertSign().
3363 * @see NumericT::invertedSign().
3364 */
3365template <>
3366constexpr inline double NumericT<double>::invertSign(const double first, const double second)
3367{
3368 const uint64_t value = ((*(uint64_t*)&first) & 0x7FFFFFFFFFFFFFFFull)
3369 | ((~*(uint64_t*)&second) & 0x8000000000000000ull);
3370
3371#ifdef OCEAN_DEBUG
3372
3373 ocean_assert(sizeof(uint64_t) == sizeof(double));
3374
3375 const double result = *(double*)&value;
3376
3377 double testValue = 0;
3378
3379 if (second < 0)
3380 {
3381 testValue = NumericT<double>::abs(first);
3382 }
3383 else
3384 {
3385 testValue = -NumericT<double>::abs(first);
3386 }
3387
3388 ocean_assert(result == testValue);
3389
3390#endif
3391
3392
3393 return *(double*)&value;
3394}
3395
3396/**
3397 * Specialization of NumericT::invertSign().
3398 * @see NumericT::invertSign().
3399 */
3400template <>
3401constexpr inline float NumericT<float>::invertSign(const float first, const float second)
3402{
3403 const uint32_t value = ((*(uint32_t*)&first) & 0x7FFFFFFFu) | ((~*(uint32_t*)&second) & 0x80000000u);
3404
3405#ifdef OCEAN_DEBUG
3406
3407 ocean_assert(sizeof(uint32_t) == sizeof(float));
3408
3409 const float result = *(float*)&value;
3410
3411 double testValue = 0;
3412
3413 if (second < 0)
3414 {
3415 testValue = NumericT<float>::abs(first);
3416 }
3417 else
3418 {
3419 testValue = -NumericT<float>::abs(first);
3420 }
3421
3422 ocean_assert(result == testValue);
3423
3424#endif
3425
3426 return *(float*)&value;
3427}
3428
3429#endif // #if 0
3430
3431template <typename T>
3432T NumericT<T>::pythagoras(const T a, const T b)
3433{
3434 const T absA = NumericT<T>::abs(a);
3435 const T absB = NumericT<T>::abs(b);
3436
3437 if (absA > absB)
3438 {
3439 const T factor = absB / absA;
3440 return absA * sqrt(1 + factor * factor);
3441 }
3442 else if (absB != 0)
3443 {
3444 const T factor = absA / absB;
3445 return absB * sqrt(1 + factor * factor);
3446 }
3447
3448 return 0;
3449}
3450
3451template <typename T>
3452inline T NumericT<T>::gaussianDistribution(const T x, const T sigma)
3453{
3454 ocean_assert(sigma > eps());
3455
3456 const T inverseSigma = T(1) / sigma;
3457
3458 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3459}
3460
3461template <typename T>
3462inline T NumericT<T>::gaussianDistribution(const T x, const T x0, const T sigma)
3463{
3464 ocean_assert(sigma > eps());
3465
3466 const T inverseSigma = T(1) / sigma;
3467 const T x_x0 = x - x0;
3468
3469 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3470}
3471
3472template <typename T>
3473inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T sigma)
3474{
3475 ocean_assert(sigma > eps());
3476
3477 const T inverseSigma = T(1) / sigma;
3478
3479 return NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3480}
3481
3482template <typename T>
3483inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T x0, const T sigma)
3484{
3485 ocean_assert(sigma > eps());
3486
3487 const T inverseSigma = T(1) / sigma;
3488 const T x_x0 = x - x0;
3489
3490 return NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3491}
3492
3493template <typename T>
3494inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3495{
3496 ocean_assert(sigmaX > eps() && sigmaY > eps());
3497
3498 const T inverseSigmaX = T(1) / sigmaX;
3499 const T inverseSigmaY = T(1) / sigmaY;
3500
3501 return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3502}
3503
3504template <typename T>
3505inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3506{
3507 ocean_assert(sigmaX > eps() && sigmaY > eps());
3508
3509 const T inverseSigmaX = T(1) / sigmaX;
3510 const T inverseSigmaY = T(1) / sigmaY;
3511
3512 const T x_x0 = x - x0;
3513 const T y_y0 = y - y0;
3514
3515 return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3516}
3517
3518template <typename T>
3519inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3520{
3521 ocean_assert(sigmaX > eps() && sigmaY > eps());
3522
3523 const T inverseSigmaX = T(1) / sigmaX;
3524 const T inverseSigmaY = T(1) / sigmaY;
3525
3526 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3527}
3528
3529template <typename T>
3530inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3531{
3532 ocean_assert(sigmaX > eps() && sigmaY > eps());
3533
3534 const T inverseSigmaX = T(1) / sigmaX;
3535 const T inverseSigmaY = T(1) / sigmaY;
3536
3537 const T x_x0 = x - x0;
3538 const T y_y0 = y - y0;
3539
3540 return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3541}
3542
3543template <typename T>
3544inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3545{
3546 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3547
3548 const T inverseSigmaX = T(1) / sigmaX;
3549 const T inverseSigmaY = T(1) / sigmaY;
3550 const T inverseSigmaZ = T(1) / sigmaZ;
3551
3552 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3553 * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3554}
3555
3556template <typename T>
3557inline 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)
3558{
3559 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3560
3561 const T inverseSigmaX = T(1) / sigmaX;
3562 const T inverseSigmaY = T(1) / sigmaY;
3563 const T inverseSigmaZ = T(1) / sigmaZ;
3564
3565 const T x_x0 = x - x0;
3566 const T y_y0 = y - y0;
3567 const T z_z0 = z - z0;
3568
3569 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3570 * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3571}
3572
3573template <typename T>
3574inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3575{
3576 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3577
3578 const T inverseSigmaX = T(1) / sigmaX;
3579 const T inverseSigmaY = T(1) / sigmaY;
3580 const T inverseSigmaZ = T(1) / sigmaZ;
3581
3582 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3583}
3584
3585template <typename T>
3586inline 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)
3587{
3588 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3589
3590 const T inverseSigmaX = T(1) / sigmaX;
3591 const T inverseSigmaY = T(1) / sigmaY;
3592 const T inverseSigmaZ = T(1) / sigmaZ;
3593
3594 const T x_x0 = x - x0;
3595 const T y_y0 = y - y0;
3596 const T z_z0 = z - z0;
3597
3598 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));
3599}
3600
3601}
3602
3603#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:3235
static constexpr bool isNotWeakEqualEps(const T value)
Returns whether a value is not smaller than or equal to a weak epsilon.
Definition Numeric.h:2315
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3253
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:3259
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:2875
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:3114
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:3024
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:2940
static bool isWeakEqual(const T first, const T second)
Returns whether two values a equal up to a weak epsilon.
Definition Numeric.h:2575
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:3473
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition Numeric.h:2067
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:2165
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:3432
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:2389
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:2930
static T gaussianDistribution(const T x, const T sigma)
Returns a value of the univariate Gaussian distribution centered around the origin.
Definition Numeric.h:3452
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:3494
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:2079
static constexpr T nan()
Returns a value which is not a number (nan).
Definition Numeric.h:2950
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:2029
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:3574
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:1991
static constexpr int64_t round64(const T value)
Returns the rounded 64 bit integer value of a given value.
Definition Numeric.h:2073
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:2884
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:3519
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2090
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition Numeric.h:3267
static constexpr T rad2deg(const T rad)
Converts rad to deg.
Definition Numeric.h:3241
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:3544
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:3137
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2910
static constexpr T invertSign(const T signReceiver, const T signProvider)
Copies the inverted sign of a given value to another one.
Definition Numeric.h:3349
static constexpr T inf()
Returns a value which is positive infinity.
Definition Numeric.h:3040
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2240
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:2616
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:3247
static T asin(const T value)
Returns the arcsine of a given value.
Definition Numeric.h:2890
static bool isNotWeakEqual(const T first, const T second)
Returns whether two values are not equal up to a weak epsilon.
Definition Numeric.h:2689
static constexpr T binomialCoefficient(const T &n, const T &k)
Returns the binomial coefficient for two binomial parameters.
Definition Numeric.h:1960
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:1053
NumericT< Scalar > Numeric
Definition of a Numeric class.
Definition Numeric.h:33
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