#include #include #include #include #include #define DATA_L 1024 #define FP_acc 1000 #define PI 3.141592653589793238462643383279502884197169399375105820974944 int64_t cos_delta_FP_arr[DATA_L] = {0,}; int64_t sin_delta_FP_arr[DATA_L] = {0,}; int64_t wr_arr[DATA_L][DATA_L / 2] = {0,}; int64_t wi_arr[DATA_L][DATA_L / 2] = {0,}; void FFT_fp(int64_t* inp, uint32_t inp_L, int64_t* buf){ // buf имеет длину inp_L * 2 (Re, Im, Re, Im, ...) // inp содержит inp_L значений uint32_t uint32_t i, j, bit; // uint32_t N = inp_L / 2; // длина комплексного массива (inp содержит только Re-часть) uint32_t N = inp_L; // длина комплексного массива (inp содержит только Re-часть) // --- копирование входных данных в буфер --- for (i = 0; i < inp_L; i++) { buf[i * 2] = inp[i]; buf[i * 2 + 1] = 0; } // --- bit-reversal перестановка --- j = 0; for (i = 1; i < N; i++) { bit = N >> 1; while (j & bit) { j ^= bit; bit >>= 1; } j |= bit; if (i < j) { int64_t tmp_re = buf[i * 2]; int64_t tmp_im = buf[i * 2 + 1]; buf[i * 2] = buf[j * 2]; buf[i * 2 + 1] = buf[j * 2 + 1]; buf[j * 2] = tmp_re; buf[j * 2 + 1] = tmp_im; } } // --- уровни бабочек --- uint32_t m = 2; while (m <= N) { uint32_t half = m >> 1; for (uint32_t start = 0; start < N; start += m) { int64_t *twiddle_re = wr_arr[m - 2]; int64_t *twiddle_im = wi_arr[m - 2]; for (uint32_t k = 0; k < half; k++) { int64_t wr = twiddle_re[k]; int64_t wi = twiddle_im[k]; int64_t u_re = buf[(start + k) * 2]; int64_t u_im = buf[(start + k) * 2 + 1]; int64_t v_re = buf[(start + k + half) * 2]; int64_t v_im = buf[(start + k + half) * 2 + 1]; // t = w * v (в фиксированной точке) int64_t t_re = (wr * v_re - wi * v_im) / FP_acc; int64_t t_im = (wr * v_im + wi * v_re) / FP_acc; // верх/низ buf[(start + k) * 2] = u_re + t_re; buf[(start + k) * 2 + 1] = u_im + t_im; buf[(start + k + half) * 2] = u_re - t_re; buf[(start + k + half) * 2 + 1] = u_im - t_im; } } m <<= 1; } for (uint32_t i = 0; i < inp_L; ++i){ //buf[i*2] /= inp_L; //buf[i*2+1] /= inp_L; printf("re,im: %lld, %lld\n", (long long)buf[i*2], (long long)buf[i*2 +1]); } } void imagery2abs(int64_t* inp, uint32_t inp_L, int64_t *out){ printf("+++++++++++++++++++++\n"); printf("calculating abs^2\n"); for (uint32_t i = 0; i < inp_L; ++i){ int64_t re = inp[i*2]; int64_t im = inp[i*2 +1]; int64_t val = (re * re + im * im) / FP_acc; printf("%lld\n", (long long)val); out[i] = val; } } void sin_cos_filler(int64_t* sin_arr, int64_t* cos_arr, uint32_t L){ //[int(-sin(2.0 * pi / m) * FP_acc) for m in range(2,inp_L//2 + 2)] for (uint32_t i = 0; i < L; ++i){ int m = i + 2; double angle = 2.0* PI/m; sin_arr[i] = lround(-sin(angle) * FP_acc); cos_arr[i] = lround(cos(angle) * FP_acc); uint32_t half = m >> 1; for (uint32_t k = 0; k < half; ++k){ double tw_angle = angle * k; wr_arr[i][k] = lround(cos(tw_angle) * FP_acc); wi_arr[i][k] = lround(-sin(tw_angle) * FP_acc); } printf("i, angle, sin, cos: %d %g %lld %lld\n", i, angle, (long long)sin_arr[i], (long long)cos_arr[i]); } } void data_generator(int64_t* X, int64_t* Y, uint32_t N){ for (int i = 0; i < N; ++i){ X[i] = (int64_t)i; Y[i] = lround(sin(((double)i)*2.0* PI/(N/10))*FP_acc); Y[i] += 1*FP_acc; } } void main(){ char* logfilename = "tmp"; int64_t data_X[DATA_L] = {0,}; int64_t data_Y[DATA_L] = {0,}; int64_t data_res_FFT_imag[DATA_L*2] = {0,}; int64_t data_res_FFT_abs[DATA_L] = {0,}; sin_cos_filler(sin_delta_FP_arr, cos_delta_FP_arr, DATA_L); data_generator(data_X, data_Y, DATA_L); FFT_fp(data_Y, DATA_L, data_res_FFT_imag); imagery2abs(data_res_FFT_imag, DATA_L, data_res_FFT_abs); FILE *logfile_ptr; logfile_ptr = fopen(logfilename, "w"); fprintf(logfile_ptr, "X, Y, FFT\n"); for (uint32_t i = 0; i < DATA_L; ++i){ fprintf(logfile_ptr, "%lld, %lg, %lg \n", (long long)data_X[i], ((double)data_Y[i])/(double)FP_acc , (double)data_res_FFT_abs[i]/(double)FP_acc); } fclose(logfile_ptr); }