1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "main.h"
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <Eigen/LU>
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename MatrixType> void inverse(const MatrixType& m)
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  using std::abs;
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Index Index;
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  /* this test covers the following files:
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath     Inverse.h
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  */
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index rows = m.rows();
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  Index cols = m.cols();
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef typename MatrixType::Scalar Scalar;
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m1(rows, cols),
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             m2(rows, cols),
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath             identity = MatrixType::Identity(rows, rows);
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  createRandomPIMatrixOfRank(rows,rows,rows,m1);
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2 = m1.inverse();
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1, m2.inverse() );
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX((Scalar(2)*m2).inverse(), m2.inverse()*Scalar(0.5));
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(identity, m1.inverse() * m1 );
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(identity, m1 * m1.inverse() );
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(m1, m1.inverse().inverse() );
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // since for the general case we implement separately row-major and col-major, test that
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(MatrixType(m1.transpose().inverse()), MatrixType(m1.inverse().transpose()));
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#if !defined(EIGEN_TEST_PART_5) && !defined(EIGEN_TEST_PART_6)
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef typename NumTraits<Scalar>::Real RealScalar;
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  typedef Matrix<Scalar, MatrixType::ColsAtCompileTime, 1> VectorType;
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  //computeInverseAndDetWithCheck tests
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  //First: an invertible matrix
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  bool invertible;
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  RealScalar det;
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2.setZero();
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m1.computeInverseAndDetWithCheck(m2, det, invertible);
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(invertible);
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(identity, m1*m2);
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(det, m1.determinant());
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m2.setZero();
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m1.computeInverseWithCheck(m2, invertible);
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY(invertible);
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY_IS_APPROX(identity, m1*m2);
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  //Second: a rank one matrix (not invertible, except for 1x1 matrices)
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VectorType v3 = VectorType::Random(rows);
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  MatrixType m3 = v3*v3.transpose(), m4(rows,cols);
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.computeInverseAndDetWithCheck(m4, det, invertible);
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY( rows==1 ? invertible : !invertible );
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  VERIFY_IS_MUCH_SMALLER_THAN(abs(det-m3.determinant()), RealScalar(1));
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  m3.computeInverseWithCheck(m4, invertible);
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  VERIFY( rows==1 ? invertible : !invertible );
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // check in-place inversion
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if(MatrixType::RowsAtCompileTime>=2 && MatrixType::RowsAtCompileTime<=4)
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    // in-place is forbidden
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_RAISES_ASSERT(m1 = m1.inverse());
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  else
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m2 = m1.inverse();
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    m1 = m1.inverse();
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    VERIFY_IS_APPROX(m1,m2);
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid test_inverse()
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  int s = 0;
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for(int i = 0; i < g_repeat; i++) {
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_1( inverse(Matrix<double,1,1>()) );
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_2( inverse(Matrix2d()) );
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_3( inverse(Matrix3f()) );
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_4( inverse(Matrix4f()) );
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_4( inverse(Matrix<float,4,4,DontAlign>()) );
967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    s = internal::random<int>(50,320);
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_5( inverse(MatrixXf(s,s)) );
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    s = internal::random<int>(25,100);
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_6( inverse(MatrixXcd(s,s)) );
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_7( inverse(Matrix4d()) );
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    CALL_SUBTEST_7( inverse(Matrix<double,4,4,DontAlign>()) );
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  TEST_SET_BUT_UNUSED_VARIABLE(s)
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
105