Ejemplo n.º 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);
    }
}
Ejemplo n.º 3
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_);
        }
    }
}