2008-06-02 22:54:52 +08:00
// This file is part of Eigen, a lightweight C++ template library
2009-05-23 02:25:33 +08:00
// for linear algebra.
2008-06-02 22:54:52 +08:00
//
2008-09-03 08:32:56 +08:00
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
2008-11-24 21:40:43 +08:00
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
2008-06-02 22:54:52 +08:00
//
// 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 <http://www.gnu.org/licenses/>.
2008-06-08 23:03:23 +08:00
// this hack is needed to make this file compiles with -pedantic (gcc)
2009-01-22 08:09:34 +08:00
# ifdef __GNUC__
2008-06-04 18:15:48 +08:00
# define throw(X)
2009-01-22 08:09:34 +08:00
# endif
2009-01-08 23:20:21 +08:00
// discard stack allocation as that too bypasses malloc
2008-12-31 08:25:31 +08:00
# define EIGEN_STACK_ALLOCATION_LIMIT 0
2009-01-08 23:20:21 +08:00
// any heap allocation will raise an assert
# define EIGEN_NO_MALLOC
2008-12-31 08:25:31 +08:00
2008-06-02 22:54:52 +08:00
# include "main.h"
2010-03-09 02:31:27 +08:00
# include <Eigen/Cholesky>
# include <Eigen/Eigenvalues>
# include <Eigen/LU>
# include <Eigen/QR>
# include <Eigen/SVD>
2008-06-02 22:54:52 +08:00
template < typename MatrixType > void nomalloc ( const MatrixType & m )
{
/* this test check no dynamic memory allocation are issued with fixed-size matrices
*/
typedef typename MatrixType : : Scalar Scalar ;
typedef Matrix < Scalar , MatrixType : : RowsAtCompileTime , 1 > VectorType ;
int rows = m . rows ( ) ;
int cols = m . cols ( ) ;
2008-07-21 08:34:46 +08:00
MatrixType m1 = MatrixType : : Random ( rows , cols ) ,
m2 = MatrixType : : Random ( rows , cols ) ,
2008-06-02 22:54:52 +08:00
m3 ( rows , cols ) ,
2008-07-21 08:34:46 +08:00
mzero = MatrixType : : Zero ( rows , cols ) ,
2008-06-02 22:54:52 +08:00
identity = Matrix < Scalar , MatrixType : : RowsAtCompileTime , MatrixType : : RowsAtCompileTime >
2008-07-21 08:34:46 +08:00
: : Identity ( rows , rows ) ,
2008-06-02 22:54:52 +08:00
square = Matrix < Scalar , MatrixType : : RowsAtCompileTime , MatrixType : : RowsAtCompileTime >
2008-07-21 08:34:46 +08:00
: : Random ( rows , rows ) ;
VectorType v1 = VectorType : : Random ( rows ) ,
v2 = VectorType : : Random ( rows ) ,
vzero = VectorType : : Zero ( rows ) ;
2008-06-02 22:54:52 +08:00
Scalar s1 = ei_random < Scalar > ( ) ;
int r = ei_random < int > ( 0 , rows - 1 ) ,
c = ei_random < int > ( 0 , cols - 1 ) ;
VERIFY_IS_APPROX ( ( m1 + m2 ) * s1 , s1 * m1 + s1 * m2 ) ;
VERIFY_IS_APPROX ( ( m1 + m2 ) ( r , c ) , ( m1 ( r , c ) ) + ( m2 ( r , c ) ) ) ;
2010-01-05 02:13:08 +08:00
VERIFY_IS_APPROX ( m1 . cwiseProduct ( m1 . block ( 0 , 0 , rows , cols ) ) , ( m1 . array ( ) * m1 . array ( ) ) . matrix ( ) ) ;
2009-08-06 18:20:02 +08:00
if ( MatrixType : : RowsAtCompileTime < EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD ) {
// If the matrices are too large, we have better to use the optimized GEMM
// routines which allocates temporaries. However, on some platforms
// these temporaries are allocated on the stack using alloca.
VERIFY_IS_APPROX ( ( m1 * m1 . transpose ( ) ) * m2 , m1 * ( m1 . transpose ( ) * m2 ) ) ;
}
2008-06-02 22:54:52 +08:00
}
2010-03-09 02:31:27 +08:00
void ctms_decompositions ( )
{
const int maxSize = 16 ;
const int size = 12 ;
typedef Eigen : : Matrix < float ,
Eigen : : Dynamic , Eigen : : Dynamic ,
2010-03-09 10:30:06 +08:00
0 ,
2010-03-09 02:31:27 +08:00
maxSize , maxSize > Matrix ;
typedef Eigen : : Matrix < float ,
Eigen : : Dynamic , 1 ,
2010-03-09 10:30:06 +08:00
0 ,
2010-03-09 02:31:27 +08:00
maxSize , 1 > Vector ;
typedef Eigen : : Matrix < std : : complex < float > ,
Eigen : : Dynamic , Eigen : : Dynamic ,
2010-03-09 10:30:06 +08:00
0 ,
2010-03-09 02:31:27 +08:00
maxSize , maxSize > ComplexMatrix ;
const Matrix A ( Matrix : : Random ( size , size ) ) ;
const ComplexMatrix complexA ( ComplexMatrix : : Random ( size , size ) ) ;
// const Matrix saA = A.adjoint() * A; // NOTE: This product allocates on the stack. The two following lines are a kludgy workaround
Matrix saA ( Matrix : : Constant ( size , size , 1.0 ) ) ;
saA . diagonal ( ) . setConstant ( 2.0 ) ;
// Cholesky module
Eigen : : LLT < Matrix > LLT ; LLT . compute ( A ) ;
Eigen : : LDLT < Matrix > LDLT ; LDLT . compute ( A ) ;
// Eigenvalues module
Eigen : : HessenbergDecomposition < ComplexMatrix > hessDecomp ; hessDecomp . compute ( complexA ) ;
Eigen : : ComplexSchur < ComplexMatrix > cSchur ( size ) ; cSchur . compute ( complexA ) ;
Eigen : : ComplexEigenSolver < ComplexMatrix > cEigSolver ; //cEigSolver.compute(complexA); // NOTE: Commented-out because makes test fail (L135 of ComplexEigenSolver.h has a product that allocates on the stack)
Eigen : : EigenSolver < Matrix > eigSolver ; eigSolver . compute ( A ) ;
Eigen : : SelfAdjointEigenSolver < Matrix > saEigSolver ( size ) ; saEigSolver . compute ( saA ) ;
Eigen : : Tridiagonalization < Matrix > tridiag ; tridiag . compute ( saA ) ;
// LU module
Eigen : : PartialPivLU < Matrix > ppLU ; ppLU . compute ( A ) ;
Eigen : : FullPivLU < Matrix > fpLU ; fpLU . compute ( A ) ;
// QR module
Eigen : : HouseholderQR < Matrix > hQR ; hQR . compute ( A ) ;
Eigen : : ColPivHouseholderQR < Matrix > cpQR ; cpQR . compute ( A ) ;
Eigen : : FullPivHouseholderQR < Matrix > fpQR ; fpQR . compute ( A ) ;
// SVD module
Eigen : : JacobiSVD < Matrix > jSVD ; jSVD . compute ( A ) ;
Eigen : : SVD < Matrix > svd ; svd . compute ( A ) ;
}
2008-06-02 22:54:52 +08:00
void test_nomalloc ( )
{
// check that our operator new is indeed called:
2010-05-31 04:00:58 +08:00
VERIFY_RAISES_ASSERT ( MatrixXd dummy ( MatrixXd : : Random ( 3 , 3 ) ) ) ;
2010-03-09 10:30:06 +08:00
CALL_SUBTEST_1 ( nomalloc ( Matrix < float , 1 , 1 > ( ) ) ) ;
CALL_SUBTEST_2 ( nomalloc ( Matrix4d ( ) ) ) ;
CALL_SUBTEST_3 ( nomalloc ( Matrix < float , 32 , 32 > ( ) ) ) ;
2010-03-09 02:31:27 +08:00
// Check decomposition modules with dynamic matrices that have a known compile-time max size (ctms)
2010-03-09 10:30:06 +08:00
CALL_SUBTEST_4 ( ctms_decompositions ( ) ) ;
2010-03-09 02:31:27 +08:00
2008-06-02 22:54:52 +08:00
}