File: Schur.cpp

package info (click to toggle)
spectra 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,788 kB
  • sloc: cpp: 23,044; ansic: 175; fortran: 131; makefile: 90
file content (69 lines) | stat: -rw-r--r-- 2,177 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Test ../include/Spectra/LinAlg/UpperHessenbergSchur.h
#include <iostream>
#include <Eigen/Core>
#include <Spectra/LinAlg/UpperHessenbergSchur.h>

#include "catch.hpp"

using namespace Spectra;

using Matrix = Eigen::MatrixXd;
using Vector = Eigen::VectorXd;

// Schur decomposition on an upper Hessenberg matrix
void run_test(const Matrix& A)
{
    // Spectra implementation
    UpperHessenbergSchur<double> decomp(A);
    const Matrix& matT = decomp.matrix_T();
    const Matrix& matU = decomp.matrix_U();

    // Test whether T is upper Hessenberg
    Matrix lowerT = matT.triangularView<Eigen::StrictlyLower>();
    lowerT.diagonal(-1).setZero();
    INFO("||lower T||_inf = " << lowerT.cwiseAbs().maxCoeff());
    REQUIRE(lowerT.cwiseAbs().maxCoeff() == Approx(0.0).margin(1e-16));

    // Test whether Q is orthonormal
    constexpr double tol = 1e-12;
    const int n = A.rows();
    Matrix I = Matrix::Identity(n, n);
    Matrix resid1 = matU.transpose() * matU - I;
    Matrix resid2 = matU * matU.transpose() - I;
    INFO("||U'U - I||_inf = " << resid1.cwiseAbs().maxCoeff());
    REQUIRE(resid1.cwiseAbs().maxCoeff() == Approx(0.0).margin(tol));
    INFO("||UU' - I||_inf = " << resid2.cwiseAbs().maxCoeff());
    REQUIRE(resid2.cwiseAbs().maxCoeff() == Approx(0.0).margin(tol));

    // Test whether AU=UT
    Matrix resid3 = A * matU - matU * matT;
    INFO("||AU - UT||_inf = " << resid3.cwiseAbs().maxCoeff());
    REQUIRE(resid3.cwiseAbs().maxCoeff() == Approx(0.0).margin(tol));
}

Matrix gen_upper_hessenberg_mat(int n)
{
    std::srand(123);
    Matrix A = Matrix::Random(n, n);
    A.triangularView<Eigen::StrictlyLower>().setZero();
    A.diagonal(-1).array() = Vector::Random(n - 1).array();
    return A;
}

TEST_CASE("Schur decomposition of upper Hessenberg matrix [10x10]", "[Schur]")
{
    Matrix A = gen_upper_hessenberg_mat(10);
    run_test(A);
}

TEST_CASE("Schur decomposition of upper Hessenberg matrix [100x100]", "[Schur]")
{
    Matrix A = gen_upper_hessenberg_mat(100);
    run_test(A);
}

TEST_CASE("Schur decomposition of upper Hessenberg matrix [500x500]", "[Schur]")
{
    Matrix A = gen_upper_hessenberg_mat(500);
    run_test(A);
}