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
14template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
15{
16  typedef typename ArrayType::Index Index;
17  typedef typename ArrayType::Scalar Scalar;
18  typedef typename NumTraits<Scalar>::Real RealScalar;
19  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
20  typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
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
107template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
108{
109  typedef typename MatrixType::Index Index;
110  typedef typename MatrixType::Scalar Scalar;
111  typedef typename NumTraits<Scalar>::Real RealScalar;
112  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
113  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
114
115  Index rows = m.rows();
116  Index cols = m.cols();
117  Index r = internal::random<Index>(0, rows-1),
118        c = internal::random<Index>(0, cols-1);
119
120  MatrixType m1 = MatrixType::Random(rows, cols),
121            m2(rows, cols),
122            m3(rows, cols);
123
124  ColVectorType colvec = ColVectorType::Random(rows);
125  RowVectorType rowvec = RowVectorType::Random(cols);
126
127  // test addition
128
129  m2 = m1;
130  m2.colwise() += colvec;
131  VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
132  VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
133
134  VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
135  VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
136
137  m2 = m1;
138  m2.rowwise() += rowvec;
139  VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
140  VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
141
142  VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
143  VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
144
145  // test substraction
146
147  m2 = m1;
148  m2.colwise() -= colvec;
149  VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
150  VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
151
152  VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
153  VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
154
155  m2 = m1;
156  m2.rowwise() -= rowvec;
157  VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
158  VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
159
160  VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
161  VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
162}
163
164void test_vectorwiseop()
165{
166  CALL_SUBTEST_1(vectorwiseop_array(Array22cd()));
167  CALL_SUBTEST_2(vectorwiseop_array(Array<double, 3, 2>()));
168  CALL_SUBTEST_3(vectorwiseop_array(ArrayXXf(3, 4)));
169  CALL_SUBTEST_4(vectorwiseop_matrix(Matrix4cf()));
170  CALL_SUBTEST_5(vectorwiseop_matrix(Matrix<float,4,5>()));
171  CALL_SUBTEST_6(vectorwiseop_matrix(MatrixXd(7,2)));
172}
173