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 [[nodiscard]] static constexpr T pi();
65
66 /**
67 * Returns 2*PI which is equivalent to 360 degree.
68 * @return 2*PI
69 */
70 [[nodiscard]] static constexpr T pi2();
71
72 /**
73 * Returns PI/2 which is equivalent to 90 degree.
74 * @return PI/2
75 */
76 [[nodiscard]] static constexpr T pi_2();
77
78 /**
79 * Returns PI/3 which is equivalent to 60 degree.
80 * @return PI/3
81 */
82 [[nodiscard]] static constexpr T pi_3();
83
84 /**
85 * Returns PI/4 which is equivalent to 45 degree.
86 * @return PI/4
87 */
88 [[nodiscard]] static constexpr T pi_4();
89
90 /**
91 * Returns the square of PI i.e., PI^2.
92 * @return PI^2
93 */
94 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] static constexpr T squarePi_2();
107
108 /**
109 * Returns the euler's number.
110 * @return Euler's number
111 */
112 [[nodiscard]] static constexpr T e();
113
114 /**
115 * Returns a small epsilon.
116 * @return Small epsilon
117 */
118 [[nodiscard]] static constexpr T eps();
119
120 /**
121 * Returns a weak epsilon.
122 * @return Weak epsilon
123 */
124 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] static constexpr inline T rad2deg(const T rad);
741
742 /**
743 * Returns the max scalar value.
744 * @return Max value
745 */
746 [[nodiscard]] static constexpr inline T maxValue();
747
748 /**
749 * Returns the min scalar value.
750 * @return Min value
751 */
752 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 [[nodiscard]] 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 if (value == std::numeric_limits<long>::lowest())
1435 {
1436 return (unsigned long)(std::numeric_limits<long>::max()) + 1ul;
1437 }
1438
1439 return (unsigned long)(::llabs(value));
1440}
1441
1442/**
1443 * Specialization of NumericT::secureAbs().
1444 * @see NumericT::secureAbs().
1445 */
1446template <>
1447inline unsigned long NumericT<unsigned long>::secureAbs(const unsigned long value)
1448{
1449 return value;
1450}
1451
1452/**
1453 * Specialization of NumericT::secureAbs().
1454 * @see NumericT::secureAbs().
1455 */
1456template <>
1457inline unsigned long long NumericT<long long>::secureAbs(const long long value)
1458{
1459 if (value == std::numeric_limits<long long>::lowest())
1460 {
1461 // -9223372036854775808 -> +9223372036854775808
1462 return (unsigned long long)(std::numeric_limits<long long>::max()) + 1ull;
1463 }
1464
1465 return (unsigned long long)(::llabs(value));
1466}
1467
1468/**
1469 * Specialization of NumericT::secureAbs().
1470 * @see NumericT::secureAbs().
1471 */
1472template <>
1473inline unsigned long long NumericT<unsigned long long>::secureAbs(const unsigned long long value)
1474{
1475 return value;
1476}
1477
1478/**
1479 * Specialization of NumericT::secureAbs().
1480 * @see NumericT::secureAbs().
1481 */
1482template <>
1483inline double NumericT<double>::secureAbs(const double value)
1484{
1485 return abs(value);
1486}
1487
1488/**
1489 * Specialization of NumericT::secureAbs().
1490 * @see NumericT::secureAbs().
1491 */
1492template <>
1493inline float NumericT<float>::secureAbs(const float value)
1494{
1495 return abs(value);
1496}
1497
1498template <typename T>
1499constexpr inline T NumericT<T>::sqr(const T value)
1500{
1501 return value * value;
1502}
1503
1504template <typename T>
1505inline T NumericT<T>::sum(const T* values, const size_t number)
1506{
1507 T result = T(0);
1508
1509 for (size_t n = 0; n < number; ++n)
1510 {
1511 result += values[n];
1512 }
1513
1514 return result;
1515}
1516
1517template <typename T>
1518inline T NumericT<T>::summedSqr(const T* values, const size_t number)
1519{
1520 T result = T(0);
1521
1522 for (size_t n = 0; n < number; ++n)
1523 {
1524 result += sqr(values[n]);
1525 }
1526
1527 return result;
1528}
1529
1530template <typename T>
1531constexpr inline T NumericT<T>::sqrDistance(const T value0, const T value1)
1532{
1533 return sqr(value0 - value1);
1534}
1535
1536template <typename T>
1537inline T NumericT<T>::sqrt(const T value)
1538{
1539 ocean_assert(value >= T(0));
1540 return T(::sqrt(value));
1541}
1542
1543/**
1544 * Specialization of NumericT::sqrt().
1545 * @see NumericT::sqrt().
1546 */
1547template <>
1548inline float NumericT<float>::sqrt(const float value)
1549{
1550 ocean_assert(value >= 0.0f);
1551 return ::sqrtf(value);
1552}
1553
1554/**
1555 * Specialization of NumericT::sqrt().
1556 * @see NumericT::sqrt().
1557 */
1558template <>
1559inline int NumericT<int>::sqrt(const int value)
1560{
1561 ocean_assert(value >= 0);
1562 return int(::sqrtf(float(value)));
1563}
1564
1565template <typename T>
1566inline std::complex<T> NumericT<T>::sqrt(const std::complex<T>& value)
1567{
1568 return std::sqrt<T>(value);
1569}
1570
1571template <typename T>
1572inline T NumericT<T>::sin(const T value)
1573{
1574 return ::sin(value);
1575}
1576
1577/**
1578 * Specialization of NumericT::sin().
1579 * @see NumericT::sin().
1580 */
1581template <>
1582inline float NumericT<float>::sin(const float value)
1583{
1584 return sinf(value);
1585}
1586
1587template <typename T>
1588inline T NumericT<T>::cos(const T value)
1589{
1590 return ::cos(value);
1591}
1592
1593/**
1594 * Specialization of NumericT::cos().
1595 * @see NumericT::cos().
1596 */
1597template <>
1598inline float NumericT<float>::cos(const float value)
1599{
1600 return cosf(value);
1601}
1602
1603template <typename T>
1604inline T NumericT<T>::tan(const T value)
1605{
1606 return ::tan(value);
1607}
1608
1609/**
1610 * Specialization of NumericT::tan().
1611 * @see NumericT::tan().
1612 */
1613template <>
1614inline float NumericT<float>::tan(const float value)
1615{
1616 return tanf(value);
1617}
1618
1619template <typename T>
1620inline T NumericT<T>::atan(const T value)
1621{
1622 return ::atan(value);
1623}
1624
1625/**
1626 * Specialization of NumericT::atan().
1627 * @see NumericT::atan().
1628 */
1629template <>
1630inline float NumericT<float>::atan(const float value)
1631{
1632 return atanf(value);
1633}
1634
1635template <typename T>
1636inline T NumericT<T>::atan2(const T y, const T x)
1637{
1639
1640 const T angle = ::atan2(y, x);
1641 ocean_assert(angle >= -NumericT<T>::pi() && angle <= NumericT<T>::pi());
1642
1643 return angle;
1644}
1645
1646template <typename T>
1647inline T NumericT<T>::exp(const T value)
1648{
1649 return ::exp(value);
1650}
1651
1652template <>
1653inline float NumericT<float>::exp(const float value)
1654{
1655 return ::expf(value);
1656}
1657
1658template <typename T>
1659inline T NumericT<T>::log(const T value)
1660{
1661 ocean_assert(value > 0);
1662 return ::log(value);
1663}
1664
1665template <>
1666inline float NumericT<float>::log(const float value)
1667{
1668 ocean_assert(value > 0);
1669 return ::logf(value);
1670}
1671
1672template <typename T>
1673inline T NumericT<T>::log1p(const T value)
1674{
1675 ocean_assert(value > -1);
1676 return ::log1p(value);
1677}
1678
1679template <>
1680inline float NumericT<float>::log1p(const float value)
1681{
1682 ocean_assert(value > -1);
1683 return ::log1pf(value);
1684}
1685
1686template <typename T>
1687inline T NumericT<T>::log2(const T value)
1688{
1689 ocean_assert(value > 0);
1690
1691#if (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION >= 1800) || (OCEAN_CLANG_VERSION >= 30300 && (!defined(__ANDROID__) || !__ANDROID__))
1692 return ::log2(value);
1693#else
1694 return ::log(value) * 1.44269504088896340736; // 1 / ln(2)
1695#endif
1696}
1697
1698/**
1699 * Specialization of NumericT::log2().
1700 * @see NumericT::log2().
1701 */
1702template <>
1703inline float NumericT<float>::log2(const float value)
1704{
1705 ocean_assert(value > 0);
1706
1707#if (defined(OCEAN_COMPILER_MSC) && OCEAN_MSC_VERSION >= 1800) || (OCEAN_CLANG_VERSION >= 30300 && (!defined(__ANDROID__) || !__ANDROID__))
1708 return ::log2f(value);
1709#else
1710 return ::logf(value) * 1.44269504088896340736f; // 1 / ln(2)
1711#endif
1712}
1713
1714template <typename T>
1715inline T NumericT<T>::log10(const T value)
1716{
1717 ocean_assert(value > 0);
1718 return ::log10(value);
1719}
1720
1721template <>
1722inline float NumericT<float>::log10(const float value)
1723{
1724 ocean_assert(value > 0);
1725 return ::log10f(value);
1726}
1727
1728/**
1729 * Specialization of NumericT::atan2().
1730 * @see NumericT::atan2().
1731 */
1732template <>
1733inline float NumericT<float>::atan2(const float y, const float x)
1734{
1736
1737 return atan2f(y, x);
1738}
1739
1740template <typename T>
1741inline T NumericT<T>::fmod(const T valueA, const T valueB)
1742{
1743 return ::fmod(valueA, valueB);
1744}
1745
1746/**
1747 * Specialization of NumericT::fmod().
1748 * @see NumericT::fmod().
1749 */
1750template <>
1751inline float NumericT<float>::fmod(const float valueA, const float valueB)
1752{
1753 return fmodf(valueA, valueB);
1754}
1755
1756template <typename T>
1757inline T NumericT<T>::dot(const T* vectorA, const T* vectorB, const size_t size)
1758{
1759 T result = T(0);
1760
1761 for (size_t n = 0; n < size; ++n)
1762 {
1763 result += vectorA[n] * vectorB[n];
1764 }
1765
1766 return result;
1767}
1768
1769template <typename T>
1771{
1772 const T adjusted = fmod(angle, pi2());
1773
1774 if (adjusted < 0)
1775 {
1776 ocean_assert((std::is_same<T, float>::value) || (pi2() + adjusted >= 0 && pi2() + adjusted < pi2()));
1777 return pi2() + adjusted;
1778 }
1779
1780 ocean_assert(adjusted >= 0 && adjusted < pi2());
1781 return adjusted;
1782}
1783
1784template <typename T>
1786{
1787 const T adjusted = fmod(angle, pi());
1788
1789 if (adjusted < 0)
1790 {
1791 ocean_assert(pi() + adjusted >= 0 && pi() + adjusted < pi());
1792 return pi() + adjusted;
1793 }
1794
1795 ocean_assert(adjusted >= 0 && adjusted < pi());
1796 return adjusted;
1797}
1798
1799template <typename T>
1800inline T NumericT<T>::angleAdjustNull(const T angle)
1801{
1802 if (angle > -pi() && angle <= pi())
1803 {
1804 return angle;
1805 }
1806
1807 const T adjusted = fmod(angle, pi2());
1808
1809 if (isAbove(adjusted, pi()))
1810 {
1811 ocean_assert(adjusted - pi2() > -pi() - eps() && adjusted - pi2() <= pi() + eps());
1812 return adjusted - pi2();
1813 }
1814 else if (isBelow(adjusted, -pi()))
1815 {
1816 ocean_assert(adjusted + pi2() > -pi() - eps() && adjusted + pi2() <= pi() + eps());
1817 return adjusted + pi2();
1818 }
1819
1820 ocean_assert(adjusted > -pi() && adjusted <= pi());
1821 return adjusted;
1822}
1823
1824template <typename T>
1825inline bool NumericT<T>::angleIsEqual(const T angleA, const T angleB)
1826{
1827 return isEqualEps(angleDistance(angleA, angleB));
1828}
1829
1830template <typename T>
1831inline bool NumericT<T>::angleIsWeakEqual(const T angleA, const T angleB)
1832{
1833 return isWeakEqualEps(angleDistance(angleA, angleB));
1834}
1835
1836template <typename T>
1837inline bool NumericT<T>::angleIsEqual(const T angleA, const T angleB, const T epsilon)
1838{
1839 ocean_assert(epsilon >= T(0));
1840 return isEqual(angleDistance(angleA, angleB), T(0), epsilon);
1841}
1842
1843template <typename T>
1844inline bool NumericT<T>::angleIsBelowThreshold(const T angleA, const T angleB, const T threshold)
1845{
1846 ocean_assert(threshold < pi());
1847
1848 return isBelow(abs(angleAdjustNull(angleA - angleB)), threshold);
1849}
1850
1851template <typename T>
1852inline T NumericT<T>::angleDistance(const T angleA, const T angleB)
1853{
1854 const T distance = abs(angleAdjustPositive(angleA) - angleAdjustPositive(angleB));
1855 ocean_assert(distance < NumericT<T>::pi2());
1856
1857 if (distance < NumericT<T>::pi())
1858 {
1859 return distance;
1860 }
1861
1862 return NumericT<T>::pi2() - distance;
1863}
1864
1865template <typename T>
1866inline T NumericT<T>::pow(const T x, const T y)
1867{
1868 return ::pow(x, y);
1869}
1870
1871template <typename T>
1872inline std::complex<T> NumericT<T>::pow(const std::complex<T>& x, const T y)
1873{
1874 return std::pow<T>(x, y);
1875}
1876
1877/**
1878 * Specialization of NumericT::pow().
1879 * @see NumericT::pow().
1880 */
1881template <>
1882inline float NumericT<float>::pow(const float x, const float y)
1883{
1884 return powf(x, y);
1885}
1886
1887template <typename T>
1888constexpr T NumericT<T>::integerPow(const T x, const unsigned int y)
1889{
1890 return y == 0u ? T(1) : x * integerPow(x, y - 1u);
1891}
1892
1893template <typename T>
1894constexpr inline T NumericT<T>::factorial(const T& value)
1895{
1896 ocean_assert(value >= 0);
1897 ocean_assert(T(int64_t(value)) == value);
1898
1899 if (value <= 1)
1900 {
1901 return T(1);
1902 }
1903
1904 T result = T(2);
1905
1906 for (unsigned int n = 3u; n <= (unsigned int)value; ++n)
1907 {
1908 ocean_assert(maxValue() / T(n) >= result);
1909 result *= T(n);
1910 }
1911
1912 return result;
1913}
1914
1915template <>
1916constexpr inline unsigned int NumericT<unsigned int>::factorial(const unsigned int& value)
1917{
1918 switch (value)
1919 {
1920 case 0u:
1921 case 1u:
1922 return 1u;
1923
1924 case 2u:
1925 return 2u;
1926
1927 case 3u:
1928 return 6u;
1929
1930 case 4u:
1931 return 24u;
1932
1933 case 5u:
1934 return 120u;
1935
1936 case 6u:
1937 return 720u;
1938
1939 case 7u:
1940 return 5040u;
1941
1942 case 8u:
1943 return 40320u;
1944
1945 case 9u:
1946 return 362880u;
1947
1948 case 10u:
1949 return 3628800u;
1950
1951 case 11u:
1952 return 39916800u;
1953
1954 case 12u:
1955 return 479001600u;
1956
1957 default:
1958 break;
1959 }
1960
1961 ocean_assert(false && "Invalid factorial value!");
1962 return 1u;
1963}
1964
1965template <typename T>
1966constexpr inline T NumericT<T>::binomialCoefficient(const T& n, const T& k)
1967{
1968 ocean_assert(n >= 0 && k >= 0);
1969 ocean_assert(T(int64_t(n)) == n);
1970 ocean_assert(T(int64_t(k)) == k);
1971
1972 if (n <= T(1) || k == T(0) || n == k)
1973 {
1974 return T(1);
1975 }
1976
1977 ocean_assert(k < n);
1978
1979 T result = n - k + T(1);
1980
1981 for (unsigned int i = (unsigned int)(n - k) + 2u; i <= (unsigned int)(n); ++i)
1982 {
1983 ocean_assert(maxValue() / T(i) >= result);
1984 result *= T(i);
1985 }
1986
1987 for (unsigned int i = 2u; i <= (unsigned int)(k); ++i)
1988 {
1989 ocean_assert((result / T(i)) * T(i) == result);
1990 result /= T(i);
1991 }
1992
1993 return result;
1994}
1995
1996template <typename T>
1997inline T NumericT<T>::ceil(const T value)
1998{
1999 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
2000
2001 return value;
2002}
2003
2004/**
2005 * Specialization of NumericT::ceil().
2006 * @see NumericT::ceil().
2007 */
2008template <>
2009inline float NumericT<float>::ceil(const float value)
2010{
2011 return ::ceilf(value);
2012}
2013
2014/**
2015 * Specialization of NumericT::ceil().
2016 * @see NumericT::ceil().
2017 */
2018template <>
2019inline double NumericT<double>::ceil(const double value)
2020{
2021 return ::ceil(value);
2022}
2023
2024/**
2025 * Specialization of NumericT::ceil().
2026 * @see NumericT::ceil().
2027 */
2028template <>
2029inline long double NumericT<long double>::ceil(const long double value)
2030{
2031 return ::ceill(value);
2032}
2033
2034template <typename T>
2035inline T NumericT<T>::floor(const T value)
2036{
2037 static_assert(std::is_floating_point<T>::value == false, "Data type must not be a floating point!");
2038
2039 return value;
2040}
2041
2042/**
2043 * Specialization of NumericT::floor().
2044 * @see NumericT::floor().
2045 */
2046template <>
2047inline float NumericT<float>::floor(const float value)
2048{
2049 return ::floorf(value);
2050}
2051
2052/**
2053 * Specialization of NumericT::floor().
2054 * @see NumericT::floor().
2055 */
2056template <>
2057inline double NumericT<double>::floor(const double value)
2058{
2059 return ::floor(value);
2060}
2061
2062/**
2063 * Specialization of NumericT::floor().
2064 * @see NumericT::floor().
2065 */
2066template <>
2067inline long double NumericT<long double>::floor(const long double value)
2068{
2069 return ::floorl(value);
2070}
2071
2072template <typename T>
2073constexpr inline int32_t NumericT<T>::round32(const T value)
2074{
2075 return int32_t(value + copySign(T(0.5), value));
2076}
2077
2078template <typename T>
2079constexpr inline int64_t NumericT<T>::round64(const T value)
2080{
2081 return int64_t(value + copySign(T(0.5), value));
2082}
2083
2084template <typename T>
2085constexpr inline T NumericT<T>::ratio(const T nominator, const T denominator, const T fallback)
2086{
2087 if (isEqualEps(denominator))
2088 {
2089 return fallback;
2090 }
2091
2092 return nominator / denominator;
2093}
2094
2095template <typename T>
2096constexpr inline bool NumericT<T>::isEqualEps(const T value)
2097{
2098 ocean_assert(isNan(value) == false);
2099 ocean_assert((fabs(value) <= eps()) == (-eps() <= value && value <= eps()));
2100
2101 return -eps() <= value && value <= eps();
2102}
2103
2104template <>
2105constexpr inline bool NumericT<signed char>::isEqualEps(const signed char value)
2106{
2107 return value == (signed char)(0);
2108}
2109
2110template <>
2111constexpr inline bool NumericT<unsigned char>::isEqualEps(const unsigned char value)
2112{
2113 return value == (unsigned char)(0);
2114}
2115
2116template <>
2117constexpr inline bool NumericT<short>::isEqualEps(const short value)
2118{
2119 return value == short(0);
2120}
2121
2122template <>
2123constexpr inline bool NumericT<unsigned short>::isEqualEps(const unsigned short value)
2124{
2125 return value == (unsigned short)(0);
2126}
2127
2128template <>
2129constexpr inline bool NumericT<int>::isEqualEps(const int value)
2130{
2131 return value == 0;
2132}
2133
2134template <>
2135constexpr inline bool NumericT<unsigned int>::isEqualEps(const unsigned int value)
2136{
2137 return value == 0u;
2138}
2139
2140template <>
2141constexpr inline bool NumericT<long>::isEqualEps(const long value)
2142{
2143 return value == 0l;
2144}
2145
2146template <>
2147constexpr inline bool NumericT<unsigned long>::isEqualEps(const unsigned long value)
2148{
2149 return value == 0ul;
2150}
2151
2152template <>
2153constexpr inline bool NumericT<long long>::isEqualEps(const long long value)
2154{
2155 return value == 0ll;
2156}
2157
2158template <>
2159constexpr inline bool NumericT<unsigned long long>::isEqualEps(const unsigned long long value)
2160{
2161 return value == 0ull;
2162}
2163
2164template <typename T>
2165constexpr inline bool NumericT<T>::isEqualEps(const std::complex<T>& value)
2166{
2167 return isEqualEps(value.real()) && isEqualEps(value.imag());
2168}
2169
2170template <typename T>
2171constexpr inline bool NumericT<T>::isWeakEqualEps(const T value)
2172{
2173 ocean_assert(isNan(value) == false);
2174 ocean_assert((fabs(value) <= weakEps()) == (-weakEps() <= value && value <= weakEps()));
2175
2176 return -weakEps() <= value && value <= weakEps();
2177}
2178
2179template <>
2180constexpr inline bool NumericT<signed char>::isWeakEqualEps(const signed char value)
2181{
2182 return value == (signed char)(0);
2183}
2184
2185template <>
2186constexpr inline bool NumericT<unsigned char>::isWeakEqualEps(const unsigned char value)
2187{
2188 return value == (unsigned char)(0);
2189}
2190
2191template <>
2192constexpr inline bool NumericT<short>::isWeakEqualEps(const short value)
2193{
2194 return value == short(0);
2195}
2196
2197template <>
2198constexpr inline bool NumericT<unsigned short>::isWeakEqualEps(const unsigned short value)
2199{
2200 return value == (unsigned short)(0);
2201}
2202
2203template <>
2204constexpr inline bool NumericT<int>::isWeakEqualEps(const int value)
2205{
2206 return value == 0;
2207}
2208
2209template <>
2210constexpr inline bool NumericT<unsigned int>::isWeakEqualEps(const unsigned int value)
2211{
2212 return value == 0u;
2213}
2214
2215template <>
2216constexpr inline bool NumericT<long>::isWeakEqualEps(const long value)
2217{
2218 return value == 0l;
2219}
2220
2221template <>
2222constexpr inline bool NumericT<unsigned long>::isWeakEqualEps(const unsigned long value)
2223{
2224 return value == 0ul;
2225}
2226
2227template <>
2228constexpr inline bool NumericT<long long>::isWeakEqualEps(const long long value)
2229{
2230 return value == 0ll;
2231}
2232
2233template <>
2234constexpr inline bool NumericT<unsigned long long>::isWeakEqualEps(const unsigned long long value)
2235{
2236 return value == 0ull;
2237}
2238
2239template <typename T>
2240constexpr inline bool NumericT<T>::isWeakEqualEps(const std::complex<T>& value)
2241{
2242 return isWeakEqualEps(value.real()) && isWeakEqualEps(value.imag());
2243}
2244
2245template <typename T>
2246constexpr inline bool NumericT<T>::isNotEqualEps(const T value)
2247{
2248 ocean_assert(isNan(value) == false);
2249 ocean_assert((fabs(value) > eps()) == (value > eps() || value < -eps()));
2250
2251 return value > eps() || value < -eps();
2252}
2253
2254template <>
2255constexpr inline bool NumericT<signed char>::isNotEqualEps(const signed char value)
2256{
2257 return value != (signed char)(0);
2258}
2259
2260template <>
2261constexpr inline bool NumericT<unsigned char>::isNotEqualEps(const unsigned char value)
2262{
2263 return value != (unsigned char)(0);
2264}
2265
2266template <>
2267constexpr inline bool NumericT<short>::isNotEqualEps(const short value)
2268{
2269 return value != short(0);
2270}
2271
2272template <>
2273constexpr inline bool NumericT<unsigned short>::isNotEqualEps(const unsigned short value)
2274{
2275 return value != (unsigned short)(0);
2276}
2277
2278template <>
2279constexpr inline bool NumericT<int>::isNotEqualEps(const int value)
2280{
2281 return value != 0;
2282}
2283
2284template <>
2285constexpr inline bool NumericT<unsigned int>::isNotEqualEps(const unsigned int value)
2286{
2287 return value != 0u;
2288}
2289
2290template <>
2291constexpr inline bool NumericT<long>::isNotEqualEps(const long value)
2292{
2293 return value != 0l;
2294}
2295
2296template <>
2297constexpr inline bool NumericT<unsigned long>::isNotEqualEps(const unsigned long value)
2298{
2299 return value != 0ul;
2300}
2301
2302template <>
2303constexpr inline bool NumericT<long long>::isNotEqualEps(const long long value)
2304{
2305 return value != 0ll;
2306}
2307
2308template <>
2309constexpr inline bool NumericT<unsigned long long>::isNotEqualEps(const unsigned long long value)
2310{
2311 return value != 0ull;
2312}
2313
2314template <typename T>
2315constexpr inline bool NumericT<T>::isNotEqualEps(const std::complex<T>& value)
2316{
2317 return value.real() > eps() || value.real() < -eps() || value.imag() > eps() || value.imag() < -eps();
2318}
2319
2320template <typename T>
2321constexpr inline bool NumericT<T>::isNotWeakEqualEps(const T value)
2322{
2323 ocean_assert((fabs(value) > weakEps()) == (value > weakEps() || value < -weakEps()));
2324
2325 return value > weakEps() || value < -weakEps();
2326}
2327
2328template <>
2329constexpr inline bool NumericT<signed char>::isNotWeakEqualEps(const signed char value)
2330{
2331 return value != (signed char)(0);
2332}
2333
2334template <>
2335constexpr inline bool NumericT<unsigned char>::isNotWeakEqualEps(const unsigned char value)
2336{
2337 return value != (unsigned char)(0);
2338}
2339
2340template <>
2341constexpr inline bool NumericT<short>::isNotWeakEqualEps(const short value)
2342{
2343 return value != short(0);
2344}
2345
2346template <>
2347constexpr inline bool NumericT<unsigned short>::isNotWeakEqualEps(const unsigned short value)
2348{
2349 return value != (unsigned short)(0);
2350}
2351
2352template <>
2353constexpr inline bool NumericT<int>::isNotWeakEqualEps(const int value)
2354{
2355 return value != 0;
2356}
2357
2358template <>
2359constexpr inline bool NumericT<unsigned int>::isNotWeakEqualEps(const unsigned int value)
2360{
2361 return value != 0u;
2362}
2363
2364template <>
2365constexpr inline bool NumericT<long>::isNotWeakEqualEps(const long value)
2366{
2367 return value != 0l;
2368}
2369
2370template <>
2371constexpr inline bool NumericT<unsigned long>::isNotWeakEqualEps(const unsigned long value)
2372{
2373 return value != 0ul;
2374}
2375
2376template <>
2377constexpr inline bool NumericT<long long>::isNotWeakEqualEps(const long long value)
2378{
2379 return value != 0ll;
2380}
2381
2382template <>
2383constexpr inline bool NumericT<unsigned long long>::isNotWeakEqualEps(const unsigned long long value)
2384{
2385 return value != 0ull;
2386}
2387
2388template <typename T>
2389constexpr inline bool NumericT<T>::isNotWeakEqualEps(const std::complex<T>& value)
2390{
2391 return value.real() > weakEps() || value.real() < -weakEps() || value.imag() > weakEps() || value.imag() < -weakEps();
2392}
2393
2394template <typename T>
2395inline bool NumericT<T>::isEqual(const T first, const T second)
2396{
2397 return fabs(first - second) <= eps();
2398}
2399
2400template <>
2401inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second)
2402{
2403 return first == second;
2404}
2405
2406template <>
2407inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second)
2408{
2409 return first == second;
2410}
2411
2412template <>
2413inline bool NumericT<short>::isEqual(const short first, const short second)
2414{
2415 return first == second;
2416}
2417
2418template <>
2419inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second)
2420{
2421 return first == second;
2422}
2423
2424template <>
2425inline bool NumericT<int>::isEqual(const int first, const int second)
2426{
2427 return first == second;
2428}
2429
2430template <>
2431inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second)
2432{
2433 return first == second;
2434}
2435
2436template <>
2437inline bool NumericT<long>::isEqual(const long first, const long second)
2438{
2439 return first == second;
2440}
2441
2442template <>
2443inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second)
2444{
2445 return first == second;
2446}
2447
2448template <>
2449inline bool NumericT<long long>::isEqual(const long long first, const long long second)
2450{
2451 return first == second;
2452}
2453
2454template <>
2455inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second)
2456{
2457 return first == second;
2458}
2459
2460template <typename T>
2461inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second)
2462{
2463 return isEqual(first.real(), second.real()) && isEqual(first.imag(), second.imag());
2464}
2465
2466template <typename T>
2467inline bool NumericT<T>::isEqual(const T first, const T second, const T epsilon)
2468{
2469 ocean_assert(epsilon >= T(0));
2470 return NumericT<T>::abs(first - second) <= epsilon;
2471}
2472
2473template <>
2474inline bool NumericT<signed char>::isEqual(const signed char first, const signed char second, const signed char epsilon)
2475{
2476 ocean_assert(epsilon >= (signed char)(0));
2477 return std::abs(first - second) <= epsilon;
2478}
2479
2480template <>
2481inline bool NumericT<short>::isEqual(const short first, const short second, const short epsilon)
2482{
2483 ocean_assert(epsilon >= short(0));
2484 return std::abs(first - second) <= epsilon;
2485}
2486
2487template <>
2488inline bool NumericT<int>::isEqual(const int first, const int second, const int epsilon)
2489{
2490 ocean_assert(epsilon >= 0);
2491 return std::abs(first - second) <= epsilon;
2492}
2493
2494template <>
2495inline bool NumericT<long>::isEqual(const long first, const long second, const long epsilon)
2496{
2497 ocean_assert(epsilon >= long(0));
2498 return std::abs(first - second) <= epsilon;
2499}
2500
2501template <>
2502inline bool NumericT<long long>::isEqual(const long long first, const long long second, const long long epsilon)
2503{
2504 ocean_assert(epsilon >= 0ll);
2505 return std::abs(first - second) <= epsilon;
2506}
2507
2508template <>
2509inline bool NumericT<unsigned char>::isEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2510{
2511 if (first > second)
2512 {
2513 return first - second <= epsilon;
2514 }
2515 else
2516 {
2517 return second - first <= epsilon;
2518 }
2519}
2520
2521template <>
2522inline bool NumericT<unsigned short>::isEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2523{
2524 if (first > second)
2525 {
2526 return first - second <= epsilon;
2527 }
2528 else
2529 {
2530 return second - first <= epsilon;
2531 }
2532}
2533
2534template <>
2535inline bool NumericT<unsigned int>::isEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2536{
2537 if (first > second)
2538 {
2539 return first - second <= epsilon;
2540 }
2541 else
2542 {
2543 return second - first <= epsilon;
2544 }
2545}
2546
2547template <>
2548inline bool NumericT<unsigned long>::isEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2549{
2550 if (first > second)
2551 {
2552 return first - second <= epsilon;
2553 }
2554 else
2555 {
2556 return second - first <= epsilon;
2557 }
2558}
2559
2560template <>
2561inline bool NumericT<unsigned long long>::isEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2562{
2563 if (first > second)
2564 {
2565 return first - second <= epsilon;
2566 }
2567 else
2568 {
2569 return second - first <= epsilon;
2570 }
2571}
2572
2573template <typename T>
2574inline bool NumericT<T>::isEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2575{
2576 ocean_assert(epsilon >= T(0));
2577 return isEqual(first.real(), second.real(), epsilon) && isEqual(first.imag(), second.imag(), epsilon);
2578}
2579
2580template <typename T>
2581inline bool NumericT<T>::isWeakEqual(const T first, const T second)
2582{
2583 return NumericT<T>::abs(first - second) <= weakEps();
2584}
2585
2586template <>
2587inline bool NumericT<int>::isWeakEqual(const int first, const int second)
2588{
2589 return first == second;
2590}
2591
2592template <typename T>
2593inline bool NumericT<T>::isWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2594{
2595 return isWeakEqual(first.real(), second.real()) && isWeakEqual(first.imag(), second.imag());
2596}
2597
2598template <typename T>
2599template <int tMagnitude>
2600inline bool NumericT<T>::isEqual(const T first, const T second, const T referenceEpsilon)
2601{
2602 static_assert(tMagnitude >= -20 && tMagnitude <= 20, "Invalid reference magnitude");
2603 ocean_assert(referenceEpsilon >= T(0));
2604
2605 const T maximalAbsValue = max(NumericT<T>::abs(first), NumericT<T>::abs(second));
2606
2607 // we ensure that the max value is not 0 (due to the following log)
2608 if (isEqualEps(maximalAbsValue))
2609 {
2610 return NumericT<T>::isEqual(first, second, referenceEpsilon);
2611 }
2612
2613 const int offsetMagnitude = int(max(NumericT<float>::ceil(NumericT<float>::log10(float(maximalAbsValue))), float(tMagnitude))) - tMagnitude;
2614 ocean_assert(offsetMagnitude >= 0);
2615
2616 const T adjustedEpsilon = referenceEpsilon * NumericT<T>::pow(10, T(offsetMagnitude));
2617
2618 return isEqual(first, second, adjustedEpsilon);
2619}
2620
2621template <typename T>
2622inline bool NumericT<T>::isNotEqual(const T first, const T second)
2623{
2624 return fabs(first - second) > eps();
2625}
2626
2627template <>
2628inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second)
2629{
2630 return first != second;
2631}
2632
2633template <>
2634inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second)
2635{
2636 return first != second;
2637}
2638
2639template <>
2640inline bool NumericT<short>::isNotEqual(const short first, const short second)
2641{
2642 return first != second;
2643}
2644
2645template <>
2646inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second)
2647{
2648 return first != second;
2649}
2650
2651template <>
2652inline bool NumericT<int>::isNotEqual(const int first, const int second)
2653{
2654 return first != second;
2655}
2656
2657template <>
2658inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second)
2659{
2660 return first != second;
2661}
2662
2663template <>
2664inline bool NumericT<long>::isNotEqual(const long first, const long second)
2665{
2666 return first != second;
2667}
2668
2669template <>
2670inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second)
2671{
2672 return first != second;
2673}
2674
2675
2676template <>
2677inline bool NumericT<long long>::isNotEqual(const long long first, const long long second)
2678{
2679 return first != second;
2680}
2681
2682template <>
2683inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second)
2684{
2685 return first != second;
2686}
2687
2688template <typename T>
2689inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second)
2690{
2691 return isNotEqual(first.real(), second.real()) || isNotEqual(first.imag(), second.imag());
2692}
2693
2694template <typename T>
2695inline bool NumericT<T>::isNotWeakEqual(const T first, const T second)
2696{
2697 return fabs(first - second) > weakEps();
2698}
2699
2700template <>
2701inline bool NumericT<signed char>::isNotWeakEqual(const signed char first, const signed char second)
2702{
2703 return first != second;
2704}
2705
2706template <>
2707inline bool NumericT<unsigned char>::isNotWeakEqual(const unsigned char first, const unsigned char second)
2708{
2709 return first != second;
2710}
2711
2712template <>
2713inline bool NumericT<short>::isNotWeakEqual(const short first, const short second)
2714{
2715 return first != second;
2716}
2717
2718template <>
2719inline bool NumericT<unsigned short>::isNotWeakEqual(const unsigned short first, const unsigned short second)
2720{
2721 return first != second;
2722}
2723
2724template <>
2725inline bool NumericT<int>::isNotWeakEqual(const int first, const int second)
2726{
2727 return first != second;
2728}
2729
2730template <>
2731inline bool NumericT<unsigned int>::isNotWeakEqual(const unsigned int first, const unsigned int second)
2732{
2733 return first != second;
2734}
2735
2736template <>
2737inline bool NumericT<long>::isNotWeakEqual(const long first, const long second)
2738{
2739 return first != second;
2740}
2741
2742template <>
2743inline bool NumericT<unsigned long>::isNotWeakEqual(const unsigned long first, const unsigned long second)
2744{
2745 return first != second;
2746}
2747
2748template <>
2749inline bool NumericT<long long>::isNotWeakEqual(const long long first, const long long second)
2750{
2751 return first != second;
2752}
2753
2754template <>
2755inline bool NumericT<unsigned long long>::isNotWeakEqual(const unsigned long long first, const unsigned long long second)
2756{
2757 return first != second;
2758}
2759
2760template <typename T>
2761inline bool NumericT<T>::isNotWeakEqual(const std::complex<T>& first, const std::complex<T>& second)
2762{
2763 return isNotWeakEqual(first.real(), second.real()) || isNotWeakEqual(first.imag(), second.imag());
2764}
2765
2766template <typename T>
2767inline bool NumericT<T>::isNotEqual(const T first, const T second, const T epsilon)
2768{
2769 ocean_assert(epsilon >= 0);
2770 return fabs(first - second) > epsilon;
2771}
2772
2773template <>
2774inline bool NumericT<signed char>::isNotEqual(const signed char first, const signed char second, const signed char epsilon)
2775{
2776 ocean_assert(epsilon >= (signed char)(0));
2777 return std::abs(first - second) > epsilon;
2778}
2779
2780template <>
2781inline bool NumericT<short>::isNotEqual(const short first, const short second, const short epsilon)
2782{
2783 ocean_assert(epsilon >= short(0));
2784 return std::abs(first - second) > epsilon;
2785}
2786
2787template <>
2788inline bool NumericT<int>::isNotEqual(const int first, const int second, const int epsilon)
2789{
2790 ocean_assert(epsilon >= 0);
2791 return std::abs(first - second) > epsilon;
2792}
2793
2794template <>
2795inline bool NumericT<long>::isNotEqual(const long first, const long second, const long epsilon)
2796{
2797 ocean_assert(epsilon >= long(0));
2798 return std::abs(first - second) > epsilon;
2799}
2800
2801template <>
2802inline bool NumericT<long long>::isNotEqual(const long long first, const long long second, const long long epsilon)
2803{
2804 ocean_assert(epsilon >= 0ll);
2805 return std::abs(first - second) > epsilon;
2806}
2807
2808template <>
2809inline bool NumericT<unsigned char>::isNotEqual(const unsigned char first, const unsigned char second, const unsigned char epsilon)
2810{
2811 if (first > second)
2812 {
2813 return first - second > epsilon;
2814 }
2815 else
2816 {
2817 return second - first > epsilon;
2818 }
2819}
2820
2821template <>
2822inline bool NumericT<unsigned short>::isNotEqual(const unsigned short first, const unsigned short second, const unsigned short epsilon)
2823{
2824 if (first > second)
2825 {
2826 return first - second > epsilon;
2827 }
2828 else
2829 {
2830 return second - first > epsilon;
2831 }
2832}
2833
2834template <>
2835inline bool NumericT<unsigned int>::isNotEqual(const unsigned int first, const unsigned int second, const unsigned int epsilon)
2836{
2837 if (first > second)
2838 {
2839 return first - second > epsilon;
2840 }
2841 else
2842 {
2843 return second - first > epsilon;
2844 }
2845}
2846
2847template <>
2848inline bool NumericT<unsigned long>::isNotEqual(const unsigned long first, const unsigned long second, const unsigned long epsilon)
2849{
2850 if (first > second)
2851 {
2852 return first - second > epsilon;
2853 }
2854 else
2855 {
2856 return second - first > epsilon;
2857 }
2858}
2859
2860template <>
2861inline bool NumericT<unsigned long long>::isNotEqual(const unsigned long long first, const unsigned long long second, const unsigned long long epsilon)
2862{
2863 if (first > second)
2864 {
2865 return first - second > epsilon;
2866 }
2867 else
2868 {
2869 return second - first > epsilon;
2870 }
2871}
2872
2873template <typename T>
2874inline bool NumericT<T>::isNotEqual(const std::complex<T>& first, const std::complex<T>& second, const T epsilon)
2875{
2876 ocean_assert(epsilon >= 0);
2877 return isNotEqual(first.real(), second.real(), epsilon) || isNotEqual(first.imag(), second.imag(), epsilon);
2878}
2879
2880template <typename T>
2881constexpr bool NumericT<T>::isInsideRange(const T lower, const T value, const T upper, const T epsilon)
2882{
2883 ocean_assert(lower <= upper);
2884 ocean_assert(epsilon >= T(0));
2885
2886 return value >= lower - epsilon && value <= upper + epsilon;
2887}
2888
2889template <typename T>
2890constexpr bool NumericT<T>::isInsideWeakRange(const T lower, const T value, const T upper)
2891{
2892 return isInsideRange(lower, value, upper, weakEps());
2893}
2894
2895template <typename T>
2896inline T NumericT<T>::asin(const T value)
2897{
2898 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2899
2900 return ::asin(max(T(-1), min(T(1), value)));
2901}
2902
2903/**
2904 * Specialization of NumericT::asin().
2905 * @see NumericT::asin().
2906 */
2907template <>
2908inline float NumericT<float>::asin(const float value)
2909{
2910 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2911
2912 return asinf(max(-1.0f, min(1.0f, value)));
2913}
2914
2915template <typename T>
2916inline T NumericT<T>::acos(const T value)
2917{
2918 ocean_assert(NumericT<T>::isInsideWeakRange(T(-1), value, T(1)));
2919
2920 return ::acos(max(T(-1), min(T(1), value)));
2921}
2922
2923/**
2924 * Specialization of NumericT::acos().
2925 * @see NumericT::acos().
2926 */
2927template <>
2928inline float NumericT<float>::acos(const float value)
2929{
2930 ocean_assert(NumericT<float>::isInsideWeakRange(-1.0f, value, 1.0f));
2931
2932 return acosf(max(-1.0f, min(1.0f, value)));
2933}
2934
2935template <typename T>
2936constexpr bool NumericT<T>::isBelow(const T value, const T upper, const T epsilon)
2937{
2938 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2939
2940 ocean_assert(epsilon >= T(0));
2941
2942 return value <= upper + epsilon;
2943}
2944
2945template <typename T>
2946constexpr bool NumericT<T>::isAbove(const T value, const T lower, const T epsilon)
2947{
2948 static_assert(std::is_floating_point<T>::value, "Invalid data type!");
2949
2950 ocean_assert(epsilon >= T(0));
2951
2952 return lower - epsilon <= value;
2953}
2954
2955template <typename T>
2956constexpr inline T NumericT<T>::nan()
2957{
2958 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
2959
2960 if constexpr (std::is_same<T, float>::value)
2961 {
2962 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
2963
2964 constexpr uint32_t integerValue = 0x7FC00000u;
2965
2966 float floatValue = 0.0f;
2967 memcpy(&floatValue, &integerValue, sizeof(integerValue));
2968
2969 return T(floatValue);
2970 }
2971 else
2972 {
2973 static_assert(std::is_same<T, double>::value, "Invalid data type!");
2974 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
2975
2976 constexpr uint64_t integerValue = 0x7FF8000000000000ull;
2977
2978 double doubleValue = 0.0;
2979 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
2980
2981 return T(doubleValue);
2982 }
2983}
2984
2985template <>
2986inline bool NumericT<float>::isNan(const float value)
2987{
2988 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
2989 // thus implementing a custom check
2990
2991 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
2992
2993 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
2994
2995 uint32_t tmpValue;
2996 memcpy(&tmpValue, &value, sizeof(tmpValue));
2997
2998 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
2999 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
3000
3001 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3002 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0u;
3003
3004 return allExponentBitsAreOne && mantissaIsNotZero;
3005}
3006
3007template <>
3008inline bool NumericT<double>::isNan(const double value)
3009{
3010 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3011 // thus implementing a custom check
3012
3013 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3014
3015 // IEEE 754: all exponents are encoded as 1, and the mantissa is not zero
3016
3017 uint64_t tmpValue;
3018 memcpy(&tmpValue, &value, sizeof(tmpValue));
3019
3020 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3021 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3022
3023 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3024 const bool mantissaIsNotZero = (tmpValue & mantissaBitsAllOne) != 0ull;
3025
3026 return allExponentBitsAreOne && mantissaIsNotZero;
3027}
3028
3029template <typename T>
3030inline bool NumericT<T>::isNan(const T /*value*/)
3031{
3032 // with compiler optimizations, `std::isnan()` will not work anymore (the compiler simply skips the check),
3033 // thus implementing a custom check
3034
3035 ocean_assert(std::is_floating_point<T>::value == false);
3036 return false;
3037}
3038
3039template <typename T>
3040inline bool NumericT<T>::isNan(const std::complex<T>& value)
3041{
3042 return NumericT<T>::isNan(value.real()) || NumericT<T>::isNan(value.imag());
3043}
3044
3045template <typename T>
3046constexpr inline T NumericT<T>::inf()
3047{
3048 static_assert(std::is_floating_point<T>::value, "Data type must be a floating point data type");
3049
3050 if constexpr (std::is_same<T, float>::value)
3051 {
3052 static_assert(sizeof(float) == sizeof(uint32_t), "Invalid data type!");
3053
3054 constexpr uint32_t integerValue = 0x7F800000u;
3055
3056 float floatValue = 0.0f;
3057 memcpy(&floatValue, &integerValue, sizeof(integerValue));
3058
3059 return T(floatValue);
3060 }
3061 else
3062 {
3063 static_assert(std::is_same<T, double>::value, "Invalid data type!");
3064 static_assert(sizeof(double) == sizeof(uint64_t), "Invalid data type!");
3065
3066 constexpr uint64_t integerValue = 0x7FF0000000000000ull;
3067
3068 double doubleValue = 0.0;
3069 memcpy(&doubleValue, &integerValue, sizeof(integerValue));
3070
3071 return T(doubleValue);
3072 }
3073}
3074
3075template <>
3076inline bool NumericT<float>::isInf(const float value)
3077{
3078 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3079 // thus implementing a custom check
3080
3081 static_assert(sizeof(uint32_t) == sizeof(value), "Invalid value!");
3082
3083 // IEEE 754: all exponents are encoded as 1, and the mantissa is zero
3084
3085 uint32_t tmpValue;
3086 memcpy(&tmpValue, &value, sizeof(tmpValue));
3087
3088 constexpr uint32_t exponentBitsAllOne = 0x7F800000u;
3089 constexpr uint32_t mantissaBitsAllOne = 0x007FFFFFu;
3090
3091 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3092 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0u;
3093
3094 return allExponentBitsAreOne && allMantissaBitsAreZero;
3095}
3096
3097template <>
3098inline bool NumericT<double>::isInf(const double value)
3099{
3100 // with compiler optimizations, `std::isInf()` will not work anymore (the compiler simply skips the check),
3101 // thus implementing a custom check
3102
3103 static_assert(sizeof(uint64_t) == sizeof(value), "Invalid value!");
3104
3105 // IEEE 754: all exponents are encoded as 1, and the mantissa is zero
3106
3107 uint64_t tmpValue;
3108 memcpy(&tmpValue, &value, sizeof(tmpValue));
3109
3110 constexpr uint64_t exponentBitsAllOne = 0x7FF0000000000000ull;
3111 constexpr uint64_t mantissaBitsAllOne = 0x000FFFFFFFFFFFFFull;
3112
3113 const bool allExponentBitsAreOne = (tmpValue & exponentBitsAllOne) == exponentBitsAllOne;
3114 const bool allMantissaBitsAreZero = (tmpValue & mantissaBitsAllOne) == 0ull;
3115
3116 return allExponentBitsAreOne && allMantissaBitsAreZero;
3117}
3118
3119template <typename T>
3120inline bool NumericT<T>::isInf(const T /*value*/)
3121{
3122 // with compiler optimizations, `std::isinf()` will not work anymore (the compiler simply skips the check),
3123 // thus implementing a custom check
3124
3125 ocean_assert(std::is_floating_point<T>::value == false);
3126 return false;
3127}
3128
3129template <>
3130inline bool NumericT<long double>::isInf(const long double value)
3131{
3132 return std::isinf(value);
3133}
3134
3135template <typename T>
3136inline bool NumericT<T>::isInf(const std::complex<T>& value)
3137{
3138 return NumericT<T>::isInf(value.real()) || NumericT<T>::isInf(value.imag());
3139}
3140
3141template <typename T>
3142template <typename TValue>
3143inline bool NumericT<T>::isInsideValueRange(const TValue& value)
3144{
3145 if constexpr (std::is_same<T, TValue>::value)
3146 {
3147 // e.g., [int8_t, int8_t], [uint8_t, uint8_t], [float, float], ...
3148
3149 return true;
3150 }
3151
3152 if constexpr (std::is_floating_point<T>::value && std::is_floating_point<TValue>::value)
3153 {
3154 // either [float, double], or [double, float]
3155
3156 // float/double values fit in each other (however, may be casted to inf)
3157
3158 return true;
3159 }
3160
3161 if constexpr (std::is_integral<T>::value && std::is_integral<TValue>::value)
3162 {
3163 // e.g., int8_t, uint8_t, int16_t, ...
3164
3165 if constexpr (std::is_signed<T>::value == std::is_signed<TValue>::value)
3166 {
3167 // e.g., [int8_t, int16_t], [int16_t, int8_t], [int32_t, int64_t], ...
3168
3169 if constexpr (sizeof(TValue) <= sizeof(T))
3170 {
3171 // e.g., [int16_t, int8_t], [uint64_t, uint8_t], ...
3172
3173 return true;
3174 }
3175 else
3176 {
3177 ocean_assert(sizeof(T) < sizeof(TValue));
3178
3179 // e.g., [int8_t, int16_t], [uint8_t, uint64_t], ...
3180
3181 return TValue(NumericT<T>::minValue()) <= value && value <= TValue(NumericT<T>::maxValue());
3182 }
3183 }
3184
3185 if constexpr (std::is_signed<T>::value)
3186 {
3187 ocean_assert(!std::is_signed<TValue>::value);
3188
3189 // e.g., [int8_t, uint8_t], [int32_t, uint8_t], [int64_t, uint16_t], [int8_t, uint64_t], ...
3190
3191 if constexpr (sizeof(TValue) < sizeof(T))
3192 {
3193 // e.g., [int16_t, uint8_t], [int64_t, uint16_t], ...
3194
3195 return true;
3196 }
3197
3198 // e.g., [int8_t, uint8_t], [int8_t, uint32_t], ...
3199
3200 return value <= TValue(NumericT<T>::maxValue());
3201 }
3202
3203 if constexpr (std::is_signed<TValue>::value)
3204 {
3205 ocean_assert(!std::is_signed<T>::value);
3206
3207 // e.g., [uint8_t, int8_t], [uint32_t, int8_t], [uint64_t, int16_t], [uint8_t, int64_t], ...
3208
3209 if (value < TValue(0))
3210 {
3211 return false;
3212 }
3213
3214 if constexpr (sizeof(TValue) < sizeof(T))
3215 {
3216 // e.g., [uint16_t, int8_t], [uint_64_t, int16_t], ...
3217
3218 return true;
3219 }
3220 else if constexpr (sizeof(TValue) == sizeof(T))
3221 {
3222 // e.g., [uint8_t, int8_t], [uint32_t, int32_t], [uint64_t, int64_t], ...
3223
3224 ocean_assert(value >= TValue(0));
3225
3226 return true;
3227 }
3228
3229 // e.g., [uint8_t, int16_t], [uint32_t, int64_t], ...
3230
3231 ocean_assert(value >= TValue(0));
3232
3233 return value <= TValue(NumericT<T>::maxValue());
3234 }
3235 }
3236
3237 return false;
3238}
3239
3240template <typename T>
3241constexpr inline T NumericT<T>::deg2rad(const T deg)
3242{
3243 return deg * T(0.017453292519943295769236907684886);
3244}
3245
3246template <typename T>
3247constexpr inline T NumericT<T>::rad2deg(const T rad)
3248{
3249 return rad * T(57.295779513082320876798154814105);
3250}
3251
3252template <typename T>
3253constexpr inline T NumericT<T>::maxValue()
3254{
3255 return std::numeric_limits<T>::max();
3256}
3257
3258template <typename T>
3259constexpr inline T NumericT<T>::minValue()
3260{
3261 return std::numeric_limits<T>::lowest();
3262}
3263
3264template <typename T>
3265constexpr inline T NumericT<T>::sign(const T& value)
3266{
3267 static_assert(std::numeric_limits<T>::is_signed, "T must be a signed data type!");
3268
3269 return T((T(0) < value) - (value < T(0)));
3270}
3271
3272template <typename T>
3273constexpr inline T NumericT<T>::copySign(const T signReceiver, const T signProvider)
3274{
3275 if (signProvider >= 0)
3276 {
3277 return abs(signReceiver);
3278 }
3279
3280 return -abs(signReceiver);
3281}
3282
3283#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3284
3285/**
3286 * Specialization of NumericT::copySign().
3287 * @see NumericT::copySign().
3288 */
3289template <>
3290constexpr inline double NumericT<double>::copySign(const double first, const double second)
3291{
3292 const uint64_t value = ((*(uint64_t*)&first) & 0x7FFFFFFFFFFFFFFFull)
3293 | ((*(uint64_t*)&second) & 0x8000000000000000ull);
3294
3295#ifdef OCEAN_DEBUG
3296
3297 ocean_assert(sizeof(uint64_t) == sizeof(double));
3298
3299 const double result = *(double*)(&value);
3300
3301 double testValue = 0;
3302
3303 if (second >= 0.0)
3304 {
3305 testValue = NumericT<double>::abs(first);
3306 }
3307 else
3308 {
3309 testValue = -NumericT<double>::abs(first);
3310 }
3311
3312 ocean_assert(result == testValue || second == 0.0);
3313
3314#endif
3315
3316 return *(double*)&value;
3317}
3318
3319/**
3320 * Specialization of NumericT::copySign().
3321 * @see NumericT::copySign().
3322 */
3323template <>
3324constexpr inline float NumericT<float>::copySign(const float first, const float second)
3325{
3326 const uint32_t value = ((*(uint32_t*)&first) & 0x7FFFFFFFu) | ((*(uint32_t*)&second) & 0x80000000u);
3327
3328#ifdef OCEAN_DEBUG
3329
3330 ocean_assert(sizeof(uint32_t) == sizeof(float));
3331
3332 const float result = *(float*)(&value);
3333
3334 float testValue = 0;
3335
3336 if (second >= 0.0f)
3337 {
3338 testValue = NumericT<float>::abs(first);
3339 }
3340 else
3341 {
3342 testValue = -NumericT<float>::abs(first);
3343 }
3344
3345 ocean_assert(result == testValue || second == 0.0);
3346
3347#endif
3348
3349 return *(float*)&value;
3350}
3351
3352#endif // #if 0
3353
3354template <typename T>
3355constexpr inline T NumericT<T>::invertSign(const T signReceiver, const T signProvider)
3356{
3357 if (signProvider < 0)
3358 {
3359 return abs(signReceiver);
3360 }
3361
3362 return -abs(signReceiver);
3363}
3364
3365#if 0 // although the following code is a create optimization, we do not use it to avoid strict-aliasing compiler warnings
3366
3367/**
3368 * Specialization of NumericT::invertSign().
3369 * @see NumericT::invertedSign().
3370 */
3371template <>
3372constexpr inline double NumericT<double>::invertSign(const double first, const double second)
3373{
3374 const uint64_t value = ((*(uint64_t*)&first) & 0x7FFFFFFFFFFFFFFFull)
3375 | ((~*(uint64_t*)&second) & 0x8000000000000000ull);
3376
3377#ifdef OCEAN_DEBUG
3378
3379 ocean_assert(sizeof(uint64_t) == sizeof(double));
3380
3381 const double result = *(double*)&value;
3382
3383 double testValue = 0;
3384
3385 if (second < 0)
3386 {
3387 testValue = NumericT<double>::abs(first);
3388 }
3389 else
3390 {
3391 testValue = -NumericT<double>::abs(first);
3392 }
3393
3394 ocean_assert(result == testValue);
3395
3396#endif
3397
3398
3399 return *(double*)&value;
3400}
3401
3402/**
3403 * Specialization of NumericT::invertSign().
3404 * @see NumericT::invertSign().
3405 */
3406template <>
3407constexpr inline float NumericT<float>::invertSign(const float first, const float second)
3408{
3409 const uint32_t value = ((*(uint32_t*)&first) & 0x7FFFFFFFu) | ((~*(uint32_t*)&second) & 0x80000000u);
3410
3411#ifdef OCEAN_DEBUG
3412
3413 ocean_assert(sizeof(uint32_t) == sizeof(float));
3414
3415 const float result = *(float*)&value;
3416
3417 double testValue = 0;
3418
3419 if (second < 0)
3420 {
3421 testValue = NumericT<float>::abs(first);
3422 }
3423 else
3424 {
3425 testValue = -NumericT<float>::abs(first);
3426 }
3427
3428 ocean_assert(result == testValue);
3429
3430#endif
3431
3432 return *(float*)&value;
3433}
3434
3435#endif // #if 0
3436
3437template <typename T>
3438T NumericT<T>::pythagoras(const T a, const T b)
3439{
3440 const T absA = NumericT<T>::abs(a);
3441 const T absB = NumericT<T>::abs(b);
3442
3443 if (absA > absB)
3444 {
3445 const T factor = absB / absA;
3446 return absA * sqrt(1 + factor * factor);
3447 }
3448 else if (absB != 0)
3449 {
3450 const T factor = absA / absB;
3451 return absB * sqrt(1 + factor * factor);
3452 }
3453
3454 return 0;
3455}
3456
3457template <typename T>
3458inline T NumericT<T>::gaussianDistribution(const T x, const T sigma)
3459{
3460 ocean_assert(sigma > eps());
3461
3462 const T inverseSigma = T(1) / sigma;
3463
3464 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3465}
3466
3467template <typename T>
3468inline T NumericT<T>::gaussianDistribution(const T x, const T x0, const T sigma)
3469{
3470 ocean_assert(sigma > eps());
3471
3472 const T inverseSigma = T(1) / sigma;
3473 const T x_x0 = x - x0;
3474
3475 return inverseSigma * T(0.3989422804014326779) * NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3476}
3477
3478template <typename T>
3479inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T sigma)
3480{
3481 ocean_assert(sigma > eps());
3482
3483 const T inverseSigma = T(1) / sigma;
3484
3485 return NumericT<T>::exp(T(-0.5) * x * x * inverseSigma * inverseSigma);
3486}
3487
3488template <typename T>
3489inline T NumericT<T>::normalizedGaussianDistribution(const T x, const T x0, const T sigma)
3490{
3491 ocean_assert(sigma > eps());
3492
3493 const T inverseSigma = T(1) / sigma;
3494 const T x_x0 = x - x0;
3495
3496 return NumericT<T>::exp(T(-0.5) * x_x0 * x_x0 * inverseSigma * inverseSigma);
3497}
3498
3499template <typename T>
3500inline T NumericT<T>::gaussianDistribution2(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 inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3508}
3509
3510template <typename T>
3511inline T NumericT<T>::gaussianDistribution2(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 inverseSigmaX * inverseSigmaY * T(0.15915494309189533576888) * 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>::normalizedGaussianDistribution2(const T x, const T y, const T sigmaX, const T sigmaY)
3526{
3527 ocean_assert(sigmaX > eps() && sigmaY > eps());
3528
3529 const T inverseSigmaX = T(1) / sigmaX;
3530 const T inverseSigmaY = T(1) / sigmaY;
3531
3532 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY));
3533}
3534
3535template <typename T>
3536inline T NumericT<T>::normalizedGaussianDistribution2(const T x, const T y, const T x0, const T y0, const T sigmaX, const T sigmaY)
3537{
3538 ocean_assert(sigmaX > eps() && sigmaY > eps());
3539
3540 const T inverseSigmaX = T(1) / sigmaX;
3541 const T inverseSigmaY = T(1) / sigmaY;
3542
3543 const T x_x0 = x - x0;
3544 const T y_y0 = y - y0;
3545
3546 return NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY));
3547}
3548
3549template <typename T>
3550inline T NumericT<T>::gaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3551{
3552 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3553
3554 const T inverseSigmaX = T(1) / sigmaX;
3555 const T inverseSigmaY = T(1) / sigmaY;
3556 const T inverseSigmaZ = T(1) / sigmaZ;
3557
3558 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3559 * NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3560}
3561
3562template <typename T>
3563inline 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)
3564{
3565 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3566
3567 const T inverseSigmaX = T(1) / sigmaX;
3568 const T inverseSigmaY = T(1) / sigmaY;
3569 const T inverseSigmaZ = T(1) / sigmaZ;
3570
3571 const T x_x0 = x - x0;
3572 const T y_y0 = y - y0;
3573 const T z_z0 = z - z0;
3574
3575 return inverseSigmaX * inverseSigmaY * inverseSigmaZ * T(0.06349363593424096978576330493464)
3576 * NumericT<T>::exp(T(-0.5) * (x_x0 * x_x0 * inverseSigmaX * inverseSigmaX + y_y0 * y_y0 * inverseSigmaY * inverseSigmaY + z_z0 * z_z0 * inverseSigmaZ * inverseSigmaZ));
3577}
3578
3579template <typename T>
3580inline T NumericT<T>::normalizedGaussianDistribution3(const T x, const T y, const T z, const T sigmaX, const T sigmaY, const T sigmaZ)
3581{
3582 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3583
3584 const T inverseSigmaX = T(1) / sigmaX;
3585 const T inverseSigmaY = T(1) / sigmaY;
3586 const T inverseSigmaZ = T(1) / sigmaZ;
3587
3588 return NumericT<T>::exp(T(-0.5) * (x * x * inverseSigmaX * inverseSigmaX + y * y * inverseSigmaY * inverseSigmaY + z * z * inverseSigmaZ * inverseSigmaZ));
3589}
3590
3591template <typename T>
3592inline 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)
3593{
3594 ocean_assert(sigmaX > eps() && sigmaY > eps() && sigmaZ > eps());
3595
3596 const T inverseSigmaX = T(1) / sigmaX;
3597 const T inverseSigmaY = T(1) / sigmaY;
3598 const T inverseSigmaZ = T(1) / sigmaZ;
3599
3600 const T x_x0 = x - x0;
3601 const T y_y0 = y - y0;
3602 const T z_z0 = z - z0;
3603
3604 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));
3605}
3606
3607}
3608
3609#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:1770
static constexpr T deg2rad(const T deg)
Converts deg to rad.
Definition Numeric.h:3241
static constexpr bool isNotWeakEqualEps(const T value)
Returns whether a value is not smaller than or equal to a weak epsilon.
Definition Numeric.h:2321
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3259
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:3265
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:2881
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:1659
static T exp(const T value)
Returns the base-e exponential function of a given value.
Definition Numeric.h:1647
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:1673
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:1620
static T atan2(const T y, const T x)
Returns the arctangent of a given value in radian.
Definition Numeric.h:1636
static constexpr T sqrDistance(const T value0, const T value1)
Returns the square distance between two values.
Definition Numeric.h:1531
static T sin(const T value)
Returns the sine of a given value.
Definition Numeric.h:1572
static bool isInf(const T value)
Returns whether a given value is positive or negative infinity.
Definition Numeric.h:3120
static T pow(const T x, const T y)
Returns x raised to the power of y.
Definition Numeric.h:1866
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:3030
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:1894
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:1715
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:2946
static bool isWeakEqual(const T first, const T second)
Returns whether two values a equal up to a weak epsilon.
Definition Numeric.h:2581
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:3479
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition Numeric.h:2073
static T sum(const T *values, const size_t number)
Returns the sum of given values.
Definition Numeric.h:1505
static constexpr bool isWeakEqualEps(const T value)
Returns whether a value is smaller than or equal to a weak epsilon.
Definition Numeric.h:2171
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1537
static T pythagoras(const T a, const T b)
Returns the length of the hypotenuse of a given right-angled triangle.
Definition Numeric.h:3438
static T fmod(const T valueA, const T valueB)
Returns the floating-point remainder of a given value.
Definition Numeric.h:1741
static T angleAdjustNull(const T angle)
Adjusts an arbitrary angle into the range of (-PI, PI].
Definition Numeric.h:1800
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:1844
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:2395
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:2936
static T gaussianDistribution(const T x, const T sigma)
Returns a value of the univariate Gaussian distribution centered around the origin.
Definition Numeric.h:3458
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:3500
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:2085
static constexpr T nan()
Returns a value which is not a number (nan).
Definition Numeric.h:2956
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:2035
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:1888
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:1604
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:3580
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:1997
static constexpr int64_t round64(const T value)
Returns the rounded 64 bit integer value of a given value.
Definition Numeric.h:2079
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:1825
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:1499
static T angleAdjustPositiveHalf(const T angle)
Adjusts an arbitrary angle into the range of [0.0, PI).
Definition Numeric.h:1785
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:2890
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:3525
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
static constexpr T copySign(const T signReceiver, const T signProvider)
Copies the sign of a given value to another one.
Definition Numeric.h:3273
static constexpr T rad2deg(const T rad)
Converts rad to deg.
Definition Numeric.h:3247
static T cos(const T value)
Returns the cosine of a given value.
Definition Numeric.h:1588
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:3550
static T dot(const T *vectorA, const T *vectorB, const size_t size)
Returns the dot product for two vectors.
Definition Numeric.h:1757
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:3143
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2916
static constexpr T invertSign(const T signReceiver, const T signProvider)
Copies the inverted sign of a given value to another one.
Definition Numeric.h:3355
static constexpr T inf()
Returns a value which is positive infinity.
Definition Numeric.h:3046
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2246
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:1831
static T angleDistance(const T angleA, const T angleB)
Returns the angular difference (distance between two angles).
Definition Numeric.h:1852
static bool isNotEqual(const T first, const T second)
Returns whether two values are not equal up to a small epsilon.
Definition Numeric.h:2622
static T summedSqr(const T *values, const size_t number)
Returns the summed squares of a given values.
Definition Numeric.h:1518
static T log2(const T value)
Returns the logarithm to base 2 of a given value.
Definition Numeric.h:1687
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3253
static T asin(const T value)
Returns the arcsine of a given value.
Definition Numeric.h:2896
static bool isNotWeakEqual(const T first, const T second)
Returns whether two values are not equal up to a weak epsilon.
Definition Numeric.h:2695
static constexpr T binomialCoefficient(const T &n, const T &k)
Returns the binomial coefficient for two binomial parameters.
Definition Numeric.h:1966
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:1099
The namespace covering the entire Ocean framework.
Definition Accessor.h:15