예제 #1
0
/*************************************************************************
1-dimensional complex cross-correlation.

For given Pattern/Signal returns corr(Pattern,Signal) (non-circular).

Correlation is calculated using reduction to  convolution.  Algorithm with
max(N,N)*log(max(N,N)) complexity is used (see  ConvC1D()  for  more  info
about performance).

IMPORTANT:
    for  historical reasons subroutine accepts its parameters in  reversed
    order: CorrC1D(Signal, Pattern) = Pattern x Signal (using  traditional
    definition of cross-correlation, denoting cross-correlation as "x").

INPUT PARAMETERS
    Signal  -   array[0..N-1] - complex function to be transformed,
                signal containing pattern
    N       -   problem size
    Pattern -   array[0..M-1] - complex function to be transformed,
                pattern to search withing signal
    M       -   problem size

OUTPUT PARAMETERS
    R       -   cross-correlation, array[0..N+M-2]:
                * positive lags are stored in R[0..N-1],
                  R[i] = sum(conj(pattern[j])*signal[i+j]
                * negative lags are stored in R[N..N+M-2],
                  R[N+M-1-i] = sum(conj(pattern[j])*signal[-i+j]

NOTE:
    It is assumed that pattern domain is [0..M-1].  If Pattern is non-zero
on [-K..M-1],  you can still use this subroutine, just shift result by K.

  -- ALGLIB --
     Copyright 21.07.2009 by Bochkanov Sergey
*************************************************************************/
void corrc1d(const ap::complex_1d_array& signal,
     int n,
     const ap::complex_1d_array& pattern,
     int m,
     ap::complex_1d_array& r)
{
    ap::complex_1d_array p;
    ap::complex_1d_array b;
    int i;
    int i_;
    int i1_;

    ap::ap_error::make_assertion(n>0&&m>0, "CorrC1D: incorrect N or M!");
    p.setlength(m);
    for(i = 0; i <= m-1; i++)
    {
        p(m-1-i) = ap::conj(pattern(i));
    }
    convc1d(p, m, signal, n, b);
    r.setlength(m+n-1);
    i1_ = (m-1) - (0);
    for(i_=0; i_<=n-1;i_++)
    {
        r(i_) = b(i_+i1_);
    }
    if( m+n-2>=n )
    {
        i1_ = (0) - (n);
        for(i_=n; i_<=m+n-2;i_++)
        {
            r(i_) = b(i_+i1_);
        }
    }
}
/*************************************************************************
Internal real FFT stub.
Uses straightforward formula with O(N^2) complexity.
*************************************************************************/
static void refinternalrfft(const ap::real_1d_array& a,
     int nn,
     ap::complex_1d_array& f)
{
    ap::real_1d_array tmp;
    int i;

    tmp.setbounds(0, 2*nn-1);
    for(i = 0; i <= nn-1; i++)
    {
        tmp(2*i) = a(i);
        tmp(2*i+1) = 0;
    }
    refinternalcfft(tmp, nn, false);
    f.setlength(nn);
    for(i = 0; i <= nn-1; i++)
    {
        f(i).x = tmp(2*i+0);
        f(i).y = tmp(2*i+1);
    }
}
예제 #3
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;
    }
}
예제 #4
0
/*************************************************************************
1-dimensional circular complex cross-correlation.

For given Pattern/Signal returns corr(Pattern,Signal) (circular).
Algorithm has linearithmic complexity for any M/N.

IMPORTANT:
    for  historical reasons subroutine accepts its parameters in  reversed
    order:   CorrC1DCircular(Signal, Pattern) = Pattern x Signal    (using
    traditional definition of cross-correlation, denoting cross-correlation
    as "x").

INPUT PARAMETERS
    Signal  -   array[0..N-1] - complex function to be transformed,
                periodic signal containing pattern
    N       -   problem size
    Pattern -   array[0..M-1] - complex function to be transformed,
                non-periodic pattern to search withing signal
    M       -   problem size

OUTPUT PARAMETERS
    R   -   convolution: A*B. array[0..M-1].


  -- ALGLIB --
     Copyright 21.07.2009 by Bochkanov Sergey
*************************************************************************/
void corrc1dcircular(const ap::complex_1d_array& signal,
     int m,
     const ap::complex_1d_array& pattern,
     int n,
     ap::complex_1d_array& c)
{
    ap::complex_1d_array p;
    ap::complex_1d_array b;
    int i1;
    int i2;
    int i;
    int j2;
    int i_;
    int i1_;

    ap::ap_error::make_assertion(n>0&&m>0, "ConvC1DCircular: incorrect N or M!");
    
    //
    // normalize task: make M>=N,
    // so A will be longer (at least - not shorter) that B.
    //
    if( m<n )
    {
        b.setlength(m);
        for(i1 = 0; i1 <= m-1; i1++)
        {
            b(i1) = 0;
        }
        i1 = 0;
        while(i1<n)
        {
            i2 = ap::minint(i1+m-1, n-1);
            j2 = i2-i1;
            i1_ = (i1) - (0);
            for(i_=0; i_<=j2;i_++)
            {
                b(i_) = b(i_) + pattern(i_+i1_);
            }
            i1 = i1+m;
        }
        corrc1dcircular(signal, m, b, m, c);
        return;
    }
    
    //
    // Task is normalized
    //
    p.setlength(n);
    for(i = 0; i <= n-1; i++)
    {
        p(n-1-i) = ap::conj(pattern(i));
    }
    convc1dcircular(signal, m, p, n, b);
    c.setlength(m);
    i1_ = (n-1) - (0);
    for(i_=0; i_<=m-n;i_++)
    {
        c(i_) = b(i_+i1_);
    }
    if( m-n+1<=m-1 )
    {
        i1_ = (0) - (m-n+1);
        for(i_=m-n+1; i_<=m-1;i_++)
        {
            c(i_) = b(i_+i1_);
        }
    }
}
예제 #5
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;
}
예제 #6
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;
}