Molassembler  1.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 != std::numeric_limits<T>::quiet_NaN()
80  && b != std::numeric_limits<T>::quiet_NaN()
81  && a != std::numeric_limits<T>::signaling_NaN()
82  && b != std::numeric_limits<T>::signaling_NaN()
83  )) {
84  throw "isCloseRelativeOrAbsolute cannot handle infinities or NaNs!";
85  }
86 
87  if(!(relativeTolerance >= 0 && absoluteTolerance >= 0)) {
88  throw "isCloseRelativeOrAbsolute: One of either tolerances "
89  "needs to be above zero!";
90  }
91 
92  return(
93  Math::abs(a - b)
94  <= Math::max(
95  relativeTolerance * Math::max(
96  Math::abs(a),
97  Math::abs(b)
98  ),
99  absoluteTolerance
100  )
101  );
102 }
103 
104 } // namespace Detail
105 
106 template<typename T>
107 PURITY_STRONG constexpr std::enable_if_t<
108  std::is_floating_point<T>::value,
109  bool
110 > isCloseRelative(
111  const T a,
112  const T b,
113  const T relativeTolerance
114 ) {
115  return Detail::isCloseRelativeOrAbsolute(
116  a,
117  b,
118  relativeTolerance,
119  T {0}
120  );
121 }
122 
123 template<typename T>
124 PURITY_STRONG constexpr std::enable_if_t<
125  std::is_floating_point<T>::value,
126  bool
127 > isCloseAbsolute(
128  const T a,
129  const T b,
130  const T absoluteTolerance
131 ) {
132  return Detail::isCloseRelativeOrAbsolute(
133  a,
134  b,
135  T {0},
136  absoluteTolerance
137  );
138 }
139 
140 // Comparators exploiting relative and absolute expanded definitions of equality
141 
142 template<typename T>
144 private:
145  const T absoluteTolerance_;
146 
147 public:
148  constexpr ExpandedAbsoluteEqualityComparator(const T absoluteTolerance)
149  : absoluteTolerance_(absoluteTolerance)
150  {
151  assert(
152  absoluteTolerance > 0
153  && absoluteTolerance != std::numeric_limits<T>::infinity()
154  && absoluteTolerance != std::numeric_limits<T>::quiet_NaN()
155  && absoluteTolerance != std::numeric_limits<T>::signaling_NaN()
156  );
157  }
158 
159  constexpr bool isLessThan(const T a, const T b) const noexcept {
160  return a < (b - absoluteTolerance_);
161  }
162 
163  constexpr bool isMoreThan(const T a, const T b) const noexcept {
164  return a > (b + absoluteTolerance_);
165  }
166 
167  constexpr bool isLessOrEqual(const T a, const T b) const noexcept {
168  return a < (b + absoluteTolerance_);
169  }
170 
171  constexpr bool isMoreOrEqual(const T a, const T b) const noexcept {
172  return a > (b - absoluteTolerance_);
173  }
174 
175  constexpr bool isEqual(const T a, const T b) const noexcept {
176  return Math::abs(a - b) <= absoluteTolerance_;
177  }
178 
179  constexpr bool isUnequal(const T a, const T b) const noexcept {
180  return !isEqual(a, b);
181  }
182 
184  constexpr bool operator () (const T a, const T b) const noexcept {
185  return isEqual(a, b);
186  }
187 };
188 
189 template<typename T>
191 private:
192  const T relativeTolerance_;
193 
194 public:
195  constexpr ExpandedRelativeEqualityComparator(const T relativeTolerance)
196  : relativeTolerance_(relativeTolerance)
197  {
198  assert(relativeTolerance > 0);
199  }
200 
201  constexpr bool isLessThan(const T a, const T b) const {
202  return (
203  (a < b) && !Detail::isCloseRelativeOrAbsolute(
204  a,
205  b,
206  relativeTolerance_,
207  T {0}
208  )
209  );
210  }
211 
212  constexpr bool isMoreThan(const T a, const T b) const {
213  return (
214  (a > b) && !Detail::isCloseRelativeOrAbsolute(
215  a,
216  b,
217  relativeTolerance_,
218  T {0}
219  )
220  );
221  }
222 
223  constexpr bool isLessOrEqual(const T a, const T b) const {
224  return (
225  (a < b) || Detail::isCloseRelativeOrAbsolute(
226  a,
227  b,
228  relativeTolerance_,
229  T {0}
230  )
231  );
232  }
233 
234  constexpr bool isMoreOrEqual(const T a, const T b) const {
235  return (
236  (a > b) || Detail::isCloseRelativeOrAbsolute(
237  a,
238  b,
239  relativeTolerance_,
240  T {0}
241  )
242  );
243  }
244 
245  constexpr bool isEqual(const T a, const T b) const {
246  return Detail::isCloseRelativeOrAbsolute(
247  a,
248  b,
249  relativeTolerance_,
250  T {0}
251  );
252  }
253 
254  constexpr bool isUnequal(const T a, const T b) const {
255  return !Detail::isCloseRelativeOrAbsolute(
256  a,
257  b,
258  relativeTolerance_,
259  T {0}
260  );
261  }
262 
264  constexpr bool operator () (const T a, const T b) const noexcept {
265  return isEqual(a, b);
266  }
267 };
268 
269 } // namespace Floating
270 } // namespace Temple
271 } // namespace Molassembler
272 } // namespace Scine
273 
274 #endif
constexpr math implementations
constexpr bool operator()(const T a, const T b) const noexcept
Function call operator compares equality.
Definition: FloatingPointComparison.h:184
#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:264