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 (at) 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 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 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 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