Example #1
0
/*************************************************************************
Finding the eigenvalues and eigenvectors of a symmetric matrix

The algorithm finds eigen pairs of a symmetric matrix by reducing it to
tridiagonal form and using the QL/QR algorithm.

Input parameters:
    A       -   symmetric matrix which is given by its upper or lower
                triangular part.
                Array whose indexes range within [0..N-1, 0..N-1].
    N       -   size of matrix A.
    IsUpper -   storage format.
    ZNeeded -   flag controlling whether the eigenvectors are needed or not.
                If ZNeeded is equal to:
                 * 0, the eigenvectors are not returned;
                 * 1, the eigenvectors are returned.

Output parameters:
    D       -   eigenvalues in ascending order.
                Array whose index ranges within [0..N-1].
    Z       -   if ZNeeded is equal to:
                 * 0, Z hasn’t changed;
                 * 1, Z contains the eigenvectors.
                Array whose indexes range within [0..N-1, 0..N-1].
                The eigenvectors are stored in the matrix columns.

Result:
    True, if the algorithm has converged.
    False, if the algorithm hasn't converged (rare case).

  -- ALGLIB --
     Copyright 2005-2008 by Bochkanov Sergey
*************************************************************************/
bool smatrixevd(ap::real_2d_array a,
     int n,
     int zneeded,
     bool isupper,
     ap::real_1d_array& d,
     ap::real_2d_array& z)
{
    bool result;
    ap::real_1d_array tau;
    ap::real_1d_array e;

    ap::ap_error::make_assertion(zneeded==0||zneeded==1, "SMatrixEVD: incorrect ZNeeded");
    smatrixtd(a, n, isupper, tau, d, e);
    if( zneeded==1 )
    {
        smatrixtdunpackq(a, n, isupper, tau, z);
    }
    result = smatrixtdevd(d, e, n, zneeded, z);
    return result;
}
/*************************************************************************
Subroutine for finding the eigenvalues (and eigenvectors) of  a  symmetric
matrix  in  a  given half open interval (A, B] by using  a  bisection  and
inverse iteration

Input parameters:
    A       -   symmetric matrix which is given by its upper or lower
                triangular part. Array [0..N-1, 0..N-1].
    N       -   size of matrix A.
    ZNeeded -   flag controlling whether the eigenvectors are needed or not.
                If ZNeeded is equal to:
                 * 0, the eigenvectors are not returned;
                 * 1, the eigenvectors are returned.
    IsUpperA -  storage format of matrix A.
    B1, B2 -    half open interval (B1, B2] to search eigenvalues in.

Output parameters:
    M       -   number of eigenvalues found in a given half-interval (M>=0).
    W       -   array of the eigenvalues found.
                Array whose index ranges within [0..M-1].
    Z       -   if ZNeeded is equal to:
                 * 0, Z hasn’t changed;
                 * 1, Z contains eigenvectors.
                Array whose indexes range within [0..N-1, 0..M-1].
                The eigenvectors are stored in the matrix columns.

Result:
    True, if successful. M contains the number of eigenvalues in the given
    half-interval (could be equal to 0), W contains the eigenvalues,
    Z contains the eigenvectors (if needed).

    False, if the bisection method subroutine wasn't able to find the
    eigenvalues in the given interval or if the inverse iteration subroutine
    wasn't able to find all the corresponding eigenvectors.
    In that case, the eigenvalues and eigenvectors are not returned,
    M is equal to 0.

  -- ALGLIB --
     Copyright 07.01.2006 by Bochkanov Sergey
*************************************************************************/
bool smatrixevdr(ap::real_2d_array a,
     int n,
     int zneeded,
     bool isupper,
     double b1,
     double b2,
     int& m,
     ap::real_1d_array& w,
     ap::real_2d_array& z)
{
    bool result;
    ap::real_1d_array tau;
    ap::real_1d_array e;

    ap::ap_error::make_assertion(zneeded==0||zneeded==1, "SMatrixTDEVDR: incorrect ZNeeded");
    smatrixtd(a, n, isupper, tau, w, e);
    if( zneeded==1 )
    {
        smatrixtdunpackq(a, n, isupper, tau, z);
    }
    result = smatrixtdevdr(w, e, n, zneeded, b1, b2, m, z);
    return result;
}
static void teststdproblem(const ap::real_2d_array& a,
     int n,
     double& materr,
     double& orterr)
{
    int i;
    int j;
    ap::real_2d_array ua;
    ap::real_2d_array la;
    ap::real_2d_array t;
    ap::real_2d_array q;
    ap::real_2d_array t2;
    ap::real_2d_array t3;
    ap::real_1d_array tau;
    ap::real_1d_array d;
    ap::real_1d_array e;
    double v;

    ua.setbounds(0, n-1, 0, n-1);
    la.setbounds(0, n-1, 0, n-1);
    t.setbounds(0, n-1, 0, n-1);
    q.setbounds(0, n-1, 0, n-1);
    t2.setbounds(0, n-1, 0, n-1);
    t3.setbounds(0, n-1, 0, n-1);
    
    //
    // fill
    //
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            ua(i,j) = 0;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = i; j <= n-1; j++)
        {
            ua(i,j) = a(i,j);
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            la(i,j) = 0;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= i; j++)
        {
            la(i,j) = a(i,j);
        }
    }
    
    //
    // Test 2tridiagonal: upper
    //
    smatrixtd(ua, n, true, tau, d, e);
    smatrixtdunpackq(ua, n, true, tau, q);
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            t(i,j) = 0;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        t(i,i) = d(i);
    }
    for(i = 0; i <= n-2; i++)
    {
        t(i,i+1) = e(i);
        t(i+1,i) = e(i);
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(q.getcolumn(i, 0, n-1), a.getcolumn(j, 0, n-1));
            t2(i,j) = v;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(t2.getrow(i, 0, n-1), q.getcolumn(j, 0, n-1));
            t3(i,j) = v;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            materr = ap::maxreal(materr, ap::abscomplex(t3(i,j)-t(i,j)));
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(&q(i, 0), &q(j, 0), ap::vlen(0,n-1));
            if( i==j )
            {
                orterr = ap::maxreal(orterr, ap::abscomplex(v-1));
            }
            else
            {
                orterr = ap::maxreal(orterr, ap::abscomplex(v));
            }
        }
    }
    
    //
    // Test 2tridiagonal: lower
    //
    smatrixtd(la, n, false, tau, d, e);
    smatrixtdunpackq(la, n, false, tau, q);
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            t(i,j) = 0;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        t(i,i) = d(i);
    }
    for(i = 0; i <= n-2; i++)
    {
        t(i,i+1) = e(i);
        t(i+1,i) = e(i);
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(q.getcolumn(i, 0, n-1), a.getcolumn(j, 0, n-1));
            t2(i,j) = v;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(t2.getrow(i, 0, n-1), q.getcolumn(j, 0, n-1));
            t3(i,j) = v;
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            materr = ap::maxreal(materr, ap::abscomplex(t3(i,j)-t(i,j)));
        }
    }
    for(i = 0; i <= n-1; i++)
    {
        for(j = 0; j <= n-1; j++)
        {
            v = ap::vdotproduct(&q(i, 0), &q(j, 0), ap::vlen(0,n-1));
            if( i==j )
            {
                orterr = ap::maxreal(orterr, ap::abscomplex(v-1));
            }
            else
            {
                orterr = ap::maxreal(orterr, ap::abscomplex(v));
            }
        }
    }
}