int CalcDelay<T>::gcc(const typename CDEVector<T>::Type &X, const typename CDEVector<T>::Type &Y, int maxdelay, int filter) { assert( X.length() == Y.length() ); typename CDEVector<T>::Type tmp( X.length() ); int fftsize = 2*(X.length()-1); // multiplication in frequency domain for(int i=1; i<=X.length(); ++i) tmp(i) = conj( X(i) ) * Y(i); // calc phase transform if needed if( filter == 1 ) { for(int i=1; i<=X.length(); ++i) if( std::abs(tmp(i)) != 0) tmp(i) = tmp(i) / std::abs(tmp(i)); } // calc crosscorr with IFFT typename DEVector<T>::Type crosscorr; irfft(tmp,crosscorr); // calc delay for(int i=1; i<=fftsize; ++i) crosscorr(i) = std::abs( crosscorr(i) ); int mdelay = (fftsize < maxdelay) ? fftsize : maxdelay; int delay = (int) ( std::max_element( crosscorr.data(), crosscorr.data()+mdelay ) - crosscorr.data() ); // cout << crosscorr << "fftsize:" << fftsize << ",mdelay:" << mdelay // << "maxdelay;" << maxdelay << endl; return delay; }
const Field3D DDZ(const Field3D &f, CELL_LOC outloc, DIFF_METHOD method, bool inc_xbndry) { deriv_func func = fDDZ; // Set to default function DiffLookup *table = FirstDerivTable; CELL_LOC inloc = f.getLocation(); // Input location CELL_LOC diffloc = inloc; // Location of differential result if(StaggerGrids && (outloc == CELL_DEFAULT)) { // Take care of CELL_DEFAULT case outloc = diffloc; // No shift (i.e. same as no stagger case) } if(StaggerGrids && (outloc != inloc)) { // Shifting to a new location if(((inloc == CELL_CENTRE) && (outloc == CELL_ZLOW)) || ((inloc == CELL_ZLOW) && (outloc == CELL_CENTRE))) { // Shifting in Z. Centre -> Zlow, or Zlow -> Centre func = sfDDZ; // Set default table = FirstStagDerivTable; // Set table for others diffloc = (inloc == CELL_CENTRE) ? CELL_ZLOW : CELL_CENTRE; } else { // A more complicated shift. Get a result at cell centre, then shift. if(inloc == CELL_ZLOW) { // Shifting func = sfDDZ; // Set default table = FirstStagDerivTable; // Set table for others diffloc = CELL_CENTRE; } else if(inloc != CELL_CENTRE) { // Interpolate then (centre -> centre) then interpolate return DDZ(interp_to(f, CELL_CENTRE), outloc, method); } } } if(method != DIFF_DEFAULT) { // Lookup function func = lookupFunc(table, method); } Field3D result; if(func == NULL) { // Use FFT real shift = 0.; // Shifting result in Z? if(StaggerGrids) { if((inloc == CELL_CENTRE) && (diffloc == CELL_ZLOW)) { // Shifting down - multiply by exp(-0.5*i*k*dz) shift = -1.; } else if((inloc == CELL_ZLOW) && (diffloc == CELL_CENTRE)) { // Shifting up shift = 1.; } } result.Allocate(); // Make sure data allocated static dcomplex *cv = (dcomplex*) NULL; int jx, jy, jz; real kwave; real flt; int xge = MXG, xlt = ngx-MXG; if(inc_xbndry) { // Include x boundary region (for mixed XZ derivatives) xge = 0; xlt = ngx; } if(cv == (dcomplex*) NULL) cv = new dcomplex[ncz/2 + 1]; for(jx=xge; jx<xlt; jx++) { for(jy=0; jy<ngy; jy++) { rfft(f[jx][jy], ncz, cv); // Forward FFT for(jz=0; jz<=ncz/2; jz++) { kwave=jz*2.0*PI/zlength; // wave number is 1/[rad] if (jz>0.4*ncz) flt=1e-10; else flt=1.0; cv[jz] *= dcomplex(0.0, kwave) * flt; if(StaggerGrids) cv[jz] *= exp(Im * (shift * kwave * dz)); } irfft(cv, ncz, result[jx][jy]); // Reverse FFT result[jx][jy][ncz] = result[jx][jy][0]; } } #ifdef CHECK // Mark boundaries as invalid result.bndry_xin = result.bndry_xout = result.bndry_yup = result.bndry_ydown = false; #endif } else { // All other (non-FFT) functions result = applyZdiff(f, func, dz); } result.setLocation(diffloc); return interp_to(result, outloc); }
int main(int argc, char **argv) { int i; int N, M, L; FILE *fp; M = 128; /* kernel size */ N = 2*M; /* input sub-section length (fft size) */ L = N - M + 1; /* number of "good" points per section */ if ( argc != 2 || isatty(fileno(stdin)) || isatty(fileno(stdout)) ) { bu_exit(1, "Usage: dconv filter < doubles > doubles\nXXX Warning: kernal size must be 2^i - 1\n" ); } #ifdef never /* prepare the kernel(!) */ /* this is either the direct complex response, * or the FT(impulse resp) */ for ( i = 0; i < N; i++ ) { if ( i <= N/2 ) ibuf[i] = 1.0; /* Real part */ else ibuf[i] = 0.0; /* Imag part */ } #endif /* never */ if ( (fp = fopen( argv[1], "r" )) == NULL ) { bu_exit(2, "dconv: can't open \"%s\"\n", argv[1] ); } if ( (M = fread( ibuf, sizeof(*ibuf), 2*MAXM, fp )) == 0 ) { bu_exit(3, "dconv: problem reading filter file\n" ); } fclose( fp ); if ( M > MAXM ) { bu_exit(4, "dconv: only compiled for up to %d sized filter kernels\n", MAXM ); } /*XXX HACK HACK HACK HACK XXX*/ /* Assume M = 2^i - 1 */ M += 1; N = 2*M; /* input sub-section length (fft size) */ L = N - M + 1; /* number of "good" points per section */ if ( N == 256 ) rfft256( ibuf ); else rfft( ibuf, N ); while ( (i = fread(&xbuf[M-1], sizeof(*xbuf), L, stdin)) > 0 ) { if ( i < L ) { /* pad the end with zero's */ memset((char *)&xbuf[M-1+i], 0, (L-i)*sizeof(*savebuffer)); } memcpy(xbuf, savebuffer, (M-1)*sizeof(*savebuffer)); memcpy(savebuffer, &xbuf[L], (M-1)*sizeof(*savebuffer)); /*xform( xbuf, N );*/ if ( N == 256 ) rfft256( xbuf ); else rfft( xbuf, N ); /* Mult */ mult( xbuf, ibuf, N ); /*invxform( xbuf, N );*/ if ( N == 256 ) irfft256( xbuf ); else irfft( xbuf, N ); fwrite( &xbuf[M-1], sizeof(*xbuf), L, stdout ); } return 0; }