OpenStructure
vec_mat_predicates.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // This file is part of the OpenStructure project <www.openstructure.org>
3 //
4 // Copyright (C) 2008-2020 by the OpenStructure authors
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 3.0 of the License, or (at your option)
9 // any later version.
10 // This library is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this library; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //------------------------------------------------------------------------------
19 #ifndef OST_GEOM_VEC_MAT_PREDICATES_HH
20 #define OST_GEOM_VEC_MAT_PREDICATES_HH
21 #include <boost/test/unit_test.hpp>
22 #include <boost/version.hpp>
23 #if BOOST_VERSION<105900
24 #include <boost/test/floating_point_comparison.hpp>
25 #else
26 #include <boost/test/tools/floating_point_comparison.hpp>
27 #endif
28 #include <ost/geom/geom.hh>
29 
30 
31 /*
32  This file contains several predicates to check for equality of vectors and
33  matrices. Usage:
34 
35  BOOST_CHECK(vec2_is_close(geom::Vec2(1,2), geom::Vec2(1, 2)));
36  */
37 
38 template<class V>
39 boost::test_tools::predicate_result vec_is_close(const V& v1, const V& v2,
40  Real tolerance,
41  unsigned int dim)
42 {
43  std::string labels[]={"x","y","z","w"};
44  bool flag=true;
45  boost::test_tools::predicate_result res( false );
46 #if BOOST_VERSION<105900
47  boost::test_tools::close_at_tolerance<Real> close_test(boost::test_tools::percent_tolerance(tolerance));
48 #else
49  boost::math::fpc::close_at_tolerance<Real> close_test(boost::math::fpc::percent_tolerance(tolerance));
50 #endif
51  for(unsigned int i=0;i<dim;++i){
52  if(v1[i]==0.0){
53  if(!boost::test_tools::check_is_small(v2[i],tolerance)){
54  flag=false;
55  res.message() << "Value for " << labels[i] << " differs: ( " << v1[i] << " != " << v2[i] << " ). ";
56  }
57  }else if (v2[i]==0.0){
58  if(!boost::test_tools::check_is_small(v1[i],tolerance)){
59  flag=false;
60  res.message() << "Value for "<< labels[i] << " differs: ( " << v1[i] << " != " << v2[i] << " ). ";
61  }
62  }else{
63  if(!close_test(v1[i],v2[i])){
64  flag=false;
65  res.message() << "Value for " << labels[i] << " differs: ( " << v1[i] << " != " << v2[i] << " ). ";
66  }
67  }
68  }
69  if(flag){
70  return true;
71  }else{
72  return res;
73  }
74 }
75 
76 boost::test_tools::predicate_result vec2_is_close(const geom::Vec2& v1,
77  const geom::Vec2& v2,
78  Real tolerance=geom::EPSILON)
79 {
80  return vec_is_close<geom::Vec2>(v1,v2,tolerance,2);
81 }
82 
83 boost::test_tools::predicate_result vec3_is_close(const geom::Vec3& v1,
84  const geom::Vec3& v2,
85  Real tolerance=geom::EPSILON)
86 {
87  return vec_is_close<geom::Vec3>(v1,v2,tolerance,3);
88 }
89 
90 boost::test_tools::predicate_result vec4_is_close(const geom::Vec4& v1,
91  const geom::Vec4& v2,
92  Real tolerance=geom::EPSILON)
93 {
94  return vec_is_close<geom::Vec4>(v1,v2,tolerance,4);
95 }
96 
97 template<class M>
98 boost::test_tools::predicate_result mat_is_close(const M& m1, const M& m2,
99  Real tolerance,
100  unsigned int dim)
101 {
102  bool flag=true;
103  boost::test_tools::predicate_result res( false );
104 #if BOOST_VERSION<105900
105  boost::test_tools::close_at_tolerance<Real> close_test(boost::test_tools::percent_tolerance(tolerance));
106 #else
107  boost::math::fpc::close_at_tolerance<Real> close_test(boost::math::fpc::percent_tolerance(tolerance));
108 #endif
109  for(unsigned int i=0;i<dim;++i){
110  for(unsigned int j=0;j<dim;++j){
111  if(m1(i,j)==0.0){
112  if(!boost::test_tools::check_is_small(m2(i,j),tolerance)){
113  flag=false;
114  res.message() << "Value for (" << i << "," << j << ") differs: (" << m1(i,j) << "!=" << m2(i,j) << "). ";
115  }
116  }else if (m2(i,j)==0.0){
117  if(!boost::test_tools::check_is_small(m1(i,j),tolerance)){
118  flag=false;
119  res.message() << "Value for (" << i << "," << j << ") differs: (" << m1(i,j) << "!=" << m2(i,j) << "). ";
120  }
121  }else{
122  if(!close_test(m1(i,j),m2(i,j))){
123  flag=false;
124  res.message() << "Value for (" << i << "," << j << ") differs: (" << m1(i,j) << "!=" << m2(i,j) << "). ";
125  }
126  }
127  }
128  }
129  if(flag){
130  return true;
131  }else{
132  return res;
133  }
134 }
135 
136 boost::test_tools::predicate_result mat2_is_close(const geom::Mat2& m1,
137  const geom::Mat2& m2,
138  Real tolerance=geom::EPSILON)
139 {
140  return mat_is_close<geom::Mat2>(m1,m2,tolerance,2);
141 }
142 
143 boost::test_tools::predicate_result mat3_is_close(const geom::Mat3& m1,
144  const geom::Mat3& m2,
145  Real tolerance=geom::EPSILON)
146 {
147  return mat_is_close<geom::Mat3>(m1,m2,tolerance,3);
148 }
149 
150 boost::test_tools::predicate_result mat4_is_close(const geom::Mat4& m1,
151  const geom::Mat4& m2,
152  Real tolerance=geom::EPSILON)
153 {
154  return mat_is_close<geom::Mat4>(m1,m2,tolerance,4);
155 }
156 
157 #endif
Three dimensional vector class, using Real precision.
Definition: vec3.hh:48
float Real
Definition: base.hh:44
static const Real EPSILON
Definition: constants.hh:28
boost::test_tools::predicate_result mat_is_close(const M &m1, const M &m2, Real tolerance, unsigned int dim)
boost::test_tools::predicate_result mat2_is_close(const geom::Mat2 &m1, const geom::Mat2 &m2, Real tolerance=geom::EPSILON)
boost::test_tools::predicate_result mat4_is_close(const geom::Mat4 &m1, const geom::Mat4 &m2, Real tolerance=geom::EPSILON)
boost::test_tools::predicate_result vec_is_close(const V &v1, const V &v2, Real tolerance, unsigned int dim)
boost::test_tools::predicate_result vec3_is_close(const geom::Vec3 &v1, const geom::Vec3 &v2, Real tolerance=geom::EPSILON)
boost::test_tools::predicate_result vec2_is_close(const geom::Vec2 &v1, const geom::Vec2 &v2, Real tolerance=geom::EPSILON)
boost::test_tools::predicate_result vec4_is_close(const geom::Vec4 &v1, const geom::Vec4 &v2, Real tolerance=geom::EPSILON)
boost::test_tools::predicate_result mat3_is_close(const geom::Mat3 &m1, const geom::Mat3 &m2, Real tolerance=geom::EPSILON)