SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MatrixTestUtilities.h
Go to the documentation of this file.
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2012 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 #ifndef TESTING_UTIL_MATRIXTESTUTILITIES
30 #define TESTING_UTIL_MATRIXTESTUTILITIES 1
31 
32 #include <gtest/gtest.h>
33 #include <boost/test/floating_point_comparison.hpp>
34 #include <boost/tuple/tuple.hpp>
35 #include <boost/timer.hpp>
36 #include <boost/assign.hpp>
37 #include <boost/filesystem.hpp>
38 #include <stdexcept>
39 
43 #include <Core/Utils/StringUtil.h>
44 
45 #include <Testing/Utils/share.h>
46 
47 namespace SCIRun
48 {
49 
50 namespace TestUtils
51 {
52 
54 {
55  return m1.nrows() == m2.nrows()
56  && m1.ncols() == m2.ncols();
57 }
58 
59 #define DEFAULT_MATRIX_PERCENT_TOLERANCE 1e-5
60 
61 //TODO improve error reporting
63 {
64  using namespace boost::test_tools;
65  return equal_size(m1, m2) &&
66  std::equal(m1.data(), m1.data() + m1.size(), m2.data(),
67  close_at_tolerance<double>(percent_tolerance(percentTolerance)));
68 }
69 
71 {
72  using namespace boost::test_tools;
73  return equal_size(m1, m2) &&
74  std::equal(m1.valuePtr(), m1.valuePtr() + m1.nonZeros(), m2.valuePtr(),
75  close_at_tolerance<double>(percent_tolerance(percentTolerance)));
76 }
77 
78 inline ::testing::AssertionResult compare_with_tolerance_readable(const Core::Datatypes::DenseMatrix& m1, const Core::Datatypes::DenseMatrix& m2, double percentTolerance, int printSize = 50)
79 {
80  return compare_with_tolerance(m1, m2, percentTolerance) ?
81  ::testing::AssertionSuccess() :
82  ::testing::AssertionFailure() << "Matrix 1: \n"<< matrix_to_string(m1).substr(0, printSize) << "\nMatrix 2: \n" << matrix_to_string(m2).substr(0, printSize);
83 }
84 
86 {
87  Core::Datatypes::DenseColumnMatrix diff = xhat - x;
88  double num = diff.lpNorm<Eigen::Infinity>();
89  double denom = xhat.lpNorm<Eigen::Infinity>();
90 
91  return num / denom;
92 }
93 
94 inline ::testing::AssertionResult compare_with_relative_infinity_norm(const Core::Datatypes::DenseColumnMatrix& x, const Core::Datatypes::DenseColumnMatrix& xhat, double relativeError = DEFAULT_MATRIX_PERCENT_TOLERANCE, int printSize = 50)
95 {
96  return relative_infinity_norm(x, xhat) < relativeError ?
97  ::testing::AssertionSuccess() :
98  ::testing::AssertionFailure() << "ColumnMatrix 1: \n"<< matrix_to_string(x).substr(0, printSize) << "ColumnMatrix 2: \n" << matrix_to_string(xhat).substr(0, printSize);
99 }
100 
101 
102 inline ::testing::AssertionResult compare_with_two_norm(const Core::Datatypes::DenseColumnMatrix& x, const Core::Datatypes::DenseColumnMatrix& xhat, double error = 1e-15, int printSize = 50)
103 {
104  double delta = (x - xhat).norm();
105  return delta < error ?
106  ::testing::AssertionSuccess() :
107  ::testing::AssertionFailure() <<
108  "Vectors are " << delta << " apart, expect less than " << error << " distance apart.\n" <<
109  "ColumnMatrix 1: \n"<< Core::to_string(x).substr(0, printSize) << "ColumnMatrix 2: \n" << Core::to_string(xhat).substr(0, printSize);
110 }
111 
113 {
114  to.setZero();
115  for (int i = 0; i < from.rows(); ++i)
116  for (int j = 0; j < from.cols(); ++j)
117  if (fabs(from(i,j)) > 1e-10)
118  to.insert(i,j) = from(i,j);
119 }
120 
122 {
123  Core::Datatypes::SparseRowMatrixHandle sp(boost::make_shared<Core::Datatypes::SparseRowMatrix>(static_cast<int>(dense.rows()), static_cast<int>(dense.cols())));
124  copyDenseToSparse(dense, *sp);
125  return sp;
126 }
127 
129 {
130  Core::Datatypes::DenseMatrixHandle dense(new Core::Datatypes::DenseMatrix(sparse.rows(), sparse.cols(), 0));
131  for (int k=0; k < sparse.outerSize(); ++k)
132  {
133  for (Core::Datatypes::SparseRowMatrix::InnerIterator it(sparse,k); it; ++it)
134  {
135  (*dense)(it.row(), it.col()) = it.value();
136  }
137  }
138  return dense;
139 }
140 
141 //TODO improve failure reporting
142 
143 #define EXPECT_MATRIX_EQ_TOLERANCE(actual, expected, tolerance) EXPECT_TRUE(compare_with_tolerance_readable((actual), (expected), (tolerance)))
144 #define EXPECT_MATRIX_EQ(actual, expected) EXPECT_MATRIX_EQ_TOLERANCE((actual), (expected), DEFAULT_MATRIX_PERCENT_TOLERANCE)
145 //#define EXPECT_MATRIX_EQ_TO(actual, expected) EXPECT_MATRIX_EQ((actual), MAKE_DENSE_MATRIX(expected))
146 //
147 //#define EXPECT_SPARSE_ROW_MATRIX_EQ_TO(actual, expected) EXPECT_MATRIX_EQ((actual), MAKE_SPARSE_ROW_MATRIX(expected))
148 //
149 //#define EXPECT_COLUMN_MATRIX_EQ_TO(actual, expected) EXPECT_MATRIX_EQ((actual), MAKE_COLUMN_MATRIX(expected))
150 //
151 //#define EXPECT_COLUMN_MATRIX_EQ_BY_RELATIVE_INFINITY_NORM(actual, expected, error) EXPECT_TRUE(compare_with_relative_infinity_norm((actual), (expected), (error)))
152 #define EXPECT_COLUMN_MATRIX_EQ_BY_TWO_NORM(actual, expected, error) EXPECT_TRUE(compare_with_two_norm((actual), (expected), (error)))
153 //#define EXPECT_COLUMN_MATRIX_EQ_BY_TWO_NORM_WITHIN_MACHINE_EPSILON(actual, expected) EXPECT_TRUE(compare_with_two_norm((actual), (expected)))
154 //
155 //#define EXPECT_MATRIX_NOT_EQ_TOLERANCE(actual, expected, tolerance) EXPECT_FALSE(compare_with_tolerance_readable((actual), (expected), (tolerance)))
156 //#define EXPECT_MATRIX_NOT_EQ(actual, expected) EXPECT_MATRIX_NOT_EQ_TOLERANCE((actual), (expected), DEFAULT_MATRIX_PERCENT_TOLERANCE)
157 
158 
159 // Note: this approach is limited to matrices with <= 5 columns, due to the implementation of boost::assign::tuple_list_of.
160 template <class Tuple>
161 Core::Datatypes::DenseMatrix convertDataToMatrix(const std::vector<Tuple>& matrixData)
162 {
163  typedef typename boost::tuples::element<0,Tuple>::type element0type;
164  typedef boost::is_convertible<element0type, double> CanConvertToDouble;
165  BOOST_STATIC_ASSERT(CanConvertToDouble::value);
166 
167  const int columns = boost::tuples::length<Tuple>::value;
168  const bool tupleShouldBeAllOneType = columns * sizeof(element0type) == sizeof(Tuple);
169  BOOST_STATIC_ASSERT(tupleShouldBeAllOneType);
170 
171  const size_t rows = matrixData.size();
172  Core::Datatypes::DenseMatrix matrix(rows, columns);
173 
174  for (size_t i = 0; i < rows; ++i)
175  {
176  const element0type* tupleData = reinterpret_cast<const element0type*>(&matrixData[i]);
177  std::copy(tupleData, tupleData + columns, matrix.data() + i*columns);
178  }
179 
180  return matrix;
181 }
182 
183 template <class Cont>
184 inline std::vector<typename Cont::value_type> to_vector(const Cont& cont)
185 {
186  if (cont.empty())
187  throw std::invalid_argument("Matrix<double> construction will not work without any data");
188 
189  std::vector<typename Cont::value_type> v;
190  return cont.to_container(v);
191 }
192 
193 #define MAKE_DENSE_MATRIX(x) (convertDataToMatrix(to_vector(boost::assign::tuple_list_of x)))
194 
195 #define MAKE_DENSE_MATRIX_HANDLE(x) (boost::make_shared<SCIRun::Core::Datatypes::DenseMatrix>(MAKE_DENSE_MATRIX(x)))
196 
197 #define MAKE_SPARSE_MATRIX_HANDLE(x) (toSparseHandle(MAKE_DENSE_MATRIX(x)))
198 
200 {
201  explicit ScopedTimer(const std::string& name) : name_(name)
202  {
203  std::cout << "Starting timer " << name_ << std::endl;
204  t_.restart();
205  }
206 
208  {
209  double elapsed = t_.elapsed();
210  std::cout << "Timer " << name_ << " stopped at " << elapsed << " seconds." << std::endl;
211  }
212 
213  std::string name_;
214  boost::timer t_;
215 };
216 
217 SCISHARE FieldHandle loadFieldFromFile(const boost::filesystem::path& filename);
218 
219 }
220 
221 }
222 
223 #endif
Definition: DenseColumnMatrix.h:43
~ScopedTimer()
Definition: MatrixTestUtilities.h:207
virtual size_t ncols() const =0
bool compare_with_tolerance(const Core::Datatypes::DenseMatrix &m1, const Core::Datatypes::DenseMatrix &m2, double percentTolerance=DEFAULT_MATRIX_PERCENT_TOLERANCE)
Definition: MatrixTestUtilities.h:62
ScopedTimer(const std::string &name)
Definition: MatrixTestUtilities.h:201
std::string to_string(const T &t)
Definition: StringUtil.h:55
std::string name_
Definition: MatrixTestUtilities.h:213
boost::timer t_
Definition: MatrixTestUtilities.h:214
#define SCISHARE
Definition: share.h:39
boost::shared_ptr< SparseRowMatrix > SparseRowMatrixHandle
Definition: MatrixFwd.h:68
std::vector< typename Cont::value_type > to_vector(const Cont &cont)
Definition: MatrixTestUtilities.h:184
Core::Datatypes::SparseRowMatrixHandle toSparseHandle(const Core::Datatypes::DenseMatrix &dense)
Definition: MatrixTestUtilities.h:121
virtual size_t nrows() const =0
SCISHARE FieldHandle loadFieldFromFile(const boost::filesystem::path &filename)
Definition: MatrixTestUtilities.cc:34
#define DEFAULT_MATRIX_PERCENT_TOLERANCE
Definition: MatrixTestUtilities.h:59
Core::Datatypes::DenseMatrixHandle makeDense(const Core::Datatypes::SparseRowMatrix &sparse)
Definition: MatrixTestUtilities.h:128
const char * name[]
Definition: BoostGraphExampleTests.cc:87
bool equal_size(const Core::Datatypes::Matrix &m1, const Core::Datatypes::Matrix &m2)
Definition: MatrixTestUtilities.h:53
void copyDenseToSparse(const Core::Datatypes::DenseMatrix &from, Core::Datatypes::SparseRowMatrix &to)
Definition: MatrixTestUtilities.h:112
inline::testing::AssertionResult compare_with_two_norm(const Core::Datatypes::DenseColumnMatrix &x, const Core::Datatypes::DenseColumnMatrix &xhat, double error=1e-15, int printSize=50)
Definition: MatrixTestUtilities.h:102
Core::Datatypes::DenseMatrix convertDataToMatrix(const std::vector< Tuple > &matrixData)
Definition: MatrixTestUtilities.h:161
v
Definition: readAllFields.py:42
double relative_infinity_norm(const Core::Datatypes::DenseColumnMatrix &x, const Core::Datatypes::DenseColumnMatrix &xhat)
Definition: MatrixTestUtilities.h:85
inline::testing::AssertionResult compare_with_tolerance_readable(const Core::Datatypes::DenseMatrix &m1, const Core::Datatypes::DenseMatrix &m2, double percentTolerance, int printSize=50)
Definition: MatrixTestUtilities.h:78
boost::shared_ptr< DenseMatrix > DenseMatrixHandle
Definition: MatrixFwd.h:52
Definition: ParallelLinearAlgebraTests.cc:751
boost::shared_ptr< Field > FieldHandle
Definition: DatatypeFwd.h:65
Definition: MatrixTestUtilities.h:199
std::string matrix_to_string(const MatrixBase &mat)
Definition: Matrix.h:206
inline::testing::AssertionResult compare_with_relative_infinity_norm(const Core::Datatypes::DenseColumnMatrix &x, const Core::Datatypes::DenseColumnMatrix &xhat, double relativeError=DEFAULT_MATRIX_PERCENT_TOLERANCE, int printSize=50)
Definition: MatrixTestUtilities.h:94