/************************************************************************* 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); } }
/************************************************************************* 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_); } } }