// 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 Index rows = m.rows();
  const 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);
}

EIGEN_DECLARE_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(Matrix<std::complex<double>,Dynamic,Dynamic,RowMajor>(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>()) );
  }
}
