void KTable::accumulate(const KTable& rhs, double scalar) { clearCache(); // invalidate any stored interpolations check_array(); if (_N != rhs._N) throw FFTError("KTable::accumulate() with mismatched sizes"); if (_dk != rhs._dk) throw FFTError("KTable::accumulate() with mismatched dk"); for (int i=0; i<_N*(_No2+1); ++i) _array[i] += scalar * rhs._array[i]; }
void KTable::operator*=(const KTable& rhs) { clearCache(); // invalidate any stored interpolations check_array(); if (_N != rhs._N) throw FFTError("KTable::operator*=() with mismatched sizes"); if (_dk != rhs._dk) throw FFTError("KTable::operator*=() with mismatched dk"); for (int i=0; i<_N*(_No2+1); ++i) _array[i] *= rhs._array[i]; }
XTable::XTable(int N, double dx, double value) : _dx(dx) { #ifdef FFT_DEBUG if (N<=0) throw FFTError("XTable size <=0"); #endif _N = 2*((N+1)/2); //Round size up to even. _array.resize(_N); _array.fill(value); }
void XTable::accumulate(const XTable& rhs, double scalar) { check_array(); clearCache(); // invalidate any stored interpolations #ifdef FFT_DEBUG if (_N != rhs._N) throw FFTError("XTable::accumulate() with mismatched sizes"); #endif for (int i=0; i<_N*_N; i++) _array[i] += scalar * rhs._array[i]; }
void TestDft() { // icomplex v[82]; // icomplex w[82]; // ComputeFFT80RtoCCosSinTable(); // ComputeFFT16RtoCCosSinTable(); rngseed = 1; // Seed random number generator. #if (0) printf("testing FFT80CtoC() as its own inverse (with conjugation)\n"); // compute_dft5_constants(); // compute_dft16_constants(); getdft80tables(); // Initialize 3 tables used in fast 80-pt FFT. // compute_dBTable(); total_err_db = 0; #define NUM_TESTS 64 for (k=0; k<NUM_TESTS; k++) { for (j=0; j<80; j++) { w[j].r = myrand(); v[j].r = w[j].r; } for (j=0; j<80; j++) { w[j].i = myrand(); v[j].i = w[j].i; } // DEBUG!!! Also test with sine waves. /* for (j=0; j<80; j++) { printf("%6d %6d ",w[j].r,w[j].i); if ((j%4) == 3) printf("\n"); } getchar(); */ // FFT80CtoC() scales up by square root of 80. // Here, we scale down the first output by 8 and the second output by 10. FFT80CtoC(v); for (i=0; i < 80; i++) { v[i].r = (v[i].r + 4) >> 3; v[i].i = (-v[i].i + 4) >> 3; } FFT80CtoC(v); for (i=0; i < 80; i++) { v[i].r = (v[i].r * 3277 + 16384) >> 15; v[i].i = (-v[i].i * 3277 + 16384) >> 15; } /* for (i=0; i < 80; i++) { printf("%6d %6d %6d %6d\n",w[i].r, w[i].i, v[i].r, v[i].i); if (i%16 == 15) getchar(); } getchar(); */ total_err_db += FFTError((int *) v,(int *) w, 2*80); // if (k%4 == 3) printf("\n"); printf("\n"); } printf("\n"); total_err_db /= NUM_TESTS; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); // printf("average error should be 66.17 db down.\n"); getchar(); #endif #if (0) printf("testing FFT40CtoC() as its own inverse (with conjugation)\n"); GetDft40Tables(); // Initialize 3 tables used in fast 40-pt FFT. total_err_db = 0; #define NUM_TESTS 64 for (k=0; k<NUM_TESTS; k++) { for (j=0; j<40; j++) { w[j].r = myrand(); v[j].r = w[j].r; } for (j=0; j<40; j++) { w[j].i = myrand(); v[j].i = w[j].i; } // DEBUG!!! Also test with sine waves. /* for (j=0; j<40; j++) { printf("%6d %6d ",w[j].r,w[j].i); if ((j%4) == 3) printf("\n"); } getchar(); */ // FFT40CtoC() scales up by square root of 40. // Here, we scale down the first output by 4 and the second output by 10. FFT40CtoC(v); for (i=0; i < 40; i++) { v[i].r = (v[i].r + 2) >> 2; v[i].i = (-v[i].i + 2) >> 2; } FFT40CtoC(v); for (i=0; i < 40; i++) { v[i].r = (v[i].r * 3277 + 16384) >> 15; v[i].i = (-v[i].i * 3277 + 16384) >> 15; } /* for (i=0; i < 40; i++) { printf("%6d %6d %6d %6d\n",w[i].r, w[i].i, v[i].r, v[i].i); if (i%16 == 15) getchar(); } getchar(); */ total_err_db += FFTError((int *) v,(int *) w, 2*40); if (k%8 == 7) printf("\n"); // printf("\n"); } printf("\n"); total_err_db /= NUM_TESTS; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); printf("average error should be 68.54 db down.\n"); getchar(); #endif #if (0) printf("testing FFT80RtoC() vs FFT80CtoC()\n"); int x[82]; getdft80tables(); // Initialize 3 tables used in fast 80-pt FFT total_err_db = 0; for (k=0; k<64; k++) { for (j=0; j < 80; j++) { x[j]= myrand(); v[j].r = x[j]; v[j].i = 0; } FFT80RtoC((icomplex *) x); for (i=0; i <= 40; i++) { w[i].r = x[2*i]; w[i].i = x[2*i+1]; } FFT80CtoC(v); /* for (i=0; i <= 40; i++) { printf("%6d %6d %6d %6d %6d %6d\n",v[i].r, v[i].i, w[i].r, w[i].i, (v[i].r - w[i].r), (v[i].i - w[i].i)); if (i%16 == 15) getchar(); } getchar(); */ total_err_db += FFTError((int *) w,(int *) v, 2*41); // if (k%4 == 3) printf("\n"); printf("\n"); } printf("\n"); total_err_db /= 64; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); getchar(); #endif #if (0) printf("testing FFT80CtoR() vs FFT80CtoC()\n"); icomplex u[41]; int x[80]; total_err_db = 0; for (k=0; k<64; k++) { for (j=0; j <= 40; j++) { u[j].r = myrand(); u[j].i = myrand(); } u[0].i = 0; u[40].i = 0; for (j=0; j <= 40; j++) { v[j].r = u[j].r; v[j].i = -u[j].i; } for (j=1; j < 40; j++) { v[80-j].r = u[j].r; v[80-j].i = u[j].i; } FFT80CtoR(x,u); FFT80CtoC(v); for (i=0; i < 80; i++) { printf("%6d %6d %6d %6d\n",v[i].r, v[i].i, x[i], (v[i].r - x[i])); if (i%16 == 15) getchar(); } getchar(); double pow,err,dif; pow = 0.0; err = 0.0; for (i=0; i<80; i++) { pow += (v[i].r * v[i].r); dif = (x[i] - v[i].r); err += dif*dif; } printf("%8.2f ",10.0*log10(pow/err)); // getchar(); } #endif #if (0) printf("testing FFT80RtoC() and FFT80CtoR() as inverses\n"); int x[80]; int y[82]; total_err_db = 0; #define NUM_TESTS 64 for (k=0; k<NUM_TESTS; k++) { for (j=0; j < 80; j++) { x[j]= myrand(); y[j] = x[j]; } FFT80RtoC((icomplex *) y); // FFT80RtoC() and FFT80CtoR() each scale up by square root of 80. // Here, we scale down the first output by 8 and the second output by 10. // How we do the scaling here can have a huge effect on measured error. for (i=0; i < 82; i++) { y[i] = (y[i] + 4) >> 3; } FFT80CtoR((icomplex *) y); for (i=0; i < 80; i++) { y[i] = (y[i] * 3277 + 16384) >> 15; } // xxx /* for (i=0; i < 80; i++) { printf("%6d %6d ",x[i], y[i]); if (i%4 == 3) printf("\n"); } getchar(); */ total_err_db += FFTError(x, y, 80); // getchar(); if (k%8 == 7) printf("\n"); // printf("\n"); } // printf("\n"); total_err_db /= NUM_TESTS; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); printf("average error should be 64.08 db down.\n"); getchar(); #endif #if (0) printf("testing FFT16RtoC() vs FFT16CtoC()\n"); int x[18]; total_err_db = 0; for (k=0; k<64; k++) { for (j=0; j < 16; j++) { x[j]= myrand(); v[j].r = x[j]; v[j].i = 0; } FFT16RtoC((icomplex *) x); for (i=0; i <= 8; i++) { w[i].r = x[2*i]; w[i].i = x[2*i+1]; } FFT16CtoC(v); for (i=0; i <= 8; i++) { printf("%6d %6d %6d %6d %6d %6d\n",v[i].r, v[i].i, w[i].r, w[i].i, (v[i].r - w[i].r), (v[i].i - w[i].i)); } getchar(); total_err_db += FFTError((int *) w,(int *) v, 2*9); // if (k%4 == 3) printf("\n"); printf("\n"); } printf("\n"); total_err_db /= 64; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); getchar(); #endif #if (VX1_PC0 == 0) #if (0) printf("testing FFT16RtoC() and FFT16CtoR() as inverses\n"); int x[16]; int y[18]; total_err_db = 0; #define NUM_TESTS 64 for (k=0; k<NUM_TESTS; k++) { for (j=0; j < 16; j++) { x[j]= myrand(); y[j] = x[j]; } FFT16RtoC((icomplex *) y); // FFT80RtoC() and FFT80CtoR() each scale up by square root of 16. // Here, we scale down the first output by 2 and the second output by 2. // How we do the scaling here can have a huge effect on measured error. for (i=0; i < 18; i++) { y[i] = (y[i] + 2) >> 2; } FFT16CtoR((icomplex *) y); for (i=0; i < 16; i++) { y[i] = (y[i] + 2) >> 2; } // xxx /* for (i=0; i < 16; i++) { printf("%6d %6d ",x[i], y[i]); if (i%4 == 3) printf("\n"); } getchar(); */ total_err_db += FFTError(x, y, 16); // getchar(); if (k%8 == 7) printf("\n"); // printf("\n"); } // printf("\n"); total_err_db /= NUM_TESTS; printf("average error is %2d.%2d dB down.\n",total_err_db/100, total_err_db - (total_err_db/100)*100); // printf("average error should be 64.08 db down.\n"); getchar(); #endif #endif }