Himalaya
Numerics.hpp
Go to the documentation of this file.
1 // ====================================================================
2 // This file is part of Himalaya.
3 //
4 // Himalaya is licenced under the GNU General Public License (GNU GPL)
5 // version 3.
6 // ====================================================================
7 
8 #pragma once
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <limits>
13 #include <type_traits>
14 
15 namespace himalaya {
16 namespace {
17 
18 /// absolute
19 template <typename T>
20 constexpr T dabs(T a) noexcept
21 {
22  return a >= T{0} ? a : -a;
23 }
24 
25 /// compares a number for being close to zero
26 template <typename T>
27 constexpr typename std::enable_if<!std::is_unsigned<T>::value, bool>::type
28 is_zero(T a, T prec = std::numeric_limits<T>::epsilon()) noexcept
29 {
30  return dabs(a) <= prec;
31 }
32 
33 /// compares two numbers for absolute equality
34 template <typename T>
35 constexpr bool is_equal(T a, T b, T prec = std::numeric_limits<T>::epsilon()) noexcept
36 {
37  return is_zero(a - b, prec);
38 }
39 
40 /// compares two numbers for relative equality, treating numbers with
41 /// small differences as equal
42 template <typename T>
43 constexpr bool is_equal_rel(T a, T b, T prec = std::numeric_limits<T>::epsilon()) noexcept
44 {
45  if (is_equal(a, b, std::numeric_limits<T>::epsilon()))
46  return true;
47 
48  const T min = std::min(dabs(a), dabs(b));
49 
50  if (min < std::numeric_limits<T>::epsilon()) {
51  return is_equal(a, b, prec);
52  }
53 
54  const T max = std::max(dabs(a), dabs(b));
55 
56  return is_equal(a, b, prec*max);
57 }
58 
59 /// compares two numbers for relative equality
60 template <typename T>
61 constexpr bool is_close(T a, T b, T prec = std::numeric_limits<T>::epsilon()) noexcept
62 {
63  const T max = std::max(dabs(a), dabs(b));
64  return is_zero(a - b, prec*(1 + max));
65 }
66 
67 } // anonymous namespace
68 } // namespace himalaya
Definition: H3.cpp:14