OpenVDB 13.0.1
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3//
4/// @file Math.h
5/// @brief General-purpose arithmetic and comparison routines, most of which
6/// accept arbitrary value types (or at least arbitrary numeric value types)
7
8#ifndef OPENVDB_MATH_HAS_BEEN_INCLUDED
9#define OPENVDB_MATH_HAS_BEEN_INCLUDED
10
11#include <openvdb/Platform.h>
12#include <openvdb/version.h>
14#include <openvdb/util/Assert.h>
15#include <algorithm> // for std::max()
16#include <cassert>
17#include <cmath> // for std::ceil(), std::fabs(), std::pow(), std::sqrt(), etc.
18#include <cstdlib> // for abs(int)
19#include <cstring> // for memcpy
20#include <random>
21#include <string>
22#include <type_traits> // for std::is_arithmetic
23
24
25// Compile pragmas
26
27// Intel(r) compiler fires remark #1572: floating-point equality and inequality
28// comparisons are unrealiable when == or != is used with floating point operands.
29#if defined(__INTEL_COMPILER)
30 #define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN \
31 _Pragma("warning (push)") \
32 _Pragma("warning (disable:1572)")
33 #define OPENVDB_NO_FP_EQUALITY_WARNING_END \
34 _Pragma("warning (pop)")
35#elif defined(__clang__)
36 #define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN \
37 PRAGMA(clang diagnostic push) \
38 PRAGMA(clang diagnostic ignored "-Wfloat-equal")
39 #define OPENVDB_NO_FP_EQUALITY_WARNING_END \
40 PRAGMA(clang diagnostic pop)
41#else
42 // For GCC, #pragma GCC diagnostic ignored "-Wfloat-equal"
43 // isn't working until gcc 4.2+,
44 // Trying
45 // #pragma GCC system_header
46 // creates other problems, most notably "warning: will never be executed"
47 // in from templates, unsure of how to work around.
48 // If necessary, could use integer based comparisons for equality
49 #define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
50 #define OPENVDB_NO_FP_EQUALITY_WARNING_END
51#endif
52
53
54#ifdef OPENVDB_IS_POD
55#undef OPENVDB_IS_POD
56#endif
57#define OPENVDB_IS_POD(Type) \
58static_assert(std::is_standard_layout<Type>::value, \
59 #Type" must be a POD type (satisfy StandardLayoutType.)"); \
60static_assert(std::is_trivial<Type>::value, \
61 #Type" must be a POD type (satisfy TrivialType.)");
62
63namespace openvdb {
65namespace OPENVDB_VERSION_NAME {
66
67/// @brief Return the value of type T that corresponds to zero.
68/// @note A zeroVal<T>() specialization must be defined for each @c ValueType T
69/// that cannot be constructed using the form @c T(0). For example, @c std::string(0)
70/// treats 0 as @c nullptr and throws a @c std::logic_error.
71template<typename T> inline constexpr T zeroVal() { return T(0); }
72/// Return the @c std::string value that corresponds to zero.
73template<> inline std::string zeroVal<std::string>() { return ""; }
74/// Return the @c bool value that corresponds to zero.
75template<> inline constexpr bool zeroVal<bool>() { return false; }
76
77
78/// @note Extends the implementation of std::is_arithmetic to support math::half
79template<typename T>
80struct is_arithmetic : std::is_arithmetic<T> {};
81template<>
82struct is_arithmetic<math::half> : std::true_type {};
83// Helper variable template (equivalent to std::is_arithmetic_v)
84template<typename T>
86
87namespace math {
88
89/// @todo These won't be needed if we eliminate StringGrids.
90//@{
91/// @brief Needed to support the <tt>(zeroVal<ValueType>() + val)</tt> idiom
92/// when @c ValueType is @c std::string
93inline std::string operator+(const std::string& s, bool) { return s; }
94inline std::string operator+(const std::string& s, int) { return s; }
95inline std::string operator+(const std::string& s, float) { return s; }
96inline std::string operator+(const std::string& s, double) { return s; }
97//@}
98
99/// @brief Componentwise adder for POD types.
100template<typename Type1, typename Type2>
101inline auto cwiseAdd(const Type1& v, const Type2 s)
102{
104 return v + s;
106}
107
108/// @brief Componentwise less than for POD types.
109template<typename Type1, typename Type2>
110inline bool cwiseLessThan(const Type1& a, const Type2& b)
111{
113 return a < b;
115}
116
117/// @brief Componentwise greater than for POD types.
118template<typename Type1, typename Type2>
119inline bool cwiseGreaterThan(const Type1& a, const Type2& b)
120{
122 return a > b;
124}
125
126
127
128/// @brief Pi constant taken from Boost to match old behaviour
129/// @note Available in C++20
130template <typename T> inline constexpr T pi() { return 3.141592653589793238462643383279502884e+00; }
131template <> inline constexpr float pi() { return 3.141592653589793238462643383279502884e+00F; }
132template <> inline constexpr double pi() { return 3.141592653589793238462643383279502884e+00; }
133template <> inline constexpr long double pi() { return 3.141592653589793238462643383279502884e+00L; }
134
135
136/// @brief Return the unary negation of the given value.
137/// @note A negative<T>() specialization must be defined for each ValueType T
138/// for which unary negation is not defined.
139template<typename T> inline T negative(const T& val)
140{
141// disable unary minus on unsigned warning
142#if defined(_MSC_VER)
143#pragma warning(push)
144#pragma warning(disable:4146)
145#endif
146 return T(-val);
147#if defined(_MSC_VER)
148#pragma warning(pop)
149#endif
150}
151/// Return the negation of the given boolean.
152template<> inline bool negative(const bool& val) { return !val; }
153/// Return the "negation" of the given string.
154template<> inline std::string negative(const std::string& val) { return val; }
155
156
157//@{
158/// Tolerance for floating-point comparison
159template<typename T> struct Tolerance { static T value() { return zeroVal<T>(); } };
160template<> struct Tolerance<math::half> { static math::half value() { return math::half(0.00097656f); } };
161template<> struct Tolerance<float> { static float value() { return 1e-8f; } };
162template<> struct Tolerance<double> { static double value() { return 1e-15; } };
163//@}
164
165//@{
166/// Delta for small floating-point offsets
167template<typename T> struct Delta { static T value() { return zeroVal<T>(); } };
168template<> struct Delta<math::half> { static math::half value() { return math::half(0.00390625f); } };
169template<> struct Delta<float> { static float value() { return 1e-5f; } };
170template<> struct Delta<double> { static double value() { return 1e-9; } };
171//@}
172
173
174// ==========> Random Values <==================
175
176/// @brief Simple generator of random numbers over the range [0, 1)
177/// @details Thread-safe as long as each thread has its own Rand01 instance
178template<typename FloatType = double, typename EngineType = std::mt19937>
180{
181private:
182 EngineType mEngine;
183 std::uniform_real_distribution<FloatType> mRand;
184
185public:
186 using ValueType = FloatType;
187
188 /// @brief Initialize the generator.
189 /// @param engine random number generator
190 Rand01(const EngineType& engine): mEngine(engine) {}
191
192 /// @brief Initialize the generator.
193 /// @param seed seed value for the random number generator
194 Rand01(unsigned int seed): mEngine(static_cast<typename EngineType::result_type>(seed)) {}
195
196 /// Set the seed value for the random number generator
197 void setSeed(unsigned int seed)
198 {
199 mEngine.seed(static_cast<typename EngineType::result_type>(seed));
200 }
201
202 /// Return a const reference to the random number generator.
203 const EngineType& engine() const { return mEngine; }
204
205 /// Return a uniformly distributed random number in the range [0, 1).
206 FloatType operator()() { return mRand(mEngine); }
207};
208
210
211
212/// @brief Simple random integer generator
213/// @details Thread-safe as long as each thread has its own RandInt instance
214template<typename IntType = int, typename EngineType = std::mt19937>
216{
217private:
218 using Distr = std::uniform_int_distribution<IntType>;
219 EngineType mEngine;
220 Distr mRand;
221
222public:
223 /// @brief Initialize the generator.
224 /// @param engine random number generator
225 /// @param imin,imax generate integers that are uniformly distributed over [imin, imax]
226 RandInt(const EngineType& engine, IntType imin, IntType imax):
227 mEngine(engine),
228 mRand(std::min(imin, imax), std::max(imin, imax))
229 {}
230
231 /// @brief Initialize the generator.
232 /// @param seed seed value for the random number generator
233 /// @param imin,imax generate integers that are uniformly distributed over [imin, imax]
234 RandInt(unsigned int seed, IntType imin, IntType imax):
235 mEngine(static_cast<typename EngineType::result_type>(seed)),
236 mRand(std::min(imin, imax), std::max(imin, imax))
237 {}
238
239 /// Change the range over which integers are distributed to [imin, imax].
240 void setRange(IntType imin, IntType imax)
241 {
242 mRand = Distr(std::min(imin, imax), std::max(imin, imax));
243 }
244
245 /// Set the seed value for the random number generator
246 void setSeed(unsigned int seed)
247 {
248 mEngine.seed(static_cast<typename EngineType::result_type>(seed));
249 }
250
251 /// Return a const reference to the random number generator.
252 const EngineType& engine() const { return mEngine; }
253
254 /// Return a randomly-generated integer in the current range.
255 IntType operator()() { return mRand(mEngine); }
256
257 /// @brief Return a randomly-generated integer in the new range [imin, imax],
258 /// without changing the current range.
259 IntType operator()(IntType imin, IntType imax)
260 {
261 const IntType lo = std::min(imin, imax), hi = std::max(imin, imax);
262 return mRand(mEngine, typename Distr::param_type(lo, hi));
263 }
264};
265
267
268
269// ==========> Clamp <==================
270
271/// Return @a x clamped to [@a min, @a max]
272template<typename Type>
273inline Type
274Clamp(Type x, Type min, Type max)
275{
276 OPENVDB_ASSERT( !(min>max) );
277 return x > min ? x < max ? x : max : min;
278}
279
280
281/// Return @a x clamped to [0, 1]
282template<typename Type>
283inline Type
284Clamp01(Type x) { return x > Type(0) ? x < Type(1) ? x : Type(1) : Type(0); }
285
286
287/// Return @c true if @a x is outside [0,1]
288template<typename Type>
289inline bool
291{
292 if (x >= Type(0) && x <= Type(1)) return false;
293 x = x < Type(0) ? Type(0) : Type(1);
294 return true;
295}
296
297/// @brief Return 0 if @a x < @a 0, 1 if @a x > 1 or else (3 &minus; 2 @a x) @a x&sup2;.
298template<typename Type>
299inline Type
301{
302 return x > 0 ? x < 1 ? (3-2*x)*x*x : Type(1) : Type(0);
303}
304
305/// @brief Return 0 if @a x < @a min, 1 if @a x > @a max or else (3 &minus; 2 @a t) @a t&sup2;,
306/// where @a t = (@a x &minus; @a min)/(@a max &minus; @a min).
307template<typename Type>
308inline Type
309SmoothUnitStep(Type x, Type min, Type max)
310{
311 OPENVDB_ASSERT(min < max);
312 return SmoothUnitStep((x-min)/(max-min));
313}
314
315
316// ==========> Absolute Value <==================
317
318
319//@{
320/// Return the absolute value of the given quantity.
321inline int32_t Abs(int32_t i) { return std::abs(i); }
322inline int64_t Abs(int64_t i)
323{
324 static_assert(sizeof(decltype(std::abs(i))) == sizeof(int64_t),
325 "std::abs(int64) broken");
326 return std::abs(i);
327}
328inline float Abs(float x) { return std::fabs(x); }
329inline double Abs(double x) { return std::fabs(x); }
330inline long double Abs(long double x) { return std::fabs(x); }
331inline uint32_t Abs(uint32_t i) { return i; }
332inline uint64_t Abs(uint64_t i) { return i; }
333inline bool Abs(bool b) { return b; }
334// On systems like macOS and FreeBSD, size_t and uint64_t are different types
335template <typename T>
336inline typename std::enable_if<std::is_same<T, size_t>::value, T>::type
337Abs(T i) { return i; }
338//@}
339
340
341////////////////////////////////////////
342
343
344// ==========> Value Comparison <==================
345
346
347/// Return @c true if @a x is exactly equal to zero.
348template<typename Type>
349inline bool
356
357
358/// @brief Return @c true if @a x is equal to zero to within
359/// the default floating-point comparison tolerance.
360template<typename Type>
361inline bool
362isApproxZero(const Type& x)
363{
364 const Type tolerance = Type(zeroVal<Type>() + Tolerance<Type>::value());
365 return !(x > tolerance) && !(x < -tolerance);
366}
367
368/// Return @c true if @a x is equal to zero to within the given tolerance.
369template<typename Type>
370inline bool
371isApproxZero(const Type& x, const Type& tolerance)
372{
373 return !(x > tolerance) && !(x < -tolerance);
374}
375
376
377/// Return @c true if @a x is less than zero.
378template<typename Type>
379inline bool
380isNegative(const Type& x) { return x < zeroVal<Type>(); }
381
382// Return false, since bool values are never less than zero.
383template<> inline bool isNegative<bool>(const bool&) { return false; }
384
385
386/// Return @c true if @a x is finite.
387inline bool
388isFinite(const float x) { return std::isfinite(x); }
389
390/// Return @c true if @a x is finite.
391inline bool
392isFinite(const math::half x) { return x.isFinite(); }
393
394/// Return @c true if @a x is finite.
395template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
396inline bool
397isFinite(const Type& x) { return std::isfinite(static_cast<double>(x)); }
398
399
400/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
401inline bool
402isInfinite(const float x) { return std::isinf(x); }
403
404/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
405inline bool
406isInfinite(const math::half x) { return x.isInfinity(); }
407
408/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
409template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
410inline bool
411isInfinite(const Type& x) { return std::isinf(static_cast<double>(x)); }
412
413
414/// Return @c true if @a x is a NaN (Not-A-Number) value.
415inline bool
416isNan(const float x) { return std::isnan(x); }
417
418/// Return @c true if @a x is a NaN (Not-A-Number) value.
419inline bool
420isNan(const math::half x) { return x.isNan(); }
421
422/// Return @c true if @a x is a NaN (Not-A-Number) value.
423template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
424inline bool
425isNan(const Type& x) { return std::isnan(static_cast<double>(x)); }
426
427
428/// Return @c true if @a a is equal to @a b to within the given tolerance.
429template<typename Type>
430inline bool
431isApproxEqual(const Type& a, const Type& b, const Type& tolerance)
432{
433 return !cwiseGreaterThan(Abs(a - b), tolerance);
434}
435
436/// @brief Return @c true if @a a is equal to @a b to within
437/// the default floating-point comparison tolerance.
438template<typename Type>
439inline bool
440isApproxEqual(const Type& a, const Type& b)
441{
442 const Type tolerance = Type(zeroVal<Type>() + Tolerance<Type>::value());
443 return isApproxEqual(a, b, tolerance);
444}
445
446#define OPENVDB_EXACT_IS_APPROX_EQUAL(T) \
447 template<> inline bool isApproxEqual<T>(const T& a, const T& b) { return a == b; } \
448 template<> inline bool isApproxEqual<T>(const T& a, const T& b, const T&) { return a == b; } \
449 /**/
450
453
454
455/// @brief Return @c true if @a a is larger than @a b to within
456/// the given tolerance, i.e., if @a b - @a a < @a tolerance.
457template<typename Type>
458inline bool
459isApproxLarger(const Type& a, const Type& b, const Type& tolerance)
460{
461 return (b - a < tolerance);
462}
463
464
465/// @brief Return @c true if @a a is exactly equal to @a b.
466template<typename T0, typename T1>
467inline bool
468isExactlyEqual(const T0& a, const T1& b)
469{
471 return a == b;
473}
474
475
476template<typename Type>
477inline bool
478isRelOrApproxEqual(const Type& a, const Type& b, const Type& absTol, const Type& relTol)
479{
480 // First check to see if we are inside the absolute tolerance
481 // Necessary for numbers close to 0
482 if (!(Abs(a - b) > absTol)) return true;
483
484 // Next check to see if we are inside the relative tolerance
485 // to handle large numbers that aren't within the abs tolerance
486 // but could be the closest floating point representation
487 double relError;
488 if (Abs(b) > Abs(a)) {
489 relError = Abs((a - b) / b);
490 } else {
491 relError = Abs((a - b) / a);
492 }
493 return (relError <= relTol);
494}
495
496template<>
497inline bool
498isRelOrApproxEqual(const bool& a, const bool& b, const bool&, const bool&)
499{
500 return (a == b);
501}
502
503inline int32_t
504floatToInt32(const float f)
505{
506 // switch to std:bit_cast in C++20
507 static_assert(sizeof(int32_t) == sizeof f, "`float` has an unexpected size.");
508 int32_t ret;
509 std::memcpy(&ret, &f, sizeof(int32_t));
510 return ret;
511}
512
513inline int64_t
514doubleToInt64(const double d)
515{
516 // switch to std:bit_cast in C++20
517 static_assert(sizeof(int64_t) == sizeof d, "`double` has an unexpected size.");
518 int64_t ret;
519 std::memcpy(&ret, &d, sizeof(int64_t));
520 return ret;
521}
522
523// aUnitsInLastPlace is the allowed difference between the least significant digits
524// of the numbers' floating point representation
525// Please read the reference paper before trying to use isUlpsEqual
526// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
527inline bool
528isUlpsEqual(const double aLeft, const double aRight, const int64_t aUnitsInLastPlace)
529{
530 int64_t longLeft = doubleToInt64(aLeft);
531 // Because of 2's complement, must restore lexicographical order
532 if (longLeft < 0) {
533 longLeft = INT64_C(0x8000000000000000) - longLeft;
534 }
535
536 int64_t longRight = doubleToInt64(aRight);
537 // Because of 2's complement, must restore lexicographical order
538 if (longRight < 0) {
539 longRight = INT64_C(0x8000000000000000) - longRight;
540 }
541
542 int64_t difference = Abs(longLeft - longRight);
543 return (difference <= aUnitsInLastPlace);
544}
545
546inline bool
547isUlpsEqual(const float aLeft, const float aRight, const int32_t aUnitsInLastPlace)
548{
549 int32_t intLeft = floatToInt32(aLeft);
550 // Because of 2's complement, must restore lexicographical order
551 if (intLeft < 0) {
552 intLeft = 0x80000000 - intLeft;
553 }
554
555 int32_t intRight = floatToInt32(aRight);
556 // Because of 2's complement, must restore lexicographical order
557 if (intRight < 0) {
558 intRight = 0x80000000 - intRight;
559 }
560
561 int32_t difference = Abs(intLeft - intRight);
562 return (difference <= aUnitsInLastPlace);
563}
564
565
566////////////////////////////////////////
567
568
569// ==========> Pow <==================
570
571/// Return @a x<sup>2</sup>.
572template<typename Type>
573inline Type Pow2(Type x) { return x*x; }
574
575/// Return @a x<sup>3</sup>.
576template<typename Type>
577inline Type Pow3(Type x) { return x*x*x; }
578
579/// Return @a x<sup>4</sup>.
580template<typename Type>
581inline Type Pow4(Type x) { return Pow2(Pow2(x)); }
582
583/// Return @a x<sup>n</sup>.
584template<typename Type>
585Type
586Pow(Type x, int n)
587{
588 Type ans = 1;
589 if (n < 0) {
590 n = -n;
591 x = Type(1)/x;
592 }
593 while (n--) ans *= x;
594 return ans;
595}
596
597//@{
598/// Return @a b<sup>e</sup>.
599inline math::half
601{
602 OPENVDB_ASSERT( b >= 0.0f && "Pow(half,half): base is negative" );
603 return math::half(powf(float(b),float(e)));
604}
605
606//@{
607/// Return @a b<sup>e</sup>.
608inline float
609Pow(float b, float e)
610{
611 OPENVDB_ASSERT( b >= 0.0f && "Pow(float,float): base is negative" );
612 return powf(b,e);
613}
614
615inline double
616Pow(double b, double e)
617{
618 OPENVDB_ASSERT( b >= 0.0 && "Pow(double,double): base is negative" );
619 return std::pow(b,e);
620}
621//@}
622
623
624// ==========> Max <==================
625
626namespace internal {
627
628inline const math::half&
629max_impl(const math::half& a, const math::half& b)
630{
631 return a < b ? b : a;
632}
633
634template<typename Type>
635inline const Type&
636max_impl(const Type& a, const Type& b)
637{
638 return std::max(a,b);
639}
640
641} // namespace internal
642
643/// Return the maximum of two values
644template<typename Type>
645inline const Type&
646Max(const Type& a, const Type& b)
647{
648 return internal::max_impl(a,b);
649}
650
651/// Return the maximum of three values
652template<typename Type>
653inline const Type&
654Max(const Type& a, const Type& b, const Type& c)
655{
656 return internal::max_impl(internal::max_impl(a,b), c);
657}
658
659/// Return the maximum of four values
660template<typename Type>
661inline const Type&
662Max(const Type& a, const Type& b, const Type& c, const Type& d)
663{
664 return internal::max_impl(internal::max_impl(a,b), internal::max_impl(c,d));
665}
666
667/// Return the maximum of five values
668template<typename Type>
669inline const Type&
670Max(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e)
671{
672 return internal::max_impl(internal::max_impl(a,b), Max(c,d,e));
673}
674
675/// Return the maximum of six values
676template<typename Type>
677inline const Type&
678Max(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e, const Type& f)
679{
680 return internal::max_impl(Max(a,b,c), Max(d,e,f));
681}
682
683/// Return the maximum of seven values
684template<typename Type>
685inline const Type&
686Max(const Type& a, const Type& b, const Type& c, const Type& d,
687 const Type& e, const Type& f, const Type& g)
688{
689 return internal::max_impl(Max(a,b,c,d), Max(e,f,g));
690}
691
692/// Return the maximum of eight values
693template<typename Type>
694inline const Type&
695Max(const Type& a, const Type& b, const Type& c, const Type& d,
696 const Type& e, const Type& f, const Type& g, const Type& h)
697{
698 return internal::max_impl(Max(a,b,c,d), Max(e,f,g,h));
699}
700
701
702// ==========> Min <==================
703
704namespace internal {
705
706inline const math::half&
707min_impl(const math::half& a, const math::half& b)
708{
709 return b < a ? b : a;
710}
711
712template<typename Type>
713inline const Type&
714min_impl(const Type& a, const Type& b)
715{
716 return std::min(a,b);
717}
718
719} // namespace internal
720
721/// Return the minimum of two values
722template<typename Type>
723inline const Type&
724Min(const Type& a, const Type& b) { return internal::min_impl(a, b); }
725
726/// Return the minimum of three values
727template<typename Type>
728inline const Type&
729Min(const Type& a, const Type& b, const Type& c)
730{
731 return internal::min_impl(internal::min_impl(a, b), c);
732}
733
734/// Return the minimum of four values
735template<typename Type>
736inline const Type&
737Min(const Type& a, const Type& b, const Type& c, const Type& d)
738{
739 return internal::min_impl(internal::min_impl(a, b), internal::min_impl(c, d));
740}
741
742/// Return the minimum of five values
743template<typename Type>
744inline const Type&
745Min(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e)
746{
747 return internal::min_impl(internal::min_impl(a,b), Min(c,d,e));
748}
749
750/// Return the minimum of six values
751template<typename Type>
752inline const Type&
753Min(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e, const Type& f)
754{
755 return internal::min_impl(Min(a,b,c), Min(d,e,f));
756}
757
758/// Return the minimum of seven values
759template<typename Type>
760inline const Type&
761Min(const Type& a, const Type& b, const Type& c, const Type& d,
762 const Type& e, const Type& f, const Type& g)
763{
764 return internal::min_impl(Min(a,b,c,d), Min(e,f,g));
765}
766
767/// Return the minimum of eight values
768template<typename Type>
769inline const Type&
770Min(const Type& a, const Type& b, const Type& c, const Type& d,
771 const Type& e, const Type& f, const Type& g, const Type& h)
772{
773 return internal::min_impl(Min(a,b,c,d), Min(e,f,g,h));
774}
775
776
777// ============> Exp <==================
778
779/// Return @a e<sup>x</sup>.
780template<typename Type>
781inline Type Exp(const Type& x) { return std::exp(x); }
782
783// ============> Sin <==================
784
785//@{
786/// Return sin @a x.
787inline float Sin(const float& x) { return std::sin(x); }
788
789inline double Sin(const double& x) { return std::sin(x); }
790//@}
791
792// ============> Cos <==================
793
794//@{
795/// Return cos @a x.
796inline float Cos(const float& x) { return std::cos(x); }
797
798inline double Cos(const double& x) { return std::cos(x); }
799//@}
800
801
802////////////////////////////////////////
803
804
805/// Return the sign of the given value as an integer (either -1, 0 or 1).
806template <typename Type>
807inline int Sign(const Type &x) { return (zeroVal<Type>() < x) - (x < zeroVal<Type>()); }
808
809
810/// @brief Return @c true if @a a and @a b have different signs.
811/// @note Zero is considered a positive number.
812template <typename Type>
813inline bool
814SignChange(const Type& a, const Type& b)
815{
816 return ( (a<zeroVal<Type>()) ^ (b<zeroVal<Type>()) );
817}
818
819
820/// @brief Return @c true if the interval [@a a, @a b] includes zero,
821/// i.e., if either @a a or @a b is zero or if they have different signs.
822template <typename Type>
823inline bool
824ZeroCrossing(const Type& a, const Type& b)
825{
826 return a * b <= zeroVal<Type>();
827}
828
829
830//@{
831/// Return the square root of a floating-point value.
832inline float Sqrt(float x) { return std::sqrt(x); }
833inline double Sqrt(double x) { return std::sqrt(x); }
834inline long double Sqrt(long double x) { return std::sqrt(x); }
835//@}
836
837
838//@{
839/// Return the cube root of a floating-point value.
840inline float Cbrt(float x) { return std::cbrt(x); }
841inline double Cbrt(double x) { return std::cbrt(x); }
842inline long double Cbrt(long double x) { return std::cbrt(x); }
843//@}
844
845
846//@{
847/// Return the remainder of @a x / @a y.
848inline int Mod(int x, int y) { return (x % y); }
849inline float Mod(float x, float y) { return std::fmod(x, y); }
850inline double Mod(double x, double y) { return std::fmod(x, y); }
851inline long double Mod(long double x, long double y) { return std::fmod(x, y); }
852template<typename Type> inline Type Remainder(Type x, Type y) { return Mod(x, y); }
853//@}
854
855
856//@{
857/// Return @a x rounded up to the nearest integer.
858inline float RoundUp(float x) { return std::ceil(x); }
859inline double RoundUp(double x) { return std::ceil(x); }
860inline long double RoundUp(long double x) { return std::ceil(x); }
861//@}
862/// Return @a x rounded up to the nearest multiple of @a base.
863template<typename Type>
864inline Type
865RoundUp(Type x, Type base)
866{
867 Type remainder = Remainder(x, base);
868 return remainder ? x-remainder+base : x;
869}
870
871
872//@{
873/// Return @a x rounded down to the nearest integer.
874inline float RoundDown(float x) { return std::floor(x); }
875inline double RoundDown(double x) { return std::floor(x); }
876inline long double RoundDown(long double x) { return std::floor(x); }
877//@}
878/// Return @a x rounded down to the nearest multiple of @a base.
879template<typename Type>
880inline Type
881RoundDown(Type x, Type base)
882{
883 Type remainder = Remainder(x, base);
884 return remainder ? x-remainder : x;
885}
886
887
888//@{
889/// Return @a x rounded to the nearest integer.
890inline float Round(float x) { return RoundDown(x + 0.5f); }
891inline double Round(double x) { return RoundDown(x + 0.5); }
892inline long double Round(long double x) { return RoundDown(x + 0.5l); }
893//@}
894
895
896/// Return the euclidean remainder of @a x.
897/// Note unlike % operator this will always return a positive result
898template<typename Type>
899inline Type
900EuclideanRemainder(Type x) { return x - RoundDown(x); }
901
902
903/// Return the integer part of @a x.
904template<typename Type>
905inline Type
907{
908 return (x > 0 ? RoundDown(x) : RoundUp(x));
909}
910
911/// Return the fractional part of @a x.
912template<typename Type>
913inline Type
914FractionalPart(Type x) { return Mod(x,Type(1)); }
915
916
917//@{
918/// Return the floor of @a x.
919inline int Floor(float x) { return int(RoundDown(x)); }
920inline int Floor(double x) { return int(RoundDown(x)); }
921inline int Floor(long double x) { return int(RoundDown(x)); }
922//@}
923
924
925//@{
926/// Return the ceiling of @a x.
927inline int Ceil(float x) { return int(RoundUp(x)); }
928inline int Ceil(double x) { return int(RoundUp(x)); }
929inline int Ceil(long double x) { return int(RoundUp(x)); }
930//@}
931
932
933/// Return @a x if it is greater or equal in magnitude than @a delta. Otherwise, return zero.
934template<typename Type>
935inline Type Chop(Type x, Type delta) { return (Abs(x) < delta ? zeroVal<Type>() : x); }
936
937
938/// Return @a x truncated to the given number of decimal digits.
939template<typename Type>
940inline Type
941Truncate(Type x, unsigned int digits)
942{
943 Type tenth = static_cast<Type>(Pow(size_t(10), digits));
944 return RoundDown(x*tenth+0.5)/tenth;
945}
946
947////////////////////////////////////////
948
949
950/// @brief 8-bit integer values print to std::ostreams as characters.
951/// Cast them so that they print as integers instead.
952template<typename T>
953inline auto PrintCast(const T& val) -> typename std::enable_if<!std::is_same<T, int8_t>::value
954 && !std::is_same<T, uint8_t>::value, const T&>::type { return val; }
955inline int32_t PrintCast(int8_t val) { return int32_t(val); }
956inline uint32_t PrintCast(uint8_t val) { return uint32_t(val); }
957
958
959////////////////////////////////////////
960
961
962/// Return the inverse of @a x.
963template<typename Type>
964inline Type
965Inv(Type x)
966{
968 return Type(1)/x;
969}
970
971
972enum Axis {
976};
977
978// enum values are consistent with their historical mx analogs.
989
990template <typename S, typename T, typename = std::enable_if_t<openvdb::is_arithmetic_v<S>&& openvdb::is_arithmetic_v<T>>>
991struct promote {
992 using type = typename std::common_type_t<S,T>;
993};
994
995
996/// @brief Return the index [0,1,2] of the smallest value in a 3D vector.
997/// @note This methods assumes operator[] exists.
998/// @details The return value corresponds to the largest index of the of
999/// the smallest vector components.
1000template<typename Vec3T>
1001size_t
1002MinIndex(const Vec3T& v)
1003{
1004 size_t r = 0;
1005 for (size_t i = 1; i < 3; ++i) {
1006 // largest index (backwards compatibility)
1007 if (v[i] <= v[r]) r = i;
1008 }
1009 return r;
1010}
1011
1012/// @brief Return the index [0,1,2] of the largest value in a 3D vector.
1013/// @note This methods assumes operator[] exists.
1014/// @details The return value corresponds to the largest index of the of
1015/// the largest vector components.
1016template<typename Vec3T>
1017size_t
1018MaxIndex(const Vec3T& v)
1019{
1020 size_t r = 0;
1021 for (size_t i = 1; i < 3; ++i) {
1022 // largest index (backwards compatibility)
1023 if (v[i] >= v[r]) r = i;
1024 }
1025 return r;
1026}
1027
1028} // namespace math
1029} // namespace OPENVDB_VERSION_NAME
1030} // namespace openvdb
1031
1032#endif // OPENVDB_MATH_MATH_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
#define OPENVDB_EXACT_IS_APPROX_EQUAL(T)
Definition Math.h:446
#define OPENVDB_NO_FP_EQUALITY_WARNING_END
Definition Math.h:50
#define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
Definition Math.h:49
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
Bracket code with OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN/_END, to inhibit warnings about type conve...
Definition Platform.h:244
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition Platform.h:245
Definition Half.h:509
Simple generator of random numbers over the range [0, 1)
Definition Math.h:180
void setSeed(unsigned int seed)
Set the seed value for the random number generator.
Definition Math.h:197
Rand01(const EngineType &engine)
Initialize the generator.
Definition Math.h:190
const std::mt19937 & engine() const
Definition Math.h:203
FloatType operator()()
Return a uniformly distributed random number in the range [0, 1).
Definition Math.h:206
Rand01(unsigned int seed)
Initialize the generator.
Definition Math.h:194
FloatType ValueType
Definition Math.h:186
Simple random integer generator.
Definition Math.h:216
void setSeed(unsigned int seed)
Set the seed value for the random number generator.
Definition Math.h:246
RandInt(unsigned int seed, IntType imin, IntType imax)
Initialize the generator.
Definition Math.h:234
void setRange(IntType imin, IntType imax)
Change the range over which integers are distributed to [imin, imax].
Definition Math.h:240
IntType operator()()
Return a randomly-generated integer in the current range.
Definition Math.h:255
const std::mt19937 & engine() const
Definition Math.h:252
RandInt(const EngineType &engine, IntType imin, IntType imax)
Initialize the generator.
Definition Math.h:226
IntType operator()(IntType imin, IntType imax)
Return a randomly-generated integer in the new range [imin, imax], without changing the current range...
Definition Math.h:259
Definition Types.h:763
int Sign(const Type &x)
Return the sign of the given value as an integer (either -1, 0 or 1).
Definition Math.h:807
bool isApproxLarger(const Type &a, const Type &b, const Type &tolerance)
Return true if a is larger than b to within the given tolerance, i.e., if b - a < tolerance.
Definition Math.h:459
size_t MaxIndex(const Vec3T &v)
Return the index [0,1,2] of the largest value in a 3D vector.
Definition Math.h:1018
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition Math.h:858
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x².
Definition Math.h:300
int Ceil(float x)
Return the ceiling of x.
Definition Math.h:927
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition Math.h:362
bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
Definition Math.h:402
Type IntegerPart(Type x)
Return the integer part of x.
Definition Math.h:906
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1015
constexpr T pi()
Pi constant taken from Boost to match old behaviour.
Definition Math.h:130
Type Pow(Type x, int n)
Return xn.
Definition Math.h:586
float Sqrt(float x)
Return the square root of a floating-point value.
Definition Math.h:832
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition Math.h:431
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition Math.h:478
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition Math.h:646
size_t MinIndex(const Vec3T &v)
Return the index [0,1,2] of the smallest value in a 3D vector.
Definition Math.h:1002
bool isFinite(const float x)
Return true if x is finite.
Definition Math.h:388
auto PrintCast(const T &val) -> typename std::enable_if<!std::is_same< T, int8_t >::value &&!std::is_same< T, uint8_t >::value, const T & >::type
8-bit integer values print to std::ostreams as characters. Cast them so that they print as integers i...
Definition Math.h:953
Vec3< typename promote< T, typename Coord::ValueType >::type > operator+(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be added to or subtracted from a Vec3.
Definition Coord.h:528
Type Pow4(Type x)
Return x4.
Definition Math.h:581
Type EuclideanRemainder(Type x)
Definition Math.h:900
Type Remainder(Type x, Type y)
Definition Math.h:852
Type Inv(Type x)
Return the inverse of x.
Definition Math.h:965
Type Exp(const Type &x)
Return ex.
Definition Math.h:781
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition Math.h:380
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition Math.h:416
int64_t doubleToInt64(const double d)
Definition Math.h:514
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition Math.h:284
float Cos(const float &x)
Return cos x.
Definition Math.h:796
bool isUlpsEqual(const double aLeft, const double aRight, const int64_t aUnitsInLastPlace)
Definition Math.h:528
RandInt< int, std::mt19937 > RandomInt
Definition Math.h:266
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition Math.h:874
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition Math.h:724
Coord Abs(const Coord &xyz)
Definition Coord.h:518
int Mod(int x, int y)
Return the remainder of x / y.
Definition Math.h:848
Type Truncate(Type x, unsigned int digits)
Return x truncated to the given number of decimal digits.
Definition Math.h:941
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:139
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:468
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:890
Type Pow3(Type x)
Return x3.
Definition Math.h:577
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition Math.h:274
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition Math.h:350
Type Chop(Type x, Type delta)
Return x if it is greater or equal in magnitude than delta. Otherwise, return zero.
Definition Math.h:935
Type FractionalPart(Type x)
Return the fractional part of x.
Definition Math.h:914
auto cwiseAdd(const Vec3H &v, const float s)
Definition Types.h:765
internal::half half
Definition HalfDecl.h:25
Axis
Definition Math.h:972
@ Z_AXIS
Definition Math.h:975
@ X_AXIS
Definition Math.h:973
@ Y_AXIS
Definition Math.h:974
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition Mat.h:1029
bool ClampTest01(Type &x)
Return true if x is outside [0,1].
Definition Math.h:290
float Sin(const float &x)
Return sin x.
Definition Math.h:787
int32_t floatToInt32(const float f)
Definition Math.h:504
Type Pow2(Type x)
Return x2.
Definition Math.h:573
RotationOrder
Definition Math.h:979
@ YXZ_ROTATION
Definition Math.h:982
@ ZXY_ROTATION
Definition Math.h:984
@ YZX_ROTATION
Definition Math.h:983
@ ZXZ_ROTATION
Definition Math.h:987
@ XZX_ROTATION
Definition Math.h:986
@ XYZ_ROTATION
Definition Math.h:980
@ ZYX_ROTATION
Definition Math.h:985
@ XZY_ROTATION
Definition Math.h:981
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition Math.h:840
int Floor(float x)
Return the floor of x.
Definition Math.h:919
bool SignChange(const Type &a, const Type &b)
Return true if a and b have different signs.
Definition Math.h:814
bool ZeroCrossing(const Type &a, const Type &b)
Return true if the interval [a, b] includes zero, i.e., if either a or b is zero or if they have diff...
Definition Math.h:824
Rand01< double, std::mt19937 > Random01
Definition Math.h:209
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
constexpr bool is_arithmetic_v
Definition Math.h:85
Definition Exceptions.h:13
Definition Coord.h:590
Definition Math.h:80
static double value()
Definition Math.h:170
static float value()
Definition Math.h:169
static math::half value()
Definition Math.h:168
Delta for small floating-point offsets.
Definition Math.h:167
static T value()
Definition Math.h:167
static double value()
Definition Math.h:162
static float value()
Definition Math.h:161
static math::half value()
Definition Math.h:160
Tolerance for floating-point comparison.
Definition Math.h:159
static T value()
Definition Math.h:159
Definition Math.h:991
typename std::common_type_t< S, T > type
Definition Math.h:992
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218