VTK  9.5.20251114
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#include "vtkAssume.h"
23
24#include <algorithm>
25#include <cmath>
26#include <limits>
27#include <tuple>
28#include <type_traits>
29
31{
32VTK_ABI_NAMESPACE_BEGIN
33
38template <class A>
39bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
40{
41 return fabs(a - b) < epsilon;
42}
43
47template <class A>
48A SafeDivision(A a, A b)
49{
50 // Avoid overflow
51 if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
52 {
53 return std::numeric_limits<A>::max();
54 }
55
56 // Avoid underflow
57 if ((a == static_cast<A>(0)) ||
58 ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
59 {
60 return static_cast<A>(0);
61 }
62
63 // safe to do the division
64 return (a / b);
65}
66
72template <class A>
73bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
74{
75 A absdiff = fabs(a - b);
76 A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
77 A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));
78
79 return ((d1 <= tol) || (d2 <= tol));
80}
81
105template <class A>
106inline void UpdateRange(A& min, A& max, const A& value)
107{
108 if constexpr (std::is_floating_point_v<A>)
109 {
110 if (VTK_UNLIKELY(std::isnan(value)))
111 {
112 return;
113 }
114 }
115 if (value < min)
116 {
117 min = value;
118 max = std::max(max, value);
119 }
120 else if (value > max)
121 {
122 min = std::min(min, value);
123 max = value;
124 }
125}
126
132template <class A>
133inline void UpdateRangeFinite(A& min, A& max, const A& value)
134{
135 if constexpr (std::is_floating_point_v<A>)
136 {
137 if (VTK_UNLIKELY(std::isinf(value) || std::isnan(value)))
138 {
139 return;
140 }
141 }
142 if (value < min)
143 {
144 min = value;
145 max = std::max(max, value);
146 }
147 else if (value > max)
148 {
149 min = std::min(min, value);
150 max = value;
151 }
152}
153
154VTK_ABI_NAMESPACE_END
155} // End vtkMathUtilities namespace.
156
157#endif // vtkMathUtilities_h
158// VTK-HeaderTest-Exclude: vtkMathUtilities.h
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.
void UpdateRange(A &min, A &max, const A &value)
Update an existing min - max range with a new prospective value.
void UpdateRangeFinite(A &min, A &max, const A &value)
Update an existing min - max range with a new prospective value.
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...
#define VTK_UNLIKELY(cond)
Definition vtkAssume.h:79
#define max(a, b)