Molassembler  3.0.0
Molecule graph and conformer library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
FloatingPointComparison.h
Go to the documentation of this file.
1 
13 #ifndef INCLUDE_MOLASSEMBLER_TEMPLTE_CONSTEXPR_FP_COMPARISON_H
14 #define INCLUDE_MOLASSEMBLER_TEMPLTE_CONSTEXPR_FP_COMPARISON_H
15 
17 
18 #include <tuple>
19 #include <cassert>
20 
21 namespace Scine {
22 namespace Molassembler {
23 namespace Temple {
24 
26 namespace Floating {
27 
28 // Floating point comparison helpers
29 template<typename T>
30 constexpr std::enable_if_t<
31  std::is_floating_point<T>::value,
32  bool
33 > isCloseRelative(
34  T a,
35  T b,
36  T relativeTolerance
37 );
38 
39 template<typename T>
40 constexpr std::enable_if_t<
41  std::is_floating_point<T>::value,
42  bool
43 > isCloseAbsolute(
44  T a,
45  T b,
46  T absoluteTolerance
47 );
48 
49 
50 // Implementation details
51 namespace Detail {
52 
53 template<typename T>
54 constexpr std::enable_if_t<
55  std::is_floating_point<T>::value,
56  bool
57 > isCloseRelativeOrAbsolute(
58  T a,
59  T b,
60  T relativeTolerance,
61  T absoluteTolerance
62 );
63 
64 template<typename T>
65 PURITY_STRONG constexpr std::enable_if_t<
66  std::is_floating_point<T>::value,
67  bool
68 > isCloseRelativeOrAbsolute(
69  const T a,
70  const T b,
71  const T relativeTolerance,
72  const T absoluteTolerance
73 ) {
74  if(!(
75  a != std::numeric_limits<T>::infinity()
76  && a != - std::numeric_limits<T>::infinity()
77  && b != std::numeric_limits<T>::infinity()
78  && b != - std::numeric_limits<T>::infinity()
79  && a == a // not NaN
80  && b == b // not NaN
81  )) {
82  throw "isCloseRelativeOrAbsolute cannot handle infinities or NaNs!";
83  }
84 
85  if(!(relativeTolerance >= 0 && absoluteTolerance >= 0)) {
86  throw "isCloseRelativeOrAbsolute: One of either tolerances "
87  "needs to be above zero!";
88  }
89 
90  return(
91  Math::abs(a - b)
92  <= Math::max(
93  relativeTolerance * Math::max(
94  Math::abs(a),
95  Math::abs(b)
96  ),
97  absoluteTolerance
98  )
99  );
100 }
101 
102 } // namespace Detail
103 
104 template<typename T>
105 PURITY_STRONG constexpr std::enable_if_t<
106  std::is_floating_point<T>::value,
107  bool
108 > isCloseRelative(
109  const T a,
110  const T b,
111  const T relativeTolerance
112 ) {
113  return Detail::isCloseRelativeOrAbsolute(
114  a,
115  b,
116  relativeTolerance,
117  T {0}
118  );
119 }
120 
121 template<typename T>
122 PURITY_STRONG constexpr std::enable_if_t<
123  std::is_floating_point<T>::value,
124  bool
125 > isCloseAbsolute(
126  const T a,
127  const T b,
128  const T absoluteTolerance
129 ) {
130  return Detail::isCloseRelativeOrAbsolute(
131  a,
132  b,
133  T {0},
134  absoluteTolerance
135  );
136 }
137 
138 // Comparators exploiting relative and absolute expanded definitions of equality
139 
140 template<typename T>
142 private:
143  const T absoluteTolerance_;
144 
145 public:
146  constexpr ExpandedAbsoluteEqualityComparator(const T absoluteTolerance)
147  : absoluteTolerance_(absoluteTolerance)
148  {
149  assert(
150  absoluteTolerance > 0
151  && absoluteTolerance != std::numeric_limits<T>::infinity()
152  && absoluteTolerance == absoluteTolerance // not NaN
153  );
154  }
155 
156  constexpr bool isLessThan(const T a, const T b) const noexcept {
157  return a < (b - absoluteTolerance_);
158  }
159 
160  constexpr bool isMoreThan(const T a, const T b) const noexcept {
161  return a > (b + absoluteTolerance_);
162  }
163 
164  constexpr bool isLessOrEqual(const T a, const T b) const noexcept {
165  return a < (b + absoluteTolerance_);
166  }
167 
168  constexpr bool isMoreOrEqual(const T a, const T b) const noexcept {
169  return a > (b - absoluteTolerance_);
170  }
171 
172  constexpr bool isEqual(const T a, const T b) const noexcept {
173  return Math::abs(a - b) <= absoluteTolerance_;
174  }
175 
176  constexpr bool isUnequal(const T a, const T b) const noexcept {
177  return !isEqual(a, b);
178  }
179 
181  constexpr bool operator () (const T a, const T b) const noexcept {
182  return isEqual(a, b);
183  }
184 };
185 
186 template<typename T>
188 private:
189  const T relativeTolerance_;
190 
191 public:
192  constexpr ExpandedRelativeEqualityComparator(const T relativeTolerance)
193  : relativeTolerance_(relativeTolerance)
194  {
195  assert(relativeTolerance > 0);
196  }
197 
198  constexpr bool isLessThan(const T a, const T b) const {
199  return (
200  (a < b) && !Detail::isCloseRelativeOrAbsolute(
201  a,
202  b,
203  relativeTolerance_,
204  T {0}
205  )
206  );
207  }
208 
209  constexpr bool isMoreThan(const T a, const T b) const {
210  return (
211  (a > b) && !Detail::isCloseRelativeOrAbsolute(
212  a,
213  b,
214  relativeTolerance_,
215  T {0}
216  )
217  );
218  }
219 
220  constexpr bool isLessOrEqual(const T a, const T b) const {
221  return (
222  (a < b) || Detail::isCloseRelativeOrAbsolute(
223  a,
224  b,
225  relativeTolerance_,
226  T {0}
227  )
228  );
229  }
230 
231  constexpr bool isMoreOrEqual(const T a, const T b) const {
232  return (
233  (a > b) || Detail::isCloseRelativeOrAbsolute(
234  a,
235  b,
236  relativeTolerance_,
237  T {0}
238  )
239  );
240  }
241 
242  constexpr bool isEqual(const T a, const T b) const {
243  return Detail::isCloseRelativeOrAbsolute(
244  a,
245  b,
246  relativeTolerance_,
247  T {0}
248  );
249  }
250 
251  constexpr bool isUnequal(const T a, const T b) const {
252  return !Detail::isCloseRelativeOrAbsolute(
253  a,
254  b,
255  relativeTolerance_,
256  T {0}
257  );
258  }
259 
261  constexpr bool operator () (const T a, const T b) const noexcept {
262  return isEqual(a, b);
263  }
264 };
265 
266 } // namespace Floating
267 } // namespace Temple
268 } // namespace Molassembler
269 } // namespace Scine
270 
271 #endif
constexpr math implementations
constexpr bool operator()(const T a, const T b) const noexcept
Function call operator compares equality.
Definition: FloatingPointComparison.h:181
#define PURITY_STRONG
Definition: Preprocessor.h:65
constexpr bool operator()(const T a, const T b) const noexcept
Function call operator compares equality.
Definition: FloatingPointComparison.h:261