QMCPACK
checkMatrix.hpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2021 QMCPACK developers.
6 //
7 // File developed by: Peter Doak, doakpw@ornl.gov, Oak Ridge National Lab
8 //
9 // File created by: Peter Doak, doakpw@ornl.gov, Oak Ridge National Lab
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef QMCPLUSPLUS_CHECKMATRIX_HPP
13 #define QMCPLUSPLUS_CHECKMATRIX_HPP
14 
15 #include "catch.hpp"
16 
17 #include <string>
18 #include <complex>
19 #include <type_traits>
20 #include <optional>
22 namespace qmcplusplus
23 {
24 
25 template<typename T, IsComplex<T> = true>
26 bool approxEquality(T val_a, T val_b, std::optional<double> eps)
27 {
28  if (eps)
29  return val_a == ComplexApprox(val_b).epsilon(eps.value());
30  else
31  return val_a == ComplexApprox(val_b);
32 }
33 
34 template<typename T, IsReal<T> = true>
35 bool approxEquality(T val_a, T val_b, std::optional<double> eps)
36 {
37  if (eps)
38  return val_a == Approx(val_b).epsilon(eps.value());
39  else
40  return val_a == Approx(val_b);
41 }
42 
44 {
45  bool result;
46  std::string result_message;
47 };
48 
49 /** This function checks equality a_mat and b_mat elements
50  * M1, M2 need to have their element type declared M1::value_type
51  * and have an operator(i,j) accessor.
52  * I leave the c++14 template meta programming to insure
53  * this as an exercise for the reader. Or just enjoy the compiler error.
54  *
55  * \param[in] a_mat - reference matrix, if padded must be identical to b_mat,
56  * can be a smaller than b_mat in which case it is compared to upper
57  * left block of b_mat.
58  * \param[in] b_mat - the matrix to check
59  * \param[in] check_all - if true continue to check matrix elements after failure
60  * \param[in] eps - add a tolerance for Catch Approx checks. Default to same as in Approx.
61  */
62 template<class M1, class M2>
64  M2& b_mat,
65  const bool check_all = false,
66  std::optional<const double> eps = std::nullopt)
67 {
68  // This allows use to check a padded b matrix with a nonpadded a
69  if (a_mat.rows() > b_mat.rows() || a_mat.cols() > b_mat.cols())
70  return {false, "b_mat is too small for a_mat to be a checkable block"};
71  std::stringstream error_msg;
72  auto matrixElementError = [&error_msg](int i, int j, auto& a_mat, auto& b_mat) {
73  error_msg << "checkMatrix found bad element at " << i << ":" << j << " " << a_mat(i, j) << " != " << b_mat(i, j)
74  << '\n';
75  };
76  bool all_elements_match = true;
77  for (int i = 0; i < a_mat.rows(); i++)
78  for (int j = 0; j < a_mat.cols(); j++)
79  {
80  bool approx_equality = approxEquality<typename M1::value_type>(a_mat(i, j), b_mat(i, j), eps);
81  if (!approx_equality)
82  {
83  matrixElementError(i, j, a_mat, b_mat);
84  all_elements_match = false;
85  if (!check_all)
86  return {false, error_msg.str()};
87  }
88  }
89  return {all_elements_match, error_msg.str()};
90 }
91 
92 extern template bool approxEquality<float>(float val_a, float val_b, std::optional<double> eps);
93 extern template bool approxEquality<std::complex<float>>(std::complex<float> val_a,
94  std::complex<float> val_b,
95  std::optional<double> eps);
96 extern template bool approxEquality<double>(double val_a, double val_b, std::optional<double> eps);
97 extern template bool approxEquality<std::complex<double>>(std::complex<double> val_a,
98  std::complex<double> val_b,
99  std::optional<double> eps);
100 } // namespace qmcplusplus
101 #endif
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
template bool approxEquality< double >(double val_a, double val_b, std::optional< double > eps)
bool approxEquality(T val_a, T val_b, std::optional< double > eps)
Definition: checkMatrix.hpp:26
CheckMatrixResult checkMatrix(M1 &a_mat, M2 &b_mat, const bool check_all=false, std::optional< const double > eps=std::nullopt)
This function checks equality a_mat and b_mat elements M1, M2 need to have their element type declare...
Definition: checkMatrix.hpp:63
template bool approxEquality< float >(float val_a, float val_b, std::optional< double > eps)