Squashed 'third_party/eigen/' content from commit 61d72f6

Change-Id: Iccc90fa0b55ab44037f018046d2fcffd90d9d025
git-subtree-dir: third_party/eigen
git-subtree-split: 61d72f6383cfa842868c53e30e087b0258177257
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..f5f208a
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,291 @@
+
+# generate split test header file
+message(STATUS ${CMAKE_CURRENT_BINARY_DIR})
+file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h "")
+foreach(i RANGE 1 999)
+  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/split_test_helper.h
+    "#ifdef EIGEN_TEST_PART_${i}\n"
+    "#define CALL_SUBTEST_${i}(FUNC) CALL_SUBTEST(FUNC)\n"
+    "#else\n"
+    "#define CALL_SUBTEST_${i}(FUNC)\n"
+    "#endif\n\n"
+    )
+endforeach()
+
+# configure blas/lapack (use Eigen's ones)
+set(BLAS_FOUND TRUE)
+set(LAPACK_FOUND TRUE)
+set(BLAS_LIBRARIES eigen_blas)
+set(LAPACK_LIBRARIES eigen_lapack)
+
+set(EIGEN_TEST_MATRIX_DIR "" CACHE STRING "Enable testing of realword sparse matrices contained in the specified path")
+if(EIGEN_TEST_MATRIX_DIR)
+  if(NOT WIN32)
+    message(STATUS "Test realworld sparse matrices: ${EIGEN_TEST_MATRIX_DIR}")
+    add_definitions( -DTEST_REAL_CASES="${EIGEN_TEST_MATRIX_DIR}" )
+  else(NOT WIN32)
+    message(STATUS "REAL CASES CAN NOT BE CURRENTLY TESTED ON WIN32")
+  endif(NOT WIN32)
+endif(EIGEN_TEST_MATRIX_DIR)
+
+set(SPARSE_LIBS " ")
+
+find_package(Cholmod)
+if(CHOLMOD_FOUND AND BLAS_FOUND AND LAPACK_FOUND)
+  add_definitions("-DEIGEN_CHOLMOD_SUPPORT")
+  include_directories(${CHOLMOD_INCLUDES})
+  set(SPARSE_LIBS ${SPARSE_LIBS} ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
+  set(CHOLMOD_ALL_LIBS  ${CHOLMOD_LIBRARIES} ${BLAS_LIBRARIES} ${LAPACK_LIBRARIES})
+  ei_add_property(EIGEN_TESTED_BACKENDS "Cholmod, ")
+else()
+  ei_add_property(EIGEN_MISSING_BACKENDS "Cholmod, ")
+endif()
+
+find_package(Umfpack)
+if(UMFPACK_FOUND AND BLAS_FOUND)
+  add_definitions("-DEIGEN_UMFPACK_SUPPORT")
+  include_directories(${UMFPACK_INCLUDES})
+  set(SPARSE_LIBS ${SPARSE_LIBS} ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES})
+  set(UMFPACK_ALL_LIBS ${UMFPACK_LIBRARIES} ${BLAS_LIBRARIES})
+  ei_add_property(EIGEN_TESTED_BACKENDS "UmfPack, ")
+else()
+  ei_add_property(EIGEN_MISSING_BACKENDS "UmfPack, ")
+endif()
+
+find_package(SuperLU)
+if(SUPERLU_FOUND AND BLAS_FOUND)
+  add_definitions("-DEIGEN_SUPERLU_SUPPORT")
+  include_directories(${SUPERLU_INCLUDES})
+  set(SPARSE_LIBS ${SPARSE_LIBS} ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
+  set(SUPERLU_ALL_LIBS ${SUPERLU_LIBRARIES} ${BLAS_LIBRARIES})
+  ei_add_property(EIGEN_TESTED_BACKENDS  "SuperLU, ")
+else()
+  ei_add_property(EIGEN_MISSING_BACKENDS  "SuperLU, ")
+endif()
+
+
+find_package(Pastix)
+find_package(Scotch)
+find_package(Metis 5.0 REQUIRED)
+if(PASTIX_FOUND AND BLAS_FOUND)
+  add_definitions("-DEIGEN_PASTIX_SUPPORT")
+  include_directories(${PASTIX_INCLUDES})
+  if(SCOTCH_FOUND)
+    include_directories(${SCOTCH_INCLUDES})
+    set(PASTIX_LIBRARIES ${PASTIX_LIBRARIES} ${SCOTCH_LIBRARIES})
+  elseif(METIS_FOUND)
+    include_directories(${METIS_INCLUDES})
+    set(PASTIX_LIBRARIES ${PASTIX_LIBRARIES} ${METIS_LIBRARIES})
+  else(SCOTCH_FOUND)
+    ei_add_property(EIGEN_MISSING_BACKENDS  "PaStiX, ")
+  endif(SCOTCH_FOUND)
+  set(SPARSE_LIBS ${SPARSE_LIBS} ${PASTIX_LIBRARIES} ${ORDERING_LIBRARIES} ${BLAS_LIBRARIES})
+  set(PASTIX_ALL_LIBS ${PASTIX_LIBRARIES} ${BLAS_LIBRARIES})
+  ei_add_property(EIGEN_TESTED_BACKENDS  "PaStiX, ")
+else()
+  ei_add_property(EIGEN_MISSING_BACKENDS  "PaStiX, ")
+endif()
+
+if(METIS_FOUND)
+  add_definitions("-DEIGEN_METIS_SUPPORT")
+  include_directories(${METIS_INCLUDES})
+  ei_add_property(EIGEN_TESTED_BACKENDS "METIS, ")
+else()
+  ei_add_property(EIGEN_MISSING_BACKENDS "METIS, ")
+endif()
+
+find_package(SPQR)
+if(SPQR_FOUND AND BLAS_FOUND AND LAPACK_FOUND)
+  if(CHOLMOD_FOUND)
+    add_definitions("-DEIGEN_SPQR_SUPPORT")
+    include_directories(${SPQR_INCLUDES})
+    set(SPQR_ALL_LIBS ${SPQR_LIBRARIES} ${CHOLMOD_LIBRARIES} ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES})
+    set(SPARSE_LIBS ${SPARSE_LIBS} ${SPQR_ALL_LIBS})
+    ei_add_property(EIGEN_TESTED_BACKENDS "SPQR, ")
+  else(CHOLMOD_FOUND)
+    ei_add_property(EIGEN_MISSING_BACKENDS "SPQR, ")
+  endif(CHOLMOD_FOUND)
+endif()
+
+option(EIGEN_TEST_NOQT "Disable Qt support in unit tests" OFF)
+if(NOT EIGEN_TEST_NOQT)
+  find_package(Qt4)
+  if(QT4_FOUND)
+    include(${QT_USE_FILE})
+    ei_add_property(EIGEN_TESTED_BACKENDS  "Qt4 support, ")
+  else()
+    ei_add_property(EIGEN_MISSING_BACKENDS  "Qt4 support, ")
+  endif()
+endif(NOT EIGEN_TEST_NOQT)
+
+if(TEST_LIB)
+  add_definitions("-DEIGEN_EXTERN_INSTANTIATIONS=1")
+endif(TEST_LIB)
+
+set_property(GLOBAL PROPERTY EIGEN_CURRENT_SUBPROJECT "Official")
+add_custom_target(BuildOfficial)
+
+ei_add_test(meta)
+ei_add_test(sizeof)
+ei_add_test(dynalloc)
+ei_add_test(nomalloc)
+ei_add_test(first_aligned)
+ei_add_test(mixingtypes)
+ei_add_test(packetmath)
+ei_add_test(unalignedassert)
+ei_add_test(vectorization_logic)
+ei_add_test(basicstuff)
+ei_add_test(linearstructure)
+ei_add_test(integer_types)
+ei_add_test(cwiseop)
+ei_add_test(unalignedcount)
+ei_add_test(exceptions)
+ei_add_test(redux)
+ei_add_test(visitor)
+ei_add_test(block)
+ei_add_test(corners)
+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(diagonal)
+ei_add_test(miscmatrices)
+ei_add_test(commainitializer)
+ei_add_test(smallvectors)
+ei_add_test(mapped_matrix)
+ei_add_test(mapstride)
+ei_add_test(mapstaticmethods)
+ei_add_test(array)
+ei_add_test(array_for_matrix)
+ei_add_test(array_replicate)
+ei_add_test(array_reverse)
+ei_add_test(ref)
+ei_add_test(triangular)
+ei_add_test(selfadjoint)
+ei_add_test(product_selfadjoint)
+ei_add_test(product_symm)
+ei_add_test(product_syrk)
+ei_add_test(product_trmv)
+ei_add_test(product_trmm)
+ei_add_test(product_trsolve)
+ei_add_test(product_mmtr)
+ei_add_test(product_notemporary)
+ei_add_test(stable_norm)
+ei_add_test(bandmatrix)
+ei_add_test(cholesky)
+ei_add_test(lu)
+ei_add_test(determinant)
+ei_add_test(inverse)
+ei_add_test(qr)
+ei_add_test(qr_colpivoting)
+ei_add_test(qr_fullpivoting)
+ei_add_test(upperbidiagonalization)
+ei_add_test(hessenberg)
+ei_add_test(schur_real)
+ei_add_test(schur_complex)
+ei_add_test(eigensolver_selfadjoint)
+ei_add_test(eigensolver_generic)
+ei_add_test(eigensolver_complex)
+ei_add_test(real_qz)
+ei_add_test(eigensolver_generalized_real)
+ei_add_test(jacobi)
+ei_add_test(jacobisvd)
+ei_add_test(geo_orthomethods)
+ei_add_test(geo_homogeneous)
+ei_add_test(geo_quaternion)
+ei_add_test(geo_transformations)
+ei_add_test(geo_eulerangles)
+ei_add_test(geo_hyperplane)
+ei_add_test(geo_parametrizedline)
+ei_add_test(geo_alignedbox)
+ei_add_test(stdvector)
+ei_add_test(stdvector_overload)
+ei_add_test(stdlist)
+ei_add_test(stddeque)
+ei_add_test(resize)
+ei_add_test(sparse_vector)
+ei_add_test(sparse_basic)
+ei_add_test(sparse_product)
+ei_add_test(sparse_solvers)
+ei_add_test(umeyama)
+ei_add_test(householder)
+ei_add_test(swap)
+ei_add_test(conservative_resize)
+ei_add_test(permutationmatrices)
+ei_add_test(sparse_permutations)
+ei_add_test(nullary)
+ei_add_test(nesting_ops "${CMAKE_CXX_FLAGS_DEBUG}")
+ei_add_test(zerosized)
+ei_add_test(dontalign)
+ei_add_test(sizeoverflow)
+ei_add_test(prec_inverse_4x4)
+ei_add_test(vectorwiseop)
+ei_add_test(special_numbers)
+
+ei_add_test(simplicial_cholesky)
+ei_add_test(conjugate_gradient)
+ei_add_test(bicgstab)
+ei_add_test(sparselu)
+ei_add_test(sparseqr)
+
+# ei_add_test(denseLM)
+
+if(QT4_FOUND)
+  ei_add_test(qtvector "" "${QT_QTCORE_LIBRARY}")
+endif(QT4_FOUND)
+
+ei_add_test(eigen2support)
+
+if(UMFPACK_FOUND)
+  ei_add_test(umfpack_support "" "${UMFPACK_ALL_LIBS}")
+endif()
+
+if(SUPERLU_FOUND)
+  ei_add_test(superlu_support "" "${SUPERLU_ALL_LIBS}")
+endif()
+
+if(CHOLMOD_FOUND)
+  ei_add_test(cholmod_support "" "${CHOLMOD_ALL_LIBS}")
+endif()
+
+if(PARDISO_FOUND)
+  ei_add_test(pardiso_support "" "${PARDISO_ALL_LIBS}")
+endif()
+
+if(PASTIX_FOUND AND (SCOTCH_FOUND OR METIS_FOUND))
+  ei_add_test(pastix_support "" "${PASTIX_ALL_LIBS}")
+endif()
+
+if(SPQR_FOUND AND CHOLMOD_FOUND)
+  ei_add_test(spqr_support "" "${SPQR_ALL_LIBS}")
+endif()
+
+if(METIS_FOUND)
+ei_add_test(metis_support "" "${METIS_LIBRARIES}")
+endif()
+
+string(TOLOWER "${CMAKE_CXX_COMPILER}" cmake_cxx_compiler_tolower)
+if(cmake_cxx_compiler_tolower MATCHES "qcc")
+  set(CXX_IS_QCC "ON")
+endif()
+
+ei_add_property(EIGEN_TESTING_SUMMARY "CXX:               ${CMAKE_CXX_COMPILER}\n")
+if(CMAKE_COMPILER_IS_GNUCXX AND NOT CXX_IS_QCC)
+  execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version COMMAND head -n 1 OUTPUT_VARIABLE EIGEN_CXX_VERSION_STRING OUTPUT_STRIP_TRAILING_WHITESPACE)
+  ei_add_property(EIGEN_TESTING_SUMMARY "CXX_VERSION:       ${EIGEN_CXX_VERSION_STRING}\n")
+endif()
+ei_add_property(EIGEN_TESTING_SUMMARY "CXX_FLAGS:         ${CMAKE_CXX_FLAGS}\n")
+ei_add_property(EIGEN_TESTING_SUMMARY "Sparse lib flags:  ${SPARSE_LIBS}\n")
+
+option(EIGEN_TEST_EIGEN2 "Run whole Eigen2 test suite against EIGEN2_SUPPORT" OFF)
+mark_as_advanced(EIGEN_TEST_EIGEN2)
+if(EIGEN_TEST_EIGEN2)
+  add_subdirectory(eigen2)
+endif()
+
+
+option(EIGEN_TEST_BUILD_DOCUMENTATION "Test building the doxygen documentation" OFF)
+IF(EIGEN_TEST_BUILD_DOCUMENTATION)
+  add_dependencies(buildtests doc)
+ENDIF()
diff --git a/test/adjoint.cpp b/test/adjoint.cpp
new file mode 100644
index 0000000..ea36f78
--- /dev/null
+++ b/test/adjoint.cpp
@@ -0,0 +1,160 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+
+#include "main.h"
+
+template<bool IsInteger> struct adjoint_specific;
+
+template<> struct adjoint_specific<true> {
+  template<typename Vec, typename Mat, typename Scalar>
+  static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
+    VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), 0));
+    VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), 0));
+    
+    // check compatibility of dot and adjoint
+    VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), 0));
+  }
+};
+
+template<> struct adjoint_specific<false> {
+  template<typename Vec, typename Mat, typename Scalar>
+  static void run(const Vec& v1, const Vec& v2, Vec& v3, const Mat& square, Scalar s1, Scalar s2) {
+    typedef typename NumTraits<Scalar>::Real RealScalar;
+    using std::abs;
+    
+    RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : (std::max)((s1 * v1 + s2 * v2).norm(),v3.norm());
+    VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     numext::conj(s1) * v1.dot(v3) + numext::conj(s2) * v2.dot(v3), ref));
+    VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
+  
+    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
+    // check normalized() and normalize()
+    VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
+    v3 = v1;
+    v3.normalize();
+    VERIFY_IS_APPROX(v1, v1.norm() * v3);
+    VERIFY_IS_APPROX(v3, v1.normalized());
+    VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
+    
+    // check compatibility of dot and adjoint
+    ref = NumTraits<Scalar>::IsInteger ? 0 : (std::max)((std::max)(v1.norm(),v2.norm()),(std::max)((square * v2).norm(),(square.adjoint() * v1).norm()));
+    VERIFY(internal::isMuchSmallerThan(abs(v1.dot(square * v2) - (square.adjoint() * v1).dot(v2)), ref, test_precision<Scalar>()));
+    
+    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
+    // normalized() in order to produce a consistent result.
+    VERIFY_IS_APPROX(Vec::Random(v1.size()).normalized().norm(), RealScalar(1));
+  }
+};
+
+template<typename MatrixType> void adjoint(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Transpose.h Conjugate.h Dot.h
+  */
+  using std::abs;
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             square = SquareMatrixType::Random(rows, rows);
+  VectorType v1 = VectorType::Random(rows),
+             v2 = VectorType::Random(rows),
+             v3 = VectorType::Random(rows),
+             vzero = VectorType::Zero(rows);
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>();
+
+  // check basic compatibility of adjoint, transpose, conjugate
+  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
+  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);
+
+  // check multiplicative behavior
+  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
+  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     numext::conj(s1) * m1.adjoint());
+
+  // check basic properties of dot, squaredNorm
+  VERIFY_IS_APPROX(numext::conj(v1.dot(v2)),               v2.dot(v1));
+  VERIFY_IS_APPROX(numext::real(v1.dot(v1)),               v1.squaredNorm());
+  
+  adjoint_specific<NumTraits<Scalar>::IsInteger>::run(v1, v2, v3, square, s1, s2);
+  
+  VERIFY_IS_MUCH_SMALLER_THAN(abs(vzero.dot(v1)),  static_cast<RealScalar>(1));
+  
+  // like in testBasicStuff, test operator() to check const-qualification
+  Index r = internal::random<Index>(0, rows-1),
+      c = internal::random<Index>(0, cols-1);
+  VERIFY_IS_APPROX(m1.conjugate()(r,c), numext::conj(m1(r,c)));
+  VERIFY_IS_APPROX(m1.adjoint()(c,r), numext::conj(m1(r,c)));
+
+  // check inplace transpose
+  m3 = m1;
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1.transpose());
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1);
+
+  // check inplace adjoint
+  m3 = m1;
+  m3.adjointInPlace();
+  VERIFY_IS_APPROX(m3,m1.adjoint());
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1.conjugate());
+
+  // check mixed dot product
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
+  RealVectorType rv1 = RealVectorType::Random(rows);
+  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
+  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
+}
+
+void test_adjoint()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( adjoint(Matrix3d()) );
+    CALL_SUBTEST_3( adjoint(Matrix4f()) );
+    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  // test a large static matrix only once
+  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
+
+#ifdef EIGEN_TEST_PART_4
+  {
+    MatrixXcf a(10,10), b(10,10);
+    VERIFY_RAISES_ASSERT(a = a.transpose());
+    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
+    VERIFY_RAISES_ASSERT(a = b + a.transpose());
+    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
+    VERIFY_RAISES_ASSERT(a = a.adjoint());
+    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
+    VERIFY_RAISES_ASSERT(a = b + a.adjoint());
+
+    // no assertion should be triggered for these cases:
+    a.transpose() = a.transpose();
+    a.transpose() += a.transpose();
+    a.transpose() += a.transpose() + b;
+    a.transpose() = a.adjoint();
+    a.transpose() += a.adjoint();
+    a.transpose() += a.adjoint() + b;
+  }
+#endif
+}
+
diff --git a/test/array.cpp b/test/array.cpp
new file mode 100644
index 0000000..68f6b3d
--- /dev/null
+++ b/test/array.cpp
@@ -0,0 +1,308 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename ArrayType> void array(const ArrayType& m)
+{
+  typedef typename ArrayType::Index Index;
+  typedef typename ArrayType::Scalar Scalar;
+  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
+  typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols(); 
+
+  ArrayType m1 = ArrayType::Random(rows, cols),
+             m2 = ArrayType::Random(rows, cols),
+             m3(rows, cols);
+
+  ColVectorType cv1 = ColVectorType::Random(rows);
+  RowVectorType rv1 = RowVectorType::Random(cols);
+
+  Scalar  s1 = internal::random<Scalar>(),
+          s2 = internal::random<Scalar>();
+
+  // scalar addition
+  VERIFY_IS_APPROX(m1 + s1, s1 + m1);
+  VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
+  VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
+  VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
+  VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
+  VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
+  m3 = m1;
+  m3 += s2;
+  VERIFY_IS_APPROX(m3, m1 + s2);
+  m3 = m1;
+  m3 -= s1;
+  VERIFY_IS_APPROX(m3, m1 - s1);  
+  
+  // scalar operators via Maps
+  m3 = m1;
+  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
+  VERIFY_IS_APPROX(m1, m3 - m2);
+  
+  m3 = m1;
+  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
+  VERIFY_IS_APPROX(m1, m3 + m2);
+  
+  m3 = m1;
+  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
+  VERIFY_IS_APPROX(m1, m3 * m2);
+  
+  m3 = m1;
+  m2 = ArrayType::Random(rows,cols);
+  m2 = (m2==0).select(1,m2);
+  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());  
+  VERIFY_IS_APPROX(m1, m3 / m2);
+
+  // reductions
+  VERIFY_IS_APPROX(m1.abs().colwise().sum().sum(), m1.abs().sum());
+  VERIFY_IS_APPROX(m1.abs().rowwise().sum().sum(), m1.abs().sum());
+  using std::abs;
+  VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.colwise().sum().sum() - m1.sum()), m1.abs().sum());
+  VERIFY_IS_MUCH_SMALLER_THAN(abs(m1.rowwise().sum().sum() - m1.sum()), m1.abs().sum());
+  if (!internal::isMuchSmallerThan(abs(m1.sum() - (m1+m2).sum()), m1.abs().sum(), test_precision<Scalar>()))
+      VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
+  VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
+
+  // vector-wise ops
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
+}
+
+template<typename ArrayType> void comparisons(const ArrayType& m)
+{
+  using std::abs;
+  typedef typename ArrayType::Index Index;
+  typedef typename ArrayType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  ArrayType m1 = ArrayType::Random(rows, cols),
+             m2 = ArrayType::Random(rows, cols),
+             m3(rows, cols);            
+
+  VERIFY(((m1 + Scalar(1)) > m1).all());
+  VERIFY(((m1 - Scalar(1)) < m1).all());
+  if (rows*cols>1)
+  {
+    m3 = m1;
+    m3(r,c) += 1;
+    VERIFY(! (m1 < m3).all() );
+    VERIFY(! (m1 > m3).all() );
+  }
+  VERIFY(!(m1 > m2 && m1 < m2).any());
+  VERIFY((m1 <= m2 || m1 >= m2).all());
+
+  // comparisons to scalar
+  VERIFY( (m1 != (m1(r,c)+1) ).any() );
+  VERIFY( (m1 > (m1(r,c)-1) ).any() );
+  VERIFY( (m1 < (m1(r,c)+1) ).any() );
+  VERIFY( (m1 == m1(r,c) ).any() );
+
+  // test Select
+  VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
+  VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
+  Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
+  for (int j=0; j<cols; ++j)
+  for (int i=0; i<rows; ++i)
+    m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
+  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
+                        .select(ArrayType::Zero(rows,cols),m1), m3);
+  // shorter versions:
+  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
+                        .select(0,m1), m3);
+  VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
+                        .select(m1,0), m3);
+  // even shorter version:
+  VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);
+
+  // count
+  VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);
+
+  // and/or
+  VERIFY( (m1<RealScalar(0) && m1>RealScalar(0)).count() == 0);
+  VERIFY( (m1<RealScalar(0) || m1>=RealScalar(0)).count() == rows*cols);
+  RealScalar a = m1.abs().mean();
+  VERIFY( (m1<-a || m1>a).count() == (m1.abs()>a).count());
+
+  typedef Array<typename ArrayType::Index, Dynamic, 1> ArrayOfIndices;
+
+  // TODO allows colwise/rowwise for array
+  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
+  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
+}
+
+template<typename ArrayType> void array_real(const ArrayType& m)
+{
+  using std::abs;
+  using std::sqrt;
+  typedef typename ArrayType::Index Index;
+  typedef typename ArrayType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  ArrayType m1 = ArrayType::Random(rows, cols),
+            m2 = ArrayType::Random(rows, cols),
+            m3(rows, cols);
+
+  Scalar  s1 = internal::random<Scalar>();
+
+  // these tests are mostly to check possible compilation issues.
+  VERIFY_IS_APPROX(m1.sin(), sin(m1));
+  VERIFY_IS_APPROX(m1.cos(), cos(m1));
+  VERIFY_IS_APPROX(m1.asin(), asin(m1));
+  VERIFY_IS_APPROX(m1.acos(), acos(m1));
+  VERIFY_IS_APPROX(m1.tan(), tan(m1));
+  
+  VERIFY_IS_APPROX(cos(m1+RealScalar(3)*m2), cos((m1+RealScalar(3)*m2).eval()));
+
+  VERIFY_IS_APPROX(m1.abs().sqrt(), sqrt(abs(m1)));
+  VERIFY_IS_APPROX(m1.abs(), sqrt(numext::abs2(m1)));
+
+  VERIFY_IS_APPROX(numext::abs2(numext::real(m1)) + numext::abs2(numext::imag(m1)), numext::abs2(m1));
+  VERIFY_IS_APPROX(numext::abs2(real(m1)) + numext::abs2(imag(m1)), numext::abs2(m1));
+  if(!NumTraits<Scalar>::IsComplex)
+    VERIFY_IS_APPROX(numext::real(m1), m1);
+
+  // shift argument of logarithm so that it is not zero
+  Scalar smallNumber = NumTraits<Scalar>::dummy_precision();
+  VERIFY_IS_APPROX((m1.abs() + smallNumber).log() , log(abs(m1) + smallNumber));
+
+  VERIFY_IS_APPROX(m1.exp() * m2.exp(), exp(m1+m2));
+  VERIFY_IS_APPROX(m1.exp(), exp(m1));
+  VERIFY_IS_APPROX(m1.exp() / m2.exp(),(m1-m2).exp());
+
+  VERIFY_IS_APPROX(m1.pow(2), m1.square());
+  VERIFY_IS_APPROX(pow(m1,2), m1.square());
+
+  ArrayType exponents = ArrayType::Constant(rows, cols, RealScalar(2));
+  VERIFY_IS_APPROX(Eigen::pow(m1,exponents), m1.square());
+
+  m3 = m1.abs();
+  VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
+  VERIFY_IS_APPROX(pow(m3,RealScalar(0.5)), m3.sqrt());
+
+  // scalar by array division
+  const RealScalar tiny = sqrt(std::numeric_limits<RealScalar>::epsilon());
+  s1 += Scalar(tiny);
+  m1 += ArrayType::Constant(rows,cols,Scalar(tiny));
+  VERIFY_IS_APPROX(s1/m1, s1 * m1.inverse());
+  
+  // check inplace transpose
+  m3 = m1;
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1.transpose());
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1);
+}
+
+template<typename ArrayType> void array_complex(const ArrayType& m)
+{
+  typedef typename ArrayType::Index Index;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  ArrayType m1 = ArrayType::Random(rows, cols),
+            m2(rows, cols);
+
+  for (Index i = 0; i < m.rows(); ++i)
+    for (Index j = 0; j < m.cols(); ++j)
+      m2(i,j) = sqrt(m1(i,j));
+
+  VERIFY_IS_APPROX(m1.sqrt(), m2);
+  VERIFY_IS_APPROX(m1.sqrt(), Eigen::sqrt(m1));
+}
+
+template<typename ArrayType> void min_max(const ArrayType& m)
+{
+  typedef typename ArrayType::Index Index;
+  typedef typename ArrayType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  ArrayType m1 = ArrayType::Random(rows, cols);
+
+  // min/max with array
+  Scalar maxM1 = m1.maxCoeff();
+  Scalar minM1 = m1.minCoeff();
+
+  VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)(ArrayType::Constant(rows,cols, minM1)));
+  VERIFY_IS_APPROX(m1, (m1.min)(ArrayType::Constant(rows,cols, maxM1)));
+
+  VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)(ArrayType::Constant(rows,cols, maxM1)));
+  VERIFY_IS_APPROX(m1, (m1.max)(ArrayType::Constant(rows,cols, minM1)));
+
+  // min/max with scalar input
+  VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, minM1), (m1.min)( minM1));
+  VERIFY_IS_APPROX(m1, (m1.min)( maxM1));
+
+  VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)( maxM1));
+  VERIFY_IS_APPROX(m1, (m1.max)( minM1));
+
+}
+
+void test_array()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
+    CALL_SUBTEST_2( array(Array22f()) );
+    CALL_SUBTEST_3( array(Array44d()) );
+    CALL_SUBTEST_4( array(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( array(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( array(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
+    CALL_SUBTEST_2( comparisons(Array22f()) );
+    CALL_SUBTEST_3( comparisons(Array44d()) );
+    CALL_SUBTEST_5( comparisons(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( comparisons(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( min_max(Array<float, 1, 1>()) );
+    CALL_SUBTEST_2( min_max(Array22f()) );
+    CALL_SUBTEST_3( min_max(Array44d()) );
+    CALL_SUBTEST_5( min_max(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( min_max(ArrayXXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
+    CALL_SUBTEST_2( array_real(Array22f()) );
+    CALL_SUBTEST_3( array_real(Array44d()) );
+    CALL_SUBTEST_5( array_real(ArrayXXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_4( array_complex(ArrayXXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+
+  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
+  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
+  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
+  typedef CwiseUnaryOp<internal::scalar_sum_op<double>, ArrayXd > Xpr;
+  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
+                           ArrayBase<Xpr>
+                         >::value));
+}
diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp
new file mode 100644
index 0000000..9667e1f
--- /dev/null
+++ b/test/array_for_matrix.cpp
@@ -0,0 +1,254 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void array_for_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
+  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType; 
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  ColVectorType cv1 = ColVectorType::Random(rows);
+  RowVectorType rv1 = RowVectorType::Random(cols);
+  
+  Scalar  s1 = internal::random<Scalar>(),
+          s2 = internal::random<Scalar>();
+          
+  // scalar addition
+  VERIFY_IS_APPROX(m1.array() + s1, s1 + m1.array());
+  VERIFY_IS_APPROX((m1.array() + s1).matrix(), MatrixType::Constant(rows,cols,s1) + m1);
+  VERIFY_IS_APPROX(((m1*Scalar(2)).array() - s2).matrix(), (m1+m1) - MatrixType::Constant(rows,cols,s2) );
+  m3 = m1;
+  m3.array() += s2;
+  VERIFY_IS_APPROX(m3, (m1.array() + s2).matrix());
+  m3 = m1;
+  m3.array() -= s1;
+  VERIFY_IS_APPROX(m3, (m1.array() - s1).matrix());
+
+  // reductions
+  VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum().sum() - m1.sum(), m1.squaredNorm());
+  VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum().sum() - m1.sum(), m1.squaredNorm());
+  VERIFY_IS_MUCH_SMALLER_THAN(m1.colwise().sum() + m2.colwise().sum() - (m1+m2).colwise().sum(), (m1+m2).squaredNorm());
+  VERIFY_IS_MUCH_SMALLER_THAN(m1.rowwise().sum() - m2.rowwise().sum() - (m1-m2).rowwise().sum(), (m1-m2).squaredNorm());
+  VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
+
+  // vector-wise ops
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
+  m3 = m1;
+  VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
+  
+  // empty objects
+  VERIFY_IS_APPROX(m1.block(0,0,0,cols).colwise().sum(),  RowVectorType::Zero(cols));
+  VERIFY_IS_APPROX(m1.block(0,0,rows,0).rowwise().prod(), ColVectorType::Ones(rows));
+  
+  // verify the const accessors exist
+  const Scalar& ref_m1 = m.matrix().array().coeffRef(0);
+  const Scalar& ref_m2 = m.matrix().array().coeffRef(0,0);
+  const Scalar& ref_a1 = m.array().matrix().coeffRef(0);
+  const Scalar& ref_a2 = m.array().matrix().coeffRef(0,0);
+  VERIFY(&ref_a1 == &ref_m1);
+  VERIFY(&ref_a2 == &ref_m2);
+}
+
+template<typename MatrixType> void comparisons(const MatrixType& m)
+{
+  using std::abs;
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  VERIFY(((m1.array() + Scalar(1)) > m1.array()).all());
+  VERIFY(((m1.array() - Scalar(1)) < m1.array()).all());
+  if (rows*cols>1)
+  {
+    m3 = m1;
+    m3(r,c) += 1;
+    VERIFY(! (m1.array() < m3.array()).all() );
+    VERIFY(! (m1.array() > m3.array()).all() );
+  }
+
+  // comparisons to scalar
+  VERIFY( (m1.array() != (m1(r,c)+1) ).any() );
+  VERIFY( (m1.array() > (m1(r,c)-1) ).any() );
+  VERIFY( (m1.array() < (m1(r,c)+1) ).any() );
+  VERIFY( (m1.array() == m1(r,c) ).any() );
+  VERIFY( m1.cwiseEqual(m1(r,c)).any() );
+
+  // test Select
+  VERIFY_IS_APPROX( (m1.array()<m2.array()).select(m1,m2), m1.cwiseMin(m2) );
+  VERIFY_IS_APPROX( (m1.array()>m2.array()).select(m1,m2), m1.cwiseMax(m2) );
+  Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
+  for (int j=0; j<cols; ++j)
+  for (int i=0; i<rows; ++i)
+    m3(i,j) = abs(m1(i,j))<mid ? 0 : m1(i,j);
+  VERIFY_IS_APPROX( (m1.array().abs()<MatrixType::Constant(rows,cols,mid).array())
+                        .select(MatrixType::Zero(rows,cols),m1), m3);
+  // shorter versions:
+  VERIFY_IS_APPROX( (m1.array().abs()<MatrixType::Constant(rows,cols,mid).array())
+                        .select(0,m1), m3);
+  VERIFY_IS_APPROX( (m1.array().abs()>=MatrixType::Constant(rows,cols,mid).array())
+                        .select(m1,0), m3);
+  // even shorter version:
+  VERIFY_IS_APPROX( (m1.array().abs()<mid).select(0,m1), m3);
+
+  // count
+  VERIFY(((m1.array().abs()+1)>RealScalar(0.1)).count() == rows*cols);
+
+  typedef Matrix<typename MatrixType::Index, Dynamic, 1> VectorOfIndices;
+
+  // TODO allows colwise/rowwise for array
+  VERIFY_IS_APPROX(((m1.array().abs()+1)>RealScalar(0.1)).matrix().colwise().count(), VectorOfIndices::Constant(cols,rows).transpose());
+  VERIFY_IS_APPROX(((m1.array().abs()+1)>RealScalar(0.1)).matrix().rowwise().count(), VectorOfIndices::Constant(rows, cols));
+}
+
+template<typename VectorType> void lpNorm(const VectorType& v)
+{
+  using std::sqrt;
+  VectorType u = VectorType::Random(v.size());
+
+  VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwiseAbs().maxCoeff());
+  VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwiseAbs().sum());
+  VERIFY_IS_APPROX(u.template lpNorm<2>(), sqrt(u.array().abs().square().sum()));
+  VERIFY_IS_APPROX(numext::pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.array().abs().pow(5).sum());
+}
+
+template<typename MatrixType> void cwise_min_max(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols);
+
+  // min/max with array
+  Scalar maxM1 = m1.maxCoeff();
+  Scalar minM1 = m1.minCoeff();
+
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1), m1.cwiseMin(MatrixType::Constant(rows,cols, minM1)));
+  VERIFY_IS_APPROX(m1, m1.cwiseMin(MatrixType::Constant(rows,cols, maxM1)));
+
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1), m1.cwiseMax(MatrixType::Constant(rows,cols, maxM1)));
+  VERIFY_IS_APPROX(m1, m1.cwiseMax(MatrixType::Constant(rows,cols, minM1)));
+
+  // min/max with scalar input
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1), m1.cwiseMin( minM1));
+  VERIFY_IS_APPROX(m1, m1.cwiseMin(maxM1));
+  VERIFY_IS_APPROX(-m1, (-m1).cwiseMin(-minM1));
+  VERIFY_IS_APPROX(-m1.array(), ((-m1).array().min)( -minM1));
+
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1), m1.cwiseMax( maxM1));
+  VERIFY_IS_APPROX(m1, m1.cwiseMax(minM1));
+  VERIFY_IS_APPROX(-m1, (-m1).cwiseMax(-maxM1));
+  VERIFY_IS_APPROX(-m1.array(), ((-m1).array().max)(-maxM1));
+
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, minM1).array(), (m1.array().min)( minM1));
+  VERIFY_IS_APPROX(m1.array(), (m1.array().min)( maxM1));
+
+  VERIFY_IS_APPROX(MatrixType::Constant(rows,cols, maxM1).array(), (m1.array().max)( maxM1));
+  VERIFY_IS_APPROX(m1.array(), (m1.array().max)( minM1));
+
+}
+
+template<typename MatrixTraits> void resize(const MatrixTraits& t)
+{
+  typedef typename MatrixTraits::Index Index;
+  typedef typename MatrixTraits::Scalar Scalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
+  typedef Array<Scalar,Dynamic,Dynamic> Array2DType;
+  typedef Matrix<Scalar,Dynamic,1> VectorType;
+  typedef Array<Scalar,Dynamic,1> Array1DType;
+
+  Index rows = t.rows(), cols = t.cols();
+
+  MatrixType m(rows,cols);
+  VectorType v(rows);
+  Array2DType a2(rows,cols);
+  Array1DType a1(rows);
+
+  m.array().resize(rows+1,cols+1);
+  VERIFY(m.rows()==rows+1 && m.cols()==cols+1);
+  a2.matrix().resize(rows+1,cols+1);
+  VERIFY(a2.rows()==rows+1 && a2.cols()==cols+1);
+  v.array().resize(cols);
+  VERIFY(v.size()==cols);
+  a1.matrix().resize(cols);
+  VERIFY(a1.size()==cols);
+}
+
+void regression_bug_654()
+{
+  ArrayXf a = RowVectorXf(3);
+  VectorXf v = Array<float,1,Dynamic>(3);
+}
+
+void test_array_for_matrix()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( array_for_matrix(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( array_for_matrix(Matrix2f()) );
+    CALL_SUBTEST_3( array_for_matrix(Matrix4d()) );
+    CALL_SUBTEST_4( array_for_matrix(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( array_for_matrix(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( array_for_matrix(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( comparisons(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( comparisons(Matrix2f()) );
+    CALL_SUBTEST_3( comparisons(Matrix4d()) );
+    CALL_SUBTEST_5( comparisons(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( comparisons(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( cwise_min_max(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( cwise_min_max(Matrix2f()) );
+    CALL_SUBTEST_3( cwise_min_max(Matrix4d()) );
+    CALL_SUBTEST_5( cwise_min_max(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( cwise_min_max(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( lpNorm(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( lpNorm(Vector2f()) );
+    CALL_SUBTEST_7( lpNorm(Vector3d()) );
+    CALL_SUBTEST_8( lpNorm(Vector4f()) );
+    CALL_SUBTEST_5( lpNorm(VectorXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_4( lpNorm(VectorXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_4( resize(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( resize(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( resize(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  CALL_SUBTEST_6( regression_bug_654() );
+}
diff --git a/test/array_replicate.cpp b/test/array_replicate.cpp
new file mode 100644
index 0000000..f412d1a
--- /dev/null
+++ b/test/array_replicate.cpp
@@ -0,0 +1,69 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void replicate(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Replicate.cpp
+  */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, Dynamic, Dynamic> MatrixX;
+  typedef Matrix<Scalar, Dynamic, 1> VectorX;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols);
+
+  VectorType v1 = VectorType::Random(rows);
+
+  MatrixX x1, x2;
+  VectorX vx1;
+
+  int  f1 = internal::random<int>(1,10),
+       f2 = internal::random<int>(1,10);
+
+  x1.resize(rows*f1,cols*f2);
+  for(int j=0; j<f2; j++)
+  for(int i=0; i<f1; i++)
+    x1.block(i*rows,j*cols,rows,cols) = m1;
+  VERIFY_IS_APPROX(x1, m1.replicate(f1,f2));
+
+  x2.resize(2*rows,3*cols);
+  x2 << m2, m2, m2,
+        m2, m2, m2;
+  VERIFY_IS_APPROX(x2, (m2.template replicate<2,3>()));
+
+  x2.resize(rows,f1);
+  for (int j=0; j<f1; ++j)
+    x2.col(j) = v1;
+  VERIFY_IS_APPROX(x2, v1.rowwise().replicate(f1));
+
+  vx1.resize(rows*f2);
+  for (int j=0; j<f2; ++j)
+    vx1.segment(j*rows,rows) = v1;
+  VERIFY_IS_APPROX(vx1, v1.colwise().replicate(f2));
+}
+
+void test_array_replicate()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( replicate(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( replicate(Vector2f()) );
+    CALL_SUBTEST_3( replicate(Vector3d()) );
+    CALL_SUBTEST_4( replicate(Vector4f()) );
+    CALL_SUBTEST_5( replicate(VectorXf(16)) );
+    CALL_SUBTEST_6( replicate(VectorXcd(10)) );
+  }
+}
diff --git a/test/array_reverse.cpp b/test/array_reverse.cpp
new file mode 100644
index 0000000..fbe7a99
--- /dev/null
+++ b/test/array_reverse.cpp
@@ -0,0 +1,128 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <iostream>
+
+using namespace std;
+
+template<typename MatrixType> void reverse(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols);
+  VectorType v1 = VectorType::Random(rows);
+
+  MatrixType m1_r = m1.reverse();
+  // Verify that MatrixBase::reverse() works
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_r(i, j), m1(rows - 1 - i, cols - 1 - j));
+    }
+  }
+
+  Reverse<MatrixType> m1_rd(m1);
+  // Verify that a Reverse default (in both directions) of an expression works
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_rd(i, j), m1(rows - 1 - i, cols - 1 - j));
+    }
+  }
+
+  Reverse<MatrixType, BothDirections> m1_rb(m1);
+  // Verify that a Reverse in both directions of an expression works
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_rb(i, j), m1(rows - 1 - i, cols - 1 - j));
+    }
+  }
+
+  Reverse<MatrixType, Vertical> m1_rv(m1);
+  // Verify that a Reverse in the vertical directions of an expression works
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_rv(i, j), m1(rows - 1 - i, j));
+    }
+  }
+
+  Reverse<MatrixType, Horizontal> m1_rh(m1);
+  // Verify that a Reverse in the horizontal directions of an expression works
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_rh(i, j), m1(i, cols - 1 - j));
+    }
+  }
+
+  VectorType v1_r = v1.reverse();
+  // Verify that a VectorType::reverse() of an expression works
+  for ( int i = 0; i < rows; i++ ) {
+    VERIFY_IS_APPROX(v1_r(i), v1(rows - 1 - i));
+  }
+
+  MatrixType m1_cr = m1.colwise().reverse();
+  // Verify that PartialRedux::reverse() works (for colwise())
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_cr(i, j), m1(rows - 1 - i, j));
+    }
+  }
+
+  MatrixType m1_rr = m1.rowwise().reverse();
+  // Verify that PartialRedux::reverse() works (for rowwise())
+  for ( int i = 0; i < rows; i++ ) {
+    for ( int j = 0; j < cols; j++ ) {
+      VERIFY_IS_APPROX(m1_rr(i, j), m1(i, cols - 1 - j));
+    }
+  }
+
+  Scalar x = internal::random<Scalar>();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  m1.reverse()(r, c) = x;
+  VERIFY_IS_APPROX(x, m1(rows - 1 - r, cols - 1 - c));
+
+  /*
+  m1.colwise().reverse()(r, c) = x;
+  VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));
+
+  m1.rowwise().reverse()(r, c) = x;
+  VERIFY_IS_APPROX(x, m1(r, cols - 1 - c));
+  */
+}
+
+void test_array_reverse()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( reverse(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( reverse(Matrix2f()) );
+    CALL_SUBTEST_3( reverse(Matrix4f()) );
+    CALL_SUBTEST_4( reverse(Matrix4d()) );
+    CALL_SUBTEST_5( reverse(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_6( reverse(MatrixXi(6, 3)) );
+    CALL_SUBTEST_7( reverse(MatrixXcd(20, 20)) );
+    CALL_SUBTEST_8( reverse(Matrix<float, 100, 100>()) );
+    CALL_SUBTEST_9( reverse(Matrix<float,Dynamic,Dynamic,RowMajor>(6,3)) );
+  }
+#ifdef EIGEN_TEST_PART_3
+  Vector4f x; x << 1, 2, 3, 4;
+  Vector4f y; y << 4, 3, 2, 1;
+  VERIFY(x.reverse()[1] == 3);
+  VERIFY(x.reverse() == y);
+#endif
+}
diff --git a/test/bandmatrix.cpp b/test/bandmatrix.cpp
new file mode 100644
index 0000000..5e4e8e0
--- /dev/null
+++ b/test/bandmatrix.cpp
@@ -0,0 +1,74 @@
+// This file is triangularView of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void bandmatrix(const MatrixType& _m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrixType;
+
+  Index rows = _m.rows();
+  Index cols = _m.cols();
+  Index supers = _m.supers();
+  Index subs = _m.subs();
+
+  MatrixType m(rows,cols,supers,subs);
+
+  DenseMatrixType dm1(rows,cols);
+  dm1.setZero();
+
+  m.diagonal().setConstant(123);
+  dm1.diagonal().setConstant(123);
+  for (int i=1; i<=m.supers();++i)
+  {
+    m.diagonal(i).setConstant(static_cast<RealScalar>(i));
+    dm1.diagonal(i).setConstant(static_cast<RealScalar>(i));
+  }
+  for (int i=1; i<=m.subs();++i)
+  {
+    m.diagonal(-i).setConstant(-static_cast<RealScalar>(i));
+    dm1.diagonal(-i).setConstant(-static_cast<RealScalar>(i));
+  }
+  //std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n\n\n";
+  VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
+
+  for (int i=0; i<cols; ++i)
+  {
+    m.col(i).setConstant(static_cast<RealScalar>(i+1));
+    dm1.col(i).setConstant(static_cast<RealScalar>(i+1));
+  }
+  Index d = (std::min)(rows,cols);
+  Index a = std::max<Index>(0,cols-d-supers);
+  Index b = std::max<Index>(0,rows-d-subs);
+  if(a>0) dm1.block(0,d+supers,rows,a).setZero();
+  dm1.block(0,supers+1,cols-supers-1-a,cols-supers-1-a).template triangularView<Upper>().setZero();
+  dm1.block(subs+1,0,rows-subs-1-b,rows-subs-1-b).template triangularView<Lower>().setZero();
+  if(b>0) dm1.block(d+subs,0,b,cols).setZero();
+  //std::cerr << m.m_data << "\n\n" << m.toDense() << "\n\n" << dm1 << "\n\n";
+  VERIFY_IS_APPROX(dm1,m.toDenseMatrix());
+
+}
+
+using Eigen::internal::BandMatrix;
+
+void test_bandmatrix()
+{
+  typedef BandMatrix<float>::Index Index;
+
+  for(int i = 0; i < 10*g_repeat ; i++) {
+    Index rows = internal::random<Index>(1,10);
+    Index cols = internal::random<Index>(1,10);
+    Index sups = internal::random<Index>(0,cols-1);
+    Index subs = internal::random<Index>(0,rows-1);
+    CALL_SUBTEST(bandmatrix(BandMatrix<float>(rows,cols,sups,subs)) );
+  }
+}
diff --git a/test/basicstuff.cpp b/test/basicstuff.cpp
new file mode 100644
index 0000000..8c0621e
--- /dev/null
+++ b/test/basicstuff.cpp
@@ -0,0 +1,214 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+
+#include "main.h"
+
+template<typename MatrixType> void basicStuff(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             mzero = MatrixType::Zero(rows, cols),
+             square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
+  VectorType v1 = VectorType::Random(rows),
+             vzero = VectorType::Zero(rows);
+  SquareMatrixType sm1 = SquareMatrixType::Random(rows,rows), sm2(rows,rows);
+
+  Scalar x = 0;
+  while(x == Scalar(0)) x = internal::random<Scalar>();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  m1.coeffRef(r,c) = x;
+  VERIFY_IS_APPROX(x, m1.coeff(r,c));
+  m1(r,c) = x;
+  VERIFY_IS_APPROX(x, m1(r,c));
+  v1.coeffRef(r) = x;
+  VERIFY_IS_APPROX(x, v1.coeff(r));
+  v1(r) = x;
+  VERIFY_IS_APPROX(x, v1(r));
+  v1[r] = x;
+  VERIFY_IS_APPROX(x, v1[r]);
+
+  VERIFY_IS_APPROX(               v1,    v1);
+  VERIFY_IS_NOT_APPROX(           v1,    2*v1);
+  VERIFY_IS_MUCH_SMALLER_THAN(    vzero, v1);
+  VERIFY_IS_MUCH_SMALLER_THAN(  vzero, v1.squaredNorm());
+  VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1,    v1);
+  VERIFY_IS_APPROX(               vzero, v1-v1);
+  VERIFY_IS_APPROX(               m1,    m1);
+  VERIFY_IS_NOT_APPROX(           m1,    2*m1);
+  VERIFY_IS_MUCH_SMALLER_THAN(    mzero, m1);
+  VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1,    m1);
+  VERIFY_IS_APPROX(               mzero, m1-m1);
+
+  // always test operator() on each read-only expression class,
+  // in order to check const-qualifiers.
+  // indeed, if an expression class (here Zero) is meant to be read-only,
+  // hence has no _write() method, the corresponding MatrixBase method (here zero())
+  // should return a const-qualified object so that it is the const-qualified
+  // operator() that gets called, which in turn calls _read().
+  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1));
+
+  // now test copying a row-vector into a (column-)vector and conversely.
+  square.col(r) = square.row(r).eval();
+  Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
+  Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
+  rv = square.row(r);
+  cv = square.col(r);
+  
+  VERIFY_IS_APPROX(rv, cv.transpose());
+
+  if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic)
+  {
+    VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1)));
+  }
+
+  if(cols!=1 && rows!=1)
+  {
+    VERIFY_RAISES_ASSERT(m1[0]);
+    VERIFY_RAISES_ASSERT((m1+m1)[0]);
+  }
+
+  VERIFY_IS_APPROX(m3 = m1,m1);
+  MatrixType m4;
+  VERIFY_IS_APPROX(m4 = m1,m1);
+
+  m3.real() = m1.real();
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
+
+  // check == / != operators
+  VERIFY(m1==m1);
+  VERIFY(m1!=m2);
+  VERIFY(!(m1==m2));
+  VERIFY(!(m1!=m1));
+  m1 = m2;
+  VERIFY(m1==m2);
+  VERIFY(!(m1!=m2));
+  
+  // check automatic transposition
+  sm2.setZero();
+  for(typename MatrixType::Index i=0;i<rows;++i)
+    sm2.col(i) = sm1.row(i);
+  VERIFY_IS_APPROX(sm2,sm1.transpose());
+  
+  sm2.setZero();
+  for(typename MatrixType::Index i=0;i<rows;++i)
+    sm2.col(i).noalias() = sm1.row(i);
+  VERIFY_IS_APPROX(sm2,sm1.transpose());
+  
+  sm2.setZero();
+  for(typename MatrixType::Index i=0;i<rows;++i)
+    sm2.col(i).noalias() += sm1.row(i);
+  VERIFY_IS_APPROX(sm2,sm1.transpose());
+  
+  sm2.setZero();
+  for(typename MatrixType::Index i=0;i<rows;++i)
+    sm2.col(i).noalias() -= sm1.row(i);
+  VERIFY_IS_APPROX(sm2,-sm1.transpose());
+}
+
+template<typename MatrixType> void basicStuffComplex(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> RealMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>();
+
+  VERIFY(numext::real(s1)==numext::real_ref(s1));
+  VERIFY(numext::imag(s1)==numext::imag_ref(s1));
+  numext::real_ref(s1) = numext::real(s2);
+  numext::imag_ref(s1) = numext::imag(s2);
+  VERIFY(internal::isApprox(s1, s2, NumTraits<RealScalar>::epsilon()));
+  // extended precision in Intel FPUs means that s1 == s2 in the line above is not guaranteed.
+
+  RealMatrixType rm1 = RealMatrixType::Random(rows,cols),
+                 rm2 = RealMatrixType::Random(rows,cols);
+  MatrixType cm(rows,cols);
+  cm.real() = rm1;
+  cm.imag() = rm2;
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
+  rm1.setZero();
+  rm2.setZero();
+  rm1 = cm.real();
+  rm2 = cm.imag();
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).real(), rm1);
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(cm).imag(), rm2);
+  cm.real().setZero();
+  VERIFY(static_cast<const MatrixType&>(cm).real().isZero());
+  VERIFY(!static_cast<const MatrixType&>(cm).imag().isZero());
+}
+
+#ifdef EIGEN_TEST_PART_2
+void casting()
+{
+  Matrix4f m = Matrix4f::Random(), m2;
+  Matrix4d n = m.cast<double>();
+  VERIFY(m.isApprox(n.cast<float>()));
+  m2 = m.cast<float>(); // check the specialization when NewType == Type
+  VERIFY(m.isApprox(m2));
+}
+#endif
+
+template <typename Scalar>
+void fixedSizeMatrixConstruction()
+{
+  const Scalar raw[3] = {1,2,3};
+  Matrix<Scalar,3,1> m(raw);
+  Array<Scalar,3,1> a(raw);
+  VERIFY(m(0) == 1);
+  VERIFY(m(1) == 2);
+  VERIFY(m(2) == 3);
+  VERIFY(a(0) == 1);
+  VERIFY(a(1) == 2);
+  VERIFY(a(2) == 3);  
+}
+
+void test_basicstuff()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( basicStuff(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( basicStuff(Matrix4d()) );
+    CALL_SUBTEST_3( basicStuff(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_4( basicStuff(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( basicStuff(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
+    CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+
+    CALL_SUBTEST_3( basicStuffComplex(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( basicStuffComplex(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+
+  CALL_SUBTEST_1(fixedSizeMatrixConstruction<unsigned char>());
+  CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
+  CALL_SUBTEST_1(fixedSizeMatrixConstruction<double>());
+
+  CALL_SUBTEST_2(casting());
+}
diff --git a/test/bicgstab.cpp b/test/bicgstab.cpp
new file mode 100644
index 0000000..f327e2f
--- /dev/null
+++ b/test/bicgstab.cpp
@@ -0,0 +1,30 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+#include <Eigen/IterativeLinearSolvers>
+
+template<typename T> void test_bicgstab_T()
+{
+  BiCGSTAB<SparseMatrix<T>, DiagonalPreconditioner<T> > bicgstab_colmajor_diag;
+  BiCGSTAB<SparseMatrix<T>, IdentityPreconditioner    > bicgstab_colmajor_I;
+  BiCGSTAB<SparseMatrix<T>, IncompleteLUT<T> >           bicgstab_colmajor_ilut;
+  //BiCGSTAB<SparseMatrix<T>, SSORPreconditioner<T> >     bicgstab_colmajor_ssor;
+
+  CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_diag)  );
+//   CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_I)     );
+  CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_ilut)     );
+  //CALL_SUBTEST( check_sparse_square_solving(bicgstab_colmajor_ssor)     );
+}
+
+void test_bicgstab()
+{
+  CALL_SUBTEST_1(test_bicgstab_T<double>());
+  CALL_SUBTEST_2(test_bicgstab_T<std::complex<double> >());
+}
diff --git a/test/block.cpp b/test/block.cpp
new file mode 100644
index 0000000..9ed5d7b
--- /dev/null
+++ b/test/block.cpp
@@ -0,0 +1,251 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths
+#include "main.h"
+
+template<typename MatrixType, typename Index, typename Scalar>
+typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
+block_real_only(const MatrixType &m1, Index r1, Index r2, Index c1, Index c2, const Scalar& s1) {
+  // check cwise-Functions:
+  VERIFY_IS_APPROX(m1.row(r1).cwiseMax(s1), m1.cwiseMax(s1).row(r1));
+  VERIFY_IS_APPROX(m1.col(c1).cwiseMin(s1), m1.cwiseMin(s1).col(c1));
+
+  VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMin(s1), m1.cwiseMin(s1).block(r1,c1,r2-r1+1,c2-c1+1));
+  VERIFY_IS_APPROX(m1.block(r1,c1,r2-r1+1,c2-c1+1).cwiseMax(s1), m1.cwiseMax(s1).block(r1,c1,r2-r1+1,c2-c1+1));
+  
+  return Scalar(0);
+}
+
+template<typename MatrixType, typename Index, typename Scalar>
+typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsComplex,typename MatrixType::Scalar>::type
+block_real_only(const MatrixType &, Index, Index, Index, Index, const Scalar&) {
+  return Scalar(0);
+}
+
+
+template<typename MatrixType> void block(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+  typedef Matrix<Scalar, Dynamic, Dynamic> DynamicMatrixType;
+  typedef Matrix<Scalar, Dynamic, 1> DynamicVectorType;
+  
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m1_copy = m1,
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             ones = MatrixType::Ones(rows, cols);
+  VectorType v1 = VectorType::Random(rows);
+
+  Scalar s1 = internal::random<Scalar>();
+
+  Index r1 = internal::random<Index>(0,rows-1);
+  Index r2 = internal::random<Index>(r1,rows-1);
+  Index c1 = internal::random<Index>(0,cols-1);
+  Index c2 = internal::random<Index>(c1,cols-1);
+
+  block_real_only(m1, r1, r2, c1, c1, s1);
+
+  //check row() and col()
+  VERIFY_IS_EQUAL(m1.col(c1).transpose(), m1.transpose().row(c1));
+  //check operator(), both constant and non-constant, on row() and col()
+  m1 = m1_copy;
+  m1.row(r1) += s1 * m1_copy.row(r2);
+  VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + s1 * m1_copy.row(r2));
+  // check nested block xpr on lhs
+  m1.row(r1).row(0) += s1 * m1_copy.row(r2);
+  VERIFY_IS_APPROX(m1.row(r1), m1_copy.row(r1) + Scalar(2) * s1 * m1_copy.row(r2));
+  m1 = m1_copy;
+  m1.col(c1) += s1 * m1_copy.col(c2);
+  VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + s1 * m1_copy.col(c2));
+  m1.col(c1).col(0) += s1 * m1_copy.col(c2);
+  VERIFY_IS_APPROX(m1.col(c1), m1_copy.col(c1) + Scalar(2) * s1 * m1_copy.col(c2));
+  
+  
+  //check block()
+  Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);
+
+  RowVectorType br1(m1.block(r1,0,1,cols));
+  VectorType bc1(m1.block(0,c1,rows,1));
+  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);
+
+  enum {
+    BlockRows = 2,
+    BlockCols = 5
+  };
+  if (rows>=5 && cols>=8)
+  {
+    // test fixed block() as lvalue
+    m1.template block<BlockRows,BlockCols>(1,1) *= s1;
+    // test operator() on fixed block() both as constant and non-constant
+    m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2);
+    // check that fixed block() and block() agree
+    Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
+    VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols));
+
+    // same tests with mixed fixed/dynamic size
+    m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols) *= s1;
+    m1.template block<BlockRows,Dynamic>(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2);
+    Matrix<Scalar,Dynamic,Dynamic> b2 = m1.template block<Dynamic,BlockCols>(3,3,2,5);
+    VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols));
+  }
+
+  if (rows>2)
+  {
+    // test sub vectors
+    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));
+    Index i = rows-2;
+    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 = internal::random<Index>(0,rows-2);
+    VERIFY_IS_EQUAL(v1.segment(i,2), v1.template segment<2>(i));
+  }
+
+  // stress some basic stuffs with block matrices
+  VERIFY(numext::real(ones.col(c1).sum()) == RealScalar(rows));
+  VERIFY(numext::real(ones.row(r1).sum()) == RealScalar(cols));
+
+  VERIFY(numext::real(ones.col(c1).dot(ones.col(c2))) == RealScalar(rows));
+  VERIFY(numext::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)).transpose() );
+  VERIFY_IS_EQUAL( (m1.transpose().block(c1,r1,c2-c1+1,r2-r1+1).col(0)) , (m1.row(r1).segment(c1,c2-c1+1)).transpose() );
+
+  // 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)).transpose() );
+  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)).transpose() );
+
+  // 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);
+}
+
+
+template<typename MatrixType>
+void compare_using_data_and_stride(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+  Index size = m.size();
+  Index innerStride = m.innerStride();
+  Index outerStride = m.outerStride();
+  Index rowStride = m.rowStride();
+  Index colStride = m.colStride();
+  const typename MatrixType::Scalar* data = m.data();
+
+  for(int j=0;j<cols;++j)
+    for(int i=0;i<rows;++i)
+      VERIFY(m.coeff(i,j) == data[i*rowStride + j*colStride]);
+
+  if(!MatrixType::IsVectorAtCompileTime)
+  {
+    for(int j=0;j<cols;++j)
+      for(int i=0;i<rows;++i)
+        VERIFY(m.coeff(i,j) == data[(MatrixType::Flags&RowMajorBit)
+                                     ? i*outerStride + j*innerStride
+                                     : j*outerStride + i*innerStride]);
+  }
+
+  if(MatrixType::IsVectorAtCompileTime)
+  {
+    VERIFY(innerStride == int((&m.coeff(1))-(&m.coeff(0))));
+    for (int i=0;i<size;++i)
+      VERIFY(m.coeff(i) == data[i*innerStride]);
+  }
+}
+
+template<typename MatrixType>
+void data_and_stride(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Index r1 = internal::random<Index>(0,rows-1);
+  Index r2 = internal::random<Index>(r1,rows-1);
+  Index c1 = internal::random<Index>(0,cols-1);
+  Index c2 = internal::random<Index>(c1,cols-1);
+
+  MatrixType m1 = MatrixType::Random(rows, cols);
+  compare_using_data_and_stride(m1.block(r1, c1, r2-r1+1, c2-c1+1));
+  compare_using_data_and_stride(m1.transpose().block(c1, r1, c2-c1+1, r2-r1+1));
+  compare_using_data_and_stride(m1.row(r1));
+  compare_using_data_and_stride(m1.col(c1));
+  compare_using_data_and_stride(m1.row(r1).transpose());
+  compare_using_data_and_stride(m1.col(c1).transpose());
+}
+
+void test_block()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( block(Matrix<float, 1, 1>()) );
+    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( block(Matrix<float,Dynamic,4>(3, 4)) );
+
+#ifndef EIGEN_DEFAULT_TO_ROW_MAJOR
+    CALL_SUBTEST_6( data_and_stride(MatrixXf(internal::random(5,50), internal::random(5,50))) );
+    CALL_SUBTEST_7( data_and_stride(Matrix<int,Dynamic,Dynamic,RowMajor>(internal::random(5,50), internal::random(5,50))) );
+#endif
+  }
+}
diff --git a/test/cholesky.cpp b/test/cholesky.cpp
new file mode 100644
index 0000000..56885de
--- /dev/null
+++ b/test/cholesky.cpp
@@ -0,0 +1,404 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_NO_ASSERTION_CHECKING
+#define EIGEN_NO_ASSERTION_CHECKING
+#endif
+
+static int nb_temporaries;
+
+#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { if(size!=0) nb_temporaries++; }
+
+#include "main.h"
+#include <Eigen/Cholesky>
+#include <Eigen/QR>
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+    nb_temporaries = 0; \
+    XPR; \
+    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+    VERIFY( (#XPR) && nb_temporaries==N ); \
+  }
+
+template<typename MatrixType,template <typename,int> class CholType> void test_chol_update(const MatrixType& symm)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  MatrixType symmLo = symm.template triangularView<Lower>();
+  MatrixType symmUp = symm.template triangularView<Upper>();
+  MatrixType symmCpy = symm;
+
+  CholType<MatrixType,Lower> chollo(symmLo);
+  CholType<MatrixType,Upper> cholup(symmUp);
+
+  for (int k=0; k<10; ++k)
+  {
+    VectorType vec = VectorType::Random(symm.rows());
+    RealScalar sigma = internal::random<RealScalar>();
+    symmCpy += sigma * vec * vec.adjoint();
+
+    // we are doing some downdates, so it might be the case that the matrix is not SPD anymore
+    CholType<MatrixType,Lower> chol(symmCpy);
+    if(chol.info()!=Success)
+      break;
+
+    chollo.rankUpdate(vec, sigma);
+    VERIFY_IS_APPROX(symmCpy, chollo.reconstructedMatrix());
+
+    cholup.rankUpdate(vec, sigma);
+    VERIFY_IS_APPROX(symmCpy, cholup.reconstructedMatrix());
+  }
+}
+
+template<typename MatrixType> void cholesky(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     LLT.h LDLT.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  MatrixType a0 = MatrixType::Random(rows,cols);
+  VectorType vecB = VectorType::Random(rows), vecX(rows);
+  MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
+  SquareMatrixType symm =  a0 * a0.adjoint();
+  // let's make sure the matrix is not singular or near singular
+  for (int k=0; k<3; ++k)
+  {
+    MatrixType a1 = MatrixType::Random(rows,cols);
+    symm += a1 * a1.adjoint();
+  }
+
+  // to test if really Cholesky only uses the upper triangular part, uncomment the following
+  // FIXME: currently that fails !!
+  //symm.template part<StrictlyLower>().setZero();
+
+  {
+    SquareMatrixType symmUp = symm.template triangularView<Upper>();
+    SquareMatrixType symmLo = symm.template triangularView<Lower>();
+    
+    LLT<SquareMatrixType,Lower> chollo(symmLo);
+    VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
+    vecX = chollo.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    matX = chollo.solve(matB);
+    VERIFY_IS_APPROX(symm * matX, matB);
+
+    // test the upper mode
+    LLT<SquareMatrixType,Upper> cholup(symmUp);
+    VERIFY_IS_APPROX(symm, cholup.reconstructedMatrix());
+    vecX = cholup.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    matX = cholup.solve(matB);
+    VERIFY_IS_APPROX(symm * matX, matB);
+
+    MatrixType neg = -symmLo;
+    chollo.compute(neg);
+    VERIFY(chollo.info()==NumericalIssue);
+
+    VERIFY_IS_APPROX(MatrixType(chollo.matrixL().transpose().conjugate()), MatrixType(chollo.matrixU()));
+    VERIFY_IS_APPROX(MatrixType(chollo.matrixU().transpose().conjugate()), MatrixType(chollo.matrixL()));
+    VERIFY_IS_APPROX(MatrixType(cholup.matrixL().transpose().conjugate()), MatrixType(cholup.matrixU()));
+    VERIFY_IS_APPROX(MatrixType(cholup.matrixU().transpose().conjugate()), MatrixType(cholup.matrixL()));
+    
+    // test some special use cases of SelfCwiseBinaryOp:
+    MatrixType m1 = MatrixType::Random(rows,cols), m2(rows,cols);
+    m2 = m1;
+    m2 += symmLo.template selfadjointView<Lower>().llt().solve(matB);
+    VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
+    m2 = m1;
+    m2 -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
+    VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
+    m2 = m1;
+    m2.noalias() += symmLo.template selfadjointView<Lower>().llt().solve(matB);
+    VERIFY_IS_APPROX(m2, m1 + symmLo.template selfadjointView<Lower>().llt().solve(matB));
+    m2 = m1;
+    m2.noalias() -= symmLo.template selfadjointView<Lower>().llt().solve(matB);
+    VERIFY_IS_APPROX(m2, m1 - symmLo.template selfadjointView<Lower>().llt().solve(matB));
+  }
+
+  // LDLT
+  {
+    int sign = internal::random<int>()%2 ? 1 : -1;
+
+    if(sign == -1)
+    {
+      symm = -symm; // test a negative matrix
+    }
+
+    SquareMatrixType symmUp = symm.template triangularView<Upper>();
+    SquareMatrixType symmLo = symm.template triangularView<Lower>();
+
+    LDLT<SquareMatrixType,Lower> ldltlo(symmLo);
+    VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
+    vecX = ldltlo.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    matX = ldltlo.solve(matB);
+    VERIFY_IS_APPROX(symm * matX, matB);
+
+    LDLT<SquareMatrixType,Upper> ldltup(symmUp);
+    VERIFY_IS_APPROX(symm, ldltup.reconstructedMatrix());
+    vecX = ldltup.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    matX = ldltup.solve(matB);
+    VERIFY_IS_APPROX(symm * matX, matB);
+
+    VERIFY_IS_APPROX(MatrixType(ldltlo.matrixL().transpose().conjugate()), MatrixType(ldltlo.matrixU()));
+    VERIFY_IS_APPROX(MatrixType(ldltlo.matrixU().transpose().conjugate()), MatrixType(ldltlo.matrixL()));
+    VERIFY_IS_APPROX(MatrixType(ldltup.matrixL().transpose().conjugate()), MatrixType(ldltup.matrixU()));
+    VERIFY_IS_APPROX(MatrixType(ldltup.matrixU().transpose().conjugate()), MatrixType(ldltup.matrixL()));
+
+    if(MatrixType::RowsAtCompileTime==Dynamic)
+    {
+      // note : each inplace permutation requires a small temporary vector (mask)
+
+      // check inplace solve
+      matX = matB;
+      VERIFY_EVALUATION_COUNT(matX = ldltlo.solve(matX), 0);
+      VERIFY_IS_APPROX(matX, ldltlo.solve(matB).eval());
+
+
+      matX = matB;
+      VERIFY_EVALUATION_COUNT(matX = ldltup.solve(matX), 0);
+      VERIFY_IS_APPROX(matX, ldltup.solve(matB).eval());
+    }
+
+    // restore
+    if(sign == -1)
+      symm = -symm;
+
+    // check matrices coming from linear constraints with Lagrange multipliers
+    if(rows>=3)
+    {
+      SquareMatrixType A = symm;
+      int c = internal::random<int>(0,rows-2);
+      A.bottomRightCorner(c,c).setZero();
+      // Make sure a solution exists:
+      vecX.setRandom();
+      vecB = A * vecX;
+      vecX.setZero();
+      ldltlo.compute(A);
+      VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+      vecX = ldltlo.solve(vecB);
+      VERIFY_IS_APPROX(A * vecX, vecB);
+    }
+    
+    // check non-full rank matrices
+    if(rows>=3)
+    {
+      int r = internal::random<int>(1,rows-1);
+      Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,r);
+      SquareMatrixType A = a * a.adjoint();
+      // Make sure a solution exists:
+      vecX.setRandom();
+      vecB = A * vecX;
+      vecX.setZero();
+      ldltlo.compute(A);
+      VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+      vecX = ldltlo.solve(vecB);
+      VERIFY_IS_APPROX(A * vecX, vecB);
+    }
+    
+    // check matrices with a wide spectrum
+    if(rows>=3)
+    {
+      RealScalar s = (std::min)(16,std::numeric_limits<RealScalar>::max_exponent10/8);
+      Matrix<Scalar,Dynamic,Dynamic> a = Matrix<Scalar,Dynamic,Dynamic>::Random(rows,rows);
+      Matrix<RealScalar,Dynamic,1> d =  Matrix<RealScalar,Dynamic,1>::Random(rows);
+      for(int k=0; k<rows; ++k)
+        d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+      SquareMatrixType A = a * d.asDiagonal() * a.adjoint();
+      // Make sure a solution exists:
+      vecX.setRandom();
+      vecB = A * vecX;
+      vecX.setZero();
+      ldltlo.compute(A);
+      VERIFY_IS_APPROX(A, ldltlo.reconstructedMatrix());
+      vecX = ldltlo.solve(vecB);
+      VERIFY_IS_APPROX(A * vecX, vecB);
+    }
+  }
+
+  // update/downdate
+  CALL_SUBTEST(( test_chol_update<SquareMatrixType,LLT>(symm)  ));
+  CALL_SUBTEST(( test_chol_update<SquareMatrixType,LDLT>(symm) ));
+}
+
+template<typename MatrixType> void cholesky_cplx(const MatrixType& m)
+{
+  // classic test
+  cholesky(m);
+
+  // test mixing real/scalar types
+
+  typedef typename MatrixType::Index Index;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RealMatrixType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  RealMatrixType a0 = RealMatrixType::Random(rows,cols);
+  VectorType vecB = VectorType::Random(rows), vecX(rows);
+  MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
+  RealMatrixType symm =  a0 * a0.adjoint();
+  // let's make sure the matrix is not singular or near singular
+  for (int k=0; k<3; ++k)
+  {
+    RealMatrixType a1 = RealMatrixType::Random(rows,cols);
+    symm += a1 * a1.adjoint();
+  }
+
+  {
+    RealMatrixType symmLo = symm.template triangularView<Lower>();
+
+    LLT<RealMatrixType,Lower> chollo(symmLo);
+    VERIFY_IS_APPROX(symm, chollo.reconstructedMatrix());
+    vecX = chollo.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+//     matX = chollo.solve(matB);
+//     VERIFY_IS_APPROX(symm * matX, matB);
+  }
+
+  // LDLT
+  {
+    int sign = internal::random<int>()%2 ? 1 : -1;
+
+    if(sign == -1)
+    {
+      symm = -symm; // test a negative matrix
+    }
+
+    RealMatrixType symmLo = symm.template triangularView<Lower>();
+
+    LDLT<RealMatrixType,Lower> ldltlo(symmLo);
+    VERIFY_IS_APPROX(symm, ldltlo.reconstructedMatrix());
+    vecX = ldltlo.solve(vecB);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+//     matX = ldltlo.solve(matB);
+//     VERIFY_IS_APPROX(symm * matX, matB);
+  }
+}
+
+// regression test for bug 241
+template<typename MatrixType> void cholesky_bug241(const MatrixType& m)
+{
+  eigen_assert(m.rows() == 2 && m.cols() == 2);
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  MatrixType matA;
+  matA << 1, 1, 1, 1;
+  VectorType vecB;
+  vecB << 1, 1;
+  VectorType vecX = matA.ldlt().solve(vecB);
+  VERIFY_IS_APPROX(matA * vecX, vecB);
+}
+
+// LDLT is not guaranteed to work for indefinite matrices, but happens to work fine if matrix is diagonal.
+// This test checks that LDLT reports correctly that matrix is indefinite. 
+// See http://forum.kde.org/viewtopic.php?f=74&t=106942 and bug 736
+template<typename MatrixType> void cholesky_definiteness(const MatrixType& m)
+{
+  eigen_assert(m.rows() == 2 && m.cols() == 2);
+  MatrixType mat;
+  LDLT<MatrixType> ldlt(2);
+  
+  {
+    mat << 1, 0, 0, -1;
+    ldlt.compute(mat);
+    VERIFY(!ldlt.isNegative());
+    VERIFY(!ldlt.isPositive());
+  }
+  {
+    mat << 1, 2, 2, 1;
+    ldlt.compute(mat);
+    VERIFY(!ldlt.isNegative());
+    VERIFY(!ldlt.isPositive());
+  }
+  {
+    mat << 0, 0, 0, 0;
+    ldlt.compute(mat);
+    VERIFY(ldlt.isNegative());
+    VERIFY(ldlt.isPositive());
+  }
+  {
+    mat << 0, 0, 0, 1;
+    ldlt.compute(mat);
+    VERIFY(!ldlt.isNegative());
+    VERIFY(ldlt.isPositive());
+  }
+  {
+    mat << -1, 0, 0, 0;
+    ldlt.compute(mat);
+    VERIFY(ldlt.isNegative());
+    VERIFY(!ldlt.isPositive());
+  }
+}
+
+template<typename MatrixType> void cholesky_verify_assert()
+{
+  MatrixType tmp;
+
+  LLT<MatrixType> llt;
+  VERIFY_RAISES_ASSERT(llt.matrixL())
+  VERIFY_RAISES_ASSERT(llt.matrixU())
+  VERIFY_RAISES_ASSERT(llt.solve(tmp))
+  VERIFY_RAISES_ASSERT(llt.solveInPlace(&tmp))
+
+  LDLT<MatrixType> ldlt;
+  VERIFY_RAISES_ASSERT(ldlt.matrixL())
+  VERIFY_RAISES_ASSERT(ldlt.permutationP())
+  VERIFY_RAISES_ASSERT(ldlt.vectorD())
+  VERIFY_RAISES_ASSERT(ldlt.isPositive())
+  VERIFY_RAISES_ASSERT(ldlt.isNegative())
+  VERIFY_RAISES_ASSERT(ldlt.solve(tmp))
+  VERIFY_RAISES_ASSERT(ldlt.solveInPlace(&tmp))
+}
+
+void test_cholesky()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
+    CALL_SUBTEST_3( cholesky(Matrix2d()) );
+    CALL_SUBTEST_3( cholesky_bug241(Matrix2d()) );
+    CALL_SUBTEST_3( cholesky_definiteness(Matrix2d()) );
+    CALL_SUBTEST_4( cholesky(Matrix3f()) );
+    CALL_SUBTEST_5( cholesky(Matrix4d()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_2( cholesky(MatrixXd(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_6( cholesky_cplx(MatrixXcd(s,s)) );
+  }
+
+  CALL_SUBTEST_4( cholesky_verify_assert<Matrix3f>() );
+  CALL_SUBTEST_7( cholesky_verify_assert<Matrix3d>() );
+  CALL_SUBTEST_8( cholesky_verify_assert<MatrixXf>() );
+  CALL_SUBTEST_2( cholesky_verify_assert<MatrixXd>() );
+
+  // Test problem size constructors
+  CALL_SUBTEST_9( LLT<MatrixXf>(10) );
+  CALL_SUBTEST_9( LDLT<MatrixXf>(10) );
+  
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+  TEST_SET_BUT_UNUSED_VARIABLE(nb_temporaries)
+}
diff --git a/test/cholmod_support.cpp b/test/cholmod_support.cpp
new file mode 100644
index 0000000..8f8be3c
--- /dev/null
+++ b/test/cholmod_support.cpp
@@ -0,0 +1,56 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+
+#include <Eigen/CholmodSupport>
+
+template<typename T> void test_cholmod_T()
+{
+  CholmodDecomposition<SparseMatrix<T>, Lower> g_chol_colmajor_lower; g_chol_colmajor_lower.setMode(CholmodSupernodalLLt);
+  CholmodDecomposition<SparseMatrix<T>, Upper> g_chol_colmajor_upper; g_chol_colmajor_upper.setMode(CholmodSupernodalLLt);
+  CholmodDecomposition<SparseMatrix<T>, Lower> g_llt_colmajor_lower;  g_llt_colmajor_lower.setMode(CholmodSimplicialLLt);
+  CholmodDecomposition<SparseMatrix<T>, Upper> g_llt_colmajor_upper;  g_llt_colmajor_upper.setMode(CholmodSimplicialLLt);
+  CholmodDecomposition<SparseMatrix<T>, Lower> g_ldlt_colmajor_lower; g_ldlt_colmajor_lower.setMode(CholmodLDLt);
+  CholmodDecomposition<SparseMatrix<T>, Upper> g_ldlt_colmajor_upper; g_ldlt_colmajor_upper.setMode(CholmodLDLt);
+  
+  CholmodSupernodalLLT<SparseMatrix<T>, Lower> chol_colmajor_lower;
+  CholmodSupernodalLLT<SparseMatrix<T>, Upper> chol_colmajor_upper;
+  CholmodSimplicialLLT<SparseMatrix<T>, Lower> llt_colmajor_lower;
+  CholmodSimplicialLLT<SparseMatrix<T>, Upper> llt_colmajor_upper;
+  CholmodSimplicialLDLT<SparseMatrix<T>, Lower> ldlt_colmajor_lower;
+  CholmodSimplicialLDLT<SparseMatrix<T>, Upper> ldlt_colmajor_upper;
+
+  check_sparse_spd_solving(g_chol_colmajor_lower);
+  check_sparse_spd_solving(g_chol_colmajor_upper);
+  check_sparse_spd_solving(g_llt_colmajor_lower);
+  check_sparse_spd_solving(g_llt_colmajor_upper);
+  check_sparse_spd_solving(g_ldlt_colmajor_lower);
+  check_sparse_spd_solving(g_ldlt_colmajor_upper);
+  
+  check_sparse_spd_solving(chol_colmajor_lower);
+  check_sparse_spd_solving(chol_colmajor_upper);
+  check_sparse_spd_solving(llt_colmajor_lower);
+  check_sparse_spd_solving(llt_colmajor_upper);
+  check_sparse_spd_solving(ldlt_colmajor_lower);
+  check_sparse_spd_solving(ldlt_colmajor_upper);
+  
+//  check_sparse_spd_determinant(chol_colmajor_lower);
+//  check_sparse_spd_determinant(chol_colmajor_upper);
+//  check_sparse_spd_determinant(llt_colmajor_lower);
+//  check_sparse_spd_determinant(llt_colmajor_upper);
+//  check_sparse_spd_determinant(ldlt_colmajor_lower);
+//  check_sparse_spd_determinant(ldlt_colmajor_upper);
+}
+
+void test_cholmod_support()
+{
+  CALL_SUBTEST_1(test_cholmod_T<double>());
+  CALL_SUBTEST_2(test_cholmod_T<std::complex<double> >());
+}
diff --git a/test/commainitializer.cpp b/test/commainitializer.cpp
new file mode 100644
index 0000000..99102b9
--- /dev/null
+++ b/test/commainitializer.cpp
@@ -0,0 +1,46 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_commainitializer()
+{
+  Matrix3d m3;
+  Matrix4d m4;
+
+  VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
+  
+  #ifndef _MSC_VER
+  VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
+  #endif
+
+  double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+  Matrix3d ref = Map<Matrix<double,3,3,RowMajor> >(data);
+
+  m3 = Matrix3d::Random();
+  m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
+  VERIFY_IS_APPROX(m3, ref );
+
+  Vector3d vec[3];
+  vec[0] << 1, 4, 7;
+  vec[1] << 2, 5, 8;
+  vec[2] << 3, 6, 9;
+  m3 = Matrix3d::Random();
+  m3 << vec[0], vec[1], vec[2];
+  VERIFY_IS_APPROX(m3, ref);
+
+  vec[0] << 1, 2, 3;
+  vec[1] << 4, 5, 6;
+  vec[2] << 7, 8, 9;
+  m3 = Matrix3d::Random();
+  m3 << vec[0].transpose(),
+        4, 5, 6,
+        vec[2].transpose();
+  VERIFY_IS_APPROX(m3, ref);
+}
diff --git a/test/conjugate_gradient.cpp b/test/conjugate_gradient.cpp
new file mode 100644
index 0000000..019cc4d
--- /dev/null
+++ b/test/conjugate_gradient.cpp
@@ -0,0 +1,32 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+#include <Eigen/IterativeLinearSolvers>
+
+template<typename T> void test_conjugate_gradient_T()
+{
+  ConjugateGradient<SparseMatrix<T>, Lower      > cg_colmajor_lower_diag;
+  ConjugateGradient<SparseMatrix<T>, Upper      > cg_colmajor_upper_diag;
+  ConjugateGradient<SparseMatrix<T>, Lower|Upper> cg_colmajor_loup_diag;
+  ConjugateGradient<SparseMatrix<T>, Lower, IdentityPreconditioner> cg_colmajor_lower_I;
+  ConjugateGradient<SparseMatrix<T>, Upper, IdentityPreconditioner> cg_colmajor_upper_I;
+
+  CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_lower_diag)  );
+  CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_upper_diag)  );
+  CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_loup_diag)   );
+  CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_lower_I)     );
+  CALL_SUBTEST( check_sparse_spd_solving(cg_colmajor_upper_I)     );
+}
+
+void test_conjugate_gradient()
+{
+  CALL_SUBTEST_1(test_conjugate_gradient_T<double>());
+  CALL_SUBTEST_2(test_conjugate_gradient_T<std::complex<double> >());
+}
diff --git a/test/conservative_resize.cpp b/test/conservative_resize.cpp
new file mode 100644
index 0000000..498421b
--- /dev/null
+++ b/test/conservative_resize.cpp
@@ -0,0 +1,134 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#include <Eigen/Core>
+
+using namespace Eigen;
+
+template <typename Scalar, int Storage>
+void run_matrix_tests()
+{
+  typedef Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Storage> MatrixType;
+  typedef typename MatrixType::Index Index;
+
+  MatrixType m, n;
+
+  // boundary cases ...
+  m = n = MatrixType::Random(50,50);
+  m.conservativeResize(1,50);
+  VERIFY_IS_APPROX(m, n.block(0,0,1,50));
+
+  m = n = MatrixType::Random(50,50);
+  m.conservativeResize(50,1);
+  VERIFY_IS_APPROX(m, n.block(0,0,50,1));
+
+  m = n = MatrixType::Random(50,50);
+  m.conservativeResize(50,50);
+  VERIFY_IS_APPROX(m, n.block(0,0,50,50));
+
+  // random shrinking ...
+  for (int i=0; i<25; ++i)
+  {
+    const Index rows = internal::random<Index>(1,50);
+    const Index cols = internal::random<Index>(1,50);
+    m = n = MatrixType::Random(50,50);
+    m.conservativeResize(rows,cols);
+    VERIFY_IS_APPROX(m, n.block(0,0,rows,cols));
+  }
+
+  // random growing with zeroing ...
+  for (int i=0; i<25; ++i)
+  {
+    const Index rows = internal::random<Index>(50,75);
+    const Index cols = internal::random<Index>(50,75);
+    m = n = MatrixType::Random(50,50);
+    m.conservativeResizeLike(MatrixType::Zero(rows,cols));
+    VERIFY_IS_APPROX(m.block(0,0,n.rows(),n.cols()), n);
+    VERIFY( rows<=50 || m.block(50,0,rows-50,cols).sum() == Scalar(0) );
+    VERIFY( cols<=50 || m.block(0,50,rows,cols-50).sum() == Scalar(0) );
+  }
+}
+
+template <typename Scalar>
+void run_vector_tests()
+{
+  typedef Matrix<Scalar, 1, Eigen::Dynamic> VectorType;
+
+  VectorType m, n;
+
+  // boundary cases ...
+  m = n = VectorType::Random(50);
+  m.conservativeResize(1);
+  VERIFY_IS_APPROX(m, n.segment(0,1));
+
+  m = n = VectorType::Random(50);
+  m.conservativeResize(50);
+  VERIFY_IS_APPROX(m, n.segment(0,50));
+  
+  m = n = VectorType::Random(50);
+  m.conservativeResize(m.rows(),1);
+  VERIFY_IS_APPROX(m, n.segment(0,1));
+
+  m = n = VectorType::Random(50);
+  m.conservativeResize(m.rows(),50);
+  VERIFY_IS_APPROX(m, n.segment(0,50));
+
+  // random shrinking ...
+  for (int i=0; i<50; ++i)
+  {
+    const int size = internal::random<int>(1,50);
+    m = n = VectorType::Random(50);
+    m.conservativeResize(size);
+    VERIFY_IS_APPROX(m, n.segment(0,size));
+    
+    m = n = VectorType::Random(50);
+    m.conservativeResize(m.rows(), size);
+    VERIFY_IS_APPROX(m, n.segment(0,size));
+  }
+
+  // random growing with zeroing ...
+  for (int i=0; i<50; ++i)
+  {
+    const int size = internal::random<int>(50,100);
+    m = n = VectorType::Random(50);
+    m.conservativeResizeLike(VectorType::Zero(size));
+    VERIFY_IS_APPROX(m.segment(0,50), n);
+    VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
+    
+    m = n = VectorType::Random(50);
+    m.conservativeResizeLike(Matrix<Scalar,Dynamic,Dynamic>::Zero(1,size));
+    VERIFY_IS_APPROX(m.segment(0,50), n);
+    VERIFY( size<=50 || m.segment(50,size-50).sum() == Scalar(0) );
+  }
+}
+
+void test_conservative_resize()
+{
+  for(int i=0; i<g_repeat; ++i)
+  {
+    CALL_SUBTEST_1((run_matrix_tests<int, Eigen::RowMajor>()));
+    CALL_SUBTEST_1((run_matrix_tests<int, Eigen::ColMajor>()));
+    CALL_SUBTEST_2((run_matrix_tests<float, Eigen::RowMajor>()));
+    CALL_SUBTEST_2((run_matrix_tests<float, Eigen::ColMajor>()));
+    CALL_SUBTEST_3((run_matrix_tests<double, Eigen::RowMajor>()));
+    CALL_SUBTEST_3((run_matrix_tests<double, Eigen::ColMajor>()));
+    CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::RowMajor>()));
+    CALL_SUBTEST_4((run_matrix_tests<std::complex<float>, Eigen::ColMajor>()));
+    CALL_SUBTEST_5((run_matrix_tests<std::complex<double>, Eigen::RowMajor>()));
+    CALL_SUBTEST_6((run_matrix_tests<std::complex<double>, Eigen::ColMajor>()));
+
+    CALL_SUBTEST_1((run_vector_tests<int>()));
+    CALL_SUBTEST_2((run_vector_tests<float>()));
+    CALL_SUBTEST_3((run_vector_tests<double>()));
+    CALL_SUBTEST_4((run_vector_tests<std::complex<float> >()));
+    CALL_SUBTEST_5((run_vector_tests<std::complex<double> >()));
+  }
+}
diff --git a/test/corners.cpp b/test/corners.cpp
new file mode 100644
index 0000000..3c64c32
--- /dev/null
+++ b/test/corners.cpp
@@ -0,0 +1,118 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#define COMPARE_CORNER(A,B) \
+  VERIFY_IS_EQUAL(matrix.A, matrix.B); \
+  VERIFY_IS_EQUAL(const_matrix.A, const_matrix.B);
+
+template<typename MatrixType> void corners(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Index r = internal::random<Index>(1,rows);
+  Index c = internal::random<Index>(1,cols);
+
+  MatrixType matrix = MatrixType::Random(rows,cols);
+  const MatrixType const_matrix = MatrixType::Random(rows,cols);
+
+  COMPARE_CORNER(topLeftCorner(r,c), block(0,0,r,c));
+  COMPARE_CORNER(topRightCorner(r,c), block(0,cols-c,r,c));
+  COMPARE_CORNER(bottomLeftCorner(r,c), block(rows-r,0,r,c));
+  COMPARE_CORNER(bottomRightCorner(r,c), block(rows-r,cols-c,r,c));
+
+  Index sr = internal::random<Index>(1,rows) - 1;
+  Index nr = internal::random<Index>(1,rows-sr);
+  Index sc = internal::random<Index>(1,cols) - 1;
+  Index nc = internal::random<Index>(1,cols-sc);
+
+  COMPARE_CORNER(topRows(r), block(0,0,r,cols));
+  COMPARE_CORNER(middleRows(sr,nr), block(sr,0,nr,cols));
+  COMPARE_CORNER(bottomRows(r), block(rows-r,0,r,cols));
+  COMPARE_CORNER(leftCols(c), block(0,0,rows,c));
+  COMPARE_CORNER(middleCols(sc,nc), block(0,sc,rows,nc));
+  COMPARE_CORNER(rightCols(c), block(0,cols-c,rows,c));
+}
+
+template<typename MatrixType, int CRows, int CCols, int SRows, int SCols> void corners_fixedsize()
+{
+  MatrixType matrix = MatrixType::Random();
+  const MatrixType const_matrix = MatrixType::Random();
+
+  enum {
+    rows = MatrixType::RowsAtCompileTime,
+    cols = MatrixType::ColsAtCompileTime,
+    r = CRows,
+    c = CCols,
+	sr = SRows,
+	sc = SCols
+  };
+
+  VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template block<r,c>(0,0)));
+  VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template block<r,c>(0,cols-c)));
+  VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template block<r,c>(rows-r,0)));
+  VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template block<r,c>(rows-r,cols-c)));
+
+  VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<r,Dynamic>(r,c)));
+
+  VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template topLeftCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template topRightCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template bottomRightCorner<Dynamic,c>(r,c)));
+
+  VERIFY_IS_EQUAL((matrix.template topRows<r>()), (matrix.template block<r,cols>(0,0)));
+  VERIFY_IS_EQUAL((matrix.template middleRows<r>(sr)), (matrix.template block<r,cols>(sr,0)));
+  VERIFY_IS_EQUAL((matrix.template bottomRows<r>()), (matrix.template block<r,cols>(rows-r,0)));
+  VERIFY_IS_EQUAL((matrix.template leftCols<c>()), (matrix.template block<rows,c>(0,0)));
+  VERIFY_IS_EQUAL((matrix.template middleCols<c>(sc)), (matrix.template block<rows,c>(0,sc)));
+  VERIFY_IS_EQUAL((matrix.template rightCols<c>()), (matrix.template block<rows,c>(0,cols-c)));
+
+  VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template block<r,c>(0,0)));
+  VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template block<r,c>(0,cols-c)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,0)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,cols-c)));
+
+  VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<r,Dynamic>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<r,Dynamic>(r,c)));
+
+  VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template topLeftCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template topRightCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template bottomLeftCorner<Dynamic,c>(r,c)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template bottomRightCorner<Dynamic,c>(r,c)));
+
+  VERIFY_IS_EQUAL((const_matrix.template topRows<r>()), (const_matrix.template block<r,cols>(0,0)));
+  VERIFY_IS_EQUAL((const_matrix.template middleRows<r>(sr)), (const_matrix.template block<r,cols>(sr,0)));
+  VERIFY_IS_EQUAL((const_matrix.template bottomRows<r>()), (const_matrix.template block<r,cols>(rows-r,0)));
+  VERIFY_IS_EQUAL((const_matrix.template leftCols<c>()), (const_matrix.template block<rows,c>(0,0)));
+  VERIFY_IS_EQUAL((const_matrix.template middleCols<c>(sc)), (const_matrix.template block<rows,c>(0,sc)));
+  VERIFY_IS_EQUAL((const_matrix.template rightCols<c>()), (const_matrix.template block<rows,c>(0,cols-c)));
+}
+
+void test_corners()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( corners(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( corners(Matrix4d()) );
+    CALL_SUBTEST_3( corners(Matrix<int,10,12>()) );
+    CALL_SUBTEST_4( corners(MatrixXcf(5, 7)) );
+    CALL_SUBTEST_5( corners(MatrixXf(21, 20)) );
+
+    CALL_SUBTEST_1(( corners_fixedsize<Matrix<float, 1, 1>, 1, 1, 0, 0>() ));
+    CALL_SUBTEST_2(( corners_fixedsize<Matrix4d,2,2,1,1>() ));
+    CALL_SUBTEST_3(( corners_fixedsize<Matrix<int,10,12>,4,7,5,2>() ));
+  }
+}
diff --git a/test/cwiseop.cpp b/test/cwiseop.cpp
new file mode 100644
index 0000000..e3361da
--- /dev/null
+++ b/test/cwiseop.cpp
@@ -0,0 +1,184 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN2_SUPPORT
+#define EIGEN_NO_EIGEN2_DEPRECATED_WARNING
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "main.h"
+#include <functional>
+
+#ifdef min
+#undef min
+#endif
+
+#ifdef max
+#undef max
+#endif
+
+using namespace std;
+
+template<typename Scalar> struct AddIfNull {
+    const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
+    enum { Cost = NumTraits<Scalar>::AddCost };
+};
+
+template<typename MatrixType>
+typename Eigen::internal::enable_if<!NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
+cwiseops_real_only(MatrixType& m1, MatrixType& m2, MatrixType& m3, MatrixType& mones)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  
+  VERIFY_IS_APPROX(m1.cwise() / m2,    m1.cwise() * (m2.cwise().inverse()));
+  m3 = m1.cwise().abs().cwise().sqrt();
+  VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
+  VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
+  VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
+
+  VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
+  m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
+  VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
+  m3 = m1.cwise().abs();
+  VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
+
+//   VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
+  VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
+  m3 = m1;
+  m3.cwise() /= m2;
+  VERIFY_IS_APPROX(m3, m1.cwise() / m2);
+  
+  return Scalar(0);
+}
+
+template<typename MatrixType>
+typename Eigen::internal::enable_if<NumTraits<typename MatrixType::Scalar>::IsInteger,typename MatrixType::Scalar>::type
+cwiseops_real_only(MatrixType& , MatrixType& , MatrixType& , MatrixType& )
+{
+  return 0;
+}
+
+template<typename MatrixType> void cwiseops(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m1bis = m1,
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             m4(rows, cols),
+             mzero = MatrixType::Zero(rows, cols),
+             mones = MatrixType::Ones(rows, cols),
+             identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
+                              ::Identity(rows, rows);
+  VectorType vzero = VectorType::Zero(rows),
+             vones = VectorType::Ones(rows),
+             v3(rows);
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  Scalar s1 = internal::random<Scalar>();
+
+  // test Zero, Ones, Constant, and the set* variants
+  m3 = MatrixType::Constant(rows, cols, s1);
+  for (int j=0; j<cols; ++j)
+    for (int i=0; i<rows; ++i)
+    {
+      VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
+      VERIFY_IS_APPROX(mones(i,j), Scalar(1));
+      VERIFY_IS_APPROX(m3(i,j), s1);
+    }
+  VERIFY(mzero.isZero());
+  VERIFY(mones.isOnes());
+  VERIFY(m3.isConstant(s1));
+  VERIFY(identity.isIdentity());
+  VERIFY_IS_APPROX(m4.setConstant(s1), m3);
+  VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
+  VERIFY_IS_APPROX(m4.setZero(), mzero);
+  VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
+  VERIFY_IS_APPROX(m4.setOnes(), mones);
+  VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
+  m4.fill(s1);
+  VERIFY_IS_APPROX(m4, m3);
+
+  VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
+  VERIFY_IS_APPROX(v3.setZero(rows), vzero);
+  VERIFY_IS_APPROX(v3.setOnes(rows), vones);
+
+  m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
+
+  VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
+  VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
+  VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
+
+  VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
+  VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
+  m3 = m1; m3.cwise() += 1;
+  VERIFY_IS_APPROX(m1 + mones, m3);
+  m3 = m1; m3.cwise() -= 1;
+  VERIFY_IS_APPROX(m1 - mones, m3);
+
+  VERIFY_IS_APPROX(m2, m2.cwise() * mones);
+  VERIFY_IS_APPROX(m1.cwise() * m2,  m2.cwise() * m1);
+  m3 = m1;
+  m3.cwise() *= m2;
+  VERIFY_IS_APPROX(m3, m1.cwise() * m2);
+
+  VERIFY_IS_APPROX(mones,    m2.cwise()/m2);
+
+  // check min
+  VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
+  VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
+  VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
+
+  // check max
+  VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
+  VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
+  VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
+
+  VERIFY( (m1.cwise() == m1).all() );
+  VERIFY( (m1.cwise() != m2).any() );
+  VERIFY(!(m1.cwise() == (m1+mones)).any() );
+  if (rows*cols>1)
+  {
+    m3 = m1;
+    m3(r,c) += 1;
+    VERIFY( (m1.cwise() == m3).any() );
+    VERIFY( !(m1.cwise() == m3).all() );
+  }
+  VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
+  VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
+  VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
+  VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
+
+  VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
+  VERIFY( !(m1.cwise()<m1bis.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
+  VERIFY( !(m1.cwise()>m1bis.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
+  
+  cwiseops_real_only(m1, m2, m3, mones);
+}
+
+void test_cwiseop()
+{
+  for(int i = 0; i < g_repeat ; i++) {
+    CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( cwiseops(Matrix4d()) );
+    CALL_SUBTEST_3( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_4( cwiseops(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_5( cwiseops(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( cwiseops(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+}
diff --git a/test/denseLM.cpp b/test/denseLM.cpp
new file mode 100644
index 0000000..0aa736e
--- /dev/null
+++ b/test/denseLM.cpp
@@ -0,0 +1,190 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "main.h"
+#include <Eigen/LevenbergMarquardt>
+using namespace std;
+using namespace Eigen;
+
+template<typename Scalar>
+struct DenseLM : DenseFunctor<Scalar>
+{
+  typedef DenseFunctor<Scalar> Base;
+  typedef typename Base::JacobianType JacobianType;
+  typedef Matrix<Scalar,Dynamic,1> VectorType;
+  
+  DenseLM(int n, int m) : DenseFunctor<Scalar>(n,m) 
+  { }
+ 
+  VectorType model(const VectorType& uv, VectorType& x)
+  {
+    VectorType y; // Should change to use expression template
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(uv.size()%2 == 0);
+    eigen_assert(uv.size() == n);
+    eigen_assert(x.size() == m);
+    y.setZero(m);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    for (int j = 0; j < m; j++)
+    {
+      for (int i = 0; i < half; i++)
+        y(j) += u(i)*std::exp(-(x(j)-i)*(x(j)-i)/(v(i)*v(i)));
+    }
+    return y;
+    
+  }
+  void initPoints(VectorType& uv_ref, VectorType& x)
+  {
+    m_x = x;
+    m_y = this->model(uv_ref, x);
+  }
+  
+  int operator()(const VectorType& uv, VectorType& fvec)
+  {
+    
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(uv.size()%2 == 0);
+    eigen_assert(uv.size() == n);
+    eigen_assert(fvec.size() == m);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    for (int j = 0; j < m; j++)
+    {
+      fvec(j) = m_y(j);
+      for (int i = 0; i < half; i++)
+      {
+        fvec(j) -= u(i) *std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+      }
+    }
+    
+    return 0;
+  }
+  int df(const VectorType& uv, JacobianType& fjac)
+  {
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(n == uv.size());
+    eigen_assert(fjac.rows() == m);
+    eigen_assert(fjac.cols() == n);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    for (int j = 0; j < m; j++)
+    {
+      for (int i = 0; i < half; i++)
+      {
+        fjac.coeffRef(j,i) = -std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+        fjac.coeffRef(j,i+half) = -2.*u(i)*(m_x(j)-i)*(m_x(j)-i)/(std::pow(v(i),3)) * std::exp(-(m_x(j)-i)*(m_x(j)-i)/(v(i)*v(i)));
+      }
+    }
+    return 0;
+  }
+  VectorType m_x, m_y; //Data Points
+};
+
+template<typename FunctorType, typename VectorType>
+int test_minimizeLM(FunctorType& functor, VectorType& uv)
+{
+  LevenbergMarquardt<FunctorType> lm(functor);
+  LevenbergMarquardtSpace::Status info; 
+  
+  info = lm.minimize(uv);
+  
+  VERIFY_IS_EQUAL(info, 1);
+  //FIXME Check other parameters
+  return info;
+}
+
+template<typename FunctorType, typename VectorType>
+int test_lmder(FunctorType& functor, VectorType& uv)
+{
+  typedef typename VectorType::Scalar Scalar;
+  LevenbergMarquardtSpace::Status info; 
+  LevenbergMarquardt<FunctorType> lm(functor);
+  info = lm.lmder1(uv);
+  
+  VERIFY_IS_EQUAL(info, 1);
+  //FIXME Check other parameters
+  return info;
+}
+
+template<typename FunctorType, typename VectorType>
+int test_minimizeSteps(FunctorType& functor, VectorType& uv)
+{
+  LevenbergMarquardtSpace::Status info;   
+  LevenbergMarquardt<FunctorType> lm(functor);
+  info = lm.minimizeInit(uv);
+  if (info==LevenbergMarquardtSpace::ImproperInputParameters)
+      return info;
+  do 
+  {
+    info = lm.minimizeOneStep(uv);
+  } while (info==LevenbergMarquardtSpace::Running);
+  
+  VERIFY_IS_EQUAL(info, 1);
+  //FIXME Check other parameters
+  return info;
+}
+
+template<typename T>
+void test_denseLM_T()
+{
+  typedef Matrix<T,Dynamic,1> VectorType;
+  
+  int inputs = 10; 
+  int values = 1000; 
+  DenseLM<T> dense_gaussian(inputs, values);
+  VectorType uv(inputs),uv_ref(inputs);
+  VectorType x(values);
+  
+  // Generate the reference solution 
+  uv_ref << -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
+  
+  //Generate the reference data points
+  x.setRandom();
+  x = 10*x;
+  x.array() += 10;
+  dense_gaussian.initPoints(uv_ref, x);
+  
+  // Generate the initial parameters 
+  VectorBlock<VectorType> u(uv, 0, inputs/2); 
+  VectorBlock<VectorType> v(uv, inputs/2, inputs/2);
+  
+  // Solve the optimization problem
+  
+  //Solve in one go
+  u.setOnes(); v.setOnes();
+  test_minimizeLM(dense_gaussian, uv);
+  
+  //Solve until the machine precision
+  u.setOnes(); v.setOnes();
+  test_lmder(dense_gaussian, uv); 
+  
+  // Solve step by step
+  v.setOnes(); u.setOnes();
+  test_minimizeSteps(dense_gaussian, uv);
+  
+}
+
+void test_denseLM()
+{
+  CALL_SUBTEST_2(test_denseLM_T<double>());
+  
+  // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
+}
diff --git a/test/determinant.cpp b/test/determinant.cpp
new file mode 100644
index 0000000..758f3af
--- /dev/null
+++ b/test/determinant.cpp
@@ -0,0 +1,67 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+
+template<typename MatrixType> void determinant(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Determinant.h
+  */
+  typedef typename MatrixType::Index Index;
+  Index size = m.rows();
+
+  MatrixType m1(size, size), m2(size, size);
+  m1.setRandom();
+  m2.setRandom();
+  typedef typename MatrixType::Scalar Scalar;
+  Scalar x = internal::random<Scalar>();
+  VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
+  VERIFY_IS_APPROX((m1*m2).eval().determinant(), m1.determinant() * m2.determinant());
+  if(size==1) return;
+  Index i = internal::random<Index>(0, size-1);
+  Index j;
+  do {
+    j = internal::random<Index>(0, size-1);
+  } while(j==i);
+  m2 = m1;
+  m2.row(i).swap(m2.row(j));
+  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
+  m2 = m1;
+  m2.col(i).swap(m2.col(j));
+  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
+  VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
+  VERIFY_IS_APPROX(numext::conj(m2.determinant()), m2.adjoint().determinant());
+  m2 = m1;
+  m2.row(i) += x*m2.row(j);
+  VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
+  m2 = m1;
+  m2.row(i) *= x;
+  VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x);
+  
+  // check empty matrix
+  VERIFY_IS_APPROX(m2.block(0,0,0,0).determinant(), Scalar(1));
+}
+
+void test_determinant()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    int s = 0;
+    CALL_SUBTEST_1( determinant(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( determinant(Matrix<double, 2, 2>()) );
+    CALL_SUBTEST_3( determinant(Matrix<double, 3, 3>()) );
+    CALL_SUBTEST_4( determinant(Matrix<double, 4, 4>()) );
+    CALL_SUBTEST_5( determinant(Matrix<std::complex<double>, 10, 10>()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_6( determinant(MatrixXd(s, s)) );
+    TEST_SET_BUT_UNUSED_VARIABLE(s)
+  }
+}
diff --git a/test/diagonal.cpp b/test/diagonal.cpp
new file mode 100644
index 0000000..53814a5
--- /dev/null
+++ b/test/diagonal.cpp
@@ -0,0 +1,77 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void diagonal(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index 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>2 ?  2 : 0,
+      N2 = MatrixType::RowsAtCompileTime>1 ? -1 : 0
+    };
+
+    // check sub/super diagonal
+    if(MatrixType::SizeAtCompileTime!=Dynamic)
+    {
+      VERIFY(m1.template diagonal<N1>().RowsAtCompileTime == m1.diagonal(N1).size());
+      VERIFY(m1.template diagonal<N2>().RowsAtCompileTime == m1.diagonal(N2).size());
+    }
+
+    m2.template diagonal<N1>() = 2 * m1.template diagonal<N1>();
+    VERIFY_IS_APPROX(m2.template diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
+    m2.template diagonal<N1>()[0] *= 3;
+    VERIFY_IS_APPROX(m2.template diagonal<N1>()[0], static_cast<Scalar>(6) * m1.template diagonal<N1>()[0]);
+
+
+    m2.template diagonal<N2>() = 2 * m1.template diagonal<N2>();
+    m2.template diagonal<N2>()[0] *= 3;
+    VERIFY_IS_APPROX(m2.template diagonal<N2>()[0], static_cast<Scalar>(6) * m1.template diagonal<N2>()[0]);
+
+    m2.diagonal(N1) = 2 * m1.diagonal(N1);
+    VERIFY_IS_APPROX(m2.template diagonal<N1>(), static_cast<Scalar>(2) * m1.diagonal(N1));
+    m2.diagonal(N1)[0] *= 3;
+    VERIFY_IS_APPROX(m2.diagonal(N1)[0], static_cast<Scalar>(6) * m1.diagonal(N1)[0]);
+
+    m2.diagonal(N2) = 2 * m1.diagonal(N2);
+    VERIFY_IS_APPROX(m2.template diagonal<N2>(), static_cast<Scalar>(2) * m1.diagonal(N2));
+    m2.diagonal(N2)[0] *= 3;
+    VERIFY_IS_APPROX(m2.diagonal(N2)[0], static_cast<Scalar>(6) * m1.diagonal(N2)[0]);
+  }
+}
+
+void test_diagonal()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( diagonal(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( diagonal(Matrix<float, 4, 9>()) );
+    CALL_SUBTEST_1( diagonal(Matrix<float, 7, 3>()) );
+    CALL_SUBTEST_2( diagonal(Matrix4d()) );
+    CALL_SUBTEST_2( diagonal(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_2( diagonal(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_2( diagonal(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_1( diagonal(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_1( diagonal(Matrix<float,Dynamic,4>(3, 4)) );
+  }
+}
diff --git a/test/diagonalmatrices.cpp b/test/diagonalmatrices.cpp
new file mode 100644
index 0000000..149f1db
--- /dev/null
+++ b/test/diagonalmatrices.cpp
@@ -0,0 +1,102 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+using namespace std;
+template<typename MatrixType> void diagonalmatrices(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
+  typedef Matrix<Scalar, Rows, 1> VectorType;
+  typedef Matrix<Scalar, 1, Cols> RowVectorType;
+  typedef Matrix<Scalar, Rows, Rows> SquareMatrixType;
+  typedef DiagonalMatrix<Scalar, Rows> LeftDiagonalMatrix;
+  typedef DiagonalMatrix<Scalar, Cols> RightDiagonalMatrix;
+  typedef Matrix<Scalar, Rows==Dynamic?Dynamic:2*Rows, Cols==Dynamic?Dynamic:2*Cols> BigMatrix;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols);
+  VectorType v1 = VectorType::Random(rows),
+             v2 = VectorType::Random(rows);
+  RowVectorType rv1 = RowVectorType::Random(cols),
+             rv2 = RowVectorType::Random(cols);
+  LeftDiagonalMatrix ldm1(v1), ldm2(v2);
+  RightDiagonalMatrix rdm1(rv1), rdm2(rv2);
+  
+  Scalar s1 = internal::random<Scalar>();
+
+  SquareMatrixType sq_m1 (v1.asDiagonal());
+  VERIFY_IS_APPROX(sq_m1, v1.asDiagonal().toDenseMatrix());
+  sq_m1 = v1.asDiagonal();
+  VERIFY_IS_APPROX(sq_m1, v1.asDiagonal().toDenseMatrix());
+  SquareMatrixType sq_m2 = v1.asDiagonal();
+  VERIFY_IS_APPROX(sq_m1, sq_m2);
+  
+  ldm1 = v1.asDiagonal();
+  LeftDiagonalMatrix ldm3(v1);
+  VERIFY_IS_APPROX(ldm1.diagonal(), ldm3.diagonal());
+  LeftDiagonalMatrix ldm4 = v1.asDiagonal();
+  VERIFY_IS_APPROX(ldm1.diagonal(), ldm4.diagonal());
+  
+  sq_m1.block(0,0,rows,rows) = ldm1;
+  VERIFY_IS_APPROX(sq_m1, ldm1.toDenseMatrix());
+  sq_m1.transpose() = ldm1;
+  VERIFY_IS_APPROX(sq_m1, ldm1.toDenseMatrix());
+  
+  Index i = internal::random<Index>(0, rows-1);
+  Index j = internal::random<Index>(0, cols-1);
+  
+  VERIFY_IS_APPROX( ((ldm1 * m1)(i,j))  , ldm1.diagonal()(i) * m1(i,j) );
+  VERIFY_IS_APPROX( ((ldm1 * (m1+m2))(i,j))  , ldm1.diagonal()(i) * (m1+m2)(i,j) );
+  VERIFY_IS_APPROX( ((m1 * rdm1)(i,j))  , rdm1.diagonal()(j) * m1(i,j) );
+  VERIFY_IS_APPROX( ((v1.asDiagonal() * m1)(i,j))  , v1(i) * m1(i,j) );
+  VERIFY_IS_APPROX( ((m1 * rv1.asDiagonal())(i,j))  , rv1(j) * m1(i,j) );
+  VERIFY_IS_APPROX( (((v1+v2).asDiagonal() * m1)(i,j))  , (v1+v2)(i) * m1(i,j) );
+  VERIFY_IS_APPROX( (((v1+v2).asDiagonal() * (m1+m2))(i,j))  , (v1+v2)(i) * (m1+m2)(i,j) );
+  VERIFY_IS_APPROX( ((m1 * (rv1+rv2).asDiagonal())(i,j))  , (rv1+rv2)(j) * m1(i,j) );
+  VERIFY_IS_APPROX( (((m1+m2) * (rv1+rv2).asDiagonal())(i,j))  , (rv1+rv2)(j) * (m1+m2)(i,j) );
+
+  BigMatrix big;
+  big.setZero(2*rows, 2*cols);
+  
+  big.block(i,j,rows,cols) = m1;
+  big.block(i,j,rows,cols) = v1.asDiagonal() * big.block(i,j,rows,cols);
+  
+  VERIFY_IS_APPROX((big.block(i,j,rows,cols)) , v1.asDiagonal() * m1 );
+  
+  big.block(i,j,rows,cols) = m1;
+  big.block(i,j,rows,cols) = big.block(i,j,rows,cols) * rv1.asDiagonal();
+  VERIFY_IS_APPROX((big.block(i,j,rows,cols)) , m1 * rv1.asDiagonal() );
+  
+  
+  // scalar multiple
+  VERIFY_IS_APPROX(LeftDiagonalMatrix(ldm1*s1).diagonal(), ldm1.diagonal() * s1);
+  VERIFY_IS_APPROX(LeftDiagonalMatrix(s1*ldm1).diagonal(), s1 * ldm1.diagonal());
+  
+  VERIFY_IS_APPROX(m1 * (rdm1 * s1), (m1 * rdm1) * s1);
+  VERIFY_IS_APPROX(m1 * (s1 * rdm1), (m1 * rdm1) * s1);
+}
+
+void test_diagonalmatrices()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( diagonalmatrices(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( diagonalmatrices(Matrix3f()) );
+    CALL_SUBTEST_3( diagonalmatrices(Matrix<double,3,3,RowMajor>()) );
+    CALL_SUBTEST_4( diagonalmatrices(Matrix4d()) );
+    CALL_SUBTEST_5( diagonalmatrices(Matrix<float,4,4,RowMajor>()) );
+    CALL_SUBTEST_6( diagonalmatrices(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_7( diagonalmatrices(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_8( diagonalmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_9( diagonalmatrices(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+}
diff --git a/test/dontalign.cpp b/test/dontalign.cpp
new file mode 100644
index 0000000..4643cfe
--- /dev/null
+++ b/test/dontalign.cpp
@@ -0,0 +1,63 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if defined EIGEN_TEST_PART_1 || defined EIGEN_TEST_PART_2 || defined EIGEN_TEST_PART_3 || defined EIGEN_TEST_PART_4
+#define EIGEN_DONT_ALIGN
+#elif defined EIGEN_TEST_PART_5 || defined EIGEN_TEST_PART_6 || defined EIGEN_TEST_PART_7 || defined EIGEN_TEST_PART_8
+#define EIGEN_DONT_ALIGN_STATICALLY
+#endif
+
+#include "main.h"
+#include <Eigen/Dense>
+
+template<typename MatrixType>
+void dontalign(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  SquareMatrixType square = SquareMatrixType::Random(rows,rows);
+  VectorType v = VectorType::Random(rows);
+
+  VERIFY_IS_APPROX(v, square * square.colPivHouseholderQr().solve(v));
+  square = square.inverse().eval();
+  a = square * a;
+  square = square*square;
+  v = square * v;
+  v = a.adjoint() * v;
+  VERIFY(square.determinant() != Scalar(0));
+
+  // bug 219: MapAligned() was giving an assert with EIGEN_DONT_ALIGN, because Map Flags were miscomputed
+  Scalar* array = internal::aligned_new<Scalar>(rows);
+  v = VectorType::MapAligned(array, rows);
+  internal::aligned_delete(array, rows);
+}
+
+void test_dontalign()
+{
+#if defined EIGEN_TEST_PART_1 || defined EIGEN_TEST_PART_5
+  dontalign(Matrix3d());
+  dontalign(Matrix4f());
+#elif defined EIGEN_TEST_PART_2 || defined EIGEN_TEST_PART_6
+  dontalign(Matrix3cd());
+  dontalign(Matrix4cf());
+#elif defined EIGEN_TEST_PART_3 || defined EIGEN_TEST_PART_7
+  dontalign(Matrix<float, 32, 32>());
+  dontalign(Matrix<std::complex<float>, 32, 32>());
+#elif defined EIGEN_TEST_PART_4 || defined EIGEN_TEST_PART_8
+  dontalign(MatrixXd(32, 32));
+  dontalign(MatrixXcf(32, 32));
+#endif
+}
diff --git a/test/dynalloc.cpp b/test/dynalloc.cpp
new file mode 100644
index 0000000..7e41bfa
--- /dev/null
+++ b/test/dynalloc.cpp
@@ -0,0 +1,134 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#if EIGEN_ALIGN
+#define ALIGNMENT 16
+#else
+#define ALIGNMENT 1
+#endif
+
+void check_handmade_aligned_malloc()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    char *p = (char*)internal::handmade_aligned_malloc(i);
+    VERIFY(size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    internal::handmade_aligned_free(p);
+  }
+}
+
+void check_aligned_malloc()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    char *p = (char*)internal::aligned_malloc(i);
+    VERIFY(size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    internal::aligned_free(p);
+  }
+}
+
+void check_aligned_new()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    float *p = internal::aligned_new<float>(i);
+    VERIFY(size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    internal::aligned_delete(p,i);
+  }
+}
+
+void check_aligned_stack_alloc()
+{
+  for(int i = 1; i < 400; i++)
+  {
+    ei_declare_aligned_stack_constructed_variable(float,p,i,0);
+    VERIFY(size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+  }
+}
+
+
+// test compilation with both a struct and a class...
+struct MyStruct
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  char dummychar;
+  Vector4f avec;
+};
+
+class MyClassA
+{
+  public:
+    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+    char dummychar;
+    Vector4f avec;
+};
+
+template<typename T> void check_dynaligned()
+{
+  T* obj = new T;
+  VERIFY(T::NeedsToAlign==1);
+  VERIFY(size_t(obj)%ALIGNMENT==0);
+  delete obj;
+}
+
+void test_dynalloc()
+{
+  // low level dynamic memory allocation
+  CALL_SUBTEST(check_handmade_aligned_malloc());
+  CALL_SUBTEST(check_aligned_malloc());
+  CALL_SUBTEST(check_aligned_new());
+  CALL_SUBTEST(check_aligned_stack_alloc());
+
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    CALL_SUBTEST(check_dynaligned<Vector4f>() );
+    CALL_SUBTEST(check_dynaligned<Vector2d>() );
+    CALL_SUBTEST(check_dynaligned<Matrix4f>() );
+    CALL_SUBTEST(check_dynaligned<Vector4d>() );
+    CALL_SUBTEST(check_dynaligned<Vector4i>() );
+  }
+  
+  // check static allocation, who knows ?
+  #if EIGEN_ALIGN_STATICALLY
+  {
+    MyStruct foo0;  VERIFY(size_t(foo0.avec.data())%ALIGNMENT==0);
+    MyClassA fooA;  VERIFY(size_t(fooA.avec.data())%ALIGNMENT==0);
+  }
+  
+  // dynamic allocation, single object
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    MyStruct *foo0 = new MyStruct();  VERIFY(size_t(foo0->avec.data())%ALIGNMENT==0);
+    MyClassA *fooA = new MyClassA();  VERIFY(size_t(fooA->avec.data())%ALIGNMENT==0);
+    delete foo0;
+    delete fooA;
+  }
+
+  // dynamic allocation, array
+  const int N = 10;
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    MyStruct *foo0 = new MyStruct[N];  VERIFY(size_t(foo0->avec.data())%ALIGNMENT==0);
+    MyClassA *fooA = new MyClassA[N];  VERIFY(size_t(fooA->avec.data())%ALIGNMENT==0);
+    delete[] foo0;
+    delete[] fooA;
+  }
+  #endif
+  
+}
diff --git a/test/eigen2/CMakeLists.txt b/test/eigen2/CMakeLists.txt
new file mode 100644
index 0000000..9615a60
--- /dev/null
+++ b/test/eigen2/CMakeLists.txt
@@ -0,0 +1,61 @@
+add_custom_target(eigen2_buildtests)
+add_custom_target(eigen2_check COMMAND "ctest -R eigen2")
+add_dependencies(eigen2_check eigen2_buildtests)
+add_dependencies(buildtests eigen2_buildtests)
+
+add_definitions("-DEIGEN2_SUPPORT_STAGE10_FULL_EIGEN2_API")
+add_definitions("-DEIGEN_NO_EIGEN2_DEPRECATED_WARNING")
+
+ei_add_test(eigen2_meta)
+ei_add_test(eigen2_sizeof)
+ei_add_test(eigen2_dynalloc)
+ei_add_test(eigen2_nomalloc)
+#ei_add_test(eigen2_first_aligned)
+ei_add_test(eigen2_mixingtypes)
+#ei_add_test(eigen2_packetmath)
+ei_add_test(eigen2_unalignedassert)
+#ei_add_test(eigen2_vectorization_logic)
+ei_add_test(eigen2_basicstuff)
+ei_add_test(eigen2_linearstructure)
+ei_add_test(eigen2_cwiseop)
+ei_add_test(eigen2_sum)
+ei_add_test(eigen2_product_small)
+ei_add_test(eigen2_product_large ${EI_OFLAG})
+ei_add_test(eigen2_adjoint)
+ei_add_test(eigen2_submatrices)
+ei_add_test(eigen2_miscmatrices)
+ei_add_test(eigen2_commainitializer)
+ei_add_test(eigen2_smallvectors)
+ei_add_test(eigen2_map)
+ei_add_test(eigen2_array)
+ei_add_test(eigen2_triangular)
+ei_add_test(eigen2_cholesky " " "${GSL_LIBRARIES}")
+ei_add_test(eigen2_lu ${EI_OFLAG})
+ei_add_test(eigen2_determinant ${EI_OFLAG})
+ei_add_test(eigen2_inverse)
+ei_add_test(eigen2_qr)
+ei_add_test(eigen2_eigensolver " " "${GSL_LIBRARIES}")
+ei_add_test(eigen2_svd)
+ei_add_test(eigen2_geometry)
+ei_add_test(eigen2_geometry_with_eigen2_prefix)
+ei_add_test(eigen2_hyperplane)
+ei_add_test(eigen2_parametrizedline)
+ei_add_test(eigen2_alignedbox)
+ei_add_test(eigen2_regression)
+ei_add_test(eigen2_stdvector)
+ei_add_test(eigen2_newstdvector)
+if(QT4_FOUND)
+  ei_add_test(eigen2_qtvector " " "${QT_QTCORE_LIBRARY}")
+endif(QT4_FOUND)
+# no support for eigen2 sparse module
+# if(NOT EIGEN_DEFAULT_TO_ROW_MAJOR)
+#   ei_add_test(eigen2_sparse_vector)
+#   ei_add_test(eigen2_sparse_basic)
+#   ei_add_test(eigen2_sparse_solvers " " "${SPARSE_LIBS}")
+#   ei_add_test(eigen2_sparse_product)
+# endif()
+ei_add_test(eigen2_swap)
+ei_add_test(eigen2_visitor)
+ei_add_test(eigen2_bug_132)
+
+ei_add_test(eigen2_prec_inverse_4x4 ${EI_OFLAG})
diff --git a/test/eigen2/eigen2_adjoint.cpp b/test/eigen2/eigen2_adjoint.cpp
new file mode 100644
index 0000000..c0f8114
--- /dev/null
+++ b/test/eigen2/eigen2_adjoint.cpp
@@ -0,0 +1,99 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void adjoint(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Transpose.h Conjugate.h Dot.h
+  */
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  int rows = m.rows();
+  int cols = m.cols();
+
+  RealScalar largerEps = test_precision<RealScalar>();
+  if (ei_is_same_type<RealScalar,float>::ret)
+    largerEps = RealScalar(1e-3f);
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             square = SquareMatrixType::Random(rows, rows);
+  VectorType v1 = VectorType::Random(rows),
+             v2 = VectorType::Random(rows),
+             v3 = VectorType::Random(rows),
+             vzero = VectorType::Zero(rows);
+
+  Scalar s1 = ei_random<Scalar>(),
+         s2 = ei_random<Scalar>();
+
+  // check basic compatibility of adjoint, transpose, conjugate
+  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
+  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);
+
+  // check multiplicative behavior
+  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
+  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     ei_conj(s1) * m1.adjoint());
+
+  // check basic properties of dot, norm, norm2
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  VERIFY(ei_isApprox((s1 * v1 + s2 * v2).eigen2_dot(v3),   s1 * v1.eigen2_dot(v3) + s2 * v2.eigen2_dot(v3), largerEps));
+  VERIFY(ei_isApprox(v3.eigen2_dot(s1 * v1 + s2 * v2),     ei_conj(s1)*v3.eigen2_dot(v1)+ei_conj(s2)*v3.eigen2_dot(v2), largerEps));
+  VERIFY_IS_APPROX(ei_conj(v1.eigen2_dot(v2)),               v2.eigen2_dot(v1));
+  VERIFY_IS_APPROX(ei_real(v1.eigen2_dot(v1)),               v1.squaredNorm());
+  if(NumTraits<Scalar>::HasFloatingPoint)
+    VERIFY_IS_APPROX(v1.squaredNorm(),                      v1.norm() * v1.norm());
+  VERIFY_IS_MUCH_SMALLER_THAN(ei_abs(vzero.eigen2_dot(v1)),  static_cast<RealScalar>(1));
+  if(NumTraits<Scalar>::HasFloatingPoint)
+    VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(),         static_cast<RealScalar>(1));
+
+  // check compatibility of dot and adjoint
+  VERIFY(ei_isApprox(v1.eigen2_dot(square * v2), (square.adjoint() * v1).eigen2_dot(v2), largerEps));
+
+  // like in testBasicStuff, test operator() to check const-qualification
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+  VERIFY_IS_APPROX(m1.conjugate()(r,c), ei_conj(m1(r,c)));
+  VERIFY_IS_APPROX(m1.adjoint()(c,r), ei_conj(m1(r,c)));
+
+  if(NumTraits<Scalar>::HasFloatingPoint)
+  {
+    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
+    // normalized() in order to produce a consistent result.
+    VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
+  }
+
+  // check inplace transpose
+  m3 = m1;
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1.transpose());
+  m3.transposeInPlace();
+  VERIFY_IS_APPROX(m3,m1);
+  
+}
+
+void test_eigen2_adjoint()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( adjoint(Matrix3d()) );
+    CALL_SUBTEST_3( adjoint(Matrix4f()) );
+    CALL_SUBTEST_4( adjoint(MatrixXcf(4, 4)) );
+    CALL_SUBTEST_5( adjoint(MatrixXi(8, 12)) );
+    CALL_SUBTEST_6( adjoint(MatrixXf(21, 21)) );
+  }
+  // test a large matrix only once
+  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );
+}
+
diff --git a/test/eigen2/eigen2_alignedbox.cpp b/test/eigen2/eigen2_alignedbox.cpp
new file mode 100644
index 0000000..35043b9
--- /dev/null
+++ b/test/eigen2/eigen2_alignedbox.cpp
@@ -0,0 +1,60 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+template<typename BoxType> void alignedbox(const BoxType& _box)
+{
+  /* this test covers the following files:
+     AlignedBox.h
+  */
+
+  const int dim = _box.dim();
+  typedef typename BoxType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+  RealScalar s1 = ei_random<RealScalar>(0,1);
+
+  BoxType b0(dim);
+  BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
+  BoxType b2;
+
+  b0.extend(p0);
+  b0.extend(p1);
+  VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
+  VERIFY(!b0.contains(p0 + (1+s1)*(p1-p0)));
+
+  (b2 = b0).extend(b1);
+  VERIFY(b2.contains(b0));
+  VERIFY(b2.contains(b1));
+  VERIFY_IS_APPROX(b2.clamp(b0), b0);
+
+  // casting
+  const int Dim = BoxType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  AlignedBox<OtherScalar,Dim> hp1f = b0.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),b0);
+  AlignedBox<Scalar,Dim> hp1d = b0.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),b0);
+}
+
+void test_eigen2_alignedbox()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( alignedbox(AlignedBox<float,2>()) );
+    CALL_SUBTEST_2( alignedbox(AlignedBox<float,3>()) );
+    CALL_SUBTEST_3( alignedbox(AlignedBox<double,4>()) );
+  }
+}
diff --git a/test/eigen2/eigen2_array.cpp b/test/eigen2/eigen2_array.cpp
new file mode 100644
index 0000000..c1ff40c
--- /dev/null
+++ b/test/eigen2/eigen2_array.cpp
@@ -0,0 +1,142 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Array>
+
+template<typename MatrixType> void array(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Array.cpp
+  */
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  Scalar  s1 = ei_random<Scalar>(),
+          s2 = ei_random<Scalar>();
+
+  // scalar addition
+  VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
+  VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
+  VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
+  m3 = m1;
+  m3.cwise() += s2;
+  VERIFY_IS_APPROX(m3, m1.cwise() + s2);
+  m3 = m1;
+  m3.cwise() -= s1;
+  VERIFY_IS_APPROX(m3, m1.cwise() - s1);
+
+  // reductions
+  VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
+  VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
+  if (!ei_isApprox(m1.sum(), (m1+m2).sum()))
+    VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
+  VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));
+}
+
+template<typename MatrixType> void comparisons(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  VERIFY(((m1.cwise() + Scalar(1)).cwise() > m1).all());
+  VERIFY(((m1.cwise() - Scalar(1)).cwise() < m1).all());
+  if (rows*cols>1)
+  {
+    m3 = m1;
+    m3(r,c) += 1;
+    VERIFY(! (m1.cwise() < m3).all() );
+    VERIFY(! (m1.cwise() > m3).all() );
+  }
+  
+  // comparisons to scalar
+  VERIFY( (m1.cwise() != (m1(r,c)+1) ).any() );
+  VERIFY( (m1.cwise() > (m1(r,c)-1) ).any() );
+  VERIFY( (m1.cwise() < (m1(r,c)+1) ).any() );
+  VERIFY( (m1.cwise() == m1(r,c) ).any() );
+  
+  // test Select
+  VERIFY_IS_APPROX( (m1.cwise()<m2).select(m1,m2), m1.cwise().min(m2) );
+  VERIFY_IS_APPROX( (m1.cwise()>m2).select(m1,m2), m1.cwise().max(m2) );
+  Scalar mid = (m1.cwise().abs().minCoeff() + m1.cwise().abs().maxCoeff())/Scalar(2);
+  for (int j=0; j<cols; ++j)
+  for (int i=0; i<rows; ++i)
+    m3(i,j) = ei_abs(m1(i,j))<mid ? 0 : m1(i,j);
+  VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
+                        .select(MatrixType::Zero(rows,cols),m1), m3);
+  // shorter versions:
+  VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<MatrixType::Constant(rows,cols,mid))
+                        .select(0,m1), m3);
+  VERIFY_IS_APPROX( (m1.cwise().abs().cwise()>=MatrixType::Constant(rows,cols,mid))
+                        .select(m1,0), m3);
+  // even shorter version:
+  VERIFY_IS_APPROX( (m1.cwise().abs().cwise()<mid).select(0,m1), m3);
+  
+  // count
+  VERIFY(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).count() == rows*cols);
+  VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).colwise().count().template cast<int>(), RowVectorXi::Constant(cols,rows));
+  VERIFY_IS_APPROX(((m1.cwise().abs().cwise()+1).cwise()>RealScalar(0.1)).rowwise().count().template cast<int>(), VectorXi::Constant(rows, cols));
+}
+
+template<typename VectorType> void lpNorm(const VectorType& v)
+{
+  VectorType u = VectorType::Random(v.size());
+
+  VERIFY_IS_APPROX(u.template lpNorm<Infinity>(), u.cwise().abs().maxCoeff());
+  VERIFY_IS_APPROX(u.template lpNorm<1>(), u.cwise().abs().sum());
+  VERIFY_IS_APPROX(u.template lpNorm<2>(), ei_sqrt(u.cwise().abs().cwise().square().sum()));
+  VERIFY_IS_APPROX(ei_pow(u.template lpNorm<5>(), typename VectorType::RealScalar(5)), u.cwise().abs().cwise().pow(5).sum());
+}
+
+void test_eigen2_array()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( array(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( array(Matrix2f()) );
+    CALL_SUBTEST_3( array(Matrix4d()) );
+    CALL_SUBTEST_4( array(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_5( array(MatrixXf(8, 12)) );
+    CALL_SUBTEST_6( array(MatrixXi(8, 12)) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( comparisons(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( comparisons(Matrix2f()) );
+    CALL_SUBTEST_3( comparisons(Matrix4d()) );
+    CALL_SUBTEST_5( comparisons(MatrixXf(8, 12)) );
+    CALL_SUBTEST_6( comparisons(MatrixXi(8, 12)) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( lpNorm(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( lpNorm(Vector2f()) );
+    CALL_SUBTEST_3( lpNorm(Vector3d()) );
+    CALL_SUBTEST_4( lpNorm(Vector4f()) );
+    CALL_SUBTEST_5( lpNorm(VectorXf(16)) );
+    CALL_SUBTEST_7( lpNorm(VectorXcd(10)) );
+  }
+}
diff --git a/test/eigen2/eigen2_basicstuff.cpp b/test/eigen2/eigen2_basicstuff.cpp
new file mode 100644
index 0000000..dd2dec1
--- /dev/null
+++ b/test/eigen2/eigen2_basicstuff.cpp
@@ -0,0 +1,105 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void basicStuff(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             mzero = MatrixType::Zero(rows, cols),
+             square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>::Random(rows, rows);
+  VectorType v1 = VectorType::Random(rows),
+             vzero = VectorType::Zero(rows);
+
+  Scalar x = ei_random<Scalar>();
+
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+
+  m1.coeffRef(r,c) = x;
+  VERIFY_IS_APPROX(x, m1.coeff(r,c));
+  m1(r,c) = x;
+  VERIFY_IS_APPROX(x, m1(r,c));
+  v1.coeffRef(r) = x;
+  VERIFY_IS_APPROX(x, v1.coeff(r));
+  v1(r) = x;
+  VERIFY_IS_APPROX(x, v1(r));
+  v1[r] = x;
+  VERIFY_IS_APPROX(x, v1[r]);
+
+  VERIFY_IS_APPROX(               v1,    v1);
+  VERIFY_IS_NOT_APPROX(           v1,    2*v1);
+  VERIFY_IS_MUCH_SMALLER_THAN(    vzero, v1);
+  if(NumTraits<Scalar>::HasFloatingPoint)
+    VERIFY_IS_MUCH_SMALLER_THAN(  vzero, v1.norm());
+  VERIFY_IS_NOT_MUCH_SMALLER_THAN(v1,    v1);
+  VERIFY_IS_APPROX(               vzero, v1-v1);
+  VERIFY_IS_APPROX(               m1,    m1);
+  VERIFY_IS_NOT_APPROX(           m1,    2*m1);
+  VERIFY_IS_MUCH_SMALLER_THAN(    mzero, m1);
+  VERIFY_IS_NOT_MUCH_SMALLER_THAN(m1,    m1);
+  VERIFY_IS_APPROX(               mzero, m1-m1);
+
+  // always test operator() on each read-only expression class,
+  // in order to check const-qualifiers.
+  // indeed, if an expression class (here Zero) is meant to be read-only,
+  // hence has no _write() method, the corresponding MatrixBase method (here zero())
+  // should return a const-qualified object so that it is the const-qualified
+  // operator() that gets called, which in turn calls _read().
+  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows,cols)(r,c), static_cast<Scalar>(1));
+
+  // now test copying a row-vector into a (column-)vector and conversely.
+  square.col(r) = square.row(r).eval();
+  Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> rv(rows);
+  Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> cv(rows);
+  rv = square.row(r);
+  cv = square.col(r);
+  VERIFY_IS_APPROX(rv, cv.transpose());
+
+  if(cols!=1 && rows!=1 && MatrixType::SizeAtCompileTime!=Dynamic)
+  {
+    VERIFY_RAISES_ASSERT(m1 = (m2.block(0,0, rows-1, cols-1)));
+  }
+
+  VERIFY_IS_APPROX(m3 = m1,m1);
+  MatrixType m4;
+  VERIFY_IS_APPROX(m4 = m1,m1);
+
+  // test swap
+  m3 = m1;
+  m1.swap(m2);
+  VERIFY_IS_APPROX(m3, m2);
+  if(rows*cols>=3)
+  {
+    VERIFY_IS_NOT_APPROX(m3, m1);
+  }
+}
+
+void test_eigen2_basicstuff()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( basicStuff(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( basicStuff(Matrix4d()) );
+    CALL_SUBTEST_3( basicStuff(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_4( basicStuff(MatrixXi(8, 12)) );
+    CALL_SUBTEST_5( basicStuff(MatrixXcd(20, 20)) );
+    CALL_SUBTEST_6( basicStuff(Matrix<float, 100, 100>()) );
+    CALL_SUBTEST_7( basicStuff(Matrix<long double,Dynamic,Dynamic>(10,10)) );
+  }
+}
diff --git a/test/eigen2/eigen2_bug_132.cpp b/test/eigen2/eigen2_bug_132.cpp
new file mode 100644
index 0000000..7fe3610
--- /dev/null
+++ b/test/eigen2/eigen2_bug_132.cpp
@@ -0,0 +1,26 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_eigen2_bug_132() {
+  int size = 100;
+  MatrixXd A(size, size);
+  VectorXd b(size), c(size);
+  {
+    VectorXd y = A.transpose() * (b-c);  // bug 132: infinite recursion in coeffRef
+    VectorXd z = (b-c).transpose() * A;  // bug 132: infinite recursion in coeffRef
+  }
+
+  // the following ones weren't failing, but let's include them for completeness:
+  {
+    VectorXd y = A * (b-c);
+    VectorXd z = (b-c).transpose() * A.transpose();
+  }
+}
diff --git a/test/eigen2/eigen2_cholesky.cpp b/test/eigen2/eigen2_cholesky.cpp
new file mode 100644
index 0000000..9c4b6f5
--- /dev/null
+++ b/test/eigen2/eigen2_cholesky.cpp
@@ -0,0 +1,113 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_ASSERTION_CHECKING
+#include "main.h"
+#include <Eigen/Cholesky>
+#include <Eigen/LU>
+
+#ifdef HAS_GSL
+#include "gsl_helper.h"
+#endif
+
+template<typename MatrixType> void cholesky(const MatrixType& m)
+{
+  /* this test covers the following files:
+     LLT.h LDLT.h
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  MatrixType a0 = MatrixType::Random(rows,cols);
+  VectorType vecB = VectorType::Random(rows), vecX(rows);
+  MatrixType matB = MatrixType::Random(rows,cols), matX(rows,cols);
+  SquareMatrixType symm =  a0 * a0.adjoint();
+  // let's make sure the matrix is not singular or near singular
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  symm += a1 * a1.adjoint();
+
+  #ifdef HAS_GSL
+  if (ei_is_same_type<RealScalar,double>::ret)
+  {
+    typedef GslTraits<Scalar> Gsl;
+    typename Gsl::Matrix gMatA=0, gSymm=0;
+    typename Gsl::Vector gVecB=0, gVecX=0;
+    convert<MatrixType>(symm, gSymm);
+    convert<MatrixType>(symm, gMatA);
+    convert<VectorType>(vecB, gVecB);
+    convert<VectorType>(vecB, gVecX);
+    Gsl::cholesky(gMatA);
+    Gsl::cholesky_solve(gMatA, gVecB, gVecX);
+    VectorType vecX(rows), _vecX, _vecB;
+    convert(gVecX, _vecX);
+    symm.llt().solve(vecB, &vecX);
+    Gsl::prod(gSymm, gVecX, gVecB);
+    convert(gVecB, _vecB);
+    // test gsl itself !
+    VERIFY_IS_APPROX(vecB, _vecB);
+    VERIFY_IS_APPROX(vecX, _vecX);
+
+    Gsl::free(gMatA);
+    Gsl::free(gSymm);
+    Gsl::free(gVecB);
+    Gsl::free(gVecX);
+  }
+  #endif
+
+  {
+    LDLT<SquareMatrixType> ldlt(symm);
+    VERIFY(ldlt.isPositiveDefinite());
+    // in eigen3, LDLT is pivoting
+    //VERIFY_IS_APPROX(symm, ldlt.matrixL() * ldlt.vectorD().asDiagonal() * ldlt.matrixL().adjoint());
+    ldlt.solve(vecB, &vecX);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    ldlt.solve(matB, &matX);
+    VERIFY_IS_APPROX(symm * matX, matB);
+  }
+
+  {
+    LLT<SquareMatrixType> chol(symm);
+    VERIFY(chol.isPositiveDefinite());
+    VERIFY_IS_APPROX(symm, chol.matrixL() * chol.matrixL().adjoint());
+    chol.solve(vecB, &vecX);
+    VERIFY_IS_APPROX(symm * vecX, vecB);
+    chol.solve(matB, &matX);
+    VERIFY_IS_APPROX(symm * matX, matB);
+  }
+
+#if 0 // cholesky is not rank-revealing anyway
+  // test isPositiveDefinite on non definite matrix
+  if (rows>4)
+  {
+    SquareMatrixType symm =  a0.block(0,0,rows,cols-4) * a0.block(0,0,rows,cols-4).adjoint();
+    LLT<SquareMatrixType> chol(symm);
+    VERIFY(!chol.isPositiveDefinite());
+    LDLT<SquareMatrixType> cholnosqrt(symm);
+    VERIFY(!cholnosqrt.isPositiveDefinite());
+  }
+#endif
+}
+
+void test_eigen2_cholesky()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( cholesky(Matrix<double,1,1>()) );
+    CALL_SUBTEST_2( cholesky(Matrix2d()) );
+    CALL_SUBTEST_3( cholesky(Matrix3f()) );
+    CALL_SUBTEST_4( cholesky(Matrix4d()) );
+    CALL_SUBTEST_5( cholesky(MatrixXcd(7,7)) );
+    CALL_SUBTEST_6( cholesky(MatrixXf(17,17)) );
+    CALL_SUBTEST_7( cholesky(MatrixXd(33,33)) );
+  }
+}
diff --git a/test/eigen2/eigen2_commainitializer.cpp b/test/eigen2/eigen2_commainitializer.cpp
new file mode 100644
index 0000000..e0f901e
--- /dev/null
+++ b/test/eigen2/eigen2_commainitializer.cpp
@@ -0,0 +1,46 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_eigen2_commainitializer()
+{
+  Matrix3d m3;
+  Matrix4d m4;
+
+  VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8) );
+  
+  #ifndef _MSC_VER
+  VERIFY_RAISES_ASSERT( (m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) );
+  #endif
+
+  double data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+  Matrix3d ref = Map<Matrix<double,3,3,RowMajor> >(data);
+
+  m3 = Matrix3d::Random();
+  m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9;
+  VERIFY_IS_APPROX(m3, ref );
+
+  Vector3d vec[3];
+  vec[0] << 1, 4, 7;
+  vec[1] << 2, 5, 8;
+  vec[2] << 3, 6, 9;
+  m3 = Matrix3d::Random();
+  m3 << vec[0], vec[1], vec[2];
+  VERIFY_IS_APPROX(m3, ref);
+
+  vec[0] << 1, 2, 3;
+  vec[1] << 4, 5, 6;
+  vec[2] << 7, 8, 9;
+  m3 = Matrix3d::Random();
+  m3 << vec[0].transpose(),
+        4, 5, 6,
+        vec[2].transpose();
+  VERIFY_IS_APPROX(m3, ref);
+}
diff --git a/test/eigen2/eigen2_cwiseop.cpp b/test/eigen2/eigen2_cwiseop.cpp
new file mode 100644
index 0000000..22e1cc3
--- /dev/null
+++ b/test/eigen2/eigen2_cwiseop.cpp
@@ -0,0 +1,155 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <functional>
+#include <Eigen/Array>
+
+using namespace std;
+
+template<typename Scalar> struct AddIfNull {
+    const Scalar operator() (const Scalar a, const Scalar b) const {return a<=1e-3 ? b : a;}
+    enum { Cost = NumTraits<Scalar>::AddCost };
+};
+
+template<typename MatrixType> void cwiseops(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             m4(rows, cols),
+             mzero = MatrixType::Zero(rows, cols),
+             mones = MatrixType::Ones(rows, cols),
+             identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
+                              ::Identity(rows, rows);
+  VectorType vzero = VectorType::Zero(rows),
+             vones = VectorType::Ones(rows),
+             v3(rows);
+
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+  
+  Scalar s1 = ei_random<Scalar>();
+  
+  // test Zero, Ones, Constant, and the set* variants
+  m3 = MatrixType::Constant(rows, cols, s1);
+  for (int j=0; j<cols; ++j)
+    for (int i=0; i<rows; ++i)
+    {
+      VERIFY_IS_APPROX(mzero(i,j), Scalar(0));
+      VERIFY_IS_APPROX(mones(i,j), Scalar(1));
+      VERIFY_IS_APPROX(m3(i,j), s1);
+    }
+  VERIFY(mzero.isZero());
+  VERIFY(mones.isOnes());
+  VERIFY(m3.isConstant(s1));
+  VERIFY(identity.isIdentity());
+  VERIFY_IS_APPROX(m4.setConstant(s1), m3);
+  VERIFY_IS_APPROX(m4.setConstant(rows,cols,s1), m3);
+  VERIFY_IS_APPROX(m4.setZero(), mzero);
+  VERIFY_IS_APPROX(m4.setZero(rows,cols), mzero);
+  VERIFY_IS_APPROX(m4.setOnes(), mones);
+  VERIFY_IS_APPROX(m4.setOnes(rows,cols), mones);
+  m4.fill(s1);
+  VERIFY_IS_APPROX(m4, m3);
+  
+  VERIFY_IS_APPROX(v3.setConstant(rows, s1), VectorType::Constant(rows,s1));
+  VERIFY_IS_APPROX(v3.setZero(rows), vzero);
+  VERIFY_IS_APPROX(v3.setOnes(rows), vones);
+
+  m2 = m2.template binaryExpr<AddIfNull<Scalar> >(mones);
+
+  VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().abs2());
+  VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
+  VERIFY_IS_APPROX(m1.cwise().pow(3), m1.cwise().cube());
+
+  VERIFY_IS_APPROX(m1 + mones, m1.cwise()+Scalar(1));
+  VERIFY_IS_APPROX(m1 - mones, m1.cwise()-Scalar(1));
+  m3 = m1; m3.cwise() += 1;
+  VERIFY_IS_APPROX(m1 + mones, m3);
+  m3 = m1; m3.cwise() -= 1;
+  VERIFY_IS_APPROX(m1 - mones, m3);
+
+  VERIFY_IS_APPROX(m2, m2.cwise() * mones);
+  VERIFY_IS_APPROX(m1.cwise() * m2,  m2.cwise() * m1);
+  m3 = m1;
+  m3.cwise() *= m2;
+  VERIFY_IS_APPROX(m3, m1.cwise() * m2);
+  
+  VERIFY_IS_APPROX(mones,    m2.cwise()/m2);
+  if(NumTraits<Scalar>::HasFloatingPoint)
+  {
+    VERIFY_IS_APPROX(m1.cwise() / m2,    m1.cwise() * (m2.cwise().inverse()));
+    m3 = m1.cwise().abs().cwise().sqrt();
+    VERIFY_IS_APPROX(m3.cwise().square(), m1.cwise().abs());
+    VERIFY_IS_APPROX(m1.cwise().square().cwise().sqrt(), m1.cwise().abs());
+    VERIFY_IS_APPROX(m1.cwise().abs().cwise().log().cwise().exp() , m1.cwise().abs());
+
+    VERIFY_IS_APPROX(m1.cwise().pow(2), m1.cwise().square());
+    m3 = (m1.cwise().abs().cwise()<=RealScalar(0.01)).select(mones,m1);
+    VERIFY_IS_APPROX(m3.cwise().pow(-1), m3.cwise().inverse());
+    m3 = m1.cwise().abs();
+    VERIFY_IS_APPROX(m3.cwise().pow(RealScalar(0.5)), m3.cwise().sqrt());
+    
+//     VERIFY_IS_APPROX(m1.cwise().tan(), m1.cwise().sin().cwise() / m1.cwise().cos());
+    VERIFY_IS_APPROX(mones, m1.cwise().sin().cwise().square() + m1.cwise().cos().cwise().square());
+    m3 = m1;
+    m3.cwise() /= m2;
+    VERIFY_IS_APPROX(m3, m1.cwise() / m2);
+  }
+
+  // check min
+  VERIFY_IS_APPROX( m1.cwise().min(m2), m2.cwise().min(m1) );
+  VERIFY_IS_APPROX( m1.cwise().min(m1+mones), m1 );
+  VERIFY_IS_APPROX( m1.cwise().min(m1-mones), m1-mones );
+
+  // check max
+  VERIFY_IS_APPROX( m1.cwise().max(m2), m2.cwise().max(m1) );
+  VERIFY_IS_APPROX( m1.cwise().max(m1-mones), m1 );
+  VERIFY_IS_APPROX( m1.cwise().max(m1+mones), m1+mones );
+  
+  VERIFY( (m1.cwise() == m1).all() );
+  VERIFY( (m1.cwise() != m2).any() );
+  VERIFY(!(m1.cwise() == (m1+mones)).any() );
+  if (rows*cols>1)
+  {
+    m3 = m1;
+    m3(r,c) += 1;
+    VERIFY( (m1.cwise() == m3).any() );
+    VERIFY( !(m1.cwise() == m3).all() );
+  }
+  VERIFY( (m1.cwise().min(m2).cwise() <= m2).all() );
+  VERIFY( (m1.cwise().max(m2).cwise() >= m2).all() );
+  VERIFY( (m1.cwise().min(m2).cwise() < (m1+mones)).all() );
+  VERIFY( (m1.cwise().max(m2).cwise() > (m1-mones)).all() );
+
+  VERIFY( (m1.cwise()<m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).all() );
+  VERIFY( !(m1.cwise()<m1.unaryExpr(bind2nd(minus<Scalar>(), Scalar(1)))).all() );
+  VERIFY( !(m1.cwise()>m1.unaryExpr(bind2nd(plus<Scalar>(), Scalar(1)))).any() );
+}
+
+void test_eigen2_cwiseop()
+{
+  for(int i = 0; i < g_repeat ; i++) {
+    CALL_SUBTEST_1( cwiseops(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( cwiseops(Matrix4d()) );
+    CALL_SUBTEST_3( cwiseops(MatrixXf(3, 3)) );
+    CALL_SUBTEST_3( cwiseops(MatrixXf(22, 22)) );
+    CALL_SUBTEST_4( cwiseops(MatrixXi(8, 12)) );
+    CALL_SUBTEST_5( cwiseops(MatrixXd(20, 20)) );
+  }
+}
diff --git a/test/eigen2/eigen2_determinant.cpp b/test/eigen2/eigen2_determinant.cpp
new file mode 100644
index 0000000..c7b4ad0
--- /dev/null
+++ b/test/eigen2/eigen2_determinant.cpp
@@ -0,0 +1,61 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+
+template<typename MatrixType> void determinant(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Determinant.h
+  */
+  int size = m.rows();
+
+  MatrixType m1(size, size), m2(size, size);
+  m1.setRandom();
+  m2.setRandom();
+  typedef typename MatrixType::Scalar Scalar;
+  Scalar x = ei_random<Scalar>();
+  VERIFY_IS_APPROX(MatrixType::Identity(size, size).determinant(), Scalar(1));
+  VERIFY_IS_APPROX((m1*m2).determinant(), m1.determinant() * m2.determinant());
+  if(size==1) return;
+  int i = ei_random<int>(0, size-1);
+  int j;
+  do {
+    j = ei_random<int>(0, size-1);
+  } while(j==i);
+  m2 = m1;
+  m2.row(i).swap(m2.row(j));
+  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
+  m2 = m1;
+  m2.col(i).swap(m2.col(j));
+  VERIFY_IS_APPROX(m2.determinant(), -m1.determinant());
+  VERIFY_IS_APPROX(m2.determinant(), m2.transpose().determinant());
+  VERIFY_IS_APPROX(ei_conj(m2.determinant()), m2.adjoint().determinant());
+  m2 = m1;
+  m2.row(i) += x*m2.row(j);
+  VERIFY_IS_APPROX(m2.determinant(), m1.determinant());
+  m2 = m1;
+  m2.row(i) *= x;
+  VERIFY_IS_APPROX(m2.determinant(), m1.determinant() * x);
+}
+
+void test_eigen2_determinant()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( determinant(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( determinant(Matrix<double, 2, 2>()) );
+    CALL_SUBTEST_3( determinant(Matrix<double, 3, 3>()) );
+    CALL_SUBTEST_4( determinant(Matrix<double, 4, 4>()) );
+    CALL_SUBTEST_5( determinant(Matrix<std::complex<double>, 10, 10>()) );
+    CALL_SUBTEST_6( determinant(MatrixXd(20, 20)) );
+  }
+  CALL_SUBTEST_6( determinant(MatrixXd(200, 200)) );
+}
diff --git a/test/eigen2/eigen2_dynalloc.cpp b/test/eigen2/eigen2_dynalloc.cpp
new file mode 100644
index 0000000..1891a9e
--- /dev/null
+++ b/test/eigen2/eigen2_dynalloc.cpp
@@ -0,0 +1,131 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#if EIGEN_ARCH_WANTS_ALIGNMENT
+#define ALIGNMENT 16
+#else
+#define ALIGNMENT 1
+#endif
+
+void check_handmade_aligned_malloc()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    char *p = (char*)ei_handmade_aligned_malloc(i);
+    VERIFY(std::size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    ei_handmade_aligned_free(p);
+  }
+}
+
+void check_aligned_malloc()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    char *p = (char*)ei_aligned_malloc(i);
+    VERIFY(std::size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    ei_aligned_free(p);
+  }
+}
+
+void check_aligned_new()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    float *p = ei_aligned_new<float>(i);
+    VERIFY(std::size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+    ei_aligned_delete(p,i);
+  }
+}
+
+void check_aligned_stack_alloc()
+{
+  for(int i = 1; i < 1000; i++)
+  {
+    ei_declare_aligned_stack_constructed_variable(float, p, i, 0);
+    VERIFY(std::size_t(p)%ALIGNMENT==0);
+    // if the buffer is wrongly allocated this will give a bad write --> check with valgrind
+    for(int j = 0; j < i; j++) p[j]=0;
+  }
+}
+
+
+// test compilation with both a struct and a class...
+struct MyStruct
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  char dummychar;
+  Vector4f avec;
+};
+
+class MyClassA
+{
+  public:
+    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+    char dummychar;
+    Vector4f avec;
+};
+
+template<typename T> void check_dynaligned()
+{
+  T* obj = new T;
+  VERIFY(std::size_t(obj)%ALIGNMENT==0);
+  delete obj;
+}
+
+void test_eigen2_dynalloc()
+{
+  // low level dynamic memory allocation
+  CALL_SUBTEST(check_handmade_aligned_malloc());
+  CALL_SUBTEST(check_aligned_malloc());
+  CALL_SUBTEST(check_aligned_new());
+  CALL_SUBTEST(check_aligned_stack_alloc());
+
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    CALL_SUBTEST( check_dynaligned<Vector4f>() );
+    CALL_SUBTEST( check_dynaligned<Vector2d>() );
+    CALL_SUBTEST( check_dynaligned<Matrix4f>() );
+    CALL_SUBTEST( check_dynaligned<Vector4d>() );
+    CALL_SUBTEST( check_dynaligned<Vector4i>() );
+  }
+  
+  // check static allocation, who knows ?
+  {
+    MyStruct foo0;  VERIFY(std::size_t(foo0.avec.data())%ALIGNMENT==0);
+    MyClassA fooA;  VERIFY(std::size_t(fooA.avec.data())%ALIGNMENT==0);
+  }
+
+  // dynamic allocation, single object
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    MyStruct *foo0 = new MyStruct();  VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
+    MyClassA *fooA = new MyClassA();  VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
+    delete foo0;
+    delete fooA;
+  }
+
+  // dynamic allocation, array
+  const int N = 10;
+  for (int i=0; i<g_repeat*100; ++i)
+  {
+    MyStruct *foo0 = new MyStruct[N];  VERIFY(std::size_t(foo0->avec.data())%ALIGNMENT==0);
+    MyClassA *fooA = new MyClassA[N];  VERIFY(std::size_t(fooA->avec.data())%ALIGNMENT==0);
+    delete[] foo0;
+    delete[] fooA;
+  }
+  
+}
diff --git a/test/eigen2/eigen2_eigensolver.cpp b/test/eigen2/eigen2_eigensolver.cpp
new file mode 100644
index 0000000..48b4ace
--- /dev/null
+++ b/test/eigen2/eigen2_eigensolver.cpp
@@ -0,0 +1,146 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+#ifdef HAS_GSL
+#include "gsl_helper.h"
+#endif
+
+template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
+{
+  /* this test covers the following files:
+     EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
+  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
+
+  RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
+
+  MatrixType b = MatrixType::Random(rows,cols);
+  MatrixType b1 = MatrixType::Random(rows,cols);
+  MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
+
+  SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
+  // generalized eigen pb
+  SelfAdjointEigenSolver<MatrixType> eiSymmGen(symmA, symmB);
+
+  #ifdef HAS_GSL
+  if (ei_is_same_type<RealScalar,double>::ret)
+  {
+    typedef GslTraits<Scalar> Gsl;
+    typename Gsl::Matrix gEvec=0, gSymmA=0, gSymmB=0;
+    typename GslTraits<RealScalar>::Vector gEval=0;
+    RealVectorType _eval;
+    MatrixType _evec;
+    convert<MatrixType>(symmA, gSymmA);
+    convert<MatrixType>(symmB, gSymmB);
+    convert<MatrixType>(symmA, gEvec);
+    gEval = GslTraits<RealScalar>::createVector(rows);
+
+    Gsl::eigen_symm(gSymmA, gEval, gEvec);
+    convert(gEval, _eval);
+    convert(gEvec, _evec);
+
+    // test gsl itself !
+    VERIFY((symmA * _evec).isApprox(_evec * _eval.asDiagonal(), largerEps));
+
+    // compare with eigen
+    VERIFY_IS_APPROX(_eval, eiSymm.eigenvalues());
+    VERIFY_IS_APPROX(_evec.cwise().abs(), eiSymm.eigenvectors().cwise().abs());
+
+    // generalized pb
+    Gsl::eigen_symm_gen(gSymmA, gSymmB, gEval, gEvec);
+    convert(gEval, _eval);
+    convert(gEvec, _evec);
+    // test GSL itself:
+    VERIFY((symmA * _evec).isApprox(symmB * (_evec * _eval.asDiagonal()), largerEps));
+
+    // compare with eigen
+    MatrixType normalized_eivec = eiSymmGen.eigenvectors()*eiSymmGen.eigenvectors().colwise().norm().asDiagonal().inverse();
+    VERIFY_IS_APPROX(_eval, eiSymmGen.eigenvalues());
+    VERIFY_IS_APPROX(_evec.cwiseAbs(), normalized_eivec.cwiseAbs());
+
+    Gsl::free(gSymmA);
+    Gsl::free(gSymmB);
+    GslTraits<RealScalar>::free(gEval);
+    Gsl::free(gEvec);
+  }
+  #endif
+
+  VERIFY((symmA * eiSymm.eigenvectors()).isApprox(
+          eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
+
+  // generalized eigen problem Ax = lBx
+  VERIFY((symmA * eiSymmGen.eigenvectors()).isApprox(
+          symmB * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
+
+  MatrixType sqrtSymmA = eiSymm.operatorSqrt();
+  VERIFY_IS_APPROX(symmA, sqrtSymmA*sqrtSymmA);
+  VERIFY_IS_APPROX(sqrtSymmA, symmA*eiSymm.operatorInverseSqrt());
+}
+
+template<typename MatrixType> void eigensolver(const MatrixType& m)
+{
+  /* this test covers the following files:
+     EigenSolver.h
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
+  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
+
+  // RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
+
+  EigenSolver<MatrixType> ei0(symmA);
+  VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
+  VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
+    (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));
+
+  EigenSolver<MatrixType> ei1(a);
+  VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
+  VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
+                   ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
+
+}
+
+void test_eigen2_eigensolver()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    // very important to test a 3x3 matrix since we provide a special path for it
+    CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
+    CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
+    CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(7,7)) );
+    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXcd(5,5)) );
+    CALL_SUBTEST_5( selfadjointeigensolver(MatrixXd(19,19)) );
+
+    CALL_SUBTEST_6( eigensolver(Matrix4f()) );
+    CALL_SUBTEST_5( eigensolver(MatrixXd(17,17)) );
+  }
+}
+
diff --git a/test/eigen2/eigen2_first_aligned.cpp b/test/eigen2/eigen2_first_aligned.cpp
new file mode 100644
index 0000000..51bb3ca
--- /dev/null
+++ b/test/eigen2/eigen2_first_aligned.cpp
@@ -0,0 +1,49 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar>
+void test_eigen2_first_aligned_helper(Scalar *array, int size)
+{
+  const int packet_size = sizeof(Scalar) * ei_packet_traits<Scalar>::size;
+  VERIFY(((std::size_t(array) + sizeof(Scalar) * ei_alignmentOffset(array, size)) % packet_size) == 0);
+}
+
+template<typename Scalar>
+void test_eigen2_none_aligned_helper(Scalar *array, int size)
+{
+  VERIFY(ei_packet_traits<Scalar>::size == 1 || ei_alignmentOffset(array, size) == size);
+}
+
+struct some_non_vectorizable_type { float x; };
+
+void test_eigen2_first_aligned()
+{
+  EIGEN_ALIGN_128 float array_float[100];
+  test_first_aligned_helper(array_float, 50);
+  test_first_aligned_helper(array_float+1, 50);
+  test_first_aligned_helper(array_float+2, 50);
+  test_first_aligned_helper(array_float+3, 50);
+  test_first_aligned_helper(array_float+4, 50);
+  test_first_aligned_helper(array_float+5, 50);
+  
+  EIGEN_ALIGN_128 double array_double[100];
+  test_first_aligned_helper(array_double, 50);
+  test_first_aligned_helper(array_double+1, 50);
+  test_first_aligned_helper(array_double+2, 50);
+  
+  double *array_double_plus_4_bytes = (double*)(std::size_t(array_double)+4);
+  test_none_aligned_helper(array_double_plus_4_bytes, 50);
+  test_none_aligned_helper(array_double_plus_4_bytes+1, 50);
+  
+  some_non_vectorizable_type array_nonvec[100];
+  test_first_aligned_helper(array_nonvec, 100);
+  test_none_aligned_helper(array_nonvec, 100);
+}
diff --git a/test/eigen2/eigen2_geometry.cpp b/test/eigen2/eigen2_geometry.cpp
new file mode 100644
index 0000000..5140407
--- /dev/null
+++ b/test/eigen2/eigen2_geometry.cpp
@@ -0,0 +1,432 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename Scalar> void geometry(void)
+{
+  /* this test covers the following files:
+     Cross.h Quaternion.h, Transform.cpp
+  */
+
+  typedef Matrix<Scalar,2,2> Matrix2;
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,4,4> Matrix4;
+  typedef Matrix<Scalar,2,1> Vector2;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Matrix<Scalar,4,1> Vector4;
+  typedef Quaternion<Scalar> Quaternionx;
+  typedef AngleAxis<Scalar> AngleAxisx;
+  typedef Transform<Scalar,2> Transform2;
+  typedef Transform<Scalar,3> Transform3;
+  typedef Scaling<Scalar,2> Scaling2;
+  typedef Scaling<Scalar,3> Scaling3;
+  typedef Translation<Scalar,2> Translation2;
+  typedef Translation<Scalar,3> Translation3;
+
+  Scalar largeEps = test_precision<Scalar>();
+  if (ei_is_same_type<Scalar,float>::ret)
+    largeEps = 1e-2f;
+
+  Vector3 v0 = Vector3::Random(),
+    v1 = Vector3::Random(),
+    v2 = Vector3::Random();
+  Vector2 u0 = Vector2::Random();
+  Matrix3 matrot1;
+
+  Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+  // cross product
+  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
+  Matrix3 m;
+  m << v0.normalized(),
+      (v0.cross(v1)).normalized(),
+      (v0.cross(v1).cross(v0)).normalized();
+  VERIFY(m.isUnitary());
+
+  // Quaternion: Identity(), setIdentity();
+  Quaternionx q1, q2;
+  q2.setIdentity();
+  VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
+  q1.coeffs().setRandom();
+  VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
+
+  // unitOrthogonal
+  VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
+  VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
+  VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
+
+
+  VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
+  VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
+  VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
+  m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
+  VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
+  VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
+
+  q1 = AngleAxisx(a, v0.normalized());
+  q2 = AngleAxisx(a, v1.normalized());
+
+  // angular distance
+  Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
+  if (refangle>Scalar(M_PI))
+    refangle = Scalar(2)*Scalar(M_PI) - refangle;
+  
+  if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
+  {
+    VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
+  }
+
+  // rotation matrix conversion
+  VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
+  VERIFY_IS_APPROX(q1 * q2 * v2,
+    q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
+
+  VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
+    q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
+
+  q2 = q1.toRotationMatrix();
+  VERIFY_IS_APPROX(q1*v1,q2*v1);
+
+  matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
+          * AngleAxisx(Scalar(0.2), Vector3::UnitY())
+          * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
+  VERIFY_IS_APPROX(matrot1 * v1,
+       AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
+
+  // angle-axis conversion
+  AngleAxisx aa = q1;
+  VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+  VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
+
+  // from two vector creation
+  VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
+  VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
+
+  // inverse and conjugate
+  VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
+  VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
+
+  // AngleAxis
+  VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
+    Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
+
+  AngleAxisx aa1;
+  m = q1.toRotationMatrix();
+  aa1 = m;
+  VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
+    Quaternionx(m).toRotationMatrix());
+
+  // Transform
+  // TODO complete the tests !
+  a = 0;
+  while (ei_abs(a)<Scalar(0.1))
+    a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
+  q1 = AngleAxisx(a, v0.normalized());
+  Transform3 t0, t1, t2;
+  // first test setIdentity() and Identity()
+  t0.setIdentity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+  t0.matrix().setZero();
+  t0 = Transform3::Identity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+
+  t0.linear() = q1.toRotationMatrix();
+  t1.setIdentity();
+  t1.linear() = q1.toRotationMatrix();
+
+  v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
+  t0.scale(v0);
+  t1.prescale(v0);
+
+  VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
+  //VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
+
+  t0.setIdentity();
+  t1.setIdentity();
+  v1 << 1, 2, 3;
+  t0.linear() = q1.toRotationMatrix();
+  t0.pretranslate(v0);
+  t0.scale(v1);
+  t1.linear() = q1.conjugate().toRotationMatrix();
+  t1.prescale(v1.cwise().inverse());
+  t1.translate(-v0);
+
+  VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
+
+  t1.fromPositionOrientationScale(v0, q1, v1);
+  VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
+  VERIFY_IS_APPROX(t1*v1, t0*v1);
+
+  t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
+  t1.setIdentity(); t1.scale(v0).rotate(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
+  VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
+
+  // More transform constructors, operator=, operator*=
+
+  Matrix3 mat3 = Matrix3::Random();
+  Matrix4 mat4;
+  mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
+  Transform3 tmat3(mat3), tmat4(mat4);
+  tmat4.matrix()(3,3) = Scalar(1);
+  VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
+
+  Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+  Vector3 v3 = Vector3::Random().normalized();
+  AngleAxisx aa3(a3, v3);
+  Transform3 t3(aa3);
+  Transform3 t4;
+  t4 = aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+  t4.rotate(AngleAxisx(-a3,v3));
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+
+  v3 = Vector3::Random();
+  Translation3 tv3(v3);
+  Transform3 t5(tv3);
+  t4 = tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+  t4.translate(-v3);
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+
+  Scaling3 sv3(v3);
+  Transform3 t6(sv3);
+  t4 = sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+  t4.scale(v3.cwise().inverse());
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+
+  // matrix * transform
+  VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
+
+  // chained Transform product
+  VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
+
+  // check that Transform product doesn't have aliasing problems
+  t5 = t4;
+  t5 = t5*t5;
+  VERIFY_IS_APPROX(t5, t4*t4);
+
+  // 2D transformation
+  Transform2 t20, t21;
+  Vector2 v20 = Vector2::Random();
+  Vector2 v21 = Vector2::Random();
+  for (int k=0; k<2; ++k)
+    if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
+  VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
+    t21.pretranslate(v20).scale(v21).matrix());
+
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
+  VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
+        * (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
+
+  // Transform - new API
+  // 3D
+  t0.setIdentity();
+  t0.rotate(q1).scale(v0).translate(v0);
+  // mat * scaling and mat * translation
+  t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // mat * transformation and scaling * translation
+  t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.prerotate(q1).prescale(v0).pretranslate(v0);
+  // translation * scaling and transformation * mat
+  t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // scaling * mat and translation * mat
+  t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.scale(v0).translate(v0).rotate(q1);
+  // translation * mat and scaling * transformation
+  t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * scaling
+  t0.scale(v0);
+  t1 = t1 * Scaling3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * translation
+  t0.translate(v0);
+  t1 = t1 * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // translation * transformation
+  t0.pretranslate(v0);
+  t1 = Translation3(v0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // transform * quaternion
+  t0.rotate(q1);
+  t1 = t1 * q1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // translation * quaternion
+  t0.translate(v1).rotate(q1);
+  t1 = t1 * (Translation3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // scaling * quaternion
+  t0.scale(v1).rotate(q1);
+  t1 = t1 * (Scaling3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * transform
+  t0.prerotate(q1);
+  t1 = q1 * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * translation
+  t0.rotate(q1).translate(v1);
+  t1 = t1 * (q1 * Translation3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * scaling
+  t0.rotate(q1).scale(v1);
+  t1 = t1 * (q1 * Scaling3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // translation * vector
+  t0.setIdentity();
+  t0.translate(v0);
+  VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
+
+  // scaling * vector
+  t0.setIdentity();
+  t0.scale(v0);
+  VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
+
+  // test transform inversion
+  t0.setIdentity();
+  t0.translate(v0);
+  t0.linear().setRandom();
+  VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1);
+  VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
+
+  // test extract rotation and scaling
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1).scale(v1);
+  VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
+
+  Matrix3 mat_rotation, mat_scaling;
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1).scale(v1);
+  t0.computeRotationScaling(&mat_rotation, &mat_scaling);
+  VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+  t0.computeScalingRotation(&mat_scaling, &mat_rotation);
+  VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+
+  // test casting
+  Transform<float,3> t1f = t1.template cast<float>();
+  VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
+  Transform<double,3> t1d = t1.template cast<double>();
+  VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
+
+  Translation3 tr1(v0);
+  Translation<float,3> tr1f = tr1.template cast<float>();
+  VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
+  Translation<double,3> tr1d = tr1.template cast<double>();
+  VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
+
+  Scaling3 sc1(v0);
+  Scaling<float,3> sc1f = sc1.template cast<float>();
+  VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
+  Scaling<double,3> sc1d = sc1.template cast<double>();
+  VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
+
+  Quaternion<float> q1f = q1.template cast<float>();
+  VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
+  Quaternion<double> q1d = q1.template cast<double>();
+  VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
+
+  AngleAxis<float> aa1f = aa1.template cast<float>();
+  VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
+  AngleAxis<double> aa1d = aa1.template cast<double>();
+  VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
+
+  Rotation2D<Scalar> r2d1(ei_random<Scalar>());
+  Rotation2D<float> r2d1f = r2d1.template cast<float>();
+  VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
+  Rotation2D<double> r2d1d = r2d1.template cast<double>();
+  VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
+
+  m = q1;
+//   m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
+//   m.col(0) = Vector3(-1,0,0).normalized();
+//   m.col(2) = m.col(0).cross(m.col(1));
+  #define VERIFY_EULER(I,J,K, X,Y,Z) { \
+    Vector3 ea = m.eulerAngles(I,J,K); \
+    Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
+    VERIFY_IS_APPROX(m, m1); \
+    VERIFY_IS_APPROX(m,  Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
+  }
+  VERIFY_EULER(0,1,2, X,Y,Z);
+  VERIFY_EULER(0,1,0, X,Y,X);
+  VERIFY_EULER(0,2,1, X,Z,Y);
+  VERIFY_EULER(0,2,0, X,Z,X);
+
+  VERIFY_EULER(1,2,0, Y,Z,X);
+  VERIFY_EULER(1,2,1, Y,Z,Y);
+  VERIFY_EULER(1,0,2, Y,X,Z);
+  VERIFY_EULER(1,0,1, Y,X,Y);
+
+  VERIFY_EULER(2,0,1, Z,X,Y);
+  VERIFY_EULER(2,0,2, Z,X,Z);
+  VERIFY_EULER(2,1,0, Z,Y,X);
+  VERIFY_EULER(2,1,2, Z,Y,Z);
+
+  // colwise/rowwise cross product
+  mat3.setRandom();
+  Vector3 vec3 = Vector3::Random();
+  Matrix3 mcross;
+  int i = ei_random<int>(0,2);
+  mcross = mat3.colwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
+  mcross = mat3.rowwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
+
+
+}
+
+void test_eigen2_geometry()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( geometry<float>() );
+    CALL_SUBTEST_2( geometry<double>() );
+  }
+}
diff --git a/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp b/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp
new file mode 100644
index 0000000..12d4a71
--- /dev/null
+++ b/test/eigen2/eigen2_geometry_with_eigen2_prefix.cpp
@@ -0,0 +1,435 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN2_SUPPORT_STAGE15_RESOLVE_API_CONFLICTS_WARN
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename Scalar> void geometry(void)
+{
+  /* this test covers the following files:
+     Cross.h Quaternion.h, Transform.cpp
+  */
+
+  typedef Matrix<Scalar,2,2> Matrix2;
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,4,4> Matrix4;
+  typedef Matrix<Scalar,2,1> Vector2;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Matrix<Scalar,4,1> Vector4;
+  typedef eigen2_Quaternion<Scalar> Quaternionx;
+  typedef eigen2_AngleAxis<Scalar> AngleAxisx;
+  typedef eigen2_Transform<Scalar,2> Transform2;
+  typedef eigen2_Transform<Scalar,3> Transform3;
+  typedef eigen2_Scaling<Scalar,2> Scaling2;
+  typedef eigen2_Scaling<Scalar,3> Scaling3;
+  typedef eigen2_Translation<Scalar,2> Translation2;
+  typedef eigen2_Translation<Scalar,3> Translation3;
+
+  Scalar largeEps = test_precision<Scalar>();
+  if (ei_is_same_type<Scalar,float>::ret)
+    largeEps = 1e-2f;
+
+  Vector3 v0 = Vector3::Random(),
+    v1 = Vector3::Random(),
+    v2 = Vector3::Random();
+  Vector2 u0 = Vector2::Random();
+  Matrix3 matrot1;
+
+  Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+  // cross product
+  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1));
+  Matrix3 m;
+  m << v0.normalized(),
+      (v0.cross(v1)).normalized(),
+      (v0.cross(v1).cross(v0)).normalized();
+  VERIFY(m.isUnitary());
+
+  // Quaternion: Identity(), setIdentity();
+  Quaternionx q1, q2;
+  q2.setIdentity();
+  VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
+  q1.coeffs().setRandom();
+  VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
+
+  // unitOrthogonal
+  VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1));
+  VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
+  VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
+
+
+  VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
+  VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
+  VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
+  m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
+  VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
+  VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
+
+  q1 = AngleAxisx(a, v0.normalized());
+  q2 = AngleAxisx(a, v1.normalized());
+
+  // angular distance
+  Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
+  if (refangle>Scalar(M_PI))
+    refangle = Scalar(2)*Scalar(M_PI) - refangle;
+  
+  if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
+  {
+    VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
+  }
+
+  // rotation matrix conversion
+  VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
+  VERIFY_IS_APPROX(q1 * q2 * v2,
+    q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
+
+  VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
+    q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
+
+  q2 = q1.toRotationMatrix();
+  VERIFY_IS_APPROX(q1*v1,q2*v1);
+
+  matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
+          * AngleAxisx(Scalar(0.2), Vector3::UnitY())
+          * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
+  VERIFY_IS_APPROX(matrot1 * v1,
+       AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
+
+  // angle-axis conversion
+  AngleAxisx aa = q1;
+  VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+  VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
+
+  // from two vector creation
+  VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
+  VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
+
+  // inverse and conjugate
+  VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
+  VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
+
+  // AngleAxis
+  VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
+    Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
+
+  AngleAxisx aa1;
+  m = q1.toRotationMatrix();
+  aa1 = m;
+  VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
+    Quaternionx(m).toRotationMatrix());
+
+  // Transform
+  // TODO complete the tests !
+  a = 0;
+  while (ei_abs(a)<Scalar(0.1))
+    a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
+  q1 = AngleAxisx(a, v0.normalized());
+  Transform3 t0, t1, t2;
+  // first test setIdentity() and Identity()
+  t0.setIdentity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+  t0.matrix().setZero();
+  t0 = Transform3::Identity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+
+  t0.linear() = q1.toRotationMatrix();
+  t1.setIdentity();
+  t1.linear() = q1.toRotationMatrix();
+
+  v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5));
+  t0.scale(v0);
+  t1.prescale(v0);
+
+  VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x());
+  //VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x()));
+
+  t0.setIdentity();
+  t1.setIdentity();
+  v1 << 1, 2, 3;
+  t0.linear() = q1.toRotationMatrix();
+  t0.pretranslate(v0);
+  t0.scale(v1);
+  t1.linear() = q1.conjugate().toRotationMatrix();
+  t1.prescale(v1.cwise().inverse());
+  t1.translate(-v0);
+
+  VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>()));
+
+  t1.fromPositionOrientationScale(v0, q1, v1);
+  VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
+  VERIFY_IS_APPROX(t1*v1, t0*v1);
+
+  t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
+  t1.setIdentity(); t1.scale(v0).rotate(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
+  VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
+
+  // More transform constructors, operator=, operator*=
+
+  Matrix3 mat3 = Matrix3::Random();
+  Matrix4 mat4;
+  mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
+  Transform3 tmat3(mat3), tmat4(mat4);
+  tmat4.matrix()(3,3) = Scalar(1);
+  VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
+
+  Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+  Vector3 v3 = Vector3::Random().normalized();
+  AngleAxisx aa3(a3, v3);
+  Transform3 t3(aa3);
+  Transform3 t4;
+  t4 = aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+  t4.rotate(AngleAxisx(-a3,v3));
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+
+  v3 = Vector3::Random();
+  Translation3 tv3(v3);
+  Transform3 t5(tv3);
+  t4 = tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+  t4.translate(-v3);
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+
+  Scaling3 sv3(v3);
+  Transform3 t6(sv3);
+  t4 = sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+  t4.scale(v3.cwise().inverse());
+  VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity());
+  t4 *= sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+
+  // matrix * transform
+  VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix());
+
+  // chained Transform product
+  VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
+
+  // check that Transform product doesn't have aliasing problems
+  t5 = t4;
+  t5 = t5*t5;
+  VERIFY_IS_APPROX(t5, t4*t4);
+
+  // 2D transformation
+  Transform2 t20, t21;
+  Vector2 v20 = Vector2::Random();
+  Vector2 v21 = Vector2::Random();
+  for (int k=0; k<2; ++k)
+    if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
+  VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
+    t21.pretranslate(v20).scale(v21).matrix());
+
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
+  VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
+        * (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
+
+  // Transform - new API
+  // 3D
+  t0.setIdentity();
+  t0.rotate(q1).scale(v0).translate(v0);
+  // mat * scaling and mat * translation
+  t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // mat * transformation and scaling * translation
+  t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.prerotate(q1).prescale(v0).pretranslate(v0);
+  // translation * scaling and transformation * mat
+  t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // scaling * mat and translation * mat
+  t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.scale(v0).translate(v0).rotate(q1);
+  // translation * mat and scaling * transformation
+  t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * scaling
+  t0.scale(v0);
+  t1 = t1 * Scaling3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * translation
+  t0.translate(v0);
+  t1 = t1 * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // translation * transformation
+  t0.pretranslate(v0);
+  t1 = Translation3(v0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // transform * quaternion
+  t0.rotate(q1);
+  t1 = t1 * q1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // translation * quaternion
+  t0.translate(v1).rotate(q1);
+  t1 = t1 * (Translation3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // scaling * quaternion
+  t0.scale(v1).rotate(q1);
+  t1 = t1 * (Scaling3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * transform
+  t0.prerotate(q1);
+  t1 = q1 * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * translation
+  t0.rotate(q1).translate(v1);
+  t1 = t1 * (q1 * Translation3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * scaling
+  t0.rotate(q1).scale(v1);
+  t1 = t1 * (q1 * Scaling3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // translation * vector
+  t0.setIdentity();
+  t0.translate(v0);
+  VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
+
+  // scaling * vector
+  t0.setIdentity();
+  t0.scale(v0);
+  VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1);
+
+  // test transform inversion
+  t0.setIdentity();
+  t0.translate(v0);
+  t0.linear().setRandom();
+  VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse());
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1);
+  VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
+
+  // test extract rotation and scaling
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1).scale(v1);
+  VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
+
+  Matrix3 mat_rotation, mat_scaling;
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1).scale(v1);
+  t0.computeRotationScaling(&mat_rotation, &mat_scaling);
+  VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+  t0.computeScalingRotation(&mat_scaling, &mat_rotation);
+  VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+
+  // test casting
+  eigen2_Transform<float,3> t1f = t1.template cast<float>();
+  VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
+  eigen2_Transform<double,3> t1d = t1.template cast<double>();
+  VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
+
+  Translation3 tr1(v0);
+  eigen2_Translation<float,3> tr1f = tr1.template cast<float>();
+  VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
+  eigen2_Translation<double,3> tr1d = tr1.template cast<double>();
+  VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
+
+  Scaling3 sc1(v0);
+  eigen2_Scaling<float,3> sc1f = sc1.template cast<float>();
+  VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
+  eigen2_Scaling<double,3> sc1d = sc1.template cast<double>();
+  VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
+
+  eigen2_Quaternion<float> q1f = q1.template cast<float>();
+  VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
+  eigen2_Quaternion<double> q1d = q1.template cast<double>();
+  VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
+
+  eigen2_AngleAxis<float> aa1f = aa1.template cast<float>();
+  VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
+  eigen2_AngleAxis<double> aa1d = aa1.template cast<double>();
+  VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
+
+  eigen2_Rotation2D<Scalar> r2d1(ei_random<Scalar>());
+  eigen2_Rotation2D<float> r2d1f = r2d1.template cast<float>();
+  VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
+  eigen2_Rotation2D<double> r2d1d = r2d1.template cast<double>();
+  VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
+
+  m = q1;
+//   m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
+//   m.col(0) = Vector3(-1,0,0).normalized();
+//   m.col(2) = m.col(0).cross(m.col(1));
+  #define VERIFY_EULER(I,J,K, X,Y,Z) { \
+    Vector3 ea = m.eulerAngles(I,J,K); \
+    Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
+    VERIFY_IS_APPROX(m, m1); \
+    VERIFY_IS_APPROX(m,  Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
+  }
+  VERIFY_EULER(0,1,2, X,Y,Z);
+  VERIFY_EULER(0,1,0, X,Y,X);
+  VERIFY_EULER(0,2,1, X,Z,Y);
+  VERIFY_EULER(0,2,0, X,Z,X);
+
+  VERIFY_EULER(1,2,0, Y,Z,X);
+  VERIFY_EULER(1,2,1, Y,Z,Y);
+  VERIFY_EULER(1,0,2, Y,X,Z);
+  VERIFY_EULER(1,0,1, Y,X,Y);
+
+  VERIFY_EULER(2,0,1, Z,X,Y);
+  VERIFY_EULER(2,0,2, Z,X,Z);
+  VERIFY_EULER(2,1,0, Z,Y,X);
+  VERIFY_EULER(2,1,2, Z,Y,Z);
+
+  // colwise/rowwise cross product
+  mat3.setRandom();
+  Vector3 vec3 = Vector3::Random();
+  Matrix3 mcross;
+  int i = ei_random<int>(0,2);
+  mcross = mat3.colwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
+  mcross = mat3.rowwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
+
+
+}
+
+void test_eigen2_geometry_with_eigen2_prefix()
+{
+  std::cout << "eigen2 support: " << EIGEN2_SUPPORT_STAGE << std::endl;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( geometry<float>() );
+    CALL_SUBTEST_2( geometry<double>() );
+  }
+}
diff --git a/test/eigen2/eigen2_hyperplane.cpp b/test/eigen2/eigen2_hyperplane.cpp
new file mode 100644
index 0000000..f3f85e1
--- /dev/null
+++ b/test/eigen2/eigen2_hyperplane.cpp
@@ -0,0 +1,126 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
+{
+  /* this test covers the following files:
+     Hyperplane.h
+  */
+
+  const int dim = _plane.dim();
+  typedef typename HyperplaneType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
+                         HyperplaneType::AmbientDimAtCompileTime> MatrixType;
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+
+  VectorType n0 = VectorType::Random(dim).normalized();
+  VectorType n1 = VectorType::Random(dim).normalized();
+
+  HyperplaneType pl0(n0, p0);
+  HyperplaneType pl1(n1, p1);
+  HyperplaneType pl2 = pl1;
+
+  Scalar s0 = ei_random<Scalar>();
+  Scalar s1 = ei_random<Scalar>();
+
+  VERIFY_IS_APPROX( n1.eigen2_dot(n1), Scalar(1) );
+
+  VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
+  VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
+  VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 +  pl1.normal().unitOrthogonal() * s1), Scalar(1) );
+
+  // transform
+  if (!NumTraits<Scalar>::IsComplex)
+  {
+    MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ();
+    Scaling<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
+    Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
+
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
+                                 .absDistance((rot*scaling*translation) * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
+                                 .absDistance((rot*translation) * p1), Scalar(1) );
+  }
+
+  // casting
+  const int Dim = HyperplaneType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  Hyperplane<OtherScalar,Dim> hp1f = pl1.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
+  Hyperplane<Scalar,Dim> hp1d = pl1.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
+}
+
+template<typename Scalar> void lines()
+{
+  typedef Hyperplane<Scalar, 2> HLine;
+  typedef ParametrizedLine<Scalar, 2> PLine;
+  typedef Matrix<Scalar,2,1> Vector;
+  typedef Matrix<Scalar,3,1> CoeffsType;
+
+  for(int i = 0; i < 10; i++)
+  {
+    Vector center = Vector::Random();
+    Vector u = Vector::Random();
+    Vector v = Vector::Random();
+    Scalar a = ei_random<Scalar>();
+    while (ei_abs(a-1) < 1e-4) a = ei_random<Scalar>();
+    while (u.norm() < 1e-4) u = Vector::Random();
+    while (v.norm() < 1e-4) v = Vector::Random();
+
+    HLine line_u = HLine::Through(center + u, center + a*u);
+    HLine line_v = HLine::Through(center + v, center + a*v);
+
+    // the line equations should be normalized so that a^2+b^2=1
+    VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
+    VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
+
+    Vector result = line_u.intersection(line_v);
+
+    // the lines should intersect at the point we called "center"
+    VERIFY_IS_APPROX(result, center);
+
+    // check conversions between two types of lines
+    PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
+    CoeffsType converted_coeffs(HLine(pl).coeffs());
+    converted_coeffs *= line_u.coeffs()(0)/converted_coeffs(0);
+    VERIFY(line_u.coeffs().isApprox(converted_coeffs));
+  }
+}
+
+void test_eigen2_hyperplane()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
+    CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
+    CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
+    CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
+    CALL_SUBTEST_5( lines<float>() );
+    CALL_SUBTEST_6( lines<double>() );
+  }
+}
diff --git a/test/eigen2/eigen2_inverse.cpp b/test/eigen2/eigen2_inverse.cpp
new file mode 100644
index 0000000..ccd24a1
--- /dev/null
+++ b/test/eigen2/eigen2_inverse.cpp
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+
+template<typename MatrixType> void inverse(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Inverse.h
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2(rows, cols),
+             identity = MatrixType::Identity(rows, rows);
+
+  while(ei_abs(m1.determinant()) < RealScalar(0.1) && rows <= 8)
+  {
+    m1 = MatrixType::Random(rows, cols);
+  }
+
+  m2 = m1.inverse();
+  VERIFY_IS_APPROX(m1, m2.inverse() );
+
+  m1.computeInverse(&m2);
+  VERIFY_IS_APPROX(m1, m2.inverse() );
+
+  VERIFY_IS_APPROX((Scalar(2)*m2).inverse(), m2.inverse()*Scalar(0.5));
+
+  VERIFY_IS_APPROX(identity, m1.inverse() * m1 );
+  VERIFY_IS_APPROX(identity, m1 * m1.inverse() );
+
+  VERIFY_IS_APPROX(m1, m1.inverse().inverse() );
+
+  // since for the general case we implement separately row-major and col-major, test that
+  VERIFY_IS_APPROX(m1.transpose().inverse(), m1.inverse().transpose());
+}
+
+void test_eigen2_inverse()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
+    CALL_SUBTEST_2( inverse(Matrix2d()) );
+    CALL_SUBTEST_3( inverse(Matrix3f()) );
+    CALL_SUBTEST_4( inverse(Matrix4f()) );
+    CALL_SUBTEST_5( inverse(MatrixXf(8,8)) );
+    CALL_SUBTEST_6( inverse(MatrixXcd(7,7)) );
+  }
+}
diff --git a/test/eigen2/eigen2_linearstructure.cpp b/test/eigen2/eigen2_linearstructure.cpp
new file mode 100644
index 0000000..488f4c4
--- /dev/null
+++ b/test/eigen2/eigen2_linearstructure.cpp
@@ -0,0 +1,83 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void linearStructure(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Sum.h Difference.h Opposite.h ScalarMultiple.h
+  */
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  Scalar s1 = ei_random<Scalar>();
+  while (ei_abs(s1)<1e-3) s1 = ei_random<Scalar>();
+
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+
+  VERIFY_IS_APPROX(-(-m1),                  m1);
+  VERIFY_IS_APPROX(m1+m1,                   2*m1);
+  VERIFY_IS_APPROX(m1+m2-m1,                m2);
+  VERIFY_IS_APPROX(-m2+m1+m2,               m1);
+  VERIFY_IS_APPROX(m1*s1,                   s1*m1);
+  VERIFY_IS_APPROX((m1+m2)*s1,              s1*m1+s1*m2);
+  VERIFY_IS_APPROX((-m1+m2)*s1,             -s1*m1+s1*m2);
+  m3 = m2; m3 += m1;
+  VERIFY_IS_APPROX(m3,                      m1+m2);
+  m3 = m2; m3 -= m1;
+  VERIFY_IS_APPROX(m3,                      m2-m1);
+  m3 = m2; m3 *= s1;
+  VERIFY_IS_APPROX(m3,                      s1*m2);
+  if(NumTraits<Scalar>::HasFloatingPoint)
+  {
+    m3 = m2; m3 /= s1;
+    VERIFY_IS_APPROX(m3,                    m2/s1);
+  }
+
+  // again, test operator() to check const-qualification
+  VERIFY_IS_APPROX((-m1)(r,c), -(m1(r,c)));
+  VERIFY_IS_APPROX((m1-m2)(r,c), (m1(r,c))-(m2(r,c)));
+  VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
+  VERIFY_IS_APPROX((s1*m1)(r,c), s1*(m1(r,c)));
+  VERIFY_IS_APPROX((m1*s1)(r,c), (m1(r,c))*s1);
+  if(NumTraits<Scalar>::HasFloatingPoint)
+    VERIFY_IS_APPROX((m1/s1)(r,c), (m1(r,c))/s1);
+
+  // use .block to disable vectorization and compare to the vectorized version
+  VERIFY_IS_APPROX(m1+m1.block(0,0,rows,cols), m1+m1);
+  VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
+  VERIFY_IS_APPROX(m1 - m1.block(0,0,rows,cols), m1 - m1);
+  VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
+}
+
+void test_eigen2_linearstructure()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( linearStructure(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( linearStructure(Matrix2f()) );
+    CALL_SUBTEST_3( linearStructure(Vector3d()) );
+    CALL_SUBTEST_4( linearStructure(Matrix4d()) );
+    CALL_SUBTEST_5( linearStructure(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_6( linearStructure(MatrixXf(8, 12)) );
+    CALL_SUBTEST_7( linearStructure(MatrixXi(8, 12)) );
+    CALL_SUBTEST_8( linearStructure(MatrixXcd(20, 20)) );
+  }
+}
diff --git a/test/eigen2/eigen2_lu.cpp b/test/eigen2/eigen2_lu.cpp
new file mode 100644
index 0000000..e993b1c
--- /dev/null
+++ b/test/eigen2/eigen2_lu.cpp
@@ -0,0 +1,122 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+
+template<typename Derived>
+void doSomeRankPreservingOperations(Eigen::MatrixBase<Derived>& m)
+{
+  typedef typename Derived::RealScalar RealScalar;
+  for(int a = 0; a < 3*(m.rows()+m.cols()); a++)
+  {
+    RealScalar d = Eigen::ei_random<RealScalar>(-1,1);
+    int i = Eigen::ei_random<int>(0,m.rows()-1); // i is a random row number
+    int j;
+    do {
+      j = Eigen::ei_random<int>(0,m.rows()-1);
+    } while (i==j); // j is another one (must be different)
+    m.row(i) += d * m.row(j);
+
+    i = Eigen::ei_random<int>(0,m.cols()-1); // i is a random column number
+    do {
+      j = Eigen::ei_random<int>(0,m.cols()-1);
+    } while (i==j); // j is another one (must be different)
+    m.col(i) += d * m.col(j);
+  }
+}
+
+template<typename MatrixType> void lu_non_invertible()
+{
+  /* this test covers the following files:
+     LU.h
+  */
+  // NOTE there seems to be a problem with too small sizes -- could easily lie in the doSomeRankPreservingOperations function
+  int rows = ei_random<int>(20,200), cols = ei_random<int>(20,200), cols2 = ei_random<int>(20,200);
+  int rank = ei_random<int>(1, std::min(rows, cols)-1);
+
+  MatrixType m1(rows, cols), m2(cols, cols2), m3(rows, cols2), k(1,1);
+  m1 = MatrixType::Random(rows,cols);
+  if(rows <= cols)
+    for(int i = rank; i < rows; i++) m1.row(i).setZero();
+  else
+    for(int i = rank; i < cols; i++) m1.col(i).setZero();
+  doSomeRankPreservingOperations(m1);
+
+  LU<MatrixType> lu(m1);
+  typename LU<MatrixType>::KernelResultType m1kernel = lu.kernel();
+  typename LU<MatrixType>::ImageResultType m1image = lu.image();
+
+  VERIFY(rank == lu.rank());
+  VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
+  VERIFY(!lu.isInjective());
+  VERIFY(!lu.isInvertible());
+  VERIFY(lu.isSurjective() == (lu.rank() == rows));
+  VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
+  VERIFY(m1image.lu().rank() == rank);
+  MatrixType sidebyside(m1.rows(), m1.cols() + m1image.cols());
+  sidebyside << m1, m1image;
+  VERIFY(sidebyside.lu().rank() == rank);
+  m2 = MatrixType::Random(cols,cols2);
+  m3 = m1*m2;
+  m2 = MatrixType::Random(cols,cols2);
+  lu.solve(m3, &m2);
+  VERIFY_IS_APPROX(m3, m1*m2);
+  /* solve now always returns true
+  m3 = MatrixType::Random(rows,cols2);
+  VERIFY(!lu.solve(m3, &m2));
+  */
+}
+
+template<typename MatrixType> void lu_invertible()
+{
+  /* this test covers the following files:
+     LU.h
+  */
+  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+  int size = ei_random<int>(10,200);
+
+  MatrixType m1(size, size), m2(size, size), m3(size, size);
+  m1 = MatrixType::Random(size,size);
+
+  if (ei_is_same_type<RealScalar,float>::ret)
+  {
+    // let's build a matrix more stable to inverse
+    MatrixType a = MatrixType::Random(size,size*2);
+    m1 += a * a.adjoint();
+  }
+
+  LU<MatrixType> lu(m1);
+  VERIFY(0 == lu.dimensionOfKernel());
+  VERIFY(size == lu.rank());
+  VERIFY(lu.isInjective());
+  VERIFY(lu.isSurjective());
+  VERIFY(lu.isInvertible());
+  VERIFY(lu.image().lu().isInvertible());
+  m3 = MatrixType::Random(size,size);
+  lu.solve(m3, &m2);
+  VERIFY_IS_APPROX(m3, m1*m2);
+  VERIFY_IS_APPROX(m2, lu.inverse()*m3);
+  m3 = MatrixType::Random(size,size);
+  VERIFY(lu.solve(m3, &m2));
+}
+
+void test_eigen2_lu()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( lu_non_invertible<MatrixXf>() );
+    CALL_SUBTEST_2( lu_non_invertible<MatrixXd>() );
+    CALL_SUBTEST_3( lu_non_invertible<MatrixXcf>() );
+    CALL_SUBTEST_4( lu_non_invertible<MatrixXcd>() );
+    CALL_SUBTEST_1( lu_invertible<MatrixXf>() );
+    CALL_SUBTEST_2( lu_invertible<MatrixXd>() );
+    CALL_SUBTEST_3( lu_invertible<MatrixXcf>() );
+    CALL_SUBTEST_4( lu_invertible<MatrixXcd>() );
+  }
+}
diff --git a/test/eigen2/eigen2_map.cpp b/test/eigen2/eigen2_map.cpp
new file mode 100644
index 0000000..4a1c4e1
--- /dev/null
+++ b/test/eigen2/eigen2_map.cpp
@@ -0,0 +1,114 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename VectorType> void map_class_vector(const VectorType& m)
+{
+  typedef typename VectorType::Scalar Scalar;
+
+  int size = m.size();
+
+  // test Map.h
+  Scalar* array1 = ei_aligned_new<Scalar>(size);
+  Scalar* array2 = ei_aligned_new<Scalar>(size);
+  Scalar* array3 = new Scalar[size+1];
+  Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
+  
+  Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
+  Map<VectorType>(array2, size) = Map<VectorType>(array1, size);
+  Map<VectorType>(array3unaligned, size) = Map<VectorType>((const Scalar*)array1, size); // test non-const-correctness support in eigen2
+  VectorType ma1 = Map<VectorType>(array1, size);
+  VectorType ma2 = Map<VectorType, Aligned>(array2, size);
+  VectorType ma3 = Map<VectorType>(array3unaligned, size);
+  VERIFY_IS_APPROX(ma1, ma2);
+  VERIFY_IS_APPROX(ma1, ma3);
+  
+  ei_aligned_delete(array1, size);
+  ei_aligned_delete(array2, size);
+  delete[] array3;
+}
+
+template<typename MatrixType> void map_class_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+
+  int rows = m.rows(), cols = m.cols(), size = rows*cols;
+
+  // test Map.h
+  Scalar* array1 = ei_aligned_new<Scalar>(size);
+  for(int i = 0; i < size; i++) array1[i] = Scalar(1);
+  Scalar* array2 = ei_aligned_new<Scalar>(size);
+  for(int i = 0; i < size; i++) array2[i] = Scalar(1);
+  Scalar* array3 = new Scalar[size+1];
+  for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
+  Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
+  Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
+  Map<MatrixType>(array2, rows, cols) = Map<MatrixType>((const Scalar*)array1, rows, cols); // test non-const-correctness support in eigen2
+  Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
+  MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
+  MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
+  VERIFY_IS_APPROX(ma1, ma2);
+  MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
+  VERIFY_IS_APPROX(ma1, ma3);
+  
+  ei_aligned_delete(array1, size);
+  ei_aligned_delete(array2, size);
+  delete[] array3;
+}
+
+template<typename VectorType> void map_static_methods(const VectorType& m)
+{
+  typedef typename VectorType::Scalar Scalar;
+
+  int size = m.size();
+
+  // test Map.h
+  Scalar* array1 = ei_aligned_new<Scalar>(size);
+  Scalar* array2 = ei_aligned_new<Scalar>(size);
+  Scalar* array3 = new Scalar[size+1];
+  Scalar* array3unaligned = std::size_t(array3)%16 == 0 ? array3+1 : array3;
+  
+  VectorType::MapAligned(array1, size) = VectorType::Random(size);
+  VectorType::Map(array2, size) = VectorType::Map(array1, size);
+  VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
+  VectorType ma1 = VectorType::Map(array1, size);
+  VectorType ma2 = VectorType::MapAligned(array2, size);
+  VectorType ma3 = VectorType::Map(array3unaligned, size);
+  VERIFY_IS_APPROX(ma1, ma2);
+  VERIFY_IS_APPROX(ma1, ma3);
+  
+  ei_aligned_delete(array1, size);
+  ei_aligned_delete(array2, size);
+  delete[] array3;
+}
+
+
+void test_eigen2_map()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_vector(Vector4d()) );
+    CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
+    CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
+    CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );
+
+    CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
+    CALL_SUBTEST_6( map_class_matrix(Matrix<float,3,5>()) );
+    CALL_SUBTEST_4( map_class_matrix(MatrixXcf(ei_random<int>(1,10),ei_random<int>(1,10))) );
+    CALL_SUBTEST_5( map_class_matrix(MatrixXi(ei_random<int>(1,10),ei_random<int>(1,10))) );
+
+    CALL_SUBTEST_1( map_static_methods(Matrix<double, 1, 1>()) );
+    CALL_SUBTEST_2( map_static_methods(Vector3f()) );
+    CALL_SUBTEST_7( map_static_methods(RowVector3d()) );
+    CALL_SUBTEST_4( map_static_methods(VectorXcd(8)) );
+    CALL_SUBTEST_5( map_static_methods(VectorXf(12)) );
+  }
+}
diff --git a/test/eigen2/eigen2_meta.cpp b/test/eigen2/eigen2_meta.cpp
new file mode 100644
index 0000000..1d01bd8
--- /dev/null
+++ b/test/eigen2/eigen2_meta.cpp
@@ -0,0 +1,60 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_eigen2_meta()
+{
+  typedef float & FloatRef;
+  typedef const float & ConstFloatRef;
+  
+  VERIFY((ei_meta_if<(3<4),ei_meta_true, ei_meta_false>::ret::ret));
+  VERIFY(( ei_is_same_type<float,float>::ret));
+  VERIFY((!ei_is_same_type<float,double>::ret));
+  VERIFY((!ei_is_same_type<float,float&>::ret));
+  VERIFY((!ei_is_same_type<float,const float&>::ret));
+  
+  VERIFY(( ei_is_same_type<float,ei_cleantype<const float&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<const float*>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<const float*&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<float**>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<float**&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<float* const *&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_cleantype<float* const>::type >::ret));
+
+  VERIFY(( ei_is_same_type<float*,ei_unconst<const float*>::type >::ret));
+  VERIFY(( ei_is_same_type<float&,ei_unconst<const float&>::type >::ret));
+  VERIFY(( ei_is_same_type<float&,ei_unconst<ConstFloatRef>::type >::ret));
+  
+  VERIFY(( ei_is_same_type<float&,ei_unconst<float&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_unref<float&>::type >::ret));
+  VERIFY(( ei_is_same_type<const float,ei_unref<const float&>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_unpointer<float*>::type >::ret));
+  VERIFY(( ei_is_same_type<const float,ei_unpointer<const float*>::type >::ret));
+  VERIFY(( ei_is_same_type<float,ei_unpointer<float* const >::type >::ret));
+  
+  VERIFY(ei_meta_sqrt<1>::ret == 1);
+  #define VERIFY_META_SQRT(X) VERIFY(ei_meta_sqrt<X>::ret == int(ei_sqrt(double(X))))
+  VERIFY_META_SQRT(2);
+  VERIFY_META_SQRT(3);
+  VERIFY_META_SQRT(4);
+  VERIFY_META_SQRT(5);
+  VERIFY_META_SQRT(6);
+  VERIFY_META_SQRT(8);
+  VERIFY_META_SQRT(9);
+  VERIFY_META_SQRT(15);
+  VERIFY_META_SQRT(16);
+  VERIFY_META_SQRT(17);
+  VERIFY_META_SQRT(255);
+  VERIFY_META_SQRT(256);
+  VERIFY_META_SQRT(257);
+  VERIFY_META_SQRT(1023);
+  VERIFY_META_SQRT(1024);
+  VERIFY_META_SQRT(1025);
+}
diff --git a/test/eigen2/eigen2_miscmatrices.cpp b/test/eigen2/eigen2_miscmatrices.cpp
new file mode 100644
index 0000000..8bbb20c
--- /dev/null
+++ b/test/eigen2/eigen2_miscmatrices.cpp
@@ -0,0 +1,48 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void miscMatrices(const MatrixType& m)
+{
+  /* this test covers the following files:
+     DiagonalMatrix.h Ones.h
+  */
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+  int rows = m.rows();
+  int cols = m.cols();
+
+  int r = ei_random<int>(0, rows-1), r2 = ei_random<int>(0, rows-1), c = ei_random<int>(0, cols-1);
+  VERIFY_IS_APPROX(MatrixType::Ones(rows,cols)(r,c), static_cast<Scalar>(1));
+  MatrixType m1 = MatrixType::Ones(rows,cols);
+  VERIFY_IS_APPROX(m1(r,c), static_cast<Scalar>(1));
+  VectorType v1 = VectorType::Random(rows);
+  v1[0];
+  Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
+  square = v1.asDiagonal();
+  if(r==r2) VERIFY_IS_APPROX(square(r,r2), v1[r]);
+  else VERIFY_IS_MUCH_SMALLER_THAN(square(r,r2), static_cast<Scalar>(1));
+  square = MatrixType::Zero(rows, rows);
+  square.diagonal() = VectorType::Ones(rows);
+  VERIFY_IS_APPROX(square, MatrixType::Identity(rows, rows));
+}
+
+void test_eigen2_miscmatrices()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( miscMatrices(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( miscMatrices(Matrix4d()) );
+    CALL_SUBTEST_3( miscMatrices(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_4( miscMatrices(MatrixXi(8, 12)) );
+    CALL_SUBTEST_5( miscMatrices(MatrixXcd(20, 20)) );
+  }
+}
diff --git a/test/eigen2/eigen2_mixingtypes.cpp b/test/eigen2/eigen2_mixingtypes.cpp
new file mode 100644
index 0000000..fb5ac5d
--- /dev/null
+++ b/test/eigen2/eigen2_mixingtypes.cpp
@@ -0,0 +1,77 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_NO_STATIC_ASSERT
+#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
+#endif
+
+#ifndef EIGEN_DONT_VECTORIZE
+#define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
+#endif
+
+#include "main.h"
+
+
+template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
+{
+  typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
+  typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
+  typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
+  typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
+  typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
+  typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
+  typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
+  typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;
+
+  Mat_f mf(size,size);
+  Mat_d md(size,size);
+  Mat_cf mcf(size,size);
+  Mat_cd mcd(size,size);
+  Vec_f vf(size,1);
+  Vec_d vd(size,1);
+  Vec_cf vcf(size,1);
+  Vec_cd vcd(size,1);
+
+  mf+mf;
+  VERIFY_RAISES_ASSERT(mf+md);
+  VERIFY_RAISES_ASSERT(mf+mcf);
+  VERIFY_RAISES_ASSERT(vf=vd);
+  VERIFY_RAISES_ASSERT(vf+=vd);
+  VERIFY_RAISES_ASSERT(mcd=md);
+
+  mf*mf;
+  md*mcd;
+  mcd*md;
+  mf*vcf;
+  mcf*vf;
+  mcf *= mf;
+  vcd = md*vcd;
+  vcf = mcf*vf;
+#if 0
+  // these are know generating hard build errors in eigen3
+  VERIFY_RAISES_ASSERT(mf*md);
+  VERIFY_RAISES_ASSERT(mcf*mcd);
+  VERIFY_RAISES_ASSERT(mcf*vcd);
+  VERIFY_RAISES_ASSERT(vcf = mf*vf);
+
+  vf.eigen2_dot(vf);
+  VERIFY_RAISES_ASSERT(vd.eigen2_dot(vf));
+  VERIFY_RAISES_ASSERT(vcf.eigen2_dot(vf)); // yeah eventually we should allow this but i'm too lazy to make that change now in Dot.h
+  // especially as that might be rewritten as cwise product .sum() which would make that automatic.
+#endif
+}
+
+void test_eigen2_mixingtypes()
+{
+  // check that our operator new is indeed called:
+  CALL_SUBTEST_1(mixingtypes<3>());
+  CALL_SUBTEST_2(mixingtypes<4>());
+  CALL_SUBTEST_3(mixingtypes<Dynamic>(20));
+}
diff --git a/test/eigen2/eigen2_newstdvector.cpp b/test/eigen2/eigen2_newstdvector.cpp
new file mode 100644
index 0000000..5f90099
--- /dev/null
+++ b/test/eigen2/eigen2_newstdvector.cpp
@@ -0,0 +1,149 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_USE_NEW_STDVECTOR
+#include "main.h"
+#include <Eigen/StdVector>
+#include <Eigen/Geometry>
+
+template<typename MatrixType>
+void check_stdvector_matrix(const MatrixType& m)
+{
+  int rows = m.rows();
+  int cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::vector<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_stdvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::vector<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_stdvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::vector<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_eigen2_newstdvector()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix2f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Vector4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stdvector_transform(Transform2f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Transform3f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Transform3d()));
+  //CALL_SUBTEST(check_stdvector_transform(Transform4d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaterniond()));
+}
diff --git a/test/eigen2/eigen2_nomalloc.cpp b/test/eigen2/eigen2_nomalloc.cpp
new file mode 100644
index 0000000..d34a699
--- /dev/null
+++ b/test/eigen2/eigen2_nomalloc.cpp
@@ -0,0 +1,53 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// this hack is needed to make this file compiles with -pedantic (gcc)
+#ifdef __GNUC__
+#define throw(X)
+#endif
+// discard stack allocation as that too bypasses malloc
+#define EIGEN_STACK_ALLOCATION_LIMIT 0
+// any heap allocation will raise an assert
+#define EIGEN_NO_MALLOC
+
+#include "main.h"
+
+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;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols);
+
+  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)));
+  VERIFY_IS_APPROX(m1.cwise() * m1.block(0,0,rows,cols), m1.cwise() * m1);
+  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
+}
+
+void test_eigen2_nomalloc()
+{
+  // check that our operator new is indeed called:
+  VERIFY_RAISES_ASSERT(MatrixXd dummy = MatrixXd::Random(3,3));
+  CALL_SUBTEST_1( nomalloc(Matrix<float, 1, 1>()) );
+  CALL_SUBTEST_2( nomalloc(Matrix4d()) );
+  CALL_SUBTEST_3( nomalloc(Matrix<float,32,32>()) );
+}
diff --git a/test/eigen2/eigen2_packetmath.cpp b/test/eigen2/eigen2_packetmath.cpp
new file mode 100644
index 0000000..b1f325f
--- /dev/null
+++ b/test/eigen2/eigen2_packetmath.cpp
@@ -0,0 +1,132 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+// using namespace Eigen;
+
+template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int size)
+{
+  for (int i=0; i<size; ++i)
+    if (!ei_isApprox(a[i],b[i])) return false;
+  return true;
+}
+
+#define CHECK_CWISE(REFOP, POP) { \
+  for (int i=0; i<PacketSize; ++i) \
+    ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
+  ei_pstore(data2, POP(ei_pload(data1), ei_pload(data1+PacketSize))); \
+  VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
+}
+
+#define REF_ADD(a,b) ((a)+(b))
+#define REF_SUB(a,b) ((a)-(b))
+#define REF_MUL(a,b) ((a)*(b))
+#define REF_DIV(a,b) ((a)/(b))
+
+namespace std {
+
+template<> const complex<float>& min(const complex<float>& a, const complex<float>& b)
+{ return a.real() < b.real() ? a : b; }
+
+template<> const complex<float>& max(const complex<float>& a, const complex<float>& b)
+{ return a.real() < b.real() ? b : a; }
+
+}
+
+template<typename Scalar> void packetmath()
+{
+  typedef typename ei_packet_traits<Scalar>::type Packet;
+  const int PacketSize = ei_packet_traits<Scalar>::size;
+
+  const int size = PacketSize*4;
+  EIGEN_ALIGN_128 Scalar data1[ei_packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN_128 Scalar data2[ei_packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN_128 Packet packets[PacketSize*2];
+  EIGEN_ALIGN_128 Scalar ref[ei_packet_traits<Scalar>::size*4];
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = ei_random<Scalar>();
+    data2[i] = ei_random<Scalar>();
+  }
+
+  ei_pstore(data2, ei_pload(data1));
+  VERIFY(areApprox(data1, data2, PacketSize) && "aligned load/store");
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    ei_pstore(data2, ei_ploadu(data1+offset));
+    VERIFY(areApprox(data1+offset, data2, PacketSize) && "ei_ploadu");
+  }
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    ei_pstoreu(data2+offset, ei_pload(data1));
+    VERIFY(areApprox(data1, data2+offset, PacketSize) && "ei_pstoreu");
+  }
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    packets[0] = ei_pload(data1);
+    packets[1] = ei_pload(data1+PacketSize);
+         if (offset==0) ei_palign<0>(packets[0], packets[1]);
+    else if (offset==1) ei_palign<1>(packets[0], packets[1]);
+    else if (offset==2) ei_palign<2>(packets[0], packets[1]);
+    else if (offset==3) ei_palign<3>(packets[0], packets[1]);
+    ei_pstore(data2, packets[0]);
+
+    for (int i=0; i<PacketSize; ++i)
+      ref[i] = data1[i+offset];
+
+    typedef Matrix<Scalar, PacketSize, 1> Vector;
+    VERIFY(areApprox(ref, data2, PacketSize) && "ei_palign");
+  }
+
+  CHECK_CWISE(REF_ADD,  ei_padd);
+  CHECK_CWISE(REF_SUB,  ei_psub);
+  CHECK_CWISE(REF_MUL,  ei_pmul);
+  #ifndef EIGEN_VECTORIZE_ALTIVEC
+  if (!ei_is_same_type<Scalar,int>::ret)
+    CHECK_CWISE(REF_DIV,  ei_pdiv);
+  #endif
+  CHECK_CWISE(std::min, ei_pmin);
+  CHECK_CWISE(std::max, ei_pmax);
+
+  for (int i=0; i<PacketSize; ++i)
+    ref[i] = data1[0];
+  ei_pstore(data2, ei_pset1(data1[0]));
+  VERIFY(areApprox(ref, data2, PacketSize) && "ei_pset1");
+
+  VERIFY(ei_isApprox(data1[0], ei_pfirst(ei_pload(data1))) && "ei_pfirst");
+
+  ref[0] = 0;
+  for (int i=0; i<PacketSize; ++i)
+    ref[0] += data1[i];
+  VERIFY(ei_isApprox(ref[0], ei_predux(ei_pload(data1))) && "ei_predux");
+
+  for (int j=0; j<PacketSize; ++j)
+  {
+    ref[j] = 0;
+    for (int i=0; i<PacketSize; ++i)
+      ref[j] += data1[i+j*PacketSize];
+    packets[j] = ei_pload(data1+j*PacketSize);
+  }
+  ei_pstore(data2, ei_preduxp(packets));
+  VERIFY(areApprox(ref, data2, PacketSize) && "ei_preduxp");
+}
+
+void test_eigen2_packetmath()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( packetmath<float>() );
+    CALL_SUBTEST_2( packetmath<double>() );
+    CALL_SUBTEST_3( packetmath<int>() );
+    CALL_SUBTEST_4( packetmath<std::complex<float> >() );
+  }
+}
diff --git a/test/eigen2/eigen2_parametrizedline.cpp b/test/eigen2/eigen2_parametrizedline.cpp
new file mode 100644
index 0000000..8147288
--- /dev/null
+++ b/test/eigen2/eigen2_parametrizedline.cpp
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+template<typename LineType> void parametrizedline(const LineType& _line)
+{
+  /* this test covers the following files:
+     ParametrizedLine.h
+  */
+
+  const int dim = _line.dim();
+  typedef typename LineType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime,
+                         LineType::AmbientDimAtCompileTime> MatrixType;
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+
+  VectorType d0 = VectorType::Random(dim).normalized();
+
+  LineType l0(p0, d0);
+
+  Scalar s0 = ei_random<Scalar>();
+  Scalar s1 = ei_abs(ei_random<Scalar>());
+
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0), RealScalar(1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) );
+  VERIFY_IS_APPROX( (l0.projection(p1)-p1).norm(), l0.distance(p1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(l0.projection(p1)), RealScalar(1) );
+  VERIFY_IS_APPROX( Scalar(l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1)), s1 );
+
+  // casting
+  const int Dim = LineType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  ParametrizedLine<OtherScalar,Dim> hp1f = l0.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),l0);
+  ParametrizedLine<Scalar,Dim> hp1d = l0.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),l0);
+}
+
+void test_eigen2_parametrizedline()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
+    CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
+    CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
+    CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
+  }
+}
diff --git a/test/eigen2/eigen2_prec_inverse_4x4.cpp b/test/eigen2/eigen2_prec_inverse_4x4.cpp
new file mode 100644
index 0000000..8bfa556
--- /dev/null
+++ b/test/eigen2/eigen2_prec_inverse_4x4.cpp
@@ -0,0 +1,84 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+#include <algorithm>
+
+template<typename T> std::string type_name() { return "other"; }
+template<> std::string type_name<float>() { return "float"; }
+template<> std::string type_name<double>() { return "double"; }
+template<> std::string type_name<int>() { return "int"; }
+template<> std::string type_name<std::complex<float> >() { return "complex<float>"; }
+template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
+template<> std::string type_name<std::complex<int> >() { return "complex<int>"; }
+
+#define EIGEN_DEBUG_VAR(x) std::cerr << #x << " = " << x << std::endl;
+
+template<typename T> inline typename NumTraits<T>::Real epsilon()
+{
+ return std::numeric_limits<typename NumTraits<T>::Real>::epsilon();
+}
+
+template<typename MatrixType> void inverse_permutation_4x4()
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  Vector4i indices(0,1,2,3);
+  for(int i = 0; i < 24; ++i)
+  {
+    MatrixType m = MatrixType::Zero();
+    m(indices(0),0) = 1;
+    m(indices(1),1) = 1;
+    m(indices(2),2) = 1;
+    m(indices(3),3) = 1;
+    MatrixType inv = m.inverse();
+    double error = double( (m*inv-MatrixType::Identity()).norm() / epsilon<Scalar>() );
+    VERIFY(error == 0.0);
+    std::next_permutation(indices.data(),indices.data()+4);
+  }
+}
+
+template<typename MatrixType> void inverse_general_4x4(int repeat)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  double error_sum = 0., error_max = 0.;
+  for(int i = 0; i < repeat; ++i)
+  {
+    MatrixType m;
+    RealScalar absdet;
+    do {
+      m = MatrixType::Random();
+      absdet = ei_abs(m.determinant());
+    } while(absdet < 10 * epsilon<Scalar>());
+    MatrixType inv = m.inverse();
+    double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / epsilon<Scalar>() );
+    error_sum += error;
+    error_max = std::max(error_max, error);
+  }
+  std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl;
+  double error_avg = error_sum / repeat;
+  EIGEN_DEBUG_VAR(error_avg);
+  EIGEN_DEBUG_VAR(error_max);
+  VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
+  VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
+}
+
+void test_eigen2_prec_inverse_4x4()
+{
+  CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
+  CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
+
+  CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
+  CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
+
+  CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
+  CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
+}
diff --git a/test/eigen2/eigen2_product_large.cpp b/test/eigen2/eigen2_product_large.cpp
new file mode 100644
index 0000000..5149ef7
--- /dev/null
+++ b/test/eigen2/eigen2_product_large.cpp
@@ -0,0 +1,45 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "product.h"
+
+void test_eigen2_product_large()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( product(MatrixXf(ei_random<int>(1,320), ei_random<int>(1,320))) );
+    CALL_SUBTEST_2( product(MatrixXd(ei_random<int>(1,320), ei_random<int>(1,320))) );
+    CALL_SUBTEST_3( product(MatrixXi(ei_random<int>(1,320), ei_random<int>(1,320))) );
+    CALL_SUBTEST_4( product(MatrixXcf(ei_random<int>(1,50), ei_random<int>(1,50))) );
+    CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(ei_random<int>(1,320), ei_random<int>(1,320))) );
+  }
+
+#ifdef EIGEN_TEST_PART_6
+  {
+    // test a specific issue in DiagonalProduct
+    int N = 1000000;
+    VectorXf v = VectorXf::Ones(N);
+    MatrixXf m = MatrixXf::Ones(N,3);
+    m = (v+v).asDiagonal() * m;
+    VERIFY_IS_APPROX(m, MatrixXf::Constant(N,3,2));
+  }
+
+  {
+    // test deferred resizing in Matrix::operator=
+    MatrixXf a = MatrixXf::Random(10,4), b = MatrixXf::Random(4,10), c = a;
+    VERIFY_IS_APPROX((a = a * b), (c * b).eval());
+  }
+
+  {
+    MatrixXf mat1(10,10); mat1.setRandom();
+    MatrixXf mat2(32,10); mat2.setRandom();
+    MatrixXf result = mat1.row(2)*mat2.transpose();
+    VERIFY_IS_APPROX(result, (mat1.row(2)*mat2.transpose()).eval());
+  }
+#endif
+}
diff --git a/test/eigen2/eigen2_product_small.cpp b/test/eigen2/eigen2_product_small.cpp
new file mode 100644
index 0000000..4cd8c10
--- /dev/null
+++ b/test/eigen2/eigen2_product_small.cpp
@@ -0,0 +1,22 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "product.h"
+
+void test_eigen2_product_small()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
+    CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
+    CALL_SUBTEST_3( product(Matrix3d()) );
+    CALL_SUBTEST_4( product(Matrix4d()) );
+    CALL_SUBTEST_5( product(Matrix4f()) );
+  }
+}
diff --git a/test/eigen2/eigen2_qr.cpp b/test/eigen2/eigen2_qr.cpp
new file mode 100644
index 0000000..76977e4
--- /dev/null
+++ b/test/eigen2/eigen2_qr.cpp
@@ -0,0 +1,69 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename MatrixType> void qr(const MatrixType& m)
+{
+  /* this test covers the following files:
+     QR.h
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> SquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  QR<MatrixType> qrOfA(a);
+  VERIFY_IS_APPROX(a, qrOfA.matrixQ() * qrOfA.matrixR());
+  VERIFY_IS_NOT_APPROX(a+MatrixType::Identity(rows, cols), qrOfA.matrixQ() * qrOfA.matrixR());
+
+  #if 0 // eigenvalues module not yet ready
+  SquareMatrixType b = a.adjoint() * a;
+
+  // check tridiagonalization
+  Tridiagonalization<SquareMatrixType> tridiag(b);
+  VERIFY_IS_APPROX(b, tridiag.matrixQ() * tridiag.matrixT() * tridiag.matrixQ().adjoint());
+
+  // check hessenberg decomposition
+  HessenbergDecomposition<SquareMatrixType> hess(b);
+  VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
+  VERIFY_IS_APPROX(tridiag.matrixT(), hess.matrixH());
+  b = SquareMatrixType::Random(cols,cols);
+  hess.compute(b);
+  VERIFY_IS_APPROX(b, hess.matrixQ() * hess.matrixH() * hess.matrixQ().adjoint());
+  #endif
+}
+
+void test_eigen2_qr()
+{
+  for(int i = 0; i < 1; i++) {
+    CALL_SUBTEST_1( qr(Matrix2f()) );
+    CALL_SUBTEST_2( qr(Matrix4d()) );
+    CALL_SUBTEST_3( qr(MatrixXf(12,8)) );
+    CALL_SUBTEST_4( qr(MatrixXcd(5,5)) );
+    CALL_SUBTEST_4( qr(MatrixXcd(7,3)) );
+  }
+
+#ifdef EIGEN_TEST_PART_5
+  // small isFullRank test
+  {
+    Matrix3d mat;
+    mat << 1, 45, 1, 2, 2, 2, 1, 2, 3;
+    VERIFY(mat.qr().isFullRank());
+    mat << 1, 1, 1, 2, 2, 2, 1, 2, 3;
+    //always returns true in eigen2support
+    //VERIFY(!mat.qr().isFullRank());
+  }
+
+#endif
+}
diff --git a/test/eigen2/eigen2_qtvector.cpp b/test/eigen2/eigen2_qtvector.cpp
new file mode 100644
index 0000000..6cfb58a
--- /dev/null
+++ b/test/eigen2/eigen2_qtvector.cpp
@@ -0,0 +1,158 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
+
+#include "main.h"
+
+#include <Eigen/Geometry>
+#include <Eigen/QtAlignedMalloc>
+
+#include <QtCore/QVector>
+
+template<typename MatrixType>
+void check_qtvector_matrix(const MatrixType& m)
+{
+  int rows = m.rows();
+  int cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  QVector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], y);
+  }
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_qtvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  QVector<TransformType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; int(i)<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_qtvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  QVector<QuaternionType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; int(i)<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_eigen2_qtvector()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_qtvector_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_qtvector_matrix(Matrix3f()));
+  CALL_SUBTEST_1(check_qtvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_2(check_qtvector_matrix(Matrix2f()));
+  CALL_SUBTEST_2(check_qtvector_matrix(Vector4f()));
+  CALL_SUBTEST_2(check_qtvector_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_qtvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_qtvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_qtvector_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_qtvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_qtvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_qtvector_transform(Transform2f()));
+  CALL_SUBTEST_4(check_qtvector_transform(Transform3f()));
+  CALL_SUBTEST_4(check_qtvector_transform(Transform3d()));
+  //CALL_SUBTEST_4(check_qtvector_transform(Transform4d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_qtvector_quaternion(Quaternionf()));
+}
diff --git a/test/eigen2/eigen2_regression.cpp b/test/eigen2/eigen2_regression.cpp
new file mode 100644
index 0000000..c68b58d
--- /dev/null
+++ b/test/eigen2/eigen2_regression.cpp
@@ -0,0 +1,136 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LeastSquares>
+
+template<typename VectorType,
+         typename HyperplaneType>
+void makeNoisyCohyperplanarPoints(int numPoints,
+                                  VectorType **points,
+                                  HyperplaneType *hyperplane,
+                                  typename VectorType::Scalar noiseAmplitude)
+{
+  typedef typename VectorType::Scalar Scalar;
+  const int size = points[0]->size();
+  // pick a random hyperplane, store the coefficients of its equation
+  hyperplane->coeffs().resize(size + 1);
+  for(int j = 0; j < size + 1; j++)
+  {
+    do {
+      hyperplane->coeffs().coeffRef(j) = ei_random<Scalar>();
+    } while(ei_abs(hyperplane->coeffs().coeff(j)) < 0.5);
+  }
+
+  // now pick numPoints random points on this hyperplane
+  for(int i = 0; i < numPoints; i++)
+  {
+    VectorType& cur_point = *(points[i]);
+    do
+    {
+      cur_point = VectorType::Random(size)/*.normalized()*/;
+      // project cur_point onto the hyperplane
+      Scalar x = - (hyperplane->coeffs().start(size).cwise()*cur_point).sum();
+      cur_point *= hyperplane->coeffs().coeff(size) / x;
+    } while( cur_point.norm() < 0.5
+          || cur_point.norm() > 2.0 );
+  }
+
+  // add some noise to these points
+  for(int i = 0; i < numPoints; i++ )
+    *(points[i]) += noiseAmplitude * VectorType::Random(size);
+}
+
+template<typename VectorType>
+void check_linearRegression(int numPoints,
+                            VectorType **points,
+                            const VectorType& original,
+                            typename VectorType::Scalar tolerance)
+{
+  int size = points[0]->size();
+  assert(size==2);
+  VectorType result(size);
+  linearRegression(numPoints, points, &result, 1);
+  typename VectorType::Scalar error = (result - original).norm() / original.norm();
+  VERIFY(ei_abs(error) < ei_abs(tolerance));
+}
+
+template<typename VectorType,
+         typename HyperplaneType>
+void check_fitHyperplane(int numPoints,
+                         VectorType **points,
+                         const HyperplaneType& original,
+                         typename VectorType::Scalar tolerance)
+{
+  int size = points[0]->size();
+  HyperplaneType result(size);
+  fitHyperplane(numPoints, points, &result);
+  result.coeffs() *= original.coeffs().coeff(size)/result.coeffs().coeff(size);
+  typename VectorType::Scalar error = (result.coeffs() - original.coeffs()).norm() / original.coeffs().norm();
+  std::cout << ei_abs(error) << "  xxx   " << ei_abs(tolerance) << std::endl;
+  VERIFY(ei_abs(error) < ei_abs(tolerance));
+}
+
+void test_eigen2_regression()
+{
+  for(int i = 0; i < g_repeat; i++)
+  {
+#ifdef EIGEN_TEST_PART_1
+    {
+      Vector2f points2f [1000];
+      Vector2f *points2f_ptrs [1000];
+      for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
+      Vector2f coeffs2f;
+      Hyperplane<float,2> coeffs3f;
+      makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
+      coeffs2f[0] = -coeffs3f.coeffs()[0]/coeffs3f.coeffs()[1];
+      coeffs2f[1] = -coeffs3f.coeffs()[2]/coeffs3f.coeffs()[1];
+      CALL_SUBTEST(check_linearRegression(10, points2f_ptrs, coeffs2f, 0.05f));
+      CALL_SUBTEST(check_linearRegression(100, points2f_ptrs, coeffs2f, 0.01f));
+      CALL_SUBTEST(check_linearRegression(1000, points2f_ptrs, coeffs2f, 0.002f));
+    }
+#endif
+#ifdef EIGEN_TEST_PART_2
+    {
+      Vector2f points2f [1000];
+      Vector2f *points2f_ptrs [1000];
+      for(int i = 0; i < 1000; i++) points2f_ptrs[i] = &(points2f[i]);
+      Hyperplane<float,2> coeffs3f;
+      makeNoisyCohyperplanarPoints(1000, points2f_ptrs, &coeffs3f, 0.01f);
+      CALL_SUBTEST(check_fitHyperplane(10, points2f_ptrs, coeffs3f, 0.05f));
+      CALL_SUBTEST(check_fitHyperplane(100, points2f_ptrs, coeffs3f, 0.01f));
+      CALL_SUBTEST(check_fitHyperplane(1000, points2f_ptrs, coeffs3f, 0.002f));
+    }
+#endif
+#ifdef EIGEN_TEST_PART_3
+    {
+      Vector4d points4d [1000];
+      Vector4d *points4d_ptrs [1000];
+      for(int i = 0; i < 1000; i++) points4d_ptrs[i] = &(points4d[i]);
+      Hyperplane<double,4> coeffs5d;
+      makeNoisyCohyperplanarPoints(1000, points4d_ptrs, &coeffs5d, 0.01);
+      CALL_SUBTEST(check_fitHyperplane(10, points4d_ptrs, coeffs5d, 0.05));
+      CALL_SUBTEST(check_fitHyperplane(100, points4d_ptrs, coeffs5d, 0.01));
+      CALL_SUBTEST(check_fitHyperplane(1000, points4d_ptrs, coeffs5d, 0.002));
+    }
+#endif
+#ifdef EIGEN_TEST_PART_4
+    {
+      VectorXcd *points11cd_ptrs[1000];
+      for(int i = 0; i < 1000; i++) points11cd_ptrs[i] = new VectorXcd(11);
+      Hyperplane<std::complex<double>,Dynamic> *coeffs12cd = new Hyperplane<std::complex<double>,Dynamic>(11);
+      makeNoisyCohyperplanarPoints(1000, points11cd_ptrs, coeffs12cd, 0.01);
+      CALL_SUBTEST(check_fitHyperplane(100, points11cd_ptrs, *coeffs12cd, 0.025));
+      CALL_SUBTEST(check_fitHyperplane(1000, points11cd_ptrs, *coeffs12cd, 0.006));
+      delete coeffs12cd;
+      for(int i = 0; i < 1000; i++) delete points11cd_ptrs[i];
+    }
+#endif
+  }
+}
diff --git a/test/eigen2/eigen2_sizeof.cpp b/test/eigen2/eigen2_sizeof.cpp
new file mode 100644
index 0000000..ec1af5a
--- /dev/null
+++ b/test/eigen2/eigen2_sizeof.cpp
@@ -0,0 +1,31 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void verifySizeOf(const MatrixType&)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
+    VERIFY(sizeof(MatrixType)==sizeof(Scalar)*MatrixType::SizeAtCompileTime);
+  else
+    VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
+}
+
+void test_eigen2_sizeof()
+{
+  CALL_SUBTEST( verifySizeOf(Matrix<float, 1, 1>()) );
+  CALL_SUBTEST( verifySizeOf(Matrix4d()) );
+  CALL_SUBTEST( verifySizeOf(Matrix<double, 4, 2>()) );
+  CALL_SUBTEST( verifySizeOf(Matrix<bool, 7, 5>()) );
+  CALL_SUBTEST( verifySizeOf(MatrixXcf(3, 3)) );
+  CALL_SUBTEST( verifySizeOf(MatrixXi(8, 12)) );
+  CALL_SUBTEST( verifySizeOf(MatrixXcd(20, 20)) );
+  CALL_SUBTEST( verifySizeOf(Matrix<float, 100, 100>()) );
+}
diff --git a/test/eigen2/eigen2_smallvectors.cpp b/test/eigen2/eigen2_smallvectors.cpp
new file mode 100644
index 0000000..03962b1
--- /dev/null
+++ b/test/eigen2/eigen2_smallvectors.cpp
@@ -0,0 +1,42 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar> void smallVectors()
+{
+  typedef Matrix<Scalar, 1, 2> V2;
+  typedef Matrix<Scalar, 3, 1> V3;
+  typedef Matrix<Scalar, 1, 4> V4;
+  Scalar x1 = ei_random<Scalar>(),
+         x2 = ei_random<Scalar>(),
+         x3 = ei_random<Scalar>(),
+         x4 = ei_random<Scalar>();
+  V2 v2(x1, x2);
+  V3 v3(x1, x2, x3);
+  V4 v4(x1, x2, x3, x4);
+  VERIFY_IS_APPROX(x1, v2.x());
+  VERIFY_IS_APPROX(x1, v3.x());
+  VERIFY_IS_APPROX(x1, v4.x());
+  VERIFY_IS_APPROX(x2, v2.y());
+  VERIFY_IS_APPROX(x2, v3.y());
+  VERIFY_IS_APPROX(x2, v4.y());
+  VERIFY_IS_APPROX(x3, v3.z());
+  VERIFY_IS_APPROX(x3, v4.z());
+  VERIFY_IS_APPROX(x4, v4.w());
+}
+
+void test_eigen2_smallvectors()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST( smallVectors<int>() );
+    CALL_SUBTEST( smallVectors<float>() );
+    CALL_SUBTEST( smallVectors<double>() );
+  }
+}
diff --git a/test/eigen2/eigen2_sparse_basic.cpp b/test/eigen2/eigen2_sparse_basic.cpp
new file mode 100644
index 0000000..0490776
--- /dev/null
+++ b/test/eigen2/eigen2_sparse_basic.cpp
@@ -0,0 +1,317 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename SetterType,typename DenseType, typename Scalar, int Options>
+bool test_random_setter(SparseMatrix<Scalar,Options>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
+{
+  typedef SparseMatrix<Scalar,Options> SparseType;
+  {
+    sm.setZero();
+    SetterType w(sm);
+    std::vector<Vector2i> remaining = nonzeroCoords;
+    while(!remaining.empty())
+    {
+      int i = ei_random<int>(0,remaining.size()-1);
+      w(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
+      remaining[i] = remaining.back();
+      remaining.pop_back();
+    }
+  }
+  return sm.isApprox(ref);
+}
+
+template<typename SetterType,typename DenseType, typename T>
+bool test_random_setter(DynamicSparseMatrix<T>& sm, const DenseType& ref, const std::vector<Vector2i>& nonzeroCoords)
+{
+  sm.setZero();
+  std::vector<Vector2i> remaining = nonzeroCoords;
+  while(!remaining.empty())
+  {
+    int i = ei_random<int>(0,remaining.size()-1);
+    sm.coeffRef(remaining[i].x(),remaining[i].y()) = ref.coeff(remaining[i].x(),remaining[i].y());
+    remaining[i] = remaining.back();
+    remaining.pop_back();
+  }
+  return sm.isApprox(ref);
+}
+
+template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
+{
+  const int rows = ref.rows();
+  const int cols = ref.cols();
+  typedef typename SparseMatrixType::Scalar Scalar;
+  enum { Flags = SparseMatrixType::Flags };
+  
+  double density = std::max(8./(rows*cols), 0.01);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  Scalar eps = 1e-6;
+
+  SparseMatrixType m(rows, cols);
+  DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
+  DenseVector vec1 = DenseVector::Random(rows);
+  Scalar s1 = ei_random<Scalar>();
+
+  std::vector<Vector2i> zeroCoords;
+  std::vector<Vector2i> nonzeroCoords;
+  initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
+  
+  if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
+    return;
+
+  // test coeff and coeffRef
+  for (int i=0; i<(int)zeroCoords.size(); ++i)
+  {
+    VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
+    if(ei_is_same_type<SparseMatrixType,SparseMatrix<Scalar,Flags> >::ret)
+      VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
+  }
+  VERIFY_IS_APPROX(m, refMat);
+
+  m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+  refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+
+  VERIFY_IS_APPROX(m, refMat);
+  /*
+  // test InnerIterators and Block expressions
+  for (int t=0; t<10; ++t)
+  {
+    int j = ei_random<int>(0,cols-1);
+    int i = ei_random<int>(0,rows-1);
+    int w = ei_random<int>(1,cols-j-1);
+    int h = ei_random<int>(1,rows-i-1);
+
+//     VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
+    for(int c=0; c<w; c++)
+    {
+      VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
+      for(int r=0; r<h; r++)
+      {
+//         VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
+      }
+    }
+//     for(int r=0; r<h; r++)
+//     {
+//       VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
+//       for(int c=0; c<w; c++)
+//       {
+//         VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
+//       }
+//     }
+  }
+
+  for(int c=0; c<cols; c++)
+  {
+    VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
+    VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
+  }
+
+  for(int r=0; r<rows; r++)
+  {
+    VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
+    VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
+  }
+  */
+
+  // test SparseSetters
+  // coherent setter
+  // TODO extend the MatrixSetter
+//   {
+//     m.setZero();
+//     VERIFY_IS_NOT_APPROX(m, refMat);
+//     SparseSetter<SparseMatrixType, FullyCoherentAccessPattern> w(m);
+//     for (int i=0; i<nonzeroCoords.size(); ++i)
+//     {
+//       w->coeffRef(nonzeroCoords[i].x(),nonzeroCoords[i].y()) = refMat.coeff(nonzeroCoords[i].x(),nonzeroCoords[i].y());
+//     }
+//   }
+//   VERIFY_IS_APPROX(m, refMat);
+
+  // random setter
+//   {
+//     m.setZero();
+//     VERIFY_IS_NOT_APPROX(m, refMat);
+//     SparseSetter<SparseMatrixType, RandomAccessPattern> w(m);
+//     std::vector<Vector2i> remaining = nonzeroCoords;
+//     while(!remaining.empty())
+//     {
+//       int i = ei_random<int>(0,remaining.size()-1);
+//       w->coeffRef(remaining[i].x(),remaining[i].y()) = refMat.coeff(remaining[i].x(),remaining[i].y());
+//       remaining[i] = remaining.back();
+//       remaining.pop_back();
+//     }
+//   }
+//   VERIFY_IS_APPROX(m, refMat);
+
+    VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdMapTraits> >(m,refMat,nonzeroCoords) ));
+    #ifdef EIGEN_UNORDERED_MAP_SUPPORT
+    VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, StdUnorderedMapTraits> >(m,refMat,nonzeroCoords) ));
+    #endif
+    #ifdef _DENSE_HASH_MAP_H_
+    VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleDenseHashMapTraits> >(m,refMat,nonzeroCoords) ));
+    #endif
+    #ifdef _SPARSE_HASH_MAP_H_
+    VERIFY(( test_random_setter<RandomSetter<SparseMatrixType, GoogleSparseHashMapTraits> >(m,refMat,nonzeroCoords) ));
+    #endif
+
+    // test fillrand
+    {
+      DenseMatrix m1(rows,cols);
+      m1.setZero();
+      SparseMatrixType m2(rows,cols);
+      m2.startFill();
+      for (int j=0; j<cols; ++j)
+      {
+        for (int k=0; k<rows/2; ++k)
+        {
+          int i = ei_random<int>(0,rows-1);
+          if (m1.coeff(i,j)==Scalar(0))
+            m2.fillrand(i,j) = m1(i,j) = ei_random<Scalar>();
+        }
+      }
+      m2.endFill();
+      VERIFY_IS_APPROX(m2,m1);
+    }
+  
+  // test RandomSetter
+  /*{
+    SparseMatrixType m1(rows,cols), m2(rows,cols);
+    DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
+    initSparse<Scalar>(density, refM1, m1);
+    {
+      Eigen::RandomSetter<SparseMatrixType > setter(m2);
+      for (int j=0; j<m1.outerSize(); ++j)
+        for (typename SparseMatrixType::InnerIterator i(m1,j); i; ++i)
+          setter(i.index(), j) = i.value();
+    }
+    VERIFY_IS_APPROX(m1, m2);
+  }*/
+//   std::cerr << m.transpose() << "\n\n"  << refMat.transpose() << "\n\n";
+//   VERIFY_IS_APPROX(m, refMat);
+
+  // test basic computations
+  {
+    DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m1(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    SparseMatrixType m3(rows, rows);
+    SparseMatrixType m4(rows, rows);
+    initSparse<Scalar>(density, refM1, m1);
+    initSparse<Scalar>(density, refM2, m2);
+    initSparse<Scalar>(density, refM3, m3);
+    initSparse<Scalar>(density, refM4, m4);
+
+    VERIFY_IS_APPROX(m1+m2, refM1+refM2);
+    VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
+    VERIFY_IS_APPROX(m3.cwise()*(m1+m2), refM3.cwise()*(refM1+refM2));
+    VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
+
+    VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
+    VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
+    
+    VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
+    VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
+    
+    VERIFY_IS_APPROX(m1.col(0).eigen2_dot(refM2.row(0)), refM1.col(0).eigen2_dot(refM2.row(0)));
+    
+    refM4.setRandom();
+    // sparse cwise* dense
+    VERIFY_IS_APPROX(m3.cwise()*refM4, refM3.cwise()*refM4);
+//     VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
+  }
+
+  // test innerVector()
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    int j0 = ei_random(0,rows-1);
+    int j1 = ei_random(0,rows-1);
+    VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
+    VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
+    //m2.innerVector(j0) = 2*m2.innerVector(j1);
+    //refMat2.col(j0) = 2*refMat2.col(j1);
+    //VERIFY_IS_APPROX(m2, refMat2);
+  }
+  
+  // test innerVectors()
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    int j0 = ei_random(0,rows-2);
+    int j1 = ei_random(0,rows-2);
+    int n0 = ei_random<int>(1,rows-std::max(j0,j1));
+    VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
+    VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+                     refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+    //m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
+    //refMat2.block(0,j0,rows,n0) = refMat2.block(0,j0,rows,n0) + refMat2.block(0,j1,rows,n0);
+  }
+
+  // test transpose
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
+    VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
+  }
+  
+  // test prune
+  {
+    SparseMatrixType m2(rows, rows);
+    DenseMatrix refM2(rows, rows);
+    refM2.setZero();
+    int countFalseNonZero = 0;
+    int countTrueNonZero = 0;
+    m2.startFill();
+    for (int j=0; j<m2.outerSize(); ++j)
+      for (int i=0; i<m2.innerSize(); ++i)
+      {
+        float x = ei_random<float>(0,1);
+        if (x<0.1)
+        {
+          // do nothing
+        }
+        else if (x<0.5)
+        {
+          countFalseNonZero++;
+          m2.fill(i,j) = Scalar(0);
+        }
+        else
+        {
+          countTrueNonZero++;
+          m2.fill(i,j) = refM2(i,j) = Scalar(1);
+        }
+      }
+    m2.endFill();
+    VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
+    VERIFY_IS_APPROX(m2, refM2);
+    m2.prune(1);
+    VERIFY(countTrueNonZero==m2.nonZeros());
+    VERIFY_IS_APPROX(m2, refM2);
+  }
+}
+
+void test_eigen2_sparse_basic()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(8, 8)) );
+    CALL_SUBTEST_2( sparse_basic(SparseMatrix<std::complex<double> >(16, 16)) );
+    CALL_SUBTEST_1( sparse_basic(SparseMatrix<double>(33, 33)) );
+    
+    CALL_SUBTEST_3( sparse_basic(DynamicSparseMatrix<double>(8, 8)) );
+  }
+}
diff --git a/test/eigen2/eigen2_sparse_product.cpp b/test/eigen2/eigen2_sparse_product.cpp
new file mode 100644
index 0000000..d28e76d
--- /dev/null
+++ b/test/eigen2/eigen2_sparse_product.cpp
@@ -0,0 +1,115 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename SparseMatrixType> void sparse_product(const SparseMatrixType& ref)
+{
+  const int rows = ref.rows();
+  const int cols = ref.cols();
+  typedef typename SparseMatrixType::Scalar Scalar;
+  enum { Flags = SparseMatrixType::Flags };
+
+  double density = std::max(8./(rows*cols), 0.01);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+
+  // test matrix-matrix product
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refMat3 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refMat4 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    SparseMatrixType m3(rows, rows);
+    SparseMatrixType m4(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    initSparse<Scalar>(density, refMat3, m3);
+    initSparse<Scalar>(density, refMat4, m4);
+    VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(m4=m2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
+    VERIFY_IS_APPROX(m4=m2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
+    VERIFY_IS_APPROX(m4=m2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
+
+    // sparse * dense
+    VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(dm4=m2*refMat3.transpose(), refMat4=refMat2*refMat3.transpose());
+    VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3, refMat4=refMat2.transpose()*refMat3);
+    VERIFY_IS_APPROX(dm4=m2.transpose()*refMat3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
+
+    // dense * sparse
+    VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(dm4=refMat2*m3.transpose(), refMat4=refMat2*refMat3.transpose());
+    VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3, refMat4=refMat2.transpose()*refMat3);
+    VERIFY_IS_APPROX(dm4=refMat2.transpose()*m3.transpose(), refMat4=refMat2.transpose()*refMat3.transpose());
+
+    VERIFY_IS_APPROX(m3=m3*m3, refMat3=refMat3*refMat3);
+  }
+
+  // test matrix - diagonal product
+  if(false) // it compiles, but the precision is terrible. probably doesn't matter in this branch....
+  {
+    DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
+    DiagonalMatrix<DenseVector> d1(DenseVector::Random(rows));
+    SparseMatrixType m2(rows, rows);
+    SparseMatrixType m3(rows, rows);
+    initSparse<Scalar>(density, refM2, m2);
+    initSparse<Scalar>(density, refM3, m3);
+    VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
+    VERIFY_IS_APPROX(m3=m2.transpose()*d1, refM3=refM2.transpose()*d1);
+    VERIFY_IS_APPROX(m3=d1*m2, refM3=d1*refM2);
+    VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1 * refM2.transpose());
+  }
+
+  // test self adjoint products
+  {
+    DenseMatrix b = DenseMatrix::Random(rows, rows);
+    DenseMatrix x = DenseMatrix::Random(rows, rows);
+    DenseMatrix refX = DenseMatrix::Random(rows, rows);
+    DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refS = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType mUp(rows, rows);
+    SparseMatrixType mLo(rows, rows);
+    SparseMatrixType mS(rows, rows);
+    do {
+      initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
+    } while (refUp.isZero());
+    refLo = refUp.transpose().conjugate();
+    mLo = mUp.transpose().conjugate();
+    refS = refUp + refLo;
+    refS.diagonal() *= 0.5;
+    mS = mUp + mLo;
+    for (int k=0; k<mS.outerSize(); ++k)
+      for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
+        if (it.index() == k)
+          it.valueRef() *= 0.5;
+
+    VERIFY_IS_APPROX(refS.adjoint(), refS);
+    VERIFY_IS_APPROX(mS.transpose().conjugate(), mS);
+    VERIFY_IS_APPROX(mS, refS);
+    VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
+    VERIFY_IS_APPROX(x=mUp.template marked<UpperTriangular|SelfAdjoint>()*b, refX=refS*b);
+    VERIFY_IS_APPROX(x=mLo.template marked<LowerTriangular|SelfAdjoint>()*b, refX=refS*b);
+    VERIFY_IS_APPROX(x=mS.template marked<SelfAdjoint>()*b, refX=refS*b);
+  }
+
+}
+
+void test_eigen2_sparse_product()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(8, 8)) );
+    CALL_SUBTEST_2( sparse_product(SparseMatrix<std::complex<double> >(16, 16)) );
+    CALL_SUBTEST_1( sparse_product(SparseMatrix<double>(33, 33)) );
+
+    CALL_SUBTEST_3( sparse_product(DynamicSparseMatrix<double>(8, 8)) );
+  }
+}
diff --git a/test/eigen2/eigen2_sparse_solvers.cpp b/test/eigen2/eigen2_sparse_solvers.cpp
new file mode 100644
index 0000000..3aef27a
--- /dev/null
+++ b/test/eigen2/eigen2_sparse_solvers.cpp
@@ -0,0 +1,200 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename Scalar> void
+initSPD(double density,
+        Matrix<Scalar,Dynamic,Dynamic>& refMat,
+        SparseMatrix<Scalar>& sparseMat)
+{
+  Matrix<Scalar,Dynamic,Dynamic> aux(refMat.rows(),refMat.cols());
+  initSparse(density,refMat,sparseMat);
+  refMat = refMat * refMat.adjoint();
+  for (int k=0; k<2; ++k)
+  {
+    initSparse(density,aux,sparseMat,ForceNonZeroDiag);
+    refMat += aux * aux.adjoint();
+  }
+  sparseMat.startFill();
+  for (int j=0 ; j<sparseMat.cols(); ++j)
+    for (int i=j ; i<sparseMat.rows(); ++i)
+      if (refMat(i,j)!=Scalar(0))
+        sparseMat.fill(i,j) = refMat(i,j);
+  sparseMat.endFill();
+}
+
+template<typename Scalar> void sparse_solvers(int rows, int cols)
+{
+  double density = std::max(8./(rows*cols), 0.01);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  // Scalar eps = 1e-6;
+
+  DenseVector vec1 = DenseVector::Random(rows);
+
+  std::vector<Vector2i> zeroCoords;
+  std::vector<Vector2i> nonzeroCoords;
+
+  // test triangular solver
+  {
+    DenseVector vec2 = vec1, vec3 = vec1;
+    SparseMatrix<Scalar> m2(rows, cols);
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+
+    // lower
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template marked<LowerTriangular>().solveTriangular(vec2),
+                     m2.template marked<LowerTriangular>().solveTriangular(vec3));
+
+    // lower - transpose
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template marked<LowerTriangular>().transpose().solveTriangular(vec2),
+                     m2.template marked<LowerTriangular>().transpose().solveTriangular(vec3));
+
+    // upper
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template marked<UpperTriangular>().solveTriangular(vec2),
+                     m2.template marked<UpperTriangular>().solveTriangular(vec3));
+
+    // upper - transpose
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template marked<UpperTriangular>().transpose().solveTriangular(vec2),
+                     m2.template marked<UpperTriangular>().transpose().solveTriangular(vec3));
+  }
+
+  // test LLT
+  {
+    // TODO fix the issue with complex (see SparseLLT::solveInPlace)
+    SparseMatrix<Scalar> m2(rows, cols);
+    DenseMatrix refMat2(rows, cols);
+
+    DenseVector b = DenseVector::Random(cols);
+    DenseVector refX(cols), x(cols);
+
+    initSPD(density, refMat2, m2);
+
+    refMat2.llt().solve(b, &refX);
+    typedef SparseMatrix<Scalar,LowerTriangular|SelfAdjoint> SparseSelfAdjointMatrix;
+    if (!NumTraits<Scalar>::IsComplex)
+    {
+      x = b;
+      SparseLLT<SparseSelfAdjointMatrix> (m2).solveInPlace(x);
+      VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: default");
+    }
+    #ifdef EIGEN_CHOLMOD_SUPPORT
+    x = b;
+    SparseLLT<SparseSelfAdjointMatrix,Cholmod>(m2).solveInPlace(x);
+    VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: cholmod");
+    #endif
+    if (!NumTraits<Scalar>::IsComplex)
+    {
+      #ifdef EIGEN_TAUCS_SUPPORT
+      x = b;
+      SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,IncompleteFactorization).solveInPlace(x);
+      VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (IncompleteFactorization)");
+      x = b;
+      SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,SupernodalMultifrontal).solveInPlace(x);
+      VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (SupernodalMultifrontal)");
+      x = b;
+      SparseLLT<SparseSelfAdjointMatrix,Taucs>(m2,SupernodalLeftLooking).solveInPlace(x);
+      VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LLT: taucs (SupernodalLeftLooking)");
+      #endif
+    }
+  }
+
+  // test LDLT
+  if (!NumTraits<Scalar>::IsComplex)
+  {
+    // TODO fix the issue with complex (see SparseLDLT::solveInPlace)
+    SparseMatrix<Scalar> m2(rows, cols);
+    DenseMatrix refMat2(rows, cols);
+
+    DenseVector b = DenseVector::Random(cols);
+    DenseVector refX(cols), x(cols);
+
+    //initSPD(density, refMat2, m2);
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, 0, 0);
+    refMat2 += refMat2.adjoint();
+    refMat2.diagonal() *= 0.5;
+
+    refMat2.ldlt().solve(b, &refX);
+    typedef SparseMatrix<Scalar,UpperTriangular|SelfAdjoint> SparseSelfAdjointMatrix;
+    x = b;
+    SparseLDLT<SparseSelfAdjointMatrix> ldlt(m2);
+    if (ldlt.succeeded())
+      ldlt.solveInPlace(x);
+    VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LDLT: default");
+  }
+
+  // test LU
+  {
+    static int count = 0;
+    SparseMatrix<Scalar> m2(rows, cols);
+    DenseMatrix refMat2(rows, cols);
+
+    DenseVector b = DenseVector::Random(cols);
+    DenseVector refX(cols), x(cols);
+
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag, &zeroCoords, &nonzeroCoords);
+
+    LU<DenseMatrix> refLu(refMat2);
+    refLu.solve(b, &refX);
+    #if defined(EIGEN_SUPERLU_SUPPORT) || defined(EIGEN_UMFPACK_SUPPORT)
+    Scalar refDet = refLu.determinant();
+    #endif
+    x.setZero();
+    // // SparseLU<SparseMatrix<Scalar> > (m2).solve(b,&x);
+    // // VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: default");
+    #ifdef EIGEN_SUPERLU_SUPPORT
+    {
+      x.setZero();
+      SparseLU<SparseMatrix<Scalar>,SuperLU> slu(m2);
+      if (slu.succeeded())
+      {
+        if (slu.solve(b,&x)) {
+          VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: SuperLU");
+        }
+        // std::cerr << refDet << " == " << slu.determinant() << "\n";
+        if (count==0) {
+          VERIFY_IS_APPROX(refDet,slu.determinant()); // FIXME det is not very stable for complex
+        }
+      }
+    }
+    #endif
+    #ifdef EIGEN_UMFPACK_SUPPORT
+    {
+      // check solve
+      x.setZero();
+      SparseLU<SparseMatrix<Scalar>,UmfPack> slu(m2);
+      if (slu.succeeded()) {
+        if (slu.solve(b,&x)) {
+          if (count==0) {
+            VERIFY(refX.isApprox(x,test_precision<Scalar>()) && "LU: umfpack");  // FIXME solve is not very stable for complex
+          }
+        }
+        VERIFY_IS_APPROX(refDet,slu.determinant());
+        // TODO check the extracted data
+        //std::cerr << slu.matrixL() << "\n";
+      }
+    }
+    #endif
+    count++;
+  }
+
+}
+
+void test_eigen2_sparse_solvers()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( sparse_solvers<double>(8, 8) );
+    CALL_SUBTEST_2( sparse_solvers<std::complex<double> >(16, 16) );
+    CALL_SUBTEST_1( sparse_solvers<double>(101, 101) );
+  }
+}
diff --git a/test/eigen2/eigen2_sparse_vector.cpp b/test/eigen2/eigen2_sparse_vector.cpp
new file mode 100644
index 0000000..e6d2d77
--- /dev/null
+++ b/test/eigen2/eigen2_sparse_vector.cpp
@@ -0,0 +1,84 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename Scalar> void sparse_vector(int rows, int cols)
+{
+  double densityMat = std::max(8./(rows*cols), 0.01);
+  double densityVec = std::max(8./float(rows), 0.1);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  typedef SparseVector<Scalar> SparseVectorType;
+  typedef SparseMatrix<Scalar> SparseMatrixType;
+  Scalar eps = 1e-6;
+
+  SparseMatrixType m1(rows,cols);
+  SparseVectorType v1(rows), v2(rows), v3(rows);
+  DenseMatrix refM1 = DenseMatrix::Zero(rows, cols);
+  DenseVector refV1 = DenseVector::Random(rows),
+    refV2 = DenseVector::Random(rows),
+    refV3 = DenseVector::Random(rows);
+
+  std::vector<int> zerocoords, nonzerocoords;
+  initSparse<Scalar>(densityVec, refV1, v1, &zerocoords, &nonzerocoords);
+  initSparse<Scalar>(densityMat, refM1, m1);
+
+  initSparse<Scalar>(densityVec, refV2, v2);
+  initSparse<Scalar>(densityVec, refV3, v3);
+
+  Scalar s1 = ei_random<Scalar>();
+
+  // test coeff and coeffRef
+  for (unsigned int i=0; i<zerocoords.size(); ++i)
+  {
+    VERIFY_IS_MUCH_SMALLER_THAN( v1.coeff(zerocoords[i]), eps );
+    //VERIFY_RAISES_ASSERT( v1.coeffRef(zerocoords[i]) = 5 );
+  }
+  {
+    VERIFY(int(nonzerocoords.size()) == v1.nonZeros());
+    int j=0;
+    for (typename SparseVectorType::InnerIterator it(v1); it; ++it,++j)
+    {
+      VERIFY(nonzerocoords[j]==it.index());
+      VERIFY(it.value()==v1.coeff(it.index()));
+      VERIFY(it.value()==refV1.coeff(it.index()));
+    }
+  }
+  VERIFY_IS_APPROX(v1, refV1);
+
+  v1.coeffRef(nonzerocoords[0]) = Scalar(5);
+  refV1.coeffRef(nonzerocoords[0]) = Scalar(5);
+  VERIFY_IS_APPROX(v1, refV1);
+
+  VERIFY_IS_APPROX(v1+v2, refV1+refV2);
+  VERIFY_IS_APPROX(v1+v2+v3, refV1+refV2+refV3);
+
+  VERIFY_IS_APPROX(v1*s1-v2, refV1*s1-refV2);
+
+  VERIFY_IS_APPROX(v1*=s1, refV1*=s1);
+  VERIFY_IS_APPROX(v1/=s1, refV1/=s1);
+  
+  VERIFY_IS_APPROX(v1+=v2, refV1+=refV2);
+  VERIFY_IS_APPROX(v1-=v2, refV1-=refV2);
+
+  VERIFY_IS_APPROX(v1.eigen2_dot(v2), refV1.eigen2_dot(refV2));
+  VERIFY_IS_APPROX(v1.eigen2_dot(refV2), refV1.eigen2_dot(refV2));
+
+}
+
+void test_eigen2_sparse_vector()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( sparse_vector<double>(8, 8) );
+    CALL_SUBTEST_2( sparse_vector<std::complex<double> >(16, 16) );
+    CALL_SUBTEST_1( sparse_vector<double>(299, 535) );
+  }
+}
+
diff --git a/test/eigen2/eigen2_stdvector.cpp b/test/eigen2/eigen2_stdvector.cpp
new file mode 100644
index 0000000..6ab05c2
--- /dev/null
+++ b/test/eigen2/eigen2_stdvector.cpp
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <Eigen/StdVector>
+#include "main.h"
+#include <Eigen/Geometry>
+
+template<typename MatrixType>
+void check_stdvector_matrix(const MatrixType& m)
+{
+  int rows = m.rows();
+  int cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::vector<MatrixType, aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_stdvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::vector<TransformType, aligned_allocator<TransformType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_stdvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::vector<QuaternionType, aligned_allocator<QuaternionType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((std::size_t)&(v[22]) == (std::size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_eigen2_stdvector()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix2f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Vector4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stdvector_transform(Transform2f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Transform3f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Transform3d()));
+  //CALL_SUBTEST_4(check_stdvector_transform(Transform4d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
+}
diff --git a/test/eigen2/eigen2_submatrices.cpp b/test/eigen2/eigen2_submatrices.cpp
new file mode 100644
index 0000000..dee970b
--- /dev/null
+++ b/test/eigen2/eigen2_submatrices.cpp
@@ -0,0 +1,142 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+// check minor separately in order to avoid the possible creation of a zero-sized
+// array. Comes from a compilation error with gcc-3.4 or gcc-4 with -ansi -pedantic.
+// Another solution would be to declare the array like this: T m_data[Size==0?1:Size]; in ei_matrix_storage
+// but this is probably not bad to raise such an error at compile time...
+template<typename Scalar, int _Rows, int _Cols> struct CheckMinor
+{
+    typedef Matrix<Scalar, _Rows, _Cols> MatrixType;
+    CheckMinor(MatrixType& m1, int r1, int c1)
+    {
+        int rows = m1.rows();
+        int cols = m1.cols();
+
+        Matrix<Scalar, Dynamic, Dynamic> mi = m1.minor(0,0).eval();
+        VERIFY_IS_APPROX(mi, m1.block(1,1,rows-1,cols-1));
+        mi = m1.minor(r1,c1);
+        VERIFY_IS_APPROX(mi.transpose(), m1.transpose().minor(c1,r1));
+        //check operator(), both constant and non-constant, on minor()
+        m1.minor(r1,c1)(0,0) = m1.minor(0,0)(0,0);
+    }
+};
+
+template<typename Scalar> struct CheckMinor<Scalar,1,1>
+{
+    typedef Matrix<Scalar, 1, 1> MatrixType;
+    CheckMinor(MatrixType&, int, int) {}
+};
+
+template<typename MatrixType> void submatrices(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Row.h Column.h Block.h Minor.h DiagonalCoeffs.h
+  */
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             ones = MatrixType::Ones(rows, cols),
+             square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
+                              ::Random(rows, rows);
+  VectorType v1 = VectorType::Random(rows);
+
+  Scalar s1 = ei_random<Scalar>();
+
+  int r1 = ei_random<int>(0,rows-1);
+  int r2 = ei_random<int>(r1,rows-1);
+  int c1 = ei_random<int>(0,cols-1);
+  int c2 = ei_random<int>(c1,cols-1);
+
+  //check row() and col()
+  VERIFY_IS_APPROX(m1.col(c1).transpose(), m1.transpose().row(c1));
+  VERIFY_IS_APPROX(square.row(r1).eigen2_dot(m1.col(c1)), (square.lazy() * m1.conjugate())(r1,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);
+
+  //check block()
+  Matrix<Scalar,Dynamic,Dynamic> b1(1,1); b1(0,0) = m1(r1,c1);
+  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);
+  //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);
+
+  //check minor()
+  CheckMinor<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> checkminor(m1,r1,c1);
+
+  //check diagonal()
+  VERIFY_IS_APPROX(m1.diagonal(), m1.transpose().diagonal());
+  m2.diagonal() = 2 * m1.diagonal();
+  m2.diagonal()[0] *= 3;
+  VERIFY_IS_APPROX(m2.diagonal()[0], static_cast<Scalar>(6) * m1.diagonal()[0]);
+
+  enum {
+    BlockRows = EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::RowsAtCompileTime,2),
+    BlockCols = EIGEN_SIZE_MIN_PREFER_FIXED(MatrixType::ColsAtCompileTime,5)
+  };
+  if (rows>=5 && cols>=8)
+  {
+    // test fixed block() as lvalue
+    m1.template block<BlockRows,BlockCols>(1,1) *= s1;
+    // test operator() on fixed block() both as constant and non-constant
+    m1.template block<BlockRows,BlockCols>(1,1)(0, 3) = m1.template block<2,5>(1,1)(1,2);
+    // check that fixed block() and block() agree
+    Matrix<Scalar,Dynamic,Dynamic> b = m1.template block<BlockRows,BlockCols>(3,3);
+    VERIFY_IS_APPROX(b, m1.block(3,3,BlockRows,BlockCols));
+  }
+
+  if (rows>2)
+  {
+    // test sub vectors
+    VERIFY_IS_APPROX(v1.template start<2>(), v1.block(0,0,2,1));
+    VERIFY_IS_APPROX(v1.template start<2>(), v1.start(2));
+    VERIFY_IS_APPROX(v1.template start<2>(), v1.segment(0,2));
+    VERIFY_IS_APPROX(v1.template start<2>(), v1.template segment<2>(0));
+    int i = rows-2;
+    VERIFY_IS_APPROX(v1.template end<2>(), v1.block(i,0,2,1));
+    VERIFY_IS_APPROX(v1.template end<2>(), v1.end(2));
+    VERIFY_IS_APPROX(v1.template end<2>(), v1.segment(i,2));
+    VERIFY_IS_APPROX(v1.template end<2>(), v1.template segment<2>(i));
+    i = ei_random(0,rows-2);
+    VERIFY_IS_APPROX(v1.segment(i,2), v1.template segment<2>(i));
+  }
+
+  // stress some basic stuffs with block matrices
+  VERIFY(ei_real(ones.col(c1).sum()) == RealScalar(rows));
+  VERIFY(ei_real(ones.row(r1).sum()) == RealScalar(cols));
+
+  VERIFY(ei_real(ones.col(c1).eigen2_dot(ones.col(c2))) == RealScalar(rows));
+  VERIFY(ei_real(ones.row(r1).eigen2_dot(ones.row(r2))) == RealScalar(cols));
+}
+
+void test_eigen2_submatrices()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( submatrices(Matrix<float, 1, 1>()) );
+    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)) );
+  }
+}
diff --git a/test/eigen2/eigen2_sum.cpp b/test/eigen2/eigen2_sum.cpp
new file mode 100644
index 0000000..b47057c
--- /dev/null
+++ b/test/eigen2/eigen2_sum.cpp
@@ -0,0 +1,71 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void matrixSum(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols);
+
+  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
+  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
+  Scalar x = Scalar(0);
+  for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) x += m1(i,j);
+  VERIFY_IS_APPROX(m1.sum(), x);
+}
+
+template<typename VectorType> void vectorSum(const VectorType& w)
+{
+  typedef typename VectorType::Scalar Scalar;
+  int size = w.size();
+
+  VectorType v = VectorType::Random(size);
+  for(int i = 1; i < size; i++)
+  {
+    Scalar s = Scalar(0);
+    for(int j = 0; j < i; j++) s += v[j];
+    VERIFY_IS_APPROX(s, v.start(i).sum());
+  }
+
+  for(int i = 0; i < size-1; i++)
+  {
+    Scalar s = Scalar(0);
+    for(int j = i; j < size; j++) s += v[j];
+    VERIFY_IS_APPROX(s, v.end(size-i).sum());
+  }
+
+  for(int i = 0; i < size/2; i++)
+  {
+    Scalar s = Scalar(0);
+    for(int j = i; j < size-i; j++) s += v[j];
+    VERIFY_IS_APPROX(s, v.segment(i, size-2*i).sum());
+  }
+}
+
+void test_eigen2_sum()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( matrixSum(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( matrixSum(Matrix2f()) );
+    CALL_SUBTEST_3( matrixSum(Matrix4d()) );
+    CALL_SUBTEST_4( matrixSum(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_5( matrixSum(MatrixXf(8, 12)) );
+    CALL_SUBTEST_6( matrixSum(MatrixXi(8, 12)) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_5( vectorSum(VectorXf(5)) );
+    CALL_SUBTEST_7( vectorSum(VectorXd(10)) );
+    CALL_SUBTEST_5( vectorSum(VectorXf(33)) );
+  }
+}
diff --git a/test/eigen2/eigen2_svd.cpp b/test/eigen2/eigen2_svd.cpp
new file mode 100644
index 0000000..d4689a5
--- /dev/null
+++ b/test/eigen2/eigen2_svd.cpp
@@ -0,0 +1,87 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/SVD>
+
+template<typename MatrixType> void svd(const MatrixType& m)
+{
+  /* this test covers the following files:
+     SVD.h
+  */
+  int rows = m.rows();
+  int cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  MatrixType a = MatrixType::Random(rows,cols);
+  Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> b =
+    Matrix<Scalar, MatrixType::RowsAtCompileTime, 1>::Random(rows,1);
+  Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> x(cols,1), x2(cols,1);
+
+  RealScalar largerEps = test_precision<RealScalar>();
+  if (ei_is_same_type<RealScalar,float>::ret)
+    largerEps = 1e-3f;
+
+  {
+    SVD<MatrixType> svd(a);
+    MatrixType sigma = MatrixType::Zero(rows,cols);
+    MatrixType matU  = MatrixType::Zero(rows,rows);
+    sigma.block(0,0,cols,cols) = svd.singularValues().asDiagonal();
+    matU.block(0,0,rows,cols) = svd.matrixU();
+    VERIFY_IS_APPROX(a, matU * sigma * svd.matrixV().transpose());
+  }
+
+
+  if (rows==cols)
+  {
+    if (ei_is_same_type<RealScalar,float>::ret)
+    {
+      MatrixType a1 = MatrixType::Random(rows,cols);
+      a += a * a.adjoint() + a1 * a1.adjoint();
+    }
+    SVD<MatrixType> svd(a);
+    svd.solve(b, &x);
+    VERIFY_IS_APPROX(a * x,b);
+  }
+
+
+  if(rows==cols)
+  {
+    SVD<MatrixType> svd(a);
+    MatrixType unitary, positive;
+    svd.computeUnitaryPositive(&unitary, &positive);
+    VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
+    VERIFY_IS_APPROX(positive, positive.adjoint());
+    for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
+    VERIFY_IS_APPROX(unitary*positive, a);
+
+    svd.computePositiveUnitary(&positive, &unitary);
+    VERIFY_IS_APPROX(unitary * unitary.adjoint(), MatrixType::Identity(unitary.rows(),unitary.rows()));
+    VERIFY_IS_APPROX(positive, positive.adjoint());
+    for(int i = 0; i < rows; i++) VERIFY(positive.diagonal()[i] >= 0); // cheap necessary (not sufficient) condition for positivity
+    VERIFY_IS_APPROX(positive*unitary, a);
+  }
+}
+
+void test_eigen2_svd()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( svd(Matrix3f()) );
+    CALL_SUBTEST_2( svd(Matrix4d()) );
+    CALL_SUBTEST_3( svd(MatrixXf(7,7)) );
+    CALL_SUBTEST_4( svd(MatrixXd(14,7)) );
+    // complex are not implemented yet
+//     CALL_SUBTEST( svd(MatrixXcd(6,6)) );
+//     CALL_SUBTEST( svd(MatrixXcf(3,3)) );
+    SVD<MatrixXf> s;
+    MatrixXf m = MatrixXf::Random(10,1);
+    s.compute(m);
+  }
+}
diff --git a/test/eigen2/eigen2_swap.cpp b/test/eigen2/eigen2_swap.cpp
new file mode 100644
index 0000000..f3a8846
--- /dev/null
+++ b/test/eigen2/eigen2_swap.cpp
@@ -0,0 +1,83 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "main.h"
+
+template<typename T>
+struct other_matrix_type
+{
+  typedef int type;
+};
+
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+struct other_matrix_type<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+  typedef Matrix<_Scalar, _Rows, _Cols, _Options^RowMajor, _MaxRows, _MaxCols> type;
+};
+
+template<typename MatrixType> void swap(const MatrixType& m)
+{
+  typedef typename other_matrix_type<MatrixType>::type OtherMatrixType;
+  typedef typename MatrixType::Scalar Scalar;
+
+  ei_assert((!ei_is_same_type<MatrixType,OtherMatrixType>::ret));
+  int rows = m.rows();
+  int cols = m.cols();
+  
+  // construct 3 matrix guaranteed to be distinct
+  MatrixType m1 = MatrixType::Random(rows,cols);
+  MatrixType m2 = MatrixType::Random(rows,cols) + Scalar(100) * MatrixType::Identity(rows,cols);
+  OtherMatrixType m3 = OtherMatrixType::Random(rows,cols) + Scalar(200) * OtherMatrixType::Identity(rows,cols);
+  
+  MatrixType m1_copy = m1;
+  MatrixType m2_copy = m2;
+  OtherMatrixType m3_copy = m3;
+  
+  // test swapping 2 matrices of same type
+  m1.swap(m2);
+  VERIFY_IS_APPROX(m1,m2_copy);
+  VERIFY_IS_APPROX(m2,m1_copy);
+  m1 = m1_copy;
+  m2 = m2_copy;
+  
+  // test swapping 2 matrices of different types
+  m1.swap(m3);
+  VERIFY_IS_APPROX(m1,m3_copy);
+  VERIFY_IS_APPROX(m3,m1_copy);
+  m1 = m1_copy;
+  m3 = m3_copy;
+  
+  // test swapping matrix with expression
+  m1.swap(m2.block(0,0,rows,cols));
+  VERIFY_IS_APPROX(m1,m2_copy);
+  VERIFY_IS_APPROX(m2,m1_copy);
+  m1 = m1_copy;
+  m2 = m2_copy;
+
+  // test swapping two expressions of different types
+  m1.transpose().swap(m3.transpose());
+  VERIFY_IS_APPROX(m1,m3_copy);
+  VERIFY_IS_APPROX(m3,m1_copy);
+  m1 = m1_copy;
+  m3 = m3_copy;
+  
+  // test assertion on mismatching size -- matrix case
+  VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
+  // test assertion on mismatching size -- xpr case
+  VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
+}
+
+void test_eigen2_swap()
+{
+  CALL_SUBTEST_1( swap(Matrix3f()) ); // fixed size, no vectorization 
+  CALL_SUBTEST_1( swap(Matrix4d()) ); // fixed size, possible vectorization 
+  CALL_SUBTEST_1( swap(MatrixXd(3,3)) ); // dyn size, no vectorization 
+  CALL_SUBTEST_1( swap(MatrixXf(30,30)) ); // dyn size, possible vectorization 
+}
diff --git a/test/eigen2/eigen2_triangular.cpp b/test/eigen2/eigen2_triangular.cpp
new file mode 100644
index 0000000..6f17b7d
--- /dev/null
+++ b/test/eigen2/eigen2_triangular.cpp
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void triangular(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             m4(rows, cols),
+             r1(rows, cols),
+             r2(rows, cols);
+
+  MatrixType m1up = m1.template part<Eigen::UpperTriangular>();
+  MatrixType m2up = m2.template part<Eigen::UpperTriangular>();
+
+  if (rows*cols>1)
+  {
+    VERIFY(m1up.isUpperTriangular());
+    VERIFY(m2up.transpose().isLowerTriangular());
+    VERIFY(!m2.isLowerTriangular());
+  }
+
+//   VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
+
+  // test overloaded operator+=
+  r1.setZero();
+  r2.setZero();
+  r1.template part<Eigen::UpperTriangular>() +=  m1;
+  r2 += m1up;
+  VERIFY_IS_APPROX(r1,r2);
+
+  // test overloaded operator=
+  m1.setZero();
+  m1.template part<Eigen::UpperTriangular>() = (m2.transpose() * m2).lazy();
+  m3 = m2.transpose() * m2;
+  VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>().transpose(), m1);
+
+  // test overloaded operator=
+  m1.setZero();
+  m1.template part<Eigen::LowerTriangular>() = (m2.transpose() * m2).lazy();
+  VERIFY_IS_APPROX(m3.template part<Eigen::LowerTriangular>(), m1);
+
+  VERIFY_IS_APPROX(m3.template part<Diagonal>(), m3.diagonal().asDiagonal());
+
+  m1 = MatrixType::Random(rows, cols);
+  for (int i=0; i<rows; ++i)
+    while (ei_abs2(m1(i,i))<1e-3) m1(i,i) = ei_random<Scalar>();
+
+  Transpose<MatrixType> trm4(m4);
+  // test back and forward subsitution
+  m3 = m1.template part<Eigen::LowerTriangular>();
+  VERIFY(m3.template marked<Eigen::LowerTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
+  VERIFY(m3.transpose().template marked<Eigen::UpperTriangular>()
+    .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
+  // check M * inv(L) using in place API
+  m4 = m3;
+  m3.transpose().template marked<Eigen::UpperTriangular>().solveTriangularInPlace(trm4);
+  VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
+
+  m3 = m1.template part<Eigen::UpperTriangular>();
+  VERIFY(m3.template marked<Eigen::UpperTriangular>().solveTriangular(m3).cwise().abs().isIdentity(test_precision<RealScalar>()));
+  VERIFY(m3.transpose().template marked<Eigen::LowerTriangular>()
+    .solveTriangular(m3.transpose()).cwise().abs().isIdentity(test_precision<RealScalar>()));
+  // check M * inv(U) using in place API
+  m4 = m3;
+  m3.transpose().template marked<Eigen::LowerTriangular>().solveTriangularInPlace(trm4);
+  VERIFY(m4.cwise().abs().isIdentity(test_precision<RealScalar>()));
+
+  m3 = m1.template part<Eigen::UpperTriangular>();
+  VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::UpperTriangular>().solveTriangular(m2)), largerEps));
+  m3 = m1.template part<Eigen::LowerTriangular>();
+  VERIFY(m2.isApprox(m3 * (m3.template marked<Eigen::LowerTriangular>().solveTriangular(m2)), largerEps));
+
+  VERIFY((m1.template part<Eigen::UpperTriangular>() * m2.template part<Eigen::UpperTriangular>()).isUpperTriangular());
+
+  // test swap
+  m1.setOnes();
+  m2.setZero();
+  m2.template part<Eigen::UpperTriangular>().swap(m1);
+  m3.setZero();
+  m3.template part<Eigen::UpperTriangular>().setOnes();
+  VERIFY_IS_APPROX(m2,m3);
+
+}
+
+void selfadjoint()
+{
+  Matrix2i m;
+  m << 1, 2,
+       3, 4;
+
+  Matrix2i m1 = Matrix2i::Zero();
+  m1.part<SelfAdjoint>() = m;
+  Matrix2i ref1;
+  ref1 << 1, 2,
+          2, 4;
+  VERIFY(m1 == ref1);
+  
+  Matrix2i m2 = Matrix2i::Zero();
+  m2.part<SelfAdjoint>() = m.part<UpperTriangular>();
+  Matrix2i ref2;
+  ref2 << 1, 2,
+          2, 4;
+  VERIFY(m2 == ref2);
+ 
+  Matrix2i m3 = Matrix2i::Zero();
+  m3.part<SelfAdjoint>() = m.part<LowerTriangular>();
+  Matrix2i ref3;
+  ref3 << 1, 0,
+          0, 4;
+  VERIFY(m3 == ref3);
+  
+  // example inspired from bug 159
+  int array[] = {1, 2, 3, 4};
+  Matrix2i::Map(array).part<SelfAdjoint>() = Matrix2i::Random().part<LowerTriangular>();
+  
+  std::cout << "hello\n" << array << std::endl;
+}
+
+void test_eigen2_triangular()
+{
+  CALL_SUBTEST_8( selfadjoint() );
+  for(int i = 0; i < g_repeat ; i++) {
+    CALL_SUBTEST_1( triangular(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( triangular(Matrix<float, 2, 2>()) );
+    CALL_SUBTEST_3( triangular(Matrix3d()) );
+    CALL_SUBTEST_4( triangular(MatrixXcf(4, 4)) );
+    CALL_SUBTEST_5( triangular(Matrix<std::complex<float>,8, 8>()) );
+    CALL_SUBTEST_6( triangular(MatrixXd(17,17)) );
+    CALL_SUBTEST_7( triangular(Matrix<float,Dynamic,Dynamic,RowMajor>(5, 5)) );
+  }
+}
diff --git a/test/eigen2/eigen2_unalignedassert.cpp b/test/eigen2/eigen2_unalignedassert.cpp
new file mode 100644
index 0000000..d10b6f5
--- /dev/null
+++ b/test/eigen2/eigen2_unalignedassert.cpp
@@ -0,0 +1,116 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+struct Good1
+{
+  MatrixXd m; // good: m will allocate its own array, taking care of alignment.
+  Good1() : m(20,20) {}
+};
+
+struct Good2
+{
+  Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be aligned
+};
+
+struct Good3
+{
+  Vector2f m; // good: same reason
+};
+
+struct Bad4
+{
+  Vector2d m; // bad: sizeof(m)%16==0 so alignment is required
+};
+
+struct Bad5
+{
+  Matrix<float, 2, 6> m; // bad: same reason
+};
+
+struct Bad6
+{
+  Matrix<double, 3, 4> m; // bad: same reason
+};
+
+struct Good7
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  Vector2d m;
+  float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects
+};
+
+struct Good8
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  float f; // try the f at first -- the EIGEN_ALIGN_128 attribute of m should make that still work
+  Matrix4f m;
+};
+
+struct Good9
+{
+  Matrix<float,2,2,DontAlign> m; // good: no alignment requested
+  float f;
+};
+
+template<bool Align> struct Depends
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align)
+  Vector2d m;
+  float f;
+};
+
+template<typename T>
+void check_unalignedassert_good()
+{
+  T *x, *y;
+  x = new T;
+  delete x;
+  y = new T[2];
+  delete[] y;
+}
+
+#if EIGEN_ARCH_WANTS_ALIGNMENT
+template<typename T>
+void check_unalignedassert_bad()
+{
+  float buf[sizeof(T)+16];
+  float *unaligned = buf;
+  while((reinterpret_cast<std::size_t>(unaligned)&0xf)==0) ++unaligned; // make sure unaligned is really unaligned
+  T *x = ::new(static_cast<void*>(unaligned)) T;
+  x->~T();
+}
+#endif
+
+void unalignedassert()
+{
+  check_unalignedassert_good<Good1>();
+  check_unalignedassert_good<Good2>();
+  check_unalignedassert_good<Good3>();
+#if EIGEN_ARCH_WANTS_ALIGNMENT
+  VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad4>());
+  VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad5>());
+  VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Bad6>());
+#endif
+
+  check_unalignedassert_good<Good7>();
+  check_unalignedassert_good<Good8>();
+  check_unalignedassert_good<Good9>();
+  check_unalignedassert_good<Depends<true> >();
+
+#if EIGEN_ARCH_WANTS_ALIGNMENT
+  VERIFY_RAISES_ASSERT(check_unalignedassert_bad<Depends<false> >());
+#endif
+}
+
+void test_eigen2_unalignedassert()
+{
+  CALL_SUBTEST(unalignedassert());
+}
diff --git a/test/eigen2/eigen2_visitor.cpp b/test/eigen2/eigen2_visitor.cpp
new file mode 100644
index 0000000..4781991
--- /dev/null
+++ b/test/eigen2/eigen2_visitor.cpp
@@ -0,0 +1,116 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void matrixVisitor(const MatrixType& p)
+{
+  typedef typename MatrixType::Scalar Scalar;
+
+  int rows = p.rows();
+  int cols = p.cols();
+
+  // construct a random matrix where all coefficients are different
+  MatrixType m;
+  m = MatrixType::Random(rows, cols);
+  for(int i = 0; i < m.size(); i++)
+    for(int i2 = 0; i2 < i; i2++)
+      while(m(i) == m(i2)) // yes, ==
+        m(i) = ei_random<Scalar>();
+  
+  Scalar minc = Scalar(1000), maxc = Scalar(-1000);
+  int minrow=0,mincol=0,maxrow=0,maxcol=0;
+  for(int j = 0; j < cols; j++)
+  for(int i = 0; i < rows; i++)
+  {
+    if(m(i,j) < minc)
+    {
+      minc = m(i,j);
+      minrow = i;
+      mincol = j;
+    }
+    if(m(i,j) > maxc)
+    {
+      maxc = m(i,j);
+      maxrow = i;
+      maxcol = j;
+    }
+  }
+  int eigen_minrow, eigen_mincol, eigen_maxrow, eigen_maxcol;
+  Scalar eigen_minc, eigen_maxc;
+  eigen_minc = m.minCoeff(&eigen_minrow,&eigen_mincol);
+  eigen_maxc = m.maxCoeff(&eigen_maxrow,&eigen_maxcol);
+  VERIFY(minrow == eigen_minrow);
+  VERIFY(maxrow == eigen_maxrow);
+  VERIFY(mincol == eigen_mincol);
+  VERIFY(maxcol == eigen_maxcol);
+  VERIFY_IS_APPROX(minc, eigen_minc);
+  VERIFY_IS_APPROX(maxc, eigen_maxc);
+  VERIFY_IS_APPROX(minc, m.minCoeff());
+  VERIFY_IS_APPROX(maxc, m.maxCoeff());
+}
+
+template<typename VectorType> void vectorVisitor(const VectorType& w)
+{
+  typedef typename VectorType::Scalar Scalar;
+
+  int size = w.size();
+
+  // construct a random vector where all coefficients are different
+  VectorType v;
+  v = VectorType::Random(size);
+  for(int i = 0; i < size; i++)
+    for(int i2 = 0; i2 < i; i2++)
+      while(v(i) == v(i2)) // yes, ==
+        v(i) = ei_random<Scalar>();
+  
+  Scalar minc = Scalar(1000), maxc = Scalar(-1000);
+  int minidx=0,maxidx=0;
+  for(int i = 0; i < size; i++)
+  {
+    if(v(i) < minc)
+    {
+      minc = v(i);
+      minidx = i;
+    }
+    if(v(i) > maxc)
+    {
+      maxc = v(i);
+      maxidx = i;
+    }
+  }
+  int eigen_minidx, eigen_maxidx;
+  Scalar eigen_minc, eigen_maxc;
+  eigen_minc = v.minCoeff(&eigen_minidx);
+  eigen_maxc = v.maxCoeff(&eigen_maxidx);
+  VERIFY(minidx == eigen_minidx);
+  VERIFY(maxidx == eigen_maxidx);
+  VERIFY_IS_APPROX(minc, eigen_minc);
+  VERIFY_IS_APPROX(maxc, eigen_maxc);
+  VERIFY_IS_APPROX(minc, v.minCoeff());
+  VERIFY_IS_APPROX(maxc, v.maxCoeff());
+}
+
+void test_eigen2_visitor()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( matrixVisitor(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( matrixVisitor(Matrix2f()) );
+    CALL_SUBTEST_3( matrixVisitor(Matrix4d()) );
+    CALL_SUBTEST_4( matrixVisitor(MatrixXd(8, 12)) );
+    CALL_SUBTEST_5( matrixVisitor(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 20)) );
+    CALL_SUBTEST_6( matrixVisitor(MatrixXi(8, 12)) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_7( vectorVisitor(Vector4f()) );
+    CALL_SUBTEST_4( vectorVisitor(VectorXd(10)) );
+    CALL_SUBTEST_4( vectorVisitor(RowVectorXd(10)) );
+    CALL_SUBTEST_8( vectorVisitor(VectorXf(33)) );
+  }
+}
diff --git a/test/eigen2/gsl_helper.h b/test/eigen2/gsl_helper.h
new file mode 100644
index 0000000..d1d8545
--- /dev/null
+++ b/test/eigen2/gsl_helper.h
@@ -0,0 +1,175 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_GSL_HELPER
+#define EIGEN_GSL_HELPER
+
+#include <Eigen/Core>
+
+#include <gsl/gsl_blas.h>
+#include <gsl/gsl_multifit.h>
+#include <gsl/gsl_eigen.h>
+#include <gsl/gsl_linalg.h>
+#include <gsl/gsl_complex.h>
+#include <gsl/gsl_complex_math.h>
+
+namespace Eigen {
+
+template<typename Scalar, bool IsComplex = NumTraits<Scalar>::IsComplex> struct GslTraits
+{
+  typedef gsl_matrix* Matrix;
+  typedef gsl_vector* Vector;
+  static Matrix createMatrix(int rows, int cols) { return gsl_matrix_alloc(rows,cols); }
+  static Vector createVector(int size) { return gsl_vector_alloc(size); }
+  static void free(Matrix& m) { gsl_matrix_free(m); m=0; }
+  static void free(Vector& m) { gsl_vector_free(m); m=0; }
+  static void prod(const Matrix& m, const Vector& v, Vector& x) { gsl_blas_dgemv(CblasNoTrans,1,m,v,0,x); }
+  static void cholesky(Matrix& m) { gsl_linalg_cholesky_decomp(m); }
+  static void cholesky_solve(const Matrix& m, const Vector& b, Vector& x) { gsl_linalg_cholesky_solve(m,b,x); }
+  static void eigen_symm(const Matrix& m, Vector& eval, Matrix& evec)
+  {
+    gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc(m->size1);
+    Matrix a = createMatrix(m->size1, m->size2);
+    gsl_matrix_memcpy(a, m);
+    gsl_eigen_symmv(a,eval,evec,w);
+    gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
+    gsl_eigen_symmv_free(w);
+    free(a);
+  }
+  static void eigen_symm_gen(const Matrix& m, const Matrix& _b, Vector& eval, Matrix& evec)
+  {
+    gsl_eigen_gensymmv_workspace * w = gsl_eigen_gensymmv_alloc(m->size1);
+    Matrix a = createMatrix(m->size1, m->size2);
+    Matrix b = createMatrix(_b->size1, _b->size2);
+    gsl_matrix_memcpy(a, m);
+    gsl_matrix_memcpy(b, _b);
+    gsl_eigen_gensymmv(a,b,eval,evec,w);
+    gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
+    gsl_eigen_gensymmv_free(w);
+    free(a);
+  }
+};
+
+template<typename Scalar> struct GslTraits<Scalar,true>
+{
+  typedef gsl_matrix_complex* Matrix;
+  typedef gsl_vector_complex* Vector;
+  static Matrix createMatrix(int rows, int cols) { return gsl_matrix_complex_alloc(rows,cols); }
+  static Vector createVector(int size) { return gsl_vector_complex_alloc(size); }
+  static void free(Matrix& m) { gsl_matrix_complex_free(m); m=0; }
+  static void free(Vector& m) { gsl_vector_complex_free(m); m=0; }
+  static void cholesky(Matrix& m) { gsl_linalg_complex_cholesky_decomp(m); }
+  static void cholesky_solve(const Matrix& m, const Vector& b, Vector& x) { gsl_linalg_complex_cholesky_solve(m,b,x); }
+  static void prod(const Matrix& m, const Vector& v, Vector& x)
+  { gsl_blas_zgemv(CblasNoTrans,gsl_complex_rect(1,0),m,v,gsl_complex_rect(0,0),x); }
+  static void eigen_symm(const Matrix& m, gsl_vector* &eval, Matrix& evec)
+  {
+    gsl_eigen_hermv_workspace * w = gsl_eigen_hermv_alloc(m->size1);
+    Matrix a = createMatrix(m->size1, m->size2);
+    gsl_matrix_complex_memcpy(a, m);
+    gsl_eigen_hermv(a,eval,evec,w);
+    gsl_eigen_hermv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
+    gsl_eigen_hermv_free(w);
+    free(a);
+  }
+  static void eigen_symm_gen(const Matrix& m, const Matrix& _b, gsl_vector* &eval, Matrix& evec)
+  {
+    gsl_eigen_genhermv_workspace * w = gsl_eigen_genhermv_alloc(m->size1);
+    Matrix a = createMatrix(m->size1, m->size2);
+    Matrix b = createMatrix(_b->size1, _b->size2);
+    gsl_matrix_complex_memcpy(a, m);
+    gsl_matrix_complex_memcpy(b, _b);
+    gsl_eigen_genhermv(a,b,eval,evec,w);
+    gsl_eigen_hermv_sort(eval, evec, GSL_EIGEN_SORT_VAL_ASC);
+    gsl_eigen_genhermv_free(w);
+    free(a);
+  }
+};
+
+template<typename MatrixType>
+void convert(const MatrixType& m, gsl_matrix* &res)
+{
+//   if (res)
+//     gsl_matrix_free(res);
+  res = gsl_matrix_alloc(m.rows(), m.cols());
+  for (int i=0 ; i<m.rows() ; ++i)
+    for (int j=0 ; j<m.cols(); ++j)
+      gsl_matrix_set(res, i, j, m(i,j));
+}
+
+template<typename MatrixType>
+void convert(const gsl_matrix* m, MatrixType& res)
+{
+  res.resize(int(m->size1), int(m->size2));
+  for (int i=0 ; i<res.rows() ; ++i)
+    for (int j=0 ; j<res.cols(); ++j)
+      res(i,j) = gsl_matrix_get(m,i,j);
+}
+
+template<typename VectorType>
+void convert(const VectorType& m, gsl_vector* &res)
+{
+  if (res) gsl_vector_free(res);
+  res = gsl_vector_alloc(m.size());
+  for (int i=0 ; i<m.size() ; ++i)
+      gsl_vector_set(res, i, m[i]);
+}
+
+template<typename VectorType>
+void convert(const gsl_vector* m, VectorType& res)
+{
+  res.resize (m->size);
+  for (int i=0 ; i<res.rows() ; ++i)
+    res[i] = gsl_vector_get(m, i);
+}
+
+template<typename MatrixType>
+void convert(const MatrixType& m, gsl_matrix_complex* &res)
+{
+  res = gsl_matrix_complex_alloc(m.rows(), m.cols());
+  for (int i=0 ; i<m.rows() ; ++i)
+    for (int j=0 ; j<m.cols(); ++j)
+    {
+      gsl_matrix_complex_set(res, i, j,
+        gsl_complex_rect(m(i,j).real(), m(i,j).imag()));
+    }
+}
+
+template<typename MatrixType>
+void convert(const gsl_matrix_complex* m, MatrixType& res)
+{
+  res.resize(int(m->size1), int(m->size2));
+  for (int i=0 ; i<res.rows() ; ++i)
+    for (int j=0 ; j<res.cols(); ++j)
+      res(i,j) = typename MatrixType::Scalar(
+        GSL_REAL(gsl_matrix_complex_get(m,i,j)),
+        GSL_IMAG(gsl_matrix_complex_get(m,i,j)));
+}
+
+template<typename VectorType>
+void convert(const VectorType& m, gsl_vector_complex* &res)
+{
+  res = gsl_vector_complex_alloc(m.size());
+  for (int i=0 ; i<m.size() ; ++i)
+      gsl_vector_complex_set(res, i, gsl_complex_rect(m[i].real(), m[i].imag()));
+}
+
+template<typename VectorType>
+void convert(const gsl_vector_complex* m, VectorType& res)
+{
+  res.resize(m->size);
+  for (int i=0 ; i<res.rows() ; ++i)
+    res[i] = typename VectorType::Scalar(
+        GSL_REAL(gsl_vector_complex_get(m, i)),
+        GSL_IMAG(gsl_vector_complex_get(m, i)));
+}
+
+}
+
+#endif // EIGEN_GSL_HELPER
diff --git a/test/eigen2/main.h b/test/eigen2/main.h
new file mode 100644
index 0000000..ad2ba19
--- /dev/null
+++ b/test/eigen2/main.h
@@ -0,0 +1,399 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#ifndef EIGEN_TEST_FUNC
+#error EIGEN_TEST_FUNC must be defined
+#endif
+
+#define DEFAULT_REPEAT 10
+
+namespace Eigen
+{
+  static std::vector<std::string> g_test_stack;
+  static int g_repeat;
+}
+
+#define EI_PP_MAKE_STRING2(S) #S
+#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
+
+#define EI_PP_CAT2(a,b) a ## b
+#define EI_PP_CAT(a,b) EI_PP_CAT2(a,b)
+
+#ifndef EIGEN_NO_ASSERTION_CHECKING
+
+  namespace Eigen
+  {
+    static const bool should_raise_an_assert = false;
+
+    // Used to avoid to raise two exceptions at a time in which
+    // case the exception is not properly caught.
+    // This may happen when a second exceptions is raise in a destructor.
+    static bool no_more_assert = false;
+
+    struct eigen_assert_exception
+    {
+      eigen_assert_exception(void) {}
+      ~eigen_assert_exception() { Eigen::no_more_assert = false; }
+    };
+  }
+
+  // If EIGEN_DEBUG_ASSERTS is defined and if no assertion is raised while
+  // one should have been, then the list of excecuted assertions is printed out.
+  //
+  // EIGEN_DEBUG_ASSERTS is not enabled by default as it
+  // significantly increases the compilation time
+  // and might even introduce side effects that would hide
+  // some memory errors.
+  #ifdef EIGEN_DEBUG_ASSERTS
+
+    namespace Eigen
+    {
+      static bool ei_push_assert = false;
+      static std::vector<std::string> eigen_assert_list;
+    }
+
+    #define eigen_assert(a)                       \
+      if( (!(a)) && (!no_more_assert) )     \
+      {                                     \
+        Eigen::no_more_assert = true;       \
+        throw Eigen::eigen_assert_exception(); \
+      }                                     \
+      else if (Eigen::ei_push_assert)       \
+      {                                     \
+        eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__)" ("EI_PP_MAKE_STRING(__LINE__)") : "#a) ); \
+      }
+
+    #define VERIFY_RAISES_ASSERT(a)                                               \
+      {                                                                           \
+        Eigen::no_more_assert = false;                                            \
+        try {                                                                     \
+          Eigen::eigen_assert_list.clear();                                          \
+          Eigen::ei_push_assert = true;                                           \
+          a;                                                                      \
+          Eigen::ei_push_assert = false;                                          \
+          std::cerr << "One of the following asserts should have been raised:\n"; \
+          for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai)                       \
+            std::cerr << "  " << eigen_assert_list[ai] << "\n";                      \
+          VERIFY(Eigen::should_raise_an_assert && # a);                           \
+        } catch (Eigen::eigen_assert_exception e) {                                  \
+          Eigen::ei_push_assert = false; VERIFY(true);                            \
+        }                                                                         \
+      }
+
+  #else // EIGEN_DEBUG_ASSERTS
+
+    #undef eigen_assert
+
+    // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
+    #define eigen_assert(a) \
+      if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) )	\
+      {                                     \
+        Eigen::no_more_assert = true;       \
+        throw Eigen::eigen_assert_exception(); \
+      }
+
+    #define VERIFY_RAISES_ASSERT(a) {                             \
+        Eigen::no_more_assert = false;                            \
+        try { a; VERIFY(Eigen::should_raise_an_assert && # a); }  \
+        catch (Eigen::eigen_assert_exception e) { VERIFY(true); }    \
+      }
+
+  #endif // EIGEN_DEBUG_ASSERTS
+
+  #define EIGEN_USE_CUSTOM_ASSERT
+
+#else // EIGEN_NO_ASSERTION_CHECKING
+
+  #define VERIFY_RAISES_ASSERT(a) {}
+
+#endif // EIGEN_NO_ASSERTION_CHECKING
+
+
+#define EIGEN_INTERNAL_DEBUGGING
+#define EIGEN_NICE_RANDOM
+#include <Eigen/Array>
+
+
+#define VERIFY(a) do { if (!(a)) { \
+    std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__) << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" \
+      << std::endl << "    " << EI_PP_MAKE_STRING(a) << std::endl << std::endl; \
+    abort(); \
+  } } while (0)
+
+#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))
+#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_ei_isMuchSmallerThan(a, b))
+#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_ei_isApproxOrLessThan(a, b))
+#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_ei_isApproxOrLessThan(a, b))
+
+#define CALL_SUBTEST(FUNC) do { \
+    g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \
+    FUNC; \
+    g_test_stack.pop_back(); \
+  } while (0)
+
+namespace Eigen {
+
+template<typename T> inline typename NumTraits<T>::Real test_precision();
+template<> inline int test_precision<int>() { return 0; }
+template<> inline float test_precision<float>() { return 1e-3f; }
+template<> inline double test_precision<double>() { return 1e-6; }
+template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
+template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
+template<> inline long double test_precision<long double>() { return 1e-6; }
+
+inline bool test_ei_isApprox(const int& a, const int& b)
+{ return ei_isApprox(a, b, test_precision<int>()); }
+inline bool test_ei_isMuchSmallerThan(const int& a, const int& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<int>()); }
+inline bool test_ei_isApproxOrLessThan(const int& a, const int& b)
+{ return ei_isApproxOrLessThan(a, b, test_precision<int>()); }
+
+inline bool test_ei_isApprox(const float& a, const float& b)
+{ return ei_isApprox(a, b, test_precision<float>()); }
+inline bool test_ei_isMuchSmallerThan(const float& a, const float& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<float>()); }
+inline bool test_ei_isApproxOrLessThan(const float& a, const float& b)
+{ return ei_isApproxOrLessThan(a, b, test_precision<float>()); }
+
+inline bool test_ei_isApprox(const double& a, const double& b)
+{ return ei_isApprox(a, b, test_precision<double>()); }
+inline bool test_ei_isMuchSmallerThan(const double& a, const double& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<double>()); }
+inline bool test_ei_isApproxOrLessThan(const double& a, const double& b)
+{ return ei_isApproxOrLessThan(a, b, test_precision<double>()); }
+
+inline bool test_ei_isApprox(const std::complex<float>& a, const std::complex<float>& b)
+{ return ei_isApprox(a, b, test_precision<std::complex<float> >()); }
+inline bool test_ei_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); }
+
+inline bool test_ei_isApprox(const std::complex<double>& a, const std::complex<double>& b)
+{ return ei_isApprox(a, b, test_precision<std::complex<double> >()); }
+inline bool test_ei_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
+
+inline bool test_ei_isApprox(const long double& a, const long double& b)
+{ return ei_isApprox(a, b, test_precision<long double>()); }
+inline bool test_ei_isMuchSmallerThan(const long double& a, const long double& b)
+{ return ei_isMuchSmallerThan(a, b, test_precision<long double>()); }
+inline bool test_ei_isApproxOrLessThan(const long double& a, const long double& b)
+{ return ei_isApproxOrLessThan(a, b, test_precision<long double>()); }
+
+template<typename Type1, typename Type2>
+inline bool test_ei_isApprox(const Type1& a, const Type2& b)
+{
+  return a.isApprox(b, test_precision<typename Type1::Scalar>());
+}
+
+template<typename Derived1, typename Derived2>
+inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived1>& m1,
+                                   const MatrixBase<Derived2>& m2)
+{
+  return m1.isMuchSmallerThan(m2, test_precision<typename ei_traits<Derived1>::Scalar>());
+}
+
+template<typename Derived>
+inline bool test_ei_isMuchSmallerThan(const MatrixBase<Derived>& m,
+                                   const typename NumTraits<typename ei_traits<Derived>::Scalar>::Real& s)
+{
+  return m.isMuchSmallerThan(s, test_precision<typename ei_traits<Derived>::Scalar>());
+}
+
+} // end namespace Eigen
+
+template<typename T> struct GetDifferentType;
+
+template<> struct GetDifferentType<float> { typedef double type; };
+template<> struct GetDifferentType<double> { typedef float type; };
+template<typename T> struct GetDifferentType<std::complex<T> >
+{ typedef std::complex<typename GetDifferentType<T>::type> type; };
+
+// forward declaration of the main test function
+void EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
+
+using namespace Eigen;
+
+#ifdef EIGEN_TEST_PART_1
+#define CALL_SUBTEST_1(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_1(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_2
+#define CALL_SUBTEST_2(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_2(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_3
+#define CALL_SUBTEST_3(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_3(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_4
+#define CALL_SUBTEST_4(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_4(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_5
+#define CALL_SUBTEST_5(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_5(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_6
+#define CALL_SUBTEST_6(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_6(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_7
+#define CALL_SUBTEST_7(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_7(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_8
+#define CALL_SUBTEST_8(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_8(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_9
+#define CALL_SUBTEST_9(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_9(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_10
+#define CALL_SUBTEST_10(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_10(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_11
+#define CALL_SUBTEST_11(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_11(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_12
+#define CALL_SUBTEST_12(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_12(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_13
+#define CALL_SUBTEST_13(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_13(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_14
+#define CALL_SUBTEST_14(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_14(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_15
+#define CALL_SUBTEST_15(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_15(FUNC)
+#endif
+
+#ifdef EIGEN_TEST_PART_16
+#define CALL_SUBTEST_16(FUNC) CALL_SUBTEST(FUNC)
+#else
+#define CALL_SUBTEST_16(FUNC)
+#endif
+
+
+
+int main(int argc, char *argv[])
+{
+    bool has_set_repeat = false;
+    bool has_set_seed = false;
+    bool need_help = false;
+    unsigned int seed = 0;
+    int repeat = DEFAULT_REPEAT;
+
+    for(int i = 1; i < argc; i++)
+    {
+      if(argv[i][0] == 'r')
+      {
+        if(has_set_repeat)
+        {
+          std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
+          return 1;
+        }
+        repeat = std::atoi(argv[i]+1);
+        has_set_repeat = true;
+        if(repeat <= 0)
+        {
+          std::cout << "Invalid \'repeat\' value " << argv[i]+1 << std::endl;
+          return 1;
+        }
+      }
+      else if(argv[i][0] == 's')
+      {
+        if(has_set_seed)
+        {
+          std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
+          return 1;
+        }
+        seed = int(std::strtoul(argv[i]+1, 0, 10));
+        has_set_seed = true;
+        bool ok = seed!=0;
+        if(!ok)
+        {
+          std::cout << "Invalid \'seed\' value " << argv[i]+1 << std::endl;
+          return 1;
+        }
+      }
+      else
+      {
+        need_help = true;
+      }
+    }
+
+    if(need_help)
+    {
+      std::cout << "This test application takes the following optional arguments:" << std::endl;
+      std::cout << "  rN     Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl;
+      std::cout << "  sN     Use N as seed for random numbers (default: based on current time)" << std::endl;
+      return 1;
+    }
+
+    if(!has_set_seed) seed = (unsigned int) std::time(NULL);
+    if(!has_set_repeat) repeat = DEFAULT_REPEAT;
+
+    std::cout << "Initializing random number generator with seed " << seed << std::endl;
+	std::srand(seed);
+    std::cout << "Repeating each test " << repeat << " times" << std::endl;
+
+    Eigen::g_repeat = repeat;
+    Eigen::g_test_stack.push_back(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC));
+
+    EI_PP_CAT(test_,EIGEN_TEST_FUNC)();
+    return 0;
+}
+
+
+
diff --git a/test/eigen2/product.h b/test/eigen2/product.h
new file mode 100644
index 0000000..ae1b4ba
--- /dev/null
+++ b/test/eigen2/product.h
@@ -0,0 +1,129 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Array>
+#include <Eigen/QR>
+
+template<typename Derived1, typename Derived2>
+bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = precision<typename Derived1::RealScalar>())
+{
+  return !((m1-m2).cwise().abs2().maxCoeff() < epsilon * epsilon
+                          * std::max(m1.cwise().abs2().maxCoeff(), m2.cwise().abs2().maxCoeff()));
+}
+
+template<typename MatrixType> void product(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Identity.h Product.h
+  */
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::FloatingPoint FloatingPoint;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RowVectorType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ColVectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RowSquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> ColSquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
+                         MatrixType::Options^RowMajor> OtherMajorMatrixType;
+
+  int rows = m.rows();
+  int cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+  RowSquareMatrixType
+             identity = RowSquareMatrixType::Identity(rows, rows),
+             square = RowSquareMatrixType::Random(rows, rows),
+             res = RowSquareMatrixType::Random(rows, rows);
+  ColSquareMatrixType
+             square2 = ColSquareMatrixType::Random(cols, cols),
+             res2 = ColSquareMatrixType::Random(cols, cols);
+  RowVectorType v1 = RowVectorType::Random(rows);
+  ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols);
+  OtherMajorMatrixType tm1 = m1;
+
+  Scalar s1 = ei_random<Scalar>();
+
+  int r = ei_random<int>(0, rows-1),
+      c = ei_random<int>(0, cols-1);
+
+  // begin testing Product.h: only associativity for now
+  // (we use Transpose.h but this doesn't count as a test for it)
+
+  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
+  m3 = m1;
+  m3 *= m1.transpose() * m2;
+  VERIFY_IS_APPROX(m3,                      m1 * (m1.transpose()*m2));
+  VERIFY_IS_APPROX(m3,                      m1.lazy() * (m1.transpose()*m2));
+
+  // continue testing Product.h: distributivity
+  VERIFY_IS_APPROX(square*(m1 + m2),        square*m1+square*m2);
+  VERIFY_IS_APPROX(square*(m1 - m2),        square*m1-square*m2);
+
+  // continue testing Product.h: compatibility with ScalarMultiple.h
+  VERIFY_IS_APPROX(s1*(square*m1),          (s1*square)*m1);
+  VERIFY_IS_APPROX(s1*(square*m1),          square*(m1*s1));
+
+  // again, test operator() to check const-qualification
+  s1 += (square.lazy() * m1)(r,c);
+
+  // test Product.h together with Identity.h
+  VERIFY_IS_APPROX(v1,                      identity*v1);
+  VERIFY_IS_APPROX(v1.transpose(),          v1.transpose() * identity);
+  // again, test operator() to check const-qualification
+  VERIFY_IS_APPROX(MatrixType::Identity(rows, cols)(r,c), static_cast<Scalar>(r==c));
+
+  if (rows!=cols)
+     VERIFY_RAISES_ASSERT(m3 = m1*m1);
+
+  // test the previous tests were not screwed up because operator* returns 0
+  // (we use the more accurate default epsilon)
+  if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(m1.transpose()*m2,m2.transpose()*m1));
+  }
+
+  // test optimized operator+= path
+  res = square;
+  res += (m1 * m2.transpose()).lazy();
+  VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
+  if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(res,square + m2 * m1.transpose()));
+  }
+  vcres = vc2;
+  vcres += (m1.transpose() * v1).lazy();
+  VERIFY_IS_APPROX(vcres, vc2 + m1.transpose() * v1);
+  tm1 = m1;
+  VERIFY_IS_APPROX(tm1.transpose() * v1, m1.transpose() * v1);
+  VERIFY_IS_APPROX(v1.transpose() * tm1, v1.transpose() * m1);
+
+  // test submatrix and matrix/vector product
+  for (int i=0; i<rows; ++i)
+    res.row(i) = m1.row(i) * m2.transpose();
+  VERIFY_IS_APPROX(res, m1 * m2.transpose());
+  // the other way round:
+  for (int i=0; i<rows; ++i)
+    res.col(i) = m1 * m2.transpose().col(i);
+  VERIFY_IS_APPROX(res, m1 * m2.transpose());
+
+  res2 = square2;
+  res2 += (m1.transpose() * m2).lazy();
+  VERIFY_IS_APPROX(res2, square2 + m1.transpose() * m2);
+
+  if (NumTraits<Scalar>::HasFloatingPoint && std::min(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(res2,square2 + m2.transpose() * m1));
+  }
+}
+
diff --git a/test/eigen2/runtest.sh b/test/eigen2/runtest.sh
new file mode 100755
index 0000000..bc693af
--- /dev/null
+++ b/test/eigen2/runtest.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+black='\E[30m'
+red='\E[31m'
+green='\E[32m'
+yellow='\E[33m'
+blue='\E[34m'
+magenta='\E[35m'
+cyan='\E[36m'
+white='\E[37m'
+
+if make test_$1 > /dev/null  2> .runtest.log ; then
+  if ! ./test_$1 r20 > /dev/null 2> .runtest.log ; then
+    echo -e  $red Test $1 failed: $black
+    echo -e $blue
+    cat .runtest.log
+    echo -e $black
+    exit 1
+  else
+  echo -e $green Test $1 passed$black
+  fi
+else
+  echo -e  $red Build of target $1 failed: $black
+  echo -e $blue
+  cat .runtest.log
+  echo -e $black
+  exit 1
+fi
diff --git a/test/eigen2/sparse.h b/test/eigen2/sparse.h
new file mode 100644
index 0000000..e12f899
--- /dev/null
+++ b/test/eigen2/sparse.h
@@ -0,0 +1,154 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_TESTSPARSE_H
+
+#include "main.h"
+
+#if EIGEN_GNUC_AT_LEAST(4,0) && !defined __ICC
+#include <tr1/unordered_map>
+#define EIGEN_UNORDERED_MAP_SUPPORT
+namespace std {
+  using std::tr1::unordered_map;
+}
+#endif
+
+#ifdef EIGEN_GOOGLEHASH_SUPPORT
+  #include <google/sparse_hash_map>
+#endif
+
+#include <Eigen/Cholesky>
+#include <Eigen/LU>
+#include <Eigen/Sparse>
+
+enum {
+  ForceNonZeroDiag = 1,
+  MakeLowerTriangular = 2,
+  MakeUpperTriangular = 4,
+  ForceRealDiag = 8
+};
+
+/* Initializes both a sparse and dense matrix with same random values,
+ * and a ratio of \a density non zero entries.
+ * \param flags is a union of ForceNonZeroDiag, MakeLowerTriangular and MakeUpperTriangular
+ *        allowing to control the shape of the matrix.
+ * \param zeroCoords and nonzeroCoords allows to get the coordinate lists of the non zero,
+ *        and zero coefficients respectively.
+ */
+template<typename Scalar> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,Dynamic>& refMat,
+           SparseMatrix<Scalar>& sparseMat,
+           int flags = 0,
+           std::vector<Vector2i>* zeroCoords = 0,
+           std::vector<Vector2i>* nonzeroCoords = 0)
+{
+  sparseMat.startFill(int(refMat.rows()*refMat.cols()*density));
+  for(int j=0; j<refMat.cols(); j++)
+  {
+    for(int i=0; i<refMat.rows(); i++)
+    {
+      Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
+      if ((flags&ForceNonZeroDiag) && (i==j))
+      {
+        v = ei_random<Scalar>()*Scalar(3.);
+        v = v*v + Scalar(5.);
+      }
+      if ((flags & MakeLowerTriangular) && j>i)
+        v = Scalar(0);
+      else if ((flags & MakeUpperTriangular) && j<i)
+        v = Scalar(0);
+      
+      if ((flags&ForceRealDiag) && (i==j))
+        v = ei_real(v);
+        
+      if (v!=Scalar(0))
+      {
+        sparseMat.fill(i,j) = v;
+        if (nonzeroCoords)
+          nonzeroCoords->push_back(Vector2i(i,j));
+      }
+      else if (zeroCoords)
+      {
+        zeroCoords->push_back(Vector2i(i,j));
+      }
+      refMat(i,j) = v;
+    }
+  }
+  sparseMat.endFill();
+}
+
+template<typename Scalar> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,Dynamic>& refMat,
+           DynamicSparseMatrix<Scalar>& sparseMat,
+           int flags = 0,
+           std::vector<Vector2i>* zeroCoords = 0,
+           std::vector<Vector2i>* nonzeroCoords = 0)
+{
+  sparseMat.startFill(int(refMat.rows()*refMat.cols()*density));
+  for(int j=0; j<refMat.cols(); j++)
+  {
+    for(int i=0; i<refMat.rows(); i++)
+    {
+      Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
+      if ((flags&ForceNonZeroDiag) && (i==j))
+      {
+        v = ei_random<Scalar>()*Scalar(3.);
+        v = v*v + Scalar(5.);
+      }
+      if ((flags & MakeLowerTriangular) && j>i)
+        v = Scalar(0);
+      else if ((flags & MakeUpperTriangular) && j<i)
+        v = Scalar(0);
+      
+      if ((flags&ForceRealDiag) && (i==j))
+        v = ei_real(v);
+        
+      if (v!=Scalar(0))
+      {
+        sparseMat.fill(i,j) = v;
+        if (nonzeroCoords)
+          nonzeroCoords->push_back(Vector2i(i,j));
+      }
+      else if (zeroCoords)
+      {
+        zeroCoords->push_back(Vector2i(i,j));
+      }
+      refMat(i,j) = v;
+    }
+  }
+  sparseMat.endFill();
+}
+
+template<typename Scalar> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,1>& refVec,
+           SparseVector<Scalar>& sparseVec,
+           std::vector<int>* zeroCoords = 0,
+           std::vector<int>* nonzeroCoords = 0)
+{
+  sparseVec.reserve(int(refVec.size()*density));
+  sparseVec.setZero();
+  for(int i=0; i<refVec.size(); i++)
+  {
+    Scalar v = (ei_random<double>(0,1) < density) ? ei_random<Scalar>() : Scalar(0);
+    if (v!=Scalar(0))
+    {
+      sparseVec.fill(i) = v;
+      if (nonzeroCoords)
+        nonzeroCoords->push_back(i);
+    }
+    else if (zeroCoords)
+        zeroCoords->push_back(i);
+    refVec[i] = v;
+  }
+}
+
+#endif // EIGEN_TESTSPARSE_H
diff --git a/test/eigen2/testsuite.cmake b/test/eigen2/testsuite.cmake
new file mode 100644
index 0000000..12b6bfa
--- /dev/null
+++ b/test/eigen2/testsuite.cmake
@@ -0,0 +1,197 @@
+
+####################################################################
+#
+# Usage:
+#  - create a new folder, let's call it cdash
+#  - in that folder, do:
+#    ctest -S path/to/eigen2/test/testsuite.cmake[,option1=value1[,option2=value2]]
+#
+# Options:
+#  - EIGEN_CXX: compiler, eg.: g++-4.2
+#      default: default c++ compiler
+#  - EIGEN_SITE: eg, INRIA-Bdx_pc-gael, or the name of the contributor, etc.
+#      default: hostname
+#  - EIGEN_BUILD_STRING: a string which identify the system/compiler. It should be formed like that:
+#        <OS_name>-<OS_version>-<arch>-<compiler-version>
+#      with:
+#        <OS_name> = opensuse, debian, osx, windows, cygwin, freebsd, solaris, etc.
+#        <OS_version> = 11.1, XP, vista, leopard, etc.
+#        <arch> = i386, x86_64, ia64, powerpc, etc.
+#        <compiler-version> = gcc-4.3.2, icc-11.0, MSVC-2008, etc.
+#  - EIGEN_EXPLICIT_VECTORIZATION: novec, SSE2, Altivec
+#       default: SSE2 for x86_64 systems, novec otherwise
+#       Its value is automatically appended to EIGEN_BUILD_STRING
+#  - EIGEN_CMAKE_DIR: path to cmake executable
+#  - EIGEN_MODE: dashboard model, can be Experimental, Nightly, or Continuous
+#      default: Nightly
+#  - EIGEN_WORK_DIR: directory used to download the source files and make the builds
+#      default: folder which contains this script
+#  - EIGEN_CMAKE_ARGS: additional arguments passed to cmake
+#  - CTEST_SOURCE_DIRECTORY: path to eigen's src (use a new and empty folder, not the one you are working on)
+#      default: <EIGEN_WORK_DIR>/src
+#  - CTEST_BINARY_DIRECTORY: build directory
+#      default: <EIGEN_WORK_DIR>/nightly-<EIGEN_CXX>
+#
+# Here is an example running several compilers on a linux system:
+# #!/bin/bash
+# ARCH=`uname -m`
+# SITE=`hostname`
+# VERSION=opensuse-11.1
+# WORK_DIR=/home/gael/Coding/eigen2/cdash
+# # get the last version of the script
+# wget http://bitbucket.org/eigen/eigen/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
+# COMMON="ctest -S $WORK_DIR/testsuite.cmake,EIGEN_WORK_DIR=$WORK_DIR,EIGEN_SITE=$SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$OS_VERSION-$ARCH"
+# $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4
+# $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1
+# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=novec
+# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=SSE2
+# $COMMON-icc-11.0,EIGEN_CXX=icpc
+#
+####################################################################
+
+# process the arguments
+
+set(ARGLIST ${CTEST_SCRIPT_ARG})
+while(${ARGLIST} MATCHES  ".+.*")
+
+  # pick first
+  string(REGEX MATCH "([^,]*)(,.*)?" DUMMY ${ARGLIST})
+  SET(TOP ${CMAKE_MATCH_1})
+
+  # remove first
+  string(REGEX MATCHALL "[^,]*,(.*)" DUMMY ${ARGLIST})
+  SET(ARGLIST ${CMAKE_MATCH_1})
+
+  # decompose as a pair key=value
+  string(REGEX MATCH "([^=]*)(=.*)?" DUMMY ${TOP})
+  SET(KEY ${CMAKE_MATCH_1})
+
+  string(REGEX MATCH "[^=]*=(.*)" DUMMY ${TOP})
+  SET(VALUE ${CMAKE_MATCH_1})
+
+  # set the variable to the specified value
+  if(VALUE)
+    SET(${KEY} ${VALUE})
+  else(VALUE)
+    SET(${KEY} ON)
+  endif(VALUE)
+
+endwhile(${ARGLIST} MATCHES ".+.*")
+
+####################################################################
+# Automatically set some user variables if they have not been defined manually
+####################################################################
+cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+
+if(NOT EIGEN_SITE)
+  site_name(EIGEN_SITE)
+endif(NOT EIGEN_SITE)
+
+if(NOT EIGEN_CMAKE_DIR)
+  SET(EIGEN_CMAKE_DIR "")
+endif(NOT EIGEN_CMAKE_DIR)
+
+if(NOT EIGEN_BUILD_STRING)
+
+  # let's try to find all information we need to make the build string ourself
+
+  # OS
+  build_name(EIGEN_OS_VERSION)
+
+  # arch
+  set(EIGEN_ARCH ${CMAKE_SYSTEM_PROCESSOR})
+  if(WIN32)
+    set(EIGEN_ARCH $ENV{PROCESSOR_ARCHITECTURE})
+  else(WIN32)
+    execute_process(COMMAND uname -m OUTPUT_VARIABLE EIGEN_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
+  endif(WIN32)
+
+  set(EIGEN_BUILD_STRING ${EIGEN_OS_VERSION}${EIGEN_ARCH}-${EIGEN_CXX})
+
+endif(NOT EIGEN_BUILD_STRING)
+
+if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+  set(EIGEN_BUILD_STRING ${EIGEN_BUILD_STRING}-${EIGEN_EXPLICIT_VECTORIZATION})
+endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+
+if(NOT EIGEN_WORK_DIR)
+  set(EIGEN_WORK_DIR ${CTEST_SCRIPT_DIRECTORY})
+endif(NOT EIGEN_WORK_DIR)
+
+if(NOT CTEST_SOURCE_DIRECTORY)
+  SET (CTEST_SOURCE_DIRECTORY "${EIGEN_WORK_DIR}/src")
+endif(NOT CTEST_SOURCE_DIRECTORY)
+
+if(NOT CTEST_BINARY_DIRECTORY)
+  SET (CTEST_BINARY_DIRECTORY "${EIGEN_WORK_DIR}/nightly_${EIGEN_CXX}")
+endif(NOT CTEST_BINARY_DIRECTORY)
+
+if(NOT EIGEN_MODE)
+  set(EIGEN_MODE Nightly)
+endif(NOT EIGEN_MODE)
+
+## mandatory variables (the default should be ok in most cases):
+
+SET (CTEST_CVS_COMMAND "hg")
+SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone -r 2.0 http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
+
+# which ctest command to use for running the dashboard
+SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE}")
+
+# what cmake command to use for configuring this dashboard
+SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_BUILD_TESTS=on ")
+
+####################################################################
+# The values in this section are optional you can either
+# have them or leave them commented out
+####################################################################
+
+# this make sure we get consistent outputs
+SET($ENV{LC_MESSAGES} "en_EN")
+
+# should ctest wipe the binary tree before running
+SET(CTEST_START_WITH_EMPTY_BINARY_DIRECTORY TRUE)
+SET(CTEST_BACKUP_AND_RESTORE TRUE)
+
+# this is the initial cache to use for the binary tree, be careful to escape
+# any quotes inside of this string if you use it
+if(WIN32 AND NOT UNIX)
+  #message(SEND_ERROR "win32")
+  set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=nmake")
+  SET (CTEST_INITIAL_CACHE "
+    MAKECOMMAND:STRING=nmake -i
+    CMAKE_MAKE_PROGRAM:FILEPATH=nmake
+    CMAKE_GENERATOR:INTERNAL=NMake Makefiles
+    BUILDNAME:STRING=${EIGEN_BUILD_STRING}
+    SITE:STRING=${EIGEN_SITE}
+  ")
+else(WIN32 AND NOT UNIX)
+  SET (CTEST_INITIAL_CACHE "
+    BUILDNAME:STRING=${EIGEN_BUILD_STRING}
+    SITE:STRING=${EIGEN_SITE}
+  ")
+endif(WIN32 AND NOT UNIX)
+
+# set any extra environment variables to use during the execution of the script here:
+
+if(EIGEN_CXX)
+  set(CTEST_ENVIRONMENT "CXX=${EIGEN_CXX}")
+endif(EIGEN_CXX)
+
+if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+  if(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE3)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES Altivec)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_ALTIVEC=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES novec)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON")
+  else(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+    message(FATAL_ERROR "Invalid value for EIGEN_EXPLICIT_VECTORIZATION (${EIGEN_EXPLICIT_VECTORIZATION}), must be: novec, SSE2, SSE3, Altivec")
+  endif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+
+if(DEFINED EIGEN_CMAKE_ARGS)
+  set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} ${EIGEN_CMAKE_ARGS}")
+endif(DEFINED EIGEN_CMAKE_ARGS)
diff --git a/test/eigen2support.cpp b/test/eigen2support.cpp
new file mode 100644
index 0000000..1fa49a8
--- /dev/null
+++ b/test/eigen2support.cpp
@@ -0,0 +1,67 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN2_SUPPORT
+#define EIGEN_NO_EIGEN2_DEPRECATED_WARNING
+
+#include "main.h"
+
+template<typename MatrixType> void eigen2support(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  Scalar  s1 = internal::random<Scalar>(),
+          s2 = internal::random<Scalar>();
+
+  // scalar addition
+  VERIFY_IS_APPROX(m1.cwise() + s1, s1 + m1.cwise());
+  VERIFY_IS_APPROX(m1.cwise() + s1, MatrixType::Constant(rows,cols,s1) + m1);
+  VERIFY_IS_APPROX((m1*Scalar(2)).cwise() - s2, (m1+m1) - MatrixType::Constant(rows,cols,s2) );
+  m3 = m1;
+  m3.cwise() += s2;
+  VERIFY_IS_APPROX(m3, m1.cwise() + s2);
+  m3 = m1;
+  m3.cwise() -= s1;
+  VERIFY_IS_APPROX(m3, m1.cwise() - s1);
+
+  VERIFY_IS_EQUAL((m1.corner(TopLeft,1,1)), (m1.block(0,0,1,1)));
+  VERIFY_IS_EQUAL((m1.template corner<1,1>(TopLeft)), (m1.template block<1,1>(0,0)));
+  VERIFY_IS_EQUAL((m1.col(0).start(1)), (m1.col(0).segment(0,1)));
+  VERIFY_IS_EQUAL((m1.col(0).template start<1>()), (m1.col(0).segment(0,1)));
+  VERIFY_IS_EQUAL((m1.col(0).end(1)), (m1.col(0).segment(rows-1,1)));
+  VERIFY_IS_EQUAL((m1.col(0).template end<1>()), (m1.col(0).segment(rows-1,1)));
+  
+  using std::cos;
+  using numext::real;
+  using numext::abs2;
+  VERIFY_IS_EQUAL(ei_cos(s1), cos(s1));
+  VERIFY_IS_EQUAL(ei_real(s1), real(s1));
+  VERIFY_IS_EQUAL(ei_abs2(s1), abs2(s1));
+
+  m1.minor(0,0);
+}
+
+void test_eigen2support()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( eigen2support(Matrix<double,1,1>()) );
+    CALL_SUBTEST_2( eigen2support(MatrixXd(1,1)) );
+    CALL_SUBTEST_4( eigen2support(Matrix3f()) );
+    CALL_SUBTEST_5( eigen2support(Matrix4d()) );
+    CALL_SUBTEST_2( eigen2support(MatrixXf(200,200)) );
+    CALL_SUBTEST_6( eigen2support(MatrixXcd(100,100)) );
+  }
+}
diff --git a/test/eigensolver_complex.cpp b/test/eigensolver_complex.cpp
new file mode 100644
index 0000000..c9d8c08
--- /dev/null
+++ b/test/eigensolver_complex.cpp
@@ -0,0 +1,122 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+#include <Eigen/LU>
+
+/* Check that two column vectors are approximately equal upto permutations,
+   by checking that the k-th power sums are equal for k = 1, ..., vec1.rows() */
+template<typename VectorType>
+void verify_is_approx_upto_permutation(const VectorType& vec1, const VectorType& vec2)
+{
+  typedef typename NumTraits<typename VectorType::Scalar>::Real RealScalar;
+
+  VERIFY(vec1.cols() == 1);
+  VERIFY(vec2.cols() == 1);
+  VERIFY(vec1.rows() == vec2.rows());
+  for (int k = 1; k <= vec1.rows(); ++k)
+  {
+    VERIFY_IS_APPROX(vec1.array().pow(RealScalar(k)).sum(), vec2.array().pow(RealScalar(k)).sum());
+  }
+}
+
+
+template<typename MatrixType> void eigensolver(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     ComplexEigenSolver.h, and indirectly ComplexSchur.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType symmA =  a.adjoint() * a;
+
+  ComplexEigenSolver<MatrixType> ei0(symmA);
+  VERIFY_IS_EQUAL(ei0.info(), Success);
+  VERIFY_IS_APPROX(symmA * ei0.eigenvectors(), ei0.eigenvectors() * ei0.eigenvalues().asDiagonal());
+
+  ComplexEigenSolver<MatrixType> ei1(a);
+  VERIFY_IS_EQUAL(ei1.info(), Success);
+  VERIFY_IS_APPROX(a * ei1.eigenvectors(), ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
+  // Note: If MatrixType is real then a.eigenvalues() uses EigenSolver and thus
+  // another algorithm so results may differ slightly
+  verify_is_approx_upto_permutation(a.eigenvalues(), ei1.eigenvalues());
+
+  ComplexEigenSolver<MatrixType> ei2;
+  ei2.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
+  VERIFY_IS_EQUAL(ei2.info(), Success);
+  VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
+  VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
+  if (rows > 2) {
+    ei2.setMaxIterations(1).compute(a);
+    VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
+    VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
+  }
+
+  ComplexEigenSolver<MatrixType> eiNoEivecs(a, false);
+  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
+  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
+
+  // Regression test for issue #66
+  MatrixType z = MatrixType::Zero(rows,cols);
+  ComplexEigenSolver<MatrixType> eiz(z);
+  VERIFY((eiz.eigenvalues().cwiseEqual(0)).all());
+
+  MatrixType id = MatrixType::Identity(rows, cols);
+  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
+
+  if (rows > 1)
+  {
+    // Test matrix with NaN
+    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
+    ComplexEigenSolver<MatrixType> eiNaN(a);
+    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
+  }
+}
+
+template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
+{
+  ComplexEigenSolver<MatrixType> eig;
+  VERIFY_RAISES_ASSERT(eig.eigenvectors());
+  VERIFY_RAISES_ASSERT(eig.eigenvalues());
+
+  MatrixType a = MatrixType::Random(m.rows(),m.cols());
+  eig.compute(a, false);
+  VERIFY_RAISES_ASSERT(eig.eigenvectors());
+}
+
+void test_eigensolver_complex()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( eigensolver(Matrix4cf()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_2( eigensolver(MatrixXcd(s,s)) );
+    CALL_SUBTEST_3( eigensolver(Matrix<std::complex<float>, 1, 1>()) );
+    CALL_SUBTEST_4( eigensolver(Matrix3f()) );
+  }
+  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4cf()) );
+  s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXcd(s,s)) );
+  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<std::complex<float>, 1, 1>()) );
+  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix3f()) );
+
+  // Test problem size constructors
+  CALL_SUBTEST_5(ComplexEigenSolver<MatrixXf> tmp(s));
+  
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/eigensolver_generalized_real.cpp b/test/eigensolver_generalized_real.cpp
new file mode 100644
index 0000000..566a4bd
--- /dev/null
+++ b/test/eigensolver_generalized_real.cpp
@@ -0,0 +1,59 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void generalized_eigensolver_real(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     GeneralizedEigenSolver.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType b = MatrixType::Random(rows,cols);
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  MatrixType b1 = MatrixType::Random(rows,cols);
+  MatrixType spdA =  a.adjoint() * a + a1.adjoint() * a1;
+  MatrixType spdB =  b.adjoint() * b + b1.adjoint() * b1;
+
+  // lets compare to GeneralizedSelfAdjointEigenSolver
+  GeneralizedSelfAdjointEigenSolver<MatrixType> symmEig(spdA, spdB);
+  GeneralizedEigenSolver<MatrixType> eig(spdA, spdB);
+
+  VERIFY_IS_EQUAL(eig.eigenvalues().imag().cwiseAbs().maxCoeff(), 0);
+
+  VectorType realEigenvalues = eig.eigenvalues().real();
+  std::sort(realEigenvalues.data(), realEigenvalues.data()+realEigenvalues.size());
+  VERIFY_IS_APPROX(realEigenvalues, symmEig.eigenvalues());
+}
+
+void test_eigensolver_generalized_real()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    int s = 0;
+    CALL_SUBTEST_1( generalized_eigensolver_real(Matrix4f()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(s,s)) );
+
+    // some trivial but implementation-wise tricky cases
+    CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(1,1)) );
+    CALL_SUBTEST_2( generalized_eigensolver_real(MatrixXd(2,2)) );
+    CALL_SUBTEST_3( generalized_eigensolver_real(Matrix<double,1,1>()) );
+    CALL_SUBTEST_4( generalized_eigensolver_real(Matrix2d()) );
+    TEST_SET_BUT_UNUSED_VARIABLE(s)
+  }
+}
diff --git a/test/eigensolver_generic.cpp b/test/eigensolver_generic.cpp
new file mode 100644
index 0000000..005af81
--- /dev/null
+++ b/test/eigensolver_generic.cpp
@@ -0,0 +1,125 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void eigensolver(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     EigenSolver.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
+  typedef typename std::complex<typename NumTraits<typename MatrixType::Scalar>::Real> Complex;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
+
+  EigenSolver<MatrixType> ei0(symmA);
+  VERIFY_IS_EQUAL(ei0.info(), Success);
+  VERIFY_IS_APPROX(symmA * ei0.pseudoEigenvectors(), ei0.pseudoEigenvectors() * ei0.pseudoEigenvalueMatrix());
+  VERIFY_IS_APPROX((symmA.template cast<Complex>()) * (ei0.pseudoEigenvectors().template cast<Complex>()),
+    (ei0.pseudoEigenvectors().template cast<Complex>()) * (ei0.eigenvalues().asDiagonal()));
+
+  EigenSolver<MatrixType> ei1(a);
+  VERIFY_IS_EQUAL(ei1.info(), Success);
+  VERIFY_IS_APPROX(a * ei1.pseudoEigenvectors(), ei1.pseudoEigenvectors() * ei1.pseudoEigenvalueMatrix());
+  VERIFY_IS_APPROX(a.template cast<Complex>() * ei1.eigenvectors(),
+                   ei1.eigenvectors() * ei1.eigenvalues().asDiagonal());
+  VERIFY_IS_APPROX(ei1.eigenvectors().colwise().norm(), RealVectorType::Ones(rows).transpose());
+  VERIFY_IS_APPROX(a.eigenvalues(), ei1.eigenvalues());
+
+  EigenSolver<MatrixType> ei2;
+  ei2.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * rows).compute(a);
+  VERIFY_IS_EQUAL(ei2.info(), Success);
+  VERIFY_IS_EQUAL(ei2.eigenvectors(), ei1.eigenvectors());
+  VERIFY_IS_EQUAL(ei2.eigenvalues(), ei1.eigenvalues());
+  if (rows > 2) {
+    ei2.setMaxIterations(1).compute(a);
+    VERIFY_IS_EQUAL(ei2.info(), NoConvergence);
+    VERIFY_IS_EQUAL(ei2.getMaxIterations(), 1);
+  }
+
+  EigenSolver<MatrixType> eiNoEivecs(a, false);
+  VERIFY_IS_EQUAL(eiNoEivecs.info(), Success);
+  VERIFY_IS_APPROX(ei1.eigenvalues(), eiNoEivecs.eigenvalues());
+  VERIFY_IS_APPROX(ei1.pseudoEigenvalueMatrix(), eiNoEivecs.pseudoEigenvalueMatrix());
+
+  MatrixType id = MatrixType::Identity(rows, cols);
+  VERIFY_IS_APPROX(id.operatorNorm(), RealScalar(1));
+
+  if (rows > 2)
+  {
+    // Test matrix with NaN
+    a(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
+    EigenSolver<MatrixType> eiNaN(a);
+    VERIFY_IS_EQUAL(eiNaN.info(), NoConvergence);
+  }
+}
+
+template<typename MatrixType> void eigensolver_verify_assert(const MatrixType& m)
+{
+  EigenSolver<MatrixType> eig;
+  VERIFY_RAISES_ASSERT(eig.eigenvectors());
+  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
+  VERIFY_RAISES_ASSERT(eig.pseudoEigenvalueMatrix());
+  VERIFY_RAISES_ASSERT(eig.eigenvalues());
+
+  MatrixType a = MatrixType::Random(m.rows(),m.cols());
+  eig.compute(a, false);
+  VERIFY_RAISES_ASSERT(eig.eigenvectors());
+  VERIFY_RAISES_ASSERT(eig.pseudoEigenvectors());
+}
+
+void test_eigensolver_generic()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( eigensolver(Matrix4f()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_2( eigensolver(MatrixXd(s,s)) );
+
+    // some trivial but implementation-wise tricky cases
+    CALL_SUBTEST_2( eigensolver(MatrixXd(1,1)) );
+    CALL_SUBTEST_2( eigensolver(MatrixXd(2,2)) );
+    CALL_SUBTEST_3( eigensolver(Matrix<double,1,1>()) );
+    CALL_SUBTEST_4( eigensolver(Matrix2d()) );
+  }
+
+  CALL_SUBTEST_1( eigensolver_verify_assert(Matrix4f()) );
+  s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+  CALL_SUBTEST_2( eigensolver_verify_assert(MatrixXd(s,s)) );
+  CALL_SUBTEST_3( eigensolver_verify_assert(Matrix<double,1,1>()) );
+  CALL_SUBTEST_4( eigensolver_verify_assert(Matrix2d()) );
+
+  // Test problem size constructors
+  CALL_SUBTEST_5(EigenSolver<MatrixXf> tmp(s));
+
+  // regression test for bug 410
+  CALL_SUBTEST_2(
+  {
+     MatrixXd A(1,1);
+     A(0,0) = std::sqrt(-1.);
+     Eigen::EigenSolver<MatrixXd> solver(A);
+     MatrixXd V(1, 1);
+     V(0,0) = solver.eigenvectors()(0,0).real();
+  }
+  );
+  
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/eigensolver_selfadjoint.cpp b/test/eigensolver_selfadjoint.cpp
new file mode 100644
index 0000000..38689cf
--- /dev/null
+++ b/test/eigensolver_selfadjoint.cpp
@@ -0,0 +1,160 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void selfadjointeigensolver(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     EigenSolver.h, SelfAdjointEigenSolver.h (and indirectly: Tridiagonalization.h)
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  MatrixType a1 = MatrixType::Random(rows,cols);
+  MatrixType symmA =  a.adjoint() * a + a1.adjoint() * a1;
+  MatrixType symmC = symmA;
+  
+  // randomly nullify some rows/columns
+  {
+    Index count = 1;//internal::random<Index>(-cols,cols);
+    for(Index k=0; k<count; ++k)
+    {
+      Index i = internal::random<Index>(0,cols-1);
+      symmA.row(i).setZero();
+      symmA.col(i).setZero();
+    }
+  }
+  
+  symmA.template triangularView<StrictlyUpper>().setZero();
+  symmC.template triangularView<StrictlyUpper>().setZero();
+
+  MatrixType b = MatrixType::Random(rows,cols);
+  MatrixType b1 = MatrixType::Random(rows,cols);
+  MatrixType symmB = b.adjoint() * b + b1.adjoint() * b1;
+  symmB.template triangularView<StrictlyUpper>().setZero();
+
+  SelfAdjointEigenSolver<MatrixType> eiSymm(symmA);
+  SelfAdjointEigenSolver<MatrixType> eiDirect;
+  eiDirect.computeDirect(symmA);
+  // generalized eigen pb
+  GeneralizedSelfAdjointEigenSolver<MatrixType> eiSymmGen(symmC, symmB);
+
+  VERIFY_IS_EQUAL(eiSymm.info(), Success);
+  VERIFY((symmA.template selfadjointView<Lower>() * eiSymm.eigenvectors()).isApprox(
+          eiSymm.eigenvectors() * eiSymm.eigenvalues().asDiagonal(), largerEps));
+  VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiSymm.eigenvalues());
+  
+  VERIFY_IS_EQUAL(eiDirect.info(), Success);
+  VERIFY((symmA.template selfadjointView<Lower>() * eiDirect.eigenvectors()).isApprox(
+          eiDirect.eigenvectors() * eiDirect.eigenvalues().asDiagonal(), largerEps));
+  VERIFY_IS_APPROX(symmA.template selfadjointView<Lower>().eigenvalues(), eiDirect.eigenvalues());
+
+  SelfAdjointEigenSolver<MatrixType> eiSymmNoEivecs(symmA, false);
+  VERIFY_IS_EQUAL(eiSymmNoEivecs.info(), Success);
+  VERIFY_IS_APPROX(eiSymm.eigenvalues(), eiSymmNoEivecs.eigenvalues());
+  
+  // generalized eigen problem Ax = lBx
+  eiSymmGen.compute(symmC, symmB,Ax_lBx);
+  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
+  VERIFY((symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors()).isApprox(
+          symmB.template selfadjointView<Lower>() * (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
+
+  // generalized eigen problem BAx = lx
+  eiSymmGen.compute(symmC, symmB,BAx_lx);
+  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
+  VERIFY((symmB.template selfadjointView<Lower>() * (symmC.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
+         (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
+
+  // generalized eigen problem ABx = lx
+  eiSymmGen.compute(symmC, symmB,ABx_lx);
+  VERIFY_IS_EQUAL(eiSymmGen.info(), Success);
+  VERIFY((symmC.template selfadjointView<Lower>() * (symmB.template selfadjointView<Lower>() * eiSymmGen.eigenvectors())).isApprox(
+         (eiSymmGen.eigenvectors() * eiSymmGen.eigenvalues().asDiagonal()), largerEps));
+
+
+  eiSymm.compute(symmC);
+  MatrixType sqrtSymmA = eiSymm.operatorSqrt();
+  VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), sqrtSymmA*sqrtSymmA);
+  VERIFY_IS_APPROX(sqrtSymmA, symmC.template selfadjointView<Lower>()*eiSymm.operatorInverseSqrt());
+
+  MatrixType id = MatrixType::Identity(rows, cols);
+  VERIFY_IS_APPROX(id.template selfadjointView<Lower>().operatorNorm(), RealScalar(1));
+
+  SelfAdjointEigenSolver<MatrixType> eiSymmUninitialized;
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.info());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvalues());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
+
+  eiSymmUninitialized.compute(symmA, false);
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.eigenvectors());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorSqrt());
+  VERIFY_RAISES_ASSERT(eiSymmUninitialized.operatorInverseSqrt());
+
+  // test Tridiagonalization's methods
+  Tridiagonalization<MatrixType> tridiag(symmC);
+  // FIXME tridiag.matrixQ().adjoint() does not work
+  VERIFY_IS_APPROX(MatrixType(symmC.template selfadjointView<Lower>()), tridiag.matrixQ() * tridiag.matrixT().eval() * MatrixType(tridiag.matrixQ()).adjoint());
+  
+  if (rows > 1)
+  {
+    // Test matrix with NaN
+    symmC(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
+    SelfAdjointEigenSolver<MatrixType> eiSymmNaN(symmC);
+    VERIFY_IS_EQUAL(eiSymmNaN.info(), NoConvergence);
+  }
+}
+
+void test_eigensolver_selfadjoint()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    // very important to test 3x3 and 2x2 matrices since we provide special paths for them
+    CALL_SUBTEST_1( selfadjointeigensolver(Matrix2f()) );
+    CALL_SUBTEST_1( selfadjointeigensolver(Matrix2d()) );
+    CALL_SUBTEST_1( selfadjointeigensolver(Matrix3f()) );
+    CALL_SUBTEST_1( selfadjointeigensolver(Matrix3d()) );
+    CALL_SUBTEST_2( selfadjointeigensolver(Matrix4d()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_3( selfadjointeigensolver(MatrixXf(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_5( selfadjointeigensolver(MatrixXcd(s,s)) );
+    
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_9( selfadjointeigensolver(Matrix<std::complex<double>,Dynamic,Dynamic,RowMajor>(s,s)) );
+
+    // some trivial but implementation-wise tricky cases
+    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(1,1)) );
+    CALL_SUBTEST_4( selfadjointeigensolver(MatrixXd(2,2)) );
+    CALL_SUBTEST_6( selfadjointeigensolver(Matrix<double,1,1>()) );
+    CALL_SUBTEST_7( selfadjointeigensolver(Matrix<double,2,2>()) );
+  }
+
+  // Test problem size constructors
+  s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+  CALL_SUBTEST_8(SelfAdjointEigenSolver<MatrixXf> tmp1(s));
+  CALL_SUBTEST_8(Tridiagonalization<MatrixXf> tmp2(s));
+  
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
+
diff --git a/test/exceptions.cpp b/test/exceptions.cpp
new file mode 100644
index 0000000..b83fb82
--- /dev/null
+++ b/test/exceptions.cpp
@@ -0,0 +1,113 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+// Various sanity tests with exceptions:
+//  - no memory leak when a custom scalar type trow an exceptions
+//  - todo: complete the list of tests!
+
+#define EIGEN_STACK_ALLOCATION_LIMIT 100000000
+
+#include "main.h"
+
+struct my_exception
+{
+  my_exception() {}
+  ~my_exception() {}
+};
+    
+class ScalarWithExceptions
+{
+  public:
+    ScalarWithExceptions() { init(); }
+    ScalarWithExceptions(const float& _v) { init(); *v = _v; }
+    ScalarWithExceptions(const ScalarWithExceptions& other) { init(); *v = *(other.v); }
+    ~ScalarWithExceptions() {
+      delete v;
+      instances--;
+    }
+
+    void init() {
+      v = new float;
+      instances++;
+    }
+
+    ScalarWithExceptions operator+(const ScalarWithExceptions& other) const
+    {
+      countdown--;
+      if(countdown<=0)
+        throw my_exception();
+      return ScalarWithExceptions(*v+*other.v);
+    }
+    
+    ScalarWithExceptions operator-(const ScalarWithExceptions& other) const
+    { return ScalarWithExceptions(*v-*other.v); }
+    
+    ScalarWithExceptions operator*(const ScalarWithExceptions& other) const
+    { return ScalarWithExceptions((*v)*(*other.v)); }
+    
+    ScalarWithExceptions& operator+=(const ScalarWithExceptions& other)
+    { *v+=*other.v; return *this; }
+    ScalarWithExceptions& operator-=(const ScalarWithExceptions& other)
+    { *v-=*other.v; return *this; }
+    ScalarWithExceptions& operator=(const ScalarWithExceptions& other)
+    { *v = *(other.v); return *this; }
+  
+    bool operator==(const ScalarWithExceptions& other) const
+    { return *v==*other.v; }
+    bool operator!=(const ScalarWithExceptions& other) const
+    { return *v!=*other.v; }
+    
+    float* v;
+    static int instances;
+    static int countdown;
+};
+
+ScalarWithExceptions real(const ScalarWithExceptions &x) { return x; }
+ScalarWithExceptions imag(const ScalarWithExceptions & ) { return 0; }
+ScalarWithExceptions conj(const ScalarWithExceptions &x) { return x; }
+
+int ScalarWithExceptions::instances = 0;
+int ScalarWithExceptions::countdown = 0;
+
+
+#define CHECK_MEMLEAK(OP) {                                 \
+    ScalarWithExceptions::countdown = 100;                  \
+    int before = ScalarWithExceptions::instances;           \
+    bool exception_thrown = false;                         \
+    try { OP; }                              \
+    catch (my_exception) {                                  \
+      exception_thrown = true;                              \
+      VERIFY(ScalarWithExceptions::instances==before && "memory leak detected in " && EIGEN_MAKESTRING(OP)); \
+    } \
+    VERIFY(exception_thrown && " no exception thrown in " && EIGEN_MAKESTRING(OP)); \
+  }
+
+void memoryleak()
+{
+  typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,1> VectorType;
+  typedef Eigen::Matrix<ScalarWithExceptions,Dynamic,Dynamic> MatrixType;
+  
+  {
+    int n = 50;
+    VectorType v0(n), v1(n);
+    MatrixType m0(n,n), m1(n,n), m2(n,n);
+    v0.setOnes(); v1.setOnes();
+    m0.setOnes(); m1.setOnes(); m2.setOnes();
+    CHECK_MEMLEAK(v0 = m0 * m1 * v1);
+    CHECK_MEMLEAK(m2 = m0 * m1 * m2);
+    CHECK_MEMLEAK((v0+v1).dot(v0+v1));
+  }
+  VERIFY(ScalarWithExceptions::instances==0 && "global memory leak detected in " && EIGEN_MAKESTRING(OP)); \
+}
+
+void test_exceptions()
+{
+  CALL_SUBTEST( memoryleak() );
+}
diff --git a/test/first_aligned.cpp b/test/first_aligned.cpp
new file mode 100644
index 0000000..467f945
--- /dev/null
+++ b/test/first_aligned.cpp
@@ -0,0 +1,51 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar>
+void test_first_aligned_helper(Scalar *array, int size)
+{
+  const int packet_size = sizeof(Scalar) * internal::packet_traits<Scalar>::size;
+  VERIFY(((size_t(array) + sizeof(Scalar) * internal::first_aligned(array, size)) % packet_size) == 0);
+}
+
+template<typename Scalar>
+void test_none_aligned_helper(Scalar *array, int size)
+{
+  EIGEN_UNUSED_VARIABLE(array);
+  EIGEN_UNUSED_VARIABLE(size);
+  VERIFY(internal::packet_traits<Scalar>::size == 1 || internal::first_aligned(array, size) == size);
+}
+
+struct some_non_vectorizable_type { float x; };
+
+void test_first_aligned()
+{
+  EIGEN_ALIGN16 float array_float[100];
+  test_first_aligned_helper(array_float, 50);
+  test_first_aligned_helper(array_float+1, 50);
+  test_first_aligned_helper(array_float+2, 50);
+  test_first_aligned_helper(array_float+3, 50);
+  test_first_aligned_helper(array_float+4, 50);
+  test_first_aligned_helper(array_float+5, 50);
+  
+  EIGEN_ALIGN16 double array_double[100];
+  test_first_aligned_helper(array_double, 50);
+  test_first_aligned_helper(array_double+1, 50);
+  test_first_aligned_helper(array_double+2, 50);
+  
+  double *array_double_plus_4_bytes = (double*)(size_t(array_double)+4);
+  test_none_aligned_helper(array_double_plus_4_bytes, 50);
+  test_none_aligned_helper(array_double_plus_4_bytes+1, 50);
+  
+  some_non_vectorizable_type array_nonvec[100];
+  test_first_aligned_helper(array_nonvec, 100);
+  test_none_aligned_helper(array_nonvec, 100);
+}
diff --git a/test/geo_alignedbox.cpp b/test/geo_alignedbox.cpp
new file mode 100644
index 0000000..8e36adb
--- /dev/null
+++ b/test/geo_alignedbox.cpp
@@ -0,0 +1,178 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+#include<iostream>
+using namespace std;
+
+template<typename T> EIGEN_DONT_INLINE
+void kill_extra_precision(T& x) { eigen_assert(&x != 0); }
+
+
+template<typename BoxType> void alignedbox(const BoxType& _box)
+{
+  /* this test covers the following files:
+     AlignedBox.h
+  */
+  typedef typename BoxType::Index Index;  
+  typedef typename BoxType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
+
+  const Index dim = _box.dim();
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+  while( p1 == p0 ){
+      p1 =  VectorType::Random(dim); }
+  RealScalar s1 = internal::random<RealScalar>(0,1);
+
+  BoxType b0(dim);
+  BoxType b1(VectorType::Random(dim),VectorType::Random(dim));
+  BoxType b2;
+  
+  kill_extra_precision(b1);
+  kill_extra_precision(p0);
+  kill_extra_precision(p1);
+
+  b0.extend(p0);
+  b0.extend(p1);
+  VERIFY(b0.contains(p0*s1+(Scalar(1)-s1)*p1));
+
+  (b2 = b0).extend(b1);
+  VERIFY(b2.contains(b0));
+  VERIFY(b2.contains(b1));
+  VERIFY_IS_APPROX(b2.clamp(b0), b0);
+
+
+  // alignment -- make sure there is no memory alignment assertion
+  BoxType *bp0 = new BoxType(dim);
+  BoxType *bp1 = new BoxType(dim);
+  bp0->extend(*bp1);
+  delete bp0;
+  delete bp1;
+
+  // sampling
+  for( int i=0; i<10; ++i )
+  {
+      VectorType r = b0.sample();
+      VERIFY(b0.contains(r));
+  }
+
+}
+
+
+
+template<typename BoxType>
+void alignedboxCastTests(const BoxType& _box)
+{
+  // casting  
+  typedef typename BoxType::Index Index;
+  typedef typename BoxType::Scalar Scalar;
+  typedef Matrix<Scalar, BoxType::AmbientDimAtCompileTime, 1> VectorType;
+
+  const Index dim = _box.dim();
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+
+  BoxType b0(dim);
+
+  b0.extend(p0);
+  b0.extend(p1);
+
+  const int Dim = BoxType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  AlignedBox<OtherScalar,Dim> hp1f = b0.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),b0);
+  AlignedBox<Scalar,Dim> hp1d = b0.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),b0);
+}
+
+
+void specificTest1()
+{
+    Vector2f m; m << -1.0f, -2.0f;
+    Vector2f M; M <<  1.0f,  5.0f;
+
+    typedef AlignedBox2f  BoxType;
+    BoxType box( m, M );
+
+    Vector2f sides = M-m;
+    VERIFY_IS_APPROX(sides, box.sizes() );
+    VERIFY_IS_APPROX(sides[1], box.sizes()[1] );
+    VERIFY_IS_APPROX(sides[1], box.sizes().maxCoeff() );
+    VERIFY_IS_APPROX(sides[0], box.sizes().minCoeff() );
+
+    VERIFY_IS_APPROX( 14.0f, box.volume() );
+    VERIFY_IS_APPROX( 53.0f, box.diagonal().squaredNorm() );
+    VERIFY_IS_APPROX( std::sqrt( 53.0f ), box.diagonal().norm() );
+
+    VERIFY_IS_APPROX( m, box.corner( BoxType::BottomLeft ) );
+    VERIFY_IS_APPROX( M, box.corner( BoxType::TopRight ) );
+    Vector2f bottomRight; bottomRight << M[0], m[1];
+    Vector2f topLeft; topLeft << m[0], M[1];
+    VERIFY_IS_APPROX( bottomRight, box.corner( BoxType::BottomRight ) );
+    VERIFY_IS_APPROX( topLeft, box.corner( BoxType::TopLeft ) );
+}
+
+
+void specificTest2()
+{
+    Vector3i m; m << -1, -2, 0;
+    Vector3i M; M <<  1,  5, 3;
+
+    typedef AlignedBox3i  BoxType;
+    BoxType box( m, M );
+
+    Vector3i sides = M-m;
+    VERIFY_IS_APPROX(sides, box.sizes() );
+    VERIFY_IS_APPROX(sides[1], box.sizes()[1] );
+    VERIFY_IS_APPROX(sides[1], box.sizes().maxCoeff() );
+    VERIFY_IS_APPROX(sides[0], box.sizes().minCoeff() );
+
+    VERIFY_IS_APPROX( 42, box.volume() );
+    VERIFY_IS_APPROX( 62, box.diagonal().squaredNorm() );
+
+    VERIFY_IS_APPROX( m, box.corner( BoxType::BottomLeftFloor ) );
+    VERIFY_IS_APPROX( M, box.corner( BoxType::TopRightCeil ) );
+    Vector3i bottomRightFloor; bottomRightFloor << M[0], m[1], m[2];
+    Vector3i topLeftFloor; topLeftFloor << m[0], M[1], m[2];
+    VERIFY_IS_APPROX( bottomRightFloor, box.corner( BoxType::BottomRightFloor ) );
+    VERIFY_IS_APPROX( topLeftFloor, box.corner( BoxType::TopLeftFloor ) );
+}
+
+
+void test_geo_alignedbox()
+{
+  for(int i = 0; i < g_repeat; i++)
+  {
+    CALL_SUBTEST_1( alignedbox(AlignedBox2f()) );
+    CALL_SUBTEST_2( alignedboxCastTests(AlignedBox2f()) );
+
+    CALL_SUBTEST_3( alignedbox(AlignedBox3f()) );
+    CALL_SUBTEST_4( alignedboxCastTests(AlignedBox3f()) );
+
+    CALL_SUBTEST_5( alignedbox(AlignedBox4d()) );
+    CALL_SUBTEST_6( alignedboxCastTests(AlignedBox4d()) );
+
+    CALL_SUBTEST_7( alignedbox(AlignedBox1d()) );
+    CALL_SUBTEST_8( alignedboxCastTests(AlignedBox1d()) );
+
+    CALL_SUBTEST_9( alignedbox(AlignedBox1i()) );
+    CALL_SUBTEST_10( alignedbox(AlignedBox2i()) );
+    CALL_SUBTEST_11( alignedbox(AlignedBox3i()) );
+  }
+  CALL_SUBTEST_12( specificTest1() );
+  CALL_SUBTEST_13( specificTest2() );
+}
diff --git a/test/geo_eulerangles.cpp b/test/geo_eulerangles.cpp
new file mode 100644
index 0000000..b4830bd
--- /dev/null
+++ b/test/geo_eulerangles.cpp
@@ -0,0 +1,112 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+
+template<typename Scalar>
+void verify_euler(const Matrix<Scalar,3,1>& ea, int i, int j, int k)
+{
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef AngleAxis<Scalar> AngleAxisx;
+  using std::abs;
+  Matrix3 m(AngleAxisx(ea[0], Vector3::Unit(i)) * AngleAxisx(ea[1], Vector3::Unit(j)) * AngleAxisx(ea[2], Vector3::Unit(k)));
+  Vector3 eabis = m.eulerAngles(i, j, k);
+  Matrix3 mbis(AngleAxisx(eabis[0], Vector3::Unit(i)) * AngleAxisx(eabis[1], Vector3::Unit(j)) * AngleAxisx(eabis[2], Vector3::Unit(k))); 
+  VERIFY_IS_APPROX(m,  mbis); 
+  /* If I==K, and ea[1]==0, then there no unique solution. */ 
+  /* The remark apply in the case where I!=K, and |ea[1]| is close to pi/2. */ 
+  if( (i!=k || ea[1]!=0) && (i==k || !internal::isApprox(abs(ea[1]),Scalar(M_PI/2),test_precision<Scalar>())) ) 
+    VERIFY((ea-eabis).norm() <= test_precision<Scalar>());
+  
+  // approx_or_less_than does not work for 0
+  VERIFY(0 < eabis[0] || test_isMuchSmallerThan(eabis[0], Scalar(1)));
+  VERIFY_IS_APPROX_OR_LESS_THAN(eabis[0], Scalar(M_PI));
+  VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[1]);
+  VERIFY_IS_APPROX_OR_LESS_THAN(eabis[1], Scalar(M_PI));
+  VERIFY_IS_APPROX_OR_LESS_THAN(-Scalar(M_PI), eabis[2]);
+  VERIFY_IS_APPROX_OR_LESS_THAN(eabis[2], Scalar(M_PI));
+}
+
+template<typename Scalar> void check_all_var(const Matrix<Scalar,3,1>& ea)
+{
+  verify_euler(ea, 0,1,2);
+  verify_euler(ea, 0,1,0);
+  verify_euler(ea, 0,2,1);
+  verify_euler(ea, 0,2,0);
+
+  verify_euler(ea, 1,2,0);
+  verify_euler(ea, 1,2,1);
+  verify_euler(ea, 1,0,2);
+  verify_euler(ea, 1,0,1);
+
+  verify_euler(ea, 2,0,1);
+  verify_euler(ea, 2,0,2);
+  verify_euler(ea, 2,1,0);
+  verify_euler(ea, 2,1,2);
+}
+
+template<typename Scalar> void eulerangles()
+{
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Array<Scalar,3,1> Array3;
+  typedef Quaternion<Scalar> Quaternionx;
+  typedef AngleAxis<Scalar> AngleAxisx;
+
+  Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+  Quaternionx q1;
+  q1 = AngleAxisx(a, Vector3::Random().normalized());
+  Matrix3 m;
+  m = q1;
+  
+  Vector3 ea = m.eulerAngles(0,1,2);
+  check_all_var(ea);
+  ea = m.eulerAngles(0,1,0);
+  check_all_var(ea);
+  
+  // Check with purely random Quaternion:
+  q1.coeffs() = Quaternionx::Coefficients::Random().normalized();
+  m = q1;
+  ea = m.eulerAngles(0,1,2);
+  check_all_var(ea);
+  ea = m.eulerAngles(0,1,0);
+  check_all_var(ea);
+  
+  // Check with random angles in range [0:pi]x[-pi:pi]x[-pi:pi].
+  ea = (Array3::Random() + Array3(1,0,0))*Scalar(M_PI)*Array3(0.5,1,1);
+  check_all_var(ea);
+  
+  ea[2] = ea[0] = internal::random<Scalar>(0,Scalar(M_PI));
+  check_all_var(ea);
+  
+  ea[0] = ea[1] = internal::random<Scalar>(0,Scalar(M_PI));
+  check_all_var(ea);
+  
+  ea[1] = 0;
+  check_all_var(ea);
+  
+  ea.head(2).setZero();
+  check_all_var(ea);
+  
+  ea.setZero();
+  check_all_var(ea);
+}
+
+void test_geo_eulerangles()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( eulerangles<float>() );
+    CALL_SUBTEST_2( eulerangles<double>() );
+  }
+}
diff --git a/test/geo_homogeneous.cpp b/test/geo_homogeneous.cpp
new file mode 100644
index 0000000..c91bde8
--- /dev/null
+++ b/test/geo_homogeneous.cpp
@@ -0,0 +1,103 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+
+template<typename Scalar,int Size> void homogeneous(void)
+{
+  /* this test covers the following files:
+     Homogeneous.h
+  */
+
+  typedef Matrix<Scalar,Size,Size> MatrixType;
+  typedef Matrix<Scalar,Size,1, ColMajor> VectorType;
+
+  typedef Matrix<Scalar,Size+1,Size> HMatrixType;
+  typedef Matrix<Scalar,Size+1,1> HVectorType;
+
+  typedef Matrix<Scalar,Size,Size+1>   T1MatrixType;
+  typedef Matrix<Scalar,Size+1,Size+1> T2MatrixType;
+  typedef Matrix<Scalar,Size+1,Size> T3MatrixType;
+
+  VectorType v0 = VectorType::Random(),
+             ones = VectorType::Ones();
+
+  HVectorType hv0 = HVectorType::Random();
+
+  MatrixType m0 = MatrixType::Random();
+
+  HMatrixType hm0 = HMatrixType::Random();
+
+  hv0 << v0, 1;
+  VERIFY_IS_APPROX(v0.homogeneous(), hv0);
+  VERIFY_IS_APPROX(v0, hv0.hnormalized());
+
+  hm0 << m0, ones.transpose();
+  VERIFY_IS_APPROX(m0.colwise().homogeneous(), hm0);
+  VERIFY_IS_APPROX(m0, hm0.colwise().hnormalized());
+  hm0.row(Size-1).setRandom();
+  for(int j=0; j<Size; ++j)
+    m0.col(j) = hm0.col(j).head(Size) / hm0(Size,j);
+  VERIFY_IS_APPROX(m0, hm0.colwise().hnormalized());
+
+  T1MatrixType t1 = T1MatrixType::Random();
+  VERIFY_IS_APPROX(t1 * (v0.homogeneous().eval()), t1 * v0.homogeneous());
+  VERIFY_IS_APPROX(t1 * (m0.colwise().homogeneous().eval()), t1 * m0.colwise().homogeneous());
+
+  T2MatrixType t2 = T2MatrixType::Random();
+  VERIFY_IS_APPROX(t2 * (v0.homogeneous().eval()), t2 * v0.homogeneous());
+  VERIFY_IS_APPROX(t2 * (m0.colwise().homogeneous().eval()), t2 * m0.colwise().homogeneous());
+
+  VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t2,
+                    v0.transpose().rowwise().homogeneous() * t2);
+                    m0.transpose().rowwise().homogeneous().eval();
+  VERIFY_IS_APPROX((m0.transpose().rowwise().homogeneous().eval()) * t2,
+                    m0.transpose().rowwise().homogeneous() * t2);
+
+  T3MatrixType t3 = T3MatrixType::Random();
+  VERIFY_IS_APPROX((v0.transpose().rowwise().homogeneous().eval()) * t3,
+                    v0.transpose().rowwise().homogeneous() * t3);
+  VERIFY_IS_APPROX((m0.transpose().rowwise().homogeneous().eval()) * t3,
+                    m0.transpose().rowwise().homogeneous() * t3);
+
+  // test product with a Transform object
+  Transform<Scalar, Size, Affine> aff;
+  Transform<Scalar, Size, AffineCompact> caff;
+  Transform<Scalar, Size, Projective> proj;
+  Matrix<Scalar, Size, Dynamic>   pts;
+  Matrix<Scalar, Size+1, Dynamic> pts1, pts2;
+
+  aff.affine().setRandom();
+  proj = caff = aff;
+  pts.setRandom(Size,internal::random<int>(1,20));
+  
+  pts1 = pts.colwise().homogeneous();
+  VERIFY_IS_APPROX(aff  * pts.colwise().homogeneous(), (aff  * pts1).colwise().hnormalized());
+  VERIFY_IS_APPROX(caff * pts.colwise().homogeneous(), (caff * pts1).colwise().hnormalized());
+  VERIFY_IS_APPROX(proj * pts.colwise().homogeneous(), (proj * pts1));
+  
+  VERIFY_IS_APPROX((aff  * pts1).colwise().hnormalized(),  aff  * pts);
+  VERIFY_IS_APPROX((caff * pts1).colwise().hnormalized(), caff * pts);
+  
+  pts2 = pts1;
+  pts2.row(Size).setRandom();
+  VERIFY_IS_APPROX((aff  * pts2).colwise().hnormalized(), aff  * pts2.colwise().hnormalized());
+  VERIFY_IS_APPROX((caff * pts2).colwise().hnormalized(), caff * pts2.colwise().hnormalized());
+  VERIFY_IS_APPROX((proj * pts2).colwise().hnormalized(), (proj * pts2.colwise().hnormalized().colwise().homogeneous()).colwise().hnormalized());
+}
+
+void test_geo_homogeneous()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(( homogeneous<float,1>() ));
+    CALL_SUBTEST_2(( homogeneous<double,3>() ));
+    CALL_SUBTEST_3(( homogeneous<double,8>() ));
+  }
+}
diff --git a/test/geo_hyperplane.cpp b/test/geo_hyperplane.cpp
new file mode 100644
index 0000000..3275378
--- /dev/null
+++ b/test/geo_hyperplane.cpp
@@ -0,0 +1,185 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
+{
+  /* this test covers the following files:
+     Hyperplane.h
+  */
+  typedef typename HyperplaneType::Index Index;
+  const Index dim = _plane.dim();
+  enum { Options = HyperplaneType::Options };
+  typedef typename HyperplaneType::Scalar Scalar;
+  typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, HyperplaneType::AmbientDimAtCompileTime,
+                         HyperplaneType::AmbientDimAtCompileTime> MatrixType;
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+
+  VectorType n0 = VectorType::Random(dim).normalized();
+  VectorType n1 = VectorType::Random(dim).normalized();
+
+  HyperplaneType pl0(n0, p0);
+  HyperplaneType pl1(n1, p1);
+  HyperplaneType pl2 = pl1;
+
+  Scalar s0 = internal::random<Scalar>();
+  Scalar s1 = internal::random<Scalar>();
+
+  VERIFY_IS_APPROX( n1.dot(n1), Scalar(1) );
+
+  VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) );
+  VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 );
+  VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( pl1.absDistance(p1 +  pl1.normal().unitOrthogonal() * s1), Scalar(1) );
+
+  // transform
+  if (!NumTraits<Scalar>::IsComplex)
+  {
+    MatrixType rot = MatrixType::Random(dim,dim).householderQr().householderQ();
+    DiagonalMatrix<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
+    Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
+
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot,Isometry).absDistance(rot * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling).absDistance((rot*scaling) * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*scaling*translation)
+                                 .absDistance((rot*scaling*translation) * p1), Scalar(1) );
+    pl2 = pl1;
+    VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry)
+                                 .absDistance((rot*translation) * p1), Scalar(1) );
+  }
+
+  // casting
+  const int Dim = HyperplaneType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  Hyperplane<OtherScalar,Dim,Options> hp1f = pl1.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),pl1);
+  Hyperplane<Scalar,Dim,Options> hp1d = pl1.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),pl1);
+}
+
+template<typename Scalar> void lines()
+{
+  using std::abs;
+  typedef Hyperplane<Scalar, 2> HLine;
+  typedef ParametrizedLine<Scalar, 2> PLine;
+  typedef Matrix<Scalar,2,1> Vector;
+  typedef Matrix<Scalar,3,1> CoeffsType;
+
+  for(int i = 0; i < 10; i++)
+  {
+    Vector center = Vector::Random();
+    Vector u = Vector::Random();
+    Vector v = Vector::Random();
+    Scalar a = internal::random<Scalar>();
+    while (abs(a-1) < 1e-4) a = internal::random<Scalar>();
+    while (u.norm() < 1e-4) u = Vector::Random();
+    while (v.norm() < 1e-4) v = Vector::Random();
+
+    HLine line_u = HLine::Through(center + u, center + a*u);
+    HLine line_v = HLine::Through(center + v, center + a*v);
+
+    // the line equations should be normalized so that a^2+b^2=1
+    VERIFY_IS_APPROX(line_u.normal().norm(), Scalar(1));
+    VERIFY_IS_APPROX(line_v.normal().norm(), Scalar(1));
+
+    Vector result = line_u.intersection(line_v);
+
+    // the lines should intersect at the point we called "center"
+    VERIFY_IS_APPROX(result, center);
+
+    // check conversions between two types of lines
+    PLine pl(line_u); // gcc 3.3 will commit suicide if we don't name this variable
+    CoeffsType converted_coeffs = HLine(pl).coeffs();
+    converted_coeffs *= (line_u.coeffs()[0])/(converted_coeffs[0]);
+    VERIFY(line_u.coeffs().isApprox(converted_coeffs));
+  }
+}
+
+template<typename Scalar> void planes()
+{
+  using std::abs;
+  typedef Hyperplane<Scalar, 3> Plane;
+  typedef Matrix<Scalar,3,1> Vector;
+
+  for(int i = 0; i < 10; i++)
+  {
+    Vector v0 = Vector::Random();
+    Vector v1(v0), v2(v0);
+    if(internal::random<double>(0,1)>0.25)
+      v1 += Vector::Random();
+    if(internal::random<double>(0,1)>0.25)
+      v2 += v1 * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
+    if(internal::random<double>(0,1)>0.25)
+      v2 += Vector::Random() * std::pow(internal::random<Scalar>(0,1),internal::random<int>(1,16));
+
+    Plane p0 = Plane::Through(v0, v1, v2);
+
+    VERIFY_IS_APPROX(p0.normal().norm(), Scalar(1));
+    VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v0), Scalar(1));
+    VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v1), Scalar(1));
+    VERIFY_IS_MUCH_SMALLER_THAN(p0.absDistance(v2), Scalar(1));
+  }
+}
+
+template<typename Scalar> void hyperplane_alignment()
+{
+  typedef Hyperplane<Scalar,3,AutoAlign> Plane3a;
+  typedef Hyperplane<Scalar,3,DontAlign> Plane3u;
+
+  EIGEN_ALIGN16 Scalar array1[4];
+  EIGEN_ALIGN16 Scalar array2[4];
+  EIGEN_ALIGN16 Scalar array3[4+1];
+  Scalar* array3u = array3+1;
+
+  Plane3a *p1 = ::new(reinterpret_cast<void*>(array1)) Plane3a;
+  Plane3u *p2 = ::new(reinterpret_cast<void*>(array2)) Plane3u;
+  Plane3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Plane3u;
+  
+  p1->coeffs().setRandom();
+  *p2 = *p1;
+  *p3 = *p1;
+
+  VERIFY_IS_APPROX(p1->coeffs(), p2->coeffs());
+  VERIFY_IS_APPROX(p1->coeffs(), p3->coeffs());
+  
+  #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Plane3a));
+  #endif
+}
+
+
+void test_geo_hyperplane()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( hyperplane(Hyperplane<float,2>()) );
+    CALL_SUBTEST_2( hyperplane(Hyperplane<float,3>()) );
+    CALL_SUBTEST_2( hyperplane(Hyperplane<float,3,DontAlign>()) );
+    CALL_SUBTEST_2( hyperplane_alignment<float>() );
+    CALL_SUBTEST_3( hyperplane(Hyperplane<double,4>()) );
+    CALL_SUBTEST_4( hyperplane(Hyperplane<std::complex<double>,5>()) );
+    CALL_SUBTEST_1( lines<float>() );
+    CALL_SUBTEST_3( lines<double>() );
+    CALL_SUBTEST_2( planes<float>() );
+    CALL_SUBTEST_5( planes<double>() );
+  }
+}
diff --git a/test/geo_orthomethods.cpp b/test/geo_orthomethods.cpp
new file mode 100644
index 0000000..c836dae
--- /dev/null
+++ b/test/geo_orthomethods.cpp
@@ -0,0 +1,121 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+/* this test covers the following files:
+   Geometry/OrthoMethods.h
+*/
+
+template<typename Scalar> void orthomethods_3()
+{
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,3,1> Vector3;
+
+  typedef Matrix<Scalar,4,1> Vector4;
+
+  Vector3 v0 = Vector3::Random(),
+          v1 = Vector3::Random(),
+          v2 = Vector3::Random();
+
+  // cross product
+  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(v1.dot(v1.cross(v2)), Scalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v2), Scalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(v2.dot(v1.cross(v2)), Scalar(1));
+  Matrix3 mat3;
+  mat3 << v0.normalized(),
+         (v0.cross(v1)).normalized(),
+         (v0.cross(v1).cross(v0)).normalized();
+  VERIFY(mat3.isUnitary());
+
+
+  // colwise/rowwise cross product
+  mat3.setRandom();
+  Vector3 vec3 = Vector3::Random();
+  Matrix3 mcross;
+  int i = internal::random<int>(0,2);
+  mcross = mat3.colwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
+  mcross = mat3.rowwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
+
+  // cross3
+  Vector4 v40 = Vector4::Random(),
+          v41 = Vector4::Random(),
+          v42 = Vector4::Random();
+  v40.w() = v41.w() = v42.w() = 0;
+  v42.template head<3>() = v40.template head<3>().cross(v41.template head<3>());
+  VERIFY_IS_APPROX(v40.cross3(v41), v42);
+  
+  // check mixed product
+  typedef Matrix<RealScalar, 3, 1> RealVector3;
+  RealVector3 rv1 = RealVector3::Random();
+  VERIFY_IS_APPROX(v1.cross(rv1.template cast<Scalar>()), v1.cross(rv1));
+  VERIFY_IS_APPROX(rv1.template cast<Scalar>().cross(v1), rv1.cross(v1));
+}
+
+template<typename Scalar, int Size> void orthomethods(int size=Size)
+{
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar,Size,1> VectorType;
+  typedef Matrix<Scalar,3,Size> Matrix3N;
+  typedef Matrix<Scalar,Size,3> MatrixN3;
+  typedef Matrix<Scalar,3,1> Vector3;
+
+  VectorType v0 = VectorType::Random(size);
+
+  // unitOrthogonal
+  VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
+  VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
+
+  if (size>=3)
+  {
+    v0.template head<2>().setZero();
+    v0.tail(size-2).setRandom();
+
+    VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
+    VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1));
+  }
+
+  // colwise/rowwise cross product
+  Vector3 vec3 = Vector3::Random();
+  int i = internal::random<int>(0,size-1);
+
+  Matrix3N mat3N(3,size), mcross3N(3,size);
+  mat3N.setRandom();
+  mcross3N = mat3N.colwise().cross(vec3);
+  VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3));
+
+  MatrixN3 matN3(size,3), mcrossN3(size,3);
+  matN3.setRandom();
+  mcrossN3 = matN3.rowwise().cross(vec3);
+  VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3));
+}
+
+void test_geo_orthomethods()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( orthomethods_3<float>() );
+    CALL_SUBTEST_2( orthomethods_3<double>() );
+    CALL_SUBTEST_4( orthomethods_3<std::complex<double> >() );
+    CALL_SUBTEST_1( (orthomethods<float,2>()) );
+    CALL_SUBTEST_2( (orthomethods<double,2>()) );
+    CALL_SUBTEST_1( (orthomethods<float,3>()) );
+    CALL_SUBTEST_2( (orthomethods<double,3>()) );
+    CALL_SUBTEST_3( (orthomethods<float,7>()) );
+    CALL_SUBTEST_4( (orthomethods<std::complex<double>,8>()) );
+    CALL_SUBTEST_5( (orthomethods<float,Dynamic>(36)) );
+    CALL_SUBTEST_6( (orthomethods<double,Dynamic>(35)) );
+  }
+}
diff --git a/test/geo_parametrizedline.cpp b/test/geo_parametrizedline.cpp
new file mode 100644
index 0000000..f0462d4
--- /dev/null
+++ b/test/geo_parametrizedline.cpp
@@ -0,0 +1,104 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/QR>
+
+template<typename LineType> void parametrizedline(const LineType& _line)
+{
+  /* this test covers the following files:
+     ParametrizedLine.h
+  */
+  using std::abs;
+  typedef typename LineType::Index Index;
+  const Index dim = _line.dim();
+  typedef typename LineType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, LineType::AmbientDimAtCompileTime, 1> VectorType;
+  typedef Hyperplane<Scalar,LineType::AmbientDimAtCompileTime> HyperplaneType;
+
+  VectorType p0 = VectorType::Random(dim);
+  VectorType p1 = VectorType::Random(dim);
+
+  VectorType d0 = VectorType::Random(dim).normalized();
+
+  LineType l0(p0, d0);
+
+  Scalar s0 = internal::random<Scalar>();
+  Scalar s1 = abs(internal::random<Scalar>());
+
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0), RealScalar(1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) );
+  VERIFY_IS_APPROX( (l0.projection(p1)-p1).norm(), l0.distance(p1) );
+  VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(l0.projection(p1)), RealScalar(1) );
+  VERIFY_IS_APPROX( Scalar(l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1)), s1 );
+
+  // casting
+  const int Dim = LineType::AmbientDimAtCompileTime;
+  typedef typename GetDifferentType<Scalar>::type OtherScalar;
+  ParametrizedLine<OtherScalar,Dim> hp1f = l0.template cast<OtherScalar>();
+  VERIFY_IS_APPROX(hp1f.template cast<Scalar>(),l0);
+  ParametrizedLine<Scalar,Dim> hp1d = l0.template cast<Scalar>();
+  VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),l0);
+
+  // intersections
+  VectorType p2 = VectorType::Random(dim);
+  VectorType n2 = VectorType::Random(dim).normalized();
+  HyperplaneType hp(p2,n2);
+  Scalar t = l0.intersectionParameter(hp);
+  VectorType pi = l0.pointAt(t);
+  VERIFY_IS_MUCH_SMALLER_THAN(hp.signedDistance(pi), RealScalar(1));
+  VERIFY_IS_MUCH_SMALLER_THAN(l0.distance(pi), RealScalar(1));
+  VERIFY_IS_APPROX(l0.intersectionPoint(hp), pi);
+}
+
+template<typename Scalar> void parametrizedline_alignment()
+{
+  typedef ParametrizedLine<Scalar,4,AutoAlign> Line4a;
+  typedef ParametrizedLine<Scalar,4,DontAlign> Line4u;
+
+  EIGEN_ALIGN16 Scalar array1[8];
+  EIGEN_ALIGN16 Scalar array2[8];
+  EIGEN_ALIGN16 Scalar array3[8+1];
+  Scalar* array3u = array3+1;
+
+  Line4a *p1 = ::new(reinterpret_cast<void*>(array1)) Line4a;
+  Line4u *p2 = ::new(reinterpret_cast<void*>(array2)) Line4u;
+  Line4u *p3 = ::new(reinterpret_cast<void*>(array3u)) Line4u;
+  
+  p1->origin().setRandom();
+  p1->direction().setRandom();
+  *p2 = *p1;
+  *p3 = *p1;
+
+  VERIFY_IS_APPROX(p1->origin(), p2->origin());
+  VERIFY_IS_APPROX(p1->origin(), p3->origin());
+  VERIFY_IS_APPROX(p1->direction(), p2->direction());
+  VERIFY_IS_APPROX(p1->direction(), p3->direction());
+  
+  #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Line4a));
+  #endif
+}
+
+void test_geo_parametrizedline()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( parametrizedline(ParametrizedLine<float,2>()) );
+    CALL_SUBTEST_2( parametrizedline(ParametrizedLine<float,3>()) );
+    CALL_SUBTEST_2( parametrizedline_alignment<float>() );
+    CALL_SUBTEST_3( parametrizedline(ParametrizedLine<double,4>()) );
+    CALL_SUBTEST_3( parametrizedline_alignment<double>() );
+    CALL_SUBTEST_4( parametrizedline(ParametrizedLine<std::complex<double>,5>()) );
+  }
+}
diff --git a/test/geo_quaternion.cpp b/test/geo_quaternion.cpp
new file mode 100644
index 0000000..1694b32
--- /dev/null
+++ b/test/geo_quaternion.cpp
@@ -0,0 +1,284 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename T> T bounded_acos(T v)
+{
+  using std::acos;
+  using std::min;
+  using std::max;
+  return acos((max)(T(-1),(min)(v,T(1))));
+}
+
+template<typename QuatType> void check_slerp(const QuatType& q0, const QuatType& q1)
+{
+  using std::abs;
+  typedef typename QuatType::Scalar Scalar;
+  typedef AngleAxis<Scalar> AA;
+
+  Scalar largeEps = test_precision<Scalar>();
+
+  Scalar theta_tot = AA(q1*q0.inverse()).angle();
+  if(theta_tot>M_PI)
+    theta_tot = Scalar(2.*M_PI)-theta_tot;
+  for(Scalar t=0; t<=Scalar(1.001); t+=Scalar(0.1))
+  {
+    QuatType q = q0.slerp(t,q1);
+    Scalar theta = AA(q*q0.inverse()).angle();
+    VERIFY(abs(q.norm() - 1) < largeEps);
+    if(theta_tot==0)  VERIFY(theta_tot==0);
+    else              VERIFY(abs(theta - t * theta_tot) < largeEps);
+  }
+}
+
+template<typename Scalar, int Options> void quaternion(void)
+{
+  /* this test covers the following files:
+     Quaternion.h
+  */
+  using std::abs;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Matrix<Scalar,4,1> Vector4;
+  typedef Quaternion<Scalar,Options> Quaternionx;
+  typedef AngleAxis<Scalar> AngleAxisx;
+
+  Scalar largeEps = test_precision<Scalar>();
+  if (internal::is_same<Scalar,float>::value)
+    largeEps = 1e-3f;
+
+  Scalar eps = internal::random<Scalar>() * Scalar(1e-2);
+
+  Vector3 v0 = Vector3::Random(),
+          v1 = Vector3::Random(),
+          v2 = Vector3::Random(),
+          v3 = Vector3::Random();
+
+  Scalar  a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI)),
+          b = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+  // Quaternion: Identity(), setIdentity();
+  Quaternionx q1, q2;
+  q2.setIdentity();
+  VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
+  q1.coeffs().setRandom();
+  VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
+
+  // concatenation
+  q1 *= q2;
+
+  q1 = AngleAxisx(a, v0.normalized());
+  q2 = AngleAxisx(a, v1.normalized());
+
+  // angular distance
+  Scalar refangle = abs(AngleAxisx(q1.inverse()*q2).angle());
+  if (refangle>Scalar(M_PI))
+    refangle = Scalar(2)*Scalar(M_PI) - refangle;
+
+  if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
+  {
+    VERIFY_IS_MUCH_SMALLER_THAN(abs(q1.angularDistance(q2) - refangle), Scalar(1));
+  }
+
+  // rotation matrix conversion
+  VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
+  VERIFY_IS_APPROX(q1 * q2 * v2,
+    q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
+
+  VERIFY(  (q2*q1).isApprox(q1*q2, largeEps)
+        || !(q2 * q1 * v2).isApprox(q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
+
+  q2 = q1.toRotationMatrix();
+  VERIFY_IS_APPROX(q1*v1,q2*v1);
+
+
+  // angle-axis conversion
+  AngleAxisx aa = AngleAxisx(q1);
+  VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+
+  // Do not execute the test if the rotation angle is almost zero, or
+  // the rotation axis and v1 are almost parallel.
+  if (abs(aa.angle()) > 5*test_precision<Scalar>()
+      && (aa.axis() - v1.normalized()).norm() < 1.99
+      && (aa.axis() + v1.normalized()).norm() < 1.99) 
+  {
+    VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
+  }
+
+  // from two vector creation
+  VERIFY_IS_APPROX( v2.normalized(),(q2.setFromTwoVectors(v1, v2)*v1).normalized());
+  VERIFY_IS_APPROX( v1.normalized(),(q2.setFromTwoVectors(v1, v1)*v1).normalized());
+  VERIFY_IS_APPROX(-v1.normalized(),(q2.setFromTwoVectors(v1,-v1)*v1).normalized());
+  if (internal::is_same<Scalar,double>::value)
+  {
+    v3 = (v1.array()+eps).matrix();
+    VERIFY_IS_APPROX( v3.normalized(),(q2.setFromTwoVectors(v1, v3)*v1).normalized());
+    VERIFY_IS_APPROX(-v3.normalized(),(q2.setFromTwoVectors(v1,-v3)*v1).normalized());
+  }
+
+  // from two vector creation static function
+  VERIFY_IS_APPROX( v2.normalized(),(Quaternionx::FromTwoVectors(v1, v2)*v1).normalized());
+  VERIFY_IS_APPROX( v1.normalized(),(Quaternionx::FromTwoVectors(v1, v1)*v1).normalized());
+  VERIFY_IS_APPROX(-v1.normalized(),(Quaternionx::FromTwoVectors(v1,-v1)*v1).normalized());
+  if (internal::is_same<Scalar,double>::value)
+  {
+    v3 = (v1.array()+eps).matrix();
+    VERIFY_IS_APPROX( v3.normalized(),(Quaternionx::FromTwoVectors(v1, v3)*v1).normalized());
+    VERIFY_IS_APPROX(-v3.normalized(),(Quaternionx::FromTwoVectors(v1,-v3)*v1).normalized());
+  }
+
+  // inverse and conjugate
+  VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
+  VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
+
+  // test casting
+  Quaternion<float> q1f = q1.template cast<float>();
+  VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
+  Quaternion<double> q1d = q1.template cast<double>();
+  VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
+
+  // test bug 369 - improper alignment.
+  Quaternionx *q = new Quaternionx;
+  delete q;
+
+  q1 = AngleAxisx(a, v0.normalized());
+  q2 = AngleAxisx(b, v1.normalized());
+  check_slerp(q1,q2);
+
+  q1 = AngleAxisx(b, v1.normalized());
+  q2 = AngleAxisx(b+Scalar(M_PI), v1.normalized());
+  check_slerp(q1,q2);
+
+  q1 = AngleAxisx(b,  v1.normalized());
+  q2 = AngleAxisx(-b, -v1.normalized());
+  check_slerp(q1,q2);
+
+  q1.coeffs() = Vector4::Random().normalized();
+  q2.coeffs() = -q1.coeffs();
+  check_slerp(q1,q2);
+}
+
+template<typename Scalar> void mapQuaternion(void){
+  typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
+  typedef Map<const Quaternion<Scalar>, Aligned> MCQuaternionA;
+  typedef Map<Quaternion<Scalar> > MQuaternionUA;
+  typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
+  typedef Quaternion<Scalar> Quaternionx;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef AngleAxis<Scalar> AngleAxisx;
+  
+  Vector3 v0 = Vector3::Random(),
+          v1 = Vector3::Random();
+  Scalar  a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+  EIGEN_ALIGN16 Scalar array1[4];
+  EIGEN_ALIGN16 Scalar array2[4];
+  EIGEN_ALIGN16 Scalar array3[4+1];
+  Scalar* array3unaligned = array3+1;
+  
+  MQuaternionA    mq1(array1);
+  MCQuaternionA   mcq1(array1);
+  MQuaternionA    mq2(array2);
+  MQuaternionUA   mq3(array3unaligned);
+  MCQuaternionUA  mcq3(array3unaligned);
+
+//  std::cerr << array1 << " " << array2 << " " << array3 << "\n";
+  mq1 = AngleAxisx(a, v0.normalized());
+  mq2 = mq1;
+  mq3 = mq1;
+
+  Quaternionx q1 = mq1;
+  Quaternionx q2 = mq2;
+  Quaternionx q3 = mq3;
+  Quaternionx q4 = MCQuaternionUA(array3unaligned);
+
+  VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
+  VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs());
+  VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs());
+  #ifdef EIGEN_VECTORIZE
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned)));
+  #endif
+    
+  VERIFY_IS_APPROX(mq1 * (mq1.inverse() * v1), v1);
+  VERIFY_IS_APPROX(mq1 * (mq1.conjugate() * v1), v1);
+  
+  VERIFY_IS_APPROX(mcq1 * (mcq1.inverse() * v1), v1);
+  VERIFY_IS_APPROX(mcq1 * (mcq1.conjugate() * v1), v1);
+  
+  VERIFY_IS_APPROX(mq3 * (mq3.inverse() * v1), v1);
+  VERIFY_IS_APPROX(mq3 * (mq3.conjugate() * v1), v1);
+  
+  VERIFY_IS_APPROX(mcq3 * (mcq3.inverse() * v1), v1);
+  VERIFY_IS_APPROX(mcq3 * (mcq3.conjugate() * v1), v1);
+  
+  VERIFY_IS_APPROX(mq1*mq2, q1*q2);
+  VERIFY_IS_APPROX(mq3*mq2, q3*q2);
+  VERIFY_IS_APPROX(mcq1*mq2, q1*q2);
+  VERIFY_IS_APPROX(mcq3*mq2, q3*q2);
+}
+
+template<typename Scalar> void quaternionAlignment(void){
+  typedef Quaternion<Scalar,AutoAlign> QuaternionA;
+  typedef Quaternion<Scalar,DontAlign> QuaternionUA;
+
+  EIGEN_ALIGN16 Scalar array1[4];
+  EIGEN_ALIGN16 Scalar array2[4];
+  EIGEN_ALIGN16 Scalar array3[4+1];
+  Scalar* arrayunaligned = array3+1;
+
+  QuaternionA *q1 = ::new(reinterpret_cast<void*>(array1)) QuaternionA;
+  QuaternionUA *q2 = ::new(reinterpret_cast<void*>(array2)) QuaternionUA;
+  QuaternionUA *q3 = ::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionUA;
+
+  q1->coeffs().setRandom();
+  *q2 = *q1;
+  *q3 = *q1;
+
+  VERIFY_IS_APPROX(q1->coeffs(), q2->coeffs());
+  VERIFY_IS_APPROX(q1->coeffs(), q3->coeffs());
+  #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(arrayunaligned)) QuaternionA));
+  #endif
+}
+
+template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
+{
+  // there's a lot that we can't test here while still having this test compile!
+  // the only possible approach would be to run a script trying to compile stuff and checking that it fails.
+  // CMake can help with that.
+
+  // verify that map-to-const don't have LvalueBit
+  typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
+  VERIFY( !(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit) );
+  VERIFY( !(internal::traits<Map<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+  VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
+  VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+}
+
+void test_geo_quaternion()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
+    CALL_SUBTEST_1( check_const_correctness(Quaternionf()) );
+    CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
+    CALL_SUBTEST_2( check_const_correctness(Quaterniond()) );
+    CALL_SUBTEST_3(( quaternion<float,DontAlign>() ));
+    CALL_SUBTEST_4(( quaternion<double,DontAlign>() ));
+    CALL_SUBTEST_5(( quaternionAlignment<float>() ));
+    CALL_SUBTEST_6(( quaternionAlignment<double>() ));
+    CALL_SUBTEST_1( mapQuaternion<float>() );
+    CALL_SUBTEST_2( mapQuaternion<double>() );
+  }
+}
diff --git a/test/geo_transformations.cpp b/test/geo_transformations.cpp
new file mode 100644
index 0000000..5477657
--- /dev/null
+++ b/test/geo_transformations.cpp
@@ -0,0 +1,521 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename Scalar, int Mode, int Options> void non_projective_only()
+{
+    /* this test covers the following files:
+     Cross.h Quaternion.h, Transform.cpp
+  */
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Quaternion<Scalar> Quaternionx;
+  typedef AngleAxis<Scalar> AngleAxisx;
+  typedef Transform<Scalar,3,Mode,Options> Transform3;
+  typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
+  typedef Translation<Scalar,3> Translation3;
+
+  Vector3 v0 = Vector3::Random(),
+          v1 = Vector3::Random();
+
+  Transform3 t0, t1, t2;
+
+  Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+  Quaternionx q1, q2;
+
+  q1 = AngleAxisx(a, v0.normalized());
+
+  t0 = Transform3::Identity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+
+  t0.linear() = q1.toRotationMatrix();
+
+  v0 << 50, 2, 1;
+  t0.scale(v0);
+
+  VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).template head<3>().norm(), v0.x());
+
+  t0.setIdentity();
+  t1.setIdentity();
+  v1 << 1, 2, 3;
+  t0.linear() = q1.toRotationMatrix();
+  t0.pretranslate(v0);
+  t0.scale(v1);
+  t1.linear() = q1.conjugate().toRotationMatrix();
+  t1.prescale(v1.cwiseInverse());
+  t1.translate(-v0);
+
+  VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
+
+  t1.fromPositionOrientationScale(v0, q1, v1);
+  VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
+  VERIFY_IS_APPROX(t1*v1, t0*v1);
+
+  // translation * vector
+  t0.setIdentity();
+  t0.translate(v0);
+  VERIFY_IS_APPROX((t0 * v1).template head<3>(), Translation3(v0) * v1);
+
+  // AlignedScaling * vector
+  t0.setIdentity();
+  t0.scale(v0);
+  VERIFY_IS_APPROX((t0 * v1).template head<3>(), AlignedScaling3(v0) * v1);
+}
+
+template<typename Scalar, int Mode, int Options> void transformations()
+{
+  /* this test covers the following files:
+     Cross.h Quaternion.h, Transform.cpp
+  */
+  using std::cos;
+  using std::abs;
+  typedef Matrix<Scalar,3,3> Matrix3;
+  typedef Matrix<Scalar,4,4> Matrix4;
+  typedef Matrix<Scalar,2,1> Vector2;
+  typedef Matrix<Scalar,3,1> Vector3;
+  typedef Matrix<Scalar,4,1> Vector4;
+  typedef Quaternion<Scalar> Quaternionx;
+  typedef AngleAxis<Scalar> AngleAxisx;
+  typedef Transform<Scalar,2,Mode,Options> Transform2;
+  typedef Transform<Scalar,3,Mode,Options> Transform3;
+  typedef typename Transform3::MatrixType MatrixType;
+  typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
+  typedef Translation<Scalar,2> Translation2;
+  typedef Translation<Scalar,3> Translation3;
+
+  Vector3 v0 = Vector3::Random(),
+          v1 = Vector3::Random();
+  Matrix3 matrot1, m;
+
+  Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+  Scalar s0 = internal::random<Scalar>(),
+         s1 = internal::random<Scalar>();
+  
+  while(v0.norm() < test_precision<Scalar>()) v0 = Vector3::Random();
+  while(v1.norm() < test_precision<Scalar>()) v1 = Vector3::Random();
+    
+
+  VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
+  VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
+  if(abs(cos(a)) > test_precision<Scalar>())
+  {
+    VERIFY_IS_APPROX(cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
+  }
+  m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
+  VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
+  VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
+
+  Quaternionx q1, q2;
+  q1 = AngleAxisx(a, v0.normalized());
+  q2 = AngleAxisx(a, v1.normalized());
+
+  // rotation matrix conversion
+  matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
+          * AngleAxisx(Scalar(0.2), Vector3::UnitY())
+          * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
+  VERIFY_IS_APPROX(matrot1 * v1,
+       AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
+    * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
+
+  // angle-axis conversion
+  AngleAxisx aa = AngleAxisx(q1);
+  VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+  
+  if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision())
+  {
+    VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
+  }
+
+  aa.fromRotationMatrix(aa.toRotationMatrix());
+  VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+  if(abs(aa.angle()) > NumTraits<Scalar>::dummy_precision())
+  {
+    VERIFY( !(q1 * v1).isApprox(Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1) );
+  }
+
+  // AngleAxis
+  VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
+    Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
+
+  AngleAxisx aa1;
+  m = q1.toRotationMatrix();
+  aa1 = m;
+  VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
+    Quaternionx(m).toRotationMatrix());
+
+  // Transform
+  // TODO complete the tests !
+  a = 0;
+  while (abs(a)<Scalar(0.1))
+    a = internal::random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
+  q1 = AngleAxisx(a, v0.normalized());
+  Transform3 t0, t1, t2;
+
+  // first test setIdentity() and Identity()
+  t0.setIdentity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+  t0.matrix().setZero();
+  t0 = Transform3::Identity();
+  VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
+
+  t0.setIdentity();
+  t1.setIdentity();
+  v1 << 1, 2, 3;
+  t0.linear() = q1.toRotationMatrix();
+  t0.pretranslate(v0);
+  t0.scale(v1);
+  t1.linear() = q1.conjugate().toRotationMatrix();
+  t1.prescale(v1.cwiseInverse());
+  t1.translate(-v0);
+
+  VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
+
+  t1.fromPositionOrientationScale(v0, q1, v1);
+  VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
+
+  t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
+  t1.setIdentity(); t1.scale(v0).rotate(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
+  VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
+
+  // More transform constructors, operator=, operator*=
+
+  Matrix3 mat3 = Matrix3::Random();
+  Matrix4 mat4;
+  mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
+  Transform3 tmat3(mat3), tmat4(mat4);
+  if(Mode!=int(AffineCompact))
+    tmat4.matrix()(3,3) = Scalar(1);
+  VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
+
+  Scalar a3 = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+  Vector3 v3 = Vector3::Random().normalized();
+  AngleAxisx aa3(a3, v3);
+  Transform3 t3(aa3);
+  Transform3 t4;
+  t4 = aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+  t4.rotate(AngleAxisx(-a3,v3));
+  VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
+  t4 *= aa3;
+  VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
+
+  v3 = Vector3::Random();
+  Translation3 tv3(v3);
+  Transform3 t5(tv3);
+  t4 = tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+  t4.translate(-v3);
+  VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
+  t4 *= tv3;
+  VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
+
+  AlignedScaling3 sv3(v3);
+  Transform3 t6(sv3);
+  t4 = sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+  t4.scale(v3.cwiseInverse());
+  VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
+  t4 *= sv3;
+  VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
+
+  // matrix * transform
+  VERIFY_IS_APPROX((t3.matrix()*t4).matrix(), (t3*t4).matrix());
+
+  // chained Transform product
+  VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
+
+  // check that Transform product doesn't have aliasing problems
+  t5 = t4;
+  t5 = t5*t5;
+  VERIFY_IS_APPROX(t5, t4*t4);
+
+  // 2D transformation
+  Transform2 t20, t21;
+  Vector2 v20 = Vector2::Random();
+  Vector2 v21 = Vector2::Random();
+  for (int k=0; k<2; ++k)
+    if (abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
+  VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
+    t21.pretranslate(v20).scale(v21).matrix());
+
+  t21.setIdentity();
+  t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
+  VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
+        * (t21.prescale(v21.cwiseInverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
+
+  // Transform - new API
+  // 3D
+  t0.setIdentity();
+  t0.rotate(q1).scale(v0).translate(v0);
+  // mat * aligned scaling and mat * translation
+  t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  t1 = (Matrix3(q1) * Eigen::Scaling(v0)) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  t1 = (q1 * Eigen::Scaling(v0)) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // mat * transformation and aligned scaling * translation
+  t1 = Matrix3(q1) * (AlignedScaling3(v0) * Translation3(v0));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+
+  t0.setIdentity();
+  t0.scale(s0).translate(v0);
+  t1 = Eigen::Scaling(s0) * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  t0.prescale(s0);
+  t1 = Eigen::Scaling(s0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  
+  t0 = t3;
+  t0.scale(s0);
+  t1 = t3 * Eigen::Scaling(s0,s0,s0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  t0.prescale(s0);
+  t1 = Eigen::Scaling(s0,s0,s0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0 = t3;
+  t0.scale(s0);
+  t1 = t3 * Eigen::Scaling(s0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  t0.prescale(s0);
+  t1 = Eigen::Scaling(s0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.prerotate(q1).prescale(v0).pretranslate(v0);
+  // translation * aligned scaling and transformation * mat
+  t1 = (Translation3(v0) * AlignedScaling3(v0)) * Transform3(q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // scaling * mat and translation * mat
+  t1 = Translation3(v0) * (AlignedScaling3(v0) * Transform3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  t0.setIdentity();
+  t0.scale(v0).translate(v0).rotate(q1);
+  // translation * mat and aligned scaling * transformation
+  t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * aligned scaling
+  t0.scale(v0);
+  t1 *= AlignedScaling3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // transformation * translation
+  t0.translate(v0);
+  t1 = t1 * Translation3(v0);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+  // translation * transformation
+  t0.pretranslate(v0);
+  t1 = Translation3(v0) * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // transform * quaternion
+  t0.rotate(q1);
+  t1 = t1 * q1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // translation * quaternion
+  t0.translate(v1).rotate(q1);
+  t1 = t1 * (Translation3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // aligned scaling * quaternion
+  t0.scale(v1).rotate(q1);
+  t1 = t1 * (AlignedScaling3(v1) * q1);
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * transform
+  t0.prerotate(q1);
+  t1 = q1 * t1;
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * translation
+  t0.rotate(q1).translate(v1);
+  t1 = t1 * (q1 * Translation3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // quaternion * aligned scaling
+  t0.rotate(q1).scale(v1);
+  t1 = t1 * (q1 * AlignedScaling3(v1));
+  VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
+
+  // test transform inversion
+  t0.setIdentity();
+  t0.translate(v0);
+  do {
+    t0.linear().setRandom();
+  } while(t0.linear().jacobiSvd().singularValues()(2)<test_precision<Scalar>());
+  Matrix4 t044 = Matrix4::Zero();
+  t044(3,3) = 1;
+  t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
+  VERIFY_IS_APPROX(t0.inverse(Affine).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1);
+  t044 = Matrix4::Zero();
+  t044(3,3) = 1;
+  t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
+  VERIFY_IS_APPROX(t0.inverse(Isometry).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
+
+  Matrix3 mat_rotation, mat_scaling;
+  t0.setIdentity();
+  t0.translate(v0).rotate(q1).scale(v1);
+  t0.computeRotationScaling(&mat_rotation, &mat_scaling);
+  VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+  t0.computeScalingRotation(&mat_scaling, &mat_rotation);
+  VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
+  VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
+  VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
+
+  // test casting
+  Transform<float,3,Mode> t1f = t1.template cast<float>();
+  VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
+  Transform<double,3,Mode> t1d = t1.template cast<double>();
+  VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
+
+  Translation3 tr1(v0);
+  Translation<float,3> tr1f = tr1.template cast<float>();
+  VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
+  Translation<double,3> tr1d = tr1.template cast<double>();
+  VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
+
+  AngleAxis<float> aa1f = aa1.template cast<float>();
+  VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
+  AngleAxis<double> aa1d = aa1.template cast<double>();
+  VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
+
+  Rotation2D<Scalar> r2d1(internal::random<Scalar>());
+  Rotation2D<float> r2d1f = r2d1.template cast<float>();
+  VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
+  Rotation2D<double> r2d1d = r2d1.template cast<double>();
+  VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
+
+  t20 = Translation2(v20) * (Rotation2D<Scalar>(s0) * Eigen::Scaling(s0));
+  t21 = Translation2(v20) * Rotation2D<Scalar>(s0) * Eigen::Scaling(s0);
+  VERIFY_IS_APPROX(t20,t21);
+  
+  Rotation2D<Scalar> R0(s0), R1(s1);
+  t20 = Translation2(v20) * (R0 * Eigen::Scaling(s0));
+  t21 = Translation2(v20) * R0 * Eigen::Scaling(s0);
+  VERIFY_IS_APPROX(t20,t21);
+  
+  t20 = Translation2(v20) * (R0 * R0.inverse() * Eigen::Scaling(s0));
+  t21 = Translation2(v20) * Eigen::Scaling(s0);
+  VERIFY_IS_APPROX(t20,t21);
+  
+  VERIFY_IS_APPROX(s0, (R0.slerp(0, R1)).angle());
+  VERIFY_IS_APPROX(s1, (R0.slerp(1, R1)).angle());
+  VERIFY_IS_APPROX(s0, (R0.slerp(0.5, R0)).angle());
+  VERIFY_IS_APPROX(Scalar(0), (R0.slerp(0.5, R0.inverse())).angle());
+  
+  // check basic features
+  {
+    Rotation2D<Scalar> r1;           // default ctor
+    r1 = Rotation2D<Scalar>(s0);     // copy assignment
+    VERIFY_IS_APPROX(r1.angle(),s0);
+    Rotation2D<Scalar> r2(r1);       // copy ctor
+    VERIFY_IS_APPROX(r2.angle(),s0);
+  }
+}
+
+template<typename Scalar> void transform_alignment()
+{
+  typedef Transform<Scalar,3,Projective,AutoAlign> Projective3a;
+  typedef Transform<Scalar,3,Projective,DontAlign> Projective3u;
+
+  EIGEN_ALIGN16 Scalar array1[16];
+  EIGEN_ALIGN16 Scalar array2[16];
+  EIGEN_ALIGN16 Scalar array3[16+1];
+  Scalar* array3u = array3+1;
+
+  Projective3a *p1 = ::new(reinterpret_cast<void*>(array1)) Projective3a;
+  Projective3u *p2 = ::new(reinterpret_cast<void*>(array2)) Projective3u;
+  Projective3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Projective3u;
+  
+  p1->matrix().setRandom();
+  *p2 = *p1;
+  *p3 = *p1;
+
+  VERIFY_IS_APPROX(p1->matrix(), p2->matrix());
+  VERIFY_IS_APPROX(p1->matrix(), p3->matrix());
+  
+  VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
+  
+  #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
+  #endif
+}
+
+template<typename Scalar, int Dim, int Options> void transform_products()
+{
+  typedef Matrix<Scalar,Dim+1,Dim+1> Mat;
+  typedef Transform<Scalar,Dim,Projective,Options> Proj;
+  typedef Transform<Scalar,Dim,Affine,Options> Aff;
+  typedef Transform<Scalar,Dim,AffineCompact,Options> AffC;
+
+  Proj p; p.matrix().setRandom();
+  Aff a; a.linear().setRandom(); a.translation().setRandom();
+  AffC ac = a;
+
+  Mat p_m(p.matrix()), a_m(a.matrix());
+
+  VERIFY_IS_APPROX((p*p).matrix(), p_m*p_m);
+  VERIFY_IS_APPROX((a*a).matrix(), a_m*a_m);
+  VERIFY_IS_APPROX((p*a).matrix(), p_m*a_m);
+  VERIFY_IS_APPROX((a*p).matrix(), a_m*p_m);
+  VERIFY_IS_APPROX((ac*a).matrix(), a_m*a_m);
+  VERIFY_IS_APPROX((a*ac).matrix(), a_m*a_m);
+  VERIFY_IS_APPROX((p*ac).matrix(), p_m*a_m);
+  VERIFY_IS_APPROX((ac*p).matrix(), a_m*p_m);
+}
+
+void test_geo_transformations()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(( transformations<double,Affine,AutoAlign>() ));
+    CALL_SUBTEST_1(( non_projective_only<double,Affine,AutoAlign>() ));
+    
+    CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
+    CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
+    CALL_SUBTEST_2(( transform_alignment<float>() ));
+    
+    CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
+    CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
+    CALL_SUBTEST_3(( transform_alignment<double>() ));
+    
+    CALL_SUBTEST_4(( transformations<float,Affine,RowMajor|AutoAlign>() ));
+    CALL_SUBTEST_4(( non_projective_only<float,Affine,RowMajor>() ));
+    
+    CALL_SUBTEST_5(( transformations<double,AffineCompact,RowMajor|AutoAlign>() ));
+    CALL_SUBTEST_5(( non_projective_only<double,AffineCompact,RowMajor>() ));
+
+    CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|AutoAlign>() ));
+    CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|DontAlign>() ));
+
+
+    CALL_SUBTEST_7(( transform_products<double,3,RowMajor|AutoAlign>() ));
+    CALL_SUBTEST_7(( transform_products<float,2,AutoAlign>() ));
+  }
+}
diff --git a/test/hessenberg.cpp b/test/hessenberg.cpp
new file mode 100644
index 0000000..96bc19e
--- /dev/null
+++ b/test/hessenberg.cpp
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2010 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/Eigenvalues>
+
+template<typename Scalar,int Size> void hessenberg(int size = Size)
+{
+  typedef Matrix<Scalar,Size,Size> MatrixType;
+
+  // Test basic functionality: A = U H U* and H is Hessenberg
+  for(int counter = 0; counter < g_repeat; ++counter) {
+    MatrixType m = MatrixType::Random(size,size);
+    HessenbergDecomposition<MatrixType> hess(m);
+    MatrixType Q = hess.matrixQ();
+    MatrixType H = hess.matrixH();
+    VERIFY_IS_APPROX(m, Q * H * Q.adjoint());
+    for(int row = 2; row < size; ++row) {
+      for(int col = 0; col < row-1; ++col) {
+	VERIFY(H(row,col) == (typename MatrixType::Scalar)0);
+      }
+    }
+  }
+
+  // Test whether compute() and constructor returns same result
+  MatrixType A = MatrixType::Random(size, size);
+  HessenbergDecomposition<MatrixType> cs1;
+  cs1.compute(A);
+  HessenbergDecomposition<MatrixType> cs2(A);
+  VERIFY_IS_EQUAL(cs1.matrixH().eval(), cs2.matrixH().eval());
+  MatrixType cs1Q = cs1.matrixQ();
+  MatrixType cs2Q = cs2.matrixQ();  
+  VERIFY_IS_EQUAL(cs1Q, cs2Q);
+
+  // Test assertions for when used uninitialized
+  HessenbergDecomposition<MatrixType> hessUninitialized;
+  VERIFY_RAISES_ASSERT( hessUninitialized.matrixH() );
+  VERIFY_RAISES_ASSERT( hessUninitialized.matrixQ() );
+  VERIFY_RAISES_ASSERT( hessUninitialized.householderCoefficients() );
+  VERIFY_RAISES_ASSERT( hessUninitialized.packedMatrix() );
+
+  // TODO: Add tests for packedMatrix() and householderCoefficients()
+}
+
+void test_hessenberg()
+{
+  CALL_SUBTEST_1(( hessenberg<std::complex<double>,1>() ));
+  CALL_SUBTEST_2(( hessenberg<std::complex<double>,2>() ));
+  CALL_SUBTEST_3(( hessenberg<std::complex<float>,4>() ));
+  CALL_SUBTEST_4(( hessenberg<float,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+  CALL_SUBTEST_5(( hessenberg<std::complex<double>,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+
+  // Test problem size constructors
+  CALL_SUBTEST_6(HessenbergDecomposition<MatrixXf>(10));
+}
diff --git a/test/householder.cpp b/test/householder.cpp
new file mode 100644
index 0000000..c5f6b5e
--- /dev/null
+++ b/test/householder.cpp
@@ -0,0 +1,138 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename MatrixType> void householder(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  static bool even = true;
+  even = !even;
+  /* this test covers the following files:
+     Householder.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, internal::decrement_size<MatrixType::RowsAtCompileTime>::ret, 1> EssentialVectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  typedef Matrix<Scalar, Dynamic, MatrixType::ColsAtCompileTime> HBlockMatrixType;
+  typedef Matrix<Scalar, Dynamic, 1> HCoeffsVectorType;
+
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::RowsAtCompileTime> TMatrixType;
+  
+  Matrix<Scalar, EIGEN_SIZE_MAX(MatrixType::RowsAtCompileTime,MatrixType::ColsAtCompileTime), 1> _tmp((std::max)(rows,cols));
+  Scalar* tmp = &_tmp.coeffRef(0,0);
+
+  Scalar beta;
+  RealScalar alpha;
+  EssentialVectorType essential;
+
+  VectorType v1 = VectorType::Random(rows), v2;
+  v2 = v1;
+  v1.makeHouseholder(essential, beta, alpha);
+  v1.applyHouseholderOnTheLeft(essential,beta,tmp);
+  VERIFY_IS_APPROX(v1.norm(), v2.norm());
+  if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(v1.tail(rows-1).norm(), v1.norm());
+  v1 = VectorType::Random(rows);
+  v2 = v1;
+  v1.applyHouseholderOnTheLeft(essential,beta,tmp);
+  VERIFY_IS_APPROX(v1.norm(), v2.norm());
+
+  MatrixType m1(rows, cols),
+             m2(rows, cols);
+
+  v1 = VectorType::Random(rows);
+  if(even) v1.tail(rows-1).setZero();
+  m1.colwise() = v1;
+  m2 = m1;
+  m1.col(0).makeHouseholder(essential, beta, alpha);
+  m1.applyHouseholderOnTheLeft(essential,beta,tmp);
+  VERIFY_IS_APPROX(m1.norm(), m2.norm());
+  if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m1.block(1,0,rows-1,cols).norm(), m1.norm());
+  VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m1(0,0)), numext::real(m1(0,0)));
+  VERIFY_IS_APPROX(numext::real(m1(0,0)), alpha);
+
+  v1 = VectorType::Random(rows);
+  if(even) v1.tail(rows-1).setZero();
+  SquareMatrixType m3(rows,rows), m4(rows,rows);
+  m3.rowwise() = v1.transpose();
+  m4 = m3;
+  m3.row(0).makeHouseholder(essential, beta, alpha);
+  m3.applyHouseholderOnTheRight(essential,beta,tmp);
+  VERIFY_IS_APPROX(m3.norm(), m4.norm());
+  if(rows>=2) VERIFY_IS_MUCH_SMALLER_THAN(m3.block(0,1,rows,rows-1).norm(), m3.norm());
+  VERIFY_IS_MUCH_SMALLER_THAN(numext::imag(m3(0,0)), numext::real(m3(0,0)));
+  VERIFY_IS_APPROX(numext::real(m3(0,0)), alpha);
+
+  // test householder sequence on the left with a shift
+
+  Index shift = internal::random<Index>(0, std::max<Index>(rows-2,0));
+  Index brows = rows - shift;
+  m1.setRandom(rows, cols);
+  HBlockMatrixType hbm = m1.block(shift,0,brows,cols);
+  HouseholderQR<HBlockMatrixType> qr(hbm);
+  m2 = m1;
+  m2.block(shift,0,brows,cols) = qr.matrixQR();
+  HCoeffsVectorType hc = qr.hCoeffs().conjugate();
+  HouseholderSequence<MatrixType, HCoeffsVectorType> hseq(m2, hc);
+  hseq.setLength(hc.size()).setShift(shift);
+  VERIFY(hseq.length() == hc.size());
+  VERIFY(hseq.shift() == shift);
+  
+  MatrixType m5 = m2;
+  m5.block(shift,0,brows,cols).template triangularView<StrictlyLower>().setZero();
+  VERIFY_IS_APPROX(hseq * m5, m1); // test applying hseq directly
+  m3 = hseq;
+  VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating hseq to a dense matrix, then applying
+  
+  SquareMatrixType hseq_mat = hseq;
+  SquareMatrixType hseq_mat_conj = hseq.conjugate();
+  SquareMatrixType hseq_mat_adj = hseq.adjoint();
+  SquareMatrixType hseq_mat_trans = hseq.transpose();
+  SquareMatrixType m6 = SquareMatrixType::Random(rows, rows);
+  VERIFY_IS_APPROX(hseq_mat.adjoint(),    hseq_mat_adj);
+  VERIFY_IS_APPROX(hseq_mat.conjugate(),  hseq_mat_conj);
+  VERIFY_IS_APPROX(hseq_mat.transpose(),  hseq_mat_trans);
+  VERIFY_IS_APPROX(hseq_mat * m6,             hseq_mat * m6);
+  VERIFY_IS_APPROX(hseq_mat.adjoint() * m6,   hseq_mat_adj * m6);
+  VERIFY_IS_APPROX(hseq_mat.conjugate() * m6, hseq_mat_conj * m6);
+  VERIFY_IS_APPROX(hseq_mat.transpose() * m6, hseq_mat_trans * m6);
+  VERIFY_IS_APPROX(m6 * hseq_mat,             m6 * hseq_mat);
+  VERIFY_IS_APPROX(m6 * hseq_mat.adjoint(),   m6 * hseq_mat_adj);
+  VERIFY_IS_APPROX(m6 * hseq_mat.conjugate(), m6 * hseq_mat_conj);
+  VERIFY_IS_APPROX(m6 * hseq_mat.transpose(), m6 * hseq_mat_trans);
+
+  // test householder sequence on the right with a shift
+
+  TMatrixType tm2 = m2.transpose();
+  HouseholderSequence<TMatrixType, HCoeffsVectorType, OnTheRight> rhseq(tm2, hc);
+  rhseq.setLength(hc.size()).setShift(shift);
+  VERIFY_IS_APPROX(rhseq * m5, m1); // test applying rhseq directly
+  m3 = rhseq;
+  VERIFY_IS_APPROX(m3 * m5, m1); // test evaluating rhseq to a dense matrix, then applying
+}
+
+void test_householder()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( householder(Matrix<double,2,2>()) );
+    CALL_SUBTEST_2( householder(Matrix<float,2,3>()) );
+    CALL_SUBTEST_3( householder(Matrix<double,3,5>()) );
+    CALL_SUBTEST_4( householder(Matrix<float,4,4>()) );
+    CALL_SUBTEST_5( householder(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_6( householder(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_7( householder(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_8( householder(Matrix<double,1,1>()) );
+  }
+}
diff --git a/test/integer_types.cpp b/test/integer_types.cpp
new file mode 100644
index 0000000..950f8e9
--- /dev/null
+++ b/test/integer_types.cpp
@@ -0,0 +1,161 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+
+#include "main.h"
+
+#undef VERIFY_IS_APPROX
+#define VERIFY_IS_APPROX(a, b) VERIFY((a)==(b));
+#undef VERIFY_IS_NOT_APPROX
+#define VERIFY_IS_NOT_APPROX(a, b) VERIFY((a)!=(b));
+
+template<typename MatrixType> void signed_integer_type_tests(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
+  VERIFY(is_signed == 1);
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             mzero = MatrixType::Zero(rows, cols);
+
+  do {
+    m1 = MatrixType::Random(rows, cols);
+  } while(m1 == mzero || m1 == m2);
+
+  // check linear structure
+
+  Scalar s1;
+  do {
+    s1 = internal::random<Scalar>();
+  } while(s1 == 0);
+
+  VERIFY_IS_EQUAL(-(-m1),                  m1);
+  VERIFY_IS_EQUAL(-m2+m1+m2,               m1);
+  VERIFY_IS_EQUAL((-m1+m2)*s1,             -s1*m1+s1*m2);
+}
+
+template<typename MatrixType> void integer_type_tests(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  VERIFY(NumTraits<Scalar>::IsInteger);
+  enum { is_signed = (Scalar(-1) > Scalar(0)) ? 0 : 1 };
+  VERIFY(int(NumTraits<Scalar>::IsSigned) == is_signed);
+
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             mzero = MatrixType::Zero(rows, cols);
+
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;
+  SquareMatrixType identity = SquareMatrixType::Identity(rows, rows),
+                   square = SquareMatrixType::Random(rows, rows);
+  VectorType v1(rows),
+             v2 = VectorType::Random(rows),
+             vzero = VectorType::Zero(rows);
+
+  do {
+    m1 = MatrixType::Random(rows, cols);
+  } while(m1 == mzero || m1 == m2);
+
+  do {
+    v1 = VectorType::Random(rows);
+  } while(v1 == vzero || v1 == v2);
+
+  VERIFY_IS_APPROX(               v1,    v1);
+  VERIFY_IS_NOT_APPROX(           v1,    2*v1);
+  VERIFY_IS_APPROX(               vzero, v1-v1);
+  VERIFY_IS_APPROX(               m1,    m1);
+  VERIFY_IS_NOT_APPROX(           m1,    2*m1);
+  VERIFY_IS_APPROX(               mzero, m1-m1);
+
+  VERIFY_IS_APPROX(m3 = m1,m1);
+  MatrixType m4;
+  VERIFY_IS_APPROX(m4 = m1,m1);
+
+  m3.real() = m1.real();
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), static_cast<const MatrixType&>(m1).real());
+  VERIFY_IS_APPROX(static_cast<const MatrixType&>(m3).real(), m1.real());
+
+  // check == / != operators
+  VERIFY(m1==m1);
+  VERIFY(m1!=m2);
+  VERIFY(!(m1==m2));
+  VERIFY(!(m1!=m1));
+  m1 = m2;
+  VERIFY(m1==m2);
+  VERIFY(!(m1!=m2));
+
+  // check linear structure
+
+  Scalar s1;
+  do {
+    s1 = internal::random<Scalar>();
+  } while(s1 == 0);
+
+  VERIFY_IS_EQUAL(m1+m1,                   2*m1);
+  VERIFY_IS_EQUAL(m1+m2-m1,                m2);
+  VERIFY_IS_EQUAL(m1*s1,                   s1*m1);
+  VERIFY_IS_EQUAL((m1+m2)*s1,              s1*m1+s1*m2);
+  m3 = m2; m3 += m1;
+  VERIFY_IS_EQUAL(m3,                      m1+m2);
+  m3 = m2; m3 -= m1;
+  VERIFY_IS_EQUAL(m3,                      m2-m1);
+  m3 = m2; m3 *= s1;
+  VERIFY_IS_EQUAL(m3,                      s1*m2);
+
+  // check matrix product.
+
+  VERIFY_IS_APPROX(identity * m1, m1);
+  VERIFY_IS_APPROX(square * (m1 + m2), square * m1 + square * m2);
+  VERIFY_IS_APPROX((m1 + m2).transpose() * square, m1.transpose() * square + m2.transpose() * square);
+  VERIFY_IS_APPROX((m1 * m2.transpose()) * m1, m1 * (m2.transpose() * m1));
+}
+
+void test_integer_types()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned int, 1, 1>()) );
+    CALL_SUBTEST_1( integer_type_tests(Matrix<unsigned long, 3, 4>()) );
+
+    CALL_SUBTEST_2( integer_type_tests(Matrix<long, 2, 2>()) );
+    CALL_SUBTEST_2( signed_integer_type_tests(Matrix<long, 2, 2>()) );
+
+    CALL_SUBTEST_3( integer_type_tests(Matrix<char, 2, Dynamic>(2, 10)) );
+    CALL_SUBTEST_3( signed_integer_type_tests(Matrix<signed char, 2, Dynamic>(2, 10)) );
+
+    CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, 3, 3>()) );
+    CALL_SUBTEST_4( integer_type_tests(Matrix<unsigned char, Dynamic, Dynamic>(20, 20)) );
+
+    CALL_SUBTEST_5( integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
+    CALL_SUBTEST_5( signed_integer_type_tests(Matrix<short, Dynamic, 4>(7, 4)) );
+
+    CALL_SUBTEST_6( integer_type_tests(Matrix<unsigned short, 4, 4>()) );
+
+    CALL_SUBTEST_7( integer_type_tests(Matrix<long long, 11, 13>()) );
+    CALL_SUBTEST_7( signed_integer_type_tests(Matrix<long long, 11, 13>()) );
+
+    CALL_SUBTEST_8( integer_type_tests(Matrix<unsigned long long, Dynamic, 5>(1, 5)) );
+  }
+}
diff --git a/test/inverse.cpp b/test/inverse.cpp
new file mode 100644
index 0000000..8187b08
--- /dev/null
+++ b/test/inverse.cpp
@@ -0,0 +1,104 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+
+template<typename MatrixType> void inverse(const MatrixType& m)
+{
+  using std::abs;
+  typedef typename MatrixType::Index Index;
+  /* this test covers the following files:
+     Inverse.h
+  */
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+
+  MatrixType m1(rows, cols),
+             m2(rows, cols),
+             identity = MatrixType::Identity(rows, rows);
+  createRandomPIMatrixOfRank(rows,rows,rows,m1);
+  m2 = m1.inverse();
+  VERIFY_IS_APPROX(m1, m2.inverse() );
+
+  VERIFY_IS_APPROX((Scalar(2)*m2).inverse(), m2.inverse()*Scalar(0.5));
+
+  VERIFY_IS_APPROX(identity, m1.inverse() * m1 );
+  VERIFY_IS_APPROX(identity, m1 * m1.inverse() );
+
+  VERIFY_IS_APPROX(m1, m1.inverse().inverse() );
+
+  // since for the general case we implement separately row-major and col-major, test that
+  VERIFY_IS_APPROX(MatrixType(m1.transpose().inverse()), MatrixType(m1.inverse().transpose()));
+
+#if !defined(EIGEN_TEST_PART_5) && !defined(EIGEN_TEST_PART_6)
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
+  
+  //computeInverseAndDetWithCheck tests
+  //First: an invertible matrix
+  bool invertible;
+  RealScalar det;
+
+  m2.setZero();
+  m1.computeInverseAndDetWithCheck(m2, det, invertible);
+  VERIFY(invertible);
+  VERIFY_IS_APPROX(identity, m1*m2);
+  VERIFY_IS_APPROX(det, m1.determinant());
+
+  m2.setZero();
+  m1.computeInverseWithCheck(m2, invertible);
+  VERIFY(invertible);
+  VERIFY_IS_APPROX(identity, m1*m2);
+
+  //Second: a rank one matrix (not invertible, except for 1x1 matrices)
+  VectorType v3 = VectorType::Random(rows);
+  MatrixType m3 = v3*v3.transpose(), m4(rows,cols);
+  m3.computeInverseAndDetWithCheck(m4, det, invertible);
+  VERIFY( rows==1 ? invertible : !invertible );
+  VERIFY_IS_MUCH_SMALLER_THAN(abs(det-m3.determinant()), RealScalar(1));
+  m3.computeInverseWithCheck(m4, invertible);
+  VERIFY( rows==1 ? invertible : !invertible );
+#endif
+
+  // check in-place inversion
+  if(MatrixType::RowsAtCompileTime>=2 && MatrixType::RowsAtCompileTime<=4)
+  {
+    // in-place is forbidden
+    VERIFY_RAISES_ASSERT(m1 = m1.inverse());
+  }
+  else
+  {
+    m2 = m1.inverse();
+    m1 = m1.inverse();
+    VERIFY_IS_APPROX(m1,m2);
+  }
+}
+
+void test_inverse()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
+    CALL_SUBTEST_2( inverse(Matrix2d()) );
+    CALL_SUBTEST_3( inverse(Matrix3f()) );
+    CALL_SUBTEST_4( inverse(Matrix4f()) );
+    CALL_SUBTEST_4( inverse(Matrix<float,4,4,DontAlign>()) );
+    s = internal::random<int>(50,320); 
+    CALL_SUBTEST_5( inverse(MatrixXf(s,s)) );
+    s = internal::random<int>(25,100);
+    CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) );
+    CALL_SUBTEST_7( inverse(Matrix4d()) );
+    CALL_SUBTEST_7( inverse(Matrix<double,4,4,DontAlign>()) );
+  }
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/jacobi.cpp b/test/jacobi.cpp
new file mode 100644
index 0000000..7ccd412
--- /dev/null
+++ b/test/jacobi.cpp
@@ -0,0 +1,81 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/SVD>
+
+template<typename MatrixType, typename JacobiScalar>
+void jacobi(const MatrixType& m = MatrixType())
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime
+  };
+
+  typedef Matrix<JacobiScalar, 2, 1> JacobiVector;
+
+  const MatrixType a(MatrixType::Random(rows, cols));
+
+  JacobiVector v = JacobiVector::Random().normalized();
+  JacobiScalar c = v.x(), s = v.y();
+  JacobiRotation<JacobiScalar> rot(c, s);
+
+  {
+    Index p = internal::random<Index>(0, rows-1);
+    Index q;
+    do {
+      q = internal::random<Index>(0, rows-1);
+    } while (q == p);
+
+    MatrixType b = a;
+    b.applyOnTheLeft(p, q, rot);
+    VERIFY_IS_APPROX(b.row(p), c * a.row(p) + numext::conj(s) * a.row(q));
+    VERIFY_IS_APPROX(b.row(q), -s * a.row(p) + numext::conj(c) * a.row(q));
+  }
+
+  {
+    Index p = internal::random<Index>(0, cols-1);
+    Index q;
+    do {
+      q = internal::random<Index>(0, cols-1);
+    } while (q == p);
+
+    MatrixType b = a;
+    b.applyOnTheRight(p, q, rot);
+    VERIFY_IS_APPROX(b.col(p), c * a.col(p) - s * a.col(q));
+    VERIFY_IS_APPROX(b.col(q), numext::conj(s) * a.col(p) + numext::conj(c) * a.col(q));
+  }
+}
+
+void test_jacobi()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(( jacobi<Matrix3f, float>() ));
+    CALL_SUBTEST_2(( jacobi<Matrix4d, double>() ));
+    CALL_SUBTEST_3(( jacobi<Matrix4cf, float>() ));
+    CALL_SUBTEST_3(( jacobi<Matrix4cf, std::complex<float> >() ));
+
+    int r = internal::random<int>(2, internal::random<int>(1,EIGEN_TEST_MAX_SIZE)/2),
+        c = internal::random<int>(2, internal::random<int>(1,EIGEN_TEST_MAX_SIZE)/2);
+    CALL_SUBTEST_4(( jacobi<MatrixXf, float>(MatrixXf(r,c)) ));
+    CALL_SUBTEST_5(( jacobi<MatrixXcd, double>(MatrixXcd(r,c)) ));
+    CALL_SUBTEST_5(( jacobi<MatrixXcd, std::complex<double> >(MatrixXcd(r,c)) ));
+    // complex<float> is really important to test as it is the only way to cover conjugation issues in certain unaligned paths
+    CALL_SUBTEST_6(( jacobi<MatrixXcf, float>(MatrixXcf(r,c)) ));
+    CALL_SUBTEST_6(( jacobi<MatrixXcf, std::complex<float> >(MatrixXcf(r,c)) ));
+    
+    TEST_SET_BUT_UNUSED_VARIABLE(r);
+    TEST_SET_BUT_UNUSED_VARIABLE(c);
+  }
+}
diff --git a/test/jacobisvd.cpp b/test/jacobisvd.cpp
new file mode 100644
index 0000000..12c556e
--- /dev/null
+++ b/test/jacobisvd.cpp
@@ -0,0 +1,462 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// discard stack allocation as that too bypasses malloc
+#define EIGEN_STACK_ALLOCATION_LIMIT 0
+#define EIGEN_RUNTIME_NO_MALLOC
+#include "main.h"
+#include <Eigen/SVD>
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_check_full(const MatrixType& m, const JacobiSVD<MatrixType, QRPreconditioner>& svd)
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime
+  };
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, RowsAtCompileTime, RowsAtCompileTime> MatrixUType;
+  typedef Matrix<Scalar, ColsAtCompileTime, ColsAtCompileTime> MatrixVType;
+
+  MatrixType sigma = MatrixType::Zero(rows,cols);
+  sigma.diagonal() = svd.singularValues().template cast<Scalar>();
+  MatrixUType u = svd.matrixU();
+  MatrixVType v = svd.matrixV();
+
+  VERIFY_IS_APPROX(m, u * sigma * v.adjoint());
+  VERIFY_IS_UNITARY(u);
+  VERIFY_IS_UNITARY(v);
+}
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_compare_to_full(const MatrixType& m,
+                               unsigned int computationOptions,
+                               const JacobiSVD<MatrixType, QRPreconditioner>& referenceSvd)
+{
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+  Index diagSize = (std::min)(rows, cols);
+
+  JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions);
+
+  VERIFY_IS_APPROX(svd.singularValues(), referenceSvd.singularValues());
+  if(computationOptions & ComputeFullU)
+    VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU());
+  if(computationOptions & ComputeThinU)
+    VERIFY_IS_APPROX(svd.matrixU(), referenceSvd.matrixU().leftCols(diagSize));
+  if(computationOptions & ComputeFullV)
+    VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV());
+  if(computationOptions & ComputeThinV)
+    VERIFY_IS_APPROX(svd.matrixV(), referenceSvd.matrixV().leftCols(diagSize));
+}
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_solve(const MatrixType& m, unsigned int computationOptions)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime
+  };
+
+  typedef Matrix<Scalar, RowsAtCompileTime, Dynamic> RhsType;
+  typedef Matrix<Scalar, ColsAtCompileTime, Dynamic> SolutionType;
+
+  RhsType rhs = RhsType::Random(rows, internal::random<Index>(1, cols));
+  JacobiSVD<MatrixType, QRPreconditioner> svd(m, computationOptions);
+
+       if(internal::is_same<RealScalar,double>::value) svd.setThreshold(1e-8);
+  else if(internal::is_same<RealScalar,float>::value)  svd.setThreshold(1e-4);
+  
+  SolutionType x = svd.solve(rhs);
+  
+  RealScalar residual = (m*x-rhs).norm();
+  // Check that there is no significantly better solution in the neighborhood of x
+  if(!test_isMuchSmallerThan(residual,rhs.norm()))
+  {
+    // If the residual is very small, then we have an exact solution, so we are already good.
+    for(int k=0;k<x.rows();++k)
+    {
+      SolutionType y(x);
+      y.row(k).array() += 2*NumTraits<RealScalar>::epsilon();
+      RealScalar residual_y = (m*y-rhs).norm();
+      VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+      
+      y.row(k) = x.row(k).array() - 2*NumTraits<RealScalar>::epsilon();
+      residual_y = (m*y-rhs).norm();
+      VERIFY( test_isApprox(residual_y,residual) || residual < residual_y );
+    }
+  }
+  
+  // evaluate normal equation which works also for least-squares solutions
+  if(internal::is_same<RealScalar,double>::value)
+  {
+    // This test is not stable with single precision.
+    // This is probably because squaring m signicantly affects the precision.
+    VERIFY_IS_APPROX(m.adjoint()*m*x,m.adjoint()*rhs);
+  }
+  
+  // check minimal norm solutions
+  {
+    // generate a full-rank m x n problem with m<n
+    enum {
+      RankAtCompileTime2 = ColsAtCompileTime==Dynamic ? Dynamic : (ColsAtCompileTime)/2+1,
+      RowsAtCompileTime3 = ColsAtCompileTime==Dynamic ? Dynamic : ColsAtCompileTime+1
+    };
+    typedef Matrix<Scalar, RankAtCompileTime2, ColsAtCompileTime> MatrixType2;
+    typedef Matrix<Scalar, RankAtCompileTime2, 1> RhsType2;
+    typedef Matrix<Scalar, ColsAtCompileTime, RankAtCompileTime2> MatrixType2T;
+    Index rank = RankAtCompileTime2==Dynamic ? internal::random<Index>(1,cols) : Index(RankAtCompileTime2);
+    MatrixType2 m2(rank,cols);
+    int guard = 0;
+    do {
+      m2.setRandom();
+    } while(m2.jacobiSvd().setThreshold(test_precision<Scalar>()).rank()!=rank && (++guard)<10);
+    VERIFY(guard<10);
+    RhsType2 rhs2 = RhsType2::Random(rank);
+    // use QR to find a reference minimal norm solution
+    HouseholderQR<MatrixType2T> qr(m2.adjoint());
+    Matrix<Scalar,Dynamic,1> tmp = qr.matrixQR().topLeftCorner(rank,rank).template triangularView<Upper>().adjoint().solve(rhs2);
+    tmp.conservativeResize(cols);
+    tmp.tail(cols-rank).setZero();
+    SolutionType x21 = qr.householderQ() * tmp;
+    // now check with SVD
+    JacobiSVD<MatrixType2, ColPivHouseholderQRPreconditioner> svd2(m2, computationOptions);
+    SolutionType x22 = svd2.solve(rhs2);
+    VERIFY_IS_APPROX(m2*x21, rhs2);
+    VERIFY_IS_APPROX(m2*x22, rhs2);
+    VERIFY_IS_APPROX(x21, x22);
+    
+    // Now check with a rank deficient matrix
+    typedef Matrix<Scalar, RowsAtCompileTime3, ColsAtCompileTime> MatrixType3;
+    typedef Matrix<Scalar, RowsAtCompileTime3, 1> RhsType3;
+    Index rows3 = RowsAtCompileTime3==Dynamic ? internal::random<Index>(rank+1,2*cols) : Index(RowsAtCompileTime3);
+    Matrix<Scalar,RowsAtCompileTime3,Dynamic> C = Matrix<Scalar,RowsAtCompileTime3,Dynamic>::Random(rows3,rank);
+    MatrixType3 m3 = C * m2;
+    RhsType3 rhs3 = C * rhs2;
+    JacobiSVD<MatrixType3, ColPivHouseholderQRPreconditioner> svd3(m3, computationOptions);
+    SolutionType x3 = svd3.solve(rhs3);
+    if(svd3.rank()!=rank) {
+      std::cout << m3 << "\n\n";
+      std::cout << svd3.singularValues().transpose() << "\n";
+    std::cout << svd3.rank() << " == " << rank << "\n";
+    std::cout << x21.norm() << " == " << x3.norm() << "\n";
+    }
+//     VERIFY_IS_APPROX(m3*x3, rhs3);
+    VERIFY_IS_APPROX(m3*x21, rhs3);
+    VERIFY_IS_APPROX(m2*x3, rhs2);
+    
+    VERIFY_IS_APPROX(x21, x3);
+  }
+}
+
+template<typename MatrixType, int QRPreconditioner>
+void jacobisvd_test_all_computation_options(const MatrixType& m)
+{
+  if (QRPreconditioner == NoQRPreconditioner && m.rows() != m.cols())
+    return;
+  JacobiSVD<MatrixType, QRPreconditioner> fullSvd(m, ComputeFullU|ComputeFullV);
+  CALL_SUBTEST(( jacobisvd_check_full(m, fullSvd) ));
+  CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeFullV) ));
+  
+  #if defined __INTEL_COMPILER
+  // remark #111: statement is unreachable
+  #pragma warning disable 111
+  #endif
+  if(QRPreconditioner == FullPivHouseholderQRPreconditioner)
+    return;
+
+  CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU, fullSvd) ));
+  CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullV, fullSvd) ));
+  CALL_SUBTEST(( jacobisvd_compare_to_full(m, 0, fullSvd) ));
+
+  if (MatrixType::ColsAtCompileTime == Dynamic) {
+    // thin U/V are only available with dynamic number of columns
+    CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeFullU|ComputeThinV, fullSvd) ));
+    CALL_SUBTEST(( jacobisvd_compare_to_full(m,              ComputeThinV, fullSvd) ));
+    CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeFullV, fullSvd) ));
+    CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU             , fullSvd) ));
+    CALL_SUBTEST(( jacobisvd_compare_to_full(m, ComputeThinU|ComputeThinV, fullSvd) ));
+    CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeFullU | ComputeThinV) ));
+    CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeFullV) ));
+    CALL_SUBTEST(( jacobisvd_solve<MatrixType, QRPreconditioner>(m, ComputeThinU | ComputeThinV) ));
+
+    // test reconstruction
+    typedef typename MatrixType::Index Index;
+    Index diagSize = (std::min)(m.rows(), m.cols());
+    JacobiSVD<MatrixType, QRPreconditioner> svd(m, ComputeThinU | ComputeThinV);
+    VERIFY_IS_APPROX(m, svd.matrixU().leftCols(diagSize) * svd.singularValues().asDiagonal() * svd.matrixV().leftCols(diagSize).adjoint());
+  }
+}
+
+template<typename MatrixType>
+void jacobisvd(const MatrixType& a = MatrixType(), bool pickrandom = true)
+{
+  MatrixType m = a;
+  if(pickrandom)
+  {
+    typedef typename MatrixType::Scalar Scalar;
+    typedef typename MatrixType::RealScalar RealScalar;
+    typedef typename MatrixType::Index Index;
+    Index diagSize = (std::min)(a.rows(), a.cols());
+    RealScalar s = std::numeric_limits<RealScalar>::max_exponent10/4;
+    s = internal::random<RealScalar>(1,s);
+    Matrix<RealScalar,Dynamic,1> d =  Matrix<RealScalar,Dynamic,1>::Random(diagSize);
+    for(Index k=0; k<diagSize; ++k)
+      d(k) = d(k)*std::pow(RealScalar(10),internal::random<RealScalar>(-s,s));
+    m = Matrix<Scalar,Dynamic,Dynamic>::Random(a.rows(),diagSize) * d.asDiagonal() * Matrix<Scalar,Dynamic,Dynamic>::Random(diagSize,a.cols());
+    // cancel some coeffs
+    Index n  = internal::random<Index>(0,m.size()-1);
+    for(Index i=0; i<n; ++i)
+      m(internal::random<Index>(0,m.rows()-1), internal::random<Index>(0,m.cols()-1)) = Scalar(0);
+  }
+
+  CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, FullPivHouseholderQRPreconditioner>(m) ));
+  CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, ColPivHouseholderQRPreconditioner>(m) ));
+  CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, HouseholderQRPreconditioner>(m) ));
+  CALL_SUBTEST(( jacobisvd_test_all_computation_options<MatrixType, NoQRPreconditioner>(m) ));
+}
+
+template<typename MatrixType> void jacobisvd_verify_assert(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::Index Index;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime
+  };
+
+  typedef Matrix<Scalar, RowsAtCompileTime, 1> RhsType;
+
+  RhsType rhs(rows);
+
+  JacobiSVD<MatrixType> svd;
+  VERIFY_RAISES_ASSERT(svd.matrixU())
+  VERIFY_RAISES_ASSERT(svd.singularValues())
+  VERIFY_RAISES_ASSERT(svd.matrixV())
+  VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+  MatrixType a = MatrixType::Zero(rows, cols);
+  a.setZero();
+  svd.compute(a, 0);
+  VERIFY_RAISES_ASSERT(svd.matrixU())
+  VERIFY_RAISES_ASSERT(svd.matrixV())
+  svd.singularValues();
+  VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+  if (ColsAtCompileTime == Dynamic)
+  {
+    svd.compute(a, ComputeThinU);
+    svd.matrixU();
+    VERIFY_RAISES_ASSERT(svd.matrixV())
+    VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+    svd.compute(a, ComputeThinV);
+    svd.matrixV();
+    VERIFY_RAISES_ASSERT(svd.matrixU())
+    VERIFY_RAISES_ASSERT(svd.solve(rhs))
+
+    JacobiSVD<MatrixType, FullPivHouseholderQRPreconditioner> svd_fullqr;
+    VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeFullU|ComputeThinV))
+    VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeThinV))
+    VERIFY_RAISES_ASSERT(svd_fullqr.compute(a, ComputeThinU|ComputeFullV))
+  }
+  else
+  {
+    VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinU))
+    VERIFY_RAISES_ASSERT(svd.compute(a, ComputeThinV))
+  }
+}
+
+template<typename MatrixType>
+void jacobisvd_method()
+{
+  enum { Size = MatrixType::RowsAtCompileTime };
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<RealScalar, Size, 1> RealVecType;
+  MatrixType m = MatrixType::Identity();
+  VERIFY_IS_APPROX(m.jacobiSvd().singularValues(), RealVecType::Ones());
+  VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixU());
+  VERIFY_RAISES_ASSERT(m.jacobiSvd().matrixV());
+  VERIFY_IS_APPROX(m.jacobiSvd(ComputeFullU|ComputeFullV).solve(m), m);
+}
+
+// work around stupid msvc error when constructing at compile time an expression that involves
+// a division by zero, even if the numeric type has floating point
+template<typename Scalar>
+EIGEN_DONT_INLINE Scalar zero() { return Scalar(0); }
+
+// workaround aggressive optimization in ICC
+template<typename T> EIGEN_DONT_INLINE  T sub(T a, T b) { return a - b; }
+
+template<typename MatrixType>
+void jacobisvd_inf_nan()
+{
+  // all this function does is verify we don't iterate infinitely on nan/inf values
+
+  JacobiSVD<MatrixType> svd;
+  typedef typename MatrixType::Scalar Scalar;
+  Scalar some_inf = Scalar(1) / zero<Scalar>();
+  VERIFY(sub(some_inf, some_inf) != sub(some_inf, some_inf));
+  svd.compute(MatrixType::Constant(10,10,some_inf), ComputeFullU | ComputeFullV);
+
+  Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
+  VERIFY(nan != nan);
+  svd.compute(MatrixType::Constant(10,10,nan), ComputeFullU | ComputeFullV);
+
+  MatrixType m = MatrixType::Zero(10,10);
+  m(internal::random<int>(0,9), internal::random<int>(0,9)) = some_inf;
+  svd.compute(m, ComputeFullU | ComputeFullV);
+
+  m = MatrixType::Zero(10,10);
+  m(internal::random<int>(0,9), internal::random<int>(0,9)) = nan;
+  svd.compute(m, ComputeFullU | ComputeFullV);
+  
+  // regression test for bug 791
+  m.resize(3,3);
+  m << 0,    2*NumTraits<Scalar>::epsilon(),  0.5,
+       0,   -0.5,                             0,
+       nan,  0,                               0;
+  svd.compute(m, ComputeFullU | ComputeFullV);
+}
+
+// Regression test for bug 286: JacobiSVD loops indefinitely with some
+// matrices containing denormal numbers.
+void jacobisvd_bug286()
+{
+#if defined __INTEL_COMPILER
+// shut up warning #239: floating point underflow
+#pragma warning push
+#pragma warning disable 239
+#endif
+  Matrix2d M;
+  M << -7.90884e-313, -4.94e-324,
+                 0, 5.60844e-313;
+#if defined __INTEL_COMPILER
+#pragma warning pop
+#endif
+  JacobiSVD<Matrix2d> svd;
+  svd.compute(M); // just check we don't loop indefinitely
+}
+
+void jacobisvd_preallocate()
+{
+  Vector3f v(3.f, 2.f, 1.f);
+  MatrixXf m = v.asDiagonal();
+
+  internal::set_is_malloc_allowed(false);
+  VERIFY_RAISES_ASSERT(VectorXf tmp(10);)
+  JacobiSVD<MatrixXf> svd;
+  internal::set_is_malloc_allowed(true);
+  svd.compute(m);
+  VERIFY_IS_APPROX(svd.singularValues(), v);
+
+  JacobiSVD<MatrixXf> svd2(3,3);
+  internal::set_is_malloc_allowed(false);
+  svd2.compute(m);
+  internal::set_is_malloc_allowed(true);
+  VERIFY_IS_APPROX(svd2.singularValues(), v);
+  VERIFY_RAISES_ASSERT(svd2.matrixU());
+  VERIFY_RAISES_ASSERT(svd2.matrixV());
+  svd2.compute(m, ComputeFullU | ComputeFullV);
+  VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+  VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+  internal::set_is_malloc_allowed(false);
+  svd2.compute(m);
+  internal::set_is_malloc_allowed(true);
+
+  JacobiSVD<MatrixXf> svd3(3,3,ComputeFullU|ComputeFullV);
+  internal::set_is_malloc_allowed(false);
+  svd2.compute(m);
+  internal::set_is_malloc_allowed(true);
+  VERIFY_IS_APPROX(svd2.singularValues(), v);
+  VERIFY_IS_APPROX(svd2.matrixU(), Matrix3f::Identity());
+  VERIFY_IS_APPROX(svd2.matrixV(), Matrix3f::Identity());
+  internal::set_is_malloc_allowed(false);
+  svd2.compute(m, ComputeFullU|ComputeFullV);
+  internal::set_is_malloc_allowed(true);
+}
+
+void test_jacobisvd()
+{
+  CALL_SUBTEST_3(( jacobisvd_verify_assert(Matrix3f()) ));
+  CALL_SUBTEST_4(( jacobisvd_verify_assert(Matrix4d()) ));
+  CALL_SUBTEST_7(( jacobisvd_verify_assert(MatrixXf(10,12)) ));
+  CALL_SUBTEST_8(( jacobisvd_verify_assert(MatrixXcd(7,5)) ));
+
+  for(int i = 0; i < g_repeat; i++) {
+    Matrix2cd m;
+    m << 0, 1,
+         0, 1;
+    CALL_SUBTEST_1(( jacobisvd(m, false) ));
+    m << 1, 0,
+         1, 0;
+    CALL_SUBTEST_1(( jacobisvd(m, false) ));
+
+    Matrix2d n;
+    n << 0, 0,
+         0, 0;
+    CALL_SUBTEST_2(( jacobisvd(n, false) ));
+    n << 0, 0,
+         0, 1;
+    CALL_SUBTEST_2(( jacobisvd(n, false) ));
+    
+    CALL_SUBTEST_3(( jacobisvd<Matrix3f>() ));
+    CALL_SUBTEST_4(( jacobisvd<Matrix4d>() ));
+    CALL_SUBTEST_5(( jacobisvd<Matrix<float,3,5> >() ));
+    CALL_SUBTEST_6(( jacobisvd<Matrix<double,Dynamic,2> >(Matrix<double,Dynamic,2>(10,2)) ));
+
+    int r = internal::random<int>(1, 30),
+        c = internal::random<int>(1, 30);
+    
+    TEST_SET_BUT_UNUSED_VARIABLE(r)
+    TEST_SET_BUT_UNUSED_VARIABLE(c)
+    
+    CALL_SUBTEST_10(( jacobisvd<MatrixXd>(MatrixXd(r,c)) ));
+    CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(r,c)) ));
+    CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(r,c)) ));
+    (void) r;
+    (void) c;
+
+    // Test on inf/nan matrix
+    CALL_SUBTEST_7( jacobisvd_inf_nan<MatrixXf>() );
+    CALL_SUBTEST_10( jacobisvd_inf_nan<MatrixXd>() );
+  }
+
+  CALL_SUBTEST_7(( jacobisvd<MatrixXf>(MatrixXf(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/2))) ));
+  CALL_SUBTEST_8(( jacobisvd<MatrixXcd>(MatrixXcd(internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3), internal::random<int>(EIGEN_TEST_MAX_SIZE/4, EIGEN_TEST_MAX_SIZE/3))) ));
+
+  // test matrixbase method
+  CALL_SUBTEST_1(( jacobisvd_method<Matrix2cd>() ));
+  CALL_SUBTEST_3(( jacobisvd_method<Matrix3f>() ));
+
+  // Test problem size constructors
+  CALL_SUBTEST_7( JacobiSVD<MatrixXf>(10,10) );
+
+  // Check that preallocation avoids subsequent mallocs
+  CALL_SUBTEST_9( jacobisvd_preallocate() );
+
+  // Regression check for bug 286
+  CALL_SUBTEST_2( jacobisvd_bug286() );
+}
diff --git a/test/linearstructure.cpp b/test/linearstructure.cpp
new file mode 100644
index 0000000..618984d
--- /dev/null
+++ b/test/linearstructure.cpp
@@ -0,0 +1,84 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void linearStructure(const MatrixType& m)
+{
+  using std::abs;
+  /* this test covers the following files:
+     CwiseUnaryOp.h, CwiseBinaryOp.h, SelfCwiseBinaryOp.h 
+  */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  Scalar s1 = internal::random<Scalar>();
+  while (abs(s1)<1e-3) s1 = internal::random<Scalar>();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  VERIFY_IS_APPROX(-(-m1),                  m1);
+  VERIFY_IS_APPROX(m1+m1,                   2*m1);
+  VERIFY_IS_APPROX(m1+m2-m1,                m2);
+  VERIFY_IS_APPROX(-m2+m1+m2,               m1);
+  VERIFY_IS_APPROX(m1*s1,                   s1*m1);
+  VERIFY_IS_APPROX((m1+m2)*s1,              s1*m1+s1*m2);
+  VERIFY_IS_APPROX((-m1+m2)*s1,             -s1*m1+s1*m2);
+  m3 = m2; m3 += m1;
+  VERIFY_IS_APPROX(m3,                      m1+m2);
+  m3 = m2; m3 -= m1;
+  VERIFY_IS_APPROX(m3,                      m2-m1);
+  m3 = m2; m3 *= s1;
+  VERIFY_IS_APPROX(m3,                      s1*m2);
+  if(!NumTraits<Scalar>::IsInteger)
+  {
+    m3 = m2; m3 /= s1;
+    VERIFY_IS_APPROX(m3,                    m2/s1);
+  }
+
+  // again, test operator() to check const-qualification
+  VERIFY_IS_APPROX((-m1)(r,c), -(m1(r,c)));
+  VERIFY_IS_APPROX((m1-m2)(r,c), (m1(r,c))-(m2(r,c)));
+  VERIFY_IS_APPROX((m1+m2)(r,c), (m1(r,c))+(m2(r,c)));
+  VERIFY_IS_APPROX((s1*m1)(r,c), s1*(m1(r,c)));
+  VERIFY_IS_APPROX((m1*s1)(r,c), (m1(r,c))*s1);
+  if(!NumTraits<Scalar>::IsInteger)
+    VERIFY_IS_APPROX((m1/s1)(r,c), (m1(r,c))/s1);
+
+  // use .block to disable vectorization and compare to the vectorized version
+  VERIFY_IS_APPROX(m1+m1.block(0,0,rows,cols), m1+m1);
+  VERIFY_IS_APPROX(m1.cwiseProduct(m1.block(0,0,rows,cols)), m1.cwiseProduct(m1));
+  VERIFY_IS_APPROX(m1 - m1.block(0,0,rows,cols), m1 - m1);
+  VERIFY_IS_APPROX(m1.block(0,0,rows,cols) * s1, m1 * s1);
+}
+
+void test_linearstructure()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( linearStructure(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( linearStructure(Matrix2f()) );
+    CALL_SUBTEST_3( linearStructure(Vector3d()) );
+    CALL_SUBTEST_4( linearStructure(Matrix4d()) );
+    CALL_SUBTEST_5( linearStructure(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_6( linearStructure(MatrixXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_7( linearStructure(MatrixXi (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_8( linearStructure(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_9( linearStructure(ArrayXXf (internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+}
diff --git a/test/lu.cpp b/test/lu.cpp
new file mode 100644
index 0000000..3746526
--- /dev/null
+++ b/test/lu.cpp
@@ -0,0 +1,210 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+using namespace std;
+
+template<typename MatrixType> void lu_non_invertible()
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::RealScalar RealScalar;
+  /* this test covers the following files:
+     LU.h
+  */
+  Index rows, cols, cols2;
+  if(MatrixType::RowsAtCompileTime==Dynamic)
+  {
+    rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
+  }
+  else
+  {
+    rows = MatrixType::RowsAtCompileTime;
+  }
+  if(MatrixType::ColsAtCompileTime==Dynamic)
+  {
+    cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
+    cols2 = internal::random<int>(2,EIGEN_TEST_MAX_SIZE);
+  }
+  else
+  {
+    cols2 = cols = MatrixType::ColsAtCompileTime;
+  }
+
+  enum {
+    RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+    ColsAtCompileTime = MatrixType::ColsAtCompileTime
+  };
+  typedef typename internal::kernel_retval_base<FullPivLU<MatrixType> >::ReturnType KernelMatrixType;
+  typedef typename internal::image_retval_base<FullPivLU<MatrixType> >::ReturnType ImageMatrixType;
+  typedef Matrix<typename MatrixType::Scalar, ColsAtCompileTime, ColsAtCompileTime>
+          CMatrixType;
+  typedef Matrix<typename MatrixType::Scalar, RowsAtCompileTime, RowsAtCompileTime>
+          RMatrixType;
+
+  Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
+
+  // The image of the zero matrix should consist of a single (zero) column vector
+  VERIFY((MatrixType::Zero(rows,cols).fullPivLu().image(MatrixType::Zero(rows,cols)).cols() == 1));
+
+  MatrixType m1(rows, cols), m3(rows, cols2);
+  CMatrixType m2(cols, cols2);
+  createRandomPIMatrixOfRank(rank, rows, cols, m1);
+
+  FullPivLU<MatrixType> lu;
+
+  // The special value 0.01 below works well in tests. Keep in mind that we're only computing the rank
+  // of singular values are either 0 or 1.
+  // So it's not clear at all that the epsilon should play any role there.
+  lu.setThreshold(RealScalar(0.01));
+  lu.compute(m1);
+
+  MatrixType u(rows,cols);
+  u = lu.matrixLU().template triangularView<Upper>();
+  RMatrixType l = RMatrixType::Identity(rows,rows);
+  l.block(0,0,rows,(std::min)(rows,cols)).template triangularView<StrictlyLower>()
+    = lu.matrixLU().block(0,0,rows,(std::min)(rows,cols));
+
+  VERIFY_IS_APPROX(lu.permutationP() * m1 * lu.permutationQ(), l*u);
+
+  KernelMatrixType m1kernel = lu.kernel();
+  ImageMatrixType m1image = lu.image(m1);
+
+  VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
+  VERIFY(rank == lu.rank());
+  VERIFY(cols - lu.rank() == lu.dimensionOfKernel());
+  VERIFY(!lu.isInjective());
+  VERIFY(!lu.isInvertible());
+  VERIFY(!lu.isSurjective());
+  VERIFY((m1 * m1kernel).isMuchSmallerThan(m1));
+  VERIFY(m1image.fullPivLu().rank() == rank);
+  VERIFY_IS_APPROX(m1 * m1.adjoint() * m1image, m1image);
+
+  m2 = CMatrixType::Random(cols,cols2);
+  m3 = m1*m2;
+  m2 = CMatrixType::Random(cols,cols2);
+  // test that the code, which does resize(), may be applied to an xpr
+  m2.block(0,0,m2.rows(),m2.cols()) = lu.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+}
+
+template<typename MatrixType> void lu_invertible()
+{
+  /* this test covers the following files:
+     LU.h
+  */
+  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+  DenseIndex size = MatrixType::RowsAtCompileTime;
+  if( size==Dynamic)
+    size = internal::random<DenseIndex>(1,EIGEN_TEST_MAX_SIZE);
+
+  MatrixType m1(size, size), m2(size, size), m3(size, size);
+  FullPivLU<MatrixType> lu;
+  lu.setThreshold(RealScalar(0.01));
+  do {
+    m1 = MatrixType::Random(size,size);
+    lu.compute(m1);
+  } while(!lu.isInvertible());
+
+  VERIFY_IS_APPROX(m1, lu.reconstructedMatrix());
+  VERIFY(0 == lu.dimensionOfKernel());
+  VERIFY(lu.kernel().cols() == 1); // the kernel() should consist of a single (zero) column vector
+  VERIFY(size == lu.rank());
+  VERIFY(lu.isInjective());
+  VERIFY(lu.isSurjective());
+  VERIFY(lu.isInvertible());
+  VERIFY(lu.image(m1).fullPivLu().isInvertible());
+  m3 = MatrixType::Random(size,size);
+  m2 = lu.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+  VERIFY_IS_APPROX(m2, lu.inverse()*m3);
+
+  // Regression test for Bug 302
+  MatrixType m4 = MatrixType::Random(size,size);
+  VERIFY_IS_APPROX(lu.solve(m3*m4), lu.solve(m3)*m4);
+}
+
+template<typename MatrixType> void lu_partial_piv()
+{
+  /* this test covers the following files:
+     PartialPivLU.h
+  */
+  typedef typename MatrixType::Index Index;
+  Index rows = internal::random<Index>(1,4);
+  Index cols = rows;
+
+  MatrixType m1(cols, rows);
+  m1.setRandom();
+  PartialPivLU<MatrixType> plu(m1);
+
+  VERIFY_IS_APPROX(m1, plu.reconstructedMatrix());
+}
+
+template<typename MatrixType> void lu_verify_assert()
+{
+  MatrixType tmp;
+
+  FullPivLU<MatrixType> lu;
+  VERIFY_RAISES_ASSERT(lu.matrixLU())
+  VERIFY_RAISES_ASSERT(lu.permutationP())
+  VERIFY_RAISES_ASSERT(lu.permutationQ())
+  VERIFY_RAISES_ASSERT(lu.kernel())
+  VERIFY_RAISES_ASSERT(lu.image(tmp))
+  VERIFY_RAISES_ASSERT(lu.solve(tmp))
+  VERIFY_RAISES_ASSERT(lu.determinant())
+  VERIFY_RAISES_ASSERT(lu.rank())
+  VERIFY_RAISES_ASSERT(lu.dimensionOfKernel())
+  VERIFY_RAISES_ASSERT(lu.isInjective())
+  VERIFY_RAISES_ASSERT(lu.isSurjective())
+  VERIFY_RAISES_ASSERT(lu.isInvertible())
+  VERIFY_RAISES_ASSERT(lu.inverse())
+
+  PartialPivLU<MatrixType> plu;
+  VERIFY_RAISES_ASSERT(plu.matrixLU())
+  VERIFY_RAISES_ASSERT(plu.permutationP())
+  VERIFY_RAISES_ASSERT(plu.solve(tmp))
+  VERIFY_RAISES_ASSERT(plu.determinant())
+  VERIFY_RAISES_ASSERT(plu.inverse())
+}
+
+void test_lu()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( lu_non_invertible<Matrix3f>() );
+    CALL_SUBTEST_1( lu_invertible<Matrix3f>() );
+    CALL_SUBTEST_1( lu_verify_assert<Matrix3f>() );
+
+    CALL_SUBTEST_2( (lu_non_invertible<Matrix<double, 4, 6> >()) );
+    CALL_SUBTEST_2( (lu_verify_assert<Matrix<double, 4, 6> >()) );
+
+    CALL_SUBTEST_3( lu_non_invertible<MatrixXf>() );
+    CALL_SUBTEST_3( lu_invertible<MatrixXf>() );
+    CALL_SUBTEST_3( lu_verify_assert<MatrixXf>() );
+
+    CALL_SUBTEST_4( lu_non_invertible<MatrixXd>() );
+    CALL_SUBTEST_4( lu_invertible<MatrixXd>() );
+    CALL_SUBTEST_4( lu_partial_piv<MatrixXd>() );
+    CALL_SUBTEST_4( lu_verify_assert<MatrixXd>() );
+
+    CALL_SUBTEST_5( lu_non_invertible<MatrixXcf>() );
+    CALL_SUBTEST_5( lu_invertible<MatrixXcf>() );
+    CALL_SUBTEST_5( lu_verify_assert<MatrixXcf>() );
+
+    CALL_SUBTEST_6( lu_non_invertible<MatrixXcd>() );
+    CALL_SUBTEST_6( lu_invertible<MatrixXcd>() );
+    CALL_SUBTEST_6( lu_partial_piv<MatrixXcd>() );
+    CALL_SUBTEST_6( lu_verify_assert<MatrixXcd>() );
+
+    CALL_SUBTEST_7(( lu_non_invertible<Matrix<float,Dynamic,16> >() ));
+
+    // Test problem size constructors
+    CALL_SUBTEST_9( PartialPivLU<MatrixXf>(10) );
+    CALL_SUBTEST_9( FullPivLU<MatrixXf>(10, 20); );
+  }
+}
diff --git a/test/main.h b/test/main.h
new file mode 100644
index 0000000..6642048
--- /dev/null
+++ b/test/main.h
@@ -0,0 +1,552 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <cstdlib>
+#include <cerrno>
+#include <ctime>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <typeinfo>
+
+// The following includes of STL headers have to be done _before_ the
+// definition of macros min() and max().  The reason is that many STL
+// implementations will not work properly as the min and max symbols collide
+// with the STL functions std:min() and std::max().  The STL headers may check
+// for the macro definition of min/max and issue a warning or undefine the
+// macros.
+//
+// Still, Windows defines min() and max() in windef.h as part of the regular
+// Windows system interfaces and many other Windows APIs depend on these
+// macros being available.  To prevent the macro expansion of min/max and to
+// make Eigen compatible with the Windows environment all function calls of
+// std::min() and std::max() have to be written with parenthesis around the
+// function name.
+//
+// All STL headers used by Eigen should be included here.  Because main.h is
+// included before any Eigen header and because the STL headers are guarded
+// against multiple inclusions, no STL header will see our own min/max macro
+// definitions.
+#include <limits>
+#include <algorithm>
+#include <complex>
+#include <deque>
+#include <queue>
+#include <list>
+
+// To test that all calls from Eigen code to std::min() and std::max() are
+// protected by parenthesis against macro expansion, the min()/max() macros
+// are defined here and any not-parenthesized min/max call will cause a
+// compiler error.
+#define min(A,B) please_protect_your_min_with_parentheses
+#define max(A,B) please_protect_your_max_with_parentheses
+
+#define FORBIDDEN_IDENTIFIER (this_identifier_is_forbidden_to_avoid_clashes) this_identifier_is_forbidden_to_avoid_clashes
+// B0 is defined in POSIX header termios.h
+#define B0 FORBIDDEN_IDENTIFIER
+
+
+// shuts down ICC's remark #593: variable "XXX" was set but never used
+#define TEST_SET_BUT_UNUSED_VARIABLE(X) X = X + 0;
+
+// the following file is automatically generated by cmake
+#include "split_test_helper.h"
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+// On windows CE, NDEBUG is automatically defined <assert.h> if NDEBUG is not defined.
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+// bounds integer values for AltiVec
+#ifdef __ALTIVEC__
+#define EIGEN_MAKING_DOCS
+#endif
+
+#ifndef EIGEN_TEST_FUNC
+#error EIGEN_TEST_FUNC must be defined
+#endif
+
+#define DEFAULT_REPEAT 10
+
+namespace Eigen
+{
+  static std::vector<std::string> g_test_stack;
+  static int g_repeat;
+  static unsigned int g_seed;
+  static bool g_has_set_repeat, g_has_set_seed;
+}
+
+#define EI_PP_MAKE_STRING2(S) #S
+#define EI_PP_MAKE_STRING(S) EI_PP_MAKE_STRING2(S)
+
+#define EIGEN_DEFAULT_IO_FORMAT IOFormat(4, 0, "  ", "\n", "", "", "", "")
+
+#ifndef EIGEN_NO_ASSERTION_CHECKING
+
+  namespace Eigen
+  {
+    static const bool should_raise_an_assert = false;
+
+    // Used to avoid to raise two exceptions at a time in which
+    // case the exception is not properly caught.
+    // This may happen when a second exceptions is triggered in a destructor.
+    static bool no_more_assert = false;
+    static bool report_on_cerr_on_assert_failure = true;
+
+    struct eigen_assert_exception
+    {
+      eigen_assert_exception(void) {}
+      ~eigen_assert_exception() { Eigen::no_more_assert = false; }
+    };
+  }
+  // If EIGEN_DEBUG_ASSERTS is defined and if no assertion is triggered while
+  // one should have been, then the list of excecuted assertions is printed out.
+  //
+  // EIGEN_DEBUG_ASSERTS is not enabled by default as it
+  // significantly increases the compilation time
+  // and might even introduce side effects that would hide
+  // some memory errors.
+  #ifdef EIGEN_DEBUG_ASSERTS
+
+    namespace Eigen
+    {
+      namespace internal
+      {
+        static bool push_assert = false;
+      }
+      static std::vector<std::string> eigen_assert_list;
+    }
+    #define eigen_assert(a)                       \
+      if( (!(a)) && (!no_more_assert) )     \
+      { \
+        if(report_on_cerr_on_assert_failure) \
+          std::cerr <<  #a << " " __FILE__ << "(" << __LINE__ << ")\n"; \
+        Eigen::no_more_assert = true;       \
+        throw Eigen::eigen_assert_exception(); \
+      }                                     \
+      else if (Eigen::internal::push_assert)       \
+      {                                     \
+        eigen_assert_list.push_back(std::string(EI_PP_MAKE_STRING(__FILE__) " (" EI_PP_MAKE_STRING(__LINE__) ") : " #a) ); \
+      }
+
+    #define VERIFY_RAISES_ASSERT(a)                                                   \
+      {                                                                               \
+        Eigen::no_more_assert = false;                                                \
+        Eigen::eigen_assert_list.clear();                                                \
+        Eigen::internal::push_assert = true;                                                 \
+        Eigen::report_on_cerr_on_assert_failure = false;                              \
+        try {                                                                         \
+          a;                                                                          \
+          std::cerr << "One of the following asserts should have been triggered:\n";  \
+          for (uint ai=0 ; ai<eigen_assert_list.size() ; ++ai)                           \
+            std::cerr << "  " << eigen_assert_list[ai] << "\n";                          \
+          VERIFY(Eigen::should_raise_an_assert && # a);                               \
+        } catch (Eigen::eigen_assert_exception) {                                        \
+          Eigen::internal::push_assert = false; VERIFY(true);                                \
+        }                                                                             \
+        Eigen::report_on_cerr_on_assert_failure = true;                               \
+        Eigen::internal::push_assert = false;                                                \
+      }
+
+  #else // EIGEN_DEBUG_ASSERTS
+    // see bug 89. The copy_bool here is working around a bug in gcc <= 4.3
+    #define eigen_assert(a) \
+      if( (!Eigen::internal::copy_bool(a)) && (!no_more_assert) )\
+      {                                       \
+        Eigen::no_more_assert = true;         \
+        if(report_on_cerr_on_assert_failure)  \
+          eigen_plain_assert(a);              \
+        else                                  \
+          throw Eigen::eigen_assert_exception(); \
+      }
+    #define VERIFY_RAISES_ASSERT(a) {                             \
+        Eigen::no_more_assert = false;                            \
+        Eigen::report_on_cerr_on_assert_failure = false;          \
+        try {                                                     \
+          a;                                                      \
+          VERIFY(Eigen::should_raise_an_assert && # a);           \
+        }                                                         \
+        catch (Eigen::eigen_assert_exception&) { VERIFY(true); }     \
+        Eigen::report_on_cerr_on_assert_failure = true;           \
+      }
+
+  #endif // EIGEN_DEBUG_ASSERTS
+
+  #define EIGEN_USE_CUSTOM_ASSERT
+
+#else // EIGEN_NO_ASSERTION_CHECKING
+
+  #define VERIFY_RAISES_ASSERT(a) {}
+
+#endif // EIGEN_NO_ASSERTION_CHECKING
+
+
+#define EIGEN_INTERNAL_DEBUGGING
+#include <Eigen/QR> // required for createRandomPIMatrixOfRank
+
+inline void verify_impl(bool condition, const char *testname, const char *file, int line, const char *condition_as_string)
+{
+  if (!condition)
+  {
+    std::cerr << "Test " << testname << " failed in " << file << " (" << line << ")"
+      << std::endl << "    " << condition_as_string << std::endl;
+    std::cerr << "Stack:\n";
+    const int test_stack_size = static_cast<int>(Eigen::g_test_stack.size());
+    for(int i=test_stack_size-1; i>=0; --i)
+      std::cerr << "  - " << Eigen::g_test_stack[i] << "\n";
+    std::cerr << "\n";
+    abort();
+  }
+}
+
+#define VERIFY(a) ::verify_impl(a, g_test_stack.back().c_str(), __FILE__, __LINE__, EI_PP_MAKE_STRING(a))
+
+#define VERIFY_IS_EQUAL(a, b) VERIFY(test_is_equal(a, b))
+#define VERIFY_IS_APPROX(a, b) VERIFY(test_isApprox(a, b))
+#define VERIFY_IS_NOT_APPROX(a, b) VERIFY(!test_isApprox(a, b))
+#define VERIFY_IS_MUCH_SMALLER_THAN(a, b) VERIFY(test_isMuchSmallerThan(a, b))
+#define VERIFY_IS_NOT_MUCH_SMALLER_THAN(a, b) VERIFY(!test_isMuchSmallerThan(a, b))
+#define VERIFY_IS_APPROX_OR_LESS_THAN(a, b) VERIFY(test_isApproxOrLessThan(a, b))
+#define VERIFY_IS_NOT_APPROX_OR_LESS_THAN(a, b) VERIFY(!test_isApproxOrLessThan(a, b))
+
+#define VERIFY_IS_UNITARY(a) VERIFY(test_isUnitary(a))
+
+#define CALL_SUBTEST(FUNC) do { \
+    g_test_stack.push_back(EI_PP_MAKE_STRING(FUNC)); \
+    FUNC; \
+    g_test_stack.pop_back(); \
+  } while (0)
+
+
+namespace Eigen {
+
+template<typename T> inline typename NumTraits<T>::Real test_precision() { return NumTraits<T>::dummy_precision(); }
+template<> inline float test_precision<float>() { return 1e-3f; }
+template<> inline double test_precision<double>() { return 1e-6; }
+template<> inline float test_precision<std::complex<float> >() { return test_precision<float>(); }
+template<> inline double test_precision<std::complex<double> >() { return test_precision<double>(); }
+template<> inline long double test_precision<long double>() { return 1e-6; }
+
+inline bool test_isApprox(const int& a, const int& b)
+{ return internal::isApprox(a, b, test_precision<int>()); }
+inline bool test_isMuchSmallerThan(const int& a, const int& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<int>()); }
+inline bool test_isApproxOrLessThan(const int& a, const int& b)
+{ return internal::isApproxOrLessThan(a, b, test_precision<int>()); }
+
+inline bool test_isApprox(const float& a, const float& b)
+{ return internal::isApprox(a, b, test_precision<float>()); }
+inline bool test_isMuchSmallerThan(const float& a, const float& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<float>()); }
+inline bool test_isApproxOrLessThan(const float& a, const float& b)
+{ return internal::isApproxOrLessThan(a, b, test_precision<float>()); }
+inline bool test_isApprox(const double& a, const double& b)
+{ return internal::isApprox(a, b, test_precision<double>()); }
+
+inline bool test_isMuchSmallerThan(const double& a, const double& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<double>()); }
+inline bool test_isApproxOrLessThan(const double& a, const double& b)
+{ return internal::isApproxOrLessThan(a, b, test_precision<double>()); }
+
+inline bool test_isApprox(const std::complex<float>& a, const std::complex<float>& b)
+{ return internal::isApprox(a, b, test_precision<std::complex<float> >()); }
+inline bool test_isMuchSmallerThan(const std::complex<float>& a, const std::complex<float>& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<float> >()); }
+
+inline bool test_isApprox(const std::complex<double>& a, const std::complex<double>& b)
+{ return internal::isApprox(a, b, test_precision<std::complex<double> >()); }
+inline bool test_isMuchSmallerThan(const std::complex<double>& a, const std::complex<double>& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<std::complex<double> >()); }
+
+inline bool test_isApprox(const long double& a, const long double& b)
+{
+    bool ret = internal::isApprox(a, b, test_precision<long double>());
+    if (!ret) std::cerr
+        << std::endl << "    actual   = " << a
+        << std::endl << "    expected = " << b << std::endl << std::endl;
+    return ret;
+}
+
+inline bool test_isMuchSmallerThan(const long double& a, const long double& b)
+{ return internal::isMuchSmallerThan(a, b, test_precision<long double>()); }
+inline bool test_isApproxOrLessThan(const long double& a, const long double& b)
+{ return internal::isApproxOrLessThan(a, b, test_precision<long double>()); }
+
+template<typename Type1, typename Type2>
+inline bool test_isApprox(const Type1& a, const Type2& b)
+{
+  return a.isApprox(b, test_precision<typename Type1::Scalar>());
+}
+
+// The idea behind this function is to compare the two scalars a and b where
+// the scalar ref is a hint about the expected order of magnitude of a and b.
+// WARNING: the scalar a and b must be positive
+// Therefore, if for some reason a and b are very small compared to ref,
+// we won't issue a false negative.
+// This test could be: abs(a-b) <= eps * ref
+// However, it seems that simply comparing a+ref and b+ref is more sensitive to true error.
+template<typename Scalar,typename ScalarRef>
+inline bool test_isApproxWithRef(const Scalar& a, const Scalar& b, const ScalarRef& ref)
+{
+  return test_isApprox(a+ref, b+ref);
+}
+
+template<typename Derived1, typename Derived2>
+inline bool test_isMuchSmallerThan(const MatrixBase<Derived1>& m1,
+                                   const MatrixBase<Derived2>& m2)
+{
+  return m1.isMuchSmallerThan(m2, test_precision<typename internal::traits<Derived1>::Scalar>());
+}
+
+template<typename Derived>
+inline bool test_isMuchSmallerThan(const MatrixBase<Derived>& m,
+                                   const typename NumTraits<typename internal::traits<Derived>::Scalar>::Real& s)
+{
+  return m.isMuchSmallerThan(s, test_precision<typename internal::traits<Derived>::Scalar>());
+}
+
+template<typename Derived>
+inline bool test_isUnitary(const MatrixBase<Derived>& m)
+{
+  return m.isUnitary(test_precision<typename internal::traits<Derived>::Scalar>());
+}
+
+// Forward declaration to avoid ICC warning
+template<typename T, typename U>
+bool test_is_equal(const T& actual, const U& expected);
+
+template<typename T, typename U>
+bool test_is_equal(const T& actual, const U& expected)
+{
+    if (actual==expected)
+        return true;
+    // false:
+    std::cerr
+        << std::endl << "    actual   = " << actual
+        << std::endl << "    expected = " << expected << std::endl << std::endl;
+    return false;
+}
+
+/** 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.
+  * This is very useful to test rank-revealing algorithms.
+  */
+// Forward declaration to avoid ICC warning
+template<typename MatrixType>
+void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m);
+template<typename MatrixType>
+void createRandomPIMatrixOfRank(typename MatrixType::Index desired_rank, typename MatrixType::Index rows, typename MatrixType::Index cols, MatrixType& m)
+{
+  typedef typename internal::traits<MatrixType>::Index Index;
+  typedef typename internal::traits<MatrixType>::Scalar Scalar;
+  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
+
+  typedef Matrix<Scalar, Dynamic, 1> VectorType;
+  typedef Matrix<Scalar, Rows, Rows> MatrixAType;
+  typedef Matrix<Scalar, Cols, Cols> MatrixBType;
+
+  if(desired_rank == 0)
+  {
+    m.setZero(rows,cols);
+    return;
+  }
+
+  if(desired_rank == 1)
+  {
+    // here we normalize the vectors to get a partial isometry
+    m = VectorType::Random(rows).normalized() * VectorType::Random(cols).normalized().transpose();
+    return;
+  }
+
+  MatrixAType a = MatrixAType::Random(rows,rows);
+  MatrixType d = MatrixType::Identity(rows,cols);
+  MatrixBType  b = MatrixBType::Random(cols,cols);
+
+  // set the diagonal such that only desired_rank non-zero entries reamain
+  const Index diag_size = (std::min)(d.rows(),d.cols());
+  if(diag_size != desired_rank)
+    d.diagonal().segment(desired_rank, diag_size-desired_rank) = VectorType::Zero(diag_size-desired_rank);
+
+  HouseholderQR<MatrixAType> qra(a);
+  HouseholderQR<MatrixBType> qrb(b);
+  m = qra.householderQ() * d * qrb.householderQ();
+}
+
+// Forward declaration to avoid ICC warning
+template<typename PermutationVectorType>
+void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size);
+template<typename PermutationVectorType>
+void randomPermutationVector(PermutationVectorType& v, typename PermutationVectorType::Index size)
+{
+  typedef typename PermutationVectorType::Index Index;
+  typedef typename PermutationVectorType::Scalar Scalar;
+  v.resize(size);
+  for(Index i = 0; i < size; ++i) v(i) = Scalar(i);
+  if(size == 1) return;
+  for(Index n = 0; n < 3 * size; ++n)
+  {
+    Index i = internal::random<Index>(0, size-1);
+    Index j;
+    do j = internal::random<Index>(0, size-1); while(j==i);
+    std::swap(v(i), v(j));
+  }
+}
+
+template<typename T> bool isNotNaN(const T& x)
+{
+  return x==x;
+}
+
+template<typename T> bool isNaN(const T& x)
+{
+  return x!=x;
+}
+
+template<typename T> bool isInf(const T& x)
+{
+  return x > NumTraits<T>::highest();
+}
+
+template<typename T> bool isMinusInf(const T& x)
+{
+  return x < NumTraits<T>::lowest();
+}
+
+} // end namespace Eigen
+
+template<typename T> struct GetDifferentType;
+
+template<> struct GetDifferentType<float> { typedef double type; };
+template<> struct GetDifferentType<double> { typedef float type; };
+template<typename T> struct GetDifferentType<std::complex<T> >
+{ typedef std::complex<typename GetDifferentType<T>::type> type; };
+
+// Forward declaration to avoid ICC warning
+template<typename T> std::string type_name();
+template<typename T> std::string type_name()              { return "other"; }
+template<> std::string type_name<float>()                 { return "float"; }
+template<> std::string type_name<double>()                { return "double"; }
+template<> std::string type_name<int>()                   { return "int"; }
+template<> std::string type_name<std::complex<float> >()  { return "complex<float>"; }
+template<> std::string type_name<std::complex<double> >() { return "complex<double>"; }
+template<> std::string type_name<std::complex<int> >()    { return "complex<int>"; }
+
+// forward declaration of the main test function
+void EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
+
+using namespace Eigen;
+
+inline void set_repeat_from_string(const char *str)
+{
+  errno = 0;
+  g_repeat = int(strtoul(str, 0, 10));
+  if(errno || g_repeat <= 0)
+  {
+    std::cout << "Invalid repeat value " << str << std::endl;
+    exit(EXIT_FAILURE);
+  }
+  g_has_set_repeat = true;
+}
+
+inline void set_seed_from_string(const char *str)
+{
+  errno = 0;
+  g_seed = int(strtoul(str, 0, 10));
+  if(errno || g_seed == 0)
+  {
+    std::cout << "Invalid seed value " << str << std::endl;
+    exit(EXIT_FAILURE);
+  }
+  g_has_set_seed = true;
+}
+
+int main(int argc, char *argv[])
+{
+    g_has_set_repeat = false;
+    g_has_set_seed = false;
+    bool need_help = false;
+
+    for(int i = 1; i < argc; i++)
+    {
+      if(argv[i][0] == 'r')
+      {
+        if(g_has_set_repeat)
+        {
+          std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
+          return 1;
+        }
+        set_repeat_from_string(argv[i]+1);
+      }
+      else if(argv[i][0] == 's')
+      {
+        if(g_has_set_seed)
+        {
+          std::cout << "Argument " << argv[i] << " conflicting with a former argument" << std::endl;
+          return 1;
+        }
+         set_seed_from_string(argv[i]+1);
+      }
+      else
+      {
+        need_help = true;
+      }
+    }
+
+    if(need_help)
+    {
+      std::cout << "This test application takes the following optional arguments:" << std::endl;
+      std::cout << "  rN     Repeat each test N times (default: " << DEFAULT_REPEAT << ")" << std::endl;
+      std::cout << "  sN     Use N as seed for random numbers (default: based on current time)" << std::endl;
+      std::cout << std::endl;
+      std::cout << "If defined, the environment variables EIGEN_REPEAT and EIGEN_SEED" << std::endl;
+      std::cout << "will be used as default values for these parameters." << std::endl;
+      return 1;
+    }
+
+    char *env_EIGEN_REPEAT = getenv("EIGEN_REPEAT");
+    if(!g_has_set_repeat && env_EIGEN_REPEAT)
+      set_repeat_from_string(env_EIGEN_REPEAT);
+    char *env_EIGEN_SEED = getenv("EIGEN_SEED");
+    if(!g_has_set_seed && env_EIGEN_SEED)
+      set_seed_from_string(env_EIGEN_SEED);
+
+    if(!g_has_set_seed) g_seed = (unsigned int) time(NULL);
+    if(!g_has_set_repeat) g_repeat = DEFAULT_REPEAT;
+
+    std::cout << "Initializing random number generator with seed " << g_seed << std::endl;
+    std::stringstream ss;
+    ss << "Seed: " << g_seed;
+    g_test_stack.push_back(ss.str());
+    srand(g_seed);
+    std::cout << "Repeating each test " << g_repeat << " times" << std::endl;
+
+    Eigen::g_test_stack.push_back(std::string(EI_PP_MAKE_STRING(EIGEN_TEST_FUNC)));
+
+    EIGEN_CAT(test_,EIGEN_TEST_FUNC)();
+    return 0;
+}
+
+// These warning are disabled here such that they are still ON when parsing Eigen's header files.
+#if defined __INTEL_COMPILER
+  // remark #383: value copied to temporary, reference to temporary used
+  //  -> this warning is raised even for legal usage as: g_test_stack.push_back("foo"); where g_test_stack is a std::vector<std::string>
+  // remark #1418: external function definition with no prior declaration
+  //  -> this warning is raised for all our test functions. Declaring them static would fix the issue.
+  // warning #279: controlling expression is constant
+  // remark #1572: floating-point equality and inequality comparisons are unreliable
+  #pragma warning disable 279 383 1418 1572
+#endif
diff --git a/test/mapped_matrix.cpp b/test/mapped_matrix.cpp
new file mode 100644
index 0000000..58904fa
--- /dev/null
+++ b/test/mapped_matrix.cpp
@@ -0,0 +1,165 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_NO_STATIC_ASSERT
+#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
+#endif
+
+#include "main.h"
+
+template<typename VectorType> void map_class_vector(const VectorType& m)
+{
+  typedef typename VectorType::Index Index;
+  typedef typename VectorType::Scalar Scalar;
+
+  Index size = m.size();
+
+  // test Map.h
+  Scalar* array1 = internal::aligned_new<Scalar>(size);
+  Scalar* array2 = internal::aligned_new<Scalar>(size);
+  Scalar* array3 = new Scalar[size+1];
+  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
+
+  Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
+  Map<VectorType, Aligned>(array2, size) = Map<VectorType,Aligned>(array1, size);
+  Map<VectorType>(array3unaligned, size) = Map<VectorType>(array1, size);
+  VectorType ma1 = Map<VectorType, Aligned>(array1, size);
+  VectorType ma2 = Map<VectorType, Aligned>(array2, size);
+  VectorType ma3 = Map<VectorType>(array3unaligned, size);
+  VERIFY_IS_EQUAL(ma1, ma2);
+  VERIFY_IS_EQUAL(ma1, ma3);
+  #ifdef EIGEN_VECTORIZE
+  if(internal::packet_traits<Scalar>::Vectorizable)
+    VERIFY_RAISES_ASSERT((Map<VectorType,Aligned>(array3unaligned, size)))
+  #endif
+
+  internal::aligned_delete(array1, size);
+  internal::aligned_delete(array2, size);
+  delete[] array3;
+}
+
+template<typename MatrixType> void map_class_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows(), cols = m.cols(), size = rows*cols;
+
+  // test Map.h
+  Scalar* array1 = internal::aligned_new<Scalar>(size);
+  for(int i = 0; i < size; i++) array1[i] = Scalar(1);
+  Scalar* array2 = internal::aligned_new<Scalar>(size);
+  for(int i = 0; i < size; i++) array2[i] = Scalar(1);
+  Scalar* array3 = new Scalar[size+1];
+  for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
+  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
+  Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
+  Map<MatrixType>(array2, rows, cols) = Map<MatrixType>(array1, rows, cols);
+  Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
+  MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
+  MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
+  VERIFY_IS_EQUAL(ma1, ma2);
+  MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
+  VERIFY_IS_EQUAL(ma1, ma3);
+
+  internal::aligned_delete(array1, size);
+  internal::aligned_delete(array2, size);
+  delete[] array3;
+}
+
+template<typename VectorType> void map_static_methods(const VectorType& m)
+{
+  typedef typename VectorType::Index Index;
+  typedef typename VectorType::Scalar Scalar;
+
+  Index size = m.size();
+
+  // test Map.h
+  Scalar* array1 = internal::aligned_new<Scalar>(size);
+  Scalar* array2 = internal::aligned_new<Scalar>(size);
+  Scalar* array3 = new Scalar[size+1];
+  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
+
+  VectorType::MapAligned(array1, size) = VectorType::Random(size);
+  VectorType::Map(array2, size) = VectorType::Map(array1, size);
+  VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
+  VectorType ma1 = VectorType::Map(array1, size);
+  VectorType ma2 = VectorType::MapAligned(array2, size);
+  VectorType ma3 = VectorType::Map(array3unaligned, size);
+  VERIFY_IS_EQUAL(ma1, ma2);
+  VERIFY_IS_EQUAL(ma1, ma3);
+
+  internal::aligned_delete(array1, size);
+  internal::aligned_delete(array2, size);
+  delete[] array3;
+}
+
+template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
+{
+  // there's a lot that we can't test here while still having this test compile!
+  // the only possible approach would be to run a script trying to compile stuff and checking that it fails.
+  // CMake can help with that.
+
+  // verify that map-to-const don't have LvalueBit
+  typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
+  VERIFY( !(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit) );
+  VERIFY( !(internal::traits<Map<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+  VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
+  VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+}
+
+template<typename Scalar>
+void map_not_aligned_on_scalar()
+{
+  typedef Matrix<Scalar,Dynamic,Dynamic> MatrixType;
+  typedef typename MatrixType::Index Index;
+  Index size = 11;
+  Scalar* array1 = internal::aligned_new<Scalar>((size+1)*(size+1)+1);
+  Scalar* array2 = reinterpret_cast<Scalar*>(sizeof(Scalar)/2+std::size_t(array1));
+  Map<MatrixType,0,OuterStride<> > map2(array2, size, size, OuterStride<>(size+1));
+  MatrixType m2 = MatrixType::Random(size,size);
+  map2 = m2;
+  VERIFY_IS_EQUAL(m2, map2);
+  
+  typedef Matrix<Scalar,Dynamic,1> VectorType;
+  Map<VectorType> map3(array2, size);
+  MatrixType v3 = VectorType::Random(size);
+  map3 = v3;
+  VERIFY_IS_EQUAL(v3, map3);
+  
+  internal::aligned_delete(array1, (size+1)*(size+1)+1);
+}
+
+void test_mapped_matrix()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( check_const_correctness(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_vector(Vector4d()) );
+    CALL_SUBTEST_2( check_const_correctness(Matrix4d()) );
+    CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
+    CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
+    CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );
+    CALL_SUBTEST_5( check_const_correctness(VectorXi(12)) );
+
+    CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
+    CALL_SUBTEST_11( map_class_matrix(Matrix<float,3,5>()) );
+    CALL_SUBTEST_4( map_class_matrix(MatrixXcf(internal::random<int>(1,10),internal::random<int>(1,10))) );
+    CALL_SUBTEST_5( map_class_matrix(MatrixXi(internal::random<int>(1,10),internal::random<int>(1,10))) );
+
+    CALL_SUBTEST_6( map_static_methods(Matrix<double, 1, 1>()) );
+    CALL_SUBTEST_7( map_static_methods(Vector3f()) );
+    CALL_SUBTEST_8( map_static_methods(RowVector3d()) );
+    CALL_SUBTEST_9( map_static_methods(VectorXcd(8)) );
+    CALL_SUBTEST_10( map_static_methods(VectorXf(12)) );
+    
+    CALL_SUBTEST_11( map_not_aligned_on_scalar<double>() );
+  }
+}
diff --git a/test/mapstaticmethods.cpp b/test/mapstaticmethods.cpp
new file mode 100644
index 0000000..5b512bd
--- /dev/null
+++ b/test/mapstaticmethods.cpp
@@ -0,0 +1,173 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+float *ptr;
+const float *const_ptr;
+
+template<typename PlainObjectType,
+         bool IsDynamicSize = PlainObjectType::SizeAtCompileTime == Dynamic,
+         bool IsVector = PlainObjectType::IsVectorAtCompileTime
+>
+struct mapstaticmethods_impl {};
+
+template<typename PlainObjectType, bool IsVector>
+struct mapstaticmethods_impl<PlainObjectType, false, IsVector>
+{
+  static void run(const PlainObjectType& m)
+  {
+    mapstaticmethods_impl<PlainObjectType, true, IsVector>::run(m);
+
+    int i = internal::random<int>(2,5), j = internal::random<int>(2,5);
+
+    PlainObjectType::Map(ptr).setZero();
+    PlainObjectType::MapAligned(ptr).setZero();
+    PlainObjectType::Map(const_ptr).sum();
+    PlainObjectType::MapAligned(const_ptr).sum();
+
+    PlainObjectType::Map(ptr, InnerStride<>(i)).setZero();
+    PlainObjectType::MapAligned(ptr, InnerStride<>(i)).setZero();
+    PlainObjectType::Map(const_ptr, InnerStride<>(i)).sum();
+    PlainObjectType::MapAligned(const_ptr, InnerStride<>(i)).sum();
+
+    PlainObjectType::Map(ptr, InnerStride<2>()).setZero();
+    PlainObjectType::MapAligned(ptr, InnerStride<3>()).setZero();
+    PlainObjectType::Map(const_ptr, InnerStride<4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, InnerStride<5>()).sum();
+
+    PlainObjectType::Map(ptr, OuterStride<>(i)).setZero();
+    PlainObjectType::MapAligned(ptr, OuterStride<>(i)).setZero();
+    PlainObjectType::Map(const_ptr, OuterStride<>(i)).sum();
+    PlainObjectType::MapAligned(const_ptr, OuterStride<>(i)).sum();
+
+    PlainObjectType::Map(ptr, OuterStride<2>()).setZero();
+    PlainObjectType::MapAligned(ptr, OuterStride<3>()).setZero();
+    PlainObjectType::Map(const_ptr, OuterStride<4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, OuterStride<5>()).sum();
+
+    PlainObjectType::Map(ptr, Stride<Dynamic, Dynamic>(i,j)).setZero();
+    PlainObjectType::MapAligned(ptr, Stride<2,Dynamic>(2,i)).setZero();
+    PlainObjectType::Map(const_ptr, Stride<Dynamic,3>(i,3)).sum();
+    PlainObjectType::MapAligned(const_ptr, Stride<Dynamic, Dynamic>(i,j)).sum();
+
+    PlainObjectType::Map(ptr, Stride<2,3>()).setZero();
+    PlainObjectType::MapAligned(ptr, Stride<3,4>()).setZero();
+    PlainObjectType::Map(const_ptr, Stride<2,4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, Stride<5,3>()).sum();
+  }
+};
+
+template<typename PlainObjectType>
+struct mapstaticmethods_impl<PlainObjectType, true, false>
+{
+  static void run(const PlainObjectType& m)
+  {
+    int rows = m.rows(), cols = m.cols();
+
+    int i = internal::random<int>(2,5), j = internal::random<int>(2,5);
+
+    PlainObjectType::Map(ptr, rows, cols).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, InnerStride<>(i)).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, InnerStride<>(i)).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, InnerStride<>(i)).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, InnerStride<>(i)).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, InnerStride<2>()).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, InnerStride<3>()).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, InnerStride<4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, InnerStride<5>()).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, OuterStride<>(i)).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, OuterStride<>(i)).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, OuterStride<>(i)).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, OuterStride<>(i)).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, OuterStride<2>()).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, OuterStride<3>()).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, OuterStride<4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, OuterStride<5>()).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, Stride<Dynamic, Dynamic>(i,j)).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, Stride<2,Dynamic>(2,i)).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, Stride<Dynamic,3>(i,3)).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, Stride<Dynamic, Dynamic>(i,j)).sum();
+
+    PlainObjectType::Map(ptr, rows, cols, Stride<2,3>()).setZero();
+    PlainObjectType::MapAligned(ptr, rows, cols, Stride<3,4>()).setZero();
+    PlainObjectType::Map(const_ptr, rows, cols, Stride<2,4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, rows, cols, Stride<5,3>()).sum();
+  }
+};
+
+template<typename PlainObjectType>
+struct mapstaticmethods_impl<PlainObjectType, true, true>
+{
+  static void run(const PlainObjectType& v)
+  {
+    int size = v.size();
+
+    int i = internal::random<int>(2,5);
+
+    PlainObjectType::Map(ptr, size).setZero();
+    PlainObjectType::MapAligned(ptr, size).setZero();
+    PlainObjectType::Map(const_ptr, size).sum();
+    PlainObjectType::MapAligned(const_ptr, size).sum();
+
+    PlainObjectType::Map(ptr, size, InnerStride<>(i)).setZero();
+    PlainObjectType::MapAligned(ptr, size, InnerStride<>(i)).setZero();
+    PlainObjectType::Map(const_ptr, size, InnerStride<>(i)).sum();
+    PlainObjectType::MapAligned(const_ptr, size, InnerStride<>(i)).sum();
+
+    PlainObjectType::Map(ptr, size, InnerStride<2>()).setZero();
+    PlainObjectType::MapAligned(ptr, size, InnerStride<3>()).setZero();
+    PlainObjectType::Map(const_ptr, size, InnerStride<4>()).sum();
+    PlainObjectType::MapAligned(const_ptr, size, InnerStride<5>()).sum();
+  }
+};
+
+template<typename PlainObjectType>
+void mapstaticmethods(const PlainObjectType& m)
+{
+  mapstaticmethods_impl<PlainObjectType>::run(m);
+  VERIFY(true); // just to avoid 'unused function' warning
+}
+
+void test_mapstaticmethods()
+{
+  ptr = internal::aligned_new<float>(1000);
+  for(int i = 0; i < 1000; i++) ptr[i] = float(i);
+
+  const_ptr = ptr;
+
+  CALL_SUBTEST_1(( mapstaticmethods(Matrix<float, 1, 1>()) ));
+  CALL_SUBTEST_1(( mapstaticmethods(Vector2f()) ));
+  CALL_SUBTEST_2(( mapstaticmethods(Vector3f()) ));
+  CALL_SUBTEST_2(( mapstaticmethods(Matrix2f()) ));
+  CALL_SUBTEST_3(( mapstaticmethods(Matrix4f()) ));
+  CALL_SUBTEST_3(( mapstaticmethods(Array4f()) ));
+  CALL_SUBTEST_4(( mapstaticmethods(Array3f()) ));
+  CALL_SUBTEST_4(( mapstaticmethods(Array33f()) ));
+  CALL_SUBTEST_5(( mapstaticmethods(Array44f()) ));
+  CALL_SUBTEST_5(( mapstaticmethods(VectorXf(1)) ));
+  CALL_SUBTEST_5(( mapstaticmethods(VectorXf(8)) ));
+  CALL_SUBTEST_6(( mapstaticmethods(MatrixXf(1,1)) ));
+  CALL_SUBTEST_6(( mapstaticmethods(MatrixXf(5,7)) ));
+  CALL_SUBTEST_7(( mapstaticmethods(ArrayXf(1)) ));
+  CALL_SUBTEST_7(( mapstaticmethods(ArrayXf(5)) ));
+  CALL_SUBTEST_8(( mapstaticmethods(ArrayXXf(1,1)) ));
+  CALL_SUBTEST_8(( mapstaticmethods(ArrayXXf(8,6)) ));
+
+  internal::aligned_delete(ptr, 1000);
+}
+
diff --git a/test/mapstride.cpp b/test/mapstride.cpp
new file mode 100644
index 0000000..b1dc9de
--- /dev/null
+++ b/test/mapstride.cpp
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<int Alignment,typename VectorType> void map_class_vector(const VectorType& m)
+{
+  typedef typename VectorType::Index Index;
+  typedef typename VectorType::Scalar Scalar;
+
+  Index size = m.size();
+
+  VectorType v = VectorType::Random(size);
+
+  Index arraysize = 3*size;
+  
+  Scalar* a_array = internal::aligned_new<Scalar>(arraysize+1);
+  Scalar* array = a_array;
+  if(Alignment!=Aligned)
+    array = (Scalar*)(ptrdiff_t(a_array) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+
+  {
+    Map<VectorType, Alignment, InnerStride<3> > map(array, size);
+    map = v;
+    for(int i = 0; i < size; ++i)
+    {
+      VERIFY(array[3*i] == v[i]);
+      VERIFY(map[i] == v[i]);
+    }
+  }
+
+  {
+    Map<VectorType, Unaligned, InnerStride<Dynamic> > map(array, size, InnerStride<Dynamic>(2));
+    map = v;
+    for(int i = 0; i < size; ++i)
+    {
+      VERIFY(array[2*i] == v[i]);
+      VERIFY(map[i] == v[i]);
+    }
+  }
+
+  internal::aligned_delete(a_array, arraysize+1);
+}
+
+template<int Alignment,typename MatrixType> void map_class_matrix(const MatrixType& _m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = _m.rows(), cols = _m.cols();
+
+  MatrixType m = MatrixType::Random(rows,cols);
+
+  Index arraysize = 2*(rows+4)*(cols+4);
+
+  Scalar* a_array = internal::aligned_new<Scalar>(arraysize+1);
+  Scalar* array = a_array;
+  if(Alignment!=Aligned)
+    array = (Scalar*)(ptrdiff_t(a_array) + (internal::packet_traits<Scalar>::AlignedOnScalar?sizeof(Scalar):sizeof(typename NumTraits<Scalar>::Real)));
+
+  // test no inner stride and some dynamic outer stride
+  {
+    Map<MatrixType, Alignment, OuterStride<Dynamic> > map(array, rows, cols, OuterStride<Dynamic>(m.innerSize()+1));
+    map = m;
+    VERIFY(map.outerStride() == map.innerSize()+1);
+    for(int i = 0; i < m.outerSize(); ++i)
+      for(int j = 0; j < m.innerSize(); ++j)
+      {
+        VERIFY(array[map.outerStride()*i+j] == m.coeffByOuterInner(i,j));
+        VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
+      }
+  }
+
+  // test no inner stride and an outer stride of +4. This is quite important as for fixed-size matrices,
+  // this allows to hit the special case where it's vectorizable.
+  {
+    enum {
+      InnerSize = MatrixType::InnerSizeAtCompileTime,
+      OuterStrideAtCompileTime = InnerSize==Dynamic ? Dynamic : InnerSize+4
+    };
+    Map<MatrixType, Alignment, OuterStride<OuterStrideAtCompileTime> >
+      map(array, rows, cols, OuterStride<OuterStrideAtCompileTime>(m.innerSize()+4));
+    map = m;
+    VERIFY(map.outerStride() == map.innerSize()+4);
+    for(int i = 0; i < m.outerSize(); ++i)
+      for(int j = 0; j < m.innerSize(); ++j)
+      {
+        VERIFY(array[map.outerStride()*i+j] == m.coeffByOuterInner(i,j));
+        VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
+      }
+  }
+
+  // test both inner stride and outer stride
+  {
+    Map<MatrixType, Alignment, Stride<Dynamic,Dynamic> > map(array, rows, cols, Stride<Dynamic,Dynamic>(2*m.innerSize()+1, 2));
+    map = m;
+    VERIFY(map.outerStride() == 2*map.innerSize()+1);
+    VERIFY(map.innerStride() == 2);
+    for(int i = 0; i < m.outerSize(); ++i)
+      for(int j = 0; j < m.innerSize(); ++j)
+      {
+        VERIFY(array[map.outerStride()*i+map.innerStride()*j] == m.coeffByOuterInner(i,j));
+        VERIFY(map.coeffByOuterInner(i,j) == m.coeffByOuterInner(i,j));
+      }
+  }
+
+  internal::aligned_delete(a_array, arraysize+1);
+}
+
+void test_mapstride()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    int maxn = 30;
+    CALL_SUBTEST_1( map_class_vector<Aligned>(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( map_class_vector<Unaligned>(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_vector<Aligned>(Vector4d()) );
+    CALL_SUBTEST_2( map_class_vector<Unaligned>(Vector4d()) );
+    CALL_SUBTEST_3( map_class_vector<Aligned>(RowVector4f()) );
+    CALL_SUBTEST_3( map_class_vector<Unaligned>(RowVector4f()) );
+    CALL_SUBTEST_4( map_class_vector<Aligned>(VectorXcf(internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_4( map_class_vector<Unaligned>(VectorXcf(internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_5( map_class_vector<Aligned>(VectorXi(internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_5( map_class_vector<Unaligned>(VectorXi(internal::random<int>(1,maxn))) );
+
+    CALL_SUBTEST_1( map_class_matrix<Aligned>(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( map_class_matrix<Unaligned>(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( map_class_matrix<Aligned>(Matrix4d()) );
+    CALL_SUBTEST_2( map_class_matrix<Unaligned>(Matrix4d()) );
+    CALL_SUBTEST_3( map_class_matrix<Aligned>(Matrix<float,3,5>()) );
+    CALL_SUBTEST_3( map_class_matrix<Unaligned>(Matrix<float,3,5>()) );
+    CALL_SUBTEST_3( map_class_matrix<Aligned>(Matrix<float,4,8>()) );
+    CALL_SUBTEST_3( map_class_matrix<Unaligned>(Matrix<float,4,8>()) );
+    CALL_SUBTEST_4( map_class_matrix<Aligned>(MatrixXcf(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_4( map_class_matrix<Unaligned>(MatrixXcf(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_5( map_class_matrix<Aligned>(MatrixXi(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_5( map_class_matrix<Unaligned>(MatrixXi(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_6( map_class_matrix<Aligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    CALL_SUBTEST_6( map_class_matrix<Unaligned>(MatrixXcd(internal::random<int>(1,maxn),internal::random<int>(1,maxn))) );
+    
+    TEST_SET_BUT_UNUSED_VARIABLE(maxn);
+  }
+}
diff --git a/test/meta.cpp b/test/meta.cpp
new file mode 100644
index 0000000..3302c58
--- /dev/null
+++ b/test/meta.cpp
@@ -0,0 +1,73 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+void test_meta()
+{
+  VERIFY((internal::conditional<(3<4),internal::true_type, internal::false_type>::type::value));
+  VERIFY(( internal::is_same<float,float>::value));
+  VERIFY((!internal::is_same<float,double>::value));
+  VERIFY((!internal::is_same<float,float&>::value));
+  VERIFY((!internal::is_same<float,const float&>::value));
+  
+  VERIFY(( internal::is_same<float,internal::remove_all<const float&>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<const float*>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<const float*&>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<float**>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<float**&>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<float* const *&>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_all<float* const>::type >::value));
+
+  // test add_const
+  VERIFY(( internal::is_same< internal::add_const<float>::type, const float >::value));
+  VERIFY(( internal::is_same< internal::add_const<float*>::type, float* const>::value));
+  VERIFY(( internal::is_same< internal::add_const<float const*>::type, float const* const>::value));
+  VERIFY(( internal::is_same< internal::add_const<float&>::type, float& >::value));
+
+  // test remove_const
+  VERIFY(( internal::is_same< internal::remove_const<float const* const>::type, float const* >::value));
+  VERIFY(( internal::is_same< internal::remove_const<float const*>::type, float const* >::value));
+  VERIFY(( internal::is_same< internal::remove_const<float* const>::type, float* >::value));
+
+  // test add_const_on_value_type
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<float&>::type, float const& >::value));
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<float*>::type, float const* >::value));
+
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<float>::type, const float >::value));
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<const float>::type, const float >::value));
+
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<const float* const>::type, const float* const>::value));
+  VERIFY(( internal::is_same< internal::add_const_on_value_type<float* const>::type, const float* const>::value));
+  
+  VERIFY(( internal::is_same<float,internal::remove_reference<float&>::type >::value));
+  VERIFY(( internal::is_same<const float,internal::remove_reference<const float&>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_pointer<float*>::type >::value));
+  VERIFY(( internal::is_same<const float,internal::remove_pointer<const float*>::type >::value));
+  VERIFY(( internal::is_same<float,internal::remove_pointer<float* const >::type >::value));
+  
+  VERIFY(internal::meta_sqrt<1>::ret == 1);
+  #define VERIFY_META_SQRT(X) VERIFY(internal::meta_sqrt<X>::ret == int(std::sqrt(double(X))))
+  VERIFY_META_SQRT(2);
+  VERIFY_META_SQRT(3);
+  VERIFY_META_SQRT(4);
+  VERIFY_META_SQRT(5);
+  VERIFY_META_SQRT(6);
+  VERIFY_META_SQRT(8);
+  VERIFY_META_SQRT(9);
+  VERIFY_META_SQRT(15);
+  VERIFY_META_SQRT(16);
+  VERIFY_META_SQRT(17);
+  VERIFY_META_SQRT(255);
+  VERIFY_META_SQRT(256);
+  VERIFY_META_SQRT(257);
+  VERIFY_META_SQRT(1023);
+  VERIFY_META_SQRT(1024);
+  VERIFY_META_SQRT(1025);
+}
diff --git a/test/metis_support.cpp b/test/metis_support.cpp
new file mode 100644
index 0000000..932b040
--- /dev/null
+++ b/test/metis_support.cpp
@@ -0,0 +1,39 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// 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/>.
+#include "sparse_solver.h"
+#include <Eigen/SparseLU>
+#include <Eigen/MetisSupport>
+#include <unsupported/Eigen/SparseExtra>
+
+template<typename T> void test_metis_T()
+{
+  SparseLU<SparseMatrix<T, ColMajor>, MetisOrdering<int> > sparselu_metis;
+  
+  check_sparse_square_solving(sparselu_metis); 
+}
+
+void test_metis_support()
+{
+  CALL_SUBTEST_1(test_metis_T<double>());
+}
diff --git a/test/miscmatrices.cpp b/test/miscmatrices.cpp
new file mode 100644
index 0000000..ef20dc7
--- /dev/null
+++ b/test/miscmatrices.cpp
@@ -0,0 +1,47 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void miscMatrices(const MatrixType& m)
+{
+  /* this test covers the following files:
+     DiagonalMatrix.h Ones.h
+  */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  Index r = internal::random<Index>(0, rows-1), r2 = internal::random<Index>(0, rows-1), c = internal::random<Index>(0, cols-1);
+  VERIFY_IS_APPROX(MatrixType::Ones(rows,cols)(r,c), static_cast<Scalar>(1));
+  MatrixType m1 = MatrixType::Ones(rows,cols);
+  VERIFY_IS_APPROX(m1(r,c), static_cast<Scalar>(1));
+  VectorType v1 = VectorType::Random(rows);
+  v1[0];
+  Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
+  square(v1.asDiagonal());
+  if(r==r2) VERIFY_IS_APPROX(square(r,r2), v1[r]);
+  else VERIFY_IS_MUCH_SMALLER_THAN(square(r,r2), static_cast<Scalar>(1));
+  square = MatrixType::Zero(rows, rows);
+  square.diagonal() = VectorType::Ones(rows);
+  VERIFY_IS_APPROX(square, MatrixType::Identity(rows, rows));
+}
+
+void test_miscmatrices()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( miscMatrices(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( miscMatrices(Matrix4d()) );
+    CALL_SUBTEST_3( miscMatrices(MatrixXcf(3, 3)) );
+    CALL_SUBTEST_4( miscMatrices(MatrixXi(8, 12)) );
+    CALL_SUBTEST_5( miscMatrices(MatrixXcd(20, 20)) );
+  }
+}
diff --git a/test/mixingtypes.cpp b/test/mixingtypes.cpp
new file mode 100644
index 0000000..6c2f748
--- /dev/null
+++ b/test/mixingtypes.cpp
@@ -0,0 +1,132 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// work around "uninitialized" warnings and give that option some testing
+#define EIGEN_INITIALIZE_MATRICES_BY_ZERO
+
+#ifndef EIGEN_NO_STATIC_ASSERT
+#define EIGEN_NO_STATIC_ASSERT // turn static asserts into runtime asserts in order to check them
+#endif
+
+// #ifndef EIGEN_DONT_VECTORIZE
+// #define EIGEN_DONT_VECTORIZE // SSE intrinsics aren't designed to allow mixing types
+// #endif
+
+#include "main.h"
+
+using namespace std;
+
+template<int SizeAtCompileType> void mixingtypes(int size = SizeAtCompileType)
+{
+  typedef std::complex<float>   CF;
+  typedef std::complex<double>  CD;
+  typedef Matrix<float, SizeAtCompileType, SizeAtCompileType> Mat_f;
+  typedef Matrix<double, SizeAtCompileType, SizeAtCompileType> Mat_d;
+  typedef Matrix<std::complex<float>, SizeAtCompileType, SizeAtCompileType> Mat_cf;
+  typedef Matrix<std::complex<double>, SizeAtCompileType, SizeAtCompileType> Mat_cd;
+  typedef Matrix<float, SizeAtCompileType, 1> Vec_f;
+  typedef Matrix<double, SizeAtCompileType, 1> Vec_d;
+  typedef Matrix<std::complex<float>, SizeAtCompileType, 1> Vec_cf;
+  typedef Matrix<std::complex<double>, SizeAtCompileType, 1> Vec_cd;
+
+  Mat_f mf    = Mat_f::Random(size,size);
+  Mat_d md    = mf.template cast<double>();
+  Mat_cf mcf  = Mat_cf::Random(size,size);
+  Mat_cd mcd  = mcf.template cast<complex<double> >();
+  Vec_f vf    = Vec_f::Random(size,1);
+  Vec_d vd    = vf.template cast<double>();
+  Vec_cf vcf  = Vec_cf::Random(size,1);
+  Vec_cd vcd  = vcf.template cast<complex<double> >();
+  float           sf  = internal::random<float>();
+  double          sd  = internal::random<double>();
+  complex<float>  scf = internal::random<complex<float> >();
+  complex<double> scd = internal::random<complex<double> >();
+
+
+  mf+mf;
+  VERIFY_RAISES_ASSERT(mf+md);
+  VERIFY_RAISES_ASSERT(mf+mcf);
+  VERIFY_RAISES_ASSERT(vf=vd);
+  VERIFY_RAISES_ASSERT(vf+=vd);
+  VERIFY_RAISES_ASSERT(mcd=md);
+
+  // check scalar products
+  VERIFY_IS_APPROX(vcf * sf , vcf * complex<float>(sf));
+  VERIFY_IS_APPROX(sd * vcd, complex<double>(sd) * vcd);
+  VERIFY_IS_APPROX(vf * scf , vf.template cast<complex<float> >() * scf);
+  VERIFY_IS_APPROX(scd * vd, scd * vd.template cast<complex<double> >());
+
+  // check dot product
+  vf.dot(vf);
+#if 0 // we get other compilation errors here than just static asserts
+  VERIFY_RAISES_ASSERT(vd.dot(vf));
+#endif
+  VERIFY_IS_APPROX(vcf.dot(vf), vcf.dot(vf.template cast<complex<float> >()));
+
+  // check diagonal product
+  VERIFY_IS_APPROX(vf.asDiagonal() * mcf, vf.template cast<complex<float> >().asDiagonal() * mcf);
+  VERIFY_IS_APPROX(vcd.asDiagonal() * md, vcd.asDiagonal() * md.template cast<complex<double> >());
+  VERIFY_IS_APPROX(mcf * vf.asDiagonal(), mcf * vf.template cast<complex<float> >().asDiagonal());
+  VERIFY_IS_APPROX(md * vcd.asDiagonal(), md.template cast<complex<double> >() * vcd.asDiagonal());
+//   vd.asDiagonal() * mf;    // does not even compile
+//   vcd.asDiagonal() * mf;   // does not even compile
+
+  // check inner product
+  VERIFY_IS_APPROX((vf.transpose() * vcf).value(), (vf.template cast<complex<float> >().transpose() * vcf).value());
+
+  // check outer product
+  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());
+
+  // coeff wise product
+
+  VERIFY_IS_APPROX((vf * vcf.transpose()).eval(), (vf.template cast<complex<float> >() * vcf.transpose()).eval());
+
+  Mat_cd mcd2 = mcd;
+  VERIFY_IS_APPROX(mcd.array() *= md.array(), mcd2.array() *= md.array().template cast<std::complex<double> >());
+  
+  // check matrix-matrix products
+
+  VERIFY_IS_APPROX(sd*md*mcd, (sd*md).template cast<CD>().eval()*mcd);
+  VERIFY_IS_APPROX(sd*mcd*md, sd*mcd*md.template cast<CD>());
+  VERIFY_IS_APPROX(scd*md*mcd, scd*md.template cast<CD>().eval()*mcd);
+  VERIFY_IS_APPROX(scd*mcd*md, scd*mcd*md.template cast<CD>());
+
+  VERIFY_IS_APPROX(sf*mf*mcf, sf*mf.template cast<CF>()*mcf);
+  VERIFY_IS_APPROX(sf*mcf*mf, sf*mcf*mf.template cast<CF>());
+  VERIFY_IS_APPROX(scf*mf*mcf, scf*mf.template cast<CF>()*mcf);
+  VERIFY_IS_APPROX(scf*mcf*mf, scf*mcf*mf.template cast<CF>());
+
+  VERIFY_IS_APPROX(sf*mf*vcf, (sf*mf).template cast<CF>().eval()*vcf);
+  VERIFY_IS_APPROX(scf*mf*vcf,(scf*mf.template cast<CF>()).eval()*vcf);
+  VERIFY_IS_APPROX(sf*mcf*vf, sf*mcf*vf.template cast<CF>());
+  VERIFY_IS_APPROX(scf*mcf*vf,scf*mcf*vf.template cast<CF>());
+
+  VERIFY_IS_APPROX(sf*vcf.adjoint()*mf,  sf*vcf.adjoint()*mf.template cast<CF>().eval());
+  VERIFY_IS_APPROX(scf*vcf.adjoint()*mf, scf*vcf.adjoint()*mf.template cast<CF>().eval());
+  VERIFY_IS_APPROX(sf*vf.adjoint()*mcf,  sf*vf.adjoint().template cast<CF>().eval()*mcf);
+  VERIFY_IS_APPROX(scf*vf.adjoint()*mcf, scf*vf.adjoint().template cast<CF>().eval()*mcf);
+
+  VERIFY_IS_APPROX(sd*md*vcd, (sd*md).template cast<CD>().eval()*vcd);
+  VERIFY_IS_APPROX(scd*md*vcd,(scd*md.template cast<CD>()).eval()*vcd);
+  VERIFY_IS_APPROX(sd*mcd*vd, sd*mcd*vd.template cast<CD>().eval());
+  VERIFY_IS_APPROX(scd*mcd*vd,scd*mcd*vd.template cast<CD>().eval());
+
+  VERIFY_IS_APPROX(sd*vcd.adjoint()*md,  sd*vcd.adjoint()*md.template cast<CD>().eval());
+  VERIFY_IS_APPROX(scd*vcd.adjoint()*md, scd*vcd.adjoint()*md.template cast<CD>().eval());
+  VERIFY_IS_APPROX(sd*vd.adjoint()*mcd,  sd*vd.adjoint().template cast<CD>().eval()*mcd);
+  VERIFY_IS_APPROX(scd*vd.adjoint()*mcd, scd*vd.adjoint().template cast<CD>().eval()*mcd);
+}
+
+void test_mixingtypes()
+{
+  CALL_SUBTEST_1(mixingtypes<3>());
+  CALL_SUBTEST_2(mixingtypes<4>());
+  CALL_SUBTEST_3(mixingtypes<Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)));
+}
diff --git a/test/nesting_ops.cpp b/test/nesting_ops.cpp
new file mode 100644
index 0000000..1e85232
--- /dev/null
+++ b/test/nesting_ops.cpp
@@ -0,0 +1,33 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template <typename MatrixType> void run_nesting_ops(const MatrixType& _m)
+{
+  typename MatrixType::Nested m(_m);
+
+  // Make really sure that we are in debug mode!
+  VERIFY_RAISES_ASSERT(eigen_assert(false));
+
+  // The only intention of these tests is to ensure that this code does
+  // not trigger any asserts or segmentation faults... more to come.
+  VERIFY_IS_APPROX( (m.transpose() * m).diagonal().sum(), (m.transpose() * m).diagonal().sum() );
+  VERIFY_IS_APPROX( (m.transpose() * m).diagonal().array().abs().sum(), (m.transpose() * m).diagonal().array().abs().sum() );
+
+  VERIFY_IS_APPROX( (m.transpose() * m).array().abs().sum(), (m.transpose() * m).array().abs().sum() );
+}
+
+void test_nesting_ops()
+{
+  CALL_SUBTEST_1(run_nesting_ops(MatrixXf::Random(25,25)));
+  CALL_SUBTEST_2(run_nesting_ops(MatrixXd::Random(25,25)));
+  CALL_SUBTEST_3(run_nesting_ops(Matrix4f::Random()));
+  CALL_SUBTEST_4(run_nesting_ops(Matrix4d::Random()));
+}
diff --git a/test/nomalloc.cpp b/test/nomalloc.cpp
new file mode 100644
index 0000000..8e04023
--- /dev/null
+++ b/test/nomalloc.cpp
@@ -0,0 +1,212 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// this hack is needed to make this file compiles with -pedantic (gcc)
+#ifdef __GNUC__
+#define throw(X)
+#endif
+
+#ifdef __INTEL_COMPILER
+  // disable "warning #76: argument to macro is empty" produced by the above hack
+  #pragma warning disable 76
+#endif
+
+// discard stack allocation as that too bypasses malloc
+#define EIGEN_STACK_ALLOCATION_LIMIT 0
+// any heap allocation will raise an assert
+#define EIGEN_NO_MALLOC
+
+#include "main.h"
+#include <Eigen/Cholesky>
+#include <Eigen/Eigenvalues>
+#include <Eigen/LU>
+#include <Eigen/QR>
+#include <Eigen/SVD>
+
+template<typename MatrixType> void nomalloc(const MatrixType& m)
+{
+  /* this test check no dynamic memory allocation are issued with fixed-size matrices
+  */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  Scalar s1 = internal::random<Scalar>();
+
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(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)));
+  VERIFY_IS_APPROX(m1.cwiseProduct(m1.block(0,0,rows,cols)), (m1.array()*m1.array()).matrix());
+  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
+  
+  m2.col(0).noalias() = m1 * m1.col(0);
+  m2.col(0).noalias() -= m1.adjoint() * m1.col(0);
+  m2.col(0).noalias() -= m1 * m1.row(0).adjoint();
+  m2.col(0).noalias() -= m1.adjoint() * m1.row(0).adjoint();
+
+  m2.row(0).noalias() = m1.row(0) * m1;
+  m2.row(0).noalias() -= m1.row(0) * m1.adjoint();
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1;
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint();
+  VERIFY_IS_APPROX(m2,m2);
+  
+  m2.col(0).noalias() = m1.template triangularView<Upper>() * m1.col(0);
+  m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.col(0);
+  m2.col(0).noalias() -= m1.template triangularView<Upper>() * m1.row(0).adjoint();
+  m2.col(0).noalias() -= m1.adjoint().template triangularView<Upper>() * m1.row(0).adjoint();
+
+  m2.row(0).noalias() = m1.row(0) * m1.template triangularView<Upper>();
+  m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template triangularView<Upper>();
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template triangularView<Upper>();
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template triangularView<Upper>();
+  VERIFY_IS_APPROX(m2,m2);
+  
+  m2.col(0).noalias() = m1.template selfadjointView<Upper>() * m1.col(0);
+  m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.col(0);
+  m2.col(0).noalias() -= m1.template selfadjointView<Upper>() * m1.row(0).adjoint();
+  m2.col(0).noalias() -= m1.adjoint().template selfadjointView<Upper>() * m1.row(0).adjoint();
+
+  m2.row(0).noalias() = m1.row(0) * m1.template selfadjointView<Upper>();
+  m2.row(0).noalias() -= m1.row(0) * m1.adjoint().template selfadjointView<Upper>();
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1.template selfadjointView<Upper>();
+  m2.row(0).noalias() -= m1.col(0).adjoint() * m1.adjoint().template selfadjointView<Upper>();
+  VERIFY_IS_APPROX(m2,m2);
+  
+  m2.template selfadjointView<Lower>().rankUpdate(m1.col(0),-1);
+  m2.template selfadjointView<Lower>().rankUpdate(m1.row(0),-1);
+
+  // The following fancy matrix-matrix products are not safe yet regarding static allocation
+//   m1 += m1.template triangularView<Upper>() * m2.col(;
+//   m1.template selfadjointView<Lower>().rankUpdate(m2);
+//   m1 += m1.template triangularView<Upper>() * m2;
+//   m1 += m1.template selfadjointView<Lower>() * m2;
+//   VERIFY_IS_APPROX(m1,m1);
+}
+
+template<typename Scalar>
+void ctms_decompositions()
+{
+  const int maxSize = 16;
+  const int size    = 12;
+
+  typedef Eigen::Matrix<Scalar,
+                        Eigen::Dynamic, Eigen::Dynamic,
+                        0,
+                        maxSize, maxSize> Matrix;
+
+  typedef Eigen::Matrix<Scalar,
+                        Eigen::Dynamic, 1,
+                        0,
+                        maxSize, 1> Vector;
+
+  typedef Eigen::Matrix<std::complex<Scalar>,
+                        Eigen::Dynamic, Eigen::Dynamic,
+                        0,
+                        maxSize, maxSize> ComplexMatrix;
+
+  const Matrix A(Matrix::Random(size, size)), B(Matrix::Random(size, size));
+  Matrix X(size,size);
+  const ComplexMatrix complexA(ComplexMatrix::Random(size, size));
+  const Matrix saA = A.adjoint() * A;
+  const Vector b(Vector::Random(size));
+  Vector x(size);
+
+  // Cholesky module
+  Eigen::LLT<Matrix>  LLT;  LLT.compute(A);
+  X = LLT.solve(B);
+  x = LLT.solve(b);
+  Eigen::LDLT<Matrix> LDLT; LDLT.compute(A);
+  X = LDLT.solve(B);
+  x = LDLT.solve(b);
+
+  // Eigenvalues module
+  Eigen::HessenbergDecomposition<ComplexMatrix> hessDecomp;        hessDecomp.compute(complexA);
+  Eigen::ComplexSchur<ComplexMatrix>            cSchur(size);      cSchur.compute(complexA);
+  Eigen::ComplexEigenSolver<ComplexMatrix>      cEigSolver;        cEigSolver.compute(complexA);
+  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);
+  X = ppLU.solve(B);
+  x = ppLU.solve(b);
+  Eigen::FullPivLU<Matrix>    fpLU; fpLU.compute(A);
+  X = fpLU.solve(B);
+  x = fpLU.solve(b);
+
+  // QR module
+  Eigen::HouseholderQR<Matrix>        hQR;  hQR.compute(A);
+  X = hQR.solve(B);
+  x = hQR.solve(b);
+  Eigen::ColPivHouseholderQR<Matrix>  cpQR; cpQR.compute(A);
+  X = cpQR.solve(B);
+  x = cpQR.solve(b);
+  Eigen::FullPivHouseholderQR<Matrix> fpQR; fpQR.compute(A);
+  // FIXME X = fpQR.solve(B);
+  x = fpQR.solve(b);
+
+  // SVD module
+  Eigen::JacobiSVD<Matrix> jSVD; jSVD.compute(A, ComputeFullU | ComputeFullV);
+}
+
+void test_zerosized() {
+  // default constructors:
+  Eigen::MatrixXd A;
+  Eigen::VectorXd v;
+  // explicit zero-sized:
+  Eigen::ArrayXXd A0(0,0);
+  Eigen::ArrayXd v0(std::ptrdiff_t(0)); // FIXME ArrayXd(0) is ambiguous
+
+  // assigning empty objects to each other:
+  A=A0;
+  v=v0;
+}
+
+template<typename MatrixType> void test_reference(const MatrixType& m) {
+  typedef typename MatrixType::Scalar Scalar;
+  enum { Flag          =  MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
+  enum { TransposeFlag = !MatrixType::IsRowMajor ? Eigen::RowMajor : Eigen::ColMajor};
+  typename MatrixType::Index rows = m.rows(), cols=m.cols();
+  // Dynamic reference:
+  typedef Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Flag         > > Ref;
+  typedef Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, TransposeFlag> > RefT;
+
+  Ref r1(m);
+  Ref r2(m.block(rows/3, cols/4, rows/2, cols/2));
+  RefT r3(m.transpose());
+  RefT r4(m.topLeftCorner(rows/2, cols/2).transpose());
+
+  VERIFY_RAISES_ASSERT(RefT r5(m));
+  VERIFY_RAISES_ASSERT(Ref r6(m.transpose()));
+  VERIFY_RAISES_ASSERT(Ref r7(Scalar(2) * m));
+}
+
+void test_nomalloc()
+{
+  // check that our operator new is indeed called:
+  VERIFY_RAISES_ASSERT(MatrixXd dummy(MatrixXd::Random(3,3)));
+  CALL_SUBTEST_1(nomalloc(Matrix<float, 1, 1>()) );
+  CALL_SUBTEST_2(nomalloc(Matrix4d()) );
+  CALL_SUBTEST_3(nomalloc(Matrix<float,32,32>()) );
+  
+  // Check decomposition modules with dynamic matrices that have a known compile-time max size (ctms)
+  CALL_SUBTEST_4(ctms_decompositions<float>());
+  CALL_SUBTEST_5(test_zerosized());
+  CALL_SUBTEST_6(test_reference(Matrix<float,32,32>()));
+}
diff --git a/test/nullary.cpp b/test/nullary.cpp
new file mode 100644
index 0000000..fbc721a
--- /dev/null
+++ b/test/nullary.cpp
@@ -0,0 +1,131 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010-2011 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType>
+bool equalsIdentity(const MatrixType& A)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  Scalar zero = static_cast<Scalar>(0);
+
+  bool offDiagOK = true;
+  for (Index i = 0; i < A.rows(); ++i) {
+    for (Index j = i+1; j < A.cols(); ++j) {
+      offDiagOK = offDiagOK && (A(i,j) == zero);
+    }
+  }
+  for (Index i = 0; i < A.rows(); ++i) {
+    for (Index j = 0; j < (std::min)(i, A.cols()); ++j) {
+      offDiagOK = offDiagOK && (A(i,j) == zero);
+    }
+  }
+
+  bool diagOK = (A.diagonal().array() == 1).all();
+  return offDiagOK && diagOK;
+}
+
+template<typename VectorType>
+void testVectorType(const VectorType& base)
+{
+  typedef typename internal::traits<VectorType>::Index Index;
+  typedef typename internal::traits<VectorType>::Scalar Scalar;
+
+  const Index size = base.size();
+  
+  Scalar high = internal::random<Scalar>(-500,500);
+  Scalar low = (size == 1 ? high : internal::random<Scalar>(-500,500));
+  if (low>high) std::swap(low,high);
+
+  const Scalar step = ((size == 1) ? 1 : (high-low)/(size-1));
+
+  // check whether the result yields what we expect it to do
+  VectorType m(base);
+  m.setLinSpaced(size,low,high);
+
+  VectorType n(size);
+  for (int i=0; i<size; ++i)
+    n(i) = low+i*step;
+
+  VERIFY_IS_APPROX(m,n);
+
+  // random access version
+  m = VectorType::LinSpaced(size,low,high);
+  VERIFY_IS_APPROX(m,n);
+
+  // Assignment of a RowVectorXd to a MatrixXd (regression test for bug #79).
+  VERIFY( (MatrixXd(RowVectorXd::LinSpaced(3, 0, 1)) - RowVector3d(0, 0.5, 1)).norm() < std::numeric_limits<Scalar>::epsilon() );
+
+  // These guys sometimes fail! This is not good. Any ideas how to fix them!?
+  //VERIFY( m(m.size()-1) == high );
+  //VERIFY( m(0) == low );
+
+  // sequential access version
+  m = VectorType::LinSpaced(Sequential,size,low,high);
+  VERIFY_IS_APPROX(m,n);
+
+  // These guys sometimes fail! This is not good. Any ideas how to fix them!?
+  //VERIFY( m(m.size()-1) == high );
+  //VERIFY( m(0) == low );
+
+  // check whether everything works with row and col major vectors
+  Matrix<Scalar,Dynamic,1> row_vector(size);
+  Matrix<Scalar,1,Dynamic> col_vector(size);
+  row_vector.setLinSpaced(size,low,high);
+  col_vector.setLinSpaced(size,low,high);
+  // when using the extended precision (e.g., FPU) the relative error might exceed 1 bit
+  // when computing the squared sum in isApprox, thus the 2x factor.
+  VERIFY( row_vector.isApprox(col_vector.transpose(), Scalar(2)*NumTraits<Scalar>::epsilon()));
+
+  Matrix<Scalar,Dynamic,1> size_changer(size+50);
+  size_changer.setLinSpaced(size,low,high);
+  VERIFY( size_changer.size() == size );
+
+  typedef Matrix<Scalar,1,1> ScalarMatrix;
+  ScalarMatrix scalar;
+  scalar.setLinSpaced(1,low,high);
+  VERIFY_IS_APPROX( scalar, ScalarMatrix::Constant(high) );
+  VERIFY_IS_APPROX( ScalarMatrix::LinSpaced(1,low,high), ScalarMatrix::Constant(high) );
+
+  // regression test for bug 526 (linear vectorized transversal)
+  if (size > 1) {
+    m.tail(size-1).setLinSpaced(low, high);
+    VERIFY_IS_APPROX(m(size-1), high);
+  }
+}
+
+template<typename MatrixType>
+void testMatrixType(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  const Index rows = m.rows();
+  const Index cols = m.cols();
+
+  MatrixType A;
+  A.setIdentity(rows, cols);
+  VERIFY(equalsIdentity(A));
+  VERIFY(equalsIdentity(MatrixType::Identity(rows, cols)));
+}
+
+void test_nullary()
+{
+  CALL_SUBTEST_1( testMatrixType(Matrix2d()) );
+  CALL_SUBTEST_2( testMatrixType(MatrixXcf(internal::random<int>(1,300),internal::random<int>(1,300))) );
+  CALL_SUBTEST_3( testMatrixType(MatrixXf(internal::random<int>(1,300),internal::random<int>(1,300))) );
+  
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_4( testVectorType(VectorXd(internal::random<int>(1,300))) );
+    CALL_SUBTEST_5( testVectorType(Vector4d()) );  // regression test for bug 232
+    CALL_SUBTEST_6( testVectorType(Vector3d()) );
+    CALL_SUBTEST_7( testVectorType(VectorXf(internal::random<int>(1,300))) );
+    CALL_SUBTEST_8( testVectorType(Vector3f()) );
+    CALL_SUBTEST_8( testVectorType(Matrix<float,1,1>()) );
+  }
+}
diff --git a/test/packetmath.cpp b/test/packetmath.cpp
new file mode 100644
index 0000000..38aa256
--- /dev/null
+++ b/test/packetmath.cpp
@@ -0,0 +1,385 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+// using namespace Eigen;
+
+namespace Eigen {
+namespace internal {
+template<typename T> T negate(const T& x) { return -x; }
+}
+}
+
+template<typename Scalar> bool isApproxAbs(const Scalar& a, const Scalar& b, const typename NumTraits<Scalar>::Real& refvalue)
+{
+  return internal::isMuchSmallerThan(a-b, refvalue);
+}
+
+template<typename Scalar> bool areApproxAbs(const Scalar* a, const Scalar* b, int size, const typename NumTraits<Scalar>::Real& refvalue)
+{
+  for (int i=0; i<size; ++i)
+  {
+    if (!isApproxAbs(a[i],b[i],refvalue))
+    {
+      std::cout << "[" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != " << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "\n";
+      return false;
+    }
+  }
+  return true;
+}
+
+template<typename Scalar> bool areApprox(const Scalar* a, const Scalar* b, int size)
+{
+  for (int i=0; i<size; ++i)
+  {
+    if (a[i]!=b[i] && !internal::isApprox(a[i],b[i]))
+    {
+      std::cout << "[" << Map<const Matrix<Scalar,1,Dynamic> >(a,size) << "]" << " != " << Map<const Matrix<Scalar,1,Dynamic> >(b,size) << "\n";
+      return false;
+    }
+  }
+  return true;
+}
+
+
+#define CHECK_CWISE2(REFOP, POP) { \
+  for (int i=0; i<PacketSize; ++i) \
+    ref[i] = REFOP(data1[i], data1[i+PacketSize]); \
+  internal::pstore(data2, POP(internal::pload<Packet>(data1), internal::pload<Packet>(data1+PacketSize))); \
+  VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
+}
+
+#define CHECK_CWISE1(REFOP, POP) { \
+  for (int i=0; i<PacketSize; ++i) \
+    ref[i] = REFOP(data1[i]); \
+  internal::pstore(data2, POP(internal::pload<Packet>(data1))); \
+  VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
+}
+
+template<bool Cond,typename Packet>
+struct packet_helper
+{
+  template<typename T>
+  inline Packet load(const T* from) const { return internal::pload<Packet>(from); }
+
+  template<typename T>
+  inline void store(T* to, const Packet& x) const { internal::pstore(to,x); }
+};
+
+template<typename Packet>
+struct packet_helper<false,Packet>
+{
+  template<typename T>
+  inline T load(const T* from) const { return *from; }
+
+  template<typename T>
+  inline void store(T* to, const T& x) const { *to = x; }
+};
+
+#define CHECK_CWISE1_IF(COND, REFOP, POP) if(COND) { \
+  packet_helper<COND,Packet> h; \
+  for (int i=0; i<PacketSize; ++i) \
+    ref[i] = REFOP(data1[i]); \
+  h.store(data2, POP(h.load(data1))); \
+  VERIFY(areApprox(ref, data2, PacketSize) && #POP); \
+}
+
+#define REF_ADD(a,b) ((a)+(b))
+#define REF_SUB(a,b) ((a)-(b))
+#define REF_MUL(a,b) ((a)*(b))
+#define REF_DIV(a,b) ((a)/(b))
+
+template<typename Scalar> void packetmath()
+{
+  using std::abs;
+  typedef typename internal::packet_traits<Scalar>::type Packet;
+  const int PacketSize = internal::packet_traits<Scalar>::size;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  const int size = PacketSize*4;
+  EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Packet packets[PacketSize*2];
+  EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+  RealScalar refvalue = 0;
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>()/RealScalar(PacketSize);
+    data2[i] = internal::random<Scalar>()/RealScalar(PacketSize);
+    refvalue = (std::max)(refvalue,abs(data1[i]));
+  }
+
+  internal::pstore(data2, internal::pload<Packet>(data1));
+  VERIFY(areApprox(data1, data2, PacketSize) && "aligned load/store");
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    internal::pstore(data2, internal::ploadu<Packet>(data1+offset));
+    VERIFY(areApprox(data1+offset, data2, PacketSize) && "internal::ploadu");
+  }
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    internal::pstoreu(data2+offset, internal::pload<Packet>(data1));
+    VERIFY(areApprox(data1, data2+offset, PacketSize) && "internal::pstoreu");
+  }
+
+  for (int offset=0; offset<PacketSize; ++offset)
+  {
+    packets[0] = internal::pload<Packet>(data1);
+    packets[1] = internal::pload<Packet>(data1+PacketSize);
+         if (offset==0) internal::palign<0>(packets[0], packets[1]);
+    else if (offset==1) internal::palign<1>(packets[0], packets[1]);
+    else if (offset==2) internal::palign<2>(packets[0], packets[1]);
+    else if (offset==3) internal::palign<3>(packets[0], packets[1]);
+    internal::pstore(data2, packets[0]);
+
+    for (int i=0; i<PacketSize; ++i)
+      ref[i] = data1[i+offset];
+
+    VERIFY(areApprox(ref, data2, PacketSize) && "internal::palign");
+  }
+
+  CHECK_CWISE2(REF_ADD,  internal::padd);
+  CHECK_CWISE2(REF_SUB,  internal::psub);
+  CHECK_CWISE2(REF_MUL,  internal::pmul);
+  #ifndef EIGEN_VECTORIZE_ALTIVEC
+  if (!internal::is_same<Scalar,int>::value)
+    CHECK_CWISE2(REF_DIV,  internal::pdiv);
+  #endif
+  CHECK_CWISE1(internal::negate, internal::pnegate);
+  CHECK_CWISE1(numext::conj, internal::pconj);
+
+  for(int offset=0;offset<3;++offset)
+  {
+    for (int i=0; i<PacketSize; ++i)
+      ref[i] = data1[offset];
+    internal::pstore(data2, internal::pset1<Packet>(data1[offset]));
+    VERIFY(areApprox(ref, data2, PacketSize) && "internal::pset1");
+  }
+  
+  VERIFY(internal::isApprox(data1[0], internal::pfirst(internal::pload<Packet>(data1))) && "internal::pfirst");
+  
+  if(PacketSize>1)
+  {
+    for(int offset=0;offset<4;++offset)
+    {
+      for(int i=0;i<PacketSize/2;++i)
+        ref[2*i+0] = ref[2*i+1] = data1[offset+i];
+      internal::pstore(data2,internal::ploaddup<Packet>(data1+offset));
+      VERIFY(areApprox(ref, data2, PacketSize) && "ploaddup");
+    }
+  }
+
+  ref[0] = 0;
+  for (int i=0; i<PacketSize; ++i)
+    ref[0] += data1[i];
+  VERIFY(isApproxAbs(ref[0], internal::predux(internal::pload<Packet>(data1)), refvalue) && "internal::predux");
+
+  ref[0] = 1;
+  for (int i=0; i<PacketSize; ++i)
+    ref[0] *= data1[i];
+  VERIFY(internal::isApprox(ref[0], internal::predux_mul(internal::pload<Packet>(data1))) && "internal::predux_mul");
+
+  for (int j=0; j<PacketSize; ++j)
+  {
+    ref[j] = 0;
+    for (int i=0; i<PacketSize; ++i)
+      ref[j] += data1[i+j*PacketSize];
+    packets[j] = internal::pload<Packet>(data1+j*PacketSize);
+  }
+  internal::pstore(data2, internal::preduxp(packets));
+  VERIFY(areApproxAbs(ref, data2, PacketSize, refvalue) && "internal::preduxp");
+
+  for (int i=0; i<PacketSize; ++i)
+    ref[i] = data1[PacketSize-i-1];
+  internal::pstore(data2, internal::preverse(internal::pload<Packet>(data1)));
+  VERIFY(areApprox(ref, data2, PacketSize) && "internal::preverse");
+}
+
+template<typename Scalar> void packetmath_real()
+{
+  using std::abs;
+  typedef typename internal::packet_traits<Scalar>::type Packet;
+  const int PacketSize = internal::packet_traits<Scalar>::size;
+
+  const int size = PacketSize*4;
+  EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
+    data2[i] = internal::random<Scalar>(-1,1) * std::pow(Scalar(10), internal::random<Scalar>(-3,3));
+  }
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSin, std::sin, internal::psin);
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasCos, std::cos, internal::pcos);
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasTan, std::tan, internal::ptan);
+  
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>(-1,1);
+    data2[i] = internal::random<Scalar>(-1,1);
+  }
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasASin, std::asin, internal::pasin);
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasACos, std::acos, internal::pacos);
+
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>(-87,88);
+    data2[i] = internal::random<Scalar>(-87,88);
+  }
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasExp, std::exp, internal::pexp);
+  {
+    data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+    packet_helper<internal::packet_traits<Scalar>::HasExp,Packet> h;
+    h.store(data2, internal::pexp(h.load(data1))); 
+    VERIFY(isNaN(data2[0]));
+  }
+
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
+    data2[i] = internal::random<Scalar>(0,1) * std::pow(Scalar(10), internal::random<Scalar>(-6,6));
+  }
+  if(internal::random<float>(0,1)<0.1)
+    data1[internal::random<int>(0, PacketSize)] = 0;
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasSqrt, std::sqrt, internal::psqrt);
+  CHECK_CWISE1_IF(internal::packet_traits<Scalar>::HasLog, std::log, internal::plog);
+  {
+    data1[0] = std::numeric_limits<Scalar>::quiet_NaN();
+    packet_helper<internal::packet_traits<Scalar>::HasLog,Packet> h;
+    h.store(data2, internal::plog(h.load(data1)));
+    VERIFY(isNaN(data2[0]));
+    data1[0] = -1.0f;
+    h.store(data2, internal::plog(h.load(data1)));
+    VERIFY(isNaN(data2[0]));
+#if !EIGEN_FAST_MATH
+    h.store(data2, internal::psqrt(h.load(data1)));
+    VERIFY(isNaN(data2[0]));
+    VERIFY(isNaN(data2[1]));
+#endif
+  }
+}
+
+template<typename Scalar> void packetmath_notcomplex()
+{
+  using std::abs;
+  typedef typename internal::packet_traits<Scalar>::type Packet;
+  const int PacketSize = internal::packet_traits<Scalar>::size;
+
+  EIGEN_ALIGN16 Scalar data1[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Scalar data2[internal::packet_traits<Scalar>::size*4];
+  EIGEN_ALIGN16 Scalar ref[internal::packet_traits<Scalar>::size*4];
+  
+  Array<Scalar,Dynamic,1>::Map(data1, internal::packet_traits<Scalar>::size*4).setRandom();
+
+  ref[0] = data1[0];
+  for (int i=0; i<PacketSize; ++i)
+    ref[0] = (std::min)(ref[0],data1[i]);
+  VERIFY(internal::isApprox(ref[0], internal::predux_min(internal::pload<Packet>(data1))) && "internal::predux_min");
+
+  CHECK_CWISE2((std::min), internal::pmin);
+  CHECK_CWISE2((std::max), internal::pmax);
+  CHECK_CWISE1(abs, internal::pabs);
+
+  ref[0] = data1[0];
+  for (int i=0; i<PacketSize; ++i)
+    ref[0] = (std::max)(ref[0],data1[i]);
+  VERIFY(internal::isApprox(ref[0], internal::predux_max(internal::pload<Packet>(data1))) && "internal::predux_max");
+  
+  for (int i=0; i<PacketSize; ++i)
+    ref[i] = data1[0]+Scalar(i);
+  internal::pstore(data2, internal::plset(data1[0]));
+  VERIFY(areApprox(ref, data2, PacketSize) && "internal::plset");
+}
+
+template<typename Scalar,bool ConjLhs,bool ConjRhs> void test_conj_helper(Scalar* data1, Scalar* data2, Scalar* ref, Scalar* pval)
+{
+  typedef typename internal::packet_traits<Scalar>::type Packet;
+  const int PacketSize = internal::packet_traits<Scalar>::size;
+  
+  internal::conj_if<ConjLhs> cj0;
+  internal::conj_if<ConjRhs> cj1;
+  internal::conj_helper<Scalar,Scalar,ConjLhs,ConjRhs> cj;
+  internal::conj_helper<Packet,Packet,ConjLhs,ConjRhs> pcj;
+  
+  for(int i=0;i<PacketSize;++i)
+  {
+    ref[i] = cj0(data1[i]) * cj1(data2[i]);
+    VERIFY(internal::isApprox(ref[i], cj.pmul(data1[i],data2[i])) && "conj_helper pmul");
+  }
+  internal::pstore(pval,pcj.pmul(internal::pload<Packet>(data1),internal::pload<Packet>(data2)));
+  VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmul");
+  
+  for(int i=0;i<PacketSize;++i)
+  {
+    Scalar tmp = ref[i];
+    ref[i] += cj0(data1[i]) * cj1(data2[i]);
+    VERIFY(internal::isApprox(ref[i], cj.pmadd(data1[i],data2[i],tmp)) && "conj_helper pmadd");
+  }
+  internal::pstore(pval,pcj.pmadd(internal::pload<Packet>(data1),internal::pload<Packet>(data2),internal::pload<Packet>(pval)));
+  VERIFY(areApprox(ref, pval, PacketSize) && "conj_helper pmadd");
+}
+
+template<typename Scalar> void packetmath_complex()
+{
+  typedef typename internal::packet_traits<Scalar>::type Packet;
+  const int PacketSize = internal::packet_traits<Scalar>::size;
+
+  const int size = PacketSize*4;
+  EIGEN_ALIGN16 Scalar data1[PacketSize*4];
+  EIGEN_ALIGN16 Scalar data2[PacketSize*4];
+  EIGEN_ALIGN16 Scalar ref[PacketSize*4];
+  EIGEN_ALIGN16 Scalar pval[PacketSize*4];
+
+  for (int i=0; i<size; ++i)
+  {
+    data1[i] = internal::random<Scalar>() * Scalar(1e2);
+    data2[i] = internal::random<Scalar>() * Scalar(1e2);
+  }
+  
+  test_conj_helper<Scalar,false,false> (data1,data2,ref,pval);
+  test_conj_helper<Scalar,false,true>  (data1,data2,ref,pval);
+  test_conj_helper<Scalar,true,false>  (data1,data2,ref,pval);
+  test_conj_helper<Scalar,true,true>   (data1,data2,ref,pval);
+  
+  {
+    for(int i=0;i<PacketSize;++i)
+      ref[i] = Scalar(std::imag(data1[i]),std::real(data1[i]));
+    internal::pstore(pval,internal::pcplxflip(internal::pload<Packet>(data1)));
+    VERIFY(areApprox(ref, pval, PacketSize) && "pcplxflip");
+  }
+  
+  
+}
+
+void test_packetmath()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( packetmath<float>() );
+    CALL_SUBTEST_2( packetmath<double>() );
+    CALL_SUBTEST_3( packetmath<int>() );
+    CALL_SUBTEST_1( packetmath<std::complex<float> >() );
+    CALL_SUBTEST_2( packetmath<std::complex<double> >() );
+
+    CALL_SUBTEST_1( packetmath_notcomplex<float>() );
+    CALL_SUBTEST_2( packetmath_notcomplex<double>() );
+    CALL_SUBTEST_3( packetmath_notcomplex<int>() );
+    
+    CALL_SUBTEST_1( packetmath_real<float>() );
+    CALL_SUBTEST_2( packetmath_real<double>() );
+
+    CALL_SUBTEST_1( packetmath_complex<std::complex<float> >() );
+    CALL_SUBTEST_2( packetmath_complex<std::complex<double> >() );
+  }
+}
diff --git a/test/pardiso_support.cpp b/test/pardiso_support.cpp
new file mode 100644
index 0000000..67efad6
--- /dev/null
+++ b/test/pardiso_support.cpp
@@ -0,0 +1,29 @@
+/* 
+   Intel Copyright (C) ....
+*/
+
+#include "sparse_solver.h"
+#include <Eigen/PardisoSupport>
+
+template<typename T> void test_pardiso_T()
+{
+  PardisoLLT < SparseMatrix<T, RowMajor>, Lower> pardiso_llt_lower;
+  PardisoLLT < SparseMatrix<T, RowMajor>, Upper> pardiso_llt_upper;
+  PardisoLDLT < SparseMatrix<T, RowMajor>, Lower> pardiso_ldlt_lower;
+  PardisoLDLT < SparseMatrix<T, RowMajor>, Upper> pardiso_ldlt_upper;
+  PardisoLU  < SparseMatrix<T, RowMajor> > pardiso_lu;
+
+  check_sparse_spd_solving(pardiso_llt_lower);
+  check_sparse_spd_solving(pardiso_llt_upper);
+  check_sparse_spd_solving(pardiso_ldlt_lower);
+  check_sparse_spd_solving(pardiso_ldlt_upper);
+  check_sparse_square_solving(pardiso_lu);
+}
+
+void test_pardiso_support()
+{
+  CALL_SUBTEST_1(test_pardiso_T<float>());
+  CALL_SUBTEST_2(test_pardiso_T<double>());
+  CALL_SUBTEST_3(test_pardiso_T< std::complex<float> >());
+  CALL_SUBTEST_4(test_pardiso_T< std::complex<double> >());
+}
diff --git a/test/pastix_support.cpp b/test/pastix_support.cpp
new file mode 100644
index 0000000..14da094
--- /dev/null
+++ b/test/pastix_support.cpp
@@ -0,0 +1,44 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include "sparse_solver.h"
+#include <Eigen/PaStiXSupport>
+#include <unsupported/Eigen/SparseExtra>
+
+
+template<typename T> void test_pastix_T()
+{
+  PastixLLT< SparseMatrix<T, ColMajor>, Eigen::Lower > pastix_llt_lower;
+  PastixLDLT< SparseMatrix<T, ColMajor>, Eigen::Lower > pastix_ldlt_lower;
+  PastixLLT< SparseMatrix<T, ColMajor>, Eigen::Upper > pastix_llt_upper;
+  PastixLDLT< SparseMatrix<T, ColMajor>, Eigen::Upper > pastix_ldlt_upper;
+  PastixLU< SparseMatrix<T, ColMajor> > pastix_lu;
+
+  check_sparse_spd_solving(pastix_llt_lower);
+  check_sparse_spd_solving(pastix_ldlt_lower);
+  check_sparse_spd_solving(pastix_llt_upper);
+  check_sparse_spd_solving(pastix_ldlt_upper);
+  check_sparse_square_solving(pastix_lu);
+}
+
+// There is no support for selfadjoint matrices with PaStiX. 
+// Complex symmetric matrices should pass though
+template<typename T> void test_pastix_T_LU()
+{
+  PastixLU< SparseMatrix<T, ColMajor> > pastix_lu;
+  check_sparse_square_solving(pastix_lu);
+}
+
+void test_pastix_support()
+{
+  CALL_SUBTEST_1(test_pastix_T<float>());
+  CALL_SUBTEST_2(test_pastix_T<double>());
+  CALL_SUBTEST_3( (test_pastix_T_LU<std::complex<float> >()) );
+  CALL_SUBTEST_4(test_pastix_T_LU<std::complex<double> >());
+} 
diff --git a/test/permutationmatrices.cpp b/test/permutationmatrices.cpp
new file mode 100644
index 0000000..7b0dbc7
--- /dev/null
+++ b/test/permutationmatrices.cpp
@@ -0,0 +1,116 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+using namespace std;
+template<typename MatrixType> void permutationmatrices(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime,
+         Options = MatrixType::Options };
+  typedef PermutationMatrix<Rows> LeftPermutationType;
+  typedef Matrix<int, Rows, 1> LeftPermutationVectorType;
+  typedef Map<LeftPermutationType> MapLeftPerm;
+  typedef PermutationMatrix<Cols> RightPermutationType;
+  typedef Matrix<int, Cols, 1> RightPermutationVectorType;
+  typedef Map<RightPermutationType> MapRightPerm;
+
+  Index rows = m.rows();
+  Index 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;
+
+  for (int i=0; i<rows; i++)
+    for (int j=0; j<cols; j++)
+        VERIFY_IS_APPROX(m_permuted(lv(i),j), m_original(i,rv(j)));
+
+  Matrix<Scalar,Rows,Rows> lm(lp);
+  Matrix<Scalar,Cols,Cols> rm(rp);
+
+  VERIFY_IS_APPROX(m_permuted, lm*m_original*rm);
+
+  VERIFY_IS_APPROX(lp.inverse()*m_permuted*rp.inverse(), m_original);
+  VERIFY_IS_APPROX(lv.asPermutation().inverse()*m_permuted*rv.asPermutation().inverse(), m_original);
+  VERIFY_IS_APPROX(MapLeftPerm(lv.data(),lv.size()).inverse()*m_permuted*MapRightPerm(rv.data(),rv.size()).inverse(), m_original);
+  
+  VERIFY((lp*lp.inverse()).toDenseMatrix().isIdentity());
+  VERIFY((lv.asPermutation()*lv.asPermutation().inverse()).toDenseMatrix().isIdentity());
+  VERIFY((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv.data(),lv.size()).inverse()).toDenseMatrix().isIdentity());
+
+  LeftPermutationVectorType lv2;
+  randomPermutationVector(lv2, rows);
+  LeftPermutationType lp2(lv2);
+  Matrix<Scalar,Rows,Rows> lm2(lp2);
+  VERIFY_IS_APPROX((lp*lp2).toDenseMatrix().template cast<Scalar>(), lm*lm2);
+  VERIFY_IS_APPROX((lv.asPermutation()*lv2.asPermutation()).toDenseMatrix().template cast<Scalar>(), lm*lm2);
+  VERIFY_IS_APPROX((MapLeftPerm(lv.data(),lv.size())*MapLeftPerm(lv2.data(),lv2.size())).toDenseMatrix().template cast<Scalar>(), lm*lm2);
+
+  LeftPermutationType identityp;
+  identityp.setIdentity(rows);
+  VERIFY_IS_APPROX(m_original, identityp*m_original);
+
+  // check inplace permutations
+  m_permuted = m_original;
+  m_permuted = lp.inverse() * m_permuted;
+  VERIFY_IS_APPROX(m_permuted, lp.inverse()*m_original);
+
+  m_permuted = m_original;
+  m_permuted = m_permuted * rp.inverse();
+  VERIFY_IS_APPROX(m_permuted, m_original*rp.inverse());
+
+  m_permuted = m_original;
+  m_permuted = lp * m_permuted;
+  VERIFY_IS_APPROX(m_permuted, lp*m_original);
+
+  m_permuted = m_original;
+  m_permuted = m_permuted * rp;
+  VERIFY_IS_APPROX(m_permuted, m_original*rp);
+
+  if(rows>1 && cols>1)
+  {
+    lp2 = lp;
+    Index i = internal::random<Index>(0, rows-1);
+    Index j;
+    do j = internal::random<Index>(0, rows-1); while(j==i);
+    lp2.applyTranspositionOnTheLeft(i, j);
+    lm = lp;
+    lm.row(i).swap(lm.row(j));
+    VERIFY_IS_APPROX(lm, lp2.toDenseMatrix().template cast<Scalar>());
+
+    RightPermutationType rp2 = rp;
+    i = internal::random<Index>(0, cols-1);
+    do j = internal::random<Index>(0, cols-1); while(j==i);
+    rp2.applyTranspositionOnTheRight(i, j);
+    rm = rp;
+    rm.col(i).swap(rm.col(j));
+    VERIFY_IS_APPROX(rm, rp2.toDenseMatrix().template cast<Scalar>());
+  }  
+}
+
+void test_permutationmatrices()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( permutationmatrices(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( permutationmatrices(Matrix3f()) );
+    CALL_SUBTEST_3( permutationmatrices(Matrix<double,3,3,RowMajor>()) );
+    CALL_SUBTEST_4( permutationmatrices(Matrix4d()) );
+    CALL_SUBTEST_5( permutationmatrices(Matrix<double,40,60>()) );
+    CALL_SUBTEST_6( permutationmatrices(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 30)) );
+    CALL_SUBTEST_7( permutationmatrices(MatrixXcf(15, 10)) );
+  }
+}
diff --git a/test/prec_inverse_4x4.cpp b/test/prec_inverse_4x4.cpp
new file mode 100644
index 0000000..c4ef2d4
--- /dev/null
+++ b/test/prec_inverse_4x4.cpp
@@ -0,0 +1,68 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/LU>
+#include <algorithm>
+
+template<typename MatrixType> void inverse_permutation_4x4()
+{
+  typedef typename MatrixType::Scalar Scalar;
+  Vector4i indices(0,1,2,3);
+  for(int i = 0; i < 24; ++i)
+  {
+    MatrixType m = PermutationMatrix<4>(indices);
+    MatrixType inv = m.inverse();
+    double error = double( (m*inv-MatrixType::Identity()).norm() / NumTraits<Scalar>::epsilon() );
+    EIGEN_DEBUG_VAR(error)
+    VERIFY(error == 0.0);
+    std::next_permutation(indices.data(),indices.data()+4);
+  }
+}
+
+template<typename MatrixType> void inverse_general_4x4(int repeat)
+{
+  using std::abs;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  double error_sum = 0., error_max = 0.;
+  for(int i = 0; i < repeat; ++i)
+  {
+    MatrixType m;
+    RealScalar absdet;
+    do {
+      m = MatrixType::Random();
+      absdet = abs(m.determinant());
+    } while(absdet < NumTraits<Scalar>::epsilon());
+    MatrixType inv = m.inverse();
+    double error = double( (m*inv-MatrixType::Identity()).norm() * absdet / NumTraits<Scalar>::epsilon() );
+    error_sum += error;
+    error_max = (std::max)(error_max, error);
+  }
+  std::cerr << "inverse_general_4x4, Scalar = " << type_name<Scalar>() << std::endl;
+  double error_avg = error_sum / repeat;
+  EIGEN_DEBUG_VAR(error_avg);
+  EIGEN_DEBUG_VAR(error_max);
+   // FIXME that 1.25 used to be a 1.0 until the NumTraits changes on 28 April 2010, what's going wrong??
+   // FIXME that 1.25 used to be 1.2 until we tested gcc 4.1 on 30 June 2010 and got 1.21.
+  VERIFY(error_avg < (NumTraits<Scalar>::IsComplex ? 8.0 : 1.25));
+  VERIFY(error_max < (NumTraits<Scalar>::IsComplex ? 64.0 : 20.0));
+}
+
+void test_prec_inverse_4x4()
+{
+  CALL_SUBTEST_1((inverse_permutation_4x4<Matrix4f>()));
+  CALL_SUBTEST_1(( inverse_general_4x4<Matrix4f>(200000 * g_repeat) ));
+
+  CALL_SUBTEST_2((inverse_permutation_4x4<Matrix<double,4,4,RowMajor> >()));
+  CALL_SUBTEST_2(( inverse_general_4x4<Matrix<double,4,4,RowMajor> >(200000 * g_repeat) ));
+
+  CALL_SUBTEST_3((inverse_permutation_4x4<Matrix4cf>()));
+  CALL_SUBTEST_3((inverse_general_4x4<Matrix4cf>(50000 * g_repeat)));
+}
diff --git a/test/product.h b/test/product.h
new file mode 100644
index 0000000..0b3abe4
--- /dev/null
+++ b/test/product.h
@@ -0,0 +1,150 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename Derived1, typename Derived2>
+bool areNotApprox(const MatrixBase<Derived1>& m1, const MatrixBase<Derived2>& m2, typename Derived1::RealScalar epsilon = NumTraits<typename Derived1::RealScalar>::dummy_precision())
+{
+  return !((m1-m2).cwiseAbs2().maxCoeff() < epsilon * epsilon
+                          * (std::max)(m1.cwiseAbs2().maxCoeff(), m2.cwiseAbs2().maxCoeff()));
+}
+
+template<typename MatrixType> void product(const MatrixType& m)
+{
+  /* this test covers the following files:
+     Identity.h Product.h
+  */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> RowVectorType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> ColVectorType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> RowSquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, MatrixType::ColsAtCompileTime> ColSquareMatrixType;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime,
+                         MatrixType::Flags&RowMajorBit?ColMajor:RowMajor> OtherMajorMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // this test relies a lot on Random.h, and there's not much more that we can do
+  // to test it, hence I consider that we will have tested Random.h
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+  RowSquareMatrixType
+             identity = RowSquareMatrixType::Identity(rows, rows),
+             square = RowSquareMatrixType::Random(rows, rows),
+             res = RowSquareMatrixType::Random(rows, rows);
+  ColSquareMatrixType
+             square2 = ColSquareMatrixType::Random(cols, cols),
+             res2 = ColSquareMatrixType::Random(cols, cols);
+  RowVectorType v1 = RowVectorType::Random(rows);
+  ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols);
+  OtherMajorMatrixType tm1 = m1;
+
+  Scalar s1 = internal::random<Scalar>();
+
+  Index r  = internal::random<Index>(0, rows-1),
+        c  = internal::random<Index>(0, cols-1),
+        c2 = internal::random<Index>(0, cols-1);
+
+  // begin testing Product.h: only associativity for now
+  // (we use Transpose.h but this doesn't count as a test for it)
+  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
+  m3 = m1;
+  m3 *= m1.transpose() * m2;
+  VERIFY_IS_APPROX(m3,                      m1 * (m1.transpose()*m2));
+  VERIFY_IS_APPROX(m3,                      m1 * (m1.transpose()*m2));
+
+  // continue testing Product.h: distributivity
+  VERIFY_IS_APPROX(square*(m1 + m2),        square*m1+square*m2);
+  VERIFY_IS_APPROX(square*(m1 - m2),        square*m1-square*m2);
+
+  // continue testing Product.h: compatibility with ScalarMultiple.h
+  VERIFY_IS_APPROX(s1*(square*m1),          (s1*square)*m1);
+  VERIFY_IS_APPROX(s1*(square*m1),          square*(m1*s1));
+
+  // test Product.h together with Identity.h
+  VERIFY_IS_APPROX(v1,                      identity*v1);
+  VERIFY_IS_APPROX(v1.transpose(),          v1.transpose() * identity);
+  // again, test operator() to check const-qualification
+  VERIFY_IS_APPROX(MatrixType::Identity(rows, cols)(r,c), static_cast<Scalar>(r==c));
+
+  if (rows!=cols)
+     VERIFY_RAISES_ASSERT(m3 = m1*m1);
+
+  // test the previous tests were not screwed up because operator* returns 0
+  // (we use the more accurate default epsilon)
+  if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(m1.transpose()*m2,m2.transpose()*m1));
+  }
+
+  // test optimized operator+= path
+  res = square;
+  res.noalias() += m1 * m2.transpose();
+  VERIFY_IS_APPROX(res, square + m1 * m2.transpose());
+  if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(res,square + m2 * m1.transpose()));
+  }
+  vcres = vc2;
+  vcres.noalias() += m1.transpose() * v1;
+  VERIFY_IS_APPROX(vcres, vc2 + m1.transpose() * v1);
+
+  // test optimized operator-= path
+  res = square;
+  res.noalias() -= m1 * m2.transpose();
+  VERIFY_IS_APPROX(res, square - (m1 * m2.transpose()));
+  if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(res,square - m2 * m1.transpose()));
+  }
+  vcres = vc2;
+  vcres.noalias() -= m1.transpose() * v1;
+  VERIFY_IS_APPROX(vcres, vc2 - m1.transpose() * v1);
+
+  tm1 = m1;
+  VERIFY_IS_APPROX(tm1.transpose() * v1, m1.transpose() * v1);
+  VERIFY_IS_APPROX(v1.transpose() * tm1, v1.transpose() * m1);
+
+  // test submatrix and matrix/vector product
+  for (int i=0; i<rows; ++i)
+    res.row(i) = m1.row(i) * m2.transpose();
+  VERIFY_IS_APPROX(res, m1 * m2.transpose());
+  // the other way round:
+  for (int i=0; i<rows; ++i)
+    res.col(i) = m1 * m2.transpose().col(i);
+  VERIFY_IS_APPROX(res, m1 * m2.transpose());
+
+  res2 = square2;
+  res2.noalias() += m1.transpose() * m2;
+  VERIFY_IS_APPROX(res2, square2 + m1.transpose() * m2);
+  if (!NumTraits<Scalar>::IsInteger && (std::min)(rows,cols)>1)
+  {
+    VERIFY(areNotApprox(res2,square2 + m2.transpose() * m1));
+  }
+
+  VERIFY_IS_APPROX(res.col(r).noalias() = square.adjoint() * square.col(r), (square.adjoint() * square.col(r)).eval());
+  VERIFY_IS_APPROX(res.col(r).noalias() = square * square.col(r), (square * square.col(r)).eval());
+
+  // inner product
+  Scalar x = square2.row(c) * square2.col(c2);
+  VERIFY_IS_APPROX(x, square2.row(c).transpose().cwiseProduct(square2.col(c2)).sum());
+  
+  // outer product
+  VERIFY_IS_APPROX(m1.col(c) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+  VERIFY_IS_APPROX(m1.row(r).transpose() * m1.col(c).transpose(), m1.block(r,0,1,cols).transpose() * m1.block(0,c,rows,1).transpose());
+  VERIFY_IS_APPROX(m1.block(0,c,rows,1) * m1.row(r), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+  VERIFY_IS_APPROX(m1.col(c) * m1.block(r,0,1,cols), m1.block(0,c,rows,1) * m1.block(r,0,1,cols));
+  VERIFY_IS_APPROX(m1.leftCols(1) * m1.row(r), m1.block(0,0,rows,1) * m1.block(r,0,1,cols));
+  VERIFY_IS_APPROX(m1.col(c) * m1.topRows(1), m1.block(0,c,rows,1) * m1.block(0,0,1,cols));  
+}
diff --git a/test/product_extra.cpp b/test/product_extra.cpp
new file mode 100644
index 0000000..ea24869
--- /dev/null
+++ b/test/product_extra.cpp
@@ -0,0 +1,237 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void product_extra(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
+  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
+  typedef Matrix<Scalar, Dynamic, Dynamic,
+                         MatrixType::Flags&RowMajorBit> OtherMajorMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             mzero = MatrixType::Zero(rows, cols),
+             identity = MatrixType::Identity(rows, rows),
+             square = MatrixType::Random(rows, rows),
+             res = MatrixType::Random(rows, rows),
+             square2 = MatrixType::Random(cols, cols),
+             res2 = MatrixType::Random(cols, cols);
+  RowVectorType v1 = RowVectorType::Random(rows), vrres(rows);
+  ColVectorType vc2 = ColVectorType::Random(cols), vcres(cols);
+  OtherMajorMatrixType tm1 = m1;
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>(),
+         s3 = internal::random<Scalar>();
+
+  VERIFY_IS_APPROX(m3.noalias() = m1 * m2.adjoint(),                 m1 * m2.adjoint().eval());
+  VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * square.adjoint(),   m1.adjoint().eval() * square.adjoint().eval());
+  VERIFY_IS_APPROX(m3.noalias() = m1.adjoint() * m2,                 m1.adjoint().eval() * m2);
+  VERIFY_IS_APPROX(m3.noalias() = (s1 * m1.adjoint()) * m2,          (s1 * m1.adjoint()).eval() * m2);
+  VERIFY_IS_APPROX(m3.noalias() = ((s1 * m1).adjoint()) * m2,        (numext::conj(s1) * m1.adjoint()).eval() * m2);
+  VERIFY_IS_APPROX(m3.noalias() = (- m1.adjoint() * s1) * (s3 * m2), (- m1.adjoint()  * s1).eval() * (s3 * m2).eval());
+  VERIFY_IS_APPROX(m3.noalias() = (s2 * m1.adjoint() * s1) * m2,     (s2 * m1.adjoint()  * s1).eval() * m2);
+  VERIFY_IS_APPROX(m3.noalias() = (-m1*s2) * s1*m2.adjoint(),        (-m1*s2).eval() * (s1*m2.adjoint()).eval());
+
+  // a very tricky case where a scale factor has to be automatically conjugated:
+  VERIFY_IS_APPROX( m1.adjoint() * (s1*m2).conjugate(), (m1.adjoint()).eval() * ((s1*m2).conjugate()).eval());
+
+
+  // test all possible conjugate combinations for the four matrix-vector product cases:
+
+  VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2),
+                   (-m1.conjugate()*s2).eval() * (s1 * vc2).eval());
+  VERIFY_IS_APPROX((-m1 * s2) * (s1 * vc2.conjugate()),
+                   (-m1*s2).eval() * (s1 * vc2.conjugate()).eval());
+  VERIFY_IS_APPROX((-m1.conjugate() * s2) * (s1 * vc2.conjugate()),
+                   (-m1.conjugate()*s2).eval() * (s1 * vc2.conjugate()).eval());
+
+  VERIFY_IS_APPROX((s1 * vc2.transpose()) * (-m1.adjoint() * s2),
+                   (s1 * vc2.transpose()).eval() * (-m1.adjoint()*s2).eval());
+  VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.transpose() * s2),
+                   (s1 * vc2.adjoint()).eval() * (-m1.transpose()*s2).eval());
+  VERIFY_IS_APPROX((s1 * vc2.adjoint()) * (-m1.adjoint() * s2),
+                   (s1 * vc2.adjoint()).eval() * (-m1.adjoint()*s2).eval());
+
+  VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.transpose()),
+                   (-m1.adjoint()*s2).eval() * (s1 * v1.transpose()).eval());
+  VERIFY_IS_APPROX((-m1.transpose() * s2) * (s1 * v1.adjoint()),
+                   (-m1.transpose()*s2).eval() * (s1 * v1.adjoint()).eval());
+  VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()),
+                   (-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval());
+
+  VERIFY_IS_APPROX((s1 * v1) * (-m1.conjugate() * s2),
+                   (s1 * v1).eval() * (-m1.conjugate()*s2).eval());
+  VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1 * s2),
+                   (s1 * v1.conjugate()).eval() * (-m1*s2).eval());
+  VERIFY_IS_APPROX((s1 * v1.conjugate()) * (-m1.conjugate() * s2),
+                   (s1 * v1.conjugate()).eval() * (-m1.conjugate()*s2).eval());
+
+  VERIFY_IS_APPROX((-m1.adjoint() * s2) * (s1 * v1.adjoint()),
+                   (-m1.adjoint()*s2).eval() * (s1 * v1.adjoint()).eval());
+
+  // test the vector-matrix product with non aligned starts
+  Index i = internal::random<Index>(0,m1.rows()-2);
+  Index j = internal::random<Index>(0,m1.cols()-2);
+  Index r = internal::random<Index>(1,m1.rows()-i);
+  Index c = internal::random<Index>(1,m1.cols()-j);
+  Index i2 = internal::random<Index>(0,m1.rows()-1);
+  Index j2 = internal::random<Index>(0,m1.cols()-1);
+
+  VERIFY_IS_APPROX(m1.col(j2).adjoint() * m1.block(0,j,m1.rows(),c), m1.col(j2).adjoint().eval() * m1.block(0,j,m1.rows(),c).eval());
+  VERIFY_IS_APPROX(m1.block(i,0,r,m1.cols()) * m1.row(i2).adjoint(), m1.block(i,0,r,m1.cols()).eval() * m1.row(i2).adjoint().eval());
+  
+  // regression test
+  MatrixType tmp = m1 * m1.adjoint() * s1;
+  VERIFY_IS_APPROX(tmp, m1 * m1.adjoint() * s1);
+}
+
+// Regression test for bug reported at http://forum.kde.org/viewtopic.php?f=74&t=96947
+void mat_mat_scalar_scalar_product()
+{
+  Eigen::Matrix2Xd dNdxy(2, 3);
+  dNdxy << -0.5, 0.5, 0,
+           -0.3, 0, 0.3;
+  double det = 6.0, wt = 0.5;
+  VERIFY_IS_APPROX(dNdxy.transpose()*dNdxy*det*wt, det*wt*dNdxy.transpose()*dNdxy);
+}
+
+template <typename MatrixType> 
+void zero_sized_objects(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  const int PacketSize  = internal::packet_traits<Scalar>::size;
+  const int PacketSize1 = PacketSize>1 ?  PacketSize-1 : 1;
+  DenseIndex rows = m.rows();
+  DenseIndex cols = m.cols();
+  
+  {
+    MatrixType res, a(rows,0), b(0,cols);
+    VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(rows,cols) );
+    VERIFY_IS_APPROX( (res=a*a.transpose()), MatrixType::Zero(rows,rows) );
+    VERIFY_IS_APPROX( (res=b.transpose()*b), MatrixType::Zero(cols,cols) );
+    VERIFY_IS_APPROX( (res=b.transpose()*a.transpose()), MatrixType::Zero(cols,rows) );
+  }
+  
+  {
+    MatrixType res, a(rows,cols), b(cols,0);
+    res = a*b;
+    VERIFY(res.rows()==rows && res.cols()==0);
+    b.resize(0,rows);
+    res = b*a;
+    VERIFY(res.rows()==0 && res.cols()==cols);
+  }
+  
+  {
+    Matrix<Scalar,PacketSize,0> a;
+    Matrix<Scalar,0,1> b;
+    Matrix<Scalar,PacketSize,1> res;
+    VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize,1) );
+    VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize,1) );
+  }
+  
+  {
+    Matrix<Scalar,PacketSize1,0> a;
+    Matrix<Scalar,0,1> b;
+    Matrix<Scalar,PacketSize1,1> res;
+    VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize1,1) );
+    VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize1,1) );
+  }
+  
+  {
+    Matrix<Scalar,PacketSize,Dynamic> a(PacketSize,0);
+    Matrix<Scalar,Dynamic,1> b(0,1);
+    Matrix<Scalar,PacketSize,1> res;
+    VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize,1) );
+    VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize,1) );
+  }
+  
+  {
+    Matrix<Scalar,PacketSize1,Dynamic> a(PacketSize1,0);
+    Matrix<Scalar,Dynamic,1> b(0,1);
+    Matrix<Scalar,PacketSize1,1> res;
+    VERIFY_IS_APPROX( (res=a*b), MatrixType::Zero(PacketSize1,1) );
+    VERIFY_IS_APPROX( (res=a.lazyProduct(b)), MatrixType::Zero(PacketSize1,1) );
+  }
+}
+
+void bug_127()
+{
+  // Bug 127
+  //
+  // a product of the form lhs*rhs with
+  //
+  // lhs:
+  // rows = 1, cols = 4
+  // RowsAtCompileTime = 1, ColsAtCompileTime = -1
+  // MaxRowsAtCompileTime = 1, MaxColsAtCompileTime = 5
+  //
+  // rhs:
+  // rows = 4, cols = 0
+  // RowsAtCompileTime = -1, ColsAtCompileTime = -1
+  // MaxRowsAtCompileTime = 5, MaxColsAtCompileTime = 1
+  //
+  // was failing on a runtime assertion, because it had been mis-compiled as a dot product because Product.h was using the
+  // max-sizes to detect size 1 indicating vectors, and that didn't account for 0-sized object with max-size 1.
+
+  Matrix<float,1,Dynamic,RowMajor,1,5> a(1,4);
+  Matrix<float,Dynamic,Dynamic,ColMajor,5,1> b(4,0);
+  a*b;
+}
+
+void unaligned_objects()
+{
+  // Regression test for the bug reported here:
+  // http://forum.kde.org/viewtopic.php?f=74&t=107541
+  // Recall the matrix*vector kernel avoid unaligned loads by loading two packets and then reassemble then.
+  // There was a mistake in the computation of the valid range for fully unaligned objects: in some rare cases,
+  // memory was read outside the allocated matrix memory. Though the values were not used, this might raise segfault.
+  for(int m=450;m<460;++m)
+  {
+    for(int n=8;n<12;++n)
+    {
+      MatrixXf M(m, n);
+      VectorXf v1(n), r1(500);
+      RowVectorXf v2(m), r2(16);
+
+      M.setRandom();
+      v1.setRandom();
+      v2.setRandom();
+      for(int o=0; o<4; ++o)
+      {
+        r1.segment(o,m).noalias() = M * v1;
+        VERIFY_IS_APPROX(r1.segment(o,m), M * MatrixXf(v1));
+        r2.segment(o,n).noalias() = v2 * M;
+        VERIFY_IS_APPROX(r2.segment(o,n), MatrixXf(v2) * M);
+      }
+    }
+  }
+}
+
+void test_product_extra()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( product_extra(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_2( product_extra(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_2( mat_mat_scalar_scalar_product() );
+    CALL_SUBTEST_3( product_extra(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_4( product_extra(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_1( zero_sized_objects(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+  CALL_SUBTEST_5( bug_127() );
+  CALL_SUBTEST_6( unaligned_objects() );
+}
diff --git a/test/product_large.cpp b/test/product_large.cpp
new file mode 100644
index 0000000..03d7bd8
--- /dev/null
+++ b/test/product_large.cpp
@@ -0,0 +1,64 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "product.h"
+
+void test_product_large()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( product(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_2( product(MatrixXd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_3( product(MatrixXi(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+    CALL_SUBTEST_4( product(MatrixXcf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2), internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+    CALL_SUBTEST_5( product(Matrix<float,Dynamic,Dynamic,RowMajor>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE), internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+  }
+
+#if defined EIGEN_TEST_PART_6
+  {
+    // test a specific issue in DiagonalProduct
+    int N = 1000000;
+    VectorXf v = VectorXf::Ones(N);
+    MatrixXf m = MatrixXf::Ones(N,3);
+    m = (v+v).asDiagonal() * m;
+    VERIFY_IS_APPROX(m, MatrixXf::Constant(N,3,2));
+  }
+
+  {
+    // test deferred resizing in Matrix::operator=
+    MatrixXf a = MatrixXf::Random(10,4), b = MatrixXf::Random(4,10), c = a;
+    VERIFY_IS_APPROX((a = a * b), (c * b).eval());
+  }
+
+  {
+    // check the functions to setup blocking sizes compile and do not segfault
+    // FIXME check they do what they are supposed to do !!
+    std::ptrdiff_t l1 = internal::random<int>(10000,20000);
+    std::ptrdiff_t l2 = internal::random<int>(1000000,2000000);
+    setCpuCacheSizes(l1,l2);
+    VERIFY(l1==l1CacheSize());
+    VERIFY(l2==l2CacheSize());
+    std::ptrdiff_t k1 = internal::random<int>(10,100)*16;
+    std::ptrdiff_t m1 = internal::random<int>(10,100)*16;
+    std::ptrdiff_t n1 = internal::random<int>(10,100)*16;
+    // only makes sure it compiles fine
+    internal::computeProductBlockingSizes<float,float>(k1,m1,n1);
+  }
+
+  {
+    // test regression in row-vector by matrix (bad Map type)
+    MatrixXf mat1(10,32); mat1.setRandom();
+    MatrixXf mat2(32,32); mat2.setRandom();
+    MatrixXf r1 = mat1.row(2)*mat2.transpose();
+    VERIFY_IS_APPROX(r1, (mat1.row(2)*mat2.transpose()).eval());
+
+    MatrixXf r2 = mat1.row(2)*mat2;
+    VERIFY_IS_APPROX(r2, (mat1.row(2)*mat2).eval());
+  }
+#endif
+}
diff --git a/test/product_mmtr.cpp b/test/product_mmtr.cpp
new file mode 100644
index 0000000..aeba009
--- /dev/null
+++ b/test/product_mmtr.cpp
@@ -0,0 +1,63 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#define CHECK_MMTR(DEST, TRI, OP) {                   \
+    ref2 = ref1 = DEST;                               \
+    DEST.template triangularView<TRI>() OP;           \
+    ref1 OP;                                          \
+    ref2.template triangularView<TRI>() = ref1;       \
+    VERIFY_IS_APPROX(DEST,ref2);                      \
+  }
+
+template<typename Scalar> void mmtr(int size)
+{
+  typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> MatrixColMaj;
+  typedef Matrix<Scalar,Dynamic,Dynamic,RowMajor> MatrixRowMaj;
+
+  DenseIndex othersize = internal::random<DenseIndex>(1,200);
+  
+  MatrixColMaj matc = MatrixColMaj::Zero(size, size);
+  MatrixRowMaj matr = MatrixRowMaj::Zero(size, size);
+  MatrixColMaj ref1(size, size), ref2(size, size);
+  
+  MatrixColMaj soc(size,othersize); soc.setRandom();
+  MatrixColMaj osc(othersize,size); osc.setRandom();
+  MatrixRowMaj sor(size,othersize); sor.setRandom();
+  MatrixRowMaj osr(othersize,size); osr.setRandom();
+  
+  Scalar s = internal::random<Scalar>();
+  
+  CHECK_MMTR(matc, Lower, = s*soc*sor.adjoint());
+  CHECK_MMTR(matc, Upper, = s*(soc*soc.adjoint()));
+  CHECK_MMTR(matr, Lower, = s*soc*soc.adjoint());
+  CHECK_MMTR(matr, Upper, = soc*(s*sor.adjoint()));
+  
+  CHECK_MMTR(matc, Lower, += s*soc*soc.adjoint());
+  CHECK_MMTR(matc, Upper, += s*(soc*sor.transpose()));
+  CHECK_MMTR(matr, Lower, += s*sor*soc.adjoint());
+  CHECK_MMTR(matr, Upper, += soc*(s*soc.adjoint()));
+  
+  CHECK_MMTR(matc, Lower, -= s*soc*soc.adjoint());
+  CHECK_MMTR(matc, Upper, -= s*(osc.transpose()*osc.conjugate()));
+  CHECK_MMTR(matr, Lower, -= s*soc*soc.adjoint());
+  CHECK_MMTR(matr, Upper, -= soc*(s*soc.adjoint()));
+}
+
+void test_product_mmtr()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    CALL_SUBTEST_1((mmtr<float>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_2((mmtr<double>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_3((mmtr<std::complex<float> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
+    CALL_SUBTEST_4((mmtr<std::complex<double> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
+  }
+}
diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp
new file mode 100644
index 0000000..258d238
--- /dev/null
+++ b/test/product_notemporary.cpp
@@ -0,0 +1,141 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+static int nb_temporaries;
+
+inline void on_temporary_creation(int size) {
+  // here's a great place to set a breakpoint when debugging failures in this test!
+  if(size!=0) nb_temporaries++;
+}
+  
+
+#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+
+#include "main.h"
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+    nb_temporaries = 0; \
+    XPR; \
+    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+    VERIFY( (#XPR) && nb_temporaries==N ); \
+  }
+
+template<typename MatrixType> void product_notemporary(const MatrixType& m)
+{
+  /* This test checks the number of temporaries created
+   * during the evaluation of a complex expression */
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
+  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
+  typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ColMajorMatrixType;
+  typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  ColMajorMatrixType m1 = MatrixType::Random(rows, cols),
+                     m2 = MatrixType::Random(rows, cols),
+                     m3(rows, cols);
+  RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
+  ColVectorType cv1 = ColVectorType::Random(cols), cvres(cols);
+  RowMajorMatrixType rm3(rows, cols);
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>(),
+         s3 = internal::random<Scalar>();
+
+  Index c0 = internal::random<Index>(4,cols-8),
+        c1 = internal::random<Index>(8,cols-c0),
+        r0 = internal::random<Index>(4,cols-8),
+        r1 = internal::random<Index>(8,rows-r0);
+
+  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);
+
+  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);
+
+  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
+  VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
+  VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);
+
+  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
+  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);
+
+  // NOTE this is because the Block expression is not handled yet by our expression analyser
+  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1);
+
+  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<Lower>() * m2, 0);
+  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1);
+  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0);
+  
+  VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() = (m1 * m2.adjoint()), 0);
+  VERIFY_EVALUATION_COUNT( m3.template triangularView<Upper>() -= (m1 * m2.adjoint()), 0);
+
+  // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products
+  VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 1);
+
+  VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0);
+  VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0);
+
+  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2*s3).adjoint(), 0);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0);
+  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0);
+
+  // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products
+  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 1);
+  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 1);
+
+  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0);
+  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0);
+
+  VERIFY_EVALUATION_COUNT( m3.template selfadjointView<Lower>().rankUpdate(m2.adjoint()), 0);
+
+  // Here we will get 1 temporary for each resize operation of the lhs operator; resize(r1,c1) would lead to zero temporaries
+  m3.resize(1,1);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Lower>() * m2.block(r0,c0,r1,c1), 1);
+  m3.resize(1,1);
+  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpper>()  * m2.block(r0,c0,r1,c1), 1);
+
+  // Zero temporaries for lazy products ...
+  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose().lazyProduct(m3)).diagonal().sum(), 0 );
+
+  // ... and even no temporary for even deeply (>=2) nested products
+  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().sum(), 0 );
+  VERIFY_EVALUATION_COUNT( Scalar tmp = 0; tmp += Scalar(RealScalar(1)) /  (m3.transpose() * m3).diagonal().array().abs().sum(), 0 );
+
+  // Zero temporaries for ... CoeffBasedProductMode
+  // - does not work with GCC because of the <..>, we'ld need variadic macros ...
+  //VERIFY_EVALUATION_COUNT( m3.col(0).head<5>() * m3.col(0).transpose() + m3.col(0).head<5>() * m3.col(0).transpose(), 0 );
+
+  // Check matrix * vectors
+  VERIFY_EVALUATION_COUNT( cvres.noalias() = m1 * cv1, 0 );
+  VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * cv1, 0 );
+  VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.col(0), 0 );
+  VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * rv1.adjoint(), 0 );
+  VERIFY_EVALUATION_COUNT( cvres.noalias() -= m1 * m2.row(0).transpose(), 0 );
+}
+
+void test_product_notemporary()
+{
+  int s;
+  for(int i = 0; i < g_repeat; i++) {
+    s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_1( product_notemporary(MatrixXf(s, s)) );
+    s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_2( product_notemporary(MatrixXd(s, s)) );
+    s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_3( product_notemporary(MatrixXcf(s,s)) );
+    s = internal::random<int>(16,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_4( product_notemporary(MatrixXcd(s,s)) );
+  }
+}
diff --git a/test/product_selfadjoint.cpp b/test/product_selfadjoint.cpp
new file mode 100644
index 0000000..374e239
--- /dev/null
+++ b/test/product_selfadjoint.cpp
@@ -0,0 +1,80 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void product_selfadjoint(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+  typedef Matrix<Scalar, 1, MatrixType::RowsAtCompileTime> RowVectorType;
+
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, Dynamic, RowMajor> RhsMatrixType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3;
+  VectorType v1 = VectorType::Random(rows),
+             v2 = VectorType::Random(rows),
+             v3(rows);
+  RowVectorType r1 = RowVectorType::Random(rows),
+                r2 = RowVectorType::Random(rows);
+  RhsMatrixType m4 = RhsMatrixType::Random(rows,10);
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>(),
+         s3 = internal::random<Scalar>();
+
+  m1 = (m1.adjoint() + m1).eval();
+
+  // rank2 update
+  m2 = m1.template triangularView<Lower>();
+  m2.template selfadjointView<Lower>().rankUpdate(v1,v2);
+  VERIFY_IS_APPROX(m2, (m1 + v1 * v2.adjoint()+ v2 * v1.adjoint()).template triangularView<Lower>().toDenseMatrix());
+
+  m2 = m1.template triangularView<Upper>();
+  m2.template selfadjointView<Upper>().rankUpdate(-v1,s2*v2,s3);
+  VERIFY_IS_APPROX(m2, (m1 + (s3*(-v1)*(s2*v2).adjoint()+numext::conj(s3)*(s2*v2)*(-v1).adjoint())).template triangularView<Upper>().toDenseMatrix());
+
+  m2 = m1.template triangularView<Upper>();
+  m2.template selfadjointView<Upper>().rankUpdate(-s2*r1.adjoint(),r2.adjoint()*s3,s1);
+  VERIFY_IS_APPROX(m2, (m1 + s1*(-s2*r1.adjoint())*(r2.adjoint()*s3).adjoint() + numext::conj(s1)*(r2.adjoint()*s3) * (-s2*r1.adjoint()).adjoint()).template triangularView<Upper>().toDenseMatrix());
+
+  if (rows>1)
+  {
+    m2 = m1.template triangularView<Lower>();
+    m2.block(1,1,rows-1,cols-1).template selfadjointView<Lower>().rankUpdate(v1.tail(rows-1),v2.head(cols-1));
+    m3 = m1;
+    m3.block(1,1,rows-1,cols-1) += v1.tail(rows-1) * v2.head(cols-1).adjoint()+ v2.head(cols-1) * v1.tail(rows-1).adjoint();
+    VERIFY_IS_APPROX(m2, m3.template triangularView<Lower>().toDenseMatrix());
+  }
+}
+
+void test_product_selfadjoint()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat ; i++) {
+    CALL_SUBTEST_1( product_selfadjoint(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( product_selfadjoint(Matrix<float, 2, 2>()) );
+    CALL_SUBTEST_3( product_selfadjoint(Matrix3d()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_4( product_selfadjoint(MatrixXcf(s, s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_5( product_selfadjoint(MatrixXcd(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_6( product_selfadjoint(MatrixXd(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_7( product_selfadjoint(Matrix<float,Dynamic,Dynamic,RowMajor>(s,s)) );
+  }
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/product_small.cpp b/test/product_small.cpp
new file mode 100644
index 0000000..8b132ab
--- /dev/null
+++ b/test/product_small.cpp
@@ -0,0 +1,50 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "product.h"
+
+// regression test for bug 447
+void product1x1()
+{
+  Matrix<float,1,3> matAstatic;
+  Matrix<float,3,1> matBstatic;
+  matAstatic.setRandom();
+  matBstatic.setRandom();
+  VERIFY_IS_APPROX( (matAstatic * matBstatic).coeff(0,0), 
+                    matAstatic.cwiseProduct(matBstatic.transpose()).sum() );
+
+  MatrixXf matAdynamic(1,3);
+  MatrixXf matBdynamic(3,1);
+  matAdynamic.setRandom();
+  matBdynamic.setRandom();
+  VERIFY_IS_APPROX( (matAdynamic * matBdynamic).coeff(0,0), 
+                    matAdynamic.cwiseProduct(matBdynamic.transpose()).sum() );
+}
+
+
+void test_product_small()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( product(Matrix<float, 3, 2>()) );
+    CALL_SUBTEST_2( product(Matrix<int, 3, 5>()) );
+    CALL_SUBTEST_3( product(Matrix3d()) );
+    CALL_SUBTEST_4( product(Matrix4d()) );
+    CALL_SUBTEST_5( product(Matrix4f()) );
+    CALL_SUBTEST_6( product1x1() );
+  }
+
+#ifdef EIGEN_TEST_PART_6
+  {
+    // test compilation of (outer_product) * vector
+    Vector3f v = Vector3f::Random();
+    VERIFY_IS_APPROX( (v * v.transpose()) * v, (v * v.transpose()).eval() * v);
+  }
+#endif
+}
diff --git a/test/product_symm.cpp b/test/product_symm.cpp
new file mode 100644
index 0000000..74d7329
--- /dev/null
+++ b/test/product_symm.cpp
@@ -0,0 +1,94 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar, int Size, int OtherSize> void symm(int size = Size, int othersize = OtherSize)
+{
+  typedef Matrix<Scalar, Size, Size> MatrixType;
+  typedef Matrix<Scalar, Size, OtherSize> Rhs1;
+  typedef Matrix<Scalar, OtherSize, Size> Rhs2;
+  enum { order = OtherSize==1 ? 0 : RowMajor };
+  typedef Matrix<Scalar, Size, OtherSize,order> Rhs3;
+  typedef typename MatrixType::Index Index;
+
+  Index rows = size;
+  Index cols = size;
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols), m3;
+
+  m1 = (m1+m1.adjoint()).eval();
+
+  Rhs1 rhs1 = Rhs1::Random(cols, othersize), rhs12(cols, othersize), rhs13(cols, othersize);
+  Rhs2 rhs2 = Rhs2::Random(othersize, rows), rhs22(othersize, rows), rhs23(othersize, rows);
+  Rhs3 rhs3 = Rhs3::Random(cols, othersize), rhs32(cols, othersize), rhs33(cols, othersize);
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>();
+
+  m2 = m1.template triangularView<Lower>();
+  m3 = m2.template selfadjointView<Lower>();
+  VERIFY_IS_EQUAL(m1, m3);
+  VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>() * (s2*rhs1),
+                   rhs13 = (s1*m1) * (s2*rhs1));
+
+  m2 = m1.template triangularView<Upper>(); rhs12.setRandom(); rhs13 = rhs12;
+  m3 = m2.template selfadjointView<Upper>();
+  VERIFY_IS_EQUAL(m1, m3);
+  VERIFY_IS_APPROX(rhs12 += (s1*m2).template selfadjointView<Upper>() * (s2*rhs1),
+                   rhs13 += (s1*m1) * (s2*rhs1));
+
+  m2 = m1.template triangularView<Lower>();
+  VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Lower>() * (s2*rhs2.adjoint()),
+                   rhs13 = (s1*m1) * (s2*rhs2.adjoint()));
+
+  m2 = m1.template triangularView<Upper>();
+  VERIFY_IS_APPROX(rhs12 = (s1*m2).template selfadjointView<Upper>() * (s2*rhs2.adjoint()),
+                   rhs13 = (s1*m1) * (s2*rhs2.adjoint()));
+
+  m2 = m1.template triangularView<Upper>();
+  VERIFY_IS_APPROX(rhs12 = (s1*m2.adjoint()).template selfadjointView<Lower>() * (s2*rhs2.adjoint()),
+                   rhs13 = (s1*m1.adjoint()) * (s2*rhs2.adjoint()));
+
+  // test row major = <...>
+  m2 = m1.template triangularView<Lower>(); rhs12.setRandom(); rhs13 = rhs12;
+  VERIFY_IS_APPROX(rhs12 -= (s1*m2).template selfadjointView<Lower>() * (s2*rhs3),
+                   rhs13 -= (s1*m1) * (s2 * rhs3));
+
+  m2 = m1.template triangularView<Upper>();
+  VERIFY_IS_APPROX(rhs12 = (s1*m2.adjoint()).template selfadjointView<Lower>() * (s2*rhs3).conjugate(),
+                   rhs13 = (s1*m1.adjoint()) * (s2*rhs3).conjugate());
+
+
+  m2 = m1.template triangularView<Upper>(); rhs13 = rhs12;
+  VERIFY_IS_APPROX(rhs12.noalias() += s1 * ((m2.adjoint()).template selfadjointView<Lower>() * (s2*rhs3).conjugate()),
+                   rhs13 += (s1*m1.adjoint()) * (s2*rhs3).conjugate());
+
+  m2 = m1.template triangularView<Lower>();
+  VERIFY_IS_APPROX(rhs22 = (rhs2) * (m2).template selfadjointView<Lower>(), rhs23 = (rhs2) * (m1));
+  VERIFY_IS_APPROX(rhs22 = (s2*rhs2) * (s1*m2).template selfadjointView<Lower>(), rhs23 = (s2*rhs2) * (s1*m1));
+
+}
+
+void test_product_symm()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    CALL_SUBTEST_1(( symm<float,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+    CALL_SUBTEST_2(( symm<double,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+    CALL_SUBTEST_3(( symm<std::complex<float>,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2)) ));
+    CALL_SUBTEST_4(( symm<std::complex<double>,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2)) ));
+
+    CALL_SUBTEST_5(( symm<float,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+    CALL_SUBTEST_6(( symm<double,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+    CALL_SUBTEST_7(( symm<std::complex<float>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+    CALL_SUBTEST_8(( symm<std::complex<double>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)) ));
+  }
+}
diff --git a/test/product_syrk.cpp b/test/product_syrk.cpp
new file mode 100644
index 0000000..73c9500
--- /dev/null
+++ b/test/product_syrk.cpp
@@ -0,0 +1,135 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void syrk(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime, RowMajor> RMatrixType;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic> Rhs1;
+  typedef Matrix<Scalar, Dynamic, MatrixType::RowsAtCompileTime> Rhs2;
+  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, Dynamic,RowMajor> Rhs3;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3 = MatrixType::Random(rows, cols);
+  RMatrixType rm2 = MatrixType::Random(rows, cols);
+
+  Rhs1 rhs1 = Rhs1::Random(internal::random<int>(1,320), cols); Rhs1 rhs11 = Rhs1::Random(rhs1.rows(), cols);
+  Rhs2 rhs2 = Rhs2::Random(rows, internal::random<int>(1,320)); Rhs2 rhs22 = Rhs2::Random(rows, rhs2.cols());
+  Rhs3 rhs3 = Rhs3::Random(internal::random<int>(1,320), rows);
+
+  Scalar s1 = internal::random<Scalar>();
+  
+  Index c = internal::random<Index>(0,cols-1);
+
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(rhs2,s1)._expression()),
+                   ((s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+  m2.setZero();
+  VERIFY_IS_APPROX(((m2.template triangularView<Lower>() += s1 * rhs2  * rhs22.adjoint()).nestedExpression()),
+                   ((s1 * rhs2 * rhs22.adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+
+  
+  m2.setZero();
+  VERIFY_IS_APPROX(m2.template selfadjointView<Upper>().rankUpdate(rhs2,s1)._expression(),
+                   (s1 * rhs2 * rhs2.adjoint()).eval().template triangularView<Upper>().toDenseMatrix());
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template triangularView<Upper>() += s1 * rhs22 * rhs2.adjoint()).nestedExpression(),
+                   (s1 * rhs22 * rhs2.adjoint()).eval().template triangularView<Upper>().toDenseMatrix());
+
+  
+  m2.setZero();
+  VERIFY_IS_APPROX(m2.template selfadjointView<Lower>().rankUpdate(rhs1.adjoint(),s1)._expression(),
+                   (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<Lower>().toDenseMatrix());
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template triangularView<Lower>() += s1 * rhs11.adjoint() * rhs1).nestedExpression(),
+                   (s1 * rhs11.adjoint() * rhs1).eval().template triangularView<Lower>().toDenseMatrix());
+  
+  
+  m2.setZero();
+  VERIFY_IS_APPROX(m2.template selfadjointView<Upper>().rankUpdate(rhs1.adjoint(),s1)._expression(),
+                   (s1 * rhs1.adjoint() * rhs1).eval().template triangularView<Upper>().toDenseMatrix());
+  VERIFY_IS_APPROX((m2.template triangularView<Upper>() = s1 * rhs1.adjoint() * rhs11).nestedExpression(),
+                   (s1 * rhs1.adjoint() * rhs11).eval().template triangularView<Upper>().toDenseMatrix());
+
+  
+  m2.setZero();
+  VERIFY_IS_APPROX(m2.template selfadjointView<Lower>().rankUpdate(rhs3.adjoint(),s1)._expression(),
+                   (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<Lower>().toDenseMatrix());
+
+  m2.setZero();
+  VERIFY_IS_APPROX(m2.template selfadjointView<Upper>().rankUpdate(rhs3.adjoint(),s1)._expression(),
+                   (s1 * rhs3.adjoint() * rhs3).eval().template triangularView<Upper>().toDenseMatrix());
+                   
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(m1.col(c),s1)._expression()),
+                   ((s1 * m1.col(c) * m1.col(c).adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+                   
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.col(c),s1)._expression()),
+                   ((s1 * m1.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+  rm2.setZero();
+  VERIFY_IS_APPROX((rm2.template selfadjointView<Upper>().rankUpdate(m1.col(c),s1)._expression()),
+                   ((s1 * m1.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template triangularView<Upper>() += s1 * m3.col(c) * m1.col(c).adjoint()).nestedExpression(),
+                   ((s1 * m3.col(c) * m1.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+  rm2.setZero();
+  VERIFY_IS_APPROX((rm2.template triangularView<Upper>() += s1 * m1.col(c) * m3.col(c).adjoint()).nestedExpression(),
+                   ((s1 * m1.col(c) * m3.col(c).adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+  
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(m1.col(c).conjugate(),s1)._expression()),
+                   ((s1 * m1.col(c).conjugate() * m1.col(c).conjugate().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+                   
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.col(c).conjugate(),s1)._expression()),
+                   ((s1 * m1.col(c).conjugate() * m1.col(c).conjugate().adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+  
+  
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Lower>().rankUpdate(m1.row(c),s1)._expression()),
+                   ((s1 * m1.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+  rm2.setZero();
+  VERIFY_IS_APPROX((rm2.template selfadjointView<Lower>().rankUpdate(m1.row(c),s1)._expression()),
+                   ((s1 * m1.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template triangularView<Lower>() += s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).nestedExpression(),
+                   ((s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+  rm2.setZero();
+  VERIFY_IS_APPROX((rm2.template triangularView<Lower>() += s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).nestedExpression(),
+                   ((s1 * m3.row(c).transpose() * m1.row(c).transpose().adjoint()).eval().template triangularView<Lower>().toDenseMatrix()));
+  
+  
+  m2.setZero();
+  VERIFY_IS_APPROX((m2.template selfadjointView<Upper>().rankUpdate(m1.row(c).adjoint(),s1)._expression()),
+                   ((s1 * m1.row(c).adjoint() * m1.row(c).adjoint().adjoint()).eval().template triangularView<Upper>().toDenseMatrix()));
+}
+
+void test_product_syrk()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    int s;
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_1( syrk(MatrixXf(s, s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_2( syrk(MatrixXd(s, s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_3( syrk(MatrixXcf(s, s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_4( syrk(MatrixXcd(s, s)) );
+  }
+}
diff --git a/test/product_trmm.cpp b/test/product_trmm.cpp
new file mode 100644
index 0000000..d715b9a
--- /dev/null
+++ b/test/product_trmm.cpp
@@ -0,0 +1,107 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar, int Mode, int TriOrder, int OtherOrder, int ResOrder, int OtherCols>
+void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
+          int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE),
+          int otherCols = OtherCols==Dynamic?internal::random<int>(1,EIGEN_TEST_MAX_SIZE):OtherCols)
+{
+  typedef Matrix<Scalar,Dynamic,Dynamic,TriOrder> TriMatrix;
+  typedef Matrix<Scalar,Dynamic,OtherCols,OtherCols==1?ColMajor:OtherOrder> OnTheRight;
+  typedef Matrix<Scalar,OtherCols,Dynamic,OtherCols==1?RowMajor:OtherOrder> OnTheLeft;
+  
+  typedef Matrix<Scalar,Dynamic,OtherCols,OtherCols==1?ColMajor:ResOrder> ResXS;
+  typedef Matrix<Scalar,OtherCols,Dynamic,OtherCols==1?RowMajor:ResOrder> ResSX;
+
+  TriMatrix  mat(rows,cols), tri(rows,cols), triTr(cols,rows);
+  
+  OnTheRight  ge_right(cols,otherCols);
+  OnTheLeft   ge_left(otherCols,rows);
+  ResSX       ge_sx, ge_sx_save;
+  ResXS       ge_xs, ge_xs_save;
+
+  Scalar s1 = internal::random<Scalar>(),
+         s2 = internal::random<Scalar>();
+
+  mat.setRandom();
+  tri = mat.template triangularView<Mode>();
+  triTr = mat.transpose().template triangularView<Mode>();
+  ge_right.setRandom();
+  ge_left.setRandom();
+
+  VERIFY_IS_APPROX( ge_xs = mat.template triangularView<Mode>() * ge_right, tri * ge_right);
+  VERIFY_IS_APPROX( ge_sx = ge_left * mat.template triangularView<Mode>(), ge_left * tri);
+  
+  VERIFY_IS_APPROX( ge_xs.noalias() = mat.template triangularView<Mode>() * ge_right, tri * ge_right);
+  VERIFY_IS_APPROX( ge_sx.noalias() = ge_left * mat.template triangularView<Mode>(), ge_left * tri);
+  
+  VERIFY_IS_APPROX( ge_xs.noalias() = (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.transpose()), s1*triTr.conjugate() * (s2*ge_left.transpose()));
+  VERIFY_IS_APPROX( ge_sx.noalias() = ge_right.transpose() * mat.adjoint().template triangularView<Mode>(), ge_right.transpose() * triTr.conjugate());
+  
+  VERIFY_IS_APPROX( ge_xs.noalias() = (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.adjoint()), s1*triTr.conjugate() * (s2*ge_left.adjoint()));
+  VERIFY_IS_APPROX( ge_sx.noalias() = ge_right.adjoint() * mat.adjoint().template triangularView<Mode>(), ge_right.adjoint() * triTr.conjugate());
+  
+  ge_xs_save = ge_xs;
+  VERIFY_IS_APPROX( (ge_xs_save + s1*triTr.conjugate() * (s2*ge_left.adjoint())).eval(), ge_xs.noalias() += (s1*mat.adjoint()).template triangularView<Mode>() * (s2*ge_left.adjoint()) );
+  ge_sx.setRandom();
+  ge_sx_save = ge_sx;
+  VERIFY_IS_APPROX( ge_sx_save - (ge_right.adjoint() * (-s1 * triTr).conjugate()).eval(), ge_sx.noalias() -= (ge_right.adjoint() * (-s1 * mat).adjoint().template triangularView<Mode>()).eval());
+  
+  VERIFY_IS_APPROX( ge_xs = (s1*mat).adjoint().template triangularView<Mode>() * ge_left.adjoint(), numext::conj(s1) * triTr.conjugate() * ge_left.adjoint());
+  
+  // TODO check with sub-matrix expressions ?
+}
+
+template<typename Scalar, int Mode, int TriOrder>
+void trmv(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE))
+{
+  trmm<Scalar,Mode,TriOrder,ColMajor,ColMajor,1>(rows,cols,1);
+}
+
+template<typename Scalar, int Mode, int TriOrder, int OtherOrder, int ResOrder>
+void trmm(int rows=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int cols=internal::random<int>(1,EIGEN_TEST_MAX_SIZE), int otherCols = internal::random<int>(1,EIGEN_TEST_MAX_SIZE))
+{
+  trmm<Scalar,Mode,TriOrder,OtherOrder,ResOrder,Dynamic>(rows,cols,otherCols);
+}
+
+#define CALL_ALL_ORDERS(NB,SCALAR,MODE)                                             \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, ColMajor,ColMajor,ColMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, ColMajor,ColMajor,RowMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, ColMajor,RowMajor,ColMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, ColMajor,RowMajor,RowMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, RowMajor,ColMajor,ColMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, RowMajor,ColMajor,RowMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, RowMajor,RowMajor,ColMajor>()));  \
+  EIGEN_CAT(CALL_SUBTEST_,NB)((trmm<SCALAR, MODE, RowMajor,RowMajor,RowMajor>()));  \
+  \
+  EIGEN_CAT(CALL_SUBTEST_1,NB)((trmv<SCALAR, MODE, ColMajor>()));                   \
+  EIGEN_CAT(CALL_SUBTEST_1,NB)((trmv<SCALAR, MODE, RowMajor>()));
+
+  
+#define CALL_ALL(NB,SCALAR)                 \
+  CALL_ALL_ORDERS(EIGEN_CAT(1,NB),SCALAR,Upper)          \
+  CALL_ALL_ORDERS(EIGEN_CAT(2,NB),SCALAR,UnitUpper)      \
+  CALL_ALL_ORDERS(EIGEN_CAT(3,NB),SCALAR,StrictlyUpper)  \
+  CALL_ALL_ORDERS(EIGEN_CAT(1,NB),SCALAR,Lower)          \
+  CALL_ALL_ORDERS(EIGEN_CAT(2,NB),SCALAR,UnitLower)      \
+  CALL_ALL_ORDERS(EIGEN_CAT(3,NB),SCALAR,StrictlyLower)
+  
+
+void test_product_trmm()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    CALL_ALL(1,float);                //  EIGEN_SUFFIXES;11;111;21;121;31;131
+    CALL_ALL(2,double);               //  EIGEN_SUFFIXES;12;112;22;122;32;132
+    CALL_ALL(3,std::complex<float>);  //  EIGEN_SUFFIXES;13;113;23;123;33;133
+    CALL_ALL(4,std::complex<double>); //  EIGEN_SUFFIXES;14;114;24;124;34;134
+  }
+}
diff --git a/test/product_trmv.cpp b/test/product_trmv.cpp
new file mode 100644
index 0000000..4c3c435
--- /dev/null
+++ b/test/product_trmv.cpp
@@ -0,0 +1,89 @@
+// This file is triangularView of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void trmv(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+  VectorType v1 = VectorType::Random(rows);
+
+  Scalar s1 = internal::random<Scalar>();
+
+  m1 = MatrixType::Random(rows, cols);
+
+  // check with a column-major matrix
+  m3 = m1.template triangularView<Eigen::Lower>();
+  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Lower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::Upper>();
+  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::Upper>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::UnitLower>();
+  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitLower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::UnitUpper>();
+  VERIFY((m3 * v1).isApprox(m1.template triangularView<Eigen::UnitUpper>() * v1, largerEps));
+
+  // check conjugated and scalar multiple expressions (col-major)
+  m3 = m1.template triangularView<Eigen::Lower>();
+  VERIFY(((s1*m3).conjugate() * v1).isApprox((s1*m1).conjugate().template triangularView<Eigen::Lower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::Upper>();
+  VERIFY((m3.conjugate() * v1.conjugate()).isApprox(m1.conjugate().template triangularView<Eigen::Upper>() * v1.conjugate(), largerEps));
+
+  // check with a row-major matrix
+  m3 = m1.template triangularView<Eigen::Upper>();
+  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Lower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::Lower>();
+  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::Upper>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::UnitUpper>();
+  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitLower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::UnitLower>();
+  VERIFY((m3.transpose() * v1).isApprox(m1.transpose().template triangularView<Eigen::UnitUpper>() * v1, largerEps));
+
+  // check conjugated and scalar multiple expressions (row-major)
+  m3 = m1.template triangularView<Eigen::Upper>();
+  VERIFY((m3.adjoint() * v1).isApprox(m1.adjoint().template triangularView<Eigen::Lower>() * v1, largerEps));
+  m3 = m1.template triangularView<Eigen::Lower>();
+  VERIFY((m3.adjoint() * (s1*v1.conjugate())).isApprox(m1.adjoint().template triangularView<Eigen::Upper>() * (s1*v1.conjugate()), largerEps));
+  m3 = m1.template triangularView<Eigen::UnitUpper>();
+
+  // check transposed cases:
+  m3 = m1.template triangularView<Eigen::Lower>();
+  VERIFY((v1.transpose() * m3).isApprox(v1.transpose() * m1.template triangularView<Eigen::Lower>(), largerEps));
+  VERIFY((v1.adjoint() * m3).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>(), largerEps));
+  VERIFY((v1.adjoint() * m3.adjoint()).isApprox(v1.adjoint() * m1.template triangularView<Eigen::Lower>().adjoint(), largerEps));
+
+  // TODO check with sub-matrices
+}
+
+void test_product_trmv()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat ; i++) {
+    CALL_SUBTEST_1( trmv(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( trmv(Matrix<float, 2, 2>()) );
+    CALL_SUBTEST_3( trmv(Matrix3d()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_4( trmv(MatrixXcf(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2);
+    CALL_SUBTEST_5( trmv(MatrixXcd(s,s)) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+    CALL_SUBTEST_6( trmv(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
+  }
+  TEST_SET_BUT_UNUSED_VARIABLE(s);
+}
diff --git a/test/product_trsolve.cpp b/test/product_trsolve.cpp
new file mode 100644
index 0000000..69892b3
--- /dev/null
+++ b/test/product_trsolve.cpp
@@ -0,0 +1,93 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#define VERIFY_TRSM(TRI,XB) { \
+    (XB).setRandom(); ref = (XB); \
+    (TRI).solveInPlace(XB); \
+    VERIFY_IS_APPROX((TRI).toDenseMatrix() * (XB), ref); \
+    (XB).setRandom(); ref = (XB); \
+    (XB) = (TRI).solve(XB); \
+    VERIFY_IS_APPROX((TRI).toDenseMatrix() * (XB), ref); \
+  }
+
+#define VERIFY_TRSM_ONTHERIGHT(TRI,XB) { \
+    (XB).setRandom(); ref = (XB); \
+    (TRI).transpose().template solveInPlace<OnTheRight>(XB.transpose()); \
+    VERIFY_IS_APPROX((XB).transpose() * (TRI).transpose().toDenseMatrix(), ref.transpose()); \
+    (XB).setRandom(); ref = (XB); \
+    (XB).transpose() = (TRI).transpose().template solve<OnTheRight>(XB.transpose()); \
+    VERIFY_IS_APPROX((XB).transpose() * (TRI).transpose().toDenseMatrix(), ref.transpose()); \
+  }
+
+template<typename Scalar,int Size, int Cols> void trsolve(int size=Size,int cols=Cols)
+{
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  Matrix<Scalar,Size,Size,ColMajor> cmLhs(size,size);
+  Matrix<Scalar,Size,Size,RowMajor> rmLhs(size,size);
+
+  enum {  colmajor = Size==1 ? RowMajor : ColMajor,
+          rowmajor = Cols==1 ? ColMajor : RowMajor };
+  Matrix<Scalar,Size,Cols,colmajor> cmRhs(size,cols);
+  Matrix<Scalar,Size,Cols,rowmajor> rmRhs(size,cols);
+  Matrix<Scalar,Dynamic,Dynamic,colmajor> ref(size,cols);
+
+  cmLhs.setRandom(); cmLhs *= static_cast<RealScalar>(0.1); cmLhs.diagonal().array() += static_cast<RealScalar>(1);
+  rmLhs.setRandom(); rmLhs *= static_cast<RealScalar>(0.1); rmLhs.diagonal().array() += static_cast<RealScalar>(1);
+
+  VERIFY_TRSM(cmLhs.conjugate().template triangularView<Lower>(), cmRhs);
+  VERIFY_TRSM(cmLhs.adjoint()  .template triangularView<Lower>(), cmRhs);
+  VERIFY_TRSM(cmLhs            .template triangularView<Upper>(), cmRhs);
+  VERIFY_TRSM(cmLhs            .template triangularView<Lower>(), rmRhs);
+  VERIFY_TRSM(cmLhs.conjugate().template triangularView<Upper>(), rmRhs);
+  VERIFY_TRSM(cmLhs.adjoint()  .template triangularView<Upper>(), rmRhs);
+
+  VERIFY_TRSM(cmLhs.conjugate().template triangularView<UnitLower>(), cmRhs);
+  VERIFY_TRSM(cmLhs            .template triangularView<UnitUpper>(), rmRhs);
+
+  VERIFY_TRSM(rmLhs            .template triangularView<Lower>(), cmRhs);
+  VERIFY_TRSM(rmLhs.conjugate().template triangularView<UnitUpper>(), rmRhs);
+
+
+  VERIFY_TRSM_ONTHERIGHT(cmLhs.conjugate().template triangularView<Lower>(), cmRhs);
+  VERIFY_TRSM_ONTHERIGHT(cmLhs            .template triangularView<Upper>(), cmRhs);
+  VERIFY_TRSM_ONTHERIGHT(cmLhs            .template triangularView<Lower>(), rmRhs);
+  VERIFY_TRSM_ONTHERIGHT(cmLhs.conjugate().template triangularView<Upper>(), rmRhs);
+
+  VERIFY_TRSM_ONTHERIGHT(cmLhs.conjugate().template triangularView<UnitLower>(), cmRhs);
+  VERIFY_TRSM_ONTHERIGHT(cmLhs            .template triangularView<UnitUpper>(), rmRhs);
+
+  VERIFY_TRSM_ONTHERIGHT(rmLhs            .template triangularView<Lower>(), cmRhs);
+  VERIFY_TRSM_ONTHERIGHT(rmLhs.conjugate().template triangularView<UnitUpper>(), rmRhs);
+
+  int c = internal::random<int>(0,cols-1);
+  VERIFY_TRSM(rmLhs.template triangularView<Lower>(), rmRhs.col(c));
+  VERIFY_TRSM(cmLhs.template triangularView<Lower>(), rmRhs.col(c));
+}
+
+void test_product_trsolve()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    // matrices
+    CALL_SUBTEST_1((trsolve<float,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_2((trsolve<double,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_3((trsolve<std::complex<float>,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
+    CALL_SUBTEST_4((trsolve<std::complex<double>,Dynamic,Dynamic>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))));
+
+    // vectors
+    CALL_SUBTEST_1((trsolve<float,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_5((trsolve<std::complex<double>,Dynamic,1>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE))));
+    CALL_SUBTEST_6((trsolve<float,1,1>()));
+    CALL_SUBTEST_7((trsolve<float,1,2>()));
+    CALL_SUBTEST_8((trsolve<std::complex<float>,4,1>()));
+  }
+}
diff --git a/test/qr.cpp b/test/qr.cpp
new file mode 100644
index 0000000..a79e0dd
--- /dev/null
+++ b/test/qr.cpp
@@ -0,0 +1,127 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename MatrixType> void qr(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  HouseholderQR<MatrixType> qrOfA(a);
+
+  MatrixQType q = qrOfA.householderQ();
+  VERIFY_IS_UNITARY(q);
+
+  MatrixType r = qrOfA.matrixQR().template triangularView<Upper>();
+  VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
+}
+
+template<typename MatrixType, int Cols2> void qr_fixedsize()
+{
+  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
+  typedef typename MatrixType::Scalar Scalar;
+  Matrix<Scalar,Rows,Cols> m1 = Matrix<Scalar,Rows,Cols>::Random();
+  HouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);
+
+  Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
+  // FIXME need better way to construct trapezoid
+  for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);
+
+  VERIFY_IS_APPROX(m1, qr.householderQ() * r);
+
+  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
+  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
+  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+}
+
+template<typename MatrixType> void qr_invertible()
+{
+  using std::log;
+  using std::abs;
+  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+  typedef typename MatrixType::Scalar Scalar;
+
+  int size = internal::random<int>(10,50);
+
+  MatrixType m1(size, size), m2(size, size), m3(size, size);
+  m1 = MatrixType::Random(size,size);
+
+  if (internal::is_same<RealScalar,float>::value)
+  {
+    // let's build a matrix more stable to inverse
+    MatrixType a = MatrixType::Random(size,size*2);
+    m1 += a * a.adjoint();
+  }
+
+  HouseholderQR<MatrixType> qr(m1);
+  m3 = MatrixType::Random(size,size);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+
+  // now construct a matrix with prescribed determinant
+  m1.setZero();
+  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
+  RealScalar absdet = abs(m1.diagonal().prod());
+  m3 = qr.householderQ(); // get a unitary
+  m1 = m3 * m1 * m3;
+  qr.compute(m1);
+  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
+  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
+}
+
+template<typename MatrixType> void qr_verify_assert()
+{
+  MatrixType tmp;
+
+  HouseholderQR<MatrixType> qr;
+  VERIFY_RAISES_ASSERT(qr.matrixQR())
+  VERIFY_RAISES_ASSERT(qr.solve(tmp))
+  VERIFY_RAISES_ASSERT(qr.householderQ())
+  VERIFY_RAISES_ASSERT(qr.absDeterminant())
+  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
+}
+
+void test_qr()
+{
+  for(int i = 0; i < g_repeat; i++) {
+   CALL_SUBTEST_1( qr(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
+   CALL_SUBTEST_2( qr(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
+   CALL_SUBTEST_3(( qr_fixedsize<Matrix<float,3,4>, 2 >() ));
+   CALL_SUBTEST_4(( qr_fixedsize<Matrix<double,6,2>, 4 >() ));
+   CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,2,5>, 7 >() ));
+   CALL_SUBTEST_11( qr(Matrix<float,1,1>()) );
+  }
+
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
+    CALL_SUBTEST_6( qr_invertible<MatrixXd>() );
+    CALL_SUBTEST_7( qr_invertible<MatrixXcf>() );
+    CALL_SUBTEST_8( qr_invertible<MatrixXcd>() );
+  }
+
+  CALL_SUBTEST_9(qr_verify_assert<Matrix3f>());
+  CALL_SUBTEST_10(qr_verify_assert<Matrix3d>());
+  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
+  CALL_SUBTEST_6(qr_verify_assert<MatrixXd>());
+  CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>());
+  CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>());
+
+  // Test problem size constructors
+  CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20));
+}
diff --git a/test/qr_colpivoting.cpp b/test/qr_colpivoting.cpp
new file mode 100644
index 0000000..eb3feac
--- /dev/null
+++ b/test/qr_colpivoting.cpp
@@ -0,0 +1,150 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename MatrixType> void qr()
+{
+  typedef typename MatrixType::Index Index;
+
+  Index rows = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE), cols2 = internal::random<Index>(2,EIGEN_TEST_MAX_SIZE);
+  Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
+  MatrixType m1;
+  createRandomPIMatrixOfRank(rank,rows,cols,m1);
+  ColPivHouseholderQR<MatrixType> qr(m1);
+  VERIFY(rank == qr.rank());
+  VERIFY(cols - qr.rank() == qr.dimensionOfKernel());
+  VERIFY(!qr.isInjective());
+  VERIFY(!qr.isInvertible());
+  VERIFY(!qr.isSurjective());
+
+  MatrixQType q = qr.householderQ();
+  VERIFY_IS_UNITARY(q);
+
+  MatrixType r = qr.matrixQR().template triangularView<Upper>();
+  MatrixType c = q * r * qr.colsPermutation().inverse();
+  VERIFY_IS_APPROX(m1, c);
+
+  MatrixType m2 = MatrixType::Random(cols,cols2);
+  MatrixType m3 = m1*m2;
+  m2 = MatrixType::Random(cols,cols2);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+}
+
+template<typename MatrixType, int Cols2> void qr_fixedsize()
+{
+  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
+  typedef typename MatrixType::Scalar Scalar;
+  int rank = internal::random<int>(1, (std::min)(int(Rows), int(Cols))-1);
+  Matrix<Scalar,Rows,Cols> m1;
+  createRandomPIMatrixOfRank(rank,Rows,Cols,m1);
+  ColPivHouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);
+  VERIFY(rank == qr.rank());
+  VERIFY(Cols - qr.rank() == qr.dimensionOfKernel());
+  VERIFY(qr.isInjective() == (rank == Rows));
+  VERIFY(qr.isSurjective() == (rank == Cols));
+  VERIFY(qr.isInvertible() == (qr.isInjective() && qr.isSurjective()));
+
+  Matrix<Scalar,Rows,Cols> r = qr.matrixQR().template triangularView<Upper>();
+  Matrix<Scalar,Rows,Cols> c = qr.householderQ() * r * qr.colsPermutation().inverse();
+  VERIFY_IS_APPROX(m1, c);
+
+  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
+  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
+  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+}
+
+template<typename MatrixType> void qr_invertible()
+{
+  using std::log;
+  using std::abs;
+  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+  typedef typename MatrixType::Scalar Scalar;
+
+  int size = internal::random<int>(10,50);
+
+  MatrixType m1(size, size), m2(size, size), m3(size, size);
+  m1 = MatrixType::Random(size,size);
+
+  if (internal::is_same<RealScalar,float>::value)
+  {
+    // let's build a matrix more stable to inverse
+    MatrixType a = MatrixType::Random(size,size*2);
+    m1 += a * a.adjoint();
+  }
+
+  ColPivHouseholderQR<MatrixType> qr(m1);
+  m3 = MatrixType::Random(size,size);
+  m2 = qr.solve(m3);
+  //VERIFY_IS_APPROX(m3, m1*m2);
+
+  // now construct a matrix with prescribed determinant
+  m1.setZero();
+  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
+  RealScalar absdet = abs(m1.diagonal().prod());
+  m3 = qr.householderQ(); // get a unitary
+  m1 = m3 * m1 * m3;
+  qr.compute(m1);
+  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
+  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
+}
+
+template<typename MatrixType> void qr_verify_assert()
+{
+  MatrixType tmp;
+
+  ColPivHouseholderQR<MatrixType> qr;
+  VERIFY_RAISES_ASSERT(qr.matrixQR())
+  VERIFY_RAISES_ASSERT(qr.solve(tmp))
+  VERIFY_RAISES_ASSERT(qr.householderQ())
+  VERIFY_RAISES_ASSERT(qr.dimensionOfKernel())
+  VERIFY_RAISES_ASSERT(qr.isInjective())
+  VERIFY_RAISES_ASSERT(qr.isSurjective())
+  VERIFY_RAISES_ASSERT(qr.isInvertible())
+  VERIFY_RAISES_ASSERT(qr.inverse())
+  VERIFY_RAISES_ASSERT(qr.absDeterminant())
+  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
+}
+
+void test_qr_colpivoting()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( qr<MatrixXf>() );
+    CALL_SUBTEST_2( qr<MatrixXd>() );
+    CALL_SUBTEST_3( qr<MatrixXcd>() );
+    CALL_SUBTEST_4(( qr_fixedsize<Matrix<float,3,5>, 4 >() ));
+    CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,6,2>, 3 >() ));
+    CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,1,1>, 1 >() ));
+  }
+
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
+    CALL_SUBTEST_2( qr_invertible<MatrixXd>() );
+    CALL_SUBTEST_6( qr_invertible<MatrixXcf>() );
+    CALL_SUBTEST_3( qr_invertible<MatrixXcd>() );
+  }
+
+  CALL_SUBTEST_7(qr_verify_assert<Matrix3f>());
+  CALL_SUBTEST_8(qr_verify_assert<Matrix3d>());
+  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
+  CALL_SUBTEST_2(qr_verify_assert<MatrixXd>());
+  CALL_SUBTEST_6(qr_verify_assert<MatrixXcf>());
+  CALL_SUBTEST_3(qr_verify_assert<MatrixXcd>());
+
+  // Test problem size constructors
+  CALL_SUBTEST_9(ColPivHouseholderQR<MatrixXf>(10, 20));
+}
diff --git a/test/qr_fullpivoting.cpp b/test/qr_fullpivoting.cpp
new file mode 100644
index 0000000..511f247
--- /dev/null
+++ b/test/qr_fullpivoting.cpp
@@ -0,0 +1,137 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/QR>
+
+template<typename MatrixType> void qr()
+{
+  typedef typename MatrixType::Index Index;
+
+  Index rows = internal::random<Index>(20,200), cols = internal::random<int>(20,200), cols2 = internal::random<int>(20,200);
+  Index rank = internal::random<Index>(1, (std::min)(rows, cols)-1);
+
+  typedef typename MatrixType::Scalar Scalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;
+  MatrixType m1;
+  createRandomPIMatrixOfRank(rank,rows,cols,m1);
+  FullPivHouseholderQR<MatrixType> qr(m1);
+  VERIFY(rank == qr.rank());
+  VERIFY(cols - qr.rank() == qr.dimensionOfKernel());
+  VERIFY(!qr.isInjective());
+  VERIFY(!qr.isInvertible());
+  VERIFY(!qr.isSurjective());
+
+  MatrixType r = qr.matrixQR();
+  
+  MatrixQType q = qr.matrixQ();
+  VERIFY_IS_UNITARY(q);
+  
+  // FIXME need better way to construct trapezoid
+  for(int i = 0; i < rows; i++) for(int j = 0; j < cols; j++) if(i>j) r(i,j) = Scalar(0);
+
+  MatrixType c = qr.matrixQ() * r * qr.colsPermutation().inverse();
+
+  VERIFY_IS_APPROX(m1, c);
+
+  MatrixType m2 = MatrixType::Random(cols,cols2);
+  MatrixType m3 = m1*m2;
+  m2 = MatrixType::Random(cols,cols2);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+}
+
+template<typename MatrixType> void qr_invertible()
+{
+  using std::log;
+  using std::abs;
+  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
+  typedef typename MatrixType::Scalar Scalar;
+
+  int size = internal::random<int>(10,50);
+
+  MatrixType m1(size, size), m2(size, size), m3(size, size);
+  m1 = MatrixType::Random(size,size);
+
+  if (internal::is_same<RealScalar,float>::value)
+  {
+    // let's build a matrix more stable to inverse
+    MatrixType a = MatrixType::Random(size,size*2);
+    m1 += a * a.adjoint();
+  }
+
+  FullPivHouseholderQR<MatrixType> qr(m1);
+  VERIFY(qr.isInjective());
+  VERIFY(qr.isInvertible());
+  VERIFY(qr.isSurjective());
+
+  m3 = MatrixType::Random(size,size);
+  m2 = qr.solve(m3);
+  VERIFY_IS_APPROX(m3, m1*m2);
+
+  // now construct a matrix with prescribed determinant
+  m1.setZero();
+  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
+  RealScalar absdet = abs(m1.diagonal().prod());
+  m3 = qr.matrixQ(); // get a unitary
+  m1 = m3 * m1 * m3;
+  qr.compute(m1);
+  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
+  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
+}
+
+template<typename MatrixType> void qr_verify_assert()
+{
+  MatrixType tmp;
+
+  FullPivHouseholderQR<MatrixType> qr;
+  VERIFY_RAISES_ASSERT(qr.matrixQR())
+  VERIFY_RAISES_ASSERT(qr.solve(tmp))
+  VERIFY_RAISES_ASSERT(qr.matrixQ())
+  VERIFY_RAISES_ASSERT(qr.dimensionOfKernel())
+  VERIFY_RAISES_ASSERT(qr.isInjective())
+  VERIFY_RAISES_ASSERT(qr.isSurjective())
+  VERIFY_RAISES_ASSERT(qr.isInvertible())
+  VERIFY_RAISES_ASSERT(qr.inverse())
+  VERIFY_RAISES_ASSERT(qr.absDeterminant())
+  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
+}
+
+void test_qr_fullpivoting()
+{
+ for(int i = 0; i < 1; i++) {
+    // FIXME : very weird bug here
+//     CALL_SUBTEST(qr(Matrix2f()) );
+    CALL_SUBTEST_1( qr<MatrixXf>() );
+    CALL_SUBTEST_2( qr<MatrixXd>() );
+    CALL_SUBTEST_3( qr<MatrixXcd>() );
+  }
+
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
+    CALL_SUBTEST_2( qr_invertible<MatrixXd>() );
+    CALL_SUBTEST_4( qr_invertible<MatrixXcf>() );
+    CALL_SUBTEST_3( qr_invertible<MatrixXcd>() );
+  }
+
+  CALL_SUBTEST_5(qr_verify_assert<Matrix3f>());
+  CALL_SUBTEST_6(qr_verify_assert<Matrix3d>());
+  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
+  CALL_SUBTEST_2(qr_verify_assert<MatrixXd>());
+  CALL_SUBTEST_4(qr_verify_assert<MatrixXcf>());
+  CALL_SUBTEST_3(qr_verify_assert<MatrixXcd>());
+
+  // Test problem size constructors
+  CALL_SUBTEST_7(FullPivHouseholderQR<MatrixXf>(10, 20));
+  CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,10,20> >(10,20)));
+  CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,10,20> >(Matrix<float,10,20>::Random())));
+  CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,20,10> >(20,10)));
+  CALL_SUBTEST_7((FullPivHouseholderQR<Matrix<float,20,10> >(Matrix<float,20,10>::Random())));
+}
diff --git a/test/qtvector.cpp b/test/qtvector.cpp
new file mode 100644
index 0000000..2be885e
--- /dev/null
+++ b/test/qtvector.cpp
@@ -0,0 +1,158 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_WORK_AROUND_QT_BUG_CALLING_WRONG_OPERATOR_NEW_FIXED_IN_QT_4_5
+
+#include "main.h"
+#include <QtCore/QVector>
+#include <Eigen/Geometry>
+#include <Eigen/QtAlignedMalloc>
+
+template<typename MatrixType>
+void check_qtvector_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  QVector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], y);
+  }
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_qtvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  QVector<TransformType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; int(i)<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_qtvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  QVector<QuaternionType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.fill(y,22);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; int(i)<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_qtvector()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST(check_qtvector_matrix(Vector2f()));
+  CALL_SUBTEST(check_qtvector_matrix(Matrix3f()));
+  CALL_SUBTEST(check_qtvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST(check_qtvector_matrix(Matrix2f()));
+  CALL_SUBTEST(check_qtvector_matrix(Vector4f()));
+  CALL_SUBTEST(check_qtvector_matrix(Matrix4f()));
+  CALL_SUBTEST(check_qtvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST(check_qtvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST(check_qtvector_matrix(VectorXd(20)));
+  CALL_SUBTEST(check_qtvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST(check_qtvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST(check_qtvector_transform(Affine2f()));
+  CALL_SUBTEST(check_qtvector_transform(Affine3f()));
+  CALL_SUBTEST(check_qtvector_transform(Affine3d()));
+  //CALL_SUBTEST(check_qtvector_transform(Transform4d()));
+
+  // some Quaternion
+  CALL_SUBTEST(check_qtvector_quaternion(Quaternionf()));
+  CALL_SUBTEST(check_qtvector_quaternion(Quaternionf()));
+}
diff --git a/test/real_qz.cpp b/test/real_qz.cpp
new file mode 100644
index 0000000..a1766c6
--- /dev/null
+++ b/test/real_qz.cpp
@@ -0,0 +1,81 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Alexey Korepanov <kaikaikai@yandex.ru>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void real_qz(const MatrixType& m)
+{
+  /* this test covers the following files:
+     RealQZ.h
+  */
+  using std::abs;
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  
+  Index dim = m.cols();
+  
+  MatrixType A = MatrixType::Random(dim,dim),
+             B = MatrixType::Random(dim,dim);
+
+
+  // Regression test for bug 985: Randomly set rows or columns to zero
+  Index k=internal::random<Index>(0, dim-1);
+  switch(internal::random<int>(0,10)) {
+  case 0:
+    A.row(k).setZero(); break;
+  case 1:
+    A.col(k).setZero(); break;
+  case 2:
+    B.row(k).setZero(); break;
+  case 3:
+    B.col(k).setZero(); break;
+  default:
+    break;
+  }
+
+  RealQZ<MatrixType> qz(A,B);
+  
+  VERIFY_IS_EQUAL(qz.info(), Success);
+  // check for zeros
+  bool all_zeros = true;
+  for (Index i=0; i<A.cols(); i++)
+    for (Index j=0; j<i; j++) {
+      if (abs(qz.matrixT()(i,j))!=Scalar(0.0))
+        all_zeros = false;
+      if (j<i-1 && abs(qz.matrixS()(i,j))!=Scalar(0.0))
+        all_zeros = false;
+      if (j==i-1 && j>0 && abs(qz.matrixS()(i,j))!=Scalar(0.0) && abs(qz.matrixS()(i-1,j-1))!=Scalar(0.0))
+        all_zeros = false;
+    }
+  VERIFY_IS_EQUAL(all_zeros, true);
+  VERIFY_IS_APPROX(qz.matrixQ()*qz.matrixS()*qz.matrixZ(), A);
+  VERIFY_IS_APPROX(qz.matrixQ()*qz.matrixT()*qz.matrixZ(), B);
+  VERIFY_IS_APPROX(qz.matrixQ()*qz.matrixQ().adjoint(), MatrixType::Identity(dim,dim));
+  VERIFY_IS_APPROX(qz.matrixZ()*qz.matrixZ().adjoint(), MatrixType::Identity(dim,dim));
+}
+
+void test_real_qz()
+{
+  int s = 0;
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( real_qz(Matrix4f()) );
+    s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4);
+    CALL_SUBTEST_2( real_qz(MatrixXd(s,s)) );
+
+    // some trivial but implementation-wise tricky cases
+    CALL_SUBTEST_2( real_qz(MatrixXd(1,1)) );
+    CALL_SUBTEST_2( real_qz(MatrixXd(2,2)) );
+    CALL_SUBTEST_3( real_qz(Matrix<double,1,1>()) );
+    CALL_SUBTEST_4( real_qz(Matrix2d()) );
+  }
+  
+  TEST_SET_BUT_UNUSED_VARIABLE(s)
+}
diff --git a/test/redux.cpp b/test/redux.cpp
new file mode 100644
index 0000000..0d176e5
--- /dev/null
+++ b/test/redux.cpp
@@ -0,0 +1,159 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void matrixRedux(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols);
+
+  // The entries of m1 are uniformly distributed in [0,1], so m1.prod() is very small. This may lead to test
+  // failures if we underflow into denormals. Thus, we scale so that entires are close to 1.
+  MatrixType m1_for_prod = MatrixType::Ones(rows, cols) + RealScalar(0.2) * m1;
+
+  VERIFY_IS_MUCH_SMALLER_THAN(MatrixType::Zero(rows, cols).sum(), Scalar(1));
+  VERIFY_IS_APPROX(MatrixType::Ones(rows, cols).sum(), Scalar(float(rows*cols))); // the float() here to shut up excessive MSVC warning about int->complex conversion being lossy
+  Scalar s(0), p(1), minc(numext::real(m1.coeff(0))), maxc(numext::real(m1.coeff(0)));
+  for(int j = 0; j < cols; j++)
+  for(int i = 0; i < rows; i++)
+  {
+    s += m1(i,j);
+    p *= m1_for_prod(i,j);
+    minc = (std::min)(numext::real(minc), numext::real(m1(i,j)));
+    maxc = (std::max)(numext::real(maxc), numext::real(m1(i,j)));
+  }
+  const Scalar mean = s/Scalar(RealScalar(rows*cols));
+
+  VERIFY_IS_APPROX(m1.sum(), s);
+  VERIFY_IS_APPROX(m1.mean(), mean);
+  VERIFY_IS_APPROX(m1_for_prod.prod(), p);
+  VERIFY_IS_APPROX(m1.real().minCoeff(), numext::real(minc));
+  VERIFY_IS_APPROX(m1.real().maxCoeff(), numext::real(maxc));
+
+  // test slice vectorization assuming assign is ok
+  Index r0 = internal::random<Index>(0,rows-1);
+  Index c0 = internal::random<Index>(0,cols-1);
+  Index r1 = internal::random<Index>(r0+1,rows)-r0;
+  Index c1 = internal::random<Index>(c0+1,cols)-c0;
+  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).sum(), m1.block(r0,c0,r1,c1).eval().sum());
+  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).mean(), m1.block(r0,c0,r1,c1).eval().mean());
+  VERIFY_IS_APPROX(m1_for_prod.block(r0,c0,r1,c1).prod(), m1_for_prod.block(r0,c0,r1,c1).eval().prod());
+  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().minCoeff(), m1.block(r0,c0,r1,c1).real().eval().minCoeff());
+  VERIFY_IS_APPROX(m1.block(r0,c0,r1,c1).real().maxCoeff(), m1.block(r0,c0,r1,c1).real().eval().maxCoeff());
+  
+  // test empty objects
+  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).sum(),   Scalar(0));
+  VERIFY_IS_APPROX(m1.block(r0,c0,0,0).prod(),  Scalar(1));
+}
+
+template<typename VectorType> void vectorRedux(const VectorType& w)
+{
+  using std::abs;
+  typedef typename VectorType::Index Index;
+  typedef typename VectorType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  Index size = w.size();
+
+  VectorType v = VectorType::Random(size);
+  VectorType v_for_prod = VectorType::Ones(size) + Scalar(0.2) * v; // see comment above declaration of m1_for_prod
+
+  for(int i = 1; i < size; i++)
+  {
+    Scalar s(0), p(1);
+    RealScalar minc(numext::real(v.coeff(0))), maxc(numext::real(v.coeff(0)));
+    for(int j = 0; j < i; j++)
+    {
+      s += v[j];
+      p *= v_for_prod[j];
+      minc = (std::min)(minc, numext::real(v[j]));
+      maxc = (std::max)(maxc, numext::real(v[j]));
+    }
+    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.head(i).sum()), Scalar(1));
+    VERIFY_IS_APPROX(p, v_for_prod.head(i).prod());
+    VERIFY_IS_APPROX(minc, v.real().head(i).minCoeff());
+    VERIFY_IS_APPROX(maxc, v.real().head(i).maxCoeff());
+  }
+
+  for(int i = 0; i < size-1; i++)
+  {
+    Scalar s(0), p(1);
+    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
+    for(int j = i; j < size; j++)
+    {
+      s += v[j];
+      p *= v_for_prod[j];
+      minc = (std::min)(minc, numext::real(v[j]));
+      maxc = (std::max)(maxc, numext::real(v[j]));
+    }
+    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.tail(size-i).sum()), Scalar(1));
+    VERIFY_IS_APPROX(p, v_for_prod.tail(size-i).prod());
+    VERIFY_IS_APPROX(minc, v.real().tail(size-i).minCoeff());
+    VERIFY_IS_APPROX(maxc, v.real().tail(size-i).maxCoeff());
+  }
+
+  for(int i = 0; i < size/2; i++)
+  {
+    Scalar s(0), p(1);
+    RealScalar minc(numext::real(v.coeff(i))), maxc(numext::real(v.coeff(i)));
+    for(int j = i; j < size-i; j++)
+    {
+      s += v[j];
+      p *= v_for_prod[j];
+      minc = (std::min)(minc, numext::real(v[j]));
+      maxc = (std::max)(maxc, numext::real(v[j]));
+    }
+    VERIFY_IS_MUCH_SMALLER_THAN(abs(s - v.segment(i, size-2*i).sum()), Scalar(1));
+    VERIFY_IS_APPROX(p, v_for_prod.segment(i, size-2*i).prod());
+    VERIFY_IS_APPROX(minc, v.real().segment(i, size-2*i).minCoeff());
+    VERIFY_IS_APPROX(maxc, v.real().segment(i, size-2*i).maxCoeff());
+  }
+  
+  // test empty objects
+  VERIFY_IS_APPROX(v.head(0).sum(),   Scalar(0));
+  VERIFY_IS_APPROX(v.tail(0).prod(),  Scalar(1));
+  VERIFY_RAISES_ASSERT(v.head(0).mean());
+  VERIFY_RAISES_ASSERT(v.head(0).minCoeff());
+  VERIFY_RAISES_ASSERT(v.head(0).maxCoeff());
+}
+
+void test_redux()
+{
+  // the max size cannot be too large, otherwise reduxion operations obviously generate large errors.
+  int maxsize = (std::min)(100,EIGEN_TEST_MAX_SIZE);
+  TEST_SET_BUT_UNUSED_VARIABLE(maxsize);
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( matrixRedux(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( matrixRedux(Array<float, 1, 1>()) );
+    CALL_SUBTEST_2( matrixRedux(Matrix2f()) );
+    CALL_SUBTEST_2( matrixRedux(Array2f()) );
+    CALL_SUBTEST_3( matrixRedux(Matrix4d()) );
+    CALL_SUBTEST_3( matrixRedux(Array4d()) );
+    CALL_SUBTEST_4( matrixRedux(MatrixXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_4( matrixRedux(ArrayXXcf(internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_5( matrixRedux(MatrixXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_5( matrixRedux(ArrayXXd (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_6( matrixRedux(MatrixXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_6( matrixRedux(ArrayXXi (internal::random<int>(1,maxsize), internal::random<int>(1,maxsize))) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_7( vectorRedux(Vector4f()) );
+    CALL_SUBTEST_7( vectorRedux(Array4f()) );
+    CALL_SUBTEST_5( vectorRedux(VectorXd(internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_5( vectorRedux(ArrayXd(internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_8( vectorRedux(VectorXf(internal::random<int>(1,maxsize))) );
+    CALL_SUBTEST_8( vectorRedux(ArrayXf(internal::random<int>(1,maxsize))) );
+  }
+}
diff --git a/test/ref.cpp b/test/ref.cpp
new file mode 100644
index 0000000..44bbd3b
--- /dev/null
+++ b/test/ref.cpp
@@ -0,0 +1,276 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 20013 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// This unit test cannot be easily written to work with EIGEN_DEFAULT_TO_ROW_MAJOR
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
+
+static int nb_temporaries;
+
+inline void on_temporary_creation(int) {
+  // here's a great place to set a breakpoint when debugging failures in this test!
+  nb_temporaries++;
+}
+  
+
+#define EIGEN_DENSE_STORAGE_CTOR_PLUGIN { on_temporary_creation(size); }
+
+#include "main.h"
+
+#define VERIFY_EVALUATION_COUNT(XPR,N) {\
+    nb_temporaries = 0; \
+    XPR; \
+    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
+    VERIFY( (#XPR) && nb_temporaries==N ); \
+  }
+
+
+// test Ref.h
+
+template<typename MatrixType> void ref_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::RealScalar RealScalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic,MatrixType::Options> DynMatrixType;
+  typedef Matrix<RealScalar,Dynamic,Dynamic,MatrixType::Options> RealDynMatrixType;
+  
+  typedef Ref<MatrixType> RefMat;
+  typedef Ref<DynMatrixType> RefDynMat;
+  typedef Ref<const DynMatrixType> ConstRefDynMat;
+  typedef Ref<RealDynMatrixType , 0, Stride<Dynamic,Dynamic> > RefRealMatWithStride;
+
+  Index rows = m.rows(), cols = m.cols();
+  
+  MatrixType  m1 = MatrixType::Random(rows, cols),
+              m2 = m1;
+  
+  Index i = internal::random<Index>(0,rows-1);
+  Index j = internal::random<Index>(0,cols-1);
+  Index brows = internal::random<Index>(1,rows-i);
+  Index bcols = internal::random<Index>(1,cols-j);
+  
+  RefMat rm0 = m1;
+  VERIFY_IS_EQUAL(rm0, m1);
+  RefDynMat rm1 = m1;
+  VERIFY_IS_EQUAL(rm1, m1);
+  RefDynMat rm2 = m1.block(i,j,brows,bcols);
+  VERIFY_IS_EQUAL(rm2, m1.block(i,j,brows,bcols));
+  rm2.setOnes();
+  m2.block(i,j,brows,bcols).setOnes();
+  VERIFY_IS_EQUAL(m1, m2);
+  
+  m2.block(i,j,brows,bcols).setRandom();
+  rm2 = m2.block(i,j,brows,bcols);
+  VERIFY_IS_EQUAL(m1, m2);
+  
+  
+  ConstRefDynMat rm3 = m1.block(i,j,brows,bcols);
+  m1.block(i,j,brows,bcols) *= 2;
+  m2.block(i,j,brows,bcols) *= 2;
+  VERIFY_IS_EQUAL(rm3, m2.block(i,j,brows,bcols));
+  RefRealMatWithStride rm4 = m1.real();
+  VERIFY_IS_EQUAL(rm4, m2.real());
+  rm4.array() += 1;
+  m2.real().array() += 1;
+  VERIFY_IS_EQUAL(m1, m2);
+}
+
+template<typename VectorType> void ref_vector(const VectorType& m)
+{
+  typedef typename VectorType::Index Index;
+  typedef typename VectorType::Scalar Scalar;
+  typedef typename VectorType::RealScalar RealScalar;
+  typedef Matrix<Scalar,Dynamic,1,VectorType::Options> DynMatrixType;
+  typedef Matrix<Scalar,Dynamic,Dynamic,ColMajor> MatrixType;
+  typedef Matrix<RealScalar,Dynamic,1,VectorType::Options> RealDynMatrixType;
+  
+  typedef Ref<VectorType> RefMat;
+  typedef Ref<DynMatrixType> RefDynMat;
+  typedef Ref<const DynMatrixType> ConstRefDynMat;
+  typedef Ref<RealDynMatrixType , 0, InnerStride<> > RefRealMatWithStride;
+  typedef Ref<DynMatrixType , 0, InnerStride<> > RefMatWithStride;
+
+  Index size = m.size();
+  
+  VectorType  v1 = VectorType::Random(size),
+              v2 = v1;
+  MatrixType mat1 = MatrixType::Random(size,size),
+             mat2 = mat1,
+             mat3 = MatrixType::Random(size,size);
+  
+  Index i = internal::random<Index>(0,size-1);
+  Index bsize = internal::random<Index>(1,size-i);
+  
+  RefMat rm0 = v1;
+  VERIFY_IS_EQUAL(rm0, v1);
+  RefDynMat rv1 = v1;
+  VERIFY_IS_EQUAL(rv1, v1);
+  RefDynMat rv2 = v1.segment(i,bsize);
+  VERIFY_IS_EQUAL(rv2, v1.segment(i,bsize));
+  rv2.setOnes();
+  v2.segment(i,bsize).setOnes();
+  VERIFY_IS_EQUAL(v1, v2);
+  
+  v2.segment(i,bsize).setRandom();
+  rv2 = v2.segment(i,bsize);
+  VERIFY_IS_EQUAL(v1, v2);
+  
+  ConstRefDynMat rm3 = v1.segment(i,bsize);
+  v1.segment(i,bsize) *= 2;
+  v2.segment(i,bsize) *= 2;
+  VERIFY_IS_EQUAL(rm3, v2.segment(i,bsize));
+  
+  RefRealMatWithStride rm4 = v1.real();
+  VERIFY_IS_EQUAL(rm4, v2.real());
+  rm4.array() += 1;
+  v2.real().array() += 1;
+  VERIFY_IS_EQUAL(v1, v2);
+  
+  RefMatWithStride rm5 = mat1.row(i).transpose();
+  VERIFY_IS_EQUAL(rm5, mat1.row(i).transpose());
+  rm5.array() += 1;
+  mat2.row(i).array() += 1;
+  VERIFY_IS_EQUAL(mat1, mat2);
+  rm5.noalias() = rm4.transpose() * mat3;
+  mat2.row(i) = v2.real().transpose() * mat3;
+  VERIFY_IS_APPROX(mat1, mat2);
+}
+
+template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
+{
+  // verify that ref-to-const don't have LvalueBit
+  typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
+  VERIFY( !(internal::traits<Ref<ConstPlainObjectType> >::Flags & LvalueBit) );
+  VERIFY( !(internal::traits<Ref<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
+  VERIFY( !(Ref<ConstPlainObjectType>::Flags & LvalueBit) );
+  VERIFY( !(Ref<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
+}
+
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_1(Ref<VectorXf> a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_2(const Ref<const VectorXf>& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_3(Ref<VectorXf,0,InnerStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_4(const Ref<const VectorXf,0,InnerStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_5(Ref<MatrixXf,0,OuterStride<> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_6(const Ref<const MatrixXf,0,OuterStride<> >& a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+template<typename B>
+EIGEN_DONT_INLINE void call_ref_7(Ref<Matrix<float,Dynamic,3> > a, const B &b) { VERIFY_IS_EQUAL(a,b); }
+
+void call_ref()
+{
+  VectorXcf ca  = VectorXcf::Random(10);
+  VectorXf a    = VectorXf::Random(10);
+  RowVectorXf b = RowVectorXf::Random(10);
+  MatrixXf A    = MatrixXf::Random(10,10);
+  RowVector3f c = RowVector3f::Random();
+  const VectorXf& ac(a);
+  VectorBlock<VectorXf> ab(a,0,3);
+  const VectorBlock<VectorXf> abc(a,0,3);
+  
+
+  VERIFY_EVALUATION_COUNT( call_ref_1(a,a), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_1(b,b.transpose()), 0);
+//   call_ref_1(ac,a<c);           // does not compile because ac is const
+  VERIFY_EVALUATION_COUNT( call_ref_1(ab,ab), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_1(a.head(4),a.head(4)), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_1(abc,abc), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_1(A.col(3),A.col(3)), 0);
+//   call_ref_1(A.row(3),A.row(3));    // does not compile because innerstride!=1
+  VERIFY_EVALUATION_COUNT( call_ref_3(A.row(3),A.row(3).transpose()), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_4(A.row(3),A.row(3).transpose()), 0);
+//   call_ref_1(a+a, a+a);          // does not compile for obvious reason
+
+  MatrixXf tmp = A*A.col(1);
+  VERIFY_EVALUATION_COUNT( call_ref_2(A*A.col(1), tmp), 1);     // evaluated into a temp
+  VERIFY_EVALUATION_COUNT( call_ref_2(ac.head(5),ac.head(5)), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_2(ac,ac), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_2(a,a), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_2(ab,ab), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_2(a.head(4),a.head(4)), 0);
+  tmp = a+a;
+  VERIFY_EVALUATION_COUNT( call_ref_2(a+a,tmp), 1);            // evaluated into a temp
+  VERIFY_EVALUATION_COUNT( call_ref_2(ca.imag(),ca.imag()), 1);      // evaluated into a temp
+
+  VERIFY_EVALUATION_COUNT( call_ref_4(ac.head(5),ac.head(5)), 0);
+  tmp = a+a;
+  VERIFY_EVALUATION_COUNT( call_ref_4(a+a,tmp), 1);           // evaluated into a temp
+  VERIFY_EVALUATION_COUNT( call_ref_4(ca.imag(),ca.imag()), 0);
+
+  VERIFY_EVALUATION_COUNT( call_ref_5(a,a), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_5(a.head(3),a.head(3)), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_5(A,A), 0);
+//   call_ref_5(A.transpose(),A.transpose());   // does not compile because storage order does not match
+  VERIFY_EVALUATION_COUNT( call_ref_5(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_5(b,b), 0);             // storage order do not match, but this is a degenerate case that should work
+  VERIFY_EVALUATION_COUNT( call_ref_5(a.row(3),a.row(3)), 0);
+
+  VERIFY_EVALUATION_COUNT( call_ref_6(a,a), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_6(a.head(3),a.head(3)), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_6(A.row(3),A.row(3)), 1);           // evaluated into a temp thouth it could be avoided by viewing it as a 1xn matrix
+  tmp = A+A;
+  VERIFY_EVALUATION_COUNT( call_ref_6(A+A,tmp), 1);                // evaluated into a temp
+  VERIFY_EVALUATION_COUNT( call_ref_6(A,A), 0);
+  VERIFY_EVALUATION_COUNT( call_ref_6(A.transpose(),A.transpose()), 1);      // evaluated into a temp because the storage orders do not match
+  VERIFY_EVALUATION_COUNT( call_ref_6(A.block(1,1,2,2),A.block(1,1,2,2)), 0);
+  
+  VERIFY_EVALUATION_COUNT( call_ref_7(c,c), 0);
+}
+
+typedef Matrix<double,Dynamic,Dynamic,RowMajor> RowMatrixXd;
+int test_ref_overload_fun1(Ref<MatrixXd> )       { return 1; }
+int test_ref_overload_fun1(Ref<RowMatrixXd> )    { return 2; }
+int test_ref_overload_fun1(Ref<MatrixXf> )       { return 3; }
+
+int test_ref_overload_fun2(Ref<const MatrixXd> ) { return 4; }
+int test_ref_overload_fun2(Ref<const MatrixXf> ) { return 5; }
+
+// See also bug 969
+void test_ref_overloads()
+{
+  MatrixXd Ad, Bd;
+  RowMatrixXd rAd, rBd;
+  VERIFY( test_ref_overload_fun1(Ad)==1 );
+  VERIFY( test_ref_overload_fun1(rAd)==2 );
+  
+  MatrixXf Af, Bf;
+  VERIFY( test_ref_overload_fun2(Ad)==4 );
+  VERIFY( test_ref_overload_fun2(Ad+Bd)==4 );
+  VERIFY( test_ref_overload_fun2(Af+Bf)==5 );
+}
+
+void test_ref()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( ref_vector(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_1( check_const_correctness(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( ref_vector(Vector4d()) );
+    CALL_SUBTEST_2( check_const_correctness(Matrix4d()) );
+    CALL_SUBTEST_3( ref_vector(Vector4cf()) );
+    CALL_SUBTEST_4( ref_vector(VectorXcf(8)) );
+    CALL_SUBTEST_5( ref_vector(VectorXi(12)) );
+    CALL_SUBTEST_5( check_const_correctness(VectorXi(12)) );
+
+    CALL_SUBTEST_1( ref_matrix(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( ref_matrix(Matrix4d()) );
+    CALL_SUBTEST_1( ref_matrix(Matrix<float,3,5>()) );
+    CALL_SUBTEST_4( ref_matrix(MatrixXcf(internal::random<int>(1,10),internal::random<int>(1,10))) );
+    CALL_SUBTEST_4( ref_matrix(Matrix<std::complex<double>,10,15>()) );
+    CALL_SUBTEST_5( ref_matrix(MatrixXi(internal::random<int>(1,10),internal::random<int>(1,10))) );
+    CALL_SUBTEST_6( call_ref() );
+  }
+  
+  CALL_SUBTEST_7( test_ref_overloads() );
+}
diff --git a/test/resize.cpp b/test/resize.cpp
new file mode 100644
index 0000000..4adaafe
--- /dev/null
+++ b/test/resize.cpp
@@ -0,0 +1,41 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Keir Mierle <mierle@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<DenseIndex rows, DenseIndex cols>
+void resizeLikeTest()
+{
+  MatrixXf A(rows, cols);
+  MatrixXf B;
+  Matrix<double, rows, cols> C;
+  B.resizeLike(A);
+  C.resizeLike(B);  // Shouldn't crash.
+  VERIFY(B.rows() == rows && B.cols() == cols);
+
+  VectorXf x(rows);
+  RowVectorXf y;
+  y.resizeLike(x);
+  VERIFY(y.rows() == 1 && y.cols() == rows);
+
+  y.resize(cols);
+  x.resizeLike(y);
+  VERIFY(x.rows() == cols && x.cols() == 1);
+}
+
+void resizeLikeTest12() { resizeLikeTest<1,2>(); }
+void resizeLikeTest1020() { resizeLikeTest<10,20>(); }
+void resizeLikeTest31() { resizeLikeTest<3,1>(); }
+
+void test_resize()
+{
+  CALL_SUBTEST(resizeLikeTest12() );
+  CALL_SUBTEST(resizeLikeTest1020() );
+  CALL_SUBTEST(resizeLikeTest31() );
+}
diff --git a/test/runtest.sh b/test/runtest.sh
new file mode 100755
index 0000000..2be2508
--- /dev/null
+++ b/test/runtest.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+black='\E[30m'
+red='\E[31m'
+green='\E[32m'
+yellow='\E[33m'
+blue='\E[34m'
+magenta='\E[35m'
+cyan='\E[36m'
+white='\E[37m'
+
+if ! ./$1 > /dev/null 2> .runtest.log ; then
+  echo -e  $red Test $1 failed: $black
+  echo -e $blue
+  cat .runtest.log
+  echo -e $black
+  exit 1
+else
+echo -e $green Test $1 passed$black
+fi
diff --git a/test/schur_complex.cpp b/test/schur_complex.cpp
new file mode 100644
index 0000000..5e86979
--- /dev/null
+++ b/test/schur_complex.cpp
@@ -0,0 +1,91 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTime)
+{
+  typedef typename ComplexSchur<MatrixType>::ComplexScalar ComplexScalar;
+  typedef typename ComplexSchur<MatrixType>::ComplexMatrixType ComplexMatrixType;
+
+  // Test basic functionality: T is triangular and A = U T U*
+  for(int counter = 0; counter < g_repeat; ++counter) {
+    MatrixType A = MatrixType::Random(size, size);
+    ComplexSchur<MatrixType> schurOfA(A);
+    VERIFY_IS_EQUAL(schurOfA.info(), Success);
+    ComplexMatrixType U = schurOfA.matrixU();
+    ComplexMatrixType T = schurOfA.matrixT();
+    for(int row = 1; row < size; ++row) {
+      for(int col = 0; col < row; ++col) {
+	VERIFY(T(row,col) == (typename MatrixType::Scalar)0);
+      }
+    }
+    VERIFY_IS_APPROX(A.template cast<ComplexScalar>(), U * T * U.adjoint());
+  }
+
+  // Test asserts when not initialized
+  ComplexSchur<MatrixType> csUninitialized;
+  VERIFY_RAISES_ASSERT(csUninitialized.matrixT());
+  VERIFY_RAISES_ASSERT(csUninitialized.matrixU());
+  VERIFY_RAISES_ASSERT(csUninitialized.info());
+  
+  // Test whether compute() and constructor returns same result
+  MatrixType A = MatrixType::Random(size, size);
+  ComplexSchur<MatrixType> cs1;
+  cs1.compute(A);
+  ComplexSchur<MatrixType> cs2(A);
+  VERIFY_IS_EQUAL(cs1.info(), Success);
+  VERIFY_IS_EQUAL(cs2.info(), Success);
+  VERIFY_IS_EQUAL(cs1.matrixT(), cs2.matrixT());
+  VERIFY_IS_EQUAL(cs1.matrixU(), cs2.matrixU());
+
+  // Test maximum number of iterations
+  ComplexSchur<MatrixType> cs3;
+  cs3.setMaxIterations(ComplexSchur<MatrixType>::m_maxIterationsPerRow * size).compute(A);
+  VERIFY_IS_EQUAL(cs3.info(), Success);
+  VERIFY_IS_EQUAL(cs3.matrixT(), cs1.matrixT());
+  VERIFY_IS_EQUAL(cs3.matrixU(), cs1.matrixU());
+  cs3.setMaxIterations(1).compute(A);
+  VERIFY_IS_EQUAL(cs3.info(), size > 1 ? NoConvergence : Success);
+  VERIFY_IS_EQUAL(cs3.getMaxIterations(), 1);
+
+  MatrixType Atriangular = A;
+  Atriangular.template triangularView<StrictlyLower>().setZero(); 
+  cs3.setMaxIterations(1).compute(Atriangular); // triangular matrices do not need any iterations
+  VERIFY_IS_EQUAL(cs3.info(), Success);
+  VERIFY_IS_EQUAL(cs3.matrixT(), Atriangular.template cast<ComplexScalar>());
+  VERIFY_IS_EQUAL(cs3.matrixU(), ComplexMatrixType::Identity(size, size));
+
+  // Test computation of only T, not U
+  ComplexSchur<MatrixType> csOnlyT(A, false);
+  VERIFY_IS_EQUAL(csOnlyT.info(), Success);
+  VERIFY_IS_EQUAL(cs1.matrixT(), csOnlyT.matrixT());
+  VERIFY_RAISES_ASSERT(csOnlyT.matrixU());
+
+  if (size > 1)
+  {
+    // Test matrix with NaN
+    A(0,0) = std::numeric_limits<typename MatrixType::RealScalar>::quiet_NaN();
+    ComplexSchur<MatrixType> csNaN(A);
+    VERIFY_IS_EQUAL(csNaN.info(), NoConvergence);
+  }
+}
+
+void test_schur_complex()
+{
+  CALL_SUBTEST_1(( schur<Matrix4cd>() ));
+  CALL_SUBTEST_2(( schur<MatrixXcf>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4)) ));
+  CALL_SUBTEST_3(( schur<Matrix<std::complex<float>, 1, 1> >() ));
+  CALL_SUBTEST_4(( schur<Matrix<float, 3, 3, Eigen::RowMajor> >() ));
+
+  // Test problem size constructors
+  CALL_SUBTEST_5(ComplexSchur<MatrixXf>(10));
+}
diff --git a/test/schur_real.cpp b/test/schur_real.cpp
new file mode 100644
index 0000000..36b9c24
--- /dev/null
+++ b/test/schur_real.cpp
@@ -0,0 +1,112 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010,2012 Jitse Niesen <jitse@maths.leeds.ac.uk>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <limits>
+#include <Eigen/Eigenvalues>
+
+template<typename MatrixType> void verifyIsQuasiTriangular(const MatrixType& T)
+{
+  typedef typename MatrixType::Index Index;
+
+  const Index size = T.cols();
+  typedef typename MatrixType::Scalar Scalar;
+
+  // Check T is lower Hessenberg
+  for(int row = 2; row < size; ++row) {
+    for(int col = 0; col < row - 1; ++col) {
+      VERIFY(T(row,col) == Scalar(0));
+    }
+  }
+
+  // Check that any non-zero on the subdiagonal is followed by a zero and is
+  // part of a 2x2 diagonal block with imaginary eigenvalues.
+  for(int row = 1; row < size; ++row) {
+    if (T(row,row-1) != Scalar(0)) {
+      VERIFY(row == size-1 || T(row+1,row) == 0);
+      Scalar tr = T(row-1,row-1) + T(row,row);
+      Scalar det = T(row-1,row-1) * T(row,row) - T(row-1,row) * T(row,row-1);
+      VERIFY(4 * det > tr * tr);
+    }
+  }
+}
+
+template<typename MatrixType> void schur(int size = MatrixType::ColsAtCompileTime)
+{
+  // Test basic functionality: T is quasi-triangular and A = U T U*
+  for(int counter = 0; counter < g_repeat; ++counter) {
+    MatrixType A = MatrixType::Random(size, size);
+    RealSchur<MatrixType> schurOfA(A);
+    VERIFY_IS_EQUAL(schurOfA.info(), Success);
+    MatrixType U = schurOfA.matrixU();
+    MatrixType T = schurOfA.matrixT();
+    verifyIsQuasiTriangular(T);
+    VERIFY_IS_APPROX(A, U * T * U.transpose());
+  }
+
+  // Test asserts when not initialized
+  RealSchur<MatrixType> rsUninitialized;
+  VERIFY_RAISES_ASSERT(rsUninitialized.matrixT());
+  VERIFY_RAISES_ASSERT(rsUninitialized.matrixU());
+  VERIFY_RAISES_ASSERT(rsUninitialized.info());
+  
+  // Test whether compute() and constructor returns same result
+  MatrixType A = MatrixType::Random(size, size);
+  RealSchur<MatrixType> rs1;
+  rs1.compute(A);
+  RealSchur<MatrixType> rs2(A);
+  VERIFY_IS_EQUAL(rs1.info(), Success);
+  VERIFY_IS_EQUAL(rs2.info(), Success);
+  VERIFY_IS_EQUAL(rs1.matrixT(), rs2.matrixT());
+  VERIFY_IS_EQUAL(rs1.matrixU(), rs2.matrixU());
+
+  // Test maximum number of iterations
+  RealSchur<MatrixType> rs3;
+  rs3.setMaxIterations(RealSchur<MatrixType>::m_maxIterationsPerRow * size).compute(A);
+  VERIFY_IS_EQUAL(rs3.info(), Success);
+  VERIFY_IS_EQUAL(rs3.matrixT(), rs1.matrixT());
+  VERIFY_IS_EQUAL(rs3.matrixU(), rs1.matrixU());
+  if (size > 2) {
+    rs3.setMaxIterations(1).compute(A);
+    VERIFY_IS_EQUAL(rs3.info(), NoConvergence);
+    VERIFY_IS_EQUAL(rs3.getMaxIterations(), 1);
+  }
+
+  MatrixType Atriangular = A;
+  Atriangular.template triangularView<StrictlyLower>().setZero(); 
+  rs3.setMaxIterations(1).compute(Atriangular); // triangular matrices do not need any iterations
+  VERIFY_IS_EQUAL(rs3.info(), Success);
+  VERIFY_IS_EQUAL(rs3.matrixT(), Atriangular);
+  VERIFY_IS_EQUAL(rs3.matrixU(), MatrixType::Identity(size, size));
+
+  // Test computation of only T, not U
+  RealSchur<MatrixType> rsOnlyT(A, false);
+  VERIFY_IS_EQUAL(rsOnlyT.info(), Success);
+  VERIFY_IS_EQUAL(rs1.matrixT(), rsOnlyT.matrixT());
+  VERIFY_RAISES_ASSERT(rsOnlyT.matrixU());
+
+  if (size > 2)
+  {
+    // Test matrix with NaN
+    A(0,0) = std::numeric_limits<typename MatrixType::Scalar>::quiet_NaN();
+    RealSchur<MatrixType> rsNaN(A);
+    VERIFY_IS_EQUAL(rsNaN.info(), NoConvergence);
+  }
+}
+
+void test_schur_real()
+{
+  CALL_SUBTEST_1(( schur<Matrix4f>() ));
+  CALL_SUBTEST_2(( schur<MatrixXd>(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/4)) ));
+  CALL_SUBTEST_3(( schur<Matrix<float, 1, 1> >() ));
+  CALL_SUBTEST_4(( schur<Matrix<double, 3, 3, Eigen::RowMajor> >() ));
+
+  // Test problem size constructors
+  CALL_SUBTEST_5(RealSchur<MatrixXf>(10));
+}
diff --git a/test/selfadjoint.cpp b/test/selfadjoint.cpp
new file mode 100644
index 0000000..76dab6d
--- /dev/null
+++ b/test/selfadjoint.cpp
@@ -0,0 +1,61 @@
+// This file is triangularView of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+// This file tests the basic selfadjointView API,
+// the related products and decompositions are tested in specific files.
+
+template<typename MatrixType> void selfadjoint(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m3(rows, cols);
+
+  m1.diagonal() = m1.diagonal().real().template cast<Scalar>();
+
+  // check selfadjoint to dense
+  m3 = m1.template selfadjointView<Upper>();
+  VERIFY_IS_APPROX(MatrixType(m3.template triangularView<Upper>()), MatrixType(m1.template triangularView<Upper>()));
+  VERIFY_IS_APPROX(m3, m3.adjoint());
+
+
+  m3 = m1.template selfadjointView<Lower>();
+  VERIFY_IS_APPROX(MatrixType(m3.template triangularView<Lower>()), MatrixType(m1.template triangularView<Lower>()));
+  VERIFY_IS_APPROX(m3, m3.adjoint());
+}
+
+void bug_159()
+{
+  Matrix3d m = Matrix3d::Random().selfadjointView<Lower>();
+  EIGEN_UNUSED_VARIABLE(m)
+}
+
+void test_selfadjoint()
+{
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    int s = internal::random<int>(1,EIGEN_TEST_MAX_SIZE);
+
+    CALL_SUBTEST_1( selfadjoint(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( selfadjoint(Matrix<float, 2, 2>()) );
+    CALL_SUBTEST_3( selfadjoint(Matrix3cf()) );
+    CALL_SUBTEST_4( selfadjoint(MatrixXcd(s,s)) );
+    CALL_SUBTEST_5( selfadjoint(Matrix<float,Dynamic,Dynamic,RowMajor>(s, s)) );
+    
+    TEST_SET_BUT_UNUSED_VARIABLE(s)
+  }
+  
+  CALL_SUBTEST_1( bug_159() );
+}
diff --git a/test/simplicial_cholesky.cpp b/test/simplicial_cholesky.cpp
new file mode 100644
index 0000000..7864684
--- /dev/null
+++ b/test/simplicial_cholesky.cpp
@@ -0,0 +1,45 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+
+template<typename T> void test_simplicial_cholesky_T()
+{
+  SimplicialCholesky<SparseMatrix<T>, Lower> chol_colmajor_lower_amd;
+  SimplicialCholesky<SparseMatrix<T>, Upper> chol_colmajor_upper_amd;
+  SimplicialLLT<SparseMatrix<T>, Lower> llt_colmajor_lower_amd;
+  SimplicialLLT<SparseMatrix<T>, Upper> llt_colmajor_upper_amd;
+  SimplicialLDLT<SparseMatrix<T>, Lower> ldlt_colmajor_lower_amd;
+  SimplicialLDLT<SparseMatrix<T>, Upper> ldlt_colmajor_upper_amd;
+  SimplicialLDLT<SparseMatrix<T>, Lower, NaturalOrdering<int> > ldlt_colmajor_lower_nat;
+  SimplicialLDLT<SparseMatrix<T>, Upper, NaturalOrdering<int> > ldlt_colmajor_upper_nat;
+
+  check_sparse_spd_solving(chol_colmajor_lower_amd);
+  check_sparse_spd_solving(chol_colmajor_upper_amd);
+  check_sparse_spd_solving(llt_colmajor_lower_amd);
+  check_sparse_spd_solving(llt_colmajor_upper_amd);
+  check_sparse_spd_solving(ldlt_colmajor_lower_amd);
+  check_sparse_spd_solving(ldlt_colmajor_upper_amd);
+  
+  check_sparse_spd_determinant(chol_colmajor_lower_amd);
+  check_sparse_spd_determinant(chol_colmajor_upper_amd);
+  check_sparse_spd_determinant(llt_colmajor_lower_amd);
+  check_sparse_spd_determinant(llt_colmajor_upper_amd);
+  check_sparse_spd_determinant(ldlt_colmajor_lower_amd);
+  check_sparse_spd_determinant(ldlt_colmajor_upper_amd);
+  
+  check_sparse_spd_solving(ldlt_colmajor_lower_nat);
+  check_sparse_spd_solving(ldlt_colmajor_upper_nat);
+}
+
+void test_simplicial_cholesky()
+{
+  CALL_SUBTEST_1(test_simplicial_cholesky_T<double>());
+  CALL_SUBTEST_2(test_simplicial_cholesky_T<std::complex<double> >());
+}
diff --git a/test/sizeof.cpp b/test/sizeof.cpp
new file mode 100644
index 0000000..d9ad356
--- /dev/null
+++ b/test/sizeof.cpp
@@ -0,0 +1,34 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void verifySizeOf(const MatrixType&)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  if (MatrixType::RowsAtCompileTime!=Dynamic && MatrixType::ColsAtCompileTime!=Dynamic)
+    VERIFY(std::ptrdiff_t(sizeof(MatrixType))==std::ptrdiff_t(sizeof(Scalar))*std::ptrdiff_t(MatrixType::SizeAtCompileTime));
+  else
+    VERIFY(sizeof(MatrixType)==sizeof(Scalar*) + 2 * sizeof(typename MatrixType::Index));
+}
+
+void test_sizeof()
+{
+  CALL_SUBTEST(verifySizeOf(Matrix<float, 1, 1>()) );
+  CALL_SUBTEST(verifySizeOf(Matrix4d()) );
+  CALL_SUBTEST(verifySizeOf(Matrix<double, 4, 2>()) );
+  CALL_SUBTEST(verifySizeOf(Matrix<bool, 7, 5>()) );
+  CALL_SUBTEST(verifySizeOf(MatrixXcf(3, 3)) );
+  CALL_SUBTEST(verifySizeOf(MatrixXi(8, 12)) );
+  CALL_SUBTEST(verifySizeOf(MatrixXcd(20, 20)) );
+  CALL_SUBTEST(verifySizeOf(Matrix<float, 100, 100>()) );
+  
+  VERIFY(sizeof(std::complex<float>) == 2*sizeof(float));
+  VERIFY(sizeof(std::complex<double>) == 2*sizeof(double));
+}
diff --git a/test/sizeoverflow.cpp b/test/sizeoverflow.cpp
new file mode 100644
index 0000000..16d6f8d
--- /dev/null
+++ b/test/sizeoverflow.cpp
@@ -0,0 +1,66 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#define VERIFY_THROWS_BADALLOC(a) {                           \
+    bool threw = false;                                       \
+    try {                                                     \
+      a;                                                      \
+    }                                                         \
+    catch (std::bad_alloc&) { threw = true; }                 \
+    VERIFY(threw && "should have thrown bad_alloc: " #a);     \
+  }
+
+typedef DenseIndex Index;
+
+template<typename MatrixType>
+void triggerMatrixBadAlloc(Index rows, Index cols)
+{
+  VERIFY_THROWS_BADALLOC( MatrixType m(rows, cols) );
+  VERIFY_THROWS_BADALLOC( MatrixType m; m.resize(rows, cols) );
+  VERIFY_THROWS_BADALLOC( MatrixType m; m.conservativeResize(rows, cols) );
+}
+
+template<typename VectorType>
+void triggerVectorBadAlloc(Index size)
+{
+  VERIFY_THROWS_BADALLOC( VectorType v(size) );
+  VERIFY_THROWS_BADALLOC( VectorType v; v.resize(size) );
+  VERIFY_THROWS_BADALLOC( VectorType v; v.conservativeResize(size) );
+}
+
+void test_sizeoverflow()
+{
+  // there are 2 levels of overflow checking. first in PlainObjectBase.h we check for overflow in rows*cols computations.
+  // this is tested in tests of the form times_itself_gives_0 * times_itself_gives_0
+  // Then in Memory.h we check for overflow in size * sizeof(T) computations.
+  // this is tested in tests of the form times_4_gives_0 * sizeof(float)
+  
+  size_t times_itself_gives_0 = size_t(1) << (8 * sizeof(Index) / 2);
+  VERIFY(times_itself_gives_0 * times_itself_gives_0 == 0);
+
+  size_t times_4_gives_0 = size_t(1) << (8 * sizeof(Index) - 2);
+  VERIFY(times_4_gives_0 * 4 == 0);
+
+  size_t times_8_gives_0 = size_t(1) << (8 * sizeof(Index) - 3);
+  VERIFY(times_8_gives_0 * 8 == 0);
+
+  triggerMatrixBadAlloc<MatrixXf>(times_itself_gives_0, times_itself_gives_0);
+  triggerMatrixBadAlloc<MatrixXf>(times_itself_gives_0 / 4, times_itself_gives_0);
+  triggerMatrixBadAlloc<MatrixXf>(times_4_gives_0, 1);
+
+  triggerMatrixBadAlloc<MatrixXd>(times_itself_gives_0, times_itself_gives_0);
+  triggerMatrixBadAlloc<MatrixXd>(times_itself_gives_0 / 8, times_itself_gives_0);
+  triggerMatrixBadAlloc<MatrixXd>(times_8_gives_0, 1);
+  
+  triggerVectorBadAlloc<VectorXf>(times_4_gives_0);
+  
+  triggerVectorBadAlloc<VectorXd>(times_8_gives_0);
+}
diff --git a/test/smallvectors.cpp b/test/smallvectors.cpp
new file mode 100644
index 0000000..7815113
--- /dev/null
+++ b/test/smallvectors.cpp
@@ -0,0 +1,67 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "main.h"
+
+template<typename Scalar> void smallVectors()
+{
+  typedef Matrix<Scalar, 1, 2> V2;
+  typedef Matrix<Scalar, 3, 1> V3;
+  typedef Matrix<Scalar, 1, 4> V4;
+  typedef Matrix<Scalar, Dynamic, 1> VX;
+  Scalar x1 = internal::random<Scalar>(),
+         x2 = internal::random<Scalar>(),
+         x3 = internal::random<Scalar>(),
+         x4 = internal::random<Scalar>();
+  V2 v2(x1, x2);
+  V3 v3(x1, x2, x3);
+  V4 v4(x1, x2, x3, x4);
+  VERIFY_IS_APPROX(x1, v2.x());
+  VERIFY_IS_APPROX(x1, v3.x());
+  VERIFY_IS_APPROX(x1, v4.x());
+  VERIFY_IS_APPROX(x2, v2.y());
+  VERIFY_IS_APPROX(x2, v3.y());
+  VERIFY_IS_APPROX(x2, v4.y());
+  VERIFY_IS_APPROX(x3, v3.z());
+  VERIFY_IS_APPROX(x3, v4.z());
+  VERIFY_IS_APPROX(x4, v4.w());
+
+  if (!NumTraits<Scalar>::IsInteger)
+  {
+    VERIFY_RAISES_ASSERT(V3(2, 1))
+    VERIFY_RAISES_ASSERT(V3(3, 2))
+    VERIFY_RAISES_ASSERT(V3(Scalar(3), 1))
+    VERIFY_RAISES_ASSERT(V3(3, Scalar(1)))
+    VERIFY_RAISES_ASSERT(V3(Scalar(3), Scalar(1)))
+    VERIFY_RAISES_ASSERT(V3(Scalar(123), Scalar(123)))
+
+    VERIFY_RAISES_ASSERT(V4(1, 3))
+    VERIFY_RAISES_ASSERT(V4(2, 4))
+    VERIFY_RAISES_ASSERT(V4(1, Scalar(4)))
+    VERIFY_RAISES_ASSERT(V4(Scalar(1), 4))
+    VERIFY_RAISES_ASSERT(V4(Scalar(1), Scalar(4)))
+    VERIFY_RAISES_ASSERT(V4(Scalar(123), Scalar(123)))
+
+    VERIFY_RAISES_ASSERT(VX(3, 2))
+    VERIFY_RAISES_ASSERT(VX(Scalar(3), 1))
+    VERIFY_RAISES_ASSERT(VX(3, Scalar(1)))
+    VERIFY_RAISES_ASSERT(VX(Scalar(3), Scalar(1)))
+    VERIFY_RAISES_ASSERT(VX(Scalar(123), Scalar(123)))
+  }
+}
+
+void test_smallvectors()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST(smallVectors<int>() );
+    CALL_SUBTEST(smallVectors<float>() );
+    CALL_SUBTEST(smallVectors<double>() );
+  }
+}
diff --git a/test/sparse.h b/test/sparse.h
new file mode 100644
index 0000000..e19a763
--- /dev/null
+++ b/test/sparse.h
@@ -0,0 +1,207 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_TESTSPARSE_H
+#define EIGEN_TESTSPARSE_H
+
+#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
+
+#include "main.h"
+
+#if EIGEN_GNUC_AT_LEAST(4,0) && !defined __ICC && !defined(__clang__)
+
+#ifdef min
+#undef min
+#endif
+
+#ifdef max
+#undef max
+#endif
+
+#include <tr1/unordered_map>
+#define EIGEN_UNORDERED_MAP_SUPPORT
+namespace std {
+  using std::tr1::unordered_map;
+}
+#endif
+
+#ifdef EIGEN_GOOGLEHASH_SUPPORT
+  #include <google/sparse_hash_map>
+#endif
+
+#include <Eigen/Cholesky>
+#include <Eigen/LU>
+#include <Eigen/Sparse>
+
+enum {
+  ForceNonZeroDiag = 1,
+  MakeLowerTriangular = 2,
+  MakeUpperTriangular = 4,
+  ForceRealDiag = 8
+};
+
+/* Initializes both a sparse and dense matrix with same random values,
+ * and a ratio of \a density non zero entries.
+ * \param flags is a union of ForceNonZeroDiag, MakeLowerTriangular and MakeUpperTriangular
+ *        allowing to control the shape of the matrix.
+ * \param zeroCoords and nonzeroCoords allows to get the coordinate lists of the non zero,
+ *        and zero coefficients respectively.
+ */
+template<typename Scalar,int Opt1,int Opt2,typename Index> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,Dynamic,Opt1>& refMat,
+           SparseMatrix<Scalar,Opt2,Index>& sparseMat,
+           int flags = 0,
+           std::vector<Matrix<Index,2,1> >* zeroCoords = 0,
+           std::vector<Matrix<Index,2,1> >* nonzeroCoords = 0)
+{
+  enum { IsRowMajor = SparseMatrix<Scalar,Opt2,Index>::IsRowMajor };
+  sparseMat.setZero();
+  //sparseMat.reserve(int(refMat.rows()*refMat.cols()*density));
+  sparseMat.reserve(VectorXi::Constant(IsRowMajor ? refMat.rows() : refMat.cols(), int((1.5*density)*(IsRowMajor?refMat.cols():refMat.rows()))));
+  
+  for(Index j=0; j<sparseMat.outerSize(); j++)
+  {
+    //sparseMat.startVec(j);
+    for(Index i=0; i<sparseMat.innerSize(); i++)
+    {
+      int ai(i), aj(j);
+      if(IsRowMajor)
+        std::swap(ai,aj);
+      Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
+      if ((flags&ForceNonZeroDiag) && (i==j))
+      {
+        v = internal::random<Scalar>()*Scalar(3.);
+        v = v*v + Scalar(5.);
+      }
+      if ((flags & MakeLowerTriangular) && aj>ai)
+        v = Scalar(0);
+      else if ((flags & MakeUpperTriangular) && aj<ai)
+        v = Scalar(0);
+
+      if ((flags&ForceRealDiag) && (i==j))
+        v = numext::real(v);
+
+      if (v!=Scalar(0))
+      {
+        //sparseMat.insertBackByOuterInner(j,i) = v;
+        sparseMat.insertByOuterInner(j,i) = v;
+        if (nonzeroCoords)
+          nonzeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+      }
+      else if (zeroCoords)
+      {
+        zeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+      }
+      refMat(ai,aj) = v;
+    }
+  }
+  //sparseMat.finalize();
+}
+
+template<typename Scalar,int Opt1,int Opt2,typename Index> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,Dynamic, Opt1>& refMat,
+           DynamicSparseMatrix<Scalar, Opt2, Index>& sparseMat,
+           int flags = 0,
+           std::vector<Matrix<Index,2,1> >* zeroCoords = 0,
+           std::vector<Matrix<Index,2,1> >* nonzeroCoords = 0)
+{
+  enum { IsRowMajor = DynamicSparseMatrix<Scalar,Opt2,Index>::IsRowMajor };
+  sparseMat.setZero();
+  sparseMat.reserve(int(refMat.rows()*refMat.cols()*density));
+  for(int j=0; j<sparseMat.outerSize(); j++)
+  {
+    sparseMat.startVec(j); // not needed for DynamicSparseMatrix
+    for(int i=0; i<sparseMat.innerSize(); i++)
+    {
+      int ai(i), aj(j);
+      if(IsRowMajor)
+        std::swap(ai,aj);
+      Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
+      if ((flags&ForceNonZeroDiag) && (i==j))
+      {
+        v = internal::random<Scalar>()*Scalar(3.);
+        v = v*v + Scalar(5.);
+      }
+      if ((flags & MakeLowerTriangular) && aj>ai)
+        v = Scalar(0);
+      else if ((flags & MakeUpperTriangular) && aj<ai)
+        v = Scalar(0);
+
+      if ((flags&ForceRealDiag) && (i==j))
+        v = numext::real(v);
+
+      if (v!=Scalar(0))
+      {
+        sparseMat.insertBackByOuterInner(j,i) = v;
+        if (nonzeroCoords)
+          nonzeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+      }
+      else if (zeroCoords)
+      {
+        zeroCoords->push_back(Matrix<Index,2,1> (ai,aj));
+      }
+      refMat(ai,aj) = v;
+    }
+  }
+  sparseMat.finalize();
+}
+
+template<typename Scalar,int Options,typename Index> void
+initSparse(double density,
+           Matrix<Scalar,Dynamic,1>& refVec,
+           SparseVector<Scalar,Options,Index>& sparseVec,
+           std::vector<int>* zeroCoords = 0,
+           std::vector<int>* nonzeroCoords = 0)
+{
+  sparseVec.reserve(int(refVec.size()*density));
+  sparseVec.setZero();
+  for(Index i=0; i<refVec.size(); i++)
+  {
+    Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
+    if (v!=Scalar(0))
+    {
+      sparseVec.insertBack(i) = v;
+      if (nonzeroCoords)
+        nonzeroCoords->push_back(i);
+    }
+    else if (zeroCoords)
+        zeroCoords->push_back(i);
+    refVec[i] = v;
+  }
+}
+
+template<typename Scalar,int Options,typename Index> void
+initSparse(double density,
+           Matrix<Scalar,1,Dynamic>& refVec,
+           SparseVector<Scalar,Options,Index>& sparseVec,
+           std::vector<int>* zeroCoords = 0,
+           std::vector<int>* nonzeroCoords = 0)
+{
+  sparseVec.reserve(int(refVec.size()*density));
+  sparseVec.setZero();
+  for(int i=0; i<refVec.size(); i++)
+  {
+    Scalar v = (internal::random<double>(0,1) < density) ? internal::random<Scalar>() : Scalar(0);
+    if (v!=Scalar(0))
+    {
+      sparseVec.insertBack(i) = v;
+      if (nonzeroCoords)
+        nonzeroCoords->push_back(i);
+    }
+    else if (zeroCoords)
+        zeroCoords->push_back(i);
+    refVec[i] = v;
+  }
+}
+
+
+#include <unsupported/Eigen/SparseExtra>
+#endif // EIGEN_TESTSPARSE_H
diff --git a/test/sparseLM.cpp b/test/sparseLM.cpp
new file mode 100644
index 0000000..8e148f9
--- /dev/null
+++ b/test/sparseLM.cpp
@@ -0,0 +1,176 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+#include "main.h"
+#include <Eigen/LevenbergMarquardt>
+
+using namespace std;
+using namespace Eigen;
+
+template <typename Scalar>
+struct sparseGaussianTest : SparseFunctor<Scalar, int>
+{
+  typedef Matrix<Scalar,Dynamic,1> VectorType;
+  typedef SparseFunctor<Scalar,int> Base;
+  typedef typename Base::JacobianType JacobianType;
+  sparseGaussianTest(int inputs, int values) : SparseFunctor<Scalar,int>(inputs,values)
+  { }
+  
+  VectorType model(const VectorType& uv, VectorType& x)
+  {
+    VectorType y; //Change this to use expression template
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(uv.size()%2 == 0);
+    eigen_assert(uv.size() == n);
+    eigen_assert(x.size() == m);
+    y.setZero(m);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    Scalar coeff;
+    for (int j = 0; j < m; j++)
+    {
+      for (int i = 0; i < half; i++) 
+      {
+        coeff = (x(j)-i)/v(i);
+        coeff *= coeff;
+        if (coeff < 1. && coeff > 0.)
+          y(j) += u(i)*std::pow((1-coeff), 2);
+      }
+    }
+    return y;
+  }
+  void initPoints(VectorType& uv_ref, VectorType& x)
+  {
+    m_x = x;
+    m_y = this->model(uv_ref,x);
+  }
+  int operator()(const VectorType& uv, VectorType& fvec)
+  {
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(uv.size()%2 == 0);
+    eigen_assert(uv.size() == n);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    fvec = m_y;
+    Scalar coeff;
+    for (int j = 0; j < m; j++)
+    {
+      for (int i = 0; i < half; i++)
+      {
+        coeff = (m_x(j)-i)/v(i);
+        coeff *= coeff;
+        if (coeff < 1. && coeff > 0.)
+          fvec(j) -= u(i)*std::pow((1-coeff), 2);
+      }
+    }
+    return 0;
+  }
+  
+  int df(const VectorType& uv, JacobianType& fjac)
+  {
+    int m = Base::values(); 
+    int n = Base::inputs();
+    eigen_assert(n == uv.size());
+    eigen_assert(fjac.rows() == m);
+    eigen_assert(fjac.cols() == n);
+    int half = n/2;
+    VectorBlock<const VectorType> u(uv, 0, half);
+    VectorBlock<const VectorType> v(uv, half, half);
+    Scalar coeff;
+    
+    //Derivatives with respect to u
+    for (int col = 0; col < half; col++)
+    {
+      for (int row = 0; row < m; row++)
+      {
+        coeff = (m_x(row)-col)/v(col);
+          coeff = coeff*coeff;
+        if(coeff < 1. && coeff > 0.)
+        {
+          fjac.coeffRef(row,col) = -(1-coeff)*(1-coeff);
+        }
+      }
+    }
+    //Derivatives with respect to v
+    for (int col = 0; col < half; col++)
+    {
+      for (int row = 0; row < m; row++)
+      {
+        coeff = (m_x(row)-col)/v(col);
+        coeff = coeff*coeff;
+        if(coeff < 1. && coeff > 0.)
+        {
+          fjac.coeffRef(row,col+half) = -4 * (u(col)/v(col))*coeff*(1-coeff);
+        }
+      }
+    }
+    return 0;
+  }
+  
+  VectorType m_x, m_y; //Data points
+};
+
+
+template<typename T>
+void test_sparseLM_T()
+{
+  typedef Matrix<T,Dynamic,1> VectorType;
+  
+  int inputs = 10;
+  int values = 2000;
+  sparseGaussianTest<T> sparse_gaussian(inputs, values);
+  VectorType uv(inputs),uv_ref(inputs);
+  VectorType x(values);
+  // Generate the reference solution 
+  uv_ref << -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
+  //Generate the reference data points
+  x.setRandom();
+  x = 10*x;
+  x.array() += 10;
+  sparse_gaussian.initPoints(uv_ref, x);
+  
+  
+  // Generate the initial parameters 
+  VectorBlock<VectorType> u(uv, 0, inputs/2); 
+  VectorBlock<VectorType> v(uv, inputs/2, inputs/2);
+  v.setOnes();
+  //Generate u or Solve for u from v
+  u.setOnes();
+  
+  // Solve the optimization problem
+  LevenbergMarquardt<sparseGaussianTest<T> > lm(sparse_gaussian);
+  int info;
+//   info = lm.minimize(uv);
+  
+  VERIFY_IS_EQUAL(info,1);
+    // Do a step by step solution and save the residual 
+  int maxiter = 200;
+  int iter = 0;
+  MatrixXd Err(values, maxiter);
+  MatrixXd Mod(values, maxiter);
+  LevenbergMarquardtSpace::Status status; 
+  status = lm.minimizeInit(uv);
+  if (status==LevenbergMarquardtSpace::ImproperInputParameters)
+      return ;
+
+}
+void test_sparseLM()
+{
+  CALL_SUBTEST_1(test_sparseLM_T<double>());
+  
+  // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());
+}
diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp
new file mode 100644
index 0000000..ce41d71
--- /dev/null
+++ b/test/sparse_basic.cpp
@@ -0,0 +1,550 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+// Copyright (C) 2008 Daniel Gomez Ferro <dgomezferro@gmail.com>
+// Copyright (C) 2013 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& ref)
+{
+  typedef typename SparseMatrixType::Index Index;
+  typedef Matrix<Index,2,1> Vector2;
+  
+  const Index rows = ref.rows();
+  const Index cols = ref.cols();
+  typedef typename SparseMatrixType::Scalar Scalar;
+  enum { Flags = SparseMatrixType::Flags };
+
+  double density = (std::max)(8./(rows*cols), 0.01);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
+  Scalar eps = 1e-6;
+
+  Scalar s1 = internal::random<Scalar>();
+  {
+    SparseMatrixType m(rows, cols);
+    DenseMatrix refMat = DenseMatrix::Zero(rows, cols);
+    DenseVector vec1 = DenseVector::Random(rows);
+
+    std::vector<Vector2> zeroCoords;
+    std::vector<Vector2> nonzeroCoords;
+    initSparse<Scalar>(density, refMat, m, 0, &zeroCoords, &nonzeroCoords);
+
+    if (zeroCoords.size()==0 || nonzeroCoords.size()==0)
+      return;
+
+    // test coeff and coeffRef
+    for (int i=0; i<(int)zeroCoords.size(); ++i)
+    {
+      VERIFY_IS_MUCH_SMALLER_THAN( m.coeff(zeroCoords[i].x(),zeroCoords[i].y()), eps );
+      if(internal::is_same<SparseMatrixType,SparseMatrix<Scalar,Flags> >::value)
+        VERIFY_RAISES_ASSERT( m.coeffRef(zeroCoords[0].x(),zeroCoords[0].y()) = 5 );
+    }
+    VERIFY_IS_APPROX(m, refMat);
+
+    m.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+    refMat.coeffRef(nonzeroCoords[0].x(), nonzeroCoords[0].y()) = Scalar(5);
+
+    VERIFY_IS_APPROX(m, refMat);
+      
+      // test InnerIterators and Block expressions
+      for (int t=0; t<10; ++t)
+      {
+        int j = internal::random<int>(0,cols-1);
+        int i = internal::random<int>(0,rows-1);
+        int w = internal::random<int>(1,cols-j-1);
+        int h = internal::random<int>(1,rows-i-1);
+
+        VERIFY_IS_APPROX(m.block(i,j,h,w), refMat.block(i,j,h,w));
+        for(int c=0; c<w; c++)
+        {
+          VERIFY_IS_APPROX(m.block(i,j,h,w).col(c), refMat.block(i,j,h,w).col(c));
+          for(int r=0; r<h; r++)
+          {
+            VERIFY_IS_APPROX(m.block(i,j,h,w).col(c).coeff(r), refMat.block(i,j,h,w).col(c).coeff(r));
+            VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
+          }
+        }
+        for(int r=0; r<h; r++)
+        {
+          VERIFY_IS_APPROX(m.block(i,j,h,w).row(r), refMat.block(i,j,h,w).row(r));
+          for(int c=0; c<w; c++)
+          {
+            VERIFY_IS_APPROX(m.block(i,j,h,w).row(r).coeff(c), refMat.block(i,j,h,w).row(r).coeff(c));
+            VERIFY_IS_APPROX(m.block(i,j,h,w).coeff(r,c), refMat.block(i,j,h,w).coeff(r,c));
+          }
+        }
+        
+        VERIFY_IS_APPROX(m.middleCols(j,w), refMat.middleCols(j,w));
+        VERIFY_IS_APPROX(m.middleRows(i,h), refMat.middleRows(i,h));
+        for(int r=0; r<h; r++)
+        {
+          VERIFY_IS_APPROX(m.middleCols(j,w).row(r), refMat.middleCols(j,w).row(r));
+          VERIFY_IS_APPROX(m.middleRows(i,h).row(r), refMat.middleRows(i,h).row(r));
+          for(int c=0; c<w; c++)
+          {
+            VERIFY_IS_APPROX(m.col(c).coeff(r), refMat.col(c).coeff(r));
+            VERIFY_IS_APPROX(m.row(r).coeff(c), refMat.row(r).coeff(c));
+            
+            VERIFY_IS_APPROX(m.middleCols(j,w).coeff(r,c), refMat.middleCols(j,w).coeff(r,c));
+            VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
+            if(m.middleCols(j,w).coeff(r,c) != Scalar(0))
+            {
+              VERIFY_IS_APPROX(m.middleCols(j,w).coeffRef(r,c), refMat.middleCols(j,w).coeff(r,c));
+            }
+            if(m.middleRows(i,h).coeff(r,c) != Scalar(0))
+            {
+              VERIFY_IS_APPROX(m.middleRows(i,h).coeff(r,c), refMat.middleRows(i,h).coeff(r,c));
+            }
+          }
+        }
+        for(int c=0; c<w; c++)
+        {
+          VERIFY_IS_APPROX(m.middleCols(j,w).col(c), refMat.middleCols(j,w).col(c));
+          VERIFY_IS_APPROX(m.middleRows(i,h).col(c), refMat.middleRows(i,h).col(c));
+        }
+      }
+
+      for(int c=0; c<cols; c++)
+      {
+        VERIFY_IS_APPROX(m.col(c) + m.col(c), (m + m).col(c));
+        VERIFY_IS_APPROX(m.col(c) + m.col(c), refMat.col(c) + refMat.col(c));
+      }
+
+      for(int r=0; r<rows; r++)
+      {
+        VERIFY_IS_APPROX(m.row(r) + m.row(r), (m + m).row(r));
+        VERIFY_IS_APPROX(m.row(r) + m.row(r), refMat.row(r) + refMat.row(r));
+      }
+      
+      
+      // test assertion
+      VERIFY_RAISES_ASSERT( m.coeffRef(-1,1) = 0 );
+      VERIFY_RAISES_ASSERT( m.coeffRef(0,m.cols()) = 0 );
+    }
+
+    // test insert (inner random)
+    {
+      DenseMatrix m1(rows,cols);
+      m1.setZero();
+      SparseMatrixType m2(rows,cols);
+      if(internal::random<int>()%2)
+        m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
+      for (Index j=0; j<cols; ++j)
+      {
+        for (Index k=0; k<rows/2; ++k)
+        {
+          Index i = internal::random<Index>(0,rows-1);
+          if (m1.coeff(i,j)==Scalar(0))
+            m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
+        }
+      }
+      m2.finalize();
+      VERIFY_IS_APPROX(m2,m1);
+    }
+
+    // test insert (fully random)
+    {
+      DenseMatrix m1(rows,cols);
+      m1.setZero();
+      SparseMatrixType m2(rows,cols);
+      if(internal::random<int>()%2)
+        m2.reserve(VectorXi::Constant(m2.outerSize(), 2));
+      for (int k=0; k<rows*cols; ++k)
+      {
+        Index i = internal::random<Index>(0,rows-1);
+        Index j = internal::random<Index>(0,cols-1);
+        if ((m1.coeff(i,j)==Scalar(0)) && (internal::random<int>()%2))
+          m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
+        else
+        {
+          Scalar v = internal::random<Scalar>();
+          m2.coeffRef(i,j) += v;
+          m1(i,j) += v;
+        }
+      }
+      VERIFY_IS_APPROX(m2,m1);
+    }
+    
+    // test insert (un-compressed)
+    for(int mode=0;mode<4;++mode)
+    {
+      DenseMatrix m1(rows,cols);
+      m1.setZero();
+      SparseMatrixType m2(rows,cols);
+      VectorXi r(VectorXi::Constant(m2.outerSize(), ((mode%2)==0) ? m2.innerSize() : std::max<int>(1,m2.innerSize()/8)));
+      m2.reserve(r);
+      for (int k=0; k<rows*cols; ++k)
+      {
+        Index i = internal::random<Index>(0,rows-1);
+        Index j = internal::random<Index>(0,cols-1);
+        if (m1.coeff(i,j)==Scalar(0))
+          m2.insert(i,j) = m1(i,j) = internal::random<Scalar>();
+        if(mode==3)
+          m2.reserve(r);
+      }
+      if(internal::random<int>()%2)
+        m2.makeCompressed();
+      VERIFY_IS_APPROX(m2,m1);
+    }
+
+  // test innerVector()
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    Index j0 = internal::random<Index>(0,rows-1);
+    Index j1 = internal::random<Index>(0,rows-1);
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.row(j0));
+    else
+      VERIFY_IS_APPROX(m2.innerVector(j0), refMat2.col(j0));
+
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.row(j0)+refMat2.row(j1));
+    else
+      VERIFY_IS_APPROX(m2.innerVector(j0)+m2.innerVector(j1), refMat2.col(j0)+refMat2.col(j1));
+
+    SparseMatrixType m3(rows,rows);
+    m3.reserve(VectorXi::Constant(rows,rows/2));
+    for(Index j=0; j<rows; ++j)
+      for(Index k=0; k<j; ++k)
+        m3.insertByOuterInner(j,k) = k+1;
+    for(Index j=0; j<rows; ++j)
+    {
+      VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+      if(j>0)
+        VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+    }
+    m3.makeCompressed();
+    for(Index j=0; j<rows; ++j)
+    {
+      VERIFY(j==numext::real(m3.innerVector(j).nonZeros()));
+      if(j>0)
+        VERIFY(j==numext::real(m3.innerVector(j).lastCoeff()));
+    }
+
+    //m2.innerVector(j0) = 2*m2.innerVector(j1);
+    //refMat2.col(j0) = 2*refMat2.col(j1);
+    //VERIFY_IS_APPROX(m2, refMat2);
+  }
+
+  // test innerVectors()
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    if(internal::random<float>(0,1)>0.5) m2.makeCompressed();
+    
+    Index j0 = internal::random<Index>(0,rows-2);
+    Index j1 = internal::random<Index>(0,rows-2);
+    Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(j0,0,n0,cols));
+    else
+      VERIFY_IS_APPROX(m2.innerVectors(j0,n0), refMat2.block(0,j0,rows,n0));
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+                       refMat2.middleRows(j0,n0)+refMat2.middleRows(j1,n0));
+    else
+      VERIFY_IS_APPROX(m2.innerVectors(j0,n0)+m2.innerVectors(j1,n0),
+                      refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+    
+    VERIFY_IS_APPROX(m2, refMat2);
+    
+    m2.innerVectors(j0,n0) = m2.innerVectors(j0,n0) + m2.innerVectors(j1,n0);
+    if(SparseMatrixType::IsRowMajor)
+      refMat2.middleRows(j0,n0) = (refMat2.middleRows(j0,n0) + refMat2.middleRows(j1,n0)).eval();
+    else
+      refMat2.middleCols(j0,n0) = (refMat2.middleCols(j0,n0) + refMat2.middleCols(j1,n0)).eval();
+    
+    VERIFY_IS_APPROX(m2, refMat2);
+    
+  }
+  
+  // test basic computations
+  {
+    DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM2 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM3 = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refM4 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m1(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    SparseMatrixType m3(rows, rows);
+    SparseMatrixType m4(rows, rows);
+    initSparse<Scalar>(density, refM1, m1);
+    initSparse<Scalar>(density, refM2, m2);
+    initSparse<Scalar>(density, refM3, m3);
+    initSparse<Scalar>(density, refM4, m4);
+
+    VERIFY_IS_APPROX(m1+m2, refM1+refM2);
+    VERIFY_IS_APPROX(m1+m2+m3, refM1+refM2+refM3);
+    VERIFY_IS_APPROX(m3.cwiseProduct(m1+m2), refM3.cwiseProduct(refM1+refM2));
+    VERIFY_IS_APPROX(m1*s1-m2, refM1*s1-refM2);
+
+    VERIFY_IS_APPROX(m1*=s1, refM1*=s1);
+    VERIFY_IS_APPROX(m1/=s1, refM1/=s1);
+
+    VERIFY_IS_APPROX(m1+=m2, refM1+=refM2);
+    VERIFY_IS_APPROX(m1-=m2, refM1-=refM2);
+
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.row(0).dot(refM2.row(0)));
+    else
+      VERIFY_IS_APPROX(m1.innerVector(0).dot(refM2.row(0)), refM1.col(0).dot(refM2.row(0)));
+
+    VERIFY_IS_APPROX(m1.conjugate(), refM1.conjugate());
+    VERIFY_IS_APPROX(m1.real(), refM1.real());
+
+    refM4.setRandom();
+    // sparse cwise* dense
+    VERIFY_IS_APPROX(m3.cwiseProduct(refM4), refM3.cwiseProduct(refM4));
+//     VERIFY_IS_APPROX(m3.cwise()/refM4, refM3.cwise()/refM4);
+
+    // test aliasing
+    VERIFY_IS_APPROX((m1 = -m1), (refM1 = -refM1));
+    VERIFY_IS_APPROX((m1 = m1.transpose()), (refM1 = refM1.transpose().eval()));
+    VERIFY_IS_APPROX((m1 = -m1.transpose()), (refM1 = -refM1.transpose().eval()));
+    VERIFY_IS_APPROX((m1 += -m1), (refM1 += -refM1));
+  }
+
+  // test transpose
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    VERIFY_IS_APPROX(m2.transpose().eval(), refMat2.transpose().eval());
+    VERIFY_IS_APPROX(m2.transpose(), refMat2.transpose());
+
+    VERIFY_IS_APPROX(SparseMatrixType(m2.adjoint()), refMat2.adjoint());
+  }
+
+  
+  
+  // test generic blocks
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    Index j0 = internal::random<Index>(0,rows-2);
+    Index j1 = internal::random<Index>(0,rows-2);
+    Index n0 = internal::random<Index>(1,rows-(std::max)(j0,j1));
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.block(j0,0,n0,cols), refMat2.block(j0,0,n0,cols));
+    else
+      VERIFY_IS_APPROX(m2.block(0,j0,rows,n0), refMat2.block(0,j0,rows,n0));
+    
+    if(SparseMatrixType::IsRowMajor)
+      VERIFY_IS_APPROX(m2.block(j0,0,n0,cols)+m2.block(j1,0,n0,cols),
+                      refMat2.block(j0,0,n0,cols)+refMat2.block(j1,0,n0,cols));
+    else
+      VERIFY_IS_APPROX(m2.block(0,j0,rows,n0)+m2.block(0,j1,rows,n0),
+                      refMat2.block(0,j0,rows,n0)+refMat2.block(0,j1,rows,n0));
+      
+    Index i = internal::random<Index>(0,m2.outerSize()-1);
+    if(SparseMatrixType::IsRowMajor) {
+      m2.innerVector(i) = m2.innerVector(i) * s1;
+      refMat2.row(i) = refMat2.row(i) * s1;
+      VERIFY_IS_APPROX(m2,refMat2);
+    } else {
+      m2.innerVector(i) = m2.innerVector(i) * s1;
+      refMat2.col(i) = refMat2.col(i) * s1;
+      VERIFY_IS_APPROX(m2,refMat2);
+    }
+    
+    VERIFY_IS_APPROX(DenseVector(m2.col(j0)), refMat2.col(j0));
+    VERIFY_IS_APPROX(m2.col(j0), refMat2.col(j0));
+    
+    VERIFY_IS_APPROX(RowDenseVector(m2.row(j0)), refMat2.row(j0));
+    VERIFY_IS_APPROX(m2.row(j0), refMat2.row(j0));
+    
+    VERIFY_IS_APPROX(m2.block(j0,j1,n0,n0), refMat2.block(j0,j1,n0,n0));
+    VERIFY_IS_APPROX((2*m2).block(j0,j1,n0,n0), (2*refMat2).block(j0,j1,n0,n0));
+  }
+
+  // test prune
+  {
+    SparseMatrixType m2(rows, rows);
+    DenseMatrix refM2(rows, rows);
+    refM2.setZero();
+    int countFalseNonZero = 0;
+    int countTrueNonZero = 0;
+    for (Index j=0; j<m2.outerSize(); ++j)
+    {
+      m2.startVec(j);
+      for (Index i=0; i<m2.innerSize(); ++i)
+      {
+        float x = internal::random<float>(0,1);
+        if (x<0.1)
+        {
+          // do nothing
+        }
+        else if (x<0.5)
+        {
+          countFalseNonZero++;
+          m2.insertBackByOuterInner(j,i) = Scalar(0);
+        }
+        else
+        {
+          countTrueNonZero++;
+          m2.insertBackByOuterInner(j,i) = Scalar(1);
+          if(SparseMatrixType::IsRowMajor)
+            refM2(j,i) = Scalar(1);
+          else
+            refM2(i,j) = Scalar(1);
+        }
+      }
+    }
+    m2.finalize();
+    VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros());
+    VERIFY_IS_APPROX(m2, refM2);
+    m2.prune(Scalar(1));
+    VERIFY(countTrueNonZero==m2.nonZeros());
+    VERIFY_IS_APPROX(m2, refM2);
+  }
+
+  // test setFromTriplets
+  {
+    typedef Triplet<Scalar,Index> TripletType;
+    std::vector<TripletType> triplets;
+    int ntriplets = rows*cols;
+    triplets.reserve(ntriplets);
+    DenseMatrix refMat(rows,cols);
+    refMat.setZero();
+    for(int i=0;i<ntriplets;++i)
+    {
+      Index r = internal::random<Index>(0,rows-1);
+      Index c = internal::random<Index>(0,cols-1);
+      Scalar v = internal::random<Scalar>();
+      triplets.push_back(TripletType(r,c,v));
+      refMat(r,c) += v;
+    }
+    SparseMatrixType m(rows,cols);
+    m.setFromTriplets(triplets.begin(), triplets.end());
+    VERIFY_IS_APPROX(m, refMat);
+  }
+
+  // test triangularView
+  {
+    DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
+    SparseMatrixType m2(rows, rows), m3(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    refMat3 = refMat2.template triangularView<Lower>();
+    m3 = m2.template triangularView<Lower>();
+    VERIFY_IS_APPROX(m3, refMat3);
+
+    refMat3 = refMat2.template triangularView<Upper>();
+    m3 = m2.template triangularView<Upper>();
+    VERIFY_IS_APPROX(m3, refMat3);
+
+    refMat3 = refMat2.template triangularView<UnitUpper>();
+    m3 = m2.template triangularView<UnitUpper>();
+    VERIFY_IS_APPROX(m3, refMat3);
+
+    refMat3 = refMat2.template triangularView<UnitLower>();
+    m3 = m2.template triangularView<UnitLower>();
+    VERIFY_IS_APPROX(m3, refMat3);
+
+    refMat3 = refMat2.template triangularView<StrictlyUpper>();
+    m3 = m2.template triangularView<StrictlyUpper>();
+    VERIFY_IS_APPROX(m3, refMat3);
+
+    refMat3 = refMat2.template triangularView<StrictlyLower>();
+    m3 = m2.template triangularView<StrictlyLower>();
+    VERIFY_IS_APPROX(m3, refMat3);
+  }
+  
+  // test selfadjointView
+  if(!SparseMatrixType::IsRowMajor)
+  {
+    DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
+    SparseMatrixType m2(rows, rows), m3(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    refMat3 = refMat2.template selfadjointView<Lower>();
+    m3 = m2.template selfadjointView<Lower>();
+    VERIFY_IS_APPROX(m3, refMat3);
+  }
+  
+  // test sparseView
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
+  }
+
+  // test diagonal
+  {
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType m2(rows, rows);
+    initSparse<Scalar>(density, refMat2, m2);
+    VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval());
+  }
+  
+  // test conservative resize
+  {
+      std::vector< std::pair<Index,Index> > inc;
+      inc.push_back(std::pair<Index,Index>(-3,-2));
+      inc.push_back(std::pair<Index,Index>(0,0));
+      inc.push_back(std::pair<Index,Index>(3,2));
+      inc.push_back(std::pair<Index,Index>(3,0));
+      inc.push_back(std::pair<Index,Index>(0,3));
+      
+      for(size_t i = 0; i< inc.size(); i++) {
+        Index incRows = inc[i].first;
+        Index incCols = inc[i].second;
+        SparseMatrixType m1(rows, cols);
+        DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols);
+        initSparse<Scalar>(density, refMat1, m1);
+        
+        m1.conservativeResize(rows+incRows, cols+incCols);
+        refMat1.conservativeResize(rows+incRows, cols+incCols);
+        if (incRows > 0) refMat1.bottomRows(incRows).setZero();
+        if (incCols > 0) refMat1.rightCols(incCols).setZero();
+        
+        VERIFY_IS_APPROX(m1, refMat1);
+        
+        // Insert new values
+        if (incRows > 0) 
+          m1.insert(m1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1;
+        if (incCols > 0) 
+          m1.insert(0, m1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1;
+          
+        VERIFY_IS_APPROX(m1, refMat1);
+          
+          
+      }
+  }
+
+  // test Identity matrix
+  {
+    DenseMatrix refMat1 = DenseMatrix::Identity(rows, rows);
+    SparseMatrixType m1(rows, rows);
+    m1.setIdentity();
+    VERIFY_IS_APPROX(m1, refMat1);
+  }
+}
+
+void test_sparse_basic()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    int s = Eigen::internal::random<int>(1,50);
+    EIGEN_UNUSED_VARIABLE(s);
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(8, 8)) ));
+    CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, ColMajor>(s, s)) ));
+    CALL_SUBTEST_2(( sparse_basic(SparseMatrix<std::complex<double>, RowMajor>(s, s)) ));
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double>(s, s)) ));
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,long int>(s, s)) ));
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,long int>(s, s)) ));
+    
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,ColMajor,short int>(short(s), short(s))) ));
+    CALL_SUBTEST_1(( sparse_basic(SparseMatrix<double,RowMajor,short int>(short(s), short(s))) ));
+  }
+}
diff --git a/test/sparse_permutations.cpp b/test/sparse_permutations.cpp
new file mode 100644
index 0000000..e4ce1d6
--- /dev/null
+++ b/test/sparse_permutations.cpp
@@ -0,0 +1,187 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<int OtherStorage, typename SparseMatrixType> void sparse_permutations(const SparseMatrixType& ref)
+{
+  typedef typename SparseMatrixType::Index Index;
+
+  const Index rows = ref.rows();
+  const Index cols = ref.cols();
+  typedef typename SparseMatrixType::Scalar Scalar;
+  typedef typename SparseMatrixType::Index Index;
+  typedef SparseMatrix<Scalar, OtherStorage, Index> OtherSparseMatrixType;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Index,Dynamic,1> VectorI;
+  
+  double density = (std::max)(8./(rows*cols), 0.01);
+  
+  SparseMatrixType mat(rows, cols), up(rows,cols), lo(rows,cols);
+  OtherSparseMatrixType res;
+  DenseMatrix mat_d = DenseMatrix::Zero(rows, cols), up_sym_d, lo_sym_d, res_d;
+  
+  initSparse<Scalar>(density, mat_d, mat, 0);
+
+  up = mat.template triangularView<Upper>();
+  lo = mat.template triangularView<Lower>();
+  
+  up_sym_d = mat_d.template selfadjointView<Upper>();
+  lo_sym_d = mat_d.template selfadjointView<Lower>();
+  
+  VERIFY_IS_APPROX(mat, mat_d);
+  VERIFY_IS_APPROX(up, DenseMatrix(mat_d.template triangularView<Upper>()));
+  VERIFY_IS_APPROX(lo, DenseMatrix(mat_d.template triangularView<Lower>()));
+  
+  PermutationMatrix<Dynamic> p, p_null;
+  VectorI pi;
+  randomPermutationVector(pi, cols);
+  p.indices() = pi;
+
+  res = mat*p;
+  res_d = mat_d*p;
+  VERIFY(res.isApprox(res_d) && "mat*p");
+
+  res = p*mat;
+  res_d = p*mat_d;
+  VERIFY(res.isApprox(res_d) && "p*mat");
+
+  res = mat*p.inverse();
+  res_d = mat*p.inverse();
+  VERIFY(res.isApprox(res_d) && "mat*inv(p)");
+
+  res = p.inverse()*mat;
+  res_d = p.inverse()*mat_d;
+  VERIFY(res.isApprox(res_d) && "inv(p)*mat");
+
+  res = mat.twistedBy(p);
+  res_d = (p * mat_d) * p.inverse();
+  VERIFY(res.isApprox(res_d) && "p*mat*inv(p)");
+
+  
+  res = mat.template selfadjointView<Upper>().twistedBy(p_null);
+  res_d = up_sym_d;
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
+  
+  res = mat.template selfadjointView<Lower>().twistedBy(p_null);
+  res_d = lo_sym_d;
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
+  
+  
+  res = up.template selfadjointView<Upper>().twistedBy(p_null);
+  res_d = up_sym_d;
+  VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
+  
+  res = lo.template selfadjointView<Lower>().twistedBy(p_null);
+  res_d = lo_sym_d;
+  VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
+
+
+  res = mat.template selfadjointView<Upper>();
+  res_d = up_sym_d;
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper to full");
+
+  res = mat.template selfadjointView<Lower>();
+  res_d = lo_sym_d;
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower to full");
+
+  res = up.template selfadjointView<Upper>();
+  res_d = up_sym_d;
+  VERIFY(res.isApprox(res_d) && "upper selfadjoint to full");
+
+  res = lo.template selfadjointView<Lower>();
+  res_d = lo_sym_d;
+  VERIFY(res.isApprox(res_d) && "lower selfadjoint full");
+
+
+  res.template selfadjointView<Upper>() = mat.template selfadjointView<Upper>();
+  res_d = up_sym_d.template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper to upper");
+
+  res.template selfadjointView<Lower>() = mat.template selfadjointView<Upper>();
+  res_d = up_sym_d.template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper to lower");
+
+  res.template selfadjointView<Upper>() = mat.template selfadjointView<Lower>();
+  res_d = lo_sym_d.template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower to upper");
+
+  res.template selfadjointView<Lower>() = mat.template selfadjointView<Lower>();
+  res_d = lo_sym_d.template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower to lower");
+
+  
+  
+  res.template selfadjointView<Upper>() = mat.template selfadjointView<Upper>().twistedBy(p);
+  res_d = ((p * up_sym_d) * p.inverse()).eval().template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper twisted to upper");
+  
+  res.template selfadjointView<Upper>() = mat.template selfadjointView<Lower>().twistedBy(p);
+  res_d = ((p * lo_sym_d) * p.inverse()).eval().template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower twisted to upper");
+  
+  res.template selfadjointView<Lower>() = mat.template selfadjointView<Lower>().twistedBy(p);
+  res_d = ((p * lo_sym_d) * p.inverse()).eval().template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower twisted to lower");
+  
+  res.template selfadjointView<Lower>() = mat.template selfadjointView<Upper>().twistedBy(p);
+  res_d = ((p * up_sym_d) * p.inverse()).eval().template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper twisted to lower");
+  
+  
+  res.template selfadjointView<Upper>() = up.template selfadjointView<Upper>().twistedBy(p);
+  res_d = ((p * up_sym_d) * p.inverse()).eval().template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to upper");
+  
+  res.template selfadjointView<Upper>() = lo.template selfadjointView<Lower>().twistedBy(p);
+  res_d = ((p * lo_sym_d) * p.inverse()).eval().template triangularView<Upper>();
+  VERIFY(res.isApprox(res_d) && "lower selfadjoint twisted to upper");
+  
+  res.template selfadjointView<Lower>() = lo.template selfadjointView<Lower>().twistedBy(p);
+  res_d = ((p * lo_sym_d) * p.inverse()).eval().template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "lower selfadjoint twisted to lower");
+  
+  res.template selfadjointView<Lower>() = up.template selfadjointView<Upper>().twistedBy(p);
+  res_d = ((p * up_sym_d) * p.inverse()).eval().template triangularView<Lower>();
+  VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to lower");
+
+  
+  res = mat.template selfadjointView<Upper>().twistedBy(p);
+  res_d = (p * up_sym_d) * p.inverse();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint upper twisted to full");
+  
+  res = mat.template selfadjointView<Lower>().twistedBy(p);
+  res_d = (p * lo_sym_d) * p.inverse();
+  VERIFY(res.isApprox(res_d) && "full selfadjoint lower twisted to full");
+  
+  res = up.template selfadjointView<Upper>().twistedBy(p);
+  res_d = (p * up_sym_d) * p.inverse();
+  VERIFY(res.isApprox(res_d) && "upper selfadjoint twisted to full");
+  
+  res = lo.template selfadjointView<Lower>().twistedBy(p);
+  res_d = (p * lo_sym_d) * p.inverse();
+  VERIFY(res.isApprox(res_d) && "lower selfadjoint twisted to full");
+}
+
+template<typename Scalar> void sparse_permutations_all(int size)
+{
+  CALL_SUBTEST(( sparse_permutations<ColMajor>(SparseMatrix<Scalar, ColMajor>(size,size)) ));
+  CALL_SUBTEST(( sparse_permutations<ColMajor>(SparseMatrix<Scalar, RowMajor>(size,size)) ));
+  CALL_SUBTEST(( sparse_permutations<RowMajor>(SparseMatrix<Scalar, ColMajor>(size,size)) ));
+  CALL_SUBTEST(( sparse_permutations<RowMajor>(SparseMatrix<Scalar, RowMajor>(size,size)) ));
+}
+
+void test_sparse_permutations()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    int s = Eigen::internal::random<int>(1,50);
+    CALL_SUBTEST_1((  sparse_permutations_all<double>(s) ));
+    CALL_SUBTEST_2((  sparse_permutations_all<std::complex<double> >(s) ));
+  }
+}
diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp
new file mode 100644
index 0000000..a2ea9d5
--- /dev/null
+++ b/test/sparse_product.cpp
@@ -0,0 +1,252 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename SparseMatrixType, typename DenseMatrix, bool IsRowMajor=SparseMatrixType::IsRowMajor> struct test_outer;
+
+template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,false> {
+  static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
+    typedef typename SparseMatrixType::Index Index;
+    Index c  = internal::random<Index>(0,m2.cols()-1);
+    Index c1 = internal::random<Index>(0,m2.cols()-1);
+    VERIFY_IS_APPROX(m4=m2.col(c)*refMat2.col(c1).transpose(), refMat4=refMat2.col(c)*refMat2.col(c1).transpose());
+    VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.col(c).transpose(), refMat4=refMat2.col(c1)*refMat2.col(c).transpose());
+  }
+};
+
+template<typename SparseMatrixType, typename DenseMatrix> struct test_outer<SparseMatrixType,DenseMatrix,true> {
+  static void run(SparseMatrixType& m2, SparseMatrixType& m4, DenseMatrix& refMat2, DenseMatrix& refMat4) {
+    typedef typename SparseMatrixType::Index Index;
+    Index r  = internal::random<Index>(0,m2.rows()-1);
+    Index c1 = internal::random<Index>(0,m2.cols()-1);
+    VERIFY_IS_APPROX(m4=m2.row(r).transpose()*refMat2.col(c1).transpose(), refMat4=refMat2.row(r).transpose()*refMat2.col(c1).transpose());
+    VERIFY_IS_APPROX(m4=refMat2.col(c1)*m2.row(r), refMat4=refMat2.col(c1)*refMat2.row(r));
+  }
+};
+
+// (m2,m4,refMat2,refMat4,dv1);
+//     VERIFY_IS_APPROX(m4=m2.innerVector(c)*dv1.transpose(), refMat4=refMat2.colVector(c)*dv1.transpose());
+//     VERIFY_IS_APPROX(m4=dv1*mcm.col(c).transpose(), refMat4=dv1*refMat2.col(c).transpose());
+
+template<typename SparseMatrixType> void sparse_product()
+{
+  typedef typename SparseMatrixType::Index Index;
+  Index n = 100;
+  const Index rows  = internal::random<Index>(1,n);
+  const Index cols  = internal::random<Index>(1,n);
+  const Index depth = internal::random<Index>(1,n);
+  typedef typename SparseMatrixType::Scalar Scalar;
+  enum { Flags = SparseMatrixType::Flags };
+
+  double density = (std::max)(8./(rows*cols), 0.1);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  typedef Matrix<Scalar,1,Dynamic> RowDenseVector;
+  typedef SparseVector<Scalar,0,Index> ColSpVector;
+  typedef SparseVector<Scalar,RowMajor,Index> RowSpVector;
+
+  Scalar s1 = internal::random<Scalar>();
+  Scalar s2 = internal::random<Scalar>();
+
+  // test matrix-matrix product
+  {
+    DenseMatrix refMat2  = DenseMatrix::Zero(rows, depth);
+    DenseMatrix refMat2t = DenseMatrix::Zero(depth, rows);
+    DenseMatrix refMat3  = DenseMatrix::Zero(depth, cols);
+    DenseMatrix refMat3t = DenseMatrix::Zero(cols, depth);
+    DenseMatrix refMat4  = DenseMatrix::Zero(rows, cols);
+    DenseMatrix refMat4t = DenseMatrix::Zero(cols, rows);
+    DenseMatrix refMat5  = DenseMatrix::Random(depth, cols);
+    DenseMatrix refMat6  = DenseMatrix::Random(rows, rows);
+    DenseMatrix dm4 = DenseMatrix::Zero(rows, rows);
+//     DenseVector dv1 = DenseVector::Random(rows);
+    SparseMatrixType m2 (rows, depth);
+    SparseMatrixType m2t(depth, rows);
+    SparseMatrixType m3 (depth, cols);
+    SparseMatrixType m3t(cols, depth);
+    SparseMatrixType m4 (rows, cols);
+    SparseMatrixType m4t(cols, rows);
+    SparseMatrixType m6(rows, rows);
+    initSparse(density, refMat2,  m2);
+    initSparse(density, refMat2t, m2t);
+    initSparse(density, refMat3,  m3);
+    initSparse(density, refMat3t, m3t);
+    initSparse(density, refMat4,  m4);
+    initSparse(density, refMat4t, m4t);
+    initSparse(density, refMat6, m6);
+
+//     int c = internal::random<int>(0,depth-1);
+
+    // sparse * sparse
+    VERIFY_IS_APPROX(m4=m2*m3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(m4=m2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3);
+    VERIFY_IS_APPROX(m4=m2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
+    VERIFY_IS_APPROX(m4=m2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose());
+
+    VERIFY_IS_APPROX(m4 = m2*m3/s1, refMat4 = refMat2*refMat3/s1);
+    VERIFY_IS_APPROX(m4 = m2*m3*s1, refMat4 = refMat2*refMat3*s1);
+    VERIFY_IS_APPROX(m4 = s2*m2*m3*s1, refMat4 = s2*refMat2*refMat3*s1);
+
+    VERIFY_IS_APPROX(m4=(m2*m3).pruned(0), refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(m4=(m2t.transpose()*m3).pruned(0), refMat4=refMat2t.transpose()*refMat3);
+    VERIFY_IS_APPROX(m4=(m2t.transpose()*m3t.transpose()).pruned(0), refMat4=refMat2t.transpose()*refMat3t.transpose());
+    VERIFY_IS_APPROX(m4=(m2*m3t.transpose()).pruned(0), refMat4=refMat2*refMat3t.transpose());
+
+    // test aliasing
+    m4 = m2; refMat4 = refMat2;
+    VERIFY_IS_APPROX(m4=m4*m3, refMat4=refMat4*refMat3);
+
+    // sparse * dense
+    VERIFY_IS_APPROX(dm4=m2*refMat3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(dm4=m2*refMat3t.transpose(), refMat4=refMat2*refMat3t.transpose());
+    VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3, refMat4=refMat2t.transpose()*refMat3);
+    VERIFY_IS_APPROX(dm4=m2t.transpose()*refMat3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
+
+    VERIFY_IS_APPROX(dm4=m2*(refMat3+refMat3), refMat4=refMat2*(refMat3+refMat3));
+    VERIFY_IS_APPROX(dm4=m2t.transpose()*(refMat3+refMat5)*0.5, refMat4=refMat2t.transpose()*(refMat3+refMat5)*0.5);
+
+    // dense * sparse
+    VERIFY_IS_APPROX(dm4=refMat2*m3, refMat4=refMat2*refMat3);
+    VERIFY_IS_APPROX(dm4=refMat2*m3t.transpose(), refMat4=refMat2*refMat3t.transpose());
+    VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3, refMat4=refMat2t.transpose()*refMat3);
+    VERIFY_IS_APPROX(dm4=refMat2t.transpose()*m3t.transpose(), refMat4=refMat2t.transpose()*refMat3t.transpose());
+
+    // sparse * dense and dense * sparse outer product
+    test_outer<SparseMatrixType,DenseMatrix>::run(m2,m4,refMat2,refMat4);
+
+    VERIFY_IS_APPROX(m6=m6*m6, refMat6=refMat6*refMat6);
+    
+    // sparse matrix * sparse vector
+    ColSpVector cv0(cols), cv1;
+    DenseVector dcv0(cols), dcv1;
+    initSparse(2*density,dcv0, cv0);
+    
+    RowSpVector rv0(depth), rv1;
+    RowDenseVector drv0(depth), drv1(rv1);
+    initSparse(2*density,drv0, rv0);
+    
+    VERIFY_IS_APPROX(cv1=rv0*m3, dcv1=drv0*refMat3);
+    VERIFY_IS_APPROX(rv1=rv0*m3, drv1=drv0*refMat3);
+    VERIFY_IS_APPROX(cv1=m3*cv0, dcv1=refMat3*dcv0);
+    VERIFY_IS_APPROX(cv1=m3t.adjoint()*cv0, dcv1=refMat3t.adjoint()*dcv0);
+    VERIFY_IS_APPROX(rv1=m3*cv0, drv1=refMat3*dcv0);
+  }
+  
+  // test matrix - diagonal product
+  {
+    DenseMatrix refM2 = DenseMatrix::Zero(rows, cols);
+    DenseMatrix refM3 = DenseMatrix::Zero(rows, cols);
+    DenseMatrix d3 = DenseMatrix::Zero(rows, cols);
+    DiagonalMatrix<Scalar,Dynamic> d1(DenseVector::Random(cols));
+    DiagonalMatrix<Scalar,Dynamic> d2(DenseVector::Random(rows));
+    SparseMatrixType m2(rows, cols);
+    SparseMatrixType m3(rows, cols);
+    initSparse<Scalar>(density, refM2, m2);
+    initSparse<Scalar>(density, refM3, m3);
+    VERIFY_IS_APPROX(m3=m2*d1, refM3=refM2*d1);
+    VERIFY_IS_APPROX(m3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
+    VERIFY_IS_APPROX(m3=d2*m2, refM3=d2*refM2);
+    VERIFY_IS_APPROX(m3=d1*m2.transpose(), refM3=d1*refM2.transpose());
+    
+    // also check with a SparseWrapper:
+    DenseVector v1 = DenseVector::Random(cols);
+    DenseVector v2 = DenseVector::Random(rows);
+    VERIFY_IS_APPROX(m3=m2*v1.asDiagonal(), refM3=refM2*v1.asDiagonal());
+    VERIFY_IS_APPROX(m3=m2.transpose()*v2.asDiagonal(), refM3=refM2.transpose()*v2.asDiagonal());
+    VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2, refM3=v2.asDiagonal()*refM2);
+    VERIFY_IS_APPROX(m3=v1.asDiagonal()*m2.transpose(), refM3=v1.asDiagonal()*refM2.transpose());
+    
+    VERIFY_IS_APPROX(m3=v2.asDiagonal()*m2*v1.asDiagonal(), refM3=v2.asDiagonal()*refM2*v1.asDiagonal());
+    
+    // evaluate to a dense matrix to check the .row() and .col() iterator functions
+    VERIFY_IS_APPROX(d3=m2*d1, refM3=refM2*d1);
+    VERIFY_IS_APPROX(d3=m2.transpose()*d2, refM3=refM2.transpose()*d2);
+    VERIFY_IS_APPROX(d3=d2*m2, refM3=d2*refM2);
+    VERIFY_IS_APPROX(d3=d1*m2.transpose(), refM3=d1*refM2.transpose());
+  }
+
+  // test self adjoint products
+  {
+    DenseMatrix b = DenseMatrix::Random(rows, rows);
+    DenseMatrix x = DenseMatrix::Random(rows, rows);
+    DenseMatrix refX = DenseMatrix::Random(rows, rows);
+    DenseMatrix refUp = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refLo = DenseMatrix::Zero(rows, rows);
+    DenseMatrix refS = DenseMatrix::Zero(rows, rows);
+    SparseMatrixType mUp(rows, rows);
+    SparseMatrixType mLo(rows, rows);
+    SparseMatrixType mS(rows, rows);
+    do {
+      initSparse<Scalar>(density, refUp, mUp, ForceRealDiag|/*ForceNonZeroDiag|*/MakeUpperTriangular);
+    } while (refUp.isZero());
+    refLo = refUp.adjoint();
+    mLo = mUp.adjoint();
+    refS = refUp + refLo;
+    refS.diagonal() *= 0.5;
+    mS = mUp + mLo;
+    // TODO be able to address the diagonal....
+    for (int k=0; k<mS.outerSize(); ++k)
+      for (typename SparseMatrixType::InnerIterator it(mS,k); it; ++it)
+        if (it.index() == k)
+          it.valueRef() *= 0.5;
+
+    VERIFY_IS_APPROX(refS.adjoint(), refS);
+    VERIFY_IS_APPROX(mS.adjoint(), mS);
+    VERIFY_IS_APPROX(mS, refS);
+    VERIFY_IS_APPROX(x=mS*b, refX=refS*b);
+
+    VERIFY_IS_APPROX(x=mUp.template selfadjointView<Upper>()*b, refX=refS*b);
+    VERIFY_IS_APPROX(x=mLo.template selfadjointView<Lower>()*b, refX=refS*b);
+    VERIFY_IS_APPROX(x=mS.template selfadjointView<Upper|Lower>()*b, refX=refS*b);
+    
+    // sparse selfadjointView * sparse 
+    SparseMatrixType mSres(rows,rows);
+    VERIFY_IS_APPROX(mSres = mLo.template selfadjointView<Lower>()*mS,
+                     refX = refLo.template selfadjointView<Lower>()*refS);
+    // sparse * sparse selfadjointview
+    VERIFY_IS_APPROX(mSres = mS * mLo.template selfadjointView<Lower>(),
+                     refX = refS * refLo.template selfadjointView<Lower>());
+  }
+  
+}
+
+// New test for Bug in SparseTimeDenseProduct
+template<typename SparseMatrixType, typename DenseMatrixType> void sparse_product_regression_test()
+{
+  // This code does not compile with afflicted versions of the bug
+  SparseMatrixType sm1(3,2);
+  DenseMatrixType m2(2,2);
+  sm1.setZero();
+  m2.setZero();
+
+  DenseMatrixType m3 = sm1*m2;
+
+
+  // This code produces a segfault with afflicted versions of another SparseTimeDenseProduct
+  // bug
+
+  SparseMatrixType sm2(20000,2);
+  sm2.setZero();
+  DenseMatrixType m4(sm2*m2);
+
+  VERIFY_IS_APPROX( m4(0,0), 0.0 );
+}
+
+void test_sparse_product()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,ColMajor> >()) );
+    CALL_SUBTEST_1( (sparse_product<SparseMatrix<double,RowMajor> >()) );
+    CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, ColMajor > >()) );
+    CALL_SUBTEST_2( (sparse_product<SparseMatrix<std::complex<double>, RowMajor > >()) );
+    CALL_SUBTEST_3( (sparse_product<SparseMatrix<float,ColMajor,long int> >()) );
+    CALL_SUBTEST_4( (sparse_product_regression_test<SparseMatrix<double,RowMajor>, Matrix<double, Dynamic, Dynamic, RowMajor> >()) );
+  }
+}
diff --git a/test/sparse_solver.h b/test/sparse_solver.h
new file mode 100644
index 0000000..59d77da
--- /dev/null
+++ b/test/sparse_solver.h
@@ -0,0 +1,362 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+#include <Eigen/SparseCore>
+
+template<typename Solver, typename Rhs, typename DenseMat, typename DenseRhs>
+void check_sparse_solving(Solver& solver, const typename Solver::MatrixType& A, const Rhs& b, const DenseMat& dA, const DenseRhs& db)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+
+  DenseRhs refX = dA.lu().solve(db);
+  {
+    Rhs x(b.rows(), b.cols());
+    Rhs oldb = b;
+
+    solver.compute(A);
+    if (solver.info() != Success)
+    {
+      std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
+      exit(0);
+      return;
+    }
+    x = solver.solve(b);
+    if (solver.info() != Success)
+    {
+      std::cerr << "sparse solver testing: solving failed\n";
+      return;
+    }
+    VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+
+    VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+    x.setZero();
+    // test the analyze/factorize API
+    solver.analyzePattern(A);
+    solver.factorize(A);
+    if (solver.info() != Success)
+    {
+      std::cerr << "sparse solver testing: factorization failed (check_sparse_solving)\n";
+      exit(0);
+      return;
+    }
+    x = solver.solve(b);
+    if (solver.info() != Success)
+    {
+      std::cerr << "sparse solver testing: solving failed\n";
+      return;
+    }
+    VERIFY(oldb.isApprox(b) && "sparse solver testing: the rhs should not be modified!");
+
+    VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+  }
+  
+  // test dense Block as the result and rhs:
+  {
+    DenseRhs x(db.rows(), db.cols());
+    DenseRhs oldb(db);
+    x.setZero();
+    x.block(0,0,x.rows(),x.cols()) = solver.solve(db.block(0,0,db.rows(),db.cols()));
+    VERIFY(oldb.isApprox(db) && "sparse solver testing: the rhs should not be modified!");
+    VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+  }
+}
+
+template<typename Solver, typename Rhs>
+void check_sparse_solving_real_cases(Solver& solver, const typename Solver::MatrixType& A, const Rhs& b, const Rhs& refX)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef typename Mat::RealScalar RealScalar;
+  
+  Rhs x(b.rows(), b.cols());
+  
+  solver.compute(A);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse solver testing: factorization failed (check_sparse_solving_real_cases)\n";
+    exit(0);
+    return;
+  }
+  x = solver.solve(b);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse solver testing: solving failed\n";
+    return;
+  }
+  
+  RealScalar res_error;
+  // Compute the norm of the relative error
+  if(refX.size() != 0)
+    res_error = (refX - x).norm()/refX.norm();
+  else
+  { 
+    // Compute the relative residual norm
+    res_error = (b - A * x).norm()/b.norm();
+  }
+  if (res_error > test_precision<Scalar>() ){
+    std::cerr << "Test " << g_test_stack.back() << " failed in "EI_PP_MAKE_STRING(__FILE__) 
+    << " (" << EI_PP_MAKE_STRING(__LINE__) << ")" << std::endl << std::endl;
+    abort();
+  }
+  
+}
+template<typename Solver, typename DenseMat>
+void check_sparse_determinant(Solver& solver, const typename Solver::MatrixType& A, const DenseMat& dA)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  
+  solver.compute(A);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse solver testing: factorization failed (check_sparse_determinant)\n";
+    return;
+  }
+
+  Scalar refDet = dA.determinant();
+  VERIFY_IS_APPROX(refDet,solver.determinant());
+}
+template<typename Solver, typename DenseMat>
+void check_sparse_abs_determinant(Solver& solver, const typename Solver::MatrixType& A, const DenseMat& dA)
+{
+  using std::abs;
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  
+  solver.compute(A);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse solver testing: factorization failed (check_sparse_abs_determinant)\n";
+    return;
+  }
+
+  Scalar refDet = abs(dA.determinant());
+  VERIFY_IS_APPROX(refDet,solver.absDeterminant());
+}
+
+template<typename Solver, typename DenseMat>
+int generate_sparse_spd_problem(Solver& , typename Solver::MatrixType& A, typename Solver::MatrixType& halfA, DenseMat& dA, int maxSize = 300)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+
+  int size = internal::random<int>(1,maxSize);
+  double density = (std::max)(8./(size*size), 0.01);
+
+  Mat M(size, size);
+  DenseMatrix dM(size, size);
+
+  initSparse<Scalar>(density, dM, M, ForceNonZeroDiag);
+
+  A = M * M.adjoint();
+  dA = dM * dM.adjoint();
+  
+  halfA.resize(size,size);
+  if(Solver::UpLo==(Lower|Upper))
+    halfA = A;
+  else
+    halfA.template selfadjointView<Solver::UpLo>().rankUpdate(M);
+  
+  return size;
+}
+
+
+#ifdef TEST_REAL_CASES
+template<typename Scalar>
+inline std::string get_matrixfolder()
+{
+  std::string mat_folder = TEST_REAL_CASES; 
+  if( internal::is_same<Scalar, std::complex<float> >::value || internal::is_same<Scalar, std::complex<double> >::value )
+    mat_folder  = mat_folder + static_cast<std::string>("/complex/");
+  else
+    mat_folder = mat_folder + static_cast<std::string>("/real/");
+  return mat_folder;
+}
+#endif
+
+template<typename Solver> void check_sparse_spd_solving(Solver& solver)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef SparseMatrix<Scalar,ColMajor> SpMat;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+
+  // generate the problem
+  Mat A, halfA;
+  DenseMatrix dA;
+  for (int i = 0; i < g_repeat; i++) {
+    int size = generate_sparse_spd_problem(solver, A, halfA, dA);
+
+    // generate the right hand sides
+    int rhsCols = internal::random<int>(1,16);
+    double density = (std::max)(8./(size*rhsCols), 0.1);
+    SpMat B(size,rhsCols);
+    DenseVector b = DenseVector::Random(size);
+    DenseMatrix dB(size,rhsCols);
+    initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+  
+    check_sparse_solving(solver, A,     b,  dA, b);
+    check_sparse_solving(solver, halfA, b,  dA, b);
+    check_sparse_solving(solver, A,     dB, dA, dB);
+    check_sparse_solving(solver, halfA, dB, dA, dB);
+    check_sparse_solving(solver, A,     B,  dA, dB);
+    check_sparse_solving(solver, halfA, B,  dA, dB);
+    
+    // check only once
+    if(i==0)
+    {
+      b = DenseVector::Zero(size);
+      check_sparse_solving(solver, A, b, dA, b);
+    }
+  }
+  
+  // First, get the folder 
+#ifdef TEST_REAL_CASES  
+  if (internal::is_same<Scalar, float>::value 
+      || internal::is_same<Scalar, std::complex<float> >::value)
+    return ;
+  
+  std::string mat_folder = get_matrixfolder<Scalar>();
+  MatrixMarketIterator<Scalar> it(mat_folder);
+  for (; it; ++it)
+  {
+    if (it.sym() == SPD){
+      Mat halfA;
+      PermutationMatrix<Dynamic, Dynamic, Index> pnull;
+      halfA.template selfadjointView<Solver::UpLo>() = it.matrix().template triangularView<Eigen::Lower>().twistedBy(pnull);
+      
+      std::cout<< " ==== SOLVING WITH MATRIX " << it.matname() << " ==== \n";
+      check_sparse_solving_real_cases(solver, it.matrix(), it.rhs(), it.refX());
+      check_sparse_solving_real_cases(solver, halfA, it.rhs(), it.refX());
+    }
+  }
+#endif
+}
+
+template<typename Solver> void check_sparse_spd_determinant(Solver& solver)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+
+  // generate the problem
+  Mat A, halfA;
+  DenseMatrix dA;
+  generate_sparse_spd_problem(solver, A, halfA, dA, 30);
+  
+  for (int i = 0; i < g_repeat; i++) {
+    check_sparse_determinant(solver, A,     dA);
+    check_sparse_determinant(solver, halfA, dA );
+  }
+}
+
+template<typename Solver, typename DenseMat>
+int generate_sparse_square_problem(Solver&, typename Solver::MatrixType& A, DenseMat& dA, int maxSize = 300)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+
+  int size = internal::random<int>(1,maxSize);
+  double density = (std::max)(8./(size*size), 0.01);
+  
+  A.resize(size,size);
+  dA.resize(size,size);
+
+  initSparse<Scalar>(density, dA, A, ForceNonZeroDiag);
+  
+  return size;
+}
+
+template<typename Solver> void check_sparse_square_solving(Solver& solver)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef SparseMatrix<Scalar,ColMajor> SpMat;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+
+  int rhsCols = internal::random<int>(1,16);
+
+  Mat A;
+  DenseMatrix dA;
+  for (int i = 0; i < g_repeat; i++) {
+    int size = generate_sparse_square_problem(solver, A, dA);
+
+    A.makeCompressed();
+    DenseVector b = DenseVector::Random(size);
+    DenseMatrix dB(size,rhsCols);
+    SpMat B(size,rhsCols);
+    double density = (std::max)(8./(size*rhsCols), 0.1);
+    initSparse<Scalar>(density, dB, B, ForceNonZeroDiag);
+    B.makeCompressed();
+    check_sparse_solving(solver, A, b,  dA, b);
+    check_sparse_solving(solver, A, dB, dA, dB);
+    check_sparse_solving(solver, A, B,  dA, dB);
+    
+    // check only once
+    if(i==0)
+    {
+      b = DenseVector::Zero(size);
+      check_sparse_solving(solver, A, b, dA, b);
+    }
+  }
+  
+  // First, get the folder 
+#ifdef TEST_REAL_CASES
+  if (internal::is_same<Scalar, float>::value 
+      || internal::is_same<Scalar, std::complex<float> >::value)
+    return ;
+  
+  std::string mat_folder = get_matrixfolder<Scalar>();
+  MatrixMarketIterator<Scalar> it(mat_folder);
+  for (; it; ++it)
+  {
+    std::cout<< " ==== SOLVING WITH MATRIX " << it.matname() << " ==== \n";
+    check_sparse_solving_real_cases(solver, it.matrix(), it.rhs(), it.refX());
+  }
+#endif
+
+}
+
+template<typename Solver> void check_sparse_square_determinant(Solver& solver)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+
+  // generate the problem
+  Mat A;
+  DenseMatrix dA;
+  generate_sparse_square_problem(solver, A, dA, 30);
+  A.makeCompressed();
+  for (int i = 0; i < g_repeat; i++) {
+    check_sparse_determinant(solver, A, dA);
+  }
+}
+
+template<typename Solver> void check_sparse_square_abs_determinant(Solver& solver)
+{
+  typedef typename Solver::MatrixType Mat;
+  typedef typename Mat::Scalar Scalar;
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+
+  // generate the problem
+  Mat A;
+  DenseMatrix dA;
+  generate_sparse_square_problem(solver, A, dA, 30);
+  A.makeCompressed();
+  for (int i = 0; i < g_repeat; i++) {
+    check_sparse_abs_determinant(solver, A, dA);
+  }
+}
+
diff --git a/test/sparse_solvers.cpp b/test/sparse_solvers.cpp
new file mode 100644
index 0000000..3a8873d
--- /dev/null
+++ b/test/sparse_solvers.cpp
@@ -0,0 +1,112 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename Scalar> void
+initSPD(double density,
+        Matrix<Scalar,Dynamic,Dynamic>& refMat,
+        SparseMatrix<Scalar>& sparseMat)
+{
+  Matrix<Scalar,Dynamic,Dynamic> aux(refMat.rows(),refMat.cols());
+  initSparse(density,refMat,sparseMat);
+  refMat = refMat * refMat.adjoint();
+  for (int k=0; k<2; ++k)
+  {
+    initSparse(density,aux,sparseMat,ForceNonZeroDiag);
+    refMat += aux * aux.adjoint();
+  }
+  sparseMat.setZero();
+  for (int j=0 ; j<sparseMat.cols(); ++j)
+    for (int i=j ; i<sparseMat.rows(); ++i)
+      if (refMat(i,j)!=Scalar(0))
+        sparseMat.insert(i,j) = refMat(i,j);
+  sparseMat.finalize();
+}
+
+template<typename Scalar> void sparse_solvers(int rows, int cols)
+{
+  double density = (std::max)(8./(rows*cols), 0.01);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  // Scalar eps = 1e-6;
+
+  DenseVector vec1 = DenseVector::Random(rows);
+
+  std::vector<Vector2i> zeroCoords;
+  std::vector<Vector2i> nonzeroCoords;
+
+  // test triangular solver
+  {
+    DenseVector vec2 = vec1, vec3 = vec1;
+    SparseMatrix<Scalar> m2(rows, cols);
+    DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols);
+
+    // lower - dense
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template triangularView<Lower>().solve(vec2),
+                     m2.template triangularView<Lower>().solve(vec3));
+
+    // upper - dense
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template triangularView<Upper>().solve(vec2),
+                     m2.template triangularView<Upper>().solve(vec3));
+    VERIFY_IS_APPROX(refMat2.conjugate().template triangularView<Upper>().solve(vec2),
+                     m2.conjugate().template triangularView<Upper>().solve(vec3));
+    {
+      SparseMatrix<Scalar> cm2(m2);
+      //Index rows, Index cols, Index nnz, Index* outerIndexPtr, Index* innerIndexPtr, Scalar* valuePtr
+      MappedSparseMatrix<Scalar> mm2(rows, cols, cm2.nonZeros(), cm2.outerIndexPtr(), cm2.innerIndexPtr(), cm2.valuePtr());
+      VERIFY_IS_APPROX(refMat2.conjugate().template triangularView<Upper>().solve(vec2),
+                       mm2.conjugate().template triangularView<Upper>().solve(vec3));
+    }
+
+    // lower - transpose
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.transpose().template triangularView<Upper>().solve(vec2),
+                     m2.transpose().template triangularView<Upper>().solve(vec3));
+
+    // upper - transpose
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.transpose().template triangularView<Lower>().solve(vec2),
+                     m2.transpose().template triangularView<Lower>().solve(vec3));
+
+    SparseMatrix<Scalar> matB(rows, rows);
+    DenseMatrix refMatB = DenseMatrix::Zero(rows, rows);
+
+    // lower - sparse
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular);
+    initSparse<Scalar>(density, refMatB, matB);
+    refMat2.template triangularView<Lower>().solveInPlace(refMatB);
+    m2.template triangularView<Lower>().solveInPlace(matB);
+    VERIFY_IS_APPROX(matB.toDense(), refMatB);
+
+    // upper - sparse
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeUpperTriangular);
+    initSparse<Scalar>(density, refMatB, matB);
+    refMat2.template triangularView<Upper>().solveInPlace(refMatB);
+    m2.template triangularView<Upper>().solveInPlace(matB);
+    VERIFY_IS_APPROX(matB, refMatB);
+
+    // test deprecated API
+    initSparse<Scalar>(density, refMat2, m2, ForceNonZeroDiag|MakeLowerTriangular, &zeroCoords, &nonzeroCoords);
+    VERIFY_IS_APPROX(refMat2.template triangularView<Lower>().solve(vec2),
+                     m2.template triangularView<Lower>().solve(vec3));
+  }
+}
+
+void test_sparse_solvers()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(sparse_solvers<double>(8, 8) );
+    int s = internal::random<int>(1,300);
+    CALL_SUBTEST_2(sparse_solvers<std::complex<double> >(s,s) );
+    CALL_SUBTEST_1(sparse_solvers<double>(s,s) );
+  }
+}
diff --git a/test/sparse_vector.cpp b/test/sparse_vector.cpp
new file mode 100644
index 0000000..0c94768
--- /dev/null
+++ b/test/sparse_vector.cpp
@@ -0,0 +1,110 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2011 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse.h"
+
+template<typename Scalar,typename Index> void sparse_vector(int rows, int cols)
+{
+  double densityMat = (std::max)(8./(rows*cols), 0.01);
+  double densityVec = (std::max)(8./float(rows), 0.1);
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  typedef SparseVector<Scalar,0,Index> SparseVectorType;
+  typedef SparseMatrix<Scalar,0,Index> SparseMatrixType;
+  Scalar eps = 1e-6;
+
+  SparseMatrixType m1(rows,rows);
+  SparseVectorType v1(rows), v2(rows), v3(rows);
+  DenseMatrix refM1 = DenseMatrix::Zero(rows, rows);
+  DenseVector refV1 = DenseVector::Random(rows),
+    refV2 = DenseVector::Random(rows),
+    refV3 = DenseVector::Random(rows);
+
+  std::vector<int> zerocoords, nonzerocoords;
+  initSparse<Scalar>(densityVec, refV1, v1, &zerocoords, &nonzerocoords);
+  initSparse<Scalar>(densityMat, refM1, m1);
+
+  initSparse<Scalar>(densityVec, refV2, v2);
+  initSparse<Scalar>(densityVec, refV3, v3);
+
+  Scalar s1 = internal::random<Scalar>();
+
+  // test coeff and coeffRef
+  for (unsigned int i=0; i<zerocoords.size(); ++i)
+  {
+    VERIFY_IS_MUCH_SMALLER_THAN( v1.coeff(zerocoords[i]), eps );
+    //VERIFY_RAISES_ASSERT( v1.coeffRef(zerocoords[i]) = 5 );
+  }
+  {
+    VERIFY(int(nonzerocoords.size()) == v1.nonZeros());
+    int j=0;
+    for (typename SparseVectorType::InnerIterator it(v1); it; ++it,++j)
+    {
+      VERIFY(nonzerocoords[j]==it.index());
+      VERIFY(it.value()==v1.coeff(it.index()));
+      VERIFY(it.value()==refV1.coeff(it.index()));
+    }
+  }
+  VERIFY_IS_APPROX(v1, refV1);
+
+  v1.coeffRef(nonzerocoords[0]) = Scalar(5);
+  refV1.coeffRef(nonzerocoords[0]) = Scalar(5);
+  VERIFY_IS_APPROX(v1, refV1);
+
+  VERIFY_IS_APPROX(v1+v2, refV1+refV2);
+  VERIFY_IS_APPROX(v1+v2+v3, refV1+refV2+refV3);
+
+  VERIFY_IS_APPROX(v1*s1-v2, refV1*s1-refV2);
+
+  VERIFY_IS_APPROX(v1*=s1, refV1*=s1);
+  VERIFY_IS_APPROX(v1/=s1, refV1/=s1);
+
+  VERIFY_IS_APPROX(v1+=v2, refV1+=refV2);
+  VERIFY_IS_APPROX(v1-=v2, refV1-=refV2);
+
+  VERIFY_IS_APPROX(v1.dot(v2), refV1.dot(refV2));
+  VERIFY_IS_APPROX(v1.dot(refV2), refV1.dot(refV2));
+
+  VERIFY_IS_APPROX(v1.dot(m1*v2), refV1.dot(refM1*refV2));
+  int i = internal::random<int>(0,rows-1);
+  VERIFY_IS_APPROX(v1.dot(m1.col(i)), refV1.dot(refM1.col(i)));
+
+
+  VERIFY_IS_APPROX(v1.squaredNorm(), refV1.squaredNorm());
+  
+  VERIFY_IS_APPROX(v1.blueNorm(), refV1.blueNorm());
+
+  // test aliasing
+  VERIFY_IS_APPROX((v1 = -v1), (refV1 = -refV1));
+  VERIFY_IS_APPROX((v1 = v1.transpose()), (refV1 = refV1.transpose().eval()));
+  VERIFY_IS_APPROX((v1 += -v1), (refV1 += -refV1));
+  
+  // sparse matrix to sparse vector
+  SparseMatrixType mv1;
+  VERIFY_IS_APPROX((mv1=v1),v1);
+  VERIFY_IS_APPROX(mv1,(v1=mv1));
+  VERIFY_IS_APPROX(mv1,(v1=mv1.transpose()));
+  
+  // check copy to dense vector with transpose
+  refV3.resize(0);
+  VERIFY_IS_APPROX(refV3 = v1.transpose(),v1.toDense()); 
+  VERIFY_IS_APPROX(DenseVector(v1),v1.toDense()); 
+
+}
+
+void test_sparse_vector()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1(( sparse_vector<double,int>(8, 8) ));
+    CALL_SUBTEST_2(( sparse_vector<std::complex<double>, int>(16, 16) ));
+    CALL_SUBTEST_1(( sparse_vector<double,long int>(299, 535) ));
+    CALL_SUBTEST_1(( sparse_vector<double,short>(299, 535) ));
+  }
+}
+
diff --git a/test/sparselu.cpp b/test/sparselu.cpp
new file mode 100644
index 0000000..37eb069
--- /dev/null
+++ b/test/sparselu.cpp
@@ -0,0 +1,61 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// 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/>.
+
+
+// SparseLU solve does not accept column major matrices for the destination.
+// However, as expected, the generic check_sparse_square_solving routines produces row-major
+// rhs and destination matrices when compiled with EIGEN_DEFAULT_TO_ROW_MAJOR
+
+#ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
+#undef EIGEN_DEFAULT_TO_ROW_MAJOR
+#endif
+
+#include "sparse_solver.h"
+#include <Eigen/SparseLU>
+#include <unsupported/Eigen/SparseExtra>
+
+template<typename T> void test_sparselu_T()
+{
+  SparseLU<SparseMatrix<T, ColMajor> /*, COLAMDOrdering<int>*/ > sparselu_colamd; // COLAMDOrdering is the default
+  SparseLU<SparseMatrix<T, ColMajor>, AMDOrdering<int> > sparselu_amd; 
+  SparseLU<SparseMatrix<T, ColMajor, long int>, NaturalOrdering<long int> > sparselu_natural;
+  
+  check_sparse_square_solving(sparselu_colamd); 
+  check_sparse_square_solving(sparselu_amd);
+  check_sparse_square_solving(sparselu_natural);
+  
+  check_sparse_square_abs_determinant(sparselu_colamd);
+  check_sparse_square_abs_determinant(sparselu_amd);
+  
+  check_sparse_square_determinant(sparselu_colamd);
+  check_sparse_square_determinant(sparselu_amd);
+}
+
+void test_sparselu()
+{
+  CALL_SUBTEST_1(test_sparselu_T<float>()); 
+  CALL_SUBTEST_2(test_sparselu_T<double>());
+  CALL_SUBTEST_3(test_sparselu_T<std::complex<float> >()); 
+  CALL_SUBTEST_4(test_sparselu_T<std::complex<double> >());
+}
diff --git a/test/sparseqr.cpp b/test/sparseqr.cpp
new file mode 100644
index 0000000..451c0e7
--- /dev/null
+++ b/test/sparseqr.cpp
@@ -0,0 +1,100 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
+// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+#include "sparse.h"
+#include <Eigen/SparseQR>
+
+template<typename MatrixType,typename DenseMat>
+int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  int rows = internal::random<int>(1,maxRows);
+  int cols = internal::random<int>(1,rows);
+  double density = (std::max)(8./(rows*cols), 0.01);
+  
+  A.resize(rows,cols);
+  dA.resize(rows,cols);
+  initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
+  A.makeCompressed();
+  int nop = internal::random<int>(0, internal::random<double>(0,1) > 0.5 ? cols/2 : 0);
+  for(int k=0; k<nop; ++k)
+  {
+    int j0 = internal::random<int>(0,cols-1);
+    int j1 = internal::random<int>(0,cols-1);
+    Scalar s = internal::random<Scalar>();
+    A.col(j0)  = s * A.col(j1);
+    dA.col(j0) = s * dA.col(j1);
+  }
+  
+//   if(rows<cols) {
+//     A.conservativeResize(cols,cols);
+//     dA.conservativeResize(cols,cols);
+//     dA.bottomRows(cols-rows).setZero();
+//   }
+  
+  return rows;
+}
+
+template<typename Scalar> void test_sparseqr_scalar()
+{
+  typedef SparseMatrix<Scalar,ColMajor> MatrixType; 
+  typedef Matrix<Scalar,Dynamic,Dynamic> DenseMat;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  MatrixType A;
+  DenseMat dA;
+  DenseVector refX,x,b; 
+  SparseQR<MatrixType, COLAMDOrdering<int> > solver; 
+  generate_sparse_rectangular_problem(A,dA);
+  
+  b = dA * DenseVector::Random(A.cols());
+  solver.compute(A);
+  if(internal::random<float>(0,1)>0.5)
+    solver.factorize(A);  // this checks that calling analyzePattern is not needed if the pattern do not change.
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse QR factorization failed\n";
+    exit(0);
+    return;
+  }
+  x = solver.solve(b);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse QR factorization failed\n";
+    exit(0);
+    return;
+  }
+  
+  VERIFY_IS_APPROX(A * x, b);
+  
+  //Compare with a dense QR solver
+  ColPivHouseholderQR<DenseMat> dqr(dA);
+  refX = dqr.solve(b);
+  
+  VERIFY_IS_EQUAL(dqr.rank(), solver.rank());
+  if(solver.rank()==A.cols()) // full rank
+    VERIFY_IS_APPROX(x, refX);
+//   else
+//     VERIFY((dA * refX - b).norm() * 2 > (A * x - b).norm() );
+
+  // Compute explicitly the matrix Q
+  MatrixType Q, QtQ, idM;
+  Q = solver.matrixQ();
+  //Check  ||Q' * Q - I ||
+  QtQ = Q * Q.adjoint();
+  idM.resize(Q.rows(), Q.rows()); idM.setIdentity();
+  VERIFY(idM.isApprox(QtQ));
+}
+void test_sparseqr()
+{
+  for(int i=0; i<g_repeat; ++i)
+  {
+    CALL_SUBTEST_1(test_sparseqr_scalar<double>());
+    CALL_SUBTEST_2(test_sparseqr_scalar<std::complex<double> >());
+  }
+}
+
diff --git a/test/special_numbers.cpp b/test/special_numbers.cpp
new file mode 100644
index 0000000..2f1b704
--- /dev/null
+++ b/test/special_numbers.cpp
@@ -0,0 +1,58 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2013 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename Scalar> void special_numbers()
+{
+  typedef Matrix<Scalar, Dynamic,Dynamic> MatType;
+  int rows = internal::random<int>(1,300);
+  int cols = internal::random<int>(1,300);
+  
+  Scalar nan = std::numeric_limits<Scalar>::quiet_NaN();
+  Scalar inf = std::numeric_limits<Scalar>::infinity();
+  Scalar s1 = internal::random<Scalar>();
+  
+  MatType m1    = MatType::Random(rows,cols),
+          mnan  = MatType::Random(rows,cols),
+          minf  = MatType::Random(rows,cols),
+          mboth = MatType::Random(rows,cols);
+          
+  int n = internal::random<int>(1,10);
+  for(int k=0; k<n; ++k)
+  {
+    mnan(internal::random<int>(0,rows-1), internal::random<int>(0,cols-1)) = nan;
+    minf(internal::random<int>(0,rows-1), internal::random<int>(0,cols-1)) = inf;
+  }
+  mboth = mnan + minf;
+  
+  VERIFY(!m1.hasNaN());
+  VERIFY(m1.allFinite());
+  
+  VERIFY(mnan.hasNaN());
+  VERIFY((s1*mnan).hasNaN());
+  VERIFY(!minf.hasNaN());
+  VERIFY(!(2*minf).hasNaN());
+  VERIFY(mboth.hasNaN());
+  VERIFY(mboth.array().hasNaN());
+  
+  VERIFY(!mnan.allFinite());
+  VERIFY(!minf.allFinite());
+  VERIFY(!(minf-mboth).allFinite());
+  VERIFY(!mboth.allFinite());
+  VERIFY(!mboth.array().allFinite());
+}
+
+void test_special_numbers()
+{
+  for(int i = 0; i < 10*g_repeat; i++) {
+    CALL_SUBTEST_1( special_numbers<float>() );
+    CALL_SUBTEST_1( special_numbers<double>() );
+  }
+}
diff --git a/test/spqr_support.cpp b/test/spqr_support.cpp
new file mode 100644
index 0000000..b8980e0
--- /dev/null
+++ b/test/spqr_support.cpp
@@ -0,0 +1,62 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2012 Desire Nuentsa Wakam <desire.nuentsa_wakam@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+#include "sparse.h"
+#include <Eigen/SPQRSupport>
+
+
+template<typename MatrixType,typename DenseMat>
+int generate_sparse_rectangular_problem(MatrixType& A, DenseMat& dA, int maxRows = 300, int maxCols = 300)
+{
+  eigen_assert(maxRows >= maxCols);
+  typedef typename MatrixType::Scalar Scalar;
+  int rows = internal::random<int>(1,maxRows);
+  int cols = internal::random<int>(1,rows);
+  double density = (std::max)(8./(rows*cols), 0.01);
+  
+  A.resize(rows,rows);
+  dA.resize(rows,rows);
+  initSparse<Scalar>(density, dA, A,ForceNonZeroDiag);
+  A.makeCompressed();
+  return rows;
+}
+
+template<typename Scalar> void test_spqr_scalar()
+{
+  typedef SparseMatrix<Scalar,ColMajor> MatrixType; 
+  MatrixType A;
+  Matrix<Scalar,Dynamic,Dynamic> dA;
+  typedef Matrix<Scalar,Dynamic,1> DenseVector;
+  DenseVector refX,x,b; 
+  SPQR<MatrixType> solver; 
+  generate_sparse_rectangular_problem(A,dA);
+  
+  int m = A.rows();
+  b = DenseVector::Random(m);
+  solver.compute(A);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse QR factorization failed\n";
+    exit(0);
+    return;
+  }
+  x = solver.solve(b);
+  if (solver.info() != Success)
+  {
+    std::cerr << "sparse QR factorization failed\n";
+    exit(0);
+    return;
+  }  
+  //Compare with a dense solver
+  refX = dA.colPivHouseholderQr().solve(b);
+  VERIFY(x.isApprox(refX,test_precision<Scalar>()));
+}
+void test_spqr_support()
+{
+  CALL_SUBTEST_1(test_spqr_scalar<double>());
+  CALL_SUBTEST_2(test_spqr_scalar<std::complex<double> >());
+}
diff --git a/test/stable_norm.cpp b/test/stable_norm.cpp
new file mode 100644
index 0000000..231dd91
--- /dev/null
+++ b/test/stable_norm.cpp
@@ -0,0 +1,115 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+// workaround aggressive optimization in ICC
+template<typename T> EIGEN_DONT_INLINE  T sub(T a, T b) { return a - b; }
+
+template<typename T> bool isFinite(const T& x)
+{
+  return isNotNaN(sub(x,x));
+}
+
+template<typename T> EIGEN_DONT_INLINE T copy(const T& x)
+{
+  return x;
+}
+
+template<typename MatrixType> void stable_norm(const MatrixType& m)
+{
+  /* this test covers the following files:
+     StableNorm.h
+  */
+  using std::sqrt;
+  using std::abs;
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+
+  // Check the basic machine-dependent constants.
+  {
+    int ibeta, it, iemin, iemax;
+
+    ibeta = std::numeric_limits<RealScalar>::radix;         // base for floating-point numbers
+    it    = std::numeric_limits<RealScalar>::digits;        // number of base-beta digits in mantissa
+    iemin = std::numeric_limits<RealScalar>::min_exponent;  // minimum exponent
+    iemax = std::numeric_limits<RealScalar>::max_exponent;  // maximum exponent
+
+    VERIFY( (!(iemin > 1 - 2*it || 1+it>iemax || (it==2 && ibeta<5) || (it<=4 && ibeta <= 3 ) || it<2))
+           && "the stable norm algorithm cannot be guaranteed on this computer");
+  }
+
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  // get a non-zero random factor
+  Scalar factor = internal::random<Scalar>();
+  while(numext::abs2(factor)<RealScalar(1e-4))
+    factor = internal::random<Scalar>();
+  Scalar big = factor * ((std::numeric_limits<RealScalar>::max)() * RealScalar(1e-4));
+  
+  factor = internal::random<Scalar>();
+  while(numext::abs2(factor)<RealScalar(1e-4))
+    factor = internal::random<Scalar>();
+  Scalar small = factor * ((std::numeric_limits<RealScalar>::min)() * RealScalar(1e4));
+
+  MatrixType  vzero = MatrixType::Zero(rows, cols),
+              vrand = MatrixType::Random(rows, cols),
+              vbig(rows, cols),
+              vsmall(rows,cols);
+
+  vbig.fill(big);
+  vsmall.fill(small);
+
+  VERIFY_IS_MUCH_SMALLER_THAN(vzero.norm(), static_cast<RealScalar>(1));
+  VERIFY_IS_APPROX(vrand.stableNorm(),      vrand.norm());
+  VERIFY_IS_APPROX(vrand.blueNorm(),        vrand.norm());
+  VERIFY_IS_APPROX(vrand.hypotNorm(),       vrand.norm());
+
+  RealScalar size = static_cast<RealScalar>(m.size());
+
+  // test isFinite
+  VERIFY(!isFinite( std::numeric_limits<RealScalar>::infinity()));
+  VERIFY(!isFinite(sqrt(-abs(big))));
+
+  // test overflow
+  VERIFY(isFinite(sqrt(size)*abs(big)));
+  VERIFY_IS_NOT_APPROX(sqrt(copy(vbig.squaredNorm())), abs(sqrt(size)*big)); // here the default norm must fail
+  VERIFY_IS_APPROX(vbig.stableNorm(), sqrt(size)*abs(big));
+  VERIFY_IS_APPROX(vbig.blueNorm(),   sqrt(size)*abs(big));
+  VERIFY_IS_APPROX(vbig.hypotNorm(),  sqrt(size)*abs(big));
+
+  // test underflow
+  VERIFY(isFinite(sqrt(size)*abs(small)));
+  VERIFY_IS_NOT_APPROX(sqrt(copy(vsmall.squaredNorm())),   abs(sqrt(size)*small)); // here the default norm must fail
+  VERIFY_IS_APPROX(vsmall.stableNorm(), sqrt(size)*abs(small));
+  VERIFY_IS_APPROX(vsmall.blueNorm(),   sqrt(size)*abs(small));
+  VERIFY_IS_APPROX(vsmall.hypotNorm(),  sqrt(size)*abs(small));
+
+  // Test compilation of cwise() version
+  VERIFY_IS_APPROX(vrand.colwise().stableNorm(),      vrand.colwise().norm());
+  VERIFY_IS_APPROX(vrand.colwise().blueNorm(),        vrand.colwise().norm());
+  VERIFY_IS_APPROX(vrand.colwise().hypotNorm(),       vrand.colwise().norm());
+  VERIFY_IS_APPROX(vrand.rowwise().stableNorm(),      vrand.rowwise().norm());
+  VERIFY_IS_APPROX(vrand.rowwise().blueNorm(),        vrand.rowwise().norm());
+  VERIFY_IS_APPROX(vrand.rowwise().hypotNorm(),       vrand.rowwise().norm());
+}
+
+void test_stable_norm()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( stable_norm(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( stable_norm(Vector4d()) );
+    CALL_SUBTEST_3( stable_norm(VectorXd(internal::random<int>(10,2000))) );
+    CALL_SUBTEST_4( stable_norm(VectorXf(internal::random<int>(10,2000))) );
+    CALL_SUBTEST_5( stable_norm(VectorXcd(internal::random<int>(10,2000))) );
+  }
+}
diff --git a/test/stddeque.cpp b/test/stddeque.cpp
new file mode 100644
index 0000000..bb4b476
--- /dev/null
+++ b/test/stddeque.cpp
@@ -0,0 +1,132 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/StdDeque>
+#include <Eigen/Geometry>
+
+template<typename MatrixType>
+void check_stddeque_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  
+  Index rows = m.rows();
+  Index cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::deque<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::deque<MatrixType,Eigen::aligned_allocator<MatrixType> >::iterator vi = v.begin();
+  typename std::deque<MatrixType,Eigen::aligned_allocator<MatrixType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);  
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+template<typename TransformType>
+void check_stddeque_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::deque<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::deque<TransformType,Eigen::aligned_allocator<TransformType> >::iterator vi = v.begin();
+  typename std::deque<TransformType,Eigen::aligned_allocator<TransformType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+template<typename QuaternionType>
+void check_stddeque_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::deque<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::deque<QuaternionType,Eigen::aligned_allocator<QuaternionType> >::iterator vi = v.begin();
+  typename std::deque<QuaternionType,Eigen::aligned_allocator<QuaternionType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+void test_stddeque()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stddeque_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stddeque_matrix(Matrix3f()));
+  CALL_SUBTEST_2(check_stddeque_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stddeque_matrix(Matrix2f()));
+  CALL_SUBTEST_1(check_stddeque_matrix(Vector4f()));
+  CALL_SUBTEST_1(check_stddeque_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stddeque_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stddeque_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stddeque_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stddeque_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stddeque_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stddeque_transform(Affine2f()));
+  CALL_SUBTEST_4(check_stddeque_transform(Affine3f()));
+  CALL_SUBTEST_4(check_stddeque_transform(Affine3d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stddeque_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stddeque_quaternion(Quaterniond()));
+}
diff --git a/test/stdlist.cpp b/test/stdlist.cpp
new file mode 100644
index 0000000..17cce77
--- /dev/null
+++ b/test/stdlist.cpp
@@ -0,0 +1,132 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/StdList>
+#include <Eigen/Geometry>
+
+template<typename MatrixType>
+void check_stdlist_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  
+  Index rows = m.rows();
+  Index cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::list<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::list<MatrixType,Eigen::aligned_allocator<MatrixType> >::iterator vi = v.begin();
+  typename std::list<MatrixType,Eigen::aligned_allocator<MatrixType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);  
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+template<typename TransformType>
+void check_stdlist_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::list<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::list<TransformType,Eigen::aligned_allocator<TransformType> >::iterator vi = v.begin();
+  typename std::list<TransformType,Eigen::aligned_allocator<TransformType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+template<typename QuaternionType>
+void check_stdlist_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::list<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
+  v.front() = x;
+  w.front() = w.back();
+  VERIFY_IS_APPROX(w.front(), w.back());
+  v = w;
+
+  typename std::list<QuaternionType,Eigen::aligned_allocator<QuaternionType> >::iterator vi = v.begin();
+  typename std::list<QuaternionType,Eigen::aligned_allocator<QuaternionType> >::iterator wi = w.begin();
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(*vi, *wi);
+    ++vi;
+    ++wi;
+  }
+
+  v.resize(21);
+  v.back() = x;
+  VERIFY_IS_APPROX(v.back(), x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v.back(), y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v.back(), x);
+}
+
+void test_stdlist()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdlist_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stdlist_matrix(Matrix3f()));
+  CALL_SUBTEST_2(check_stdlist_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdlist_matrix(Matrix2f()));
+  CALL_SUBTEST_1(check_stdlist_matrix(Vector4f()));
+  CALL_SUBTEST_1(check_stdlist_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stdlist_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stdlist_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stdlist_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stdlist_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stdlist_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stdlist_transform(Affine2f()));
+  CALL_SUBTEST_4(check_stdlist_transform(Affine3f()));
+  CALL_SUBTEST_4(check_stdlist_transform(Affine3d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stdlist_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stdlist_quaternion(Quaterniond()));
+}
diff --git a/test/stdvector.cpp b/test/stdvector.cpp
new file mode 100644
index 0000000..6e173c6
--- /dev/null
+++ b/test/stdvector.cpp
@@ -0,0 +1,148 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/StdVector>
+#include <Eigen/Geometry>
+
+template<typename MatrixType>
+void check_stdvector_matrix(const MatrixType& m)
+{
+  typename MatrixType::Index rows = m.rows();
+  typename MatrixType::Index cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::vector<MatrixType,Eigen::aligned_allocator<MatrixType> > v(10, MatrixType(rows,cols)), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_stdvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::vector<TransformType,Eigen::aligned_allocator<TransformType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_stdvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::vector<QuaternionType,Eigen::aligned_allocator<QuaternionType> > v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_stdvector()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector4f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stdvector_transform(Projective2f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Projective3f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Projective3d()));
+  //CALL_SUBTEST(heck_stdvector_transform(Projective4d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaterniond()));
+}
diff --git a/test/stdvector_overload.cpp b/test/stdvector_overload.cpp
new file mode 100644
index 0000000..736ff0e
--- /dev/null
+++ b/test/stdvector_overload.cpp
@@ -0,0 +1,161 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#include <Eigen/StdVector>
+#include <Eigen/Geometry>
+
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Vector4f)
+
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2f)
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix4f)
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix4d)
+
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Affine3f)
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Affine3d)
+
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Quaternionf)
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Quaterniond)
+
+template<typename MatrixType>
+void check_stdvector_matrix(const MatrixType& m)
+{
+  typename MatrixType::Index rows = m.rows();
+  typename MatrixType::Index cols = m.cols();
+  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
+  std::vector<MatrixType> v(10, MatrixType(rows,cols)), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(MatrixType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  MatrixType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i]==w[(i-23)%w.size()]);
+  }
+}
+
+template<typename TransformType>
+void check_stdvector_transform(const TransformType&)
+{
+  typedef typename TransformType::MatrixType MatrixType;
+  TransformType x(MatrixType::Random()), y(MatrixType::Random());
+  std::vector<TransformType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(TransformType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  TransformType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].matrix()==w[(i-23)%w.size()].matrix());
+  }
+}
+
+template<typename QuaternionType>
+void check_stdvector_quaternion(const QuaternionType&)
+{
+  typedef typename QuaternionType::Coefficients Coefficients;
+  QuaternionType x(Coefficients::Random()), y(Coefficients::Random());
+  std::vector<QuaternionType> v(10), w(20, y);
+  v[5] = x;
+  w[6] = v[5];
+  VERIFY_IS_APPROX(w[6], v[5]);
+  v = w;
+  for(int i = 0; i < 20; i++)
+  {
+    VERIFY_IS_APPROX(w[i], v[i]);
+  }
+
+  v.resize(21);
+  v[20] = x;
+  VERIFY_IS_APPROX(v[20], x);
+  v.resize(22,y);
+  VERIFY_IS_APPROX(v[21], y);
+  v.push_back(x);
+  VERIFY_IS_APPROX(v[22], x);
+  VERIFY((size_t)&(v[22]) == (size_t)&(v[21]) + sizeof(QuaternionType));
+
+  // do a lot of push_back such that the vector gets internally resized
+  // (with memory reallocation)
+  QuaternionType* ref = &w[0];
+  for(int i=0; i<30 || ((ref==&w[0]) && i<300); ++i)
+    v.push_back(w[i%w.size()]);
+  for(unsigned int i=23; i<v.size(); ++i)
+  {
+    VERIFY(v[i].coeffs()==w[(i-23)%w.size()].coeffs());
+  }
+}
+
+void test_stdvector_overload()
+{
+  // some non vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix3f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix3d()));
+
+  // some vectorizable fixed sizes
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix2f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Vector4f()));
+  CALL_SUBTEST_1(check_stdvector_matrix(Matrix4f()));
+  CALL_SUBTEST_2(check_stdvector_matrix(Matrix4d()));
+
+  // some dynamic sizes
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXd(1,1)));
+  CALL_SUBTEST_3(check_stdvector_matrix(VectorXd(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(RowVectorXf(20)));
+  CALL_SUBTEST_3(check_stdvector_matrix(MatrixXcf(10,10)));
+
+  // some Transform
+  CALL_SUBTEST_4(check_stdvector_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
+  CALL_SUBTEST_4(check_stdvector_transform(Affine3f()));
+  CALL_SUBTEST_4(check_stdvector_transform(Affine3d()));
+
+  // some Quaternion
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaternionf()));
+  CALL_SUBTEST_5(check_stdvector_quaternion(Quaterniond()));
+}
diff --git a/test/superlu_support.cpp b/test/superlu_support.cpp
new file mode 100644
index 0000000..3b16135
--- /dev/null
+++ b/test/superlu_support.cpp
@@ -0,0 +1,22 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+
+#include <Eigen/SuperLUSupport>
+
+void test_superlu_support()
+{
+  SuperLU<SparseMatrix<double> > superlu_double_colmajor;
+  SuperLU<SparseMatrix<std::complex<double> > > superlu_cplxdouble_colmajor;
+  CALL_SUBTEST_1( check_sparse_square_solving(superlu_double_colmajor)      );
+  CALL_SUBTEST_2( check_sparse_square_solving(superlu_cplxdouble_colmajor)  );
+  CALL_SUBTEST_1( check_sparse_square_determinant(superlu_double_colmajor)      );
+  CALL_SUBTEST_2( check_sparse_square_determinant(superlu_cplxdouble_colmajor)  );
+}
diff --git a/test/swap.cpp b/test/swap.cpp
new file mode 100644
index 0000000..36b3531
--- /dev/null
+++ b/test/swap.cpp
@@ -0,0 +1,83 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+#include "main.h"
+
+template<typename T>
+struct other_matrix_type
+{
+  typedef int type;
+};
+
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+struct other_matrix_type<Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+  typedef Matrix<_Scalar, _Rows, _Cols, _Options^RowMajor, _MaxRows, _MaxCols> type;
+};
+
+template<typename MatrixType> void swap(const MatrixType& m)
+{
+  typedef typename other_matrix_type<MatrixType>::type OtherMatrixType;
+  typedef typename MatrixType::Scalar Scalar;
+
+  eigen_assert((!internal::is_same<MatrixType,OtherMatrixType>::value));
+  typename MatrixType::Index rows = m.rows();
+  typename MatrixType::Index cols = m.cols();
+  
+  // construct 3 matrix guaranteed to be distinct
+  MatrixType m1 = MatrixType::Random(rows,cols);
+  MatrixType m2 = MatrixType::Random(rows,cols) + Scalar(100) * MatrixType::Identity(rows,cols);
+  OtherMatrixType m3 = OtherMatrixType::Random(rows,cols) + Scalar(200) * OtherMatrixType::Identity(rows,cols);
+  
+  MatrixType m1_copy = m1;
+  MatrixType m2_copy = m2;
+  OtherMatrixType m3_copy = m3;
+  
+  // test swapping 2 matrices of same type
+  m1.swap(m2);
+  VERIFY_IS_APPROX(m1,m2_copy);
+  VERIFY_IS_APPROX(m2,m1_copy);
+  m1 = m1_copy;
+  m2 = m2_copy;
+  
+  // test swapping 2 matrices of different types
+  m1.swap(m3);
+  VERIFY_IS_APPROX(m1,m3_copy);
+  VERIFY_IS_APPROX(m3,m1_copy);
+  m1 = m1_copy;
+  m3 = m3_copy;
+  
+  // test swapping matrix with expression
+  m1.swap(m2.block(0,0,rows,cols));
+  VERIFY_IS_APPROX(m1,m2_copy);
+  VERIFY_IS_APPROX(m2,m1_copy);
+  m1 = m1_copy;
+  m2 = m2_copy;
+
+  // test swapping two expressions of different types
+  m1.transpose().swap(m3.transpose());
+  VERIFY_IS_APPROX(m1,m3_copy);
+  VERIFY_IS_APPROX(m3,m1_copy);
+  m1 = m1_copy;
+  m3 = m3_copy;
+  
+  // test assertion on mismatching size -- matrix case
+  VERIFY_RAISES_ASSERT(m1.swap(m1.row(0)));
+  // test assertion on mismatching size -- xpr case
+  VERIFY_RAISES_ASSERT(m1.row(0).swap(m1));
+}
+
+void test_swap()
+{
+  CALL_SUBTEST_1( swap(Matrix3f()) ); // fixed size, no vectorization 
+  CALL_SUBTEST_2( swap(Matrix4d()) ); // fixed size, possible vectorization 
+  CALL_SUBTEST_3( swap(MatrixXd(3,3)) ); // dyn size, no vectorization 
+  CALL_SUBTEST_4( swap(MatrixXf(30,30)) ); // dyn size, possible vectorization 
+}
diff --git a/test/testsuite.cmake b/test/testsuite.cmake
new file mode 100644
index 0000000..3bec56b
--- /dev/null
+++ b/test/testsuite.cmake
@@ -0,0 +1,229 @@
+
+####################################################################
+#
+# Usage:
+#  - create a new folder, let's call it cdash
+#  - in that folder, do:
+#    ctest -S path/to/eigen/test/testsuite.cmake[,option1=value1[,option2=value2]]
+#
+# Options:
+#  - EIGEN_CXX: compiler, eg.: g++-4.2
+#      default: default c++ compiler
+#  - EIGEN_SITE: eg, INRIA-Bdx_pc-gael, or the name of the contributor, etc.
+#      default: hostname
+#  - EIGEN_BUILD_STRING: a string which identify the system/compiler. It should be formed like that:
+#        <OS_name>-<OS_version>-<arch>-<compiler-version>
+#      with:
+#        <OS_name> = opensuse, debian, osx, windows, cygwin, freebsd, solaris, etc.
+#        <OS_version> = 11.1, XP, vista, leopard, etc.
+#        <arch> = i386, x86_64, ia64, powerpc, etc.
+#        <compiler-version> = gcc-4.3.2, icc-11.0, MSVC-2008, etc.
+#  - EIGEN_EXPLICIT_VECTORIZATION: novec, SSE2, Altivec
+#       default: SSE2 for x86_64 systems, novec otherwise
+#       Its value is automatically appended to EIGEN_BUILD_STRING
+#  - EIGEN_CMAKE_DIR: path to cmake executable
+#  - EIGEN_MODE: dashboard model, can be Experimental, Nightly, or Continuous
+#      default: Nightly
+#  - EIGEN_WORK_DIR: directory used to download the source files and make the builds
+#      default: folder which contains this script
+#  - EIGEN_CMAKE_ARGS: additional arguments passed to cmake
+#  - EIGEN_GENERATOR_TYPE: allows to overwrite the generator type
+#      default: nmake (windows
+#      See http://www.cmake.org/cmake/help/cmake2.6docs.html#section_Generators for a complete
+#      list of supported generators.
+#  - EIGEN_NO_UPDATE: allows to submit dash boards from local repositories
+#      This might be interesting in case you want to submit dashboards
+#      including local changes.
+#  - CTEST_SOURCE_DIRECTORY: path to eigen's src (use a new and empty folder, not the one you are working on)
+#      default: <EIGEN_WORK_DIR>/src
+#  - CTEST_BINARY_DIRECTORY: build directory
+#      default: <EIGEN_WORK_DIR>/nightly-<EIGEN_CXX>
+#
+# Here is an example running several compilers on a linux system:
+# #!/bin/bash
+# ARCH=`uname -m`
+# SITE=`hostname`
+# VERSION=opensuse-11.1
+# WORK_DIR=/home/gael/Coding/eigen/cdash
+# # get the last version of the script
+# wget http://bitbucket.org/eigen/eigen/raw/tip/test/testsuite.cmake -o $WORK_DIR/testsuite.cmake
+# COMMON="ctest -S $WORK_DIR/testsuite.cmake,EIGEN_WORK_DIR=$WORK_DIR,EIGEN_SITE=$SITE,EIGEN_MODE=$1,EIGEN_BUILD_STRING=$OS_VERSION-$ARCH"
+# $COMMON-gcc-3.4.6,EIGEN_CXX=g++-3.4
+# $COMMON-gcc-4.0.1,EIGEN_CXX=g++-4.0.1
+# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=novec
+# $COMMON-gcc-4.3.2,EIGEN_CXX=g++-4.3,EIGEN_EXPLICIT_VECTORIZATION=SSE2
+# $COMMON-icc-11.0,EIGEN_CXX=icpc
+#
+####################################################################
+
+# process the arguments
+
+set(ARGLIST ${CTEST_SCRIPT_ARG})
+while(${ARGLIST} MATCHES  ".+.*")
+
+  # pick first
+  string(REGEX MATCH "([^,]*)(,.*)?" DUMMY ${ARGLIST})
+  SET(TOP ${CMAKE_MATCH_1})
+
+  # remove first
+  string(REGEX MATCHALL "[^,]*,(.*)" DUMMY ${ARGLIST})
+  SET(ARGLIST ${CMAKE_MATCH_1})
+
+  # decompose as a pair key=value
+  string(REGEX MATCH "([^=]*)(=.*)?" DUMMY ${TOP})
+  SET(KEY ${CMAKE_MATCH_1})
+
+  string(REGEX MATCH "[^=]*=(.*)" DUMMY ${TOP})
+  SET(VALUE ${CMAKE_MATCH_1})
+
+  # set the variable to the specified value
+  if(VALUE)
+    SET(${KEY} ${VALUE})
+  else(VALUE)
+    SET(${KEY} ON)
+  endif(VALUE)
+
+endwhile(${ARGLIST} MATCHES ".+.*")
+
+####################################################################
+# Automatically set some user variables if they have not been defined manually
+####################################################################
+cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+
+if(NOT EIGEN_SITE)
+  site_name(EIGEN_SITE)
+endif(NOT EIGEN_SITE)
+
+if(NOT EIGEN_CMAKE_DIR)
+  SET(EIGEN_CMAKE_DIR "")
+endif(NOT EIGEN_CMAKE_DIR)
+
+if(NOT EIGEN_BUILD_STRING)
+
+  # let's try to find all information we need to make the build string ourself
+
+  # OS
+  build_name(EIGEN_OS_VERSION)
+
+  # arch
+  set(EIGEN_ARCH ${CMAKE_SYSTEM_PROCESSOR})
+  if(WIN32)
+    set(EIGEN_ARCH $ENV{PROCESSOR_ARCHITECTURE})
+  else(WIN32)
+    execute_process(COMMAND uname -m OUTPUT_VARIABLE EIGEN_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
+  endif(WIN32)
+
+  set(EIGEN_BUILD_STRING ${EIGEN_OS_VERSION}${EIGEN_ARCH}-${EIGEN_CXX})
+
+endif(NOT EIGEN_BUILD_STRING)
+
+if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+  set(EIGEN_BUILD_STRING ${EIGEN_BUILD_STRING}-${EIGEN_EXPLICIT_VECTORIZATION})
+endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+
+if(NOT EIGEN_WORK_DIR)
+  set(EIGEN_WORK_DIR ${CTEST_SCRIPT_DIRECTORY})
+endif(NOT EIGEN_WORK_DIR)
+
+if(NOT CTEST_SOURCE_DIRECTORY)
+  SET (CTEST_SOURCE_DIRECTORY "${EIGEN_WORK_DIR}/src")
+endif(NOT CTEST_SOURCE_DIRECTORY)
+
+if(NOT CTEST_BINARY_DIRECTORY)
+  SET (CTEST_BINARY_DIRECTORY "${EIGEN_WORK_DIR}/nightly_${EIGEN_CXX}")
+endif(NOT CTEST_BINARY_DIRECTORY)
+
+if(NOT EIGEN_MODE)
+  set(EIGEN_MODE Nightly)
+endif(NOT EIGEN_MODE)
+
+## mandatory variables (the default should be ok in most cases):
+
+if(NOT EIGEN_NO_UPDATE)
+  SET (CTEST_CVS_COMMAND "hg")
+  SET (CTEST_CVS_CHECKOUT "${CTEST_CVS_COMMAND} clone http://bitbucket.org/eigen/eigen \"${CTEST_SOURCE_DIRECTORY}\"")
+  SET(CTEST_BACKUP_AND_RESTORE TRUE) # the backup is CVS related ...
+endif(NOT EIGEN_NO_UPDATE)
+
+# which ctest command to use for running the dashboard
+SET (CTEST_COMMAND "${EIGEN_CMAKE_DIR}ctest -D ${EIGEN_MODE} --no-compress-output")
+if($ENV{EIGEN_CTEST_ARGS})
+SET (CTEST_COMMAND "${CTEST_COMMAND} $ENV{EIGEN_CTEST_ARGS}")
+endif($ENV{EIGEN_CTEST_ARGS})
+# what cmake command to use for configuring this dashboard
+SET (CTEST_CMAKE_COMMAND "${EIGEN_CMAKE_DIR}cmake -DEIGEN_LEAVE_TEST_IN_ALL_TARGET=ON")
+
+####################################################################
+# The values in this section are optional you can either
+# have them or leave them commented out
+####################################################################
+
+# this make sure we get consistent outputs
+SET($ENV{LC_MESSAGES} "en_EN")
+
+# should ctest wipe the binary tree before running
+SET(CTEST_START_WITH_EMPTY_BINARY_DIRECTORY TRUE)
+
+# raise the warning/error limit
+set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS "33331")
+set(CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS "33331")
+
+# this is the initial cache to use for the binary tree, be careful to escape
+# any quotes inside of this string if you use it
+if(WIN32 AND NOT UNIX)
+  #message(SEND_ERROR "win32")
+  if(EIGEN_GENERATOR_TYPE)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"${EIGEN_GENERATOR_TYPE}\"")
+    SET (CTEST_INITIAL_CACHE "
+      CMAKE_BUILD_TYPE:STRING=Release
+      BUILDNAME:STRING=${EIGEN_BUILD_STRING}
+      SITE:STRING=${EIGEN_SITE}
+    ")
+  else(EIGEN_GENERATOR_TYPE)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=nmake")
+    SET (CTEST_INITIAL_CACHE "
+      MAKECOMMAND:STRING=nmake /i
+      CMAKE_MAKE_PROGRAM:FILEPATH=nmake
+      CMAKE_GENERATOR:INTERNAL=NMake Makefiles
+      CMAKE_BUILD_TYPE:STRING=Release
+      BUILDNAME:STRING=${EIGEN_BUILD_STRING}
+      SITE:STRING=${EIGEN_SITE}
+    ")
+  endif(EIGEN_GENERATOR_TYPE)
+else(WIN32 AND NOT UNIX)
+  SET (CTEST_INITIAL_CACHE "
+    BUILDNAME:STRING=${EIGEN_BUILD_STRING}
+    SITE:STRING=${EIGEN_SITE}
+  ")
+endif(WIN32 AND NOT UNIX)
+
+# set any extra environment variables to use during the execution of the script here:
+# setting this variable on windows machines causes trouble ...
+
+if(EIGEN_CXX AND NOT WIN32)
+  set(CTEST_ENVIRONMENT "CXX=${EIGEN_CXX}")
+endif(EIGEN_CXX AND NOT WIN32)
+
+if(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+  if(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE3)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSSE3)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON")  
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE4_1)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON -DEIGEN_TEST_SSE4_1=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE4_2)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_SSE2=ON -DEIGEN_TEST_SSE3=ON -DEIGEN_TEST_SSSE3=ON -DEIGEN_TEST_SSE4_1=ON -DEIGEN_TEST_SSE4_2=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES Altivec)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_ALTIVEC=ON")
+  elseif(EIGEN_EXPLICIT_VECTORIZATION MATCHES novec)
+    set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON")
+  else(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+    message(FATAL_ERROR "Invalid value for EIGEN_EXPLICIT_VECTORIZATION (${EIGEN_EXPLICIT_VECTORIZATION}), must be: novec, SSE2, SSE3, Altivec")
+  endif(EIGEN_EXPLICIT_VECTORIZATION MATCHES SSE2)
+endif(DEFINED EIGEN_EXPLICIT_VECTORIZATION)
+
+if(DEFINED EIGEN_CMAKE_ARGS)
+  set(CTEST_CMAKE_COMMAND "${CTEST_CMAKE_COMMAND} ${EIGEN_CMAKE_ARGS}")
+endif(DEFINED EIGEN_CMAKE_ARGS)
diff --git a/test/triangular.cpp b/test/triangular.cpp
new file mode 100644
index 0000000..5432039
--- /dev/null
+++ b/test/triangular.cpp
@@ -0,0 +1,232 @@
+// This file is triangularView of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+
+
+template<typename MatrixType> void triangular_square(const MatrixType& m)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+  RealScalar largerEps = 10*test_precision<RealScalar>();
+
+  typename MatrixType::Index rows = m.rows();
+  typename MatrixType::Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             m4(rows, cols),
+             r1(rows, cols),
+             r2(rows, cols);
+  VectorType v2 = VectorType::Random(rows);
+
+  MatrixType m1up = m1.template triangularView<Upper>();
+  MatrixType m2up = m2.template triangularView<Upper>();
+
+  if (rows*cols>1)
+  {
+    VERIFY(m1up.isUpperTriangular());
+    VERIFY(m2up.transpose().isLowerTriangular());
+    VERIFY(!m2.isLowerTriangular());
+  }
+
+//   VERIFY_IS_APPROX(m1up.transpose() * m2, m1.upper().transpose().lower() * m2);
+
+  // test overloaded operator+=
+  r1.setZero();
+  r2.setZero();
+  r1.template triangularView<Upper>() +=  m1;
+  r2 += m1up;
+  VERIFY_IS_APPROX(r1,r2);
+
+  // test overloaded operator=
+  m1.setZero();
+  m1.template triangularView<Upper>() = m2.transpose() + m2;
+  m3 = m2.transpose() + m2;
+  VERIFY_IS_APPROX(m3.template triangularView<Lower>().transpose().toDenseMatrix(), m1);
+
+  // test overloaded operator=
+  m1.setZero();
+  m1.template triangularView<Lower>() = m2.transpose() + m2;
+  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
+
+  VERIFY_IS_APPROX(m3.template triangularView<Lower>().conjugate().toDenseMatrix(),
+                   m3.conjugate().template triangularView<Lower>().toDenseMatrix());
+
+  m1 = MatrixType::Random(rows, cols);
+  for (int i=0; i<rows; ++i)
+    while (numext::abs2(m1(i,i))<1e-1) m1(i,i) = internal::random<Scalar>();
+
+  Transpose<MatrixType> trm4(m4);
+  // test back and forward subsitution with a vector as the rhs
+  m3 = m1.template triangularView<Upper>();
+  VERIFY(v2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(v2)), largerEps));
+  m3 = m1.template triangularView<Lower>();
+  VERIFY(v2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(v2)), largerEps));
+  m3 = m1.template triangularView<Upper>();
+  VERIFY(v2.isApprox(m3 * (m1.template triangularView<Upper>().solve(v2)), largerEps));
+  m3 = m1.template triangularView<Lower>();
+  VERIFY(v2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(v2)), largerEps));
+
+  // test back and forward subsitution with a matrix as the rhs
+  m3 = m1.template triangularView<Upper>();
+  VERIFY(m2.isApprox(m3.adjoint() * (m1.adjoint().template triangularView<Lower>().solve(m2)), largerEps));
+  m3 = m1.template triangularView<Lower>();
+  VERIFY(m2.isApprox(m3.transpose() * (m1.transpose().template triangularView<Upper>().solve(m2)), largerEps));
+  m3 = m1.template triangularView<Upper>();
+  VERIFY(m2.isApprox(m3 * (m1.template triangularView<Upper>().solve(m2)), largerEps));
+  m3 = m1.template triangularView<Lower>();
+  VERIFY(m2.isApprox(m3.conjugate() * (m1.conjugate().template triangularView<Lower>().solve(m2)), largerEps));
+
+  // check M * inv(L) using in place API
+  m4 = m3;
+  m1.transpose().template triangularView<Eigen::Upper>().solveInPlace(trm4);
+  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Lower>(), m3);
+
+  // check M * inv(U) using in place API
+  m3 = m1.template triangularView<Upper>();
+  m4 = m3;
+  m3.transpose().template triangularView<Eigen::Lower>().solveInPlace(trm4);
+  VERIFY_IS_APPROX(m4 * m1.template triangularView<Eigen::Upper>(), m3);
+
+  // check solve with unit diagonal
+  m3 = m1.template triangularView<UnitUpper>();
+  VERIFY(m2.isApprox(m3 * (m1.template triangularView<UnitUpper>().solve(m2)), largerEps));
+
+//   VERIFY((  m1.template triangularView<Upper>()
+//           * m2.template triangularView<Upper>()).isUpperTriangular());
+
+  // test swap
+  m1.setOnes();
+  m2.setZero();
+  m2.template triangularView<Upper>().swap(m1);
+  m3.setZero();
+  m3.template triangularView<Upper>().setOnes();
+  VERIFY_IS_APPROX(m2,m3);
+
+}
+
+
+template<typename MatrixType> void triangular_rect(const MatrixType& m)
+{
+  typedef const typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  enum { Rows =  MatrixType::RowsAtCompileTime, Cols =  MatrixType::ColsAtCompileTime };
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+             m2 = MatrixType::Random(rows, cols),
+             m3(rows, cols),
+             m4(rows, cols),
+             r1(rows, cols),
+             r2(rows, cols);
+
+  MatrixType m1up = m1.template triangularView<Upper>();
+  MatrixType m2up = m2.template triangularView<Upper>();
+
+  if (rows>1 && cols>1)
+  {
+    VERIFY(m1up.isUpperTriangular());
+    VERIFY(m2up.transpose().isLowerTriangular());
+    VERIFY(!m2.isLowerTriangular());
+  }
+
+  // test overloaded operator+=
+  r1.setZero();
+  r2.setZero();
+  r1.template triangularView<Upper>() +=  m1;
+  r2 += m1up;
+  VERIFY_IS_APPROX(r1,r2);
+
+  // test overloaded operator=
+  m1.setZero();
+  m1.template triangularView<Upper>() = 3 * m2;
+  m3 = 3 * m2;
+  VERIFY_IS_APPROX(m3.template triangularView<Upper>().toDenseMatrix(), m1);
+
+
+  m1.setZero();
+  m1.template triangularView<Lower>() = 3 * m2;
+  VERIFY_IS_APPROX(m3.template triangularView<Lower>().toDenseMatrix(), m1);
+
+  m1.setZero();
+  m1.template triangularView<StrictlyUpper>() = 3 * m2;
+  VERIFY_IS_APPROX(m3.template triangularView<StrictlyUpper>().toDenseMatrix(), m1);
+
+
+  m1.setZero();
+  m1.template triangularView<StrictlyLower>() = 3 * m2;
+  VERIFY_IS_APPROX(m3.template triangularView<StrictlyLower>().toDenseMatrix(), m1);
+  m1.setRandom();
+  m2 = m1.template triangularView<Upper>();
+  VERIFY(m2.isUpperTriangular());
+  VERIFY(!m2.isLowerTriangular());
+  m2 = m1.template triangularView<StrictlyUpper>();
+  VERIFY(m2.isUpperTriangular());
+  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
+  m2 = m1.template triangularView<UnitUpper>();
+  VERIFY(m2.isUpperTriangular());
+  m2.diagonal().array() -= Scalar(1);
+  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
+  m2 = m1.template triangularView<Lower>();
+  VERIFY(m2.isLowerTriangular());
+  VERIFY(!m2.isUpperTriangular());
+  m2 = m1.template triangularView<StrictlyLower>();
+  VERIFY(m2.isLowerTriangular());
+  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
+  m2 = m1.template triangularView<UnitLower>();
+  VERIFY(m2.isLowerTriangular());
+  m2.diagonal().array() -= Scalar(1);
+  VERIFY(m2.diagonal().isMuchSmallerThan(RealScalar(1)));
+  // test swap
+  m1.setOnes();
+  m2.setZero();
+  m2.template triangularView<Upper>().swap(m1);
+  m3.setZero();
+  m3.template triangularView<Upper>().setOnes();
+  VERIFY_IS_APPROX(m2,m3);
+}
+
+void bug_159()
+{
+  Matrix3d m = Matrix3d::Random().triangularView<Lower>();
+  EIGEN_UNUSED_VARIABLE(m)
+}
+
+void test_triangular()
+{
+  int maxsize = (std::min)(EIGEN_TEST_MAX_SIZE,20);
+  for(int i = 0; i < g_repeat ; i++)
+  {
+    int r = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(r)
+    int c = internal::random<int>(2,maxsize); TEST_SET_BUT_UNUSED_VARIABLE(c)
+
+    CALL_SUBTEST_1( triangular_square(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( triangular_square(Matrix<float, 2, 2>()) );
+    CALL_SUBTEST_3( triangular_square(Matrix3d()) );
+    CALL_SUBTEST_4( triangular_square(Matrix<std::complex<float>,8, 8>()) );
+    CALL_SUBTEST_5( triangular_square(MatrixXcd(r,r)) );
+    CALL_SUBTEST_6( triangular_square(Matrix<float,Dynamic,Dynamic,RowMajor>(r, r)) );
+
+    CALL_SUBTEST_7( triangular_rect(Matrix<float, 4, 5>()) );
+    CALL_SUBTEST_8( triangular_rect(Matrix<double, 6, 2>()) );
+    CALL_SUBTEST_9( triangular_rect(MatrixXcf(r, c)) );
+    CALL_SUBTEST_5( triangular_rect(MatrixXcd(r, c)) );
+    CALL_SUBTEST_6( triangular_rect(Matrix<float,Dynamic,Dynamic,RowMajor>(r, c)) );
+  }
+  
+  CALL_SUBTEST_1( bug_159() );
+}
diff --git a/test/umeyama.cpp b/test/umeyama.cpp
new file mode 100644
index 0000000..2e80924
--- /dev/null
+++ b/test/umeyama.cpp
@@ -0,0 +1,183 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Hauke Heibel <hauke.heibel@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#include <Eigen/LU> // required for MatrixBase::determinant
+#include <Eigen/SVD> // required for SVD
+
+using namespace Eigen;
+
+//  Constructs a random matrix from the unitary group U(size).
+template <typename T>
+Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixUnitary(int size)
+{
+  typedef T Scalar;
+  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
+
+  MatrixType Q;
+
+  int max_tries = 40;
+  double is_unitary = false;
+
+  while (!is_unitary && max_tries > 0)
+  {
+    // initialize random matrix
+    Q = MatrixType::Random(size, size);
+
+    // orthogonalize columns using the Gram-Schmidt algorithm
+    for (int col = 0; col < size; ++col)
+    {
+      typename MatrixType::ColXpr colVec = Q.col(col);
+      for (int prevCol = 0; prevCol < col; ++prevCol)
+      {
+        typename MatrixType::ColXpr prevColVec = Q.col(prevCol);
+        colVec -= colVec.dot(prevColVec)*prevColVec;
+      }
+      Q.col(col) = colVec.normalized();
+    }
+
+    // this additional orthogonalization is not necessary in theory but should enhance
+    // the numerical orthogonality of the matrix
+    for (int row = 0; row < size; ++row)
+    {
+      typename MatrixType::RowXpr rowVec = Q.row(row);
+      for (int prevRow = 0; prevRow < row; ++prevRow)
+      {
+        typename MatrixType::RowXpr prevRowVec = Q.row(prevRow);
+        rowVec -= rowVec.dot(prevRowVec)*prevRowVec;
+      }
+      Q.row(row) = rowVec.normalized();
+    }
+
+    // final check
+    is_unitary = Q.isUnitary();
+    --max_tries;
+  }
+
+  if (max_tries == 0)
+    eigen_assert(false && "randMatrixUnitary: Could not construct unitary matrix!");
+
+  return Q;
+}
+
+//  Constructs a random matrix from the special unitary group SU(size).
+template <typename T>
+Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> randMatrixSpecialUnitary(int size)
+{
+  typedef T Scalar;
+
+  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
+
+  // initialize unitary matrix
+  MatrixType Q = randMatrixUnitary<Scalar>(size);
+
+  // tweak the first column to make the determinant be 1
+  Q.col(0) *= numext::conj(Q.determinant());
+
+  return Q;
+}
+
+template <typename MatrixType>
+void run_test(int dim, int num_elements)
+{
+  using std::abs;
+  typedef typename internal::traits<MatrixType>::Scalar Scalar;
+  typedef Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixX;
+  typedef Matrix<Scalar, Eigen::Dynamic, 1> VectorX;
+
+  // MUST be positive because in any other case det(cR_t) may become negative for
+  // odd dimensions!
+  const Scalar c = abs(internal::random<Scalar>());
+
+  MatrixX R = randMatrixSpecialUnitary<Scalar>(dim);
+  VectorX t = Scalar(50)*VectorX::Random(dim,1);
+
+  MatrixX cR_t = MatrixX::Identity(dim+1,dim+1);
+  cR_t.block(0,0,dim,dim) = c*R;
+  cR_t.block(0,dim,dim,1) = t;
+
+  MatrixX src = MatrixX::Random(dim+1, num_elements);
+  src.row(dim) = Matrix<Scalar, 1, Dynamic>::Constant(num_elements, Scalar(1));
+
+  MatrixX dst = cR_t*src;
+
+  MatrixX cR_t_umeyama = umeyama(src.block(0,0,dim,num_elements), dst.block(0,0,dim,num_elements));
+
+  const Scalar error = ( cR_t_umeyama*src - dst ).norm() / dst.norm();
+  VERIFY(error < Scalar(40)*std::numeric_limits<Scalar>::epsilon());
+}
+
+template<typename Scalar, int Dimension>
+void run_fixed_size_test(int num_elements)
+{
+  using std::abs;
+  typedef Matrix<Scalar, Dimension+1, Dynamic> MatrixX;
+  typedef Matrix<Scalar, Dimension+1, Dimension+1> HomMatrix;
+  typedef Matrix<Scalar, Dimension, Dimension> FixedMatrix;
+  typedef Matrix<Scalar, Dimension, 1> FixedVector;
+
+  const int dim = Dimension;
+
+  // MUST be positive because in any other case det(cR_t) may become negative for
+  // odd dimensions!
+  // Also if c is to small compared to t.norm(), problem is ill-posed (cf. Bug 744)
+  const Scalar c = internal::random<Scalar>(0.5, 2.0);
+
+  FixedMatrix R = randMatrixSpecialUnitary<Scalar>(dim);
+  FixedVector t = Scalar(32)*FixedVector::Random(dim,1);
+
+  HomMatrix cR_t = HomMatrix::Identity(dim+1,dim+1);
+  cR_t.block(0,0,dim,dim) = c*R;
+  cR_t.block(0,dim,dim,1) = t;
+
+  MatrixX src = MatrixX::Random(dim+1, num_elements);
+  src.row(dim) = Matrix<Scalar, 1, Dynamic>::Constant(num_elements, Scalar(1));
+
+  MatrixX dst = cR_t*src;
+
+  Block<MatrixX, Dimension, Dynamic> src_block(src,0,0,dim,num_elements);
+  Block<MatrixX, Dimension, Dynamic> dst_block(dst,0,0,dim,num_elements);
+
+  HomMatrix cR_t_umeyama = umeyama(src_block, dst_block);
+
+  const Scalar error = ( cR_t_umeyama*src - dst ).squaredNorm();
+
+  VERIFY(error < Scalar(16)*std::numeric_limits<Scalar>::epsilon());
+}
+
+void test_umeyama()
+{
+  for (int i=0; i<g_repeat; ++i)
+  {
+    const int num_elements = internal::random<int>(40,500);
+
+    // works also for dimensions bigger than 3...
+    for (int dim=2; dim<8; ++dim)
+    {
+      CALL_SUBTEST_1(run_test<MatrixXd>(dim, num_elements));
+      CALL_SUBTEST_2(run_test<MatrixXf>(dim, num_elements));
+    }
+
+    CALL_SUBTEST_3((run_fixed_size_test<float, 2>(num_elements)));
+    CALL_SUBTEST_4((run_fixed_size_test<float, 3>(num_elements)));
+    CALL_SUBTEST_5((run_fixed_size_test<float, 4>(num_elements)));
+
+    CALL_SUBTEST_6((run_fixed_size_test<double, 2>(num_elements)));
+    CALL_SUBTEST_7((run_fixed_size_test<double, 3>(num_elements)));
+    CALL_SUBTEST_8((run_fixed_size_test<double, 4>(num_elements)));
+  }
+
+  // Those two calls don't compile and result in meaningful error messages!
+  // umeyama(MatrixXcf(),MatrixXcf());
+  // umeyama(MatrixXcd(),MatrixXcd());
+}
diff --git a/test/umfpack_support.cpp b/test/umfpack_support.cpp
new file mode 100644
index 0000000..9eb84c1
--- /dev/null
+++ b/test/umfpack_support.cpp
@@ -0,0 +1,31 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Gael Guennebaud <g.gael@free.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "sparse_solver.h"
+
+#include <Eigen/UmfPackSupport>
+
+template<typename T> void test_umfpack_support_T()
+{
+  UmfPackLU<SparseMatrix<T, ColMajor> > umfpack_colmajor;
+  UmfPackLU<SparseMatrix<T, RowMajor> > umfpack_rowmajor;
+  
+  check_sparse_square_solving(umfpack_colmajor);
+  check_sparse_square_solving(umfpack_rowmajor);
+  
+  check_sparse_square_determinant(umfpack_colmajor);
+  check_sparse_square_determinant(umfpack_rowmajor);
+}
+
+void test_umfpack_support()
+{
+  CALL_SUBTEST_1(test_umfpack_support_T<double>());
+  CALL_SUBTEST_2(test_umfpack_support_T<std::complex<double> >());
+}
+
diff --git a/test/unalignedassert.cpp b/test/unalignedassert.cpp
new file mode 100644
index 0000000..601dbf2
--- /dev/null
+++ b/test/unalignedassert.cpp
@@ -0,0 +1,127 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+struct TestNew1
+{
+  MatrixXd m; // good: m will allocate its own array, taking care of alignment.
+  TestNew1() : m(20,20) {}
+};
+
+struct TestNew2
+{
+  Matrix3d m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned,
+              // 8-byte alignment is good enough here, which we'll get automatically
+};
+
+struct TestNew3
+{
+  Vector2f m; // good: m's size isn't a multiple of 16 bytes, so m doesn't have to be 16-byte aligned
+};
+
+struct TestNew4
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  Vector2d m;
+  float f; // make the struct have sizeof%16!=0 to make it a little more tricky when we allow an array of 2 such objects
+};
+
+struct TestNew5
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+  float f; // try the f at first -- the EIGEN_ALIGN16 attribute of m should make that still work
+  Matrix4f m;
+};
+
+struct TestNew6
+{
+  Matrix<float,2,2,DontAlign> m; // good: no alignment requested
+  float f;
+};
+
+template<bool Align> struct Depends
+{
+  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(Align)
+  Vector2d m;
+  float f;
+};
+
+template<typename T>
+void check_unalignedassert_good()
+{
+  T *x, *y;
+  x = new T;
+  delete x;
+  y = new T[2];
+  delete[] y;
+}
+
+#if EIGEN_ALIGN_STATICALLY
+template<typename T>
+void construct_at_boundary(int boundary)
+{
+  char buf[sizeof(T)+256];
+  size_t _buf = reinterpret_cast<size_t>(buf);
+  _buf += (16 - (_buf % 16)); // make 16-byte aligned
+  _buf += boundary; // make exact boundary-aligned
+  T *x = ::new(reinterpret_cast<void*>(_buf)) T;
+  x[0].setZero(); // just in order to silence warnings
+  x->~T();
+}
+#endif
+
+void unalignedassert()
+{
+  #if EIGEN_ALIGN_STATICALLY
+  construct_at_boundary<Vector2f>(4);
+  construct_at_boundary<Vector3f>(4);
+  construct_at_boundary<Vector4f>(16);
+  construct_at_boundary<Matrix2f>(16);
+  construct_at_boundary<Matrix3f>(4);
+  construct_at_boundary<Matrix4f>(16);
+
+  construct_at_boundary<Vector2d>(16);
+  construct_at_boundary<Vector3d>(4);
+  construct_at_boundary<Vector4d>(16);
+  construct_at_boundary<Matrix2d>(16);
+  construct_at_boundary<Matrix3d>(4);
+  construct_at_boundary<Matrix4d>(16);
+
+  construct_at_boundary<Vector2cf>(16);
+  construct_at_boundary<Vector3cf>(4);
+  construct_at_boundary<Vector2cd>(16);
+  construct_at_boundary<Vector3cd>(16);
+  #endif
+
+  check_unalignedassert_good<TestNew1>();
+  check_unalignedassert_good<TestNew2>();
+  check_unalignedassert_good<TestNew3>();
+
+  check_unalignedassert_good<TestNew4>();
+  check_unalignedassert_good<TestNew5>();
+  check_unalignedassert_good<TestNew6>();
+  check_unalignedassert_good<Depends<true> >();
+
+#if EIGEN_ALIGN_STATICALLY
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4f>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4f>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2d>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector4d>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix2d>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Matrix4d>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cf>(8));
+  VERIFY_RAISES_ASSERT(construct_at_boundary<Vector2cd>(8));
+#endif
+}
+
+void test_unalignedassert()
+{
+  CALL_SUBTEST(unalignedassert());
+}
diff --git a/test/unalignedcount.cpp b/test/unalignedcount.cpp
new file mode 100644
index 0000000..ca7e159
--- /dev/null
+++ b/test/unalignedcount.cpp
@@ -0,0 +1,46 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2009 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+static int nb_load;
+static int nb_loadu;
+static int nb_store;
+static int nb_storeu;
+
+#define EIGEN_DEBUG_ALIGNED_LOAD    { nb_load++;    }
+#define EIGEN_DEBUG_UNALIGNED_LOAD  { nb_loadu++;   }
+#define EIGEN_DEBUG_ALIGNED_STORE   { nb_store++;   }
+#define EIGEN_DEBUG_UNALIGNED_STORE { nb_storeu++;  }
+
+#define VERIFY_ALIGNED_UNALIGNED_COUNT(XPR,AL,UL,AS,US) {\
+    nb_load = nb_loadu = nb_store = nb_storeu = 0; \
+    XPR; \
+    if(!(nb_load==AL && nb_loadu==UL && nb_store==AS && nb_storeu==US)) \
+      std::cerr << " >> " << nb_load << ", " << nb_loadu << ", " << nb_store << ", " << nb_storeu << "\n"; \
+    VERIFY( (#XPR) && nb_load==AL && nb_loadu==UL && nb_store==AS && nb_storeu==US ); \
+  }
+
+
+#include "main.h"
+
+void test_unalignedcount()
+{
+  #ifdef EIGEN_VECTORIZE_SSE
+  VectorXf a(40), b(40);
+  VERIFY_ALIGNED_UNALIGNED_COUNT(a += b, 20, 0, 10, 0);
+  VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) += b.segment(0,40), 10, 10, 10, 0);
+  VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) -= b.segment(0,40), 10, 10, 10, 0);
+  VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) *= 3.5, 10, 0, 10, 0);
+  VERIFY_ALIGNED_UNALIGNED_COUNT(a.segment(0,40) /= 3.5, 10, 0, 10, 0);
+  #else
+  // The following line is to eliminate "variable not used" warnings
+  nb_load = nb_loadu = nb_store = nb_storeu = 0;
+  int a(0), b(0);
+  VERIFY(a==b);
+  #endif
+}
diff --git a/test/upperbidiagonalization.cpp b/test/upperbidiagonalization.cpp
new file mode 100644
index 0000000..d15bf58
--- /dev/null
+++ b/test/upperbidiagonalization.cpp
@@ -0,0 +1,43 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2010 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+#include <Eigen/SVD>
+
+template<typename MatrixType> void upperbidiag(const MatrixType& m)
+{
+  const typename MatrixType::Index rows = m.rows();
+  const typename MatrixType::Index cols = m.cols();
+
+  typedef Matrix<typename MatrixType::RealScalar, MatrixType::RowsAtCompileTime,  MatrixType::ColsAtCompileTime> RealMatrixType;
+  typedef Matrix<typename MatrixType::Scalar, MatrixType::ColsAtCompileTime,  MatrixType::RowsAtCompileTime> TransposeMatrixType;
+
+  MatrixType a = MatrixType::Random(rows,cols);
+  internal::UpperBidiagonalization<MatrixType> ubd(a);
+  RealMatrixType b(rows, cols);
+  b.setZero();
+  b.block(0,0,cols,cols) = ubd.bidiagonal();
+  MatrixType c = ubd.householderU() * b * ubd.householderV().adjoint();
+  VERIFY_IS_APPROX(a,c);
+  TransposeMatrixType d = ubd.householderV() * b.adjoint() * ubd.householderU().adjoint();
+  VERIFY_IS_APPROX(a.adjoint(),d);
+}
+
+void test_upperbidiagonalization()
+{
+  for(int i = 0; i < g_repeat; i++) {
+   CALL_SUBTEST_1( upperbidiag(MatrixXf(3,3)) );
+   CALL_SUBTEST_2( upperbidiag(MatrixXd(17,12)) );
+   CALL_SUBTEST_3( upperbidiag(MatrixXcf(20,20)) );
+   CALL_SUBTEST_4( upperbidiag(MatrixXcd(16,15)) );
+   CALL_SUBTEST_5( upperbidiag(Matrix<float,6,4>()) );
+   CALL_SUBTEST_6( upperbidiag(Matrix<float,5,5>()) );
+   CALL_SUBTEST_7( upperbidiag(Matrix<double,4,3>()) );
+  }
+}
diff --git a/test/vectorization_logic.cpp b/test/vectorization_logic.cpp
new file mode 100644
index 0000000..aee68a8
--- /dev/null
+++ b/test/vectorization_logic.cpp
@@ -0,0 +1,235 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_DEBUG_ASSIGN
+#include "main.h"
+#include <typeinfo>
+
+std::string demangle_traversal(int t)
+{
+  if(t==DefaultTraversal) return "DefaultTraversal";
+  if(t==LinearTraversal) return "LinearTraversal";
+  if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal";
+  if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal";
+  if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal";
+  return "?";
+}
+std::string demangle_unrolling(int t)
+{
+  if(t==NoUnrolling) return "NoUnrolling";
+  if(t==InnerUnrolling) return "InnerUnrolling";
+  if(t==CompleteUnrolling) return "CompleteUnrolling";
+  return "?";
+}
+
+template<typename Dst, typename Src>
+bool test_assign(const Dst&, const Src&, int traversal, int unrolling)
+{
+  internal::assign_traits<Dst,Src>::debug();
+  bool res = internal::assign_traits<Dst,Src>::Traversal==traversal
+          && internal::assign_traits<Dst,Src>::Unrolling==unrolling;
+  if(!res)
+  {
+    std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
+              << " got " << demangle_traversal(internal::assign_traits<Dst,Src>::Traversal) << "\n";
+    std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
+              << " got " << demangle_unrolling(internal::assign_traits<Dst,Src>::Unrolling) << "\n";
+  }
+  return res;
+}
+
+template<typename Dst, typename Src>
+bool test_assign(int traversal, int unrolling)
+{
+  internal::assign_traits<Dst,Src>::debug();
+  bool res = internal::assign_traits<Dst,Src>::Traversal==traversal
+          && internal::assign_traits<Dst,Src>::Unrolling==unrolling;
+  if(!res)
+  {
+    std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
+              << " got " << demangle_traversal(internal::assign_traits<Dst,Src>::Traversal) << "\n";
+    std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
+              << " got " << demangle_unrolling(internal::assign_traits<Dst,Src>::Unrolling) << "\n";
+  }
+  return res;
+}
+
+template<typename Xpr>
+bool test_redux(const Xpr&, int traversal, int unrolling)
+{
+  typedef internal::redux_traits<internal::scalar_sum_op<typename Xpr::Scalar>,Xpr> traits;
+  bool res = traits::Traversal==traversal && traits::Unrolling==unrolling;
+  if(!res)
+  {
+    std::cerr << " Expected Traversal == " << demangle_traversal(traversal)
+              << " got " << demangle_traversal(traits::Traversal) << "\n";
+    std::cerr << " Expected Unrolling == " << demangle_unrolling(unrolling)
+              << " got " << demangle_unrolling(traits::Unrolling) << "\n";
+  }
+  return res;
+}
+
+template<typename Scalar, bool Enable = internal::packet_traits<Scalar>::Vectorizable> struct vectorization_logic
+{
+  enum {
+    PacketSize = internal::packet_traits<Scalar>::size
+  };
+  static void run()
+  {
+    
+    typedef Matrix<Scalar,PacketSize,1> Vector1;
+    typedef Matrix<Scalar,Dynamic,1> VectorX;
+    typedef Matrix<Scalar,Dynamic,Dynamic> MatrixXX;
+    typedef Matrix<Scalar,PacketSize,PacketSize> Matrix11;
+    typedef Matrix<Scalar,2*PacketSize,2*PacketSize> Matrix22;
+    typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16> Matrix44;
+    typedef Matrix<Scalar,(Matrix11::Flags&RowMajorBit)?16:4*PacketSize,(Matrix11::Flags&RowMajorBit)?4*PacketSize:16,DontAlign|EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION> Matrix44u;
+    typedef Matrix<Scalar,4*PacketSize,16,ColMajor> Matrix44c;
+    typedef Matrix<Scalar,4*PacketSize,16,RowMajor> Matrix44r;
+
+    typedef Matrix<Scalar,
+        (PacketSize==8 ? 4 : PacketSize==4 ? 2 : PacketSize==2 ? 1 : /*PacketSize==1 ?*/ 1),
+        (PacketSize==8 ? 2 : PacketSize==4 ? 2 : PacketSize==2 ? 2 : /*PacketSize==1 ?*/ 1)
+      > Matrix1;
+
+    typedef Matrix<Scalar,
+        (PacketSize==8 ? 4 : PacketSize==4 ? 2 : PacketSize==2 ? 1 : /*PacketSize==1 ?*/ 1),
+        (PacketSize==8 ? 2 : PacketSize==4 ? 2 : PacketSize==2 ? 2 : /*PacketSize==1 ?*/ 1),
+      DontAlign|((Matrix1::Flags&RowMajorBit)?RowMajor:ColMajor)> Matrix1u;
+
+    // this type is made such that it can only be vectorized when viewed as a linear 1D vector
+    typedef Matrix<Scalar,
+        (PacketSize==8 ? 4 : PacketSize==4 ? 6 : PacketSize==2 ? ((Matrix11::Flags&RowMajorBit)?2:3) : /*PacketSize==1 ?*/ 1),
+        (PacketSize==8 ? 6 : PacketSize==4 ? 2 : PacketSize==2 ? ((Matrix11::Flags&RowMajorBit)?3:2) : /*PacketSize==1 ?*/ 3)
+      > Matrix3;
+    
+    #if !EIGEN_GCC_AND_ARCH_DOESNT_WANT_STACK_ALIGNMENT
+    VERIFY(test_assign(Vector1(),Vector1(),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    VERIFY(test_assign(Vector1(),Vector1()+Vector1(),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    VERIFY(test_assign(Vector1(),Vector1().cwiseProduct(Vector1()),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    VERIFY(test_assign(Vector1(),Vector1().template cast<Scalar>(),
+      InnerVectorizedTraversal,CompleteUnrolling));
+
+
+    VERIFY(test_assign(Vector1(),Vector1(),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    VERIFY(test_assign(Vector1(),Vector1()+Vector1(),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    VERIFY(test_assign(Vector1(),Vector1().cwiseProduct(Vector1()),
+      InnerVectorizedTraversal,CompleteUnrolling));
+
+    VERIFY(test_assign(Matrix44(),Matrix44()+Matrix44(),
+      InnerVectorizedTraversal,InnerUnrolling));
+
+    VERIFY(test_assign(Matrix44u(),Matrix44()+Matrix44(),
+      LinearTraversal,NoUnrolling));
+
+    VERIFY(test_assign(Matrix1u(),Matrix1()+Matrix1(),
+      LinearTraversal,CompleteUnrolling));
+
+    VERIFY(test_assign(Matrix44c().col(1),Matrix44c().col(2)+Matrix44c().col(3),
+      InnerVectorizedTraversal,CompleteUnrolling));
+    
+    VERIFY(test_assign(Matrix44r().row(2),Matrix44r().row(1)+Matrix44r().row(1),
+      InnerVectorizedTraversal,CompleteUnrolling));
+        
+    if(PacketSize>1)
+    {
+      typedef Matrix<Scalar,3,3,ColMajor> Matrix33c;
+      VERIFY(test_assign(Matrix33c().row(2),Matrix33c().row(1)+Matrix33c().row(1),
+        LinearTraversal,CompleteUnrolling));
+      VERIFY(test_assign(Matrix33c().col(0),Matrix33c().col(1)+Matrix33c().col(1),
+        LinearTraversal,CompleteUnrolling));
+      
+      VERIFY(test_assign(Matrix3(),Matrix3().cwiseQuotient(Matrix3()),
+        LinearVectorizedTraversal,CompleteUnrolling));
+
+      VERIFY(test_assign(Matrix<Scalar,17,17>(),Matrix<Scalar,17,17>()+Matrix<Scalar,17,17>(),
+        LinearTraversal,NoUnrolling));
+
+      VERIFY(test_assign(Matrix11(),Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(2,3)+Matrix<Scalar,17,17>().template block<PacketSize,PacketSize>(10,4),
+      DefaultTraversal,CompleteUnrolling));
+    }
+    
+    VERIFY(test_redux(Matrix3(),
+      LinearVectorizedTraversal,CompleteUnrolling));
+
+    VERIFY(test_redux(Matrix44(),
+      LinearVectorizedTraversal,NoUnrolling));
+
+    VERIFY(test_redux(Matrix44().template block<(Matrix1::Flags&RowMajorBit)?4:PacketSize,(Matrix1::Flags&RowMajorBit)?PacketSize:4>(1,2),
+      DefaultTraversal,CompleteUnrolling));
+
+    VERIFY(test_redux(Matrix44c().template block<2*PacketSize,1>(1,2),
+      LinearVectorizedTraversal,CompleteUnrolling));
+
+    VERIFY(test_redux(Matrix44r().template block<1,2*PacketSize>(2,1),
+      LinearVectorizedTraversal,CompleteUnrolling));
+    
+    VERIFY((test_assign<
+            Map<Matrix22, Aligned, OuterStride<3*PacketSize> >,
+            Matrix22
+            >(InnerVectorizedTraversal,CompleteUnrolling)));
+
+    VERIFY((test_assign<
+            Map<Matrix22, Aligned, InnerStride<3*PacketSize> >,
+            Matrix22
+            >(DefaultTraversal,CompleteUnrolling)));
+
+    VERIFY((test_assign(Matrix11(), Matrix11()*Matrix11(), InnerVectorizedTraversal, CompleteUnrolling)));
+    #endif
+
+    VERIFY(test_assign(MatrixXX(10,10),MatrixXX(20,20).block(10,10,2,3),
+      SliceVectorizedTraversal,NoUnrolling));
+
+    VERIFY(test_redux(VectorX(10),
+      LinearVectorizedTraversal,NoUnrolling));
+
+    
+  }
+};
+
+template<typename Scalar> struct vectorization_logic<Scalar,false>
+{
+  static void run() {}
+};
+
+void test_vectorization_logic()
+{
+
+#ifdef EIGEN_VECTORIZE
+
+  CALL_SUBTEST( vectorization_logic<float>::run() );
+  CALL_SUBTEST( vectorization_logic<double>::run() );
+  CALL_SUBTEST( vectorization_logic<std::complex<float> >::run() );
+  CALL_SUBTEST( vectorization_logic<std::complex<double> >::run() );
+  
+  if(internal::packet_traits<float>::Vectorizable)
+  {
+    VERIFY(test_assign(Matrix<float,3,3>(),Matrix<float,3,3>()+Matrix<float,3,3>(),
+      LinearTraversal,CompleteUnrolling));
+      
+    VERIFY(test_redux(Matrix<float,5,2>(),
+      DefaultTraversal,CompleteUnrolling));
+  }
+  
+  if(internal::packet_traits<double>::Vectorizable)
+  {
+    VERIFY(test_assign(Matrix<double,3,3>(),Matrix<double,3,3>()+Matrix<double,3,3>(),
+      LinearTraversal,CompleteUnrolling));
+    
+    VERIFY(test_redux(Matrix<double,7,3>(),
+      DefaultTraversal,CompleteUnrolling));
+  }
+#endif // EIGEN_VECTORIZE
+
+}
diff --git a/test/vectorwiseop.cpp b/test/vectorwiseop.cpp
new file mode 100644
index 0000000..6cd1acd
--- /dev/null
+++ b/test/vectorwiseop.cpp
@@ -0,0 +1,205 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#define EIGEN_NO_STATIC_ASSERT
+
+#include "main.h"
+
+template<typename ArrayType> void vectorwiseop_array(const ArrayType& m)
+{
+  typedef typename ArrayType::Index Index;
+  typedef typename ArrayType::Scalar Scalar;
+  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
+  typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  ArrayType m1 = ArrayType::Random(rows, cols),
+            m2(rows, cols),
+            m3(rows, cols);
+
+  ColVectorType colvec = ColVectorType::Random(rows);
+  RowVectorType rowvec = RowVectorType::Random(cols);
+
+  // test addition
+
+  m2 = m1;
+  m2.colwise() += colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() += rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
+
+  // test substraction
+
+  m2 = m1;
+  m2.colwise() -= colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() -= rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
+
+  // test multiplication
+
+  m2 = m1;
+  m2.colwise() *= colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() * colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) * colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() *= colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() * colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() *= rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() * rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) * rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() *= rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() * rowvec.transpose());
+
+  // test quotient
+
+  m2 = m1;
+  m2.colwise() /= colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() / colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) / colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() /= colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() / colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() /= rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() / rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) / rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() /= rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() / rowvec.transpose());
+  
+  m2 = m1;
+  // yes, there might be an aliasing issue there but ".rowwise() /="
+  // is suppposed to evaluate " m2.colwise().sum()" into to temporary to avoid
+  // evaluating the reducions multiple times
+  if(ArrayType::RowsAtCompileTime>2 || ArrayType::RowsAtCompileTime==Dynamic)
+  {
+    m2.rowwise() /= m2.colwise().sum();
+    VERIFY_IS_APPROX(m2, m1.rowwise() / m1.colwise().sum());
+  }
+}
+
+template<typename MatrixType> void vectorwiseop_matrix(const MatrixType& m)
+{
+  typedef typename MatrixType::Index Index;
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename NumTraits<Scalar>::Real RealScalar;
+  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> ColVectorType;
+  typedef Matrix<Scalar, 1, MatrixType::ColsAtCompileTime> RowVectorType;
+  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealColVectorType;
+  typedef Matrix<RealScalar, 1, MatrixType::ColsAtCompileTime> RealRowVectorType;
+
+  Index rows = m.rows();
+  Index cols = m.cols();
+  Index r = internal::random<Index>(0, rows-1),
+        c = internal::random<Index>(0, cols-1);
+
+  MatrixType m1 = MatrixType::Random(rows, cols),
+            m2(rows, cols),
+            m3(rows, cols);
+
+  ColVectorType colvec = ColVectorType::Random(rows);
+  RowVectorType rowvec = RowVectorType::Random(cols);
+  RealColVectorType rcres;
+  RealRowVectorType rrres;
+
+  // test addition
+
+  m2 = m1;
+  m2.colwise() += colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() + colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) + colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() += colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() + colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() += rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() + rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) + rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() += rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() + rowvec.transpose());
+
+  // test substraction
+
+  m2 = m1;
+  m2.colwise() -= colvec;
+  VERIFY_IS_APPROX(m2, m1.colwise() - colvec);
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c) - colvec);
+
+  VERIFY_RAISES_ASSERT(m2.colwise() -= colvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.colwise() - colvec.transpose());
+
+  m2 = m1;
+  m2.rowwise() -= rowvec;
+  VERIFY_IS_APPROX(m2, m1.rowwise() - rowvec);
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r) - rowvec);
+
+  VERIFY_RAISES_ASSERT(m2.rowwise() -= rowvec.transpose());
+  VERIFY_RAISES_ASSERT(m1.rowwise() - rowvec.transpose());
+  
+  // test norm
+  rrres = m1.colwise().norm();
+  VERIFY_IS_APPROX(rrres(c), m1.col(c).norm());
+  rcres = m1.rowwise().norm();
+  VERIFY_IS_APPROX(rcres(r), m1.row(r).norm());
+  
+  // test normalized
+  m2 = m1.colwise().normalized();
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
+  m2 = m1.rowwise().normalized();
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
+  
+  // test normalize
+  m2 = m1;
+  m2.colwise().normalize();
+  VERIFY_IS_APPROX(m2.col(c), m1.col(c).normalized());
+  m2 = m1;
+  m2.rowwise().normalize();
+  VERIFY_IS_APPROX(m2.row(r), m1.row(r).normalized());
+}
+
+void test_vectorwiseop()
+{
+  CALL_SUBTEST_1(vectorwiseop_array(Array22cd()));
+  CALL_SUBTEST_2(vectorwiseop_array(Array<double, 3, 2>()));
+  CALL_SUBTEST_3(vectorwiseop_array(ArrayXXf(3, 4)));
+  CALL_SUBTEST_4(vectorwiseop_matrix(Matrix4cf()));
+  CALL_SUBTEST_5(vectorwiseop_matrix(Matrix<float,4,5>()));
+  CALL_SUBTEST_6(vectorwiseop_matrix(MatrixXd(7,2)));
+}
diff --git a/test/visitor.cpp b/test/visitor.cpp
new file mode 100644
index 0000000..39a5d6b
--- /dev/null
+++ b/test/visitor.cpp
@@ -0,0 +1,130 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+template<typename MatrixType> void matrixVisitor(const MatrixType& p)
+{
+  typedef typename MatrixType::Scalar Scalar;
+  typedef typename MatrixType::Index Index;
+
+  Index rows = p.rows();
+  Index cols = p.cols();
+
+  // construct a random matrix where all coefficients are different
+  MatrixType m;
+  m = MatrixType::Random(rows, cols);
+  for(Index i = 0; i < m.size(); i++)
+    for(Index i2 = 0; i2 < i; i2++)
+      while(m(i) == m(i2)) // yes, ==
+        m(i) = internal::random<Scalar>();
+  
+  Scalar minc = Scalar(1000), maxc = Scalar(-1000);
+  Index minrow=0,mincol=0,maxrow=0,maxcol=0;
+  for(Index j = 0; j < cols; j++)
+  for(Index i = 0; i < rows; i++)
+  {
+    if(m(i,j) < minc)
+    {
+      minc = m(i,j);
+      minrow = i;
+      mincol = j;
+    }
+    if(m(i,j) > maxc)
+    {
+      maxc = m(i,j);
+      maxrow = i;
+      maxcol = j;
+    }
+  }
+  Index eigen_minrow, eigen_mincol, eigen_maxrow, eigen_maxcol;
+  Scalar eigen_minc, eigen_maxc;
+  eigen_minc = m.minCoeff(&eigen_minrow,&eigen_mincol);
+  eigen_maxc = m.maxCoeff(&eigen_maxrow,&eigen_maxcol);
+  VERIFY(minrow == eigen_minrow);
+  VERIFY(maxrow == eigen_maxrow);
+  VERIFY(mincol == eigen_mincol);
+  VERIFY(maxcol == eigen_maxcol);
+  VERIFY_IS_APPROX(minc, eigen_minc);
+  VERIFY_IS_APPROX(maxc, eigen_maxc);
+  VERIFY_IS_APPROX(minc, m.minCoeff());
+  VERIFY_IS_APPROX(maxc, m.maxCoeff());
+}
+
+template<typename VectorType> void vectorVisitor(const VectorType& w)
+{
+  typedef typename VectorType::Scalar Scalar;
+  typedef typename VectorType::Index Index;
+
+  Index size = w.size();
+
+  // construct a random vector where all coefficients are different
+  VectorType v;
+  v = VectorType::Random(size);
+  for(Index i = 0; i < size; i++)
+    for(Index i2 = 0; i2 < i; i2++)
+      while(v(i) == v(i2)) // yes, ==
+        v(i) = internal::random<Scalar>();
+  
+  Scalar minc = v(0), maxc = v(0);
+  Index minidx=0, maxidx=0;
+  for(Index i = 0; i < size; i++)
+  {
+    if(v(i) < minc)
+    {
+      minc = v(i);
+      minidx = i;
+    }
+    if(v(i) > maxc)
+    {
+      maxc = v(i);
+      maxidx = i;
+    }
+  }
+  Index eigen_minidx, eigen_maxidx;
+  Scalar eigen_minc, eigen_maxc;
+  eigen_minc = v.minCoeff(&eigen_minidx);
+  eigen_maxc = v.maxCoeff(&eigen_maxidx);
+  VERIFY(minidx == eigen_minidx);
+  VERIFY(maxidx == eigen_maxidx);
+  VERIFY_IS_APPROX(minc, eigen_minc);
+  VERIFY_IS_APPROX(maxc, eigen_maxc);
+  VERIFY_IS_APPROX(minc, v.minCoeff());
+  VERIFY_IS_APPROX(maxc, v.maxCoeff());
+  
+  Index idx0 = internal::random<Index>(0,size-1);
+  Index idx1 = eigen_minidx;
+  Index idx2 = eigen_maxidx;
+  VectorType v1(v), v2(v);
+  v1(idx0) = v1(idx1);
+  v2(idx0) = v2(idx2);
+  v1.minCoeff(&eigen_minidx);
+  v2.maxCoeff(&eigen_maxidx);
+  VERIFY(eigen_minidx == (std::min)(idx0,idx1));
+  VERIFY(eigen_maxidx == (std::min)(idx0,idx2));
+}
+
+void test_visitor()
+{
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_1( matrixVisitor(Matrix<float, 1, 1>()) );
+    CALL_SUBTEST_2( matrixVisitor(Matrix2f()) );
+    CALL_SUBTEST_3( matrixVisitor(Matrix4d()) );
+    CALL_SUBTEST_4( matrixVisitor(MatrixXd(8, 12)) );
+    CALL_SUBTEST_5( matrixVisitor(Matrix<double,Dynamic,Dynamic,RowMajor>(20, 20)) );
+    CALL_SUBTEST_6( matrixVisitor(MatrixXi(8, 12)) );
+  }
+  for(int i = 0; i < g_repeat; i++) {
+    CALL_SUBTEST_7( vectorVisitor(Vector4f()) );
+    CALL_SUBTEST_7( vectorVisitor(Matrix<int,12,1>()) );
+    CALL_SUBTEST_8( vectorVisitor(VectorXd(10)) );
+    CALL_SUBTEST_9( vectorVisitor(RowVectorXd(10)) );
+    CALL_SUBTEST_10( vectorVisitor(VectorXf(33)) );
+  }
+}
diff --git a/test/zerosized.cpp b/test/zerosized.cpp
new file mode 100644
index 0000000..da7dd04
--- /dev/null
+++ b/test/zerosized.cpp
@@ -0,0 +1,84 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011 Benoit Jacob <jacob.benoit.1@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "main.h"
+
+
+template<typename MatrixType> void zeroReduction(const MatrixType& m) {
+  // Reductions that must hold for zero sized objects
+  VERIFY(m.all());
+  VERIFY(!m.any());
+  VERIFY(m.prod()==1);
+  VERIFY(m.sum()==0);
+  VERIFY(m.count()==0);
+  VERIFY(m.allFinite());
+  VERIFY(!m.hasNaN());
+}
+
+
+template<typename MatrixType> void zeroSizedMatrix()
+{
+  MatrixType t1;
+
+  if (MatrixType::SizeAtCompileTime == Dynamic || MatrixType::SizeAtCompileTime == 0)
+  {
+    zeroReduction(t1);
+    if (MatrixType::RowsAtCompileTime == Dynamic)
+      VERIFY(t1.rows() == 0);
+    if (MatrixType::ColsAtCompileTime == Dynamic)
+      VERIFY(t1.cols() == 0);
+
+    if (MatrixType::RowsAtCompileTime == Dynamic && MatrixType::ColsAtCompileTime == Dynamic)
+    {
+
+      MatrixType t2(0, 0);
+      VERIFY(t2.rows() == 0);
+      VERIFY(t2.cols() == 0);
+
+      zeroReduction(t2);
+      VERIFY(t1==t2);
+    }
+  }
+}
+
+template<typename VectorType> void zeroSizedVector()
+{
+  VectorType t1;
+
+  if (VectorType::SizeAtCompileTime == Dynamic || VectorType::SizeAtCompileTime==0)
+  {
+    zeroReduction(t1);
+    VERIFY(t1.size() == 0);
+    VectorType t2(DenseIndex(0)); // DenseIndex disambiguates with 0-the-null-pointer (error with gcc 4.4 and MSVC8)
+    VERIFY(t2.size() == 0);
+    zeroReduction(t2);
+
+    VERIFY(t1==t2);
+  }
+}
+
+void test_zerosized()
+{
+  zeroSizedMatrix<Matrix2d>();
+  zeroSizedMatrix<Matrix3i>();
+  zeroSizedMatrix<Matrix<float, 2, Dynamic> >();
+  zeroSizedMatrix<MatrixXf>();
+  zeroSizedMatrix<Matrix<float, 0, 0> >();
+  zeroSizedMatrix<Matrix<float, Dynamic, 0, 0, 0, 0> >();
+  zeroSizedMatrix<Matrix<float, 0, Dynamic, 0, 0, 0> >();
+  zeroSizedMatrix<Matrix<float, Dynamic, Dynamic, 0, 0, 0> >();
+  zeroSizedMatrix<Matrix<float, 0, 4> >();
+  zeroSizedMatrix<Matrix<float, 4, 0> >();
+
+  zeroSizedVector<Vector2d>();
+  zeroSizedVector<Vector3i>();
+  zeroSizedVector<VectorXf>();
+  zeroSizedVector<Matrix<float, 0, 1> >();
+  zeroSizedVector<Matrix<float, 1, 0> >();
+}