Version: SMASH-3.2.2
numerics.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2018,2020,2022-2023,2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_NUMERICS_H_
11 #define SRC_INCLUDE_SMASH_NUMERICS_H_
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <cmath>
16 #include <initializer_list>
17 #include <limits>
18 #include <type_traits>
19 
20 #include "constants.h"
21 
31 namespace smash {
32 
33 namespace detail {
34 
58 template <typename N, typename = std::enable_if_t<std::is_floating_point_v<N>>>
59 bool almost_equal_knuthish(const N x, const N y, const N epsilon,
60  const N threshold = N{0.0}) noexcept {
61  assert(epsilon > 0);
62  assert(threshold >= 0);
63  if constexpr (std::numeric_limits<N>::is_iec559) {
64  if (!std::isfinite(x) || !std::isfinite(y)) {
65  return false;
66  }
67  }
68  if (x == y)
69  return true;
70  else if (x == 0)
71  return std::abs(y) <= epsilon;
72  else if (y == 0)
73  return std::abs(x) <= epsilon;
74  else
75  return std::abs(x - y) <= threshold ||
76  std::abs(x - y) <= epsilon * std::max(std::abs(x), std::abs(y));
77 }
78 
79 } // namespace detail
80 
88 template <typename N, typename = std::enable_if_t<std::is_floating_point_v<N>>>
89 bool almost_equal(const N x, const N y) {
90  return detail::almost_equal_knuthish<N>(x, y, static_cast<N>(really_small));
91 }
92 
99 template <typename N, typename = std::enable_if_t<std::is_floating_point_v<N>>>
100 bool almost_equal_physics(const N x, const N y) {
101  const auto threshold = static_cast<N>(really_small);
102  const auto epsilon = static_cast<N>(small_number);
103  return detail::almost_equal_knuthish<N>(x, y, epsilon, threshold);
104 }
105 
120 template <typename T = std::initializer_list<double>>
121 bool is_any_nan(const T& collection) {
122  for (const auto& number : collection) {
123  if (unlikely(std::isnan(number)))
124  return true;
125  }
126  return false;
127 }
128 
129 } // namespace smash
130 
131 #endif // SRC_INCLUDE_SMASH_NUMERICS_H_
Collection of useful constants that are known at compile time.
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
Definition: macros.h:16
bool almost_equal_knuthish(const N x, const N y, const N epsilon, const N threshold=N{0.0}) noexcept
Compare whether two floating-point numbers are approximately equal à la Knuth up to a given tolerance...
Definition: numerics.h:59
Definition: action.h:24
bool almost_equal(const N x, const N y)
Checks whether two floating-point numbers are almost equal.
Definition: numerics.h:89
constexpr double small_number
Physical error tolerance.
Definition: constants.h:51
bool is_any_nan(const T &collection)
Returns whether any element in a collection is NaN.
Definition: numerics.h:121
bool almost_equal_physics(const N x, const N y)
Like smash::almost_equal, but using a less strict tolerance, smash::small_number.
Definition: numerics.h:100
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37