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((long long)(value)) == value);
1892
1893 if (value <= 1)
1894 {
1895 return T(1);
1896 }
1897
1898 T result = T(2);
1899
1900 for (unsigned int n = 3u; n <= (unsigned int)value; ++n)
1901 {
1902 ocean_assert(std::numeric_limits<T>::max() / T(n) >= result);
1903 result *= T(n);
1904 }
1905
1906 return result;
1907}
1908
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
1952 ocean_assert(false && "Invalid factorial value!");
1953 return 1u;
1954}
1955
1956template <typename T>
1957constexpr inline T NumericT<T>::binomialCoefficient(const T& n, const T& k)
1958{
1959 ocean_assert(n >= 0 && k >= 0);
1960 ocean_assert(T((long long)(n)) == n);
1961 ocean_assert(T((long long)(k)) == k);
1962
1963 if (n <= T(1) || k == T(0) || n == k)
1964 {
1965 return T(1);
1966 }
1967
1968 ocean_assert(k < n);
1969
1970 T result = n - k + T(1);
1971
1972 for (unsigned int i = (unsigned int)(n - k) + 2u; i <= (unsigned int)n; ++i)
1973 {
1974 ocean_assert(std::numeric_limits<T>::max() / T(i) >= result);
1975 result *= T(i);
1976 }
1977
1978 for (unsigned int i = 2u; i <= (unsigned int)k; ++i)
1979 {
1980 ocean_assert((result / T(i)) * T(i) == result);
1981 result /= T(i);
1982 }
1983
1984 return result;
1985}
1986
1987template <typename T>
1988inline T NumericT<T>::ceil(const T value)
1989{
1990 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
1991
1992 return value;
1993}
1994
1995/**
1996 * Specialization of NumericT::ceil().
1997 * @see NumericT::ceil().
1998 */
1999template <>
2000inline float NumericT<float>::ceil(const float value)
2001{
2002 return ::ceilf(value);
2003}
2004
2005/**
2006 * Specialization of NumericT::ceil().
2007 * @see NumericT::ceil().
2008 */
2009template <>
2010inline double NumericT<double>::ceil(const double value)
2011{
2012 return ::ceil(value);
2013}
2014
2015/**
2016 * Specialization of NumericT::ceil().
2017 * @see NumericT::ceil().
2018 */
2019template <>
2020inline long double NumericT<long double>::ceil(const long double value)
2021{
2022 return ::ceill(value);
2023}
2024
2025template <typename T>
2026inline T NumericT<T>::floor(const T value)
2027{
2028 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
2029
2030 return value;
2031}
2032
2033/**
2034 * Specialization of NumericT::floor().
2035 * @see NumericT::floor().
2036 */
2037template <>
2038inline float NumericT<float>::floor(const float value)
2039{
2040 return ::floorf(value);
2041}
2042
2043/**
2044 * Specialization of NumericT::floor().
2045 * @see NumericT::floor().
2046 */
2047template <>
2048inline double NumericT<double>::floor(const double value)
2049{
2050 return ::floor(value);
2051}
2052
2053/**
2054 * Specialization of NumericT::floor().
2055 * @see NumericT::floor().
2056 */
2057template <>
2058inline long double NumericT<long double>::floor(const long double value)
2059{
2060 return ::floorl(value);
2061}
2062
2063template <typename T>
2064constexpr inline int32_t NumericT<T>::round32(const T value)
2065{
2066 return int32_t(value + copySign(T(0.5), value));
2067}
2068
2069template <typename T>
2070constexpr inline int64_t NumericT<T>::round64(const T value)
2071{
2072 return int64_t(value + copySign(T(0.5), value));
2073}
2074
2075template <typename T>
2076constexpr inline T NumericT<T>::ratio(const T nominator, const T denominator, const T fallback)
2077{
2078 if (isEqualEps(denominator))
2079 {
2080 return fallback;
2081 }
2082
2083 return nominator / denominator;
2084}
2085
2086template <typename T>
2087constexpr inline bool NumericT<T>::isEqualEps(const T value)
2088{
2089 ocean_assert(isNan(value) == false);
2090 ocean_assert((fabs(value) <= eps()) == (-eps() <= value && value <= eps()));
2091
2092 return -eps() <= value && value <= eps();
2093}
2094
2095template <>
2096constexpr inline bool NumericT<signed char>::isEqualEps(const signed char value)
2097{
2098 return value == (signed char)(0);
2099}
2100
2101template <>
2102constexpr inline bool NumericT<unsigned char>::isEqualEps(const unsigned char value)
2103{
2104 return value == (unsigned char)(0);
2105}
2106
2107template <>
2108constexpr inline bool NumericT<short>::isEqualEps(const short value)
2109{
2110 return value == short(0);
2111}
2112
2113template <>
2114constexpr inline bool NumericT<unsigned short>::isEqualEps(const unsigned short value)
2115{
2116 return value == (unsigned short)(0);
2117}
2118
2119template <>
2120constexpr inline bool NumericT<int>::isEqualEps(const int value)
2121{
2122 return value == 0;
2123}
2124
2125template <>
2126constexpr inline bool NumericT<unsigned int>::isEqualEps(const unsigned int value)
2127{
2128 return value == 0u;
2129}
2130
2131template <>
2132constexpr inline bool NumericT<long>::isEqualEps(const long value)
2133{
2134 return value == 0l;
2135}
2136
2137template <>
2138constexpr inline bool NumericT<unsigned long>::isEqualEps(const unsigned long value)
2139{
2140 return value == 0ul;
2141}
2142
2143template <>
2144constexpr inline bool NumericT<long long>::isEqualEps(const long long value)
2145{
2146 return value == 0ll;
2147}
2148
2149template <>
2150constexpr inline bool NumericT<unsigned long long>::isEqualEps(const unsigned long long value)
2151{
2152 return value == 0ull;
2153}
2154
2155template <typename T>
2156constexpr inline bool NumericT<T>::isEqualEps(const std::complex<T>& value)
2157{
2158 return isEqualEps(value.real()) && isEqualEps(value.imag());
2159}
2160
2161template <typename T>
2162constexpr inline bool NumericT<T>::isWeakEqualEps(const T value)
2163{
2164 ocean_assert(isNan(value) == false);
2165 ocean_assert((fabs(value) <= weakEps()) == (-weakEps() <= value && value <= weakEps()));
2166
2167 return -weakEps() <= value && value <= weakEps();
2168}
2169
2170template <>
2171constexpr inline bool NumericT<signed char>::isWeakEqualEps(const signed char value)
2172{
2173 return value == (signed char)(0);
2174}
2175
2176template <>
2177constexpr inline bool NumericT<unsigned char>::isWeakEqualEps(const unsigned char value)
2178{
2179 return value == (unsigned char)(0);
2180}
2181
2182template <>
2183constexpr inline bool NumericT<short>::isWeakEqualEps(const short value)
2184{
2185 return value == short(0);
2186}
2187
2188template <>
2189constexpr inline bool NumericT<unsigned short>::isWeakEqualEps(const unsigned short value)
2190{
2191 return value == (unsigned short)(0);
2192}
2193
2194template <>
2195constexpr inline bool NumericT<int>::isWeakEqualEps(const int value)
2196{
2197 return value == 0;
2198}
2199
2200template <>
2201constexpr inline bool NumericT<unsigned int>::isWeakEqualEps(const unsigned int value)
2202{
2203 return value == 0u;
2204}
2205
2206template <>
2207constexpr inline bool NumericT<long>::isWeakEqualEps(const long value)
2208{
2209 return value == 0l;
2210}
2211
2212template <>
2213constexpr inline bool NumericT<unsigned long>::isWeakEqualEps(const unsigned long value)
2214{
2215 return value == 0ul;
2216}
2217
2218template <>
2219constexpr inline bool NumericT<long long>::isWeakEqualEps(const long long value)
2220{
2221 return value == 0ll;
2222}
2223
2224template <>
2225constexpr inline bool NumericT<unsigned long long>::isWeakEqualEps(const unsigned long long value)
2226{
2227 return value == 0ull;
2228}
2229
2230template <typename T>
2231constexpr inline bool NumericT<T>::isWeakEqualEps(const std::complex<T>& value)
2232{
2233 return isWeakEqualEps(value.real()) && isWeakEqualEps(value.imag());
2234}
2235
2236template <typename T>
2237constexpr inline bool NumericT<T>::isNotEqualEps(const T value)
2238{
2239 ocean_assert(isNan(value) == false);
2240 ocean_assert((fabs(value) > eps()) == (value > eps() || value < -eps()));
2241
2242 return value > eps() || value < -eps();
2243}
2244
2245template <>
2246constexpr inline bool NumericT<signed char>::isNotEqualEps(const signed char value)
2247{
2248 return value != (signed char)(0);
2249}
2250
2251template <>
2252constexpr inline bool NumericT<unsigned char>::isNotEqualEps(const unsigned char value)
2253{
2254 return value != (unsigned char)(0);
2255}
2256
2257template <>
2258constexpr inline bool NumericT<short>::isNotEqualEps(const short value)
2259{
2260 return value != short(0);
2261}
2262
2263template <>
2264constexpr inline bool NumericT<unsigned short>::isNotEqualEps(const unsigned short value)
2265{
2266 return value != (unsigned short)(0);
2267}
2268
2269template <>
2270constexpr inline bool NumericT<int>::isNotEqualEps(const int value)
2271{
2272 return value != 0;
2273}
2274
2275template <>
2276constexpr inline bool NumericT<unsigned int>::isNotEqualEps(const unsigned int value)
2277{
2278 return value != 0u;
2279}
2280
2281template <>
2282constexpr inline bool NumericT<long>::isNotEqualEps(const long value)
2283{
2284 return value != 0l;
2285}
2286
2287template <>
2288constexpr inline bool NumericT<unsigned long>::isNotEqualEps(const unsigned long value)
2289{
2290 return value != 0ul;
2291}
2292
2293template <>
2294constexpr inline bool NumericT<long long>::isNotEqualEps(const long long value)
2295{
2296 return value != 0ll;
2297}
2298
2299template <>
2300constexpr inline bool NumericT<unsigned long long>::isNotEqualEps(const unsigned long long value)
2301{
2302 return value != 0ull;
2303}
2304
2305template <typename T>
2306constexpr inline bool NumericT<T>::isNotEqualEps(const std::complex<T>& value)
2307{
2308 return value.real() > eps() || value.real() < -eps() || value.imag() > eps() || value.imag() < -eps();
2309}
2310
2311template <typename T>
2312constexpr inline bool NumericT<T>::isNotWeakEqualEps(const T value)
2313{
2314 ocean_assert((fabs(value) > weakEps()) == (value > weakEps() || value < -weakEps()));
2315
2316 return value > weakEps() || value < -weakEps();
2317}
2318
2319template <>
2320constexpr inline bool NumericT<signed char>::isNotWeakEqualEps(const signed char value)
2321{
2322 return value != (signed char)(0);
2323}
2324
2325template <>
2326constexpr inline bool NumericT<unsigned char>::isNotWeakEqualEps(const unsigned char value)
2327{
2328 return value != (unsigned char)(0);
2329}
2330
2331template <>
2332constexpr inline bool NumericT<short>::isNotWeakEqualEps(const short value)
2333{
2334 return value != short(0);
2335}
2336
2337template <>
2338constexpr inline bool NumericT<unsigned short>::isNotWeakEqualEps(const unsigned short value)
2339{
2340 return value != (unsigned short)(0);
2341}
2342
2343template <>
2344constexpr inline bool NumericT<int>::isNotWeakEqualEps(const int value)
2345{
2346 return value != 0;
2347}
2348
2349template <>
2350constexpr inline bool NumericT<unsigned int>::isNotWeakEqualEps(const unsigned int value)
2351{
2352 return value != 0u;
2353}
2354
2355template <>
2356constexpr inline bool NumericT<long>::isNotWeakEqualEps(const long value)
2357{
2358 return value != 0l;
2359}
2360
2361template <>
2362constexpr inline bool NumericT<unsigned long>::isNotWeakEqualEps(const unsigned long value)
2363{
2364 return value != 0ul;
2365}
2366
2367template <>
2368constexpr inline bool NumericT<long long>::isNotWeakEqualEps(const long long value)
2369{
2370 return value != 0ll;
2371}
2372
2373template <>
2374constexpr inline bool NumericT<unsigned long long>::isNotWeakEqualEps(const unsigned long long value)
2375{
2376 return value != 0ull;
2377}
2378
2379template <typename T>
2380constexpr inline bool NumericT<T>::isNotWeakEqualEps(const std::complex<T>& value)
2381{
2382 return value.real() > weakEps() || value.real() < -weakEps() || value.imag() > weakEps() || value.imag() < -weakEps();
2383}
2384
2385template <typename T>
2386inline bool NumericT<T>::isEqual(const T first, const T second)
2387{
2388 return fabs(first - second) <= eps();
2389}
2390
2391template <>
2392inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second)
2393{
2394 return first == second;
2395}
2396
2397template <>
2398inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second)
2399{
2400 return first == second;
2401}
2402
2403template <>
2404inline bool NumericT<short>::isEqual(const short first, const short second)
2405{
2406 return first == second;
2407}
2408
2409template <>
2410inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second)
2411{
2412 return first == second;
2413}
2414
2415template <>
2416inline bool NumericT<int>::isEqual(const int first, const int second)
2417{
2418 return first == second;
2419}
2420
2421template <>
2422inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second)
2423{
2424 return first == second;
2425}
2426
2427template <>
2428inline bool NumericT<long>::isEqual(const long first, const long second)
2429{
2430 return first == second;
2431}
2432
2433template <>
2434inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second)
2435{
2436 return first == second;
2437}
2438
2439template <>
2440inline bool NumericT<long long>::isEqual(const long long first, const long long second)
2441{
2442 return first == second;
2443}
2444
2445template <>
2446inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second)
2447{
2448 return first == second;
2449}
2450
2451template <typename T>
2452inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second)
2453{
2454 return isEqual(first.real(), second.real()) && isEqual(first.imag(), second.imag());
2455}
2456
2457template <typename T>
2458inline bool NumericT<T>::isEqual(const T first, const T second, const T epsilon)
2459{
2460 ocean_assert(epsilon >= T(0));
2461 return NumericT<T>::abs(first - second) <= epsilon;
2462}
2463
2464template <>
2465inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second, const signed char epsilon)
2466{
2467 ocean_assert(epsilon >= (signed char)(0));
2468 return std::abs(first - second) <= epsilon;
2469}
2470
2471template <>
2472inline bool NumericT<short>::isEqual(const short first, const short second, const short epsilon)
2473{
2474 ocean_assert(epsilon >= short(0));
2475 return std::abs(first - second) <= epsilon;
2476}
2477
2478template <>
2479inline bool NumericT<int>::isEqual(const int first, const int second, const int epsilon)
2480{
2481 ocean_assert(epsilon >= 0);
2482 return std::abs(first - second) <= epsilon;
2483}
2484
2485template <>
2486inline bool NumericT<long>::isEqual(const long first, const long second, const long epsilon)
2487{
2488 ocean_assert(epsilon >= long(0));
2489 return std::abs(first - second) <= epsilon;
2490}
2491
2492template <>
2493inline bool NumericT<long long>::isEqual(const long long first, const long long second, const long long epsilon)
2494{
2495 ocean_assert(epsilon >= 0ll);
2496 return std::abs(first - second) <= epsilon;
2497}
2498
2499template <>
2500inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2501{
2502 if (first > second)
2503 {
2504 return first - second <= epsilon;
2505 }
2506 else
2507 {
2508 return second - first <= epsilon;
2509 }
2510}
2511
2512template <>
2513inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2514{
2515 if (first > second)
2516 {
2517 return first - second <= epsilon;
2518 }
2519 else
2520 {
2521 return second - first <= epsilon;
2522 }
2523}
2524
2525template <>
2526inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2527{
2528 if (first > second)
2529 {
2530 return first - second <= epsilon;
2531 }
2532 else
2533 {
2534 return second - first <= epsilon;
2535 }
2536}
2537
2538template <>
2539inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2540{
2541 if (first > second)
2542 {
2543 return first - second <= epsilon;
2544 }
2545 else
2546 {
2547 return second - first <= epsilon;
2548 }
2549}
2550
2551template <>
2552inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2553{
2554 if (first > second)
2555 {
2556 return first - second <= epsilon;
2557 }
2558 else
2559 {
2560 return second - first <= epsilon;
2561 }
2562}
2563
2564template <typename T>
2565inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2566{
2567 ocean_assert(epsilon >= T(0));
2568 return isEqual(first.real(), second.real(), epsilon) && isEqual(first.imag(), second.imag(), epsilon);
2569}
2570
2571template <typename T>
2572inline bool NumericT<T>::isWeakEqual(const T first, const T second)
2573{
2574 return NumericT<T>::abs(first - second) <= weakEps();
2575}
2576
2577template <>
2578inline bool NumericT<int>::isWeakEqual(const int first, const int second)
2579{
2580 return first == second;
2581}
2582
2583template <typename T>
2584inline bool NumericT<T>::isWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2585{
2586 return isWeakEqual(first.real(), second.real()) && isWeakEqual(first.imag(), second.imag());
2587}
2588
2589template <typename T>
2590template <int tMagnitude>
2591inline bool NumericT<T>::isEqual(const T first, const T second, const T referenceEpsilon)
2592{
2593 static_assert(tMagnitude >= -20 && tMagnitude <= 20, "Invalid reference magnitude");
2594 ocean_assert(referenceEpsilon >= T(0));
2595
2596 const T maximalAbsValue = max(NumericT<T>::abs(first), NumericT<T>::abs(second));
2597
2598 // we ensure that the max value is not 0 (due to the following log)
2599 if (isEqualEps(maximalAbsValue))
2600 {
2601 return NumericT<T>::isEqual(first, second, referenceEpsilon);
2602 }
2603
2604 const int offsetMagnitude = int(max(NumericT<float>::ceil(NumericT<float>::log10(float(maximalAbsValue))), float(tMagnitude))) - tMagnitude;
2605 ocean_assert(offsetMagnitude >= 0);
2606
2607 const T adjustedEpsilon = referenceEpsilon * NumericT<T>::pow(10, T(offsetMagnitude));
2608
2609 return isEqual(first, second, adjustedEpsilon);
2610}
2611
2612template <typename T>
2613inline bool NumericT<T>::isNotEqual(const T first, const T second)
2614{
2615 return fabs(first - second) > eps();
2616}
2617
2618template <>
2619inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second)
2620{
2621 return first != second;
2622}
2623
2624template <>
2625inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second)
2626{
2627 return first != second;
2628}
2629
2630template <>
2631inline bool NumericT<short>::isNotEqual(const short first, const short second)
2632{
2633 return first != second;
2634}
2635
2636template <>
2637inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second)
2638{
2639 return first != second;
2640}
2641
2642template <>
2643inline bool NumericT<int>::isNotEqual(const int first, const int second)
2644{
2645 return first != second;
2646}
2647
2648template <>
2649inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second)
2650{
2651 return first != second;
2652}
2653
2654template <>
2655inline bool NumericT<long>::isNotEqual(const long first, const long second)
2656{
2657 return first != second;
2658}
2659
2660template <>
2661inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second)
2662{
2663 return first != second;
2664}
2665
2666
2667template <>
2668inline bool NumericT<long long>::isNotEqual(const long long first, const long long second)
2669{
2670 return first != second;
2671}
2672
2673template <>
2674inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second)
2675{
2676 return first != second;
2677}
2678
2679template <typename T>
2680inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second)
2681{
2682 return isNotEqual(first.real(), second.real()) || isNotEqual(first.imag(), second.imag());
2683}
2684
2685template <typename T>
2686inline bool NumericT<T>::isNotWeakEqual(const T first, const T second)
2687{
2688 return fabs(first - second) > weakEps();
2689}
2690
2691template <>
2692inline bool NumericT<signed char>::isNotWeakEqual(const signed char first, const signed char second)
2693{
2694 return first != second;
2695}
2696
2697template <>
2698inline bool NumericT<unsigned char>::isNotWeakEqual(const unsigned char first, const unsigned char second)
2699{
2700 return first != second;
2701}
2702
2703template <>
2704inline bool NumericT<short>::isNotWeakEqual(const short first, const short second)
2705{
2706 return first != second;
2707}
2708
2709template <>
2710inline bool NumericT<unsigned short>::isNotWeakEqual(const unsigned short first, const unsigned short second)
2711{
2712 return first != second;
2713}
2714
2715template <>
2716inline bool NumericT<int>::isNotWeakEqual(const int first, const int second)
2717{
2718 return first != second;
2719}
2720
2721template <>
2722inline bool NumericT<unsigned int>::isNotWeakEqual(const unsigned int first, const unsigned int second)
2723{
2724 return first != second;
2725}
2726
2727template <>
2728inline bool NumericT<long>::isNotWeakEqual(const long first, const long second)
2729{
2730 return first != second;
2731}
2732
2733template <>
2734inline bool NumericT<unsigned long>::isNotWeakEqual(const unsigned long first, const unsigned long second)
2735{
2736 return first != second;
2737}
2738
2739template <>
2740inline bool NumericT<long long>::isNotWeakEqual(const long long first, const long long second)
2741{
2742 return first != second;
2743}
2744
2745template <>
2746inline bool NumericT<unsigned long long>::isNotWeakEqual(const unsigned long long first, const unsigned long long second)
2747{
2748 return first != second;
2749}
2750
2751template <typename T>
2752inline bool NumericT<T>::isNotWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2753{
2754 return isNotWeakEqual(first.real(), second.real()) || isNotWeakEqual(first.imag(), second.imag());
2755}
2756
2757template <typename T>
2758inline bool NumericT<T>::isNotEqual(const T first, const T second, const T epsilon)
2759{
2760 ocean_assert(epsilon >= 0);
2761 return fabs(first - second) > epsilon;
2762}
2763
2764template <>
2765inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second, const signed char epsilon)
2766{
2767 ocean_assert(epsilon >= (signed char)(0));
2768 return std::abs(first - second) > epsilon;
2769}
2770
2771template <>
2772inline bool NumericT<short>::isNotEqual(const short first, const short second, const short epsilon)
2773{
2774 ocean_assert(epsilon >= short(0));
2775 return std::abs(first - second) > epsilon;
2776}
2777
2778template <>
2779inline bool NumericT<int>::isNotEqual(const int first, const int second, const int epsilon)
2780{
2781 ocean_assert(epsilon >= 0);
2782 return std::abs(first - second) > epsilon;
2783}
2784
2785template <>
2786inline bool NumericT<long>::isNotEqual(const long first, const long second, const long epsilon)
2787{
2788 ocean_assert(epsilon >= long(0));
2789 return std::abs(first - second) > epsilon;
2790}
2791
2792template <>
2793inline bool NumericT<long long>::isNotEqual(const long long first, const long long second, const long long epsilon)
2794{
2795 ocean_assert(epsilon >= 0ll);
2796 return std::abs(first - second) > epsilon;
2797}
2798
2799template <>
2800inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2801{
2802 if (first > second)
2803 {
2804 return first - second > epsilon;
2805 }
2806 else
2807 {
2808 return second - first > epsilon;
2809 }
2810}
2811
2812template <>
2813inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2814{
2815 if (first > second)
2816 {
2817 return first - second > epsilon;
2818 }
2819 else
2820 {
2821 return second - first > epsilon;
2822 }
2823}
2824
2825template <>
2826inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2827{
2828 if (first > second)
2829 {
2830 return first - second > epsilon;
2831 }
2832 else
2833 {
2834 return second - first > epsilon;
2835 }
2836}
2837
2838template <>
2839inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2840{
2841 if (first > second)
2842 {
2843 return first - second > epsilon;
2844 }
2845 else
2846 {
2847 return second - first > epsilon;
2848 }
2849}
2850
2851template <>
2852inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2853{
2854 if (first > second)
2855 {
2856 return first - second > epsilon;
2857 }
2858 else
2859 {
2860 return second - first > epsilon;
2861 }
2862}
2863
2864template <typename T>
2865inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2866{
2867 ocean_assert(epsilon >= 0);
2868 return isNotEqual(first.real(), second.real(), epsilon) || isNotEqual(first.imag(), second.imag(), epsilon);
2869}
2870
2871template <typename T>
2872constexpr bool NumericT<T>::isInsideRange(const T lower, const T value, const T upper, const T epsilon)
2873{
2874 ocean_assert(lower <= upper);
2875 ocean_assert(epsilon >= T(0));
2876
2877 return value >= lower - epsilon && value <= upper + epsilon;
2878}
2879
2880template <typename T>
2881constexpr bool NumericT<T>::isInsideWeakRange(const T lower, const T value, const T upper)
2882{
2883 return isInsideRange(lower, value, upper, weakEps());
2884}
2885
2886template <typename T>
2887inline T NumericT<T>::asin(const T value)
2888{
2889 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2890
2891 return ::asin(max(T(-1), min(T(1), value)));
2892}
2893
2894/**
2895 * Specialization of NumericT::asin().
2896 * @see NumericT::asin().
2897 */
2898template <>
2899inline float NumericT<float>::asin(const float value)
2900{
2901 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2902
2903 return asinf(max(-1.0f, min(1.0f, value)));
2904}
2905
2906template <typename T>
2907inline T NumericT<T>::acos(const T value)
2908{
2909 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2910
2911 return ::acos(max(T(-1), min(T(1), value)));
2912}
2913
2914/**
2915 * Specialization of NumericT::acos().
2916 * @see NumericT::acos().
2917 */
2918template <>
2919inline float NumericT<float>::acos(const float value)
2920{
2921 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2922
2923 return acosf(max(-1.0f, min(1.0f, value)));
2924}
2925
2926template <typename T>
2927constexpr bool NumericT<T>::isBelow(const T value, const T upper, const T epsilon)
2928{
2929 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2930
2931 ocean_assert(epsilon >= T(0));
2932
2933 return value <= upper + epsilon;
2934}
2935
2936template <typename T>
2937constexpr bool NumericT<T>::isAbove(const T value, const T lower, const T epsilon)
2938{
2939 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2940
2941 ocean_assert(epsilon >= T(0));
2942
2943 return lower - epsilon <= value;
2944}
2945
2946template <typename T>
2947constexpr inline T NumericT<T>::nan()
2948{
2949 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
2950
2951 if constexpr (std::is_same<T, float>::value)
2952 {
2953 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
2954
2955 constexpr uint32_t integerValue = 0x7FC00000u;
2956
2957 float floatValue = 0.0f;
2958 memcpy(&floatValue, &integerValue, sizeof(integerValue));
2959
2960 return T(floatValue);
2961 }
2962 else
2963 {
2964 static_assert(std::is_same<T, double>::value, "Invalid data type!");
2965 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
2966
2967 constexpr uint64_t integerValue = 0x7FF8000000000000ull;
2968
2969 double doubleValue = 0.0;
2970 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
2971
2972 return T(doubleValue);
2973 }
2974}
2975
2976template <>
2977inline bool NumericT<float>::isNan(const float value)
2978{
2979 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
2980 // thus implementing a custom check
2981
2982 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
2983
2984 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
2985
2986 uint32_t tmpValue;
2987 memcpy(&tmpValue, &value, sizeof(tmpValue));
2988
2989 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
2990 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
2991
2992 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
2993 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0u;
2994
2995 return allExponentBitsAreOne && mantissaIsNotZero;
2996}
2997
2998template <>
2999inline bool NumericT<double>::isNan(const double value)
3000{
3001 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3002 // thus implementing a custom check
3003
3004 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3005
3006 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3007
3008 uint64_t tmpValue;
3009 memcpy(&tmpValue, &value, sizeof(tmpValue));
3010
3011 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3012 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3013
3014 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3015 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0ull;
3016
3017 return allExponentBitsAreOne && mantissaIsNotZero;
3018}
3019
3020template <typename T>
3021inline bool NumericT<T>::isNan(const T /*value*/)
3022{
3023 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3024 // thus implementing a custom check
3025
3026 ocean_assert(std::is_floating_point<T>::value == false);
3027 return false;
3028}
3029
3030template <typename T>
3031inline bool NumericT<T>::isNan(const std::complex<T>& value)
3032{
3033 return NumericT<T>::isNan(value.real()) || NumericT<T>::isNan(value.imag());
3034}
3035
3036template <typename T>
3037constexpr inline T NumericT<T>::inf()
3038{
3039 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
3040
3041 if constexpr (std::is_same<T, float>::value)
3042 {
3043 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
3044
3045 constexpr uint32_t integerValue = 0x7F800000u;
3046
3047 float floatValue = 0.0f;
3048 memcpy(&floatValue, &integerValue, sizeof(integerValue));
3049
3050 return T(floatValue);
3051 }
3052 else
3053 {
3054 static_assert(std::is_same<T, double>::value, "Invalid data type!");
3055 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
3056
3057 constexpr uint64_t integerValue = 0x7FF0000000000000ull;
3058
3059 double doubleValue = 0.0;
3060 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
3061
3062 return T(doubleValue);
3063 }
3064}
3065
3066template <>
3067inline bool NumericT<float>::isInf(const float value)
3068{
3069 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3070 // thus implementing a custom check
3071
3072 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
3073
3074 // IEEE 754: all exponents are encoded as 1, and the mantissa is zero
3075
3076 uint32_t tmpValue;
3077 memcpy(&tmpValue, &value, sizeof(tmpValue));
3078
3079 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
3080 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
3081
3082 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3083 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0u;
3084
3085 return allExponentBitsAreOne && allMantissaBitsAreZero;
3086}
3087
3088template <>
3089inline bool NumericT<double>::isInf(const double value)
3090{
3091 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3092 // thus implementing a custom check
3093
3094 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3095
3096 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3097
3098 uint64_t tmpValue;
3099 memcpy(&tmpValue, &value, sizeof(tmpValue));
3100
3101 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3102 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3103
3104 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3105 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0ull;
3106
3107 return allExponentBitsAreOne && allMantissaBitsAreZero;
3108}
3109
3110template <typename T>
3111inline bool NumericT<T>::isInf(const T /*value*/)
3112{
3113 // with compiler optimizations, `std::isinf()` will not work anymore (the compiler simply skips the check),
3114 // thus implementing a custom check
3115
3116 ocean_assert(std::is_floating_point<T>::value == false);
3117 return false;
3118}
3119
3120template <>
3121inline bool NumericT<long double>::isInf(const long double value)
3122{
3123 return std::isinf(value);
3124}
3125
3126template <typename T>
3127inline bool NumericT<T>::isInf(const std::complex<T>& value)
3128{
3129 return NumericT<T>::isInf(value.real()) || NumericT<T>::isInf(value.imag());
3130}
3131
3132template <typename T>
3133template <typename TValue>
3134inline bool NumericT<T>::isInsideValueRange(const TValue& value)
3135{
3136 if constexpr (std::is_same<T, TValue>::value)
3137 {
3138 // e.g., [int8_t, int8_t], [uint8_t, uint8_t], [float, float], ...
3139
3140 return true;
3141 }
3142
3143 if constexpr (std::is_floating_point<T>::value && std::is_floating_point<TValue>::value)
3144 {
3145 // either [float, double], or [double, float]
3146
3147 // float/double values fit in each other (however, may be casted to inf)
3148
3149 return true;
3150 }
3151
3152 if constexpr (std::is_integral<T>::value && std::is_integral<TValue>::value)
3153 {
3154 // e.g., int8_t, uint8_t, int16_t, ...
3155
3156 if constexpr (std::is_signed<T>::value == std::is_signed<TValue>::value)
3157 {
3158 // e.g., [int8_t, int16_t], [int16_t, int8_t], [int32_t, int64_t], ...
3159
3160 if constexpr (sizeof(TValue) <= sizeof(T))
3161 {
3162 // e.g., [int16_t, int8_t], [uint64_t, uint8_t], ...
3163
3164 return true;
3165 }
3166 else
3167 {
3168 ocean_assert(sizeof(T) < sizeof(TValue));
3169
3170 // e.g., [int8_t, int16_t], [uint8_t, uint64_t], ...
3171
3172 return TValue(NumericT<T>::minValue()) <= value && value <= TValue(NumericT<T>::maxValue());
3173 }
3174 }
3175
3176 if constexpr (std::is_signed<T>::value)
3177 {
3178 ocean_assert(!std::is_signed<TValue>::value);
3179
3180 // e.g., [int8_t, uint8_t], [int32_t, uint8_t], [int64_t, uint16_t], [int8_t, uint64_t], ...
3181
3182 if constexpr (sizeof(TValue) < sizeof(T))
3183 {
3184 // e.g., [int16_t, uint8_t], [int64_t, uint16_t], ...
3185
3186 return true;
3187 }
3188
3189 // e.g., [int8_t, uint8_t], [int8_t, uint32_t], ...
3190
3191 return value <= TValue(NumericT<T>::maxValue());
3192 }
3193
3194 if constexpr (std::is_signed<TValue>::value)
3195 {
3196 ocean_assert(!std::is_signed<T>::value);
3197
3198 // e.g., [uint8_t, int8_t], [uint32_t, int8_t], [uint64_t, int16_t], [uint8_t, int64_t], ...
3199
3200 if (value < TValue(0))
3201 {
3202 return false;
3203 }
3204
3205 if constexpr (sizeof(TValue) < sizeof(T))
3206 {
3207 // e.g., [uint16_t, int8_t], [uint_64_t, int16_t], ...
3208
3209 return true;
3210 }
3211 else if constexpr (sizeof(TValue) == sizeof(T))
3212 {
3213 // e.g., [uint8_t, int8_t], [uint32_t, int32_t], [uint64_t, int64_t], ...
3214
3215 ocean_assert(value >= TValue(0));
3216
3217 return true;
3218 }
3219
3220 // e.g., [uint8_t, int16_t], [uint32_t, int64_t], ...
3221
3222 ocean_assert(value >= TValue(0));
3223
3224 return value <= TValue(NumericT<T>::maxValue());
3225 }
3226 }
3227
3228 return false;
3229}
3230
3231template <typename T>
3232constexpr inline T NumericT<T>::deg2rad(const T deg)
3233{
3234 return deg * T(0.017453292519943295769236907684886);
3235}
3236
3237template <typename T>
3238constexpr inline T NumericT<T>::rad2deg(const T rad)
3239{
3240 return rad * T(57.295779513082320876798154814105);
3241}
3242
3243template <typename T>
3244constexpr inline T NumericT<T>::maxValue()
3245{
3246 return std::numeric_limits<T>::max();
3247}
3248
3249template <typename T>
3250constexpr inline T NumericT<T>::minValue()
3251{
3252 return std::numeric_limits<T>::lowest();
3253}
3254
3255template <typename T>
3256constexpr inline T NumericT<T>::sign(const T& value)
3257{
3258 static_assert(std::numeric_limits<T>::is_signed, "T must be a signed data type!");
3259
3260 return T((T(0) < value) - (value < T(0)));
3261}
3262
3263template <typename T>
3264constexpr inline T NumericT<T>::copySign(const T signReceiver, const T signProvider)
3265{
3266 if (signProvider >= 0)
3267 {
3268 return abs(signReceiver);
3269 }
3270
3271 return -abs(signReceiver);
3272}
3273
3274#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3275
3276/**
3277 * Specialization of NumericT::copySign().
3278 * @see NumericT::copySign().
3279 */
3280template <>
3281constexpr inline double NumericT<double>::copySign(const double first, const double second)
3282{
3283 const unsigned long long value = ((*(unsigned long long*)&first) & 0x7FFFFFFFFFFFFFFFll)
3284 | ((*(unsigned long long*)&second) & 0x8000000000000000ll);
3285
3286#ifdef OCEAN_DEBUG
3287
3288 ocean_assert(sizeof(unsigned long long) == sizeof(double));
3289
3290 const double result = *(double*)&value;
3291
3292 double testValue = 0;
3293
3294 if (second >= 0.0)
3295 testValue = NumericT<double>::abs(first);
3296 else
3297 testValue = -NumericT<double>::abs(first);
3298
3299 ocean_assert(result == testValue || second == 0.0);
3300
3301#endif
3302
3303 return *(double*)&value;
3304}
3305
3306/**
3307 * Specialization of NumericT::copySign().
3308 * @see NumericT::copySign().
3309 */
3310template <>
3311constexpr inline float NumericT<float>::copySign(const float first, const float second)
3312{
3313 const unsigned int value = ((*(unsigned int*)&first) & 0x7FFFFFFF) | ((*(unsigned int*)&second) & 0x80000000);
3314
3315#ifdef OCEAN_DEBUG
3316
3317 ocean_assert(sizeof(unsigned int) == sizeof(float));
3318
3319 const float result = *(float*)&value;
3320
3321 float testValue = 0;
3322
3323 if (second >= 0.0f)
3324 testValue = NumericT<float>::abs(first);
3325 else
3326 testValue = -NumericT<float>::abs(first);
3327
3328 ocean_assert(result == testValue || second == 0.0);
3329
3330#endif
3331
3332 return *(float*)&value;
3333}
3334
3335#endif // #if 0
3336
3337template <typename T>
3338constexpr inline T NumericT<T>::invertSign(const T signReceiver, const T signProvider)
3339{
3340 if (signProvider < 0)
3341 {
3342 return abs(signReceiver);
3343 }
3344
3345 return -abs(signReceiver);
3346}
3347
3348#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3349
3350/**
3351 * Specialization of NumericT::invertSign().
3352 * @see NumericT::invertedSign().
3353 */
3354template <>
3355constexpr inline double NumericT<double>::invertSign(const double first, const double second)
3356{
3357 const unsigned long long value = ((*(unsigned long long*)&first) & 0x7FFFFFFFFFFFFFFFll)
3358 | ((~*(unsigned long long*)&second) & 0x8000000000000000ll);
3359
3360#ifdef OCEAN_DEBUG
3361
3362 ocean_assert(sizeof(unsigned long long) == sizeof(double));
3363
3364 const double result = *(double*)&value;
3365
3366 double testValue = 0;
3367
3368 if (second < 0)
3369 testValue = NumericT<double>::abs(first);
3370 else
3371 testValue = -NumericT<double>::abs(first);
3372
3373 ocean_assert(result == testValue);
3374
3375#endif
3376
3377
3378 return *(double*)&value;
3379}
3380
3381/**
3382 * Specialization of NumericT::invertSign().
3383 * @see NumericT::invertSign().
3384 */
3385template <>
3386constexpr inline float NumericT<float>::invertSign(const float first, const float second)
3387{
3388 const unsigned int value = ((*(unsigned int*)&first) & 0x7FFFFFFF) | ((~*(unsigned int*)&second) & 0x80000000);
3389
3390#ifdef OCEAN_DEBUG
3391
3392 ocean_assert(sizeof(unsigned int) == sizeof(float));
3393
3394 const float result = *(float*)&value;
3395
3396 double testValue = 0;
3397
3398 if (second < 0)
3399 testValue = NumericT<float>::abs(first);
3400 else
3401 testValue = -NumericT<float>::abs(first);
3402
3403 ocean_assert(result == testValue);
3404
3405#endif
3406
3407 return *(float*)&value;
3408}
3409
3410#endif // #if 0
3411
3412template <typename T>
3413T NumericT<T>::pythagoras(const T a, const T b)
3414{
3415 const T absA = NumericT<T>::abs(a);
3416 const T absB = NumericT<T>::abs(b);
3417
3418 if (absA > absB)
3419 {
3420 const T factor = absB / absA;
3421 return absA * sqrt(1 + factor * factor);
3422 }
3423 else if (absB != 0)
3424 {
3425 const T factor = absA / absB;
3426 return absB * sqrt(1 + factor * factor);
3427 }
3428
3429 return 0;
3430}
3431
3432template <typename T>
3433inline T NumericT<T>::gaussianDistribution(const T x, const T sigma)
3434{
3435 ocean_assert(sigma > eps());
3436
3437 const T inverseSigma = T(1) / sigma;
3438
3439 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3440}
3441
3442template <typename T>
3443inline T NumericT<T>::gaussianDistribution(const T x, const T x0, const T sigma)
3444{
3445 ocean_assert(sigma > eps());
3446
3447 const T inverseSigma = T(1) / sigma;
3448 const T x_x0 = x - x0;
3449
3450 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3451}
3452
3453template <typename T>
3454inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T sigma)
3455{
3456 ocean_assert(sigma > eps());
3457
3458 const T inverseSigma = T(1) / sigma;
3459
3460 return NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3461}
3462
3463template <typename T>
3464inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T x0, const T sigma)
3465{
3466 ocean_assert(sigma > eps());
3467
3468 const T inverseSigma = T(1) / sigma;
3469 const T x_x0 = x - x0;
3470
3471 return NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3472}
3473
3474template <typename T>
3475inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3476{
3477 ocean_assert(sigmaX > eps() && sigmaY > eps());
3478
3479 const T inverseSigmaX = T(1) / sigmaX;
3480 const T inverseSigmaY = T(1) / sigmaY;
3481
3482 return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3483}
3484
3485template <typename T>
3486inline T NumericT<T>::gaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3487{
3488 ocean_assert(sigmaX > eps() && sigmaY > eps());
3489
3490 const T inverseSigmaX = T(1) / sigmaX;
3491 const T inverseSigmaY = T(1) / sigmaY;
3492
3493 const T x_x0 = x - x0;
3494 const T y_y0 = y - y0;
3495
3496 return inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3497}
3498
3499template <typename T>
3500inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3501{
3502 ocean_assert(sigmaX > eps() && sigmaY > eps());
3503
3504 const T inverseSigmaX = T(1) / sigmaX;
3505 const T inverseSigmaY = T(1) / sigmaY;
3506
3507 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3508}
3509
3510template <typename T>
3511inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3512{
3513 ocean_assert(sigmaX > eps() && sigmaY > eps());
3514
3515 const T inverseSigmaX = T(1) / sigmaX;
3516 const T inverseSigmaY = T(1) / sigmaY;
3517
3518 const T x_x0 = x - x0;
3519 const T y_y0 = y - y0;
3520
3521 return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3522}
3523
3524template <typename T>
3525inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3526{
3527 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3528
3529 const T inverseSigmaX = T(1) / sigmaX;
3530 const T inverseSigmaY = T(1) / sigmaY;
3531 const T inverseSigmaZ = T(1) / sigmaZ;
3532
3533 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3534 * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3535}
3536
3537template <typename T>
3538inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ)
3539{
3540 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3541
3542 const T inverseSigmaX = T(1) / sigmaX;
3543 const T inverseSigmaY = T(1) / sigmaY;
3544 const T inverseSigmaZ = T(1) / sigmaZ;
3545
3546 const T x_x0 = x - x0;
3547 const T y_y0 = y - y0;
3548 const T z_z0 = z - z0;
3549
3550 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3551 * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3552}
3553
3554template <typename T>
3555inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3556{
3557 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3558
3559 const T inverseSigmaX = T(1) / sigmaX;
3560 const T inverseSigmaY = T(1) / sigmaY;
3561 const T inverseSigmaZ = T(1) / sigmaZ;
3562
3563 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3564}
3565
3566template <typename T>
3567inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T x0, const T y0, const T z0, const T sigmaX, const T sigmaY, const T sigmaZ)
3568{
3569 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3570
3571 const T inverseSigmaX = T(1) / sigmaX;
3572 const T inverseSigmaY = T(1) / sigmaY;
3573 const T inverseSigmaZ = T(1) / sigmaZ;
3574
3575 const T x_x0 = x - x0;
3576 const T y_y0 = y - y0;
3577 const T z_z0 = z - z0;
3578
3579 return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3580}
3581
3582}
3583
3584#endif // META_OCEAN_MATH_NUMERIC_H
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T angleAdjustPositive(const T angle)
Adjusts an arbitrary angle into the range of [0.0, 2PI).
Definition Numeric.h:1764
static constexpr T deg2rad(const T deg)
Converts deg to rad.
Definition Numeric.h:3232
static constexpr bool isNotWeakEqualEps(const T value)
Returns whether a value is not smaller than or equal to a weak epsilon.
Definition Numeric.h:2312
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3250
static constexpr T pi2()
Returns 2*PI which is equivalent to 360 degree.
Definition Numeric.h:932
static constexpr T sign(const T &value)
Returns the sign of a given value by either returning -1, 0, or +1.
Definition Numeric.h:3256
static constexpr T weakEps()
Returns a weak epsilon.
static constexpr bool isInsideRange(const T lower, const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a value lies between a given range up to a provided epsilon border.
Definition Numeric.h:2872
static constexpr T pi_2()
Returns PI/2 which is equivalent to 90 degree.
Definition Numeric.h:938
static T log(const T value)
Returns the natural logarithm of a given value (the logarithm to the base e).
Definition Numeric.h:1655
static T exp(const T value)
Returns the base-e exponential function of a given value.
Definition Numeric.h:1643
static T log1p(const T value)
Returns the natural logarithm of a given value plus 1 (the logarithm to the base e).
Definition Numeric.h:1669
static constexpr T e()
Returns the euler's number.
Definition Numeric.h:974
static T atan(const T value)
Returns the arctangent of a given value.
Definition Numeric.h:1616
static T atan2(const T y, const T x)
Returns the arctangent of a given value in radian.
Definition Numeric.h:1632
static constexpr T sqrDistance(const T value0, const T value1)
Returns the square distance between two values.
Definition Numeric.h:1527
static T sin(const T value)
Returns the sine of a given value.
Definition Numeric.h:1568
static bool isInf(const T value)
Returns whether a given value is positive or negative infinity.
Definition Numeric.h:3111
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition Numeric.h:1860
static constexpr T pi_4()
Returns PI/4 which is equivalent to 45 degree.
Definition Numeric.h:950
static bool isNan(const T value)
Returns whether a given value is not a number.
Definition Numeric.h:3021
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static constexpr T factorial(const T &value)
Returns the factorial for a given value.
Definition Numeric.h:1888
static constexpr T pi()
Returns PI which is equivalent to 180 degree.
Definition Numeric.h:926
static T log10(const T value)
Returns the logarithm to base 10 of a given value.
Definition Numeric.h:1711
static constexpr T squarePi2()
Returns the square of two PI i.e., (2*PI)^2.
Definition Numeric.h:962
static constexpr bool isAbove(const T value, const T lower, const T epsilon=NumericT< T >::eps())
Returns whether a parameter lies on or above a given border tolerating a small epsilon.
Definition Numeric.h:2937
static bool isWeakEqual(const T first, const T second)
Returns whether two values a equal up to a weak epsilon.
Definition Numeric.h:2572
static T normalizedGaussianDistribution(const T x, const T sigma)
Returns a value of the normalized univariate Gaussian distribution centered around the origin.
Definition Numeric.h:3454
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition Numeric.h:2064
static T sum(const T *values, const size_t number)
Returns the sum of given values.
Definition Numeric.h:1501
static constexpr bool isWeakEqualEps(const T value)
Returns whether a value is smaller than or equal to a weak epsilon.
Definition Numeric.h:2162
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1533
static T pythagoras(const T a, const T b)
Returns the length of the hypotenuse of a given right-angled triangle.
Definition Numeric.h:3413
static T fmod(const T valueA, const T valueB)
Returns the floating-point remainder of a given value.
Definition Numeric.h:1735
static T angleAdjustNull(const T angle)
Adjusts an arbitrary angle into the range of (-PI, PI].
Definition Numeric.h:1794
static bool angleIsBelowThreshold(const T angleA, const T angleB, const T threshold)
Returns whether the angular difference (distance) between two angles is smaller than a specified thre...
Definition Numeric.h:1838
static constexpr T eps()
Returns a small epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2386
static constexpr bool isBelow(const T value, const T upper, const T epsilon=NumericT< T >::eps())
Returns whether a parameter lies on or below a given border tolerating a small epsilon.
Definition Numeric.h:2927
static T gaussianDistribution(const T x, const T sigma)
Returns a value of the univariate Gaussian distribution centered around the origin.
Definition Numeric.h:3433
static T gaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
Returns a value of the bivariate Gaussian distribution centered around the origin.
Definition Numeric.h:3475
static constexpr T ratio(const T nominator, const T denominator, const T fallback=T(1))
Returns the ratio between two values if the denominator is not equal a small epsilon.
Definition Numeric.h:2076
static constexpr T nan()
Returns a value which is not a number (nan).
Definition Numeric.h:2947
static constexpr T squarePi_2()
Returns the square of PI half i.e., (PI/2)^2.
Definition Numeric.h:968
static T floor(const T value)
Returns the largest integer value that is not greater than the given value.
Definition Numeric.h:2026
static constexpr T integerPow(const T x, const unsigned int y)
Returns x raised to the power of y while y is an integer.
Definition Numeric.h:1882
static constexpr T squarePi()
Returns the square of PI i.e., PI^2.
Definition Numeric.h:956
static T tan(const T value)
Returns the tangent of a given value.
Definition Numeric.h:1600
static T normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
Returns a value of the normalized trivariate Gaussian distribution centered around the origin.
Definition Numeric.h:3555
static UnsignedTyper< T >::Type secureAbs(const T value)
Returns the absolute value of a given value while the return value is guaranteed to be the absolute v...
Definition Numeric.h:1356
static T ceil(const T value)
Returns the smallest integer value that is not less than the given value.
Definition Numeric.h:1988
static constexpr int64_t round64(const T value)
Returns the rounded 64 bit integer value of a given value.
Definition Numeric.h:2070
static bool angleIsEqual(const T angleA, const T angleB)
Returns whether two angles represent the same angle up to a small epsilon.
Definition Numeric.h:1819
static constexpr T pi_3()
Returns PI/3 which is equivalent to 60 degree.
Definition Numeric.h:944
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1495
static T angleAdjustPositiveHalf(const T angle)
Adjusts an arbitrary angle into the range of [0.0, PI).
Definition Numeric.h:1779
static constexpr bool isInsideWeakRange(const T lower, const T value, const T upper)
Returns whether a value lies between a given range up to a weak epsilon border.
Definition Numeric.h:2881
static T normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
Returns a value of the normalized bivariate Gaussian distribution centered around the origin.
Definition Numeric.h:3500
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2087
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition Numeric.h:3264
static constexpr T rad2deg(const T rad)
Converts rad to deg.
Definition Numeric.h:3238
static T cos(const T value)
Returns the cosine of a given value.
Definition Numeric.h:1584
static T gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
Returns a value of the trivariate Gaussian distribution centered around the origin.
Definition Numeric.h:3525
static T dot(const T *vectorA, const T *vectorB, const size_t size)
Returns the dot product for two vectors.
Definition Numeric.h:1751
static bool isInsideValueRange(const TValue &value)
Returns whether a given value of an arbitrary data type fits into the value range of 'T'.
Definition Numeric.h:3134
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2907
static constexpr T invertSign(const T signReceiver, const T signProvider)
Copies the inverted sign of a given value to another one.
Definition Numeric.h:3338
static constexpr T inf()
Returns a value which is positive infinity.
Definition Numeric.h:3037
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2237
static bool angleIsWeakEqual(const T angleA, const T angleB)
Returns whether two angles represent the same angle up to a weak epsilon.
Definition Numeric.h:1825
static T angleDistance(const T angleA, const T angleB)
Returns the angular difference (distance between two angles).
Definition Numeric.h:1846
static bool isNotEqual(const T first, const T second)
Returns whether two values are not equal up to a small epsilon.
Definition Numeric.h:2613
static T summedSqr(const T *values, const size_t number)
Returns the summed squares of a given values.
Definition Numeric.h:1514
static T log2(const T value)
Returns the logarithm to base 2 of a given value.
Definition Numeric.h:1683
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3244
static T asin(const T value)
Returns the arcsine of a given value.
Definition Numeric.h:2887
static bool isNotWeakEqual(const T first, const T second)
Returns whether two values are not equal up to a weak epsilon.
Definition Numeric.h:2686
static constexpr T binomialCoefficient(const T &n, const T &k)
Returns the binomial coefficient for two binomial parameters.
Definition Numeric.h:1957
T Type
Definition of the unsigned data type, if existing.
Definition DataType.h:339
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition base/Utilities.h:1029
NumericT< Scalar > Numeric
Definition of a Numeric class.
Definition Numeric.h: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