diff --git a/CMakeLists.txt b/CMakeLists.txt index ee93e3de3..3a23479d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,7 @@ ei_testing_print_summary() message("") message("Configured Eigen ${EIGEN_VERSION_NUMBER}") +message("") string(TOLOWER "${CMAKE_GENERATOR}" cmake_generator_tolower) if(cmake_generator_tolower MATCHES "makefile") @@ -166,14 +167,15 @@ if(cmake_generator_tolower MATCHES "makefile") message("Command | Description") message("--------------+----------------------------------------------------------------") message("make install | Install to ${CMAKE_INSTALL_PREFIX}") - message(" | * To change that: cmake . -DCMAKE_INSTALL_PREFIX=yourpath") + message(" | To change that: cmake . -DCMAKE_INSTALL_PREFIX=yourpath") message("make doc | Generate the API documentation, requires Doxygen & LaTeX") - message("make check | Build and run the unit-tests") + message("make check | Build and run the unit-tests. Read this page:") + message(" | http://eigen.tuxfamily.org/index.php?title=Tests") message("make blas | Build BLAS library (not the same thing as Eigen)") message("--------------+----------------------------------------------------------------") +else() + message("To build/run the unit tests, read this page:") + message(" http://eigen.tuxfamily.org/index.php?title=Tests") endif() message("") -message("To build/run the unit tests, read this page:") -message(" http://eigen.tuxfamily.org/index.php?title=Tests") -message("") diff --git a/Eigen/Core b/Eigen/Core index 3dce6422f..2968e36c6 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -177,6 +177,7 @@ namespace Eigen { #include "src/Core/DiagonalMatrix.h" #include "src/Core/Diagonal.h" #include "src/Core/DiagonalProduct.h" +#include "src/Core/PermutationMatrix.h" #include "src/Core/Redux.h" #include "src/Core/Visitor.h" #include "src/Core/Fuzzy.h" diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 4665fe0ca..1dec82229 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -66,7 +66,7 @@ class DiagonalBase : public AnyMatrixBase inline int cols() const { return diagonal().size(); } template - const DiagonalProduct + const DiagonalProduct operator*(const MatrixBase &matrix) const; }; @@ -88,16 +88,16 @@ void DiagonalBase::evalTo(MatrixBase &other) const * * \sa class Matrix */ -template -struct ei_traits > - : ei_traits > +template +struct ei_traits > + : ei_traits > { - typedef Matrix<_Scalar,_Size,1> DiagonalVectorType; + typedef Matrix<_Scalar,SizeAtCompileTime,1,0,MaxSizeAtCompileTime,1> DiagonalVectorType; }; -template +template class DiagonalMatrix - : public DiagonalBase > + : public DiagonalBase > { public: @@ -156,8 +156,8 @@ class DiagonalMatrix inline void resize(int size) { m_diagonal.resize(size); } inline void setZero() { m_diagonal.setZero(); } inline void setZero(int size) { m_diagonal.setZero(size); } - inline void setIdentity() { m_diagonal.setIdentity(); } - inline void setIdentity(int size) { m_diagonal.setIdentity(size); } + inline void setIdentity() { m_diagonal.setOnes(); } + inline void setIdentity(int size) { m_diagonal.setOnes(size); } }; /** \class DiagonalWrapper diff --git a/Eigen/src/Core/DiagonalProduct.h b/Eigen/src/Core/DiagonalProduct.h index 7eaa380eb..fb3b11bdd 100644 --- a/Eigen/src/Core/DiagonalProduct.h +++ b/Eigen/src/Core/DiagonalProduct.h @@ -52,7 +52,7 @@ class DiagonalProduct : ei_no_assignment_operator, inline DiagonalProduct(const MatrixType& matrix, const DiagonalType& diagonal) : m_matrix(matrix), m_diagonal(diagonal) { - ei_assert(diagonal.diagonal().size() == (ProductOrder == DiagonalOnTheLeft ? matrix.rows() : matrix.cols())); + ei_assert(diagonal.diagonal().size() == (ProductOrder == OnTheLeft ? matrix.rows() : matrix.cols())); } inline int rows() const { return m_matrix.rows(); } @@ -60,7 +60,7 @@ class DiagonalProduct : ei_no_assignment_operator, const Scalar coeff(int row, int col) const { - return m_diagonal.diagonal().coeff(ProductOrder == DiagonalOnTheLeft ? row : col) * m_matrix.coeff(row, col); + return m_diagonal.diagonal().coeff(ProductOrder == OnTheLeft ? row : col) * m_matrix.coeff(row, col); } template @@ -71,10 +71,10 @@ class DiagonalProduct : ei_no_assignment_operator, InnerSize = (MatrixType::Flags & RowMajorBit) ? MatrixType::ColsAtCompileTime : MatrixType::RowsAtCompileTime, DiagonalVectorPacketLoadMode = (LoadMode == Aligned && ((InnerSize%16) == 0)) ? Aligned : Unaligned }; - const int indexInDiagonalVector = ProductOrder == DiagonalOnTheLeft ? row : col; + const int indexInDiagonalVector = ProductOrder == OnTheLeft ? row : col; - if((int(StorageOrder) == RowMajor && int(ProductOrder) == DiagonalOnTheLeft) - ||(int(StorageOrder) == ColMajor && int(ProductOrder) == DiagonalOnTheRight)) + if((int(StorageOrder) == RowMajor && int(ProductOrder) == OnTheLeft) + ||(int(StorageOrder) == ColMajor && int(ProductOrder) == OnTheRight)) { return ei_pmul(m_matrix.template packet(row, col), ei_pset1(m_diagonal.diagonal().coeff(indexInDiagonalVector))); @@ -95,20 +95,20 @@ class DiagonalProduct : ei_no_assignment_operator, */ template template -inline const DiagonalProduct +inline const DiagonalProduct MatrixBase::operator*(const DiagonalBase &diagonal) const { - return DiagonalProduct(derived(), diagonal.derived()); + return DiagonalProduct(derived(), diagonal.derived()); } /** \returns the diagonal matrix product of \c *this by the matrix \a matrix. */ template template -inline const DiagonalProduct +inline const DiagonalProduct DiagonalBase::operator*(const MatrixBase &matrix) const { - return DiagonalProduct(matrix.derived(), derived()); + return DiagonalProduct(matrix.derived(), derived()); } diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 4f8a8ce41..8078b75b0 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -410,7 +410,7 @@ template class MatrixBase void applyOnTheRight(const AnyMatrixBase& other); template - const DiagonalProduct + const DiagonalProduct operator*(const DiagonalBase &diagonal) const; template diff --git a/Eigen/src/Core/PermutationMatrix.h b/Eigen/src/Core/PermutationMatrix.h new file mode 100644 index 000000000..aaccb4e7b --- /dev/null +++ b/Eigen/src/Core/PermutationMatrix.h @@ -0,0 +1,205 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 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 . + +#ifndef EIGEN_PERMUTATIONMATRIX_H +#define EIGEN_PERMUTATIONMATRIX_H + +/** \nonstableyet + * \class PermutationMatrix + * + * \brief Permutation matrix + * + * \param SizeAtCompileTime the number of rows/cols, or Dynamic + * \param MaxSizeAtCompileTime the maximum number of rows/cols, or Dynamic. This optional parameter defaults to SizeAtCompileTime. + * + * This class represents a permutation matrix, internally stored as a vector of integers. + * The convention followed here is the same as on Wikipedia, + * namely: the matrix of permutation \a p is the matrix such that on each row \a i, the only nonzero coefficient is + * in column p(i). + * + * \sa class DiagonalMatrix + */ +template class PermutationMatrix; +template struct ei_permut_matrix_product_retval; + +template +struct ei_traits > + : ei_traits > +{}; + +template +class PermutationMatrix : public AnyMatrixBase > +{ + public: + + typedef ei_traits Traits; + typedef Matrix + DenseMatrixType; + enum { + Flags = Traits::Flags, + CoeffReadCost = Traits::CoeffReadCost, + RowsAtCompileTime = Traits::RowsAtCompileTime, + ColsAtCompileTime = Traits::ColsAtCompileTime, + MaxRowsAtCompileTime = Traits::MaxRowsAtCompileTime, + MaxColsAtCompileTime = Traits::MaxColsAtCompileTime + }; + typedef typename Traits::Scalar Scalar; + + typedef Matrix IndicesType; + + inline PermutationMatrix() + { + } + + template + inline PermutationMatrix(const PermutationMatrix& other) + : m_indices(other.indices()) {} + + /** copy constructor. prevent a default copy constructor from hiding the other templated constructor */ + inline PermutationMatrix(const PermutationMatrix& other) : m_indices(other.indices()) {} + + /** generic constructor from expression of the indices */ + template + explicit inline PermutationMatrix(const MatrixBase& other) : m_indices(other) + {} + + template + PermutationMatrix& operator=(const PermutationMatrix& other) + { + m_indices = other.indices(); + return *this; + } + + /** This is a special case of the templated operator=. Its purpose is to + * prevent a default operator= from hiding the templated operator=. + */ + PermutationMatrix& operator=(const PermutationMatrix& other) + { + m_indices = other.m_indices(); + return *this; + } + + inline PermutationMatrix(int rows, int cols) : m_indices(rows) + { + ei_assert(rows == cols); + } + + /** \returns the number of columns */ + inline int rows() const { return m_indices.size(); } + + /** \returns the number of rows */ + inline int cols() const { return m_indices.size(); } + + template + void evalTo(MatrixBase& other) const + { + other.setZero(); + for (int i=0; i +inline const ei_permut_matrix_product_retval, Derived, OnTheRight> +operator*(const MatrixBase& matrix, + const PermutationMatrix &permutation) +{ + return ei_permut_matrix_product_retval + , Derived, OnTheRight> + (permutation, matrix.derived()); +} + +/** \returns the matrix with the permutation applied to the rows. + */ +template +inline const ei_permut_matrix_product_retval + , Derived, OnTheLeft> +operator*(const PermutationMatrix &permutation, + const MatrixBase& matrix) +{ + return ei_permut_matrix_product_retval + , Derived, OnTheLeft> + (permutation, matrix.derived()); +} + +template +struct ei_traits > +{ + typedef typename MatrixType::PlainMatrixType ReturnMatrixType; +}; + +template +struct ei_permut_matrix_product_retval + : public ReturnByValue > +{ + typedef typename ei_cleantype::type MatrixTypeNestedCleaned; + + ei_permut_matrix_product_retval(const PermutationType& perm, const MatrixType& matrix) + : m_permutation(perm), m_matrix(matrix) + {} + + inline int rows() const { return m_matrix.rows(); } + inline int cols() const { return m_matrix.cols(); } + + template inline void evalTo(Dest& dst) const + { + const int n = Side==OnTheLeft ? rows() : cols(); + for(int i = 0; i < n; ++i) + { + Block< + Dest, + Side==OnTheLeft ? 1 : Dest::RowsAtCompileTime, + Side==OnTheRight ? 1 : Dest::ColsAtCompileTime + >(dst, Side==OnTheRight ? m_permutation.indices().coeff(i) : i) + + = + + Block< + MatrixTypeNestedCleaned, + Side==OnTheLeft ? 1 : MatrixType::RowsAtCompileTime, + Side==OnTheRight ? 1 : MatrixType::ColsAtCompileTime + >(m_matrix, Side==OnTheLeft ? m_permutation.indices().coeff(i) : i); + } + } + + protected: + const PermutationType& m_permutation; + const typename MatrixType::Nested m_matrix; +}; + +#endif // EIGEN_PERMUTATIONMATRIX_H diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index c9735b6e4..487425f88 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -194,8 +194,6 @@ const unsigned int SelfAdjoint = SelfAdjointBit; const unsigned int UnitUpperTriangular = UpperTriangularBit | UnitDiagBit; const unsigned int UnitLowerTriangular = LowerTriangularBit | UnitDiagBit; -enum { DiagonalOnTheLeft, DiagonalOnTheRight }; - enum { Unaligned=0, Aligned=1 }; enum { AsRequested=0, EnforceAlignedAccess=2 }; enum { ConditionalJumpCost = 5 }; @@ -232,7 +230,6 @@ enum { DontAlign = 0x2 }; -// used for the solvers enum { OnTheLeft = 1, OnTheRight = 2 diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 35e6dacf6..62e4bb31b 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -53,7 +53,7 @@ template class ProductBase; template class DiagonalBase; template class DiagonalWrapper; -template class DiagonalMatrix; +template class DiagonalMatrix; template class DiagonalProduct; template class Diagonal; diff --git a/scripts/check.in b/scripts/check.in index 525d2a589..3aa9501bb 100755 --- a/scripts/check.in +++ b/scripts/check.in @@ -3,7 +3,7 @@ if [ $# == 0 -o $# -ge 3 ] then - echo "usage: ./mctestr regexp [jobs]" + echo "usage: ./check regexp [jobs]" echo " makes and runs tests matching the regexp, with concurrent make jobs" exit 0 fi diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b074c8842..30668a2aa 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -158,6 +158,7 @@ ei_add_test(umeyama) ei_add_test(householder) ei_add_test(swap) ei_add_test(conservative_resize) +ei_add_test(permutationmatrices) ei_add_property(EIGEN_TESTING_SUMMARY "CXX: ${CMAKE_CXX_COMPILER}\n") if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/test/buildtests.in b/test/buildtests.in index 0d4d75112..52cc66281 100755 --- a/test/buildtests.in +++ b/test/buildtests.in @@ -2,7 +2,7 @@ if [ $# == 0 -o $# -ge 3 ] then - echo "usage: ./maketests regexp [jobs]" + echo "usage: ./buildtests regexp [jobs]" echo " makes tests matching the regexp, with concurrent make jobs" exit 0 fi diff --git a/test/permutationmatrices.cpp b/test/permutationmatrices.cpp new file mode 100644 index 000000000..c0353bc71 --- /dev/null +++ b/test/permutationmatrices.cpp @@ -0,0 +1,89 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 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 randomPermutationVector(PermutationVectorType& v, int size) +{ + typedef typename PermutationVectorType::Scalar Scalar; + v.resize(size); + for(int i = 0; i < size; ++i) v(i) = Scalar(i); + if(size == 1) return; + for(int n = 0; n < 3 * size; ++n) + { + int i = ei_random(0, size-1); + int j; + do j = ei_random(0, size-1); while(j==i); + std::swap(v(i), v(j)); + } +} + +using namespace std; +template void permutationmatrices(const MatrixType& m) +{ + typedef typename MatrixType::Scalar Scalar; + typedef typename MatrixType::RealScalar RealScalar; + enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime, + Options = MatrixType::Options }; + typedef PermutationMatrix LeftPermutationType; + typedef Matrix LeftPermutationVectorType; + typedef PermutationMatrix RightPermutationType; + typedef Matrix RightPermutationVectorType; + + int rows = m.rows(); + int cols = m.cols(); + + MatrixType m_original = MatrixType::Random(rows,cols); + LeftPermutationVectorType lv; + randomPermutationVector(lv, rows); + LeftPermutationType lp(lv); + RightPermutationVectorType rv; + randomPermutationVector(rv, cols); + RightPermutationType rp(rv); + MatrixType m_permuted = lp * m_original * rp; + + int i = ei_random(0, rows-1); + int j = ei_random(0, cols-1); + + VERIFY_IS_APPROX(m_original(lv(i),j), m_permuted(i,rv(j))); + + Matrix lm(lp); + Matrix rm(rp); + + VERIFY_IS_APPROX(m_permuted, lm*m_original*rm); +} + +void test_permutationmatrices() +{ + for(int i = 0; i < g_repeat; i++) { + CALL_SUBTEST_1( permutationmatrices(Matrix()) ); + CALL_SUBTEST_2( permutationmatrices(Matrix3f()) ); + CALL_SUBTEST_3( permutationmatrices(Matrix()) ); + CALL_SUBTEST_4( permutationmatrices(Matrix4d()) ); + CALL_SUBTEST_5( permutationmatrices(Matrix()) ); + CALL_SUBTEST_6( permutationmatrices(Matrix(20, 30)) ); + CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) ); + } +}