void Correlation::output() { // calculate the FFTs of the two functions if( gsl_fft_real_radix2_transform( d_x, 1, d_n ) == 0 && gsl_fft_real_radix2_transform( d_y, 1, d_n ) == 0) { for(int i=0; i<d_n/2; i++ ){// multiply the FFT by its complex conjugate if( i==0 || i==(d_n/2)-1 ) d_x[i] *= d_x[i]; else{ int ni = d_n-i; double dReal = d_x[i] * d_y[i] + d_x[ni] * d_y[ni]; double dImag = d_x[i] * d_y[ni] - d_x[ni] * d_y[i]; d_x[i] = dReal; d_x[ni] = dImag; } } } else { QMessageBox::warning((ApplicationWindow *)parent(), tr("QtiPlot") + " - " + tr("Error"), tr("Error in GSL forward FFT operation!")); return; } gsl_fft_halfcomplex_radix2_inverse(d_x, 1, d_n ); //inverse FFT addResultCurve(); d_result_table = d_table; }
/* calculates the inverse Fourier transform of signal data (half-complex), * and stores it into fft_results */ int inverse_fft (size_t N, double *data, double *fft_results) { size_t i; int retcode; double *fft_data = (double *) calloc (N, sizeof (double)); /* initialize the data for fft */ for (i=0; i<N; i++) fft_data [i] = data [i]; /* use the corresponding routine if N is power of 2 */ if (is_power_of_n (N,2)) { /* perform the fft */ retcode = gsl_fft_halfcomplex_radix2_inverse (fft_results, 1, N); gsl_fft_halfcomplex_radix2_unpack (fft_data, fft_results, 1, N); } else { /* alloc memory for real and half-complex wavetables, and workspace */ gsl_fft_halfcomplex_wavetable *hc_wavetable = gsl_fft_halfcomplex_wavetable_alloc (N); gsl_fft_real_workspace *ws = gsl_fft_real_workspace_alloc (N); /* perform the fft */ retcode = gsl_fft_halfcomplex_inverse (fft_data, 1, N, hc_wavetable, ws); gsl_fft_halfcomplex_unpack (fft_data, fft_results, 1, N); /* free memory */ gsl_fft_halfcomplex_wavetable_free (hc_wavetable); gsl_fft_real_workspace_free (ws); } free (fft_data); return retcode; }
void TimeSeriesMotion::ifft(const QVector<std::complex<double> >& in, QVector<double>& out ) const { /* #ifdef USE_IFFTW // Copy the input QVector into a double array fftw_complex* inArray = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * in.size()); for( int i = 0; i < in.size(); i++ ) { inArray[i][0] = in.at(i).real(); inArray[i][1] = in.at(i).imag(); } // Allocate the space for the output int n = 2 * (in.size() - 1); double* outArray = (double*)fftw_malloc(sizeof(double) * n); // Create the plan and execute the FFT fftw_plan p = fftw_plan_dft_c2r_1d(n, inArray, outArray, FFTW_ESTIMATE); fftw_execute(p); // Copy the data to the output QVector and normalize by QVector length out.resize(n); for (int i = 0; i < out.size(); i++) { out[i] = outArray[i] / out.size(); } // Free the memory fftw_destroy_plan(p); fftw_free(inArray); fftw_free(outArray); */ const int n = 2 * (in.size() - 1); double *d = new double[n]; d[0] = in.first().real(); for (int i = 1; i < in.size(); ++i) { d[i] = in.at(i).real(); d[n - i] = in.at(i).imag(); } d[n / 2] = in.last().real(); #if USE_FFTW fftw_plan p = fftw_plan_r2r_1d(n, d, d, FFTW_HC2R, FFTW_ESTIMATE); fftw_execute(p); for (int i = 0; i < n; ++i) { // Scale by n d[i] /= n; } #else gsl_fft_halfcomplex_radix2_inverse(d, 1, n); #endif // Copy results to output out.resize(n); memcpy(out.data(), d, n * sizeof(double)); delete [] d; }
void Convolution::convlv(double *sig, int n, double *dres, int m, int sign) { double *res = new double[n]; memset(res,0,n*sizeof(double)); int i, m2 = m/2; for (i=0;i<m2;i++) {//store the response in wrap around order, see Numerical Recipes doc res[i] = dres[m2+i]; res[n-m2+i] = dres[i]; } if(m2%2==1) res[m2]=dres[m-1]; // calculate ffts gsl_fft_real_radix2_transform(res,1,n); gsl_fft_real_radix2_transform(sig,1,n); double re, im, size; for (i=0;i<n/2;i++) {// multiply/divide both ffts if(i==0 || i==n/2-1) { if(sign == 1) sig[i] = res[i]*sig[i]; else sig[i] = sig[i]/res[i]; } else { int ni = n-i; if(sign == 1) { re = res[i]*sig[i]-res[ni]*sig[ni]; im = res[i]*sig[ni]+res[ni]*sig[i]; } else { size = res[i]*res[i]+res[ni]*res[ni]; re = res[i]*sig[i]+res[ni]*sig[ni]; im = res[i]*sig[ni]-res[ni]*sig[i]; re /= size; im /= size; } sig[i] = re; sig[ni] = im; } } delete[] res; gsl_fft_halfcomplex_radix2_inverse(sig,1,n);// inverse fft }
bool CrossCorrelate::algorithm() { KstVectorPtr array_one = inputVector(ARRAY_ONE); KstVectorPtr array_two = inputVector(ARRAY_TWO); KstVectorPtr step_value = outputVector(STEP_VALUE); KstVectorPtr correlated = outputVector(CORRELATED); if (array_one->length() <= 0 || array_two->length() <= 0 || array_one->length() != array_two->length()) { return false; } double* pdArrayOne; double* pdArrayTwo; double* pdResult[2]; double dReal; double dImag; int iLength; int iLengthNew; bool iReturn = false; // // zero-pad the array... // iLength = array_one->length(); iLength *= 2; step_value->resize(array_one->length(), false); correlated->resize(array_two->length(), false); // // round iLength up to the nearest power of two... // iLengthNew = 64; while( iLengthNew < iLength && iLengthNew > 0) { iLengthNew *= 2; } iLength = iLengthNew; if (iLength <= 0) return false; pdArrayOne = new double[iLength]; pdArrayTwo = new double[iLength]; if (pdArrayOne != NULL && pdArrayTwo != NULL) { // // zero-pad the two arrays... // memset( pdArrayOne, 0, iLength * sizeof( double ) ); memcpy( pdArrayOne, array_one->value(), array_one->length() * sizeof( double ) ); memset( pdArrayTwo, 0, iLength * sizeof( double ) ); memcpy( pdArrayTwo, array_two->value(), array_two->length() * sizeof( double ) ); // // calculate the FFTs of the two functions... // if (gsl_fft_real_radix2_transform( pdArrayOne, 1, iLength ) == 0) { if (gsl_fft_real_radix2_transform( pdArrayTwo, 1, iLength ) == 0) { // // multiply one FFT by the complex conjugate of the other... // for (int i=0; i<iLength/2; i++) { if (i==0 || i==(iLength/2)-1) { pdArrayOne[i] = pdArrayOne[i] * pdArrayTwo[i]; } else { dReal = pdArrayOne[i] * pdArrayTwo[i] + pdArrayOne[iLength-i] * pdArrayTwo[iLength-i]; dImag = pdArrayOne[i] * pdArrayTwo[iLength-i] - pdArrayOne[iLength-i] * pdArrayTwo[i]; pdArrayOne[i] = dReal; pdArrayOne[iLength-i] = dImag; } } // // do the inverse FFT... // if (gsl_fft_halfcomplex_radix2_inverse( pdArrayOne, 1, iLength ) == 0) { if (step_value->length() != array_one->length()) { pdResult[0] = (double*)realloc( step_value->value(), array_one->length() * sizeof( double ) ); } else { pdResult[0] = step_value->value(); } if (correlated->length() != array_two->length()) { pdResult[1] = (double*)realloc( correlated->value(), array_two->length() * sizeof( double ) ); } else { pdResult[1] = correlated->value(); } if (pdResult[0] != NULL && pdResult[1] != NULL) { for (int i = 0; i < array_one->length(); ++i) { step_value->value()[i] = pdResult[0][i]; } for (int i = 0; i < array_two->length(); ++i) { correlated->value()[i] = pdResult[1][i]; } for (int i = 0; i < array_one->length(); i++) { step_value->value()[i] = (double)( i - ( array_one->length() / 2 ) ); } memcpy( &(correlated->value()[array_one->length() / 2]), &(pdArrayOne[0]), ( ( array_one->length() + 1 ) / 2 ) * sizeof( double ) ); memcpy( &(correlated->value()[0]), &(pdArrayOne[iLength - (array_one->length() / 2)]), ( array_one->length() / 2 ) * sizeof( double ) ); iReturn = true; } } } } } delete[] pdArrayOne; delete[] pdArrayTwo; return iReturn; }
bool AutoCorrelate::algorithm() { KstVectorPtr array = inputVector(ARRAY); KstVectorPtr step_value = outputVector(STEP_VALUE); KstVectorPtr auto_correlated = outputVector(AUTO_CORRELATED); if (array->length() <= 0) { return false; } double* pdArrayOne; double* pdResult; double* pdCorrelate; double dReal; double dImag; double sigmaSquared = 0.0; int iLength; int iLengthNew; bool iReturn = false; // // zero-pad the array... // iLength = array->length(); iLength *= 2; step_value->resize(array->length(), false); auto_correlated->resize(array->length(), false); // // round iLength up to the nearest power of two... // iLengthNew = 64; while( iLengthNew < iLength && iLengthNew > 0) { iLengthNew *= 2; } iLength = iLengthNew; if (iLength <= 0) { return false; } pdArrayOne = new double[iLength]; if (pdArrayOne != NULL) { // // zero-pad the two arrays... // memset( pdArrayOne, 0, iLength * sizeof( double ) ); memcpy( pdArrayOne, array->value(), array->length() * sizeof( double ) ); // // calculate the FFTs of the two functions... // if (gsl_fft_real_radix2_transform( pdArrayOne, 1, iLength ) == 0) { // // multiply the FFT by its complex conjugate... // for (int i=0; i<iLength/2; i++) { if (i==0 || i==(iLength/2)-1) { pdArrayOne[i] *= pdArrayOne[i]; } else { dReal = pdArrayOne[i] * pdArrayOne[i] + pdArrayOne[iLength-i] * pdArrayOne[iLength-i]; dImag = pdArrayOne[i] * pdArrayOne[iLength-i] - pdArrayOne[iLength-i] * pdArrayOne[i]; pdArrayOne[i] = dReal; pdArrayOne[iLength-i] = dImag; } } // // do the inverse FFT... // if (gsl_fft_halfcomplex_radix2_inverse( pdArrayOne, 1, iLength ) == 0) { if (step_value->length() != array->length()) { pdResult = (double*)realloc( step_value->value(), array->length() * sizeof( double ) ); } else { pdResult = step_value->value(); } if (auto_correlated->length() != array->length()) { pdCorrelate = (double*)realloc( auto_correlated->value(), array->length() * sizeof( double ) ); } else { pdCorrelate = auto_correlated->value(); } if (pdResult != NULL && pdCorrelate != NULL) { sigmaSquared = pdArrayOne[0]; memcpy( &(auto_correlated->value()[array->length() / 2]), &(pdArrayOne[0]), ( ( array->length() + 1 ) / 2 ) * sizeof( double ) ); memcpy( &(auto_correlated->value()[0]), &(pdArrayOne[iLength - (array->length() / 2)]), ( array->length() / 2 ) * sizeof( double ) ); for (int i = 0; i < array->length(); i++) { auto_correlated->value()[i] /= sigmaSquared; step_value->value()[i] = (double)( i - ( array->length() / 2 ) ); } iReturn = true; } } } } delete[] pdArrayOne; return iReturn; }
int crosscorrelate(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]) { double* pdArrayOne; double* pdArrayTwo; double* pdResult[2]; double dReal; double dImag; int i = 0; int iLength; int iLengthNew; int iReturn = -1; if( inArrayLens[0] > 0 && inArrayLens[1] > 0 && inArrayLens[0] == inArrayLens[1] ) { // // zero-pad the array... // iLength = inArrayLens[0]; iLength *= 2; // // round iLength up to the nearest power of two... // iLengthNew = 64; while( iLengthNew < iLength && iLengthNew > 0 ) { iLengthNew *= 2; } iLength = iLengthNew; if( iLength > 0 ) { pdArrayOne = new double[iLength]; pdArrayTwo = new double[iLength]; if( pdArrayOne != NULL && pdArrayTwo != NULL ) { // // zero-pad the two arrays... // memset( pdArrayOne, 0, iLength * sizeof( double ) ); memcpy( pdArrayOne, inArrays[0], inArrayLens[0] * sizeof( double ) ); memset( pdArrayTwo, 0, iLength * sizeof( double ) ); memcpy( pdArrayTwo, inArrays[1], inArrayLens[1] * sizeof( double ) ); // // calculate the FFTs of the two functions... // if( gsl_fft_real_radix2_transform( pdArrayOne, 1, iLength ) == 0 ) { if( gsl_fft_real_radix2_transform( pdArrayTwo, 1, iLength ) == 0 ) { // // multiply one FFT by the complex conjugate of the other... // for( i=0; i<iLength/2; i++ ) { if( i==0 || i==(iLength/2)-1 ) { pdArrayOne[i] = pdArrayOne[i] * pdArrayTwo[i]; } else { dReal = pdArrayOne[i] * pdArrayTwo[i] + pdArrayOne[iLength-i] * pdArrayTwo[iLength-i]; dImag = pdArrayOne[i] * pdArrayTwo[iLength-i] - pdArrayOne[iLength-i] * pdArrayTwo[i]; pdArrayOne[i] = dReal; pdArrayOne[iLength-i] = dImag; } } // // do the inverse FFT... // if( gsl_fft_halfcomplex_radix2_inverse( pdArrayOne, 1, iLength ) == 0 ) { if( outArrayLens[0] != inArrayLens[0] ) { pdResult[0] = (double*)realloc( outArrays[0], inArrayLens[0] * sizeof( double ) ); } else { pdResult[0] = outArrays[0]; } if( outArrayLens[1] != inArrayLens[1] ) { pdResult[1] = (double*)realloc( outArrays[1], inArrayLens[1] * sizeof( double ) ); } else { pdResult[1] = outArrays[1]; } if( pdResult[0] != NULL && pdResult[1] != NULL ) { outArrays[0] = pdResult[0]; outArrayLens[0] = inArrayLens[0]; outArrays[1] = pdResult[1]; outArrayLens[1] = inArrayLens[1]; for( i=0; i<inArrayLens[0]; i++ ) { outArrays[0][i] = (double)( i - ( inArrayLens[0] / 2 ) ); } memcpy( &(outArrays[1][inArrayLens[0] / 2]), &(pdArrayOne[0]), ( ( inArrayLens[0] + 1 ) / 2 ) * sizeof( double ) ); memcpy( &(outArrays[1][0]), &(pdArrayOne[iLength - (inArrayLens[0] / 2)]), ( inArrayLens[0] / 2 ) * sizeof( double ) ); iReturn = 0; } } } } delete[] pdArrayOne; delete[] pdArrayTwo; } } } return iReturn; }
inline int inverse( DATA& data, size_t const stride = 1 ){ return gsl_fft_halfcomplex_radix2_inverse( data.data(), stride, data.size() / stride ); }
/** * C++ version of gsl_fft_halfcomplex_radix2_inverse(). * @param data An array of halfcomplex values as an array of double values. * @param n The size of the array. * @return Error code on failure. */ inline int inverse( double data[], size_t const n ){ return gsl_fft_halfcomplex_radix2_inverse( data, 1, n ); }