vectorwiseop.cpp
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2015 Gael Guennebaud <gael.guennebaud@inria.fr>
6 //
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 
11 #define TEST_ENABLE_TEMPORARY_TRACKING
12 #define EIGEN_NO_STATIC_ASSERT
13 
14 #include "main.h"
15 
16 template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
17 {
18  typedef typename ArrayType::Scalar Scalar;
21 
22  Index rows = m.rows();
23  Index cols = m.cols();
24  Index r = internal::random<Index>(0, rows-1),
25  c = internal::random<Index>(0, cols-1);
26 
27  ArrayType m1 = ArrayType::Random(rows, cols),
28  m2(rows, cols),
29  m3(rows, cols);
30 
31  ColVectorType colvec = ColVectorType::Random(rows);
32  RowVectorType rowvec = RowVectorType::Random(cols);
33 
34  // test addition
35 
36  m2 = m1;
37  m2.colwise() += colvec;
38  VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
39  VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
40 
41  VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
42  VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
43 
44  m2 = m1;
45  m2.rowwise() += rowvec;
46  VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
47  VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
48 
49  VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
50  VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
51 
52  // test substraction
53 
54  m2 = m1;
55  m2.colwise() -= colvec;
56  VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
57  VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
58 
59  VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
60  VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
61 
62  m2 = m1;
63  m2.rowwise() -= rowvec;
64  VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
65  VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
66 
67  VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
68  VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
69 
70  // test multiplication
71 
72  m2 = m1;
73  m2.colwise() *= colvec;
74  VERIFY_IS_APPROX(m2, m1.colwise() * colvec);
75  VERIFY_IS_APPROX(m2.col(c), m1.col(c) * colvec);
76 
77  VERIFY_RAISES_ASSERT(m2.colwise() *= colvec.transpose());
78  VERIFY_RAISES_ASSERT(m1.colwise() * colvec.transpose());
79 
80  m2 = m1;
81  m2.rowwise() *= rowvec;
82  VERIFY_IS_APPROX(m2, m1.rowwise() * rowvec);
83  VERIFY_IS_APPROX(m2.row(r), m1.row(r) * rowvec);
84 
85  VERIFY_RAISES_ASSERT(m2.rowwise() *= rowvec.transpose());
86  VERIFY_RAISES_ASSERT(m1.rowwise() * rowvec.transpose());
87 
88  // test quotient
89 
90  m2 = m1;
91  m2.colwise() /= colvec;
92  VERIFY_IS_APPROX(m2, m1.colwise() / colvec);
93  VERIFY_IS_APPROX(m2.col(c), m1.col(c) / colvec);
94 
95  VERIFY_RAISES_ASSERT(m2.colwise() /= colvec.transpose());
96  VERIFY_RAISES_ASSERT(m1.colwise() / colvec.transpose());
97 
98  m2 = m1;
99  m2.rowwise() /= rowvec;
100  VERIFY_IS_APPROX(m2, m1.rowwise() / rowvec);
101  VERIFY_IS_APPROX(m2.row(r), m1.row(r) / rowvec);
102 
103  VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose());
104  VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose());
105 
106  m2 = m1;
107  // yes, there might be an aliasing issue there but ".rowwise() /="
108  // is supposed to evaluate " m2.colwise().sum()" into a temporary to avoid
109  // evaluating the reduction multiple times
110  if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic)
111  {
112  m2.rowwise() /= m2.colwise().sum();
113  VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
114  }
115 
116  // all/any
117  Array<bool,Dynamic,Dynamic> mb(rows,cols);
118  mb = (m1.real()<=0.7).colwise().all();
119  VERIFY( (mb.col(c) == (m1.real().col(c)<=0.7).all()).all() );
120  mb = (m1.real()<=0.7).rowwise().all();
121  VERIFY( (mb.row(r) == (m1.real().row(r)<=0.7).all()).all() );
122 
123  mb = (m1.real()>=0.7).colwise().any();
124  VERIFY( (mb.col(c) == (m1.real().col(c)>=0.7).any()).all() );
125  mb = (m1.real()>=0.7).rowwise().any();
126  VERIFY( (mb.row(r) == (m1.real().row(r)>=0.7).any()).all() );
127 }
128 
129 template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
130 {
131  typedef typename MatrixType::Scalar Scalar;
132  typedef typename NumTraits<Scalar>::Real RealScalar;
137 
138  Index rows = m.rows();
139  Index cols = m.cols();
140  Index r = internal::random<Index>(0, rows-1),
141  c = internal::random<Index>(0, cols-1);
142 
143  MatrixType m1 = MatrixType::Random(rows, cols),
144  m2(rows, cols),
145  m3(rows, cols);
146 
147  ColVectorType colvec = ColVectorType::Random(rows);
148  RowVectorType rowvec = RowVectorType::Random(cols);
149  RealColVectorType rcres;
150  RealRowVectorType rrres;
151 
152  // test addition
153 
154  m2 = m1;
155  m2.colwise() += colvec;
156  VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
157  VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
158 
159  if(rows>1)
160  {
161  VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
162  VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
163  }
164 
165  m2 = m1;
166  m2.rowwise() += rowvec;
167  VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
168  VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
169 
170  if(cols>1)
171  {
172  VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
173  VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
174  }
175 
176  // test substraction
177 
178  m2 = m1;
179  m2.colwise() -= colvec;
180  VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
181  VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
182 
183  if(rows>1)
184  {
185  VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
186  VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
187  }
188 
189  m2 = m1;
190  m2.rowwise() -= rowvec;
191  VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
192  VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
193 
194  if(cols>1)
195  {
196  VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
197  VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
198  }
199 
200  // test norm
201  rrres = m1.colwise().norm();
202  VERIFY_IS_APPROX(rrres(c), m1.col(c).norm());
203  rcres = m1.rowwise().norm();
204  VERIFY_IS_APPROX(rcres(r), m1.row(r).norm());
205 
206  VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum(), m1.colwise().template lpNorm<1>());
207  VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().sum(), m1.rowwise().template lpNorm<1>());
208  VERIFY_IS_APPROX(m1.cwiseAbs().colwise().maxCoeff(), m1.colwise().template lpNorm<Infinity>());
209  VERIFY_IS_APPROX(m1.cwiseAbs().rowwise().maxCoeff(), m1.rowwise().template lpNorm<Infinity>());
210 
211  // regression for bug 1158
212  VERIFY_IS_APPROX(m1.cwiseAbs().colwise().sum().x(), m1.col(0).cwiseAbs().sum());
213 
214  // test normalized
215  m2 = m1.colwise().normalized();
216  VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
217  m2 = m1.rowwise().normalized();
218  VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
219 
220  // test normalize
221  m2 = m1;
222  m2.colwise().normalize();
223  VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
224  m2 = m1;
225  m2.rowwise().normalize();
226  VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
227 
228  // test with partial reduction of products
230  VERIFY_IS_APPROX( (m1 * m1.transpose()).colwise().sum(), m1m1.colwise().sum());
232  VERIFY_EVALUATION_COUNT( tmp = (m1 * m1.transpose()).colwise().sum(), 1);
233 
234  m2 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows())).eval();
235  m1 = m1.rowwise() - (m1.colwise().sum()/RealScalar(m1.rows()));
236  VERIFY_IS_APPROX( m1, m2 );
237  VERIFY_EVALUATION_COUNT( m2 = (m1.rowwise() - m1.colwise().sum()/RealScalar(m1.rows())), (MatrixType::RowsAtCompileTime!=1 ? 1 : 0) );
238 }
239 
241 {
242  CALL_SUBTEST_1( vectorwiseop_array(Array22cd()) );
243  CALL_SUBTEST_2( vectorwiseop_array(Array<double, 3, 2>()) );
244  CALL_SUBTEST_3( vectorwiseop_array(ArrayXXf(3, 4)) );
245  CALL_SUBTEST_4( vectorwiseop_matrix(Matrix4cf()) );
246  CALL_SUBTEST_5( vectorwiseop_matrix(Matrix<float,4,5>()) );
247  CALL_SUBTEST_6( vectorwiseop_matrix(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
248  CALL_SUBTEST_7( vectorwiseop_matrix(VectorXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
249  CALL_SUBTEST_7( vectorwiseop_matrix(RowVectorXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
250 }
Matrix3f m
SCALAR Scalar
Definition: bench_gemm.cpp:33
#define VERIFY_RAISES_ASSERT(a)
Definition: main.h:285
MatrixType m2(n_dims)
void test_vectorwiseop()
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
MatrixXf MatrixType
Holds information about the various numeric (i.e. scalar) types allowed by Eigen. ...
Definition: NumTraits.h:150
void vectorwiseop_matrix(const MatrixType &m)
#define VERIFY_EVALUATION_COUNT(XPR, N)
#define VERIFY_IS_APPROX(a, b)
Matrix3d m1
Definition: IOFormat.cpp:2
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
NumTraits< Scalar >::Real RealScalar
Definition: bench_gemm.cpp:34
#define VERIFY(a)
Definition: main.h:325
#define EIGEN_TEST_MAX_SIZE
General-purpose arrays with easy API for coefficient-wise operations.
Definition: Array.h:45
void vectorwiseop_array(const ArrayType &m)
const int Dynamic
Definition: Constants.h:21
The matrix class, also used for vectors and row-vectors.


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:51:23