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/// Return @c true if @a x is equal to zero to within the given tolerance.
358template<typename Type>
359inline bool
360isApproxZero(const Type& x, const Type& tolerance)
361{
362 return !cwiseGreaterThan(x, tolerance) && !cwiseLessThan(x, -tolerance);
363}
364
365/// @brief Return @c true if @a x is equal to zero to within
366/// the default floating-point comparison tolerance.
367template<typename Type>
368inline bool
369isApproxZero(const Type& x)
370{
372}
373
374/// Return @c true if @a x is less than zero.
375template<typename Type>
376inline bool
377isNegative(const Type& x) { return cwiseLessThan(x, zeroVal<Type>()); }
378
379// Return false, since bool values are never less than zero.
380template<> inline bool isNegative<bool>(const bool&) { return false; }
381
382
383/// Return @c true if @a x is finite.
384inline bool
385isFinite(const float x) { return std::isfinite(x); }
386
387/// Return @c true if @a x is finite.
388inline bool
389isFinite(const math::half x) { return x.isFinite(); }
390
391/// Return @c true if @a x is finite.
392template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
393inline bool
394isFinite(const Type& x) { return std::isfinite(static_cast<double>(x)); }
395
396
397/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
398inline bool
399isInfinite(const float x) { return std::isinf(x); }
400
401/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
402inline bool
403isInfinite(const math::half x) { return x.isInfinity(); }
404
405/// Return @c true if @a x is an infinity value (either positive infinity or negative infinity).
406template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
407inline bool
408isInfinite(const Type& x) { return std::isinf(static_cast<double>(x)); }
409
410
411/// Return @c true if @a x is a NaN (Not-A-Number) value.
412inline bool
413isNan(const float x) { return std::isnan(x); }
414
415/// Return @c true if @a x is a NaN (Not-A-Number) value.
416inline bool
417isNan(const math::half x) { return x.isNan(); }
418
419/// Return @c true if @a x is a NaN (Not-A-Number) value.
420template<typename Type, typename std::enable_if<std::is_arithmetic<Type>::value, int>::type = 0>
421inline bool
422isNan(const Type& x) { return std::isnan(static_cast<double>(x)); }
423
424
425/// Return @c true if @a a is equal to @a b to within the given tolerance.
426template<typename Type>
427inline bool
428isApproxEqual(const Type& a, const Type& b, const Type& tolerance)
429{
430 return !cwiseGreaterThan(Abs(a - b), tolerance);
431}
432
433/// @brief Return @c true if @a a is equal to @a b to within
434/// the default floating-point comparison tolerance.
435template<typename Type>
436inline bool
437isApproxEqual(const Type& a, const Type& b)
438{
439 const Type tolerance = Type(zeroVal<Type>() + Tolerance<Type>::value());
440 return isApproxEqual(a, b, tolerance);
441}
442
443#define OPENVDB_EXACT_IS_APPROX_EQUAL(T) \
444 template<> inline bool isApproxEqual<T>(const T& a, const T& b) { return a == b; } \
445 template<> inline bool isApproxEqual<T>(const T& a, const T& b, const T&) { return a == b; } \
446 /**/
447
450
451
452/// @brief Return @c true if @a a is larger than @a b to within
453/// the given tolerance, i.e., if @a b - @a a < @a tolerance.
454template<typename Type>
455inline bool
456isApproxLarger(const Type& a, const Type& b, const Type& tolerance)
457{
458 return (b - a < tolerance);
459}
460
461
462/// @brief Return @c true if @a a is exactly equal to @a b.
463template<typename T0, typename T1>
464inline bool
465isExactlyEqual(const T0& a, const T1& b)
466{
468 return a == b;
470}
471
472
473template<typename Type>
474inline bool
475isRelOrApproxEqual(const Type& a, const Type& b, const Type& absTol, const Type& relTol)
476{
477 // First check to see if we are inside the absolute tolerance
478 // Necessary for numbers close to 0
479 if (!(Abs(a - b) > absTol)) return true;
480
481 // Next check to see if we are inside the relative tolerance
482 // to handle large numbers that aren't within the abs tolerance
483 // but could be the closest floating point representation
484 double relError;
485 if (Abs(b) > Abs(a)) {
486 relError = Abs((a - b) / b);
487 } else {
488 relError = Abs((a - b) / a);
489 }
490 return (relError <= relTol);
491}
492
493template<>
494inline bool
495isRelOrApproxEqual(const bool& a, const bool& b, const bool&, const bool&)
496{
497 return (a == b);
498}
499
500inline int32_t
501floatToInt32(const float f)
502{
503 // switch to std:bit_cast in C++20
504 static_assert(sizeof(int32_t) == sizeof f, "`float` has an unexpected size.");
505 int32_t ret;
506 std::memcpy(&ret, &f, sizeof(int32_t));
507 return ret;
508}
509
510inline int64_t
511doubleToInt64(const double d)
512{
513 // switch to std:bit_cast in C++20
514 static_assert(sizeof(int64_t) == sizeof d, "`double` has an unexpected size.");
515 int64_t ret;
516 std::memcpy(&ret, &d, sizeof(int64_t));
517 return ret;
518}
519
520// aUnitsInLastPlace is the allowed difference between the least significant digits
521// of the numbers' floating point representation
522// Please read the reference paper before trying to use isUlpsEqual
523// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
524inline bool
525isUlpsEqual(const double aLeft, const double aRight, const int64_t aUnitsInLastPlace)
526{
527 int64_t longLeft = doubleToInt64(aLeft);
528 // Because of 2's complement, must restore lexicographical order
529 if (longLeft < 0) {
530 longLeft = INT64_C(0x8000000000000000) - longLeft;
531 }
532
533 int64_t longRight = doubleToInt64(aRight);
534 // Because of 2's complement, must restore lexicographical order
535 if (longRight < 0) {
536 longRight = INT64_C(0x8000000000000000) - longRight;
537 }
538
539 int64_t difference = Abs(longLeft - longRight);
540 return (difference <= aUnitsInLastPlace);
541}
542
543inline bool
544isUlpsEqual(const float aLeft, const float aRight, const int32_t aUnitsInLastPlace)
545{
546 int32_t intLeft = floatToInt32(aLeft);
547 // Because of 2's complement, must restore lexicographical order
548 if (intLeft < 0) {
549 intLeft = 0x80000000 - intLeft;
550 }
551
552 int32_t intRight = floatToInt32(aRight);
553 // Because of 2's complement, must restore lexicographical order
554 if (intRight < 0) {
555 intRight = 0x80000000 - intRight;
556 }
557
558 int32_t difference = Abs(intLeft - intRight);
559 return (difference <= aUnitsInLastPlace);
560}
561
562
563////////////////////////////////////////
564
565
566// ==========> Pow <==================
567
568/// Return @a x<sup>2</sup>.
569template<typename Type>
570inline Type Pow2(Type x) { return x*x; }
571
572/// Return @a x<sup>3</sup>.
573template<typename Type>
574inline Type Pow3(Type x) { return x*x*x; }
575
576/// Return @a x<sup>4</sup>.
577template<typename Type>
578inline Type Pow4(Type x) { return Pow2(Pow2(x)); }
579
580/// Return @a x<sup>n</sup>.
581template<typename Type>
582Type
583Pow(Type x, int n)
584{
585 Type ans = 1;
586 if (n < 0) {
587 n = -n;
588 x = Type(1)/x;
589 }
590 while (n--) ans *= x;
591 return ans;
592}
593
594//@{
595/// Return @a b<sup>e</sup>.
596inline math::half
598{
599 OPENVDB_ASSERT( b >= 0.0f && "Pow(half,half): base is negative" );
600 return math::half(powf(float(b),float(e)));
601}
602
603//@{
604/// Return @a b<sup>e</sup>.
605inline float
606Pow(float b, float e)
607{
608 OPENVDB_ASSERT( b >= 0.0f && "Pow(float,float): base is negative" );
609 return powf(b,e);
610}
611
612inline double
613Pow(double b, double e)
614{
615 OPENVDB_ASSERT( b >= 0.0 && "Pow(double,double): base is negative" );
616 return std::pow(b,e);
617}
618//@}
619
620
621// ==========> Max <==================
622
623namespace internal {
624
625inline const math::half&
626max_impl(const math::half& a, const math::half& b)
627{
628 return a < b ? b : a;
629}
630
631template<typename Type>
632inline const Type&
633max_impl(const Type& a, const Type& b)
634{
635 return std::max(a,b);
636}
637
638} // namespace internal
639
640/// Return the maximum of two values
641template<typename Type>
642inline const Type&
643Max(const Type& a, const Type& b)
644{
645 return internal::max_impl(a,b);
646}
647
648/// Return the maximum of three values
649template<typename Type>
650inline const Type&
651Max(const Type& a, const Type& b, const Type& c)
652{
653 return internal::max_impl(internal::max_impl(a,b), c);
654}
655
656/// Return the maximum of four values
657template<typename Type>
658inline const Type&
659Max(const Type& a, const Type& b, const Type& c, const Type& d)
660{
661 return internal::max_impl(internal::max_impl(a,b), internal::max_impl(c,d));
662}
663
664/// Return the maximum of five values
665template<typename Type>
666inline const Type&
667Max(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e)
668{
669 return internal::max_impl(internal::max_impl(a,b), Max(c,d,e));
670}
671
672/// Return the maximum of six values
673template<typename Type>
674inline const Type&
675Max(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e, const Type& f)
676{
677 return internal::max_impl(Max(a,b,c), Max(d,e,f));
678}
679
680/// Return the maximum of seven values
681template<typename Type>
682inline const Type&
683Max(const Type& a, const Type& b, const Type& c, const Type& d,
684 const Type& e, const Type& f, const Type& g)
685{
686 return internal::max_impl(Max(a,b,c,d), Max(e,f,g));
687}
688
689/// Return the maximum of eight values
690template<typename Type>
691inline const Type&
692Max(const Type& a, const Type& b, const Type& c, const Type& d,
693 const Type& e, const Type& f, const Type& g, const Type& h)
694{
695 return internal::max_impl(Max(a,b,c,d), Max(e,f,g,h));
696}
697
698
699// ==========> Min <==================
700
701namespace internal {
702
703inline const math::half&
704min_impl(const math::half& a, const math::half& b)
705{
706 return b < a ? b : a;
707}
708
709template<typename Type>
710inline const Type&
711min_impl(const Type& a, const Type& b)
712{
713 return std::min(a,b);
714}
715
716} // namespace internal
717
718/// Return the minimum of two values
719template<typename Type>
720inline const Type&
721Min(const Type& a, const Type& b) { return internal::min_impl(a, b); }
722
723/// Return the minimum of three values
724template<typename Type>
725inline const Type&
726Min(const Type& a, const Type& b, const Type& c)
727{
728 return internal::min_impl(internal::min_impl(a, b), c);
729}
730
731/// Return the minimum of four values
732template<typename Type>
733inline const Type&
734Min(const Type& a, const Type& b, const Type& c, const Type& d)
735{
736 return internal::min_impl(internal::min_impl(a, b), internal::min_impl(c, d));
737}
738
739/// Return the minimum of five values
740template<typename Type>
741inline const Type&
742Min(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e)
743{
744 return internal::min_impl(internal::min_impl(a,b), Min(c,d,e));
745}
746
747/// Return the minimum of six values
748template<typename Type>
749inline const Type&
750Min(const Type& a, const Type& b, const Type& c, const Type& d, const Type& e, const Type& f)
751{
752 return internal::min_impl(Min(a,b,c), Min(d,e,f));
753}
754
755/// Return the minimum of seven values
756template<typename Type>
757inline const Type&
758Min(const Type& a, const Type& b, const Type& c, const Type& d,
759 const Type& e, const Type& f, const Type& g)
760{
761 return internal::min_impl(Min(a,b,c,d), Min(e,f,g));
762}
763
764/// Return the minimum of eight values
765template<typename Type>
766inline const Type&
767Min(const Type& a, const Type& b, const Type& c, const Type& d,
768 const Type& e, const Type& f, const Type& g, const Type& h)
769{
770 return internal::min_impl(Min(a,b,c,d), Min(e,f,g,h));
771}
772
773
774// ============> Exp <==================
775
776/// Return @a e<sup>x</sup>.
777template<typename Type>
778inline Type Exp(const Type& x) { return std::exp(x); }
779
780// ============> Sin <==================
781
782//@{
783/// Return sin @a x.
784inline float Sin(const float& x) { return std::sin(x); }
785
786inline double Sin(const double& x) { return std::sin(x); }
787//@}
788
789// ============> Cos <==================
790
791//@{
792/// Return cos @a x.
793inline float Cos(const float& x) { return std::cos(x); }
794
795inline double Cos(const double& x) { return std::cos(x); }
796//@}
797
798
799////////////////////////////////////////
800
801
802/// Return the sign of the given value as an integer (either -1, 0 or 1).
803template <typename Type>
804inline int Sign(const Type &x) { return (zeroVal<Type>() < x) - (x < zeroVal<Type>()); }
805
806
807/// @brief Return @c true if @a a and @a b have different signs.
808/// @note Zero is considered a positive number.
809template <typename Type>
810inline bool
811SignChange(const Type& a, const Type& b)
812{
813 return ( (a<zeroVal<Type>()) ^ (b<zeroVal<Type>()) );
814}
815
816
817/// @brief Return @c true if the interval [@a a, @a b] includes zero,
818/// i.e., if either @a a or @a b is zero or if they have different signs.
819template <typename Type>
820inline bool
821ZeroCrossing(const Type& a, const Type& b)
822{
823 return a * b <= zeroVal<Type>();
824}
825
826
827//@{
828/// Return the square root of a floating-point value.
829inline float Sqrt(float x) { return std::sqrt(x); }
830inline double Sqrt(double x) { return std::sqrt(x); }
831inline long double Sqrt(long double x) { return std::sqrt(x); }
832//@}
833
834
835//@{
836/// Return the cube root of a floating-point value.
837inline float Cbrt(float x) { return std::cbrt(x); }
838inline double Cbrt(double x) { return std::cbrt(x); }
839inline long double Cbrt(long double x) { return std::cbrt(x); }
840//@}
841
842
843//@{
844/// Return the remainder of @a x / @a y.
845inline int Mod(int x, int y) { return (x % y); }
846inline float Mod(float x, float y) { return std::fmod(x, y); }
847inline double Mod(double x, double y) { return std::fmod(x, y); }
848inline long double Mod(long double x, long double y) { return std::fmod(x, y); }
849template<typename Type> inline Type Remainder(Type x, Type y) { return Mod(x, y); }
850//@}
851
852
853//@{
854/// Return @a x rounded up to the nearest integer.
855inline float RoundUp(float x) { return std::ceil(x); }
856inline double RoundUp(double x) { return std::ceil(x); }
857inline long double RoundUp(long double x) { return std::ceil(x); }
858//@}
859/// Return @a x rounded up to the nearest multiple of @a base.
860template<typename Type>
861inline Type
862RoundUp(Type x, Type base)
863{
864 Type remainder = Remainder(x, base);
865 return remainder ? x-remainder+base : x;
866}
867
868
869//@{
870/// Return @a x rounded down to the nearest integer.
871inline float RoundDown(float x) { return std::floor(x); }
872inline double RoundDown(double x) { return std::floor(x); }
873inline long double RoundDown(long double x) { return std::floor(x); }
874//@}
875/// Return @a x rounded down to the nearest multiple of @a base.
876template<typename Type>
877inline Type
878RoundDown(Type x, Type base)
879{
880 Type remainder = Remainder(x, base);
881 return remainder ? x-remainder : x;
882}
883
884
885//@{
886/// Return @a x rounded to the nearest integer.
887inline float Round(float x) { return RoundDown(x + 0.5f); }
888inline double Round(double x) { return RoundDown(x + 0.5); }
889inline long double Round(long double x) { return RoundDown(x + 0.5l); }
890//@}
891
892
893/// Return the euclidean remainder of @a x.
894/// Note unlike % operator this will always return a positive result
895template<typename Type>
896inline Type
897EuclideanRemainder(Type x) { return x - RoundDown(x); }
898
899
900/// Return the integer part of @a x.
901template<typename Type>
902inline Type
904{
905 return (x > 0 ? RoundDown(x) : RoundUp(x));
906}
907
908/// Return the fractional part of @a x.
909template<typename Type>
910inline Type
911FractionalPart(Type x) { return Mod(x,Type(1)); }
912
913
914//@{
915/// Return the floor of @a x.
916inline int Floor(float x) { return int(RoundDown(x)); }
917inline int Floor(double x) { return int(RoundDown(x)); }
918inline int Floor(long double x) { return int(RoundDown(x)); }
919//@}
920
921
922//@{
923/// Return the ceiling of @a x.
924inline int Ceil(float x) { return int(RoundUp(x)); }
925inline int Ceil(double x) { return int(RoundUp(x)); }
926inline int Ceil(long double x) { return int(RoundUp(x)); }
927//@}
928
929
930/// Return @a x if it is greater or equal in magnitude than @a delta. Otherwise, return zero.
931template<typename Type>
932inline Type Chop(Type x, Type delta) { return (Abs(x) < delta ? zeroVal<Type>() : x); }
933
934
935/// Return @a x truncated to the given number of decimal digits.
936template<typename Type>
937inline Type
938Truncate(Type x, unsigned int digits)
939{
940 Type tenth = static_cast<Type>(Pow(size_t(10), digits));
941 return RoundDown(x*tenth+0.5)/tenth;
942}
943
944////////////////////////////////////////
945
946
947/// @brief 8-bit integer values print to std::ostreams as characters.
948/// Cast them so that they print as integers instead.
949template<typename T>
950inline auto PrintCast(const T& val) -> typename std::enable_if<!std::is_same<T, int8_t>::value
951 && !std::is_same<T, uint8_t>::value, const T&>::type { return val; }
952inline int32_t PrintCast(int8_t val) { return int32_t(val); }
953inline uint32_t PrintCast(uint8_t val) { return uint32_t(val); }
954
955
956////////////////////////////////////////
957
958
959/// Return the inverse of @a x.
960template<typename Type>
961inline Type
962Inv(Type x)
963{
965 return Type(1)/x;
966}
967
968
969enum Axis {
973};
974
975// enum values are consistent with their historical mx analogs.
986
987template <typename S, typename T, typename = std::enable_if_t<openvdb::is_arithmetic_v<S>&& openvdb::is_arithmetic_v<T>>>
988struct promote {
989 using type = typename std::common_type_t<S,T>;
990};
991
992
993/// @brief Return the index [0,1,2] of the smallest value in a 3D vector.
994/// @note This methods assumes operator[] exists.
995/// @details The return value corresponds to the largest index of the of
996/// the smallest vector components.
997template<typename Vec3T>
998size_t
999MinIndex(const Vec3T& v)
1000{
1001 size_t r = 0;
1002 for (size_t i = 1; i < 3; ++i) {
1003 // largest index (backwards compatibility)
1004 if (v[i] <= v[r]) r = i;
1005 }
1006 return r;
1007}
1008
1009/// @brief Return the index [0,1,2] of the largest value in a 3D vector.
1010/// @note This methods assumes operator[] exists.
1011/// @details The return value corresponds to the largest index of the of
1012/// the largest vector components.
1013template<typename Vec3T>
1014size_t
1015MaxIndex(const Vec3T& v)
1016{
1017 size_t r = 0;
1018 for (size_t i = 1; i < 3; ++i) {
1019 // largest index (backwards compatibility)
1020 if (v[i] >= v[r]) r = i;
1021 }
1022 return r;
1023}
1024
1025} // namespace math
1026} // namespace OPENVDB_VERSION_NAME
1027} // namespace openvdb
1028
1029#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:443
#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:231
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition Platform.h:232
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:804
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:456
size_t MaxIndex(const Vec3T &v)
Return the index [0,1,2] of the largest value in a 3D vector.
Definition Math.h:1015
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition Math.h:855
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x².
Definition Math.h:300
bool isApproxZero(const Type &x, const Type &tolerance)
Return true if x is equal to zero to within the given tolerance.
Definition Math.h:360
int Ceil(float x)
Return the ceiling of x.
Definition Math.h:924
bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
Definition Math.h:399
Type IntegerPart(Type x)
Return the integer part of x.
Definition Math.h:903
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:583
float Sqrt(float x)
Return the square root of a floating-point value.
Definition Math.h:829
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:428
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition Math.h:475
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition Math.h:643
size_t MinIndex(const Vec3T &v)
Return the index [0,1,2] of the smallest value in a 3D vector.
Definition Math.h:999
bool isFinite(const float x)
Return true if x is finite.
Definition Math.h:385
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:950
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:578
Type EuclideanRemainder(Type x)
Definition Math.h:897
Type Remainder(Type x, Type y)
Definition Math.h:849
Type Inv(Type x)
Return the inverse of x.
Definition Math.h:962
Type Exp(const Type &x)
Return ex.
Definition Math.h:778
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition Math.h:377
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition Math.h:413
int64_t doubleToInt64(const double d)
Definition Math.h:511
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:793
bool isUlpsEqual(const double aLeft, const double aRight, const int64_t aUnitsInLastPlace)
Definition Math.h:525
RandInt< int, std::mt19937 > RandomInt
Definition Math.h:266
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition Math.h:871
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition Math.h:721
Coord Abs(const Coord &xyz)
Definition Coord.h:518
int Mod(int x, int y)
Return the remainder of x / y.
Definition Math.h:845
Type Truncate(Type x, unsigned int digits)
Return x truncated to the given number of decimal digits.
Definition Math.h:938
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:465
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:887
Type Pow3(Type x)
Return x3.
Definition Math.h:574
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:932
Type FractionalPart(Type x)
Return the fractional part of x.
Definition Math.h:911
auto cwiseAdd(const Vec3H &v, const float s)
Definition Types.h:765
internal::half half
Definition HalfDecl.h:25
Axis
Definition Math.h:969
@ Z_AXIS
Definition Math.h:972
@ X_AXIS
Definition Math.h:970
@ Y_AXIS
Definition Math.h:971
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:784
int32_t floatToInt32(const float f)
Definition Math.h:501
Type Pow2(Type x)
Return x2.
Definition Math.h:570
RotationOrder
Definition Math.h:976
@ YXZ_ROTATION
Definition Math.h:979
@ ZXY_ROTATION
Definition Math.h:981
@ YZX_ROTATION
Definition Math.h:980
@ ZXZ_ROTATION
Definition Math.h:984
@ XZX_ROTATION
Definition Math.h:983
@ XYZ_ROTATION
Definition Math.h:977
@ ZYX_ROTATION
Definition Math.h:982
@ XZY_ROTATION
Definition Math.h:978
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition Math.h:837
int Floor(float x)
Return the floor of x.
Definition Math.h:916
bool SignChange(const Type &a, const Type &b)
Return true if a and b have different signs.
Definition Math.h:811
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:821
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:988
typename std::common_type_t< S, T > type
Definition Math.h:989
#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:284