File: vtkMathUtilities.h

package info (click to toggle)
paraview 5.11.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 497,236 kB
  • sloc: cpp: 3,171,290; ansic: 1,315,072; python: 134,290; xml: 103,324; sql: 65,887; sh: 5,286; javascript: 4,901; yacc: 4,383; java: 3,977; perl: 2,363; lex: 1,909; f90: 1,255; objc: 143; makefile: 119; tcl: 59; pascal: 50; fortran: 29
file content (147 lines) | stat: -rw-r--r-- 3,969 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMathUtilities.h

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

/**
 * @class   vtkMathUtilities
 * @brief   templated utility math functions intended for
 * internal use in tests etc.
 *
 *
 * Provide a set of inline, lightweight templated math utility functions.
 * The initial motivation is to provide a few lightweight functions to help in
 * testing and internal implementation files.
 */

#ifndef vtkMathUtilities_h
#define vtkMathUtilities_h

#include "vtkABINamespace.h"

#include <cmath>
#include <limits>
#include <tuple>
#include <type_traits>

namespace vtkMathUtilities
{
VTK_ABI_NAMESPACE_BEGIN

/**
 * Perform a fuzzy compare of floats/doubles, specify the allowed tolerance
 */
template <class A>
bool FuzzyCompare(A a, A b, A epsilon = std::numeric_limits<A>::epsilon())
{
  return fabs(a - b) < epsilon;
}

/**
 * Performs safe division that catches overflow and underflow.
 */
template <class A>
A SafeDivision(A a, A b)
{
  // Avoid overflow
  if ((b < static_cast<A>(1)) && (a > b * std::numeric_limits<A>::max()))
  {
    return std::numeric_limits<A>::max();
  }

  // Avoid underflow
  if ((a == static_cast<A>(0)) ||
    ((b > static_cast<A>(1)) && (a < b * std::numeric_limits<A>::min())))
  {
    return static_cast<A>(0);
  }

  // safe to do the division
  return (a / b);
}

/**
 * A slightly different fuzzy comparator that checks if two values are
 * "nearly" equal based on Knuth, "The Art of Computer Programming (vol II)"
 */
template <class A>
bool NearlyEqual(A a, A b, A tol = std::numeric_limits<A>::epsilon())
{
  A absdiff = fabs(a - b);
  A d1 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(a));
  A d2 = vtkMathUtilities::SafeDivision<A>(absdiff, fabs(b));

  return ((d1 <= tol) || (d2 <= tol));
}

/**
 * Update an existing min - max range with a new prospective value.  If the
 * value is non NaN then the appropriate range comparisons are made and
 * updated, otherwise the original min - max values are set.
 *
 * Examples:
 *
 *   No change:
 *   UpdateRange(-100, 100, 20) -> (-100, 100)
 *
 *   Update min:
 *   UpdateRange(-100, 100, -200) -> (-200, 100)
 *
 *   Update max:
 *   UpdateRange(-100, 100, 200) -> (-100, 200)
 *
 *   Input min and max are inverted creating an invalid range so a new range
 *   with the specified value is set:
 *   UpdateRange(100, -100, 20) -> (20, 20)
 *
 *   Input value is NaN so the original range is set
 *   UpdateRange(-100, 100, NaN) -> (-100, 100)
 */
template <class A>
void UpdateRangeImpl(A& min0, A& max0, const A& value)
{
  // need temporaries to handle const/non const ref mismatch
  if (value < min0)
  {
    min0 = value;
    max0 = max0 < value ? value : max0;
  }
  else if (value > max0)
  {
    min0 = min0 > value ? value : min0;
    max0 = value;
  }
}

template <class A> // Non floating point implementation not caring about NaN
void UpdateRange(A& min0, A& max0, const A& value,
  typename std::enable_if<!std::is_floating_point<A>::value>::type* = nullptr)
{
  UpdateRangeImpl<A>(min0, max0, value);
}

template <class A> // Floating point implementation specifically considering NaN
void UpdateRange(A& min0, A& max0, const A& value,
  typename std::enable_if<std::is_floating_point<A>::value>::type* = nullptr)
{
  if (!std::isnan(value))
  {
    UpdateRangeImpl<A>(min0, max0, value);
  }
}

VTK_ABI_NAMESPACE_END
} // End vtkMathUtilities namespace.

#endif // vtkMathUtilities_h
// VTK-HeaderTest-Exclude: vtkMathUtilities.h