• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #define EIGEN_NO_STATIC_ASSERT
11 
12 #include "main.h"
13 
vectorwiseop_array(const ArrayType & m)14 template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
15 {
16   typedef typename ArrayType::Index Index;
17   typedef typename ArrayType::Scalar Scalar;
18   typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
19   typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
20 
21   Index rows = m.rows();
22   Index cols = m.cols();
23   Index r = internal::random<Index>(0, rows-1),
24         c = internal::random<Index>(0, cols-1);
25 
26   ArrayType m1 = ArrayType::Random(rows, cols),
27             m2(rows, cols),
28             m3(rows, cols);
29 
30   ColVectorType colvec = ColVectorType::Random(rows);
31   RowVectorType rowvec = RowVectorType::Random(cols);
32 
33   // test addition
34 
35   m2 = m1;
36   m2.colwise() += colvec;
37   VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
38   VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
39 
40   VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
41   VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
42 
43   m2 = m1;
44   m2.rowwise() += rowvec;
45   VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
46   VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
47 
48   VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
49   VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
50 
51   // test substraction
52 
53   m2 = m1;
54   m2.colwise() -= colvec;
55   VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
56   VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
57 
58   VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
59   VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
60 
61   m2 = m1;
62   m2.rowwise() -= rowvec;
63   VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
64   VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
65 
66   VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
67   VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
68 
69   // test multiplication
70 
71   m2 = m1;
72   m2.colwise() *= colvec;
73   VERIFY_IS_APPROX(m2, m1.colwise() * colvec);
74   VERIFY_IS_APPROX(m2.col(c), m1.col(c) * colvec);
75 
76   VERIFY_RAISES_ASSERT(m2.colwise() *= colvec.transpose());
77   VERIFY_RAISES_ASSERT(m1.colwise() * colvec.transpose());
78 
79   m2 = m1;
80   m2.rowwise() *= rowvec;
81   VERIFY_IS_APPROX(m2, m1.rowwise() * rowvec);
82   VERIFY_IS_APPROX(m2.row(r), m1.row(r) * rowvec);
83 
84   VERIFY_RAISES_ASSERT(m2.rowwise() *= rowvec.transpose());
85   VERIFY_RAISES_ASSERT(m1.rowwise() * rowvec.transpose());
86 
87   // test quotient
88 
89   m2 = m1;
90   m2.colwise() /= colvec;
91   VERIFY_IS_APPROX(m2, m1.colwise() / colvec);
92   VERIFY_IS_APPROX(m2.col(c), m1.col(c) / colvec);
93 
94   VERIFY_RAISES_ASSERT(m2.colwise() /= colvec.transpose());
95   VERIFY_RAISES_ASSERT(m1.colwise() / colvec.transpose());
96 
97   m2 = m1;
98   m2.rowwise() /= rowvec;
99   VERIFY_IS_APPROX(m2, m1.rowwise() / rowvec);
100   VERIFY_IS_APPROX(m2.row(r), m1.row(r) / rowvec);
101 
102   VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose());
103   VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose());
104 
105   m2 = m1;
106   // yes, there might be an aliasing issue there but ".rowwise() /="
107   // is suppposed to evaluate " m2.colwise().sum()" into to temporary to avoid
108   // evaluating the reducions multiple times
109   if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic)
110   {
111     m2.rowwise() /= m2.colwise().sum();
112     VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
113   }
114 }
115 
vectorwiseop_matrix(const MatrixType & m)116 template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
117 {
118   typedef typename MatrixType::Index Index;
119   typedef typename MatrixType::Scalar Scalar;
120   typedef typename NumTraits<Scalar>::Real RealScalar;
121   typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
122   typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
123   typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType;
124   typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType;
125 
126   Index rows = m.rows();
127   Index cols = m.cols();
128   Index r = internal::random<Index>(0, rows-1),
129         c = internal::random<Index>(0, cols-1);
130 
131   MatrixType m1 = MatrixType::Random(rows, cols),
132             m2(rows, cols),
133             m3(rows, cols);
134 
135   ColVectorType colvec = ColVectorType::Random(rows);
136   RowVectorType rowvec = RowVectorType::Random(cols);
137   RealColVectorType rcres;
138   RealRowVectorType rrres;
139 
140   // test addition
141 
142   m2 = m1;
143   m2.colwise() += colvec;
144   VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
145   VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
146 
147   VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
148   VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
149 
150   m2 = m1;
151   m2.rowwise() += rowvec;
152   VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
153   VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
154 
155   VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
156   VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
157 
158   // test substraction
159 
160   m2 = m1;
161   m2.colwise() -= colvec;
162   VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
163   VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
164 
165   VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
166   VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
167 
168   m2 = m1;
169   m2.rowwise() -= rowvec;
170   VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
171   VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
172 
173   VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
174   VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
175 
176   // test norm
177   rrres = m1.colwise().norm();
178   VERIFY_IS_APPROX(rrres(c), m1.col(c).norm());
179   rcres = m1.rowwise().norm();
180   VERIFY_IS_APPROX(rcres(r), m1.row(r).norm());
181 
182   // test normalized
183   m2 = m1.colwise().normalized();
184   VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
185   m2 = m1.rowwise().normalized();
186   VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
187 
188   // test normalize
189   m2 = m1;
190   m2.colwise().normalize();
191   VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
192   m2 = m1;
193   m2.rowwise().normalize();
194   VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
195 }
196 
test_vectorwiseop()197 void test_vectorwiseop()
198 {
199   CALL_SUBTEST_1(vectorwiseop_array(Array22cd()));
200   CALL_SUBTEST_2(vectorwiseop_array(Array<double, 3, 2>()));
201   CALL_SUBTEST_3(vectorwiseop_array(ArrayXXf(3, 4)));
202   CALL_SUBTEST_4(vectorwiseop_matrix(Matrix4cf()));
203   CALL_SUBTEST_5(vectorwiseop_matrix(Matrix<float,4,5>()));
204   CALL_SUBTEST_6(vectorwiseop_matrix(MatrixXd(7,2)));
205 }
206