Esempio n. 1
0
/*************************************************************************
Solving a system of linear equations with a system matrix given by its
LU decomposition.

The algorithm solves a system of linear equations whose matrix is given by
its LU decomposition. In case of a singular matrix, the algorithm  returns
False.

The algorithm solves systems with a square matrix only.

Input parameters:
    A       -   LU decomposition of a system matrix in compact  form  (the
                result of the RMatrixLU subroutine).
    Pivots  -   row permutation table (the result of a
                RMatrixLU subroutine).
    B       -   right side of a system.
                Array whose index ranges within [0..N-1].
    N       -   size of matrix A.

Output parameters:
    X       -   solution of a system.
                Array whose index ranges within [0..N-1].

Result:
    True, if the matrix is not singular.
    False, if the matrux is singular. In this case, X doesn't contain a
solution.

  -- ALGLIB --
     Copyright 2005-2008 by Bochkanov Sergey
*************************************************************************/
bool cmatrixlusolve(const ap::complex_2d_array& a,
                    const ap::integer_1d_array& pivots,
                    ap::complex_1d_array b,
                    int n,
                    ap::complex_1d_array& x)
{
    bool result;
    ap::complex_1d_array y;
    int i;
    int j;
    ap::complex v;
    int i_;

    y.setbounds(0, n-1);
    x.setbounds(0, n-1);
    result = true;
    for(i = 0; i <= n-1; i++)
    {
        if( a(i,i)==0 )
        {
            result = false;
            return result;
        }
    }

    //
    // pivots
    //
    for(i = 0; i <= n-1; i++)
    {
        if( pivots(i)!=i )
        {
            v = b(i);
            b(i) = b(pivots(i));
            b(pivots(i)) = v;
        }
    }

    //
    // Ly = b
    //
    y(0) = b(0);
    for(i = 1; i <= n-1; i++)
    {
        v = 0.0;
        for(i_=0; i_<=i-1; i_++)
        {
            v += a(i,i_)*y(i_);
        }
        y(i) = b(i)-v;
    }

    //
    // Ux = y
    //
    x(n-1) = y(n-1)/a(n-1,n-1);
    for(i = n-2; i >= 0; i--)
    {
        v = 0.0;
        for(i_=i+1; i_<=n-1; i_++)
        {
            v += a(i,i_)*x(i_);
        }
        x(i) = (y(i)-v)/a(i,i);
    }
    return result;
}
Esempio n. 2
0
/*************************************************************************
Reduction of a Hermitian matrix which is given  by  its  higher  or  lower
triangular part to a real  tridiagonal  matrix  using  unitary  similarity
transformation: Q'*A*Q = T.

Input parameters:
    A       -   matrix to be transformed
                array with elements [0..N-1, 0..N-1].
    N       -   size of matrix A.
    IsUpper -   storage format. If IsUpper = True, then matrix A is  given
                by its upper triangle, and the lower triangle is not  used
                and not modified by the algorithm, and vice versa
                if IsUpper = False.

Output parameters:
    A       -   matrices T and Q in  compact form (see lower)
    Tau     -   array of factors which are forming matrices H(i)
                array with elements [0..N-2].
    D       -   main diagonal of real symmetric matrix T.
                array with elements [0..N-1].
    E       -   secondary diagonal of real symmetric matrix T.
                array with elements [0..N-2].


  If IsUpper=True, the matrix Q is represented as a product of elementary
  reflectors

     Q = H(n-2) . . . H(2) H(0).

  Each H(i) has the form

     H(i) = I - tau * v * v'

  where tau is a complex scalar, and v is a complex vector with
  v(i+1:n-1) = 0, v(i) = 1, v(0:i-1) is stored on exit in
  A(0:i-1,i+1), and tau in TAU(i).

  If IsUpper=False, the matrix Q is represented as a product of elementary
  reflectors

     Q = H(0) H(2) . . . H(n-2).

  Each H(i) has the form

     H(i) = I - tau * v * v'

  where tau is a complex scalar, and v is a complex vector with
  v(0:i) = 0, v(i+1) = 1, v(i+2:n-1) is stored on exit in A(i+2:n-1,i),
  and tau in TAU(i).

  The contents of A on exit are illustrated by the following examples
  with n = 5:

  if UPLO = 'U':                       if UPLO = 'L':

    (  d   e   v1  v2  v3 )              (  d                  )
    (      d   e   v2  v3 )              (  e   d              )
    (          d   e   v3 )              (  v0  e   d          )
    (              d   e  )              (  v0  v1  e   d      )
    (                  d  )              (  v0  v1  v2  e   d  )

where d and e denote diagonal and off-diagonal elements of T, and vi
denotes an element of the vector defining H(i).

  -- LAPACK routine (version 3.0) --
     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
     Courant Institute, Argonne National Lab, and Rice University
     October 31, 1992
*************************************************************************/
void hmatrixtd(ap::complex_2d_array& a,
     int n,
     bool isupper,
     ap::complex_1d_array& tau,
     ap::real_1d_array& d,
     ap::real_1d_array& e)
{
    int i;
    ap::complex alpha;
    ap::complex taui;
    ap::complex v;
    ap::complex_1d_array t;
    ap::complex_1d_array t2;
    ap::complex_1d_array t3;
    int i_;
    int i1_;

    if( n<=0 )
    {
        return;
    }
    for(i = 0; i <= n-1; i++)
    {
        ap::ap_error::make_assertion(ap::fp_eq(a(i,i).y,0), "");
    }
    if( n>1 )
    {
        tau.setbounds(0, n-2);
        e.setbounds(0, n-2);
    }
    d.setbounds(0, n-1);
    t.setbounds(0, n-1);
    t2.setbounds(0, n-1);
    t3.setbounds(0, n-1);
    if( isupper )
    {
        
        //
        // Reduce the upper triangle of A
        //
        a(n-1,n-1) = a(n-1,n-1).x;
        for(i = n-2; i >= 0; i--)
        {
            
            //
            // Generate elementary reflector H = I+1 - tau * v * v'
            //
            alpha = a(i,i+1);
            t(1) = alpha;
            if( i>=1 )
            {
                i1_ = (0) - (2);
                for(i_=2; i_<=i+1;i_++)
                {
                    t(i_) = a(i_+i1_,i+1);
                }
            }
            complexgeneratereflection(t, i+1, taui);
            if( i>=1 )
            {
                i1_ = (2) - (0);
                for(i_=0; i_<=i-1;i_++)
                {
                    a(i_,i+1) = t(i_+i1_);
                }
            }
            alpha = t(1);
            e(i) = alpha.x;
            if( taui!=0 )
            {
                
                //
                // Apply H(I+1) from both sides to A
                //
                a(i,i+1) = 1;
                
                //
                // Compute  x := tau * A * v  storing x in TAU
                //
                i1_ = (0) - (1);
                for(i_=1; i_<=i+1;i_++)
                {
                    t(i_) = a(i_+i1_,i+1);
                }
                hermitianmatrixvectormultiply(a, isupper, 0, i, t, taui, t2);
                i1_ = (1) - (0);
                for(i_=0; i_<=i;i_++)
                {
                    tau(i_) = t2(i_+i1_);
                }
                
                //
                // Compute  w := x - 1/2 * tau * (x'*v) * v
                //
                v = 0.0;
                for(i_=0; i_<=i;i_++)
                {
                    v += ap::conj(tau(i_))*a(i_,i+1);
                }
                alpha = -0.5*taui*v;
                for(i_=0; i_<=i;i_++)
                {
                    tau(i_) = tau(i_) + alpha*a(i_,i+1);
                }
                
                //
                // Apply the transformation as a rank-2 update:
                //    A := A - v * w' - w * v'
                //
                i1_ = (0) - (1);
                for(i_=1; i_<=i+1;i_++)
                {
                    t(i_) = a(i_+i1_,i+1);
                }
                i1_ = (0) - (1);
                for(i_=1; i_<=i+1;i_++)
                {
                    t3(i_) = tau(i_+i1_);
                }
                hermitianrank2update(a, isupper, 0, i, t, t3, t2, -1);
            }
            else
            {
                a(i,i) = a(i,i).x;
            }
            a(i,i+1) = e(i);
            d(i+1) = a(i+1,i+1).x;
            tau(i) = taui;
        }
        d(0) = a(0,0).x;
    }
    else
    {
        
        //
        // Reduce the lower triangle of A
        //
        a(0,0) = a(0,0).x;
        for(i = 0; i <= n-2; i++)
        {
            
            //
            // Generate elementary reflector H = I - tau * v * v'
            //
            i1_ = (i+1) - (1);
            for(i_=1; i_<=n-i-1;i_++)
            {
                t(i_) = a(i_+i1_,i);
            }
            complexgeneratereflection(t, n-i-1, taui);
            i1_ = (1) - (i+1);
            for(i_=i+1; i_<=n-1;i_++)
            {
                a(i_,i) = t(i_+i1_);
            }
            e(i) = a(i+1,i).x;
            if( taui!=0 )
            {
                
                //
                // Apply H(i) from both sides to A(i+1:n,i+1:n)
                //
                a(i+1,i) = 1;
                
                //
                // Compute  x := tau * A * v  storing y in TAU
                //
                i1_ = (i+1) - (1);
                for(i_=1; i_<=n-i-1;i_++)
                {
                    t(i_) = a(i_+i1_,i);
                }
                hermitianmatrixvectormultiply(a, isupper, i+1, n-1, t, taui, t2);
                i1_ = (1) - (i);
                for(i_=i; i_<=n-2;i_++)
                {
                    tau(i_) = t2(i_+i1_);
                }
                
                //
                // Compute  w := x - 1/2 * tau * (x'*v) * v
                //
                i1_ = (i+1)-(i);
                v = 0.0;
                for(i_=i; i_<=n-2;i_++)
                {
                    v += ap::conj(tau(i_))*a(i_+i1_,i);
                }
                alpha = -0.5*taui*v;
                i1_ = (i+1) - (i);
                for(i_=i; i_<=n-2;i_++)
                {
                    tau(i_) = tau(i_) + alpha*a(i_+i1_,i);
                }
                
                //
                // Apply the transformation as a rank-2 update:
                // A := A - v * w' - w * v'
                //
                i1_ = (i+1) - (1);
                for(i_=1; i_<=n-i-1;i_++)
                {
                    t(i_) = a(i_+i1_,i);
                }
                i1_ = (i) - (1);
                for(i_=1; i_<=n-i-1;i_++)
                {
                    t2(i_) = tau(i_+i1_);
                }
                hermitianrank2update(a, isupper, i+1, n-1, t, t2, t3, -1);
            }
            else
            {
                a(i+1,i+1) = a(i+1,i+1).x;
            }
            a(i+1,i) = e(i);
            d(i) = a(i,i).x;
            tau(i) = taui;
        }
        d(n-1) = a(n-1,n-1).x;
    }
}
Esempio n. 3
0
/*************************************************************************
Obsolete 1-based subroutine
*************************************************************************/
bool complexsolvesystemlu(const ap::complex_2d_array& a,
                          const ap::integer_1d_array& pivots,
                          ap::complex_1d_array b,
                          int n,
                          ap::complex_1d_array& x)
{
    bool result;
    ap::complex_1d_array y;
    int i;
    ap::complex v;
    int ip1;
    int im1;
    int i_;

    y.setbounds(1, n);
    x.setbounds(1, n);
    result = true;
    for(i = 1; i <= n; i++)
    {
        if( a(i,i)==0 )
        {
            result = false;
            return result;
        }
    }

    //
    // pivots
    //
    for(i = 1; i <= n; i++)
    {
        if( pivots(i)!=i )
        {
            v = b(i);
            b(i) = b(pivots(i));
            b(pivots(i)) = v;
        }
    }

    //
    // Ly = b
    //
    y(1) = b(1);
    for(i = 2; i <= n; i++)
    {
        im1 = i-1;
        v = 0.0;
        for(i_=1; i_<=im1; i_++)
        {
            v += a(i,i_)*y(i_);
        }
        y(i) = b(i)-v;
    }

    //
    // Ux = y
    //
    x(n) = y(n)/a(n,n);
    for(i = n-1; i >= 1; i--)
    {
        ip1 = i+1;
        v = 0.0;
        for(i_=ip1; i_<=n; i_++)
        {
            v += a(i,i_)*x(i_);
        }
        x(i) = (y(i)-v)/a(i,i);
    }
    return result;
}