Euphoria
approx.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cmath>
4 
5 #include <limits>
6 
7 #include "catch2/catch_all.hpp"
8 
9 
10 namespace eu::tests
11 {
12  struct ApproxData
13  {
14  float epsilon;
15  float scale;
16  float margin;
17  };
18 
19  // https://groups.google.com/forum/#!topic/catch-forum/03HhdvUzIhg
20 
21  template <typename T>
22  bool
23  is_approximately_equal(const T& lhs, const T& rhs, const ApproxData& data);
24 
25 
26  template <>
27  bool
29  float const& lhs,
30  float const& rhs,
31  const ApproxData& data);
32 
33 
35  // modified Catch Approx
36 
37  namespace custom
38  {
39  template <typename T>
40  struct Approx
41  {
42  public:
43  explicit Approx(T v)
44  : epsilon{std::numeric_limits<float>::epsilon() * 100}
45  , value{v}
46  {
47  }
48 
49  Approx&
50  set_epsilon(float new_epsilon)
51  {
52  epsilon = new_epsilon;
53  return *this;
54  }
55 
56  Approx&
57  set_margin(float new_margin)
58  {
59  margin = new_margin;
60  return *this;
61  }
62 
63  Approx&
64  set_scale(float new_scale)
65  {
66  scale = new_scale;
67  return *this;
68  }
69 
70  [[nodiscard]] std::string
71  to_string() const
72  {
73  Catch::ReusableStringStream rss;
74  rss << "Approx( " << ::Catch::Detail::stringify(value)
75  << " )";
76  return rss.str();
77  }
78 
79  friend bool
80  operator==(T lhs, Approx<T> const& rhs)
81  {
82  auto data = ApproxData{};
83  data.epsilon = rhs.epsilon;
84  data.scale = rhs.scale;
85  data.margin = rhs.margin;
86  return is_approximately_equal(lhs, rhs.value, data);
87  }
88 
89  friend bool
90  operator==(Approx<T> const& lhs, T rhs)
91  {
92  return operator==(rhs, lhs);
93  }
94 
95  friend bool
96  operator!=(T lhs, Approx<T> const& rhs)
97  {
98  return !operator==(lhs, rhs);
99  }
100 
101  friend bool
102  operator!=(Approx<T> const& lhs, T rhs)
103  {
104  return !operator==(rhs, lhs);
105  }
106 
107  private:
108  float epsilon;
109  float margin = 0.0f;
110  float scale = 1.0f;
111 
112  T value;
113  };
114  }
115 
116  template <typename T>
117  std::ostream&
118  operator<<(std::ostream& stream, const custom::Approx<T>& v)
119  {
120  return stream << v.to_string();
121  }
122 
124 
125 
126  template <typename T>
127  custom::Approx<T>
128  approx(T const& t)
129  {
130  return custom::Approx<T>(t);
131  }
132 }
custom::Approx< T > approx(T const &t)
Definition: approx.h:128
bool is_approximately_equal(float const &lhs, float const &rhs, const ApproxData &data)
Definition: approx.cc:20
std::ostream & operator<<(std::ostream &stream, const custom::Approx< T > &v)
Definition: approx.h:118
friend bool operator!=(Approx< T > const &lhs, T rhs)
Definition: approx.h:102
Approx & set_margin(float new_margin)
Definition: approx.h:57
friend bool operator==(Approx< T > const &lhs, T rhs)
Definition: approx.h:90
std::string to_string() const
Definition: approx.h:71
friend bool operator!=(T lhs, Approx< T > const &rhs)
Definition: approx.h:96
friend bool operator==(T lhs, Approx< T > const &rhs)
Definition: approx.h:80
Approx & set_epsilon(float new_epsilon)
Definition: approx.h:50
Approx & set_scale(float new_scale)
Definition: approx.h:64