Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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 | |
| 14 | template<typename ArrayType> void vectorwiseop_array(const ArrayType& m) |
| 15 | { |
| 16 | typedef typename ArrayType::Index Index; |
| 17 | typedef typename ArrayType::Scalar Scalar; |
Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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()); |
Carlos Hernandez | 7faaa9f | 2014-08-05 17:53:32 -0700 | [diff] [blame] | 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 | } |
Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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; |
Carlos Hernandez | 7faaa9f | 2014-08-05 17:53:32 -0700 | [diff] [blame] | 123 | typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType; |
| 124 | typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType; |
Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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); |
Carlos Hernandez | 7faaa9f | 2014-08-05 17:53:32 -0700 | [diff] [blame] | 137 | RealColVectorType rcres; |
| 138 | RealRowVectorType rrres; |
Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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()); |
Carlos Hernandez | 7faaa9f | 2014-08-05 17:53:32 -0700 | [diff] [blame] | 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()); |
Narayan Kamath | c981c48 | 2012-11-02 10:59:05 +0000 | [diff] [blame] | 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 | } |