VTK  9.4.20241108
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{
30VTK_ABI_NAMESPACE_BEGIN
31
36template <class A>
37bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
38{
39 return fabs(a - b) < epsilon;
40}
41
45template <class A>
46A SafeDivision(A a, A b)
47{
48 // Avoid overflow
49 if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
50 {
51 return std::numeric_limits<A>::max();
52 }
53
54 // Avoid underflow
55 if ((a == static_cast<A>(0)) ||
56 ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
57 {
58 return static_cast<A>(0);
59 }
60
61 // safe to do the division
62 return (a / b);
63}
64
70template <class A>
71bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
72{
73 A absdiff = fabs(a - b);
74 A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
75 A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));
76
77 return ((d1 <= tol) || (d2 <= tol));
78}
79
103template <class A>
104void UpdateRangeImpl(A& min0, A& max0, const A& value)
105{
106 // need temporaries to handle const/non const ref mismatch
107 if (value < min0)
108 {
109 min0 = value;
110 max0 = max0 < value ? value : max0;
111 }
112 else if (value > max0)
113 {
114 min0 = min0 > value ? value : min0;
115 max0 = value;
116 }
117}
118
119template <class A> // Non floating point implementation not caring about NaN
120void UpdateRange(A& min0, A& max0, const A& value,
121 typename std::enable_if<!std::is_floating_point<A>::value>::type* = nullptr)
122{
123 UpdateRangeImpl<A>(min0, max0, value);
124}
125
126template <class A> // Floating point implementation specifically considering NaN
127void UpdateRange(A& min0, A& max0, const A& value,
128 typename std::enable_if<std::is_floating_point<A>::value>::type* = nullptr)
129{
130 if (!std::isnan(value))
131 {
132 UpdateRangeImpl<A>(min0, max0, value);
133 }
134}
135
136VTK_ABI_NAMESPACE_END
137} // End vtkMathUtilities namespace.
138
139#endif // vtkMathUtilities_h
140// 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 NB: this uses an absolute to...
void UpdateRange(A &min0, A &max0, const A &value, typename std::enable_if<!std::is_floating_point< A >::value >::type *=nullptr)