diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 99d497449..38c68778f 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -2,7 +2,7 @@ // for linear algebra. // // Copyright (C) 2007 Michael Olbrich -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2006-2010 Benoit Jacob // Copyright (C) 2008 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index d3c4dfa99..e6cfb0859 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -2,7 +2,7 @@ // for linear algebra. // // Copyright (C) 2008 Gael Guennebaud -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2006-2010 Benoit Jacob // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index eae2711f4..dc1be9ea2 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2006-2010 Benoit Jacob // Copyright (C) 2008-2009 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b0da2a1d8..c6b359ce9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -104,12 +104,13 @@ ei_add_test(cwiseop) ei_add_test(unalignedcount) ei_add_test(redux) ei_add_test(visitor) +ei_add_test(block) ei_add_test(product_small) ei_add_test(product_large) ei_add_test(product_extra) ei_add_test(diagonalmatrices) ei_add_test(adjoint) -ei_add_test(submatrices) +ei_add_test(diagonal) ei_add_test(miscmatrices) ei_add_test(commainitializer) ei_add_test(smallvectors) diff --git a/test/submatrices.cpp b/test/block.cpp similarity index 61% rename from test/submatrices.cpp rename to test/block.cpp index e71c28ceb..c180afb75 100644 --- a/test/submatrices.cpp +++ b/test/block.cpp @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2006-2008 Benoit Jacob +// Copyright (C) 2006-2010 Benoit Jacob // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -51,16 +51,18 @@ template struct CheckMinor CheckMinor(MatrixType&, int, int) {} }; -template void submatrices(const MatrixType& m) +template void block(const MatrixType& m) { /* this test covers the following files: - Row.h Column.h Block.h Minor.h DiagonalCoeffs.h + Row.h Column.h Block.h Minor.h */ typedef typename MatrixType::Scalar Scalar; typedef typename MatrixType::RealScalar RealScalar; typedef Matrix VectorType; typedef Matrix RowVectorType; - typedef Matrix SquareMatrixType; + typedef Matrix DynamicMatrixType; + typedef Matrix DynamicVectorType; + int rows = m.rows(); int cols = m.cols(); @@ -69,8 +71,6 @@ template void submatrices(const MatrixType& m) m3(rows, cols), mzero = MatrixType::Zero(rows, cols), ones = MatrixType::Ones(rows, cols); - SquareMatrixType identity = SquareMatrixType::Identity(rows, rows), - square = SquareMatrixType::Random(rows, rows); VectorType v1 = VectorType::Random(rows), v2 = VectorType::Random(rows), v3 = VectorType::Random(rows), @@ -84,9 +84,7 @@ template void submatrices(const MatrixType& m) int c2 = ei_random(c1,cols-1); //check row() and col() - VERIFY_IS_APPROX(m1.col(c1).transpose(), m1.transpose().row(c1)); - // FIXME perhaps we should re-enable that without the .eval() - VERIFY_IS_APPROX(m1.col(c1).dot(square.row(r1)), (square * m1.conjugate()).eval()(r1,c1)); + VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1)); //check operator(), both constant and non-constant, on row() and col() m1.row(r1) += s1 * m1.row(r2); m1.col(c1) += s1 * m1.col(c2); @@ -96,9 +94,9 @@ template void submatrices(const MatrixType& m) RowVectorType br1(m1.block(r1,0,1,cols)); VectorType bc1(m1.block(0,c1,rows,1)); - VERIFY_IS_APPROX(b1, m1.block(r1,c1,1,1)); - VERIFY_IS_APPROX(m1.row(r1), br1); - VERIFY_IS_APPROX(m1.col(c1), bc1); + VERIFY_IS_EQUAL(b1, m1.block(r1,c1,1,1)); + VERIFY_IS_EQUAL(m1.row(r1), br1); + VERIFY_IS_EQUAL(m1.col(c1), bc1); //check operator(), both constant and non-constant, on block() m1.block(r1,c1,r2-r1+1,c2-c1+1) = s1 * m2.block(0, 0, r2-r1+1,c2-c1+1); m1.block(r1,c1,r2-r1+1,c2-c1+1)(r2-r1,c2-c1) = m2.block(0, 0, r2-r1+1,c2-c1+1)(0,0); @@ -106,11 +104,6 @@ template void submatrices(const MatrixType& m) //check minor() CheckMinor checkminor(m1,r1,c1); - //check diagonal() - VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal()); - m2.diagonal() = 2 * m1.diagonal(); - m2.diagonal()[0] *= 3; - const int BlockRows = EIGEN_ENUM_MIN(MatrixType::RowsAtCompileTime,2); const int BlockCols = EIGEN_ENUM_MIN(MatrixType::ColsAtCompileTime,5); if (rows>=5 && cols>=8) @@ -121,45 +114,23 @@ template void submatrices(const MatrixType& m) m1.template block(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2); // check that fixed block() and block() agree Matrix b = m1.template block(3,3); - VERIFY_IS_APPROX(b, m1.block(3,3,BlockRows,BlockCols)); + VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols)); } if (rows>2) { // test sub vectors - VERIFY_IS_APPROX(v1.template head<2>(), v1.block(0,0,2,1)); - VERIFY_IS_APPROX(v1.template head<2>(), v1.head(2)); - VERIFY_IS_APPROX(v1.template head<2>(), v1.segment(0,2)); - VERIFY_IS_APPROX(v1.template head<2>(), v1.template segment<2>(0)); + VERIFY_IS_EQUAL(v1.template head<2>(), v1.block(0,0,2,1)); + VERIFY_IS_EQUAL(v1.template head<2>(), v1.head(2)); + VERIFY_IS_EQUAL(v1.template head<2>(), v1.segment(0,2)); + VERIFY_IS_EQUAL(v1.template head<2>(), v1.template segment<2>(0)); int i = rows-2; - VERIFY_IS_APPROX(v1.template tail<2>(), v1.block(i,0,2,1)); - VERIFY_IS_APPROX(v1.template tail<2>(), v1.tail(2)); - VERIFY_IS_APPROX(v1.template tail<2>(), v1.segment(i,2)); - VERIFY_IS_APPROX(v1.template tail<2>(), v1.template segment<2>(i)); + VERIFY_IS_EQUAL(v1.template tail<2>(), v1.block(i,0,2,1)); + VERIFY_IS_EQUAL(v1.template tail<2>(), v1.tail(2)); + VERIFY_IS_EQUAL(v1.template tail<2>(), v1.segment(i,2)); + VERIFY_IS_EQUAL(v1.template tail<2>(), v1.template segment<2>(i)); i = ei_random(0,rows-2); - VERIFY_IS_APPROX(v1.segment(i,2), v1.template segment<2>(i)); - - enum { - N1 = MatrixType::RowsAtCompileTime>1 ? 1 : 0, - N2 = MatrixType::RowsAtCompileTime>2 ? -2 : 0 - }; - - // check sub/super diagonal - m2.template diagonal() = 2 * m1.template diagonal(); - m2.template diagonal()[0] *= 3; - VERIFY_IS_APPROX(m2.template diagonal()[0], static_cast(6) * m1.template diagonal()[0]); - - m2.template diagonal() = 2 * m1.template diagonal(); - m2.template diagonal()[0] *= 3; - VERIFY_IS_APPROX(m2.template diagonal()[0], static_cast(6) * m1.template diagonal()[0]); - - m2.diagonal(N1) = 2 * m1.diagonal(N1); - m2.diagonal(N1)[0] *= 3; - VERIFY_IS_APPROX(m2.diagonal(N1)[0], static_cast(6) * m1.diagonal(N1)[0]); - - m2.diagonal(N2) = 2 * m1.diagonal(N2); - m2.diagonal(N2)[0] *= 3; - VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast(6) * m1.diagonal(N2)[0]); + VERIFY_IS_EQUAL(v1.segment(i,2), v1.template segment<2>(i)); } // stress some basic stuffs with block matrices @@ -168,6 +139,49 @@ template void submatrices(const MatrixType& m) VERIFY(ei_real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows)); VERIFY(ei_real(ones.row(r1).dot(ones.row(r2))) == RealScalar(cols)); + + // now test some block-inside-of-block. + + // expressions with direct access + VERIFY_IS_EQUAL( (m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , (m1.block(r2,c2,rows-r2,cols-c2)) ); + VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , (m1.row(r1).segment(c1,c2-c1+1)) ); + VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , (m1.col(c1).segment(r1,r2-r1+1)) ); + VERIFY_IS_EQUAL( (m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , (m1.row(r1).segment(c1,c2-c1+1)) ); + VERIFY_IS_EQUAL( (m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , (m1.row(r1).segment(c1,c2-c1+1)) ); + + // expressions without direct access + VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2)) , ((m1+m2).block(r2,c2,rows-r2,cols-c2)) ); + VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).row(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) ); + VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).col(0)) , ((m1+m2).col(c1).segment(r1,r2-r1+1)) ); + VERIFY_IS_EQUAL( ((m1+m2).block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) ); + VERIFY_IS_EQUAL( ((m1+m2).transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , ((m1+m2).row(r1).segment(c1,c2-c1+1)) ); + + // evaluation into plain matrices from expressions with direct access (stress MapBase) + DynamicMatrixType dm; + DynamicVectorType dv; + dm.setZero(); + dm = m1.block(r1,c1,rows-r1,cols-c1).block(r2-r1,c2-c1,rows-r2,cols-c2); + VERIFY_IS_EQUAL(dm, (m1.block(r2,c2,rows-r2,cols-c2))); + dm.setZero(); + dv.setZero(); + dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).row(0).transpose(); + dv = m1.row(r1).segment(c1,c2-c1+1); + VERIFY_IS_EQUAL(dv, dm); + dm.setZero(); + dv.setZero(); + dm = m1.col(c1).segment(r1,r2-r1+1); + dv = m1.block(r1,c1,r2-r1+1,c2-c1+1).col(0); + VERIFY_IS_EQUAL(dv, dm); + dm.setZero(); + dv.setZero(); + dm = m1.block(r1,c1,r2-r1+1,c2-c1+1).transpose().col(0); + dv = m1.row(r1).segment(c1,c2-c1+1); + VERIFY_IS_EQUAL(dv, dm); + dm.setZero(); + dv.setZero(); + dm = m1.row(r1).segment(c1,c2-c1+1).transpose(); + dv = m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0); + VERIFY_IS_EQUAL(dv, dm); } @@ -185,22 +199,22 @@ void compare_using_data_and_stride(const MatrixType& m) for(int j=0;j()) ); - CALL_SUBTEST_2( submatrices(Matrix4d()) ); - CALL_SUBTEST_3( submatrices(MatrixXcf(3, 3)) ); - CALL_SUBTEST_4( submatrices(MatrixXi(8, 12)) ); - CALL_SUBTEST_5( submatrices(MatrixXcd(20, 20)) ); - CALL_SUBTEST_6( submatrices(MatrixXf(20, 20)) ); + CALL_SUBTEST_1( block(Matrix()) ); + CALL_SUBTEST_2( block(Matrix4d()) ); + CALL_SUBTEST_3( block(MatrixXcf(3, 3)) ); + CALL_SUBTEST_4( block(MatrixXi(8, 12)) ); + CALL_SUBTEST_5( block(MatrixXcd(20, 20)) ); + CALL_SUBTEST_6( block(MatrixXf(20, 20)) ); - CALL_SUBTEST_8( submatrices(Matrix(3, 4)) ); + CALL_SUBTEST_8( block(Matrix(3, 4)) ); #ifndef EIGEN_DEFAULT_TO_ROW_MAJOR CALL_SUBTEST_6( data_and_stride(MatrixXf(ei_random(5,50), ei_random(5,50))) ); diff --git a/test/diagonal.cpp b/test/diagonal.cpp new file mode 100644 index 000000000..288d58c6e --- /dev/null +++ b/test/diagonal.cpp @@ -0,0 +1,81 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#include "main.h" + +template void diagonal(const MatrixType& m) +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + typedef Matrix VectorType; + typedef Matrix RowVectorType; + int rows = m.rows(); + int cols = m.cols(); + + MatrixType m1 = MatrixType::Random(rows, cols), + m2 = MatrixType::Random(rows, cols); + + //check diagonal() + VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal()); + m2.diagonal() = 2 * m1.diagonal(); + m2.diagonal()[0] *= 3; + + if (rows>2) + { + enum { + N1 = MatrixType::RowsAtCompileTime>1 ? 1 : 0, + N2 = MatrixType::RowsAtCompileTime>2 ? -2 : 0 + }; + + // check sub/super diagonal + m2.template diagonal() = 2 * m1.template diagonal(); + m2.template diagonal()[0] *= 3; + VERIFY_IS_APPROX(m2.template diagonal()[0], static_cast(6) * m1.template diagonal()[0]); + + m2.template diagonal() = 2 * m1.template diagonal(); + m2.template diagonal()[0] *= 3; + VERIFY_IS_APPROX(m2.template diagonal()[0], static_cast(6) * m1.template diagonal()[0]); + + m2.diagonal(N1) = 2 * m1.diagonal(N1); + m2.diagonal(N1)[0] *= 3; + VERIFY_IS_APPROX(m2.diagonal(N1)[0], static_cast(6) * m1.diagonal(N1)[0]); + + m2.diagonal(N2) = 2 * m1.diagonal(N2); + m2.diagonal(N2)[0] *= 3; + VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast(6) * m1.diagonal(N2)[0]); + } +} + +void test_diagonal() +{ + for(int i = 0; i < g_repeat; i++) { + CALL_SUBTEST_1( diagonal(Matrix()) ); + CALL_SUBTEST_2( diagonal(Matrix4d()) ); + CALL_SUBTEST_2( diagonal(MatrixXcf(3, 3)) ); + CALL_SUBTEST_2( diagonal(MatrixXi(8, 12)) ); + CALL_SUBTEST_2( diagonal(MatrixXcd(20, 20)) ); + CALL_SUBTEST_1( diagonal(MatrixXf(21, 19)) ); + CALL_SUBTEST_1( diagonal(Matrix(3, 4)) ); + } +} diff --git a/test/main.h b/test/main.h index 96324de33..5ca9395c2 100644 --- a/test/main.h +++ b/test/main.h @@ -157,6 +157,7 @@ namespace Eigen exit(2); \ } } while (0) +#define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b)) #define VERIFY_IS_APPROX(a, b) VERIFY(test_ei_isApprox(a, b)) #define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_ei_isApprox(a, b)) #define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_ei_isMuchSmallerThan(a, b)) @@ -342,6 +343,41 @@ inline bool test_isUnitary(const MatrixBase& m) return m.isUnitary(test_precision::Scalar>()); } +template +struct test_is_equal_impl +{ + static bool run(const Derived1& a1, const Derived2& a2) + { + if(a1.size() != a2.size()) return false; + // we evaluate a2 into a temporary of the shape of a1. this allows to let Assign.h handle the transposing if needed. + typename Derived1::PlainObject a2_evaluated(a2); + for(int i = 0; i < a1.size(); ++i) + if(a1.coeff(i) != a2_evaluated.coeff(i)) return false; + return true; + } +}; + +template +struct test_is_equal_impl +{ + static bool run(const Derived1& a1, const Derived2& a2) + { + if(a1.rows() != a2.rows()) return false; + if(a1.cols() != a2.cols()) return false; + for(int j = 0; j < a1.cols(); ++j) + for(int i = 0; i < a1.rows(); ++i) + if(a1.coeff(i,j) != a2.coeff(i,j)) return false; + return true; + } +}; + +template +bool test_is_equal(const Derived1& a1, const Derived2& a2) +{ + return test_is_equal_impl::run(a1, a2); +} + /** Creates a random Partial Isometry matrix of given rank. * * A partial isometry is a matrix all of whose singular values are either 0 or 1.