General Utility Library for C++14  2.11
num_util.h
Go to the documentation of this file.
1 
23 #ifndef GUL14_NUM_UTIL_H_
24 #define GUL14_NUM_UTIL_H_
25 
26 #include <algorithm>
27 #include <cmath>
28 #include <limits>
29 #include <type_traits>
30 
31 #include "gul14/internal.h"
32 
33 namespace gul14 {
34 
52 template<typename ValueT>
53 constexpr auto abs(ValueT n) noexcept -> std::enable_if_t<std::is_unsigned<ValueT>::value, ValueT>
54 {
55  return n;
56 }
57 
61 template<typename ValueT>
62 constexpr auto abs(ValueT n) noexcept -> std::enable_if_t<not std::is_unsigned<ValueT>::value, ValueT>
63 {
64  return std::abs(n);
65 }
66 
92 template<typename NumT, typename OrderT,
93  typename = std::enable_if_t<
94  std::is_arithmetic<NumT>::value
95  and std::is_arithmetic<OrderT>::value
96  >>
97 bool within_orders(const NumT a, const NumT b, const OrderT orders) noexcept(false) {
98  // std::pow() is not noexcept, which might or might not be true
99  auto difference = gul14::abs(a - b);
100  if (difference == NumT{ 0 })
101  return true;
102  auto maximum = std::max(gul14::abs(a), gul14::abs(b));
103  auto limit = maximum / std::pow(static_cast<std::decay_t<NumT>>(10.0), orders);
104  return difference < limit;
105 }
106 
118 template<typename NumT>
119 bool within_abs(NumT a, NumT b, NumT tol) noexcept {
120  tol = gul14::abs(tol); // Negative diff does not make sense
121  bool ret{};
122  if (a > b) {
123  if (std::is_floating_point<NumT>::value)
124  ret = a - tol <= b; // different formula needed because of inf/-inf and subnormal values
125  else
126  ret = a - b <= tol;
127  } else {
128  if (std::is_floating_point<NumT>::value)
129  ret = b - tol <= a;
130  else
131  ret = b - a <= tol;
132  }
133  return ret;
134 }
135 
152 template<typename NumT,
153  typename = std::enable_if_t<std::is_floating_point<NumT>::value>>
154 bool within_ulp(NumT a, NumT b, unsigned int ulp)
155 {
156  if (a == b)
157  return true;
158  auto diff = std::abs(a - b);
159  auto maxval = std::max(std::abs(a), std::abs(b));
160 
161  // NORMAL cases
162  if (std::isnormal(maxval))
163  {
164  return diff <= std::numeric_limits<NumT>::epsilon()
165  * static_cast<NumT>(ulp) * maxval;
166  }
167 
168  // SUBNORMAL cases
169  if (std::isfinite(maxval))
170  return diff <= std::numeric_limits<NumT>::denorm_min() * static_cast<NumT>(ulp);
171 
172  // NAN and INF cases: Two NANs or (a xor b is (-)INF) or (INF, -INF pair)
173  return false;
174 }
175 
207 template<class NumT>
208 constexpr const NumT& clamp(const NumT& v, const NumT& lo, const NumT& hi) {
209  return std::max(lo, std::min(v, hi)); // usually more optimized than actually using operator<()
210 }
234 template<class NumT, class Compare>
235 constexpr const NumT& clamp(const NumT& v, const NumT& lo, const NumT& hi, Compare comp) {
236  if (comp(v, lo))
237  return lo;
238  if (comp(hi, v))
239  return hi;
240  return v;
241 }
242 
244 
245 } // namespace gul14
246 
247 #endif
248 
249 // vi:ts=4:sw=4:et
constexpr auto abs(ValueT n) noexcept -> std::enable_if_t< std::is_unsigned< ValueT >::value, ValueT >
Compute the absolute value of a number.
Definition: num_util.h:53
bool within_abs(NumT a, NumT b, NumT tol) noexcept
Determine if two numbers are almost equal, allowing for an absolute difference.
Definition: num_util.h:119
bool within_ulp(NumT a, NumT b, unsigned int ulp)
Determine if two numbers are almost equal, allowing for a difference of a given number of units-in-th...
Definition: num_util.h:154
bool within_orders(const NumT a, const NumT b, const OrderT orders) noexcept(false)
Determine if two numbers are almost equal, comparing only some significant digits.
Definition: num_util.h:97
constexpr const NumT & clamp(const NumT &v, const NumT &lo, const NumT &hi)
Coerce a value to be within a given range.
Definition: num_util.h:208
auto maximum(ContainerT const &container, Accessor accessor=ElementAccessor< ElementT >()) -> DataT
Return the maximum element value in a container.
Definition: statistics.h:314
Definition of macros used internally by GUL.
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26