VTK  9.2.5
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
44template <class A>
45bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
46{
47 return fabs(a - b) < epsilon;
48}
49
53template <class A>
54A SafeDivision(A a, A b)
55{
56 // Avoid overflow
57 if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
58 {
59 return std::numeric_limits<A>::max();
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
77template <class A>
78bool 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
110template <class A>
111void 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
126template <class A> // Non floating point implementation not caring about NaN
127void 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
133template <class A> // Floating point implementation specifically considering NaN
134void 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.