/************************************************************ * APPROX2(T,U) = (T * (1.410474 + U *. 5641896)) / (.75 + (U * (3. + U))) ************************************************************/ dcomplex cerf2(dcomplex t, dcomplex u) { dcomplex p, q, c; p = dcmultr(u, 0.5641896); p = dcaddr(p, 1.410474); p = dcmult(t, p); q = dcaddr(u, 3.0); q = dcmult(u, q); q = dcaddr(q, 0.75); c = dcdiv(p, q); return c; }
/************************************************************ * APPROX1(T) = (T * .5641896) / (.5 + (T * T)) ************************************************************/ dcomplex cerf1(dcomplex t) { dcomplex p, q, c; p = dcmultr(t, 0.5641896); q = dcmult(t,t); q = dcaddr(q, 0.5); c = dcdiv(p,q); return c; }
int dconvolve(const double *data, int ndata, const double *syn, int nsyn, double *conv) { int nextpow2(); void cfft(); int ncorr,n_max,i; dcomplex *cdata,*csyn,*ccorr; if (ndata <=0 || nsyn <=0) { fprintf(stderr,"No data or syn is read in ...\n"); return -1; } ncorr = ndata+nsyn-1; // length of correlation time series n_max = nextpow2(ncorr); // closest 2 power // dynamic allocate array to avoid defining upper limit of the length cdata = (dcomplex *) malloc(n_max * sizeof(dcomplex)); csyn = (dcomplex *) malloc(n_max * sizeof(dcomplex)); ccorr = (dcomplex *) malloc(n_max * sizeof(dcomplex)); // set complex data and syn array for (i=0; i<ndata; i++) {cdata[i].re = data[i]; cdata[i].im = 0.;} for (i=ndata; i<n_max; i++) cdata[i].re = cdata[i].im = 0.; for (i=0; i<nsyn; i++) {csyn[i].re = syn[i]; csyn[i].im = 0.;} for (i=nsyn; i<n_max; i++) csyn[i].re = csyn[i].im = 0.; // fft both complex data and syn array cfft(cdata,n_max,1); cfft(csyn,n_max,1); // in frequency domain, calculate the fft of correlation for (i=0;i<n_max;i++) ccorr[i] = dcmult(cdata[i],csyn[i]); // fft back to get the correlation time series cfft(ccorr,n_max,-1); for (i=0;i<ncorr;i++) conv[i] = ccorr[i].re/n_max; free(cdata); free(csyn); free(ccorr); return ncorr; }
/************************************************************ * APPROX4(T,U) = (T * (36183.31 - U * (3321.99 - U * (1540.787 - U * * (219.031 - U *(35.7668 - U *(1.320522 - U * .56419)))))) * / (32066.6 - U * (24322.8 - U * (9022.23 - U * (2186.18 * - U * (364.219 - U * (61.5704 - U * (1.84144 - U)))))))) ************************************************************/ dcomplex cerf4(dcomplex t, dcomplex u) { dcomplex p, q, c; double a[7] = {36183.31, 3321.99, 1540.787, 219.031, 35.7668, 1.320522, 0.56419}; double b[8] = {32066.6, 24322.8, 9022.23, 2186.18, 364.219, 61.5704, 1.84144, 1.0}; /* Polynomials are all in -U */ u = dcmultr(u, -1.0); p = dcpoly(u, a, 6); p = dcmult(t, p); q = dcpoly(u, b, 7); c = dcdiv(p, q); return c; }
/************************************************************ * Fast approximation to cerf(z) using the Humlicek w4 * algorithm ************************************************************/ void humlicek_w4(int n, double x[], double y, double *c_re, double *c_im) { int i; double s, ax; dcomplex t, u, c, cexpu; if (y >= 15) { /* All points are in region I */ for (i = 0; i < n; i++) { t = dcsetri(y, -x[i]); c = cerf1(t); c_re[i] = c.re; c_im[i] = c.im; } } else if (y < 15 && y >= 5.5) { /* Points are in region I or region II */ for (i = 0; i < n; i++) { t = dcsetri(y, -x[i]); s = fabs(x[i]) + y; if (s >= 15) { c = cerf1(t); c_re[i] = c.re; c_im[i] = c.im; } else { u = dcmult(t, t); c = cerf2(t, u); c_re[i] = c.re; c_im[i] = c.im; } } } else if (y < 5.5 && y >= 0.75) { for (i = 0; i < n; i++) { t = dcsetri(y, -x[i]); s = fabs(x[i]) + y; if (s >= 15) { c = cerf1(t); c_re[i] = c.re; c_im[i] = c.im; } else if (s < 5.5) { c = cerf3(t); c_re[i] = c.re; c_im[i] = c.im; } else { u = dcmult(t, t); c = cerf2(t, u); c_re[i] = c.re; c_im[i] = c.im; } } } else { for (i = 0; i < n; i++) { t = dcsetri(y, -x[i]); ax = fabs(x[i]); s = ax + y; if (s >= 15) { c = cerf1(t); c_re[i] = c.re; c_im[i] = c.im; } else if (s < 15.0 && s >= 5.5) { u = dcmult(t, t); c = cerf2(t, u); c_re[i] = c.re; c_im[i] = c.im; } else if (s < 5.5 && y >= (0.195 * ax - 0.176)) { c = cerf3(t); c_re[i] = c.re; c_im[i] = c.im; } else { u = dcmult(t, t); c = cerf4(t,u); cexpu = dcexp(u); c = dcsub(cexpu, c); c_re[i] = c.re; c_im[i] = c.im; } } } if (y == 0.0) { for (i = 0; i < n; i++) { c_re[i] = exp(-x[i]*x[i]); } } }
int hilbert(int numsamp,const double *f,double *fhilb) { void cfft(); int find_length(); void detrend(); int i, j,npts_max; double bpfilt; dcomplex imag; dcomplex *x; if(numsamp<=0) { fprintf(stderr,"%s\n","No data points read ...."); return (1); } npts_max = find_length(numsamp); if (npts_max == 0) { fprintf(stderr,"Too long input time series \n"); return (2); } x = (dcomplex *) malloc(npts_max * sizeof(dcomplex)); if ( x == NULL ) { fprintf(stderr,"Incorrect allocation\n"); return (3); } imag.re = 0.; imag.im = 1.0; for( i=0; i<numsamp; i++) { x[i].re = f[i]; x[i].im = 0.; } for(i=numsamp; i<npts_max; i++) x[i].re = x[i].im = 0.; cfft( x,npts_max,-1 ); for (i=1; i<=npts_max/2; ++i) { x[i] = dcmult(x[i],imag); } x[0].re = 0.; x[0].im = 0.; for( i=(npts_max/2)+1; i<npts_max; i++ ) x[i] = dconj(x[npts_max-i]); cfft( x,npts_max,1 ); for( i=0; i<numsamp; i++) fhilb[i] = x[i].re/npts_max; detrend(fhilb, numsamp); free(x); return (0); }