Ariles
compare.h
Go to the documentation of this file.
1 /**
2  @file
3  @author Alexander Sherikov
4 
5  @copyright 2017-2020 Alexander Sherikov, Licensed under the Apache License, Version 2.0.
6  (see @ref LICENSE or http://www.apache.org/licenses/LICENSE-2.0)
7 
8  @brief
9 */
10 
11 #pragma once
12 
13 #include <boost/math/special_functions.hpp>
14 #include "common.h"
15 
16 /**
17 @defgroup compare Compare
18 
19 @brief Class comparison.
20 */
21 
22 namespace ariles2
23 {
24  /// @ingroup compare
25  namespace compare
26  {
28  {
29  public:
33  bool nan_equal_;
34  bool inf_equal_;
35  /// @todo continue on failure.
36 
37 
38  public:
39  explicit Parameters(const bool override_parameters = true) : visitor::Parameters(override_parameters)
40  {
41  setDefaults();
42  }
43 
44 
45  void setDefaults()
46  {
47  double_tolerance_ = 1e-12;
48  float_tolerance_ = 1e-8;
50 
51  nan_equal_ = true;
52  inf_equal_ = true;
53  }
54 
55 
56  template <typename t_Scalar, typename = std::enable_if_t<std::is_floating_point_v<t_Scalar>>>
57  t_Scalar getTolerance() const
58  {
59  if constexpr (std::is_same_v<t_Scalar, double>)
60  {
61  return (double_tolerance_);
62  }
63  if constexpr (std::is_same_v<t_Scalar, float>)
64  {
65  return (float_tolerance_);
66  }
67  }
68 
69 
70  template <class t_Complex>
71  typename t_Complex::value_type getTolerance() const
72  {
73  return (getTolerance<typename t_Complex::value_type>());
74  }
75  };
76 
77 
78  class Visitor : public visitor::Base<Visitor, compare::Parameters, bool>
79  {
80  public:
82 
83 
84  public:
85  bool equal_;
86  std::vector<std::string> backtrace_;
87 
88 
89  public:
90  template <class t_Left, class t_Right>
91  bool visit(const t_Left &left, const t_Right &right, const std::string &name, const Parameters &param)
92  {
94  try
95  {
96  equal_ = true;
97  this->visitMapEntry(left, right, name, param);
98  if (not equal_)
99  {
100  backtrace_.push_back(name);
101  }
102  }
103  catch (std::exception &e)
104  {
105  backtrace_.push_back(e.what());
106  equal_ = false;
107  }
108  return (equal_);
109  }
110 
111 
112  template <typename t_Scalar>
113  static bool compareFloats(const t_Scalar left, const t_Scalar right, const Parameters &param)
114  {
115  if (boost::math::isnan(left))
116  {
117  if (boost::math::isnan(right))
118  {
119  return (param.nan_equal_);
120  }
121  else
122  {
123  return (false);
124  }
125  }
126 
127  if (boost::math::isinf(left))
128  {
129  if (boost::math::isinf(right))
130  {
131  if (((left > 0) && (right > 0)) || ((left < 0) && (right < 0)))
132  {
133  return (param.inf_equal_);
134  }
135  }
136  return (false);
137  }
138  return (std::abs(left - right)
139  <= ((std::abs(left) < std::abs(right) ? std::abs(right) : std::abs(left))
140  * param.double_tolerance_));
141  }
142 
143 
144  template <class t_Left, class t_Right>
146  const t_Left &left,
147  const t_Right &right,
148  const std::string &name,
149  const Parameters &param)
150  {
152  CPPUT_TRACE_VALUE(name);
153  CPPUT_TRACE_TYPE(left);
154  CPPUT_TRACE_TYPE(right);
155 
156  const bool equal_check = this->equal_;
157  apply_compare(*this, left, right, param);
158  if (not this->equal_ and equal_check != this->equal_)
159  {
160  backtrace_.push_back(name);
161  }
162  }
163  };
164 
165 
166  class Base
167  {
168  };
169 
170 
171 #define ARILES2_NAMED_ENTRY_compare(v, entry, name) visitor.visitMapEntry(entry, other.entry, #name, parameters);
172 #define ARILES2_PARENT_compare(v, entry) entry::arilesVisit(visitor, other, parameters);
173 
174 #define ARILES2_VISIT_compare \
175  template <class t_Other> /* cppcheck-suppress duplInheritedMember */ \
176  void arilesVisit( \
177  ariles2::compare::Visitor &visitor, \
178  const t_Other &other, \
179  const typename ariles2::compare::Visitor::Parameters &parameters) const \
180  { \
181  CPPUT_UNUSED_ARG(visitor); \
182  CPPUT_UNUSED_ARG(other); \
183  CPPUT_UNUSED_ARG(parameters); \
184  CPPUT_TRACE_FUNCTION; \
185  ARILES2_ENTRIES(compare) \
186  }
187 
188 #define ARILES2_METHODS_compare \
189  const ariles2::compare::Visitor::Parameters &arilesGetParameters(const ariles2::compare::Visitor &visitor) const \
190  { \
191  CPPUT_TRACE_FUNCTION; \
192  return (visitor.getDefaultParameters()); \
193  }
194 #define ARILES2_BASE_METHODS_compare
195  } // namespace compare
196 
197 
198  /// @ingroup compare
200 } // namespace ariles2
t_Complex::value_type getTolerance() const
Definition: compare.h:71
Parameters(const bool override_parameters=true)
Definition: compare.h:39
t_Scalar getTolerance() const
Definition: compare.h:57
static bool compareFloats(const t_Scalar left, const t_Scalar right, const Parameters &param)
Definition: compare.h:113
bool visit(const t_Left &left, const t_Right &right, const std::string &name, const Parameters &param)
Definition: compare.h:91
void visitMapEntry(const t_Left &left, const t_Right &right, const std::string &name, const Parameters &param)
Definition: compare.h:145
std::vector< std::string > backtrace_
Definition: compare.h:86
void apply_compare(t_Visitor &visitor, const t_Left &left, const t_Right &right, const typename t_Visitor::Parameters &param)
Definition: basic.h:140
visitor::Parameters Parameters
Definition: count.h:26
Definition: basic.h:17
#define CPPUT_TRACE_FUNCTION
Definition: trace.h:126
#define CPPUT_TRACE_TYPE(type)
Definition: trace.h:128
#define CPPUT_TRACE_VALUE(value)
Definition: trace.h:127