HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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>
13 #include <openvdb/math/HalfDecl.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) \
58 static_assert(std::is_standard_layout<Type>::value, \
59  #Type" must be a POD type (satisfy StandardLayoutType.)"); \
60 static_assert(std::is_trivial<Type>::value, \
61  #Type" must be a POD type (satisfy TrivialType.)");
62 
63 namespace openvdb {
65 namespace 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.
71 template<typename T> inline constexpr T zeroVal() { return T(0); }
72 /// Return the @c std::string value that corresponds to zero.
73 template<> inline std::string zeroVal<std::string>() { return ""; }
74 /// Return the @c bool value that corresponds to zero.
75 template<> inline constexpr bool zeroVal<bool>() { return false; }
76 
77 
78 /// @note Extends the implementation of std::is_arithmetic to support math::half
79 template<typename T>
80 struct is_arithmetic : std::is_arithmetic<T> {};
81 template<>
82 struct is_arithmetic<math::half> : std::true_type {};
83 // Helper variable template (equivalent to std::is_arithmetic_v)
84 template<typename T>
85 inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
86 
87 namespace 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
93 inline std::string operator+(const std::string& s, bool) { return s; }
94 inline std::string operator+(const std::string& s, int) { return s; }
95 inline std::string operator+(const std::string& s, float) { return s; }
96 inline std::string operator+(const std::string& s, double) { return s; }
97 //@}
98 
99 /// @brief Componentwise adder for POD types.
100 template<typename Type1, typename Type2>
101 inline auto cwiseAdd(const Type1& v, const Type2 s)
102 {
104  return v + s;
106 }
107 
108 /// @brief Componentwise less than for POD types.
109 template<typename Type1, typename Type2>
110 inline bool cwiseLessThan(const Type1& a, const Type2& b)
111 {
113  return a < b;
115 }
116 
117 /// @brief Componentwise greater than for POD types.
118 template<typename Type1, typename Type2>
119 inline 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
130 template <typename T> inline constexpr T pi() { return 3.141592653589793238462643383279502884e+00; }
131 template <> inline constexpr float pi() { return 3.141592653589793238462643383279502884e+00F; }
132 template <> inline constexpr double pi() { return 3.141592653589793238462643383279502884e+00; }
133 template <> 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.
139 template<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.
152 template<> inline bool negative(const bool& val) { return !val; }
153 /// Return the "negation" of the given string.
154 template<> inline std::string negative(const std::string& val) { return val; }
155 
156 
157 //@{
158 /// Tolerance for floating-point comparison
159 template<typename T> struct Tolerance { static T value() { return zeroVal<T>(); } };
160 template<> struct Tolerance<math::half> { static math::half value() { return math::half(0.00097656f); } };
161 template<> struct Tolerance<float> { static float value() { return 1e-8f; } };
162 template<> struct Tolerance<double> { static double value() { return 1e-15; } };
163 //@}
164 
165 //@{
166 /// Delta for small floating-point offsets
167 template<typename T> struct Delta { static T value() { return zeroVal<T>(); } };
168 template<> struct Delta<math::half> { static math::half value() { return math::half(0.00390625f); } };
169 template<> struct Delta<float> { static float value() { return 1e-5f; } };
170 template<> 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
178 template<typename FloatType = double, typename EngineType = std::mt19937>
179 class Rand01
180 {
181 private:
182  EngineType mEngine;
183  std::uniform_real_distribution<FloatType> mRand;
184 
185 public:
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
214 template<typename IntType = int, typename EngineType = std::mt19937>
215 class RandInt
216 {
217 private:
218  using Distr = std::uniform_int_distribution<IntType>;
219  EngineType mEngine;
220  Distr mRand;
221 
222 public:
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]
272 template<typename Type>
273 inline Type
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]
282 template<typename Type>
283 inline Type
284 Clamp01(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]
288 template<typename Type>
289 inline 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;.
298 template<typename Type>
299 inline 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).
307 template<typename Type>
308 inline Type
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.
321 inline int32_t Abs(int32_t i) { return std::abs(i); }
322 inline 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 }
328 inline float Abs(float x) { return std::fabs(x); }
329 inline double Abs(double x) { return std::fabs(x); }
330 inline long double Abs(long double x) { return std::fabs(x); }
331 inline uint32_t Abs(uint32_t i) { return i; }
332 inline uint64_t Abs(uint64_t i) { return i; }
333 inline bool Abs(bool b) { return b; }
334 // On systems like macOS and FreeBSD, size_t and uint64_t are different types
335 template <typename T>
337 Abs(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.
348 template<typename Type>
349 inline bool
350 isZero(const Type& x)
351 {
353  return x == zeroVal<Type>();
355 }
356 
357 
358 /// @brief Return @c true if @a x is equal to zero to within
359 /// the default floating-point comparison tolerance.
360 template<typename Type>
361 inline bool
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.
369 template<typename Type>
370 inline bool
371 isApproxZero(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.
378 template<typename Type>
379 inline bool
380 isNegative(const Type& x) { return x < zeroVal<Type>(); }
381 
382 // Return false, since bool values are never less than zero.
383 template<> inline bool isNegative<bool>(const bool&) { return false; }
384 
385 
386 /// Return @c true if @a x is finite.
387 inline bool
388 isFinite(const float x) { return std::isfinite(x); }
389 
390 /// Return @c true if @a x is finite.
391 inline bool
392 isFinite(const math::half x) { return x.isFinite(); }
393 
394 /// Return @c true if @a x is finite.
396 inline bool
397 isFinite(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).
401 inline bool
402 isInfinite(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).
405 inline bool
406 isInfinite(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).
410 inline bool
411 isInfinite(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.
415 inline bool
416 isNan(const float x) { return std::isnan(x); }
417 
418 /// Return @c true if @a x is a NaN (Not-A-Number) value.
419 inline bool
420 isNan(const math::half x) { return x.isNan(); }
421 
422 /// Return @c true if @a x is a NaN (Not-A-Number) value.
424 inline bool
425 isNan(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.
429 template<typename Type>
430 inline bool
431 isApproxEqual(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.
438 template<typename Type>
439 inline bool
440 isApproxEqual(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.
457 template<typename Type>
458 inline bool
459 isApproxLarger(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.
466 template<typename T0, typename T1>
467 inline bool
468 isExactlyEqual(const T0& a, const T1& b)
469 {
471  return a == b;
473 }
474 
475 
476 template<typename Type>
477 inline bool
478 isRelOrApproxEqual(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 
496 template<>
497 inline bool
498 isRelOrApproxEqual(const bool& a, const bool& b, const bool&, const bool&)
499 {
500  return (a == b);
501 }
502 
503 inline int32_t
504 floatToInt32(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 
513 inline int64_t
514 doubleToInt64(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
527 inline bool
528 isUlpsEqual(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 
546 inline bool
547 isUlpsEqual(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>.
572 template<typename Type>
573 inline Type Pow2(Type x) { return x*x; }
574 
575 /// Return @a x<sup>3</sup>.
576 template<typename Type>
577 inline Type Pow3(Type x) { return x*x*x; }
578 
579 /// Return @a x<sup>4</sup>.
580 template<typename Type>
581 inline Type Pow4(Type x) { return Pow2(Pow2(x)); }
582 
583 /// Return @a x<sup>n</sup>.
584 template<typename Type>
585 Type
586 Pow(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>.
599 inline 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>.
608 inline float
609 Pow(float b, float e)
610 {
611  OPENVDB_ASSERT( b >= 0.0f && "Pow(float,float): base is negative" );
612  return powf(b,e);
613 }
614 
615 inline double
616 Pow(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 
626 namespace internal {
627 
628 inline const math::half&
630 {
631  return a < b ? b : a;
632 }
633 
634 template<typename Type>
635 inline const Type&
636 max_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
644 template<typename Type>
645 inline const Type&
646 Max(const Type& a, const Type& b)
647 {
648  return internal::max_impl(a,b);
649 }
650 
651 /// Return the maximum of three values
652 template<typename Type>
653 inline const Type&
654 Max(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
660 template<typename Type>
661 inline const Type&
662 Max(const Type& a, const Type& b, const Type& c, const Type& d)
663 {
665 }
666 
667 /// Return the maximum of five values
668 template<typename Type>
669 inline const Type&
670 Max(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
676 template<typename Type>
677 inline const Type&
678 Max(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
684 template<typename Type>
685 inline const Type&
686 Max(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
693 template<typename Type>
694 inline const Type&
695 Max(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 
704 namespace internal {
705 
706 inline const math::half&
708 {
709  return b < a ? b : a;
710 }
711 
712 template<typename Type>
713 inline const Type&
714 min_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
722 template<typename Type>
723 inline const Type&
724 Min(const Type& a, const Type& b) { return internal::min_impl(a, b); }
725 
726 /// Return the minimum of three values
727 template<typename Type>
728 inline const Type&
729 Min(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
735 template<typename Type>
736 inline const Type&
737 Min(const Type& a, const Type& b, const Type& c, const Type& d)
738 {
740 }
741 
742 /// Return the minimum of five values
743 template<typename Type>
744 inline const Type&
745 Min(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
751 template<typename Type>
752 inline const Type&
753 Min(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
759 template<typename Type>
760 inline const Type&
761 Min(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
768 template<typename Type>
769 inline const Type&
770 Min(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>.
780 template<typename Type>
781 inline Type Exp(const Type& x) { return std::exp(x); }
782 
783 // ============> Sin <==================
784 
785 //@{
786 /// Return sin @a x.
787 inline float Sin(const float& x) { return std::sin(x); }
788 
789 inline double Sin(const double& x) { return std::sin(x); }
790 //@}
791 
792 // ============> Cos <==================
793 
794 //@{
795 /// Return cos @a x.
796 inline float Cos(const float& x) { return std::cos(x); }
797 
798 inline 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).
806 template <typename Type>
807 inline 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.
812 template <typename Type>
813 inline bool
814 SignChange(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.
822 template <typename Type>
823 inline bool
824 ZeroCrossing(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.
832 inline float Sqrt(float x) { return std::sqrt(x); }
833 inline double Sqrt(double x) { return std::sqrt(x); }
834 inline long double Sqrt(long double x) { return std::sqrt(x); }
835 //@}
836 
837 
838 //@{
839 /// Return the cube root of a floating-point value.
840 inline float Cbrt(float x) { return std::cbrt(x); }
841 inline double Cbrt(double x) { return std::cbrt(x); }
842 inline long double Cbrt(long double x) { return std::cbrt(x); }
843 //@}
844 
845 
846 //@{
847 /// Return the remainder of @a x / @a y.
848 inline int Mod(int x, int y) { return (x % y); }
849 inline float Mod(float x, float y) { return std::fmod(x, y); }
850 inline double Mod(double x, double y) { return std::fmod(x, y); }
851 inline long double Mod(long double x, long double y) { return std::fmod(x, y); }
852 template<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.
858 inline float RoundUp(float x) { return std::ceil(x); }
859 inline double RoundUp(double x) { return std::ceil(x); }
860 inline long double RoundUp(long double x) { return std::ceil(x); }
861 //@}
862 /// Return @a x rounded up to the nearest multiple of @a base.
863 template<typename Type>
864 inline Type
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.
874 inline float RoundDown(float x) { return std::floor(x); }
875 inline double RoundDown(double x) { return std::floor(x); }
876 inline long double RoundDown(long double x) { return std::floor(x); }
877 //@}
878 /// Return @a x rounded down to the nearest multiple of @a base.
879 template<typename Type>
880 inline Type
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.
890 inline float Round(float x) { return RoundDown(x + 0.5f); }
891 inline double Round(double x) { return RoundDown(x + 0.5); }
892 inline 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
898 template<typename Type>
899 inline Type
900 EuclideanRemainder(Type x) { return x - RoundDown(x); }
901 
902 
903 /// Return the integer part of @a x.
904 template<typename Type>
905 inline Type
907 {
908  return (x > 0 ? RoundDown(x) : RoundUp(x));
909 }
910 
911 /// Return the fractional part of @a x.
912 template<typename Type>
913 inline Type
914 FractionalPart(Type x) { return Mod(x,Type(1)); }
915 
916 
917 //@{
918 /// Return the floor of @a x.
919 inline int Floor(float x) { return int(RoundDown(x)); }
920 inline int Floor(double x) { return int(RoundDown(x)); }
921 inline int Floor(long double x) { return int(RoundDown(x)); }
922 //@}
923 
924 
925 //@{
926 /// Return the ceiling of @a x.
927 inline int Ceil(float x) { return int(RoundUp(x)); }
928 inline int Ceil(double x) { return int(RoundUp(x)); }
929 inline 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.
934 template<typename Type>
935 inline 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.
939 template<typename Type>
940 inline Type
941 Truncate(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.
952 template<typename T>
954  && !std::is_same<T, uint8_t>::value, const T&>::type { return val; }
955 inline int32_t PrintCast(int8_t val) { return int32_t(val); }
956 inline uint32_t PrintCast(uint8_t val) { return uint32_t(val); }
957 
958 
959 ////////////////////////////////////////
960 
961 
962 /// Return the inverse of @a x.
963 template<typename Type>
964 inline Type
966 {
967  OPENVDB_ASSERT(x);
968  return Type(1)/x;
969 }
970 
971 
972 enum Axis {
973  X_AXIS = 0,
974  Y_AXIS = 1,
975  Z_AXIS = 2
976 };
977 
978 // enum values are consistent with their historical mx analogs.
988 };
989 
990 template <typename S, typename T, typename = std::enable_if_t<openvdb::is_arithmetic_v<S>&& openvdb::is_arithmetic_v<T>>>
991 struct 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.
1000 template<typename Vec3T>
1001 size_t
1002 MinIndex(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.
1016 template<typename Vec3T>
1017 size_t
1018 MaxIndex(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
void setSeed(unsigned int seed)
Set the seed value for the random number generator.
Definition: Math.h:197
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition: Platform.h:245
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Type Inv(Type x)
Return the inverse of x.
Definition: Math.h:965
Type Truncate(Type x, unsigned int digits)
Return x truncated to the given number of decimal digits.
Definition: Math.h:941
int Ceil(float x)
Return the ceiling of x.
Definition: Math.h:927
Simple generator of random numbers over the range [0, 1)
Definition: Math.h:179
bool cwiseGreaterThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition: Mat.h:1029
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:586
Type IntegerPart(Type x)
Return the integer part of x.
Definition: Math.h:906
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
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:468
imath_half_bits_t half
if we're in a C-only context, alias the half bits type to half
Definition: half.h:268
Type Pow2(Type x)
Return x2.
Definition: Math.h:573
IMATH_HOSTDEVICE constexpr int floor(T x) IMATH_NOEXCEPT
Definition: ImathFun.h:112
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:139
const GLdouble * v
Definition: glcorearb.h:837
size_t MaxIndex(const Vec3T &v)
Return the index [0,1,2] of the largest value in a 3D vector.
Definition: Math.h:1018
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:914
GLsizei const GLfloat * value
Definition: glcorearb.h:824
Mat3< Type1 > cwiseAdd(const Mat3< Type1 > &m, const Type2 s)
Definition: Mat3.h:805
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7694
GLboolean GLboolean g
Definition: glcorearb.h:1222
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:246
const EngineType & engine() const
Return a const reference to the random number generator.
Definition: Math.h:252
float Cos(const float &x)
Return cos x.
Definition: Math.h:796
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLint y
Definition: glcorearb.h:103
Rand01(unsigned int seed)
Initialize the generator.
Definition: Math.h:194
bool SignChange(const Type &a, const Type &b)
Return true if a and b have different signs.
Definition: Math.h:814
typename std::common_type_t< S, T > type
Definition: Math.h:992
float RoundDown(float x)
Return x rounded down to the nearest integer.
Definition: Math.h:874
RandInt(const EngineType &engine, IntType imin, IntType imax)
Initialize the generator.
Definition: Math.h:226
bool isNegative(const Type &x)
Return true if x is less than zero.
Definition: Math.h:380
Tolerance for floating-point comparison.
Definition: Math.h:159
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition: Math.h:858
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition: Math.h:840
Simple random integer generator.
Definition: Math.h:215
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
ImageBuf OIIO_API pow(const ImageBuf &A, cspan< float > B, ROI roi={}, int nthreads=0)
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:71
bool isNegative< bool >(const bool &)
Definition: Math.h:383
constexpr bool isInfinity() const noexcept
Return true if a positive or a negative infinity.
Definition: Half.h:856
GLdouble n
Definition: glcorearb.h:2008
GLfloat f
Definition: glcorearb.h:1926
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
const math::half & max_impl(const math::half &a, const math::half &b)
Definition: Math.h:629
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 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
Coord Abs(const Coord &xyz)
Definition: Coord.h:518
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:890
bool isInfinite(const float x)
Return true if x is an infinity value (either positive infinity or negative infinity).
Definition: Math.h:402
Type Pow4(Type x)
Return x4.
Definition: Math.h:581
Delta for small floating-point offsets.
Definition: Math.h:167
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:832
constexpr bool is_arithmetic_v
Definition: Math.h:85
bool isNan(const float x)
Return true if x is a NaN (Not-A-Number) value.
Definition: Math.h:416
Type Pow3(Type x)
Return x3.
Definition: Math.h:577
bool cwiseLessThan(const Mat< SIZE, T > &m0, const Mat< SIZE, T > &m1)
Definition: Mat.h:1015
bool isRelOrApproxEqual(const Type &a, const Type &b, const Type &absTol, const Type &relTol)
Definition: Math.h:478
#define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
Definition: Math.h:49
bool isUlpsEqual(const double aLeft, const double aRight, const int64_t aUnitsInLastPlace)
Definition: Math.h:528
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
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition: Math.h:274
#define OPENVDB_EXACT_IS_APPROX_EQUAL(T)
Definition: Math.h:446
RandInt(unsigned int seed, IntType imin, IntType imax)
Initialize the generator.
Definition: Math.h:234
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
IMATH_HOSTDEVICE constexpr int ceil(T x) IMATH_NOEXCEPT
Definition: ImathFun.h:119
int Sign(const Type &x)
Return the sign of the given value as an integer (either -1, 0 or 1).
Definition: Math.h:807
IMATH_NAMESPACE::V2f IMATH_NAMESPACE::Box2i std::string this attribute is obsolete as of OpenEXR v3 float
Library and file format version numbers.
void setSeed(unsigned int seed)
Set the seed value for the random number generator.
Definition: Math.h:246
#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
int32_t floatToInt32(const float f)
Definition: Math.h:504
int64_t doubleToInt64(const double d)
Definition: Math.h:514
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GLuint GLfloat * val
Definition: glcorearb.h:1608
constexpr bool isNan() const noexcept
Return true if NAN.
Definition: Half.h:850
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:724
double cbrt(double x)
const EngineType & engine() const
Return a const reference to the random number generator.
Definition: Math.h:203
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
constexpr T pi()
Pi constant taken from Boost to match old behaviour.
Definition: Math.h:130
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
int Floor(float x)
Return the floor of x.
Definition: Math.h:919
bool ClampTest01(Type &x)
Return true if x is outside [0,1].
Definition: Math.h:290
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
constexpr bool zeroVal< bool >()
Return the bool value that corresponds to zero.
Definition: Math.h:75
IntType operator()()
Return a randomly-generated integer in the current range.
Definition: Math.h:255
float Sin(const float &x)
Return sin x.
Definition: Math.h:787
GLboolean r
Definition: glcorearb.h:1222
const math::half & min_impl(const math::half &a, const math::half &b)
Definition: Math.h:707
Rand01(const EngineType &engine)
Initialize the generator.
Definition: Math.h:190
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x .
Definition: Math.h:300
constexpr bool isFinite() const noexcept
Definition: Half.h:826
void setRange(IntType imin, IntType imax)
Change the range over which integers are distributed to [imin, imax].
Definition: Math.h:240
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:119
Type Remainder(Type x, Type y)
Return the remainder of x / y.
Definition: Math.h:852
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:646
int Mod(int x, int y)
Return the remainder of x / y.
Definition: Math.h:848
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
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:350
bool isFinite(const float x)
Return true if x is finite.
Definition: Math.h:388
Type Exp(const Type &x)
Return ex.
Definition: Math.h:781
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
FloatType operator()()
Return a uniformly distributed random number in the range [0, 1).
Definition: Math.h:206
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition: Math.h:284
#define OPENVDB_NO_FP_EQUALITY_WARNING_END
Definition: Math.h:50
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