VTK  9.3.0
vtkMathUtilities.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 
18 #ifndef vtkMathUtilities_h
19 #define vtkMathUtilities_h
20 
21 #include "vtkABINamespace.h"
22 
23 #include <cmath>
24 #include <limits>
25 #include <tuple>
26 #include <type_traits>
27 
29 {
30 VTK_ABI_NAMESPACE_BEGIN
31 
35 template <class A>
36 bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
37 {
38  return fabs(a - b) < epsilon;
39 }
40 
44 template <class A>
45 A SafeDivision(A a, A b)
46 {
47  // Avoid overflow
48  if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
49  {
51  }
52 
53  // Avoid underflow
54  if ((a == static_cast<A>(0)) ||
55  ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
56  {
57  return static_cast<A>(0);
58  }
59 
60  // safe to do the division
61  return (a / b);
62 }
63 
68 template <class A>
69 bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
70 {
71  A absdiff = fabs(a - b);
72  A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
73  A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));
74 
75  return ((d1 <= tol) || (d2 <= tol));
76 }
77 
101 template <class A>
102 void UpdateRangeImpl(A& min0, A& max0, const A& value)
103 {
104  // need temporaries to handle const/non const ref mismatch
105  if (value < min0)
106  {
107  min0 = value;
108  max0 = max0 < value ? value : max0;
109  }
110  else if (value > max0)
111  {
112  min0 = min0 > value ? value : min0;
113  max0 = value;
114  }
115 }
116 
117 template <class A> // Non floating point implementation not caring about NaN
118 void UpdateRange(A& min0, A& max0, const A& value,
119  typename std::enable_if<!std::is_floating_point<A>::value>::type* = nullptr)
120 {
121  UpdateRangeImpl<A>(min0, max0, value);
122 }
123 
124 template <class A> // Floating point implementation specifically considering NaN
125 void UpdateRange(A& min0, A& max0, const A& value,
126  typename std::enable_if<std::is_floating_point<A>::value>::type* = nullptr)
127 {
128  if (!std::isnan(value))
129  {
130  UpdateRangeImpl<A>(min0, max0, value);
131  }
132 }
133 
134 VTK_ABI_NAMESPACE_END
135 } // End vtkMathUtilities namespace.
136 
137 #endif // vtkMathUtilities_h
138 // VTK-HeaderTest-Exclude: vtkMathUtilities.h
void UpdateRangeImpl(A &min0, A &max0, const A &value)
Update an existing min - max range with a new prospective value.
bool NearlyEqual(A a, A b, A tol=std::numeric_limits< A >::epsilon())
A slightly different fuzzy comparator that checks if two values are "nearly" equal based on Knuth,...
A SafeDivision(A a, A b)
Performs safe division that catches overflow and underflow.
bool FuzzyCompare(A a, A b, A epsilon=std::numeric_limits< A >::epsilon())
Perform a fuzzy compare of floats/doubles, specify the allowed tolerance.
void UpdateRange(A &min0, A &max0, const A &value, typename std::enable_if<!std::is_floating_point< A >::value >::type *=nullptr)
@ value
Definition: vtkX3D.h:220
@ type
Definition: vtkX3D.h:516
#define max(a, b)