VTK  9.2.20220703
vtkMathUtilities.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkMathUtilities.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
30 #ifndef vtkMathUtilities_h
31 #define vtkMathUtilities_h
32 
33 #include <cmath>
34 #include <limits>
35 #include <tuple>
36 #include <type_traits>
37 
39 {
40 
44 template <class A>
45 bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
46 {
47  return fabs(a - b) < epsilon;
48 }
49 
53 template <class A>
54 A SafeDivision(A a, A b)
55 {
56  // Avoid overflow
57  if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
58  {
60  }
61 
62  // Avoid underflow
63  if ((a == static_cast<A>(0)) ||
64  ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
65  {
66  return static_cast<A>(0);
67  }
68 
69  // safe to do the division
70  return (a / b);
71 }
72 
77 template <class A>
78 bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
79 {
80  A absdiff = fabs(a - b);
81  A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
82  A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));
83 
84  return ((d1 <= tol) || (d2 <= tol));
85 }
86 
110 template <class A>
111 void UpdateRangeImpl(A& min0, A& max0, const A& value)
112 {
113  // need temporaries to handle const/non const ref mismatch
114  if (value < min0)
115  {
116  min0 = value;
117  max0 = max0 < value ? value : max0;
118  }
119  else if (value > max0)
120  {
121  min0 = min0 > value ? value : min0;
122  max0 = value;
123  }
124 }
125 
126 template <class A> // Non floating point implementation not caring about NaN
127 void UpdateRange(A& min0, A& max0, const A& value,
128  typename std::enable_if<!std::is_floating_point<A>::value>::type* = 0)
129 {
130  UpdateRangeImpl<A>(min0, max0, value);
131 }
132 
133 template <class A> // Floating point implementation specifically considering NaN
134 void UpdateRange(A& min0, A& max0, const A& value,
135  typename std::enable_if<std::is_floating_point<A>::value>::type* = 0)
136 {
137  if (!std::isnan(value))
138  {
139  UpdateRangeImpl<A>(min0, max0, value);
140  }
141 }
142 
143 } // End vtkMathUtilities namespace.
144 
145 #endif // vtkMathUtilities_h
146 // VTK-HeaderTest-Exclude: vtkMathUtilities.h
void UpdateRange(A &min0, A &max0, const A &value, typename std::enable_if<!std::is_floating_point< A >::value >::type *=0)
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.
@ value
Definition: vtkX3D.h:226
@ type
Definition: vtkX3D.h:522
#define max(a, b)