OpenVDB: openvdb/math/Math.h Source File

OpenVDB 9.0.0

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