VTK  9.2.6
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
26
27#ifndef vtkMathUtilities_h
28#define vtkMathUtilities_h
29
30#include <cmath>
31#include <limits>
32#include <tuple>
33#include <type_traits>
34
36{
37
41template <class A>
42bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
43{
44 return fabs(a - b) < epsilon;
45}
46
50template <class A>
51A SafeDivision(A a, A b)
52{
53 // Avoid overflow
54 if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
55 {
56 return std::numeric_limits<A>::max();
57 }
58
59 // Avoid underflow
60 if ((a == static_cast<A>(0)) ||
61 ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
62 {
63 return static_cast<A>(0);
64 }
65
66 // safe to do the division
67 return (a / b);
68}
69
74template <class A>
75bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
76{
77 A absdiff = fabs(a - b);
78 A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
79 A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));
80
81 return ((d1 <= tol) || (d2 <= tol));
82}
83
107template <class A>
108void UpdateRangeImpl(A& min0, A& max0, const A& value)
109{
110 // need temporaries to handle const/non const ref mismatch
111 if (value < min0)
112 {
113 min0 = value;
114 max0 = max0 < value ? value : max0;
115 }
116 else if (value > max0)
117 {
118 min0 = min0 > value ? value : min0;
119 max0 = value;
120 }
121}
122
123template <class A> // Non floating point implementation not caring about NaN
124void UpdateRange(A& min0, A& max0, const A& value,
125 typename std::enable_if<!std::is_floating_point<A>::value>::type* = 0)
126{
127 UpdateRangeImpl<A>(min0, max0, value);
128}
129
130template <class A> // Floating point implementation specifically considering NaN
131void UpdateRange(A& min0, A& max0, const A& value,
132 typename std::enable_if<std::is_floating_point<A>::value>::type* = 0)
133{
134 if (!std::isnan(value))
135 {
136 UpdateRangeImpl<A>(min0, max0, value);
137 }
138}
139
140} // End vtkMathUtilities namespace.
141
142#endif // vtkMathUtilities_h
143// 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.