1 #pragma once
2 
3 /// \file Approx.h
4 /// \brief Helper wrapper that allows to check whether two values are equal to some given accuracy.
5 /// \author Pavel Sevecek (sevecek at sirrah.troja.mff.cuni.cz)
6 /// \date 2016-2021
7 
8 #include "objects/geometry/TracelessTensor.h"
9 
10 NAMESPACE_SPH_BEGIN
11 
12 /// This is more or less stolen from Catch unit-testing framework.
13 template <typename Type>
14 class Approx {
15 private:
16     Float epsilon;
17     Type value;
18 
19 public:
Approx(const Type value)20     INLINE explicit Approx(const Type value)
21         : epsilon(EPS)
22         , value(value) {}
23 
operator()24     INLINE Approx operator()(const Type& value) {
25         Approx approx(value);
26         approx.setEpsilon(epsilon);
27         return approx;
28     }
29 
30     INLINE friend bool operator==(const Type& lhs, const Approx& rhs) {
31         return almostEqual(lhs, rhs.value, rhs.epsilon);
32     }
33 
34     INLINE friend bool operator==(const Approx& lhs, const Type& rhs) {
35         return operator==(rhs, lhs);
36     }
37 
38     INLINE friend bool operator!=(const Type& lhs, const Approx& rhs) {
39         return !operator==(lhs, rhs);
40     }
41 
42     INLINE friend bool operator!=(const Approx& lhs, const Type& rhs) {
43         return !operator==(rhs, lhs);
44     }
45 
setEpsilon(const Float newEps)46     INLINE Approx& setEpsilon(const Float newEps) {
47         epsilon = newEps;
48         return *this;
49     }
50 
51     friend std::ostream& operator<<(std::ostream& stream, const Approx& approx) {
52         stream << "~" << approx.value << " (eps = " << approx.epsilon << ")";
53         return stream;
54     }
55 };
56 
57 /// We have to wait till c++17 for type deduction in constructors ...
58 template <typename Type>
59 Approx<Type> approx(const Type& value, const Float eps = EPS) {
60     return Approx<Type>(value).setEpsilon(eps);
61 }
62 
63 
64 NAMESPACE_SPH_END
65