📄 complexdoublefft_mixed.java
字号:
package jnt.FFT;/** Computes FFT's of complex, double precision data of arbitrary length n. * This class uses the Mixed Radix method; it has special methods to handle * factors 2, 3, 4, 5, 6 and 7, as well as a general factor. * <P> * This method appears to be faster than the Radix2 method, when both methods apply, * but requires extra storage (which ComplexDoubleFFT_Mixed manages itself). * <P> * See {@link ComplexDoubleFFT ComplexDoubleFFT} for details of data layout. * * @author Bruce R. Miller bruce.miller@nist.gov * @author Contribution of the National Institute of Standards and Technology, * @author not subject to copyright. * @author Derived from GSL (Gnu Scientific Library) * @author GSL's FFT Code by Brian Gough bjg@vvv.lanl.gov * @author Since GSL is released under * @author <H HREF="http://www.gnu.org/copyleft/gpl.html">GPL</A>, * @author this package must also be. */public class ComplexDoubleFFT_Mixed extends ComplexDoubleFFT{ static final double PI = Math.PI; public ComplexDoubleFFT_Mixed(int n){ super(n); setup_wavetable(n); } public void transform(double data[], int i0, int stride) { checkData(data,i0,stride); transform_internal(data, i0, stride, -1); } public void backtransform (double data[], int i0, int stride){ checkData(data,i0,stride); transform_internal(data, i0, stride, +1); } /*______________________________________________________________________ Setting up the Wavetable */ private int factors[]; // Reversed the last 2 levels of the twiddle array compared to what the C version had. private double twiddle[][][]; private int available_factors[]={7, 6, 5, 4, 3, 2}; void setup_wavetable(int n){ if (n <= 0) throw new Error("length must be positive integer : "+n); this.n = n; factors = Factorize.factor(n, available_factors); double d_theta = -2.0 * PI / ((double) n); int product = 1; twiddle = new double[factors.length][][]; for (int i = 0; i < factors.length; i++) { int factor = factors[i]; int product_1 = product; /* product_1 = p_(i-1) */ product *= factor; int q = n / product; twiddle[i] = new double[q+1][2*(factor-1)]; double twid[][] = twiddle[i]; for(int j=1; j<factor; j++){ twid[0][2*(j-1)] = 1.0; twid[0][2*(j-1)+1] = 0.0; } for (int k = 1; k <= q; k++) { int m = 0; for(int j=1; j<factor; j++){ // int m = (k*j*product_1) % n; m += k*product_1; m %= n; double theta = d_theta * m; /* d_theta*j*k*p_(i-1) */ twid[k][2*(j-1)] = Math.cos(theta); twid[k][2*(j-1)+1] = Math.sin(theta); }} } } /*______________________________________________________________________ The main transformation driver */ void transform_internal(double data[], int i0, int stride, int sign){ if (n == 1) return; /* FFT of 1 data point is the identity */ double scratch[] = new double[2*n]; int product = 1; int state = 0; double in[], out[]; int istride, ostride; int in0, out0; for (int i = 0; i < factors.length; i++) { int factor = factors[i]; product *= factor; if (state == 0) { in = data; in0 = i0; istride = stride; out = scratch; out0 = 0; ostride = 2; state = 1; } else { in = scratch; in0 = 0; istride = 2; out = data; out0 = i0; ostride = stride; state = 0; } switch(factor){ case 2: pass_2(i,in, in0, istride, out, out0, ostride, sign, product); break; case 3: pass_3(i,in, in0, istride, out, out0, ostride, sign, product); break; case 4: pass_4(i,in, in0, istride, out, out0, ostride, sign, product); break; case 5: pass_5(i,in, in0, istride, out, out0, ostride, sign, product); break; case 6: pass_6(i,in, in0, istride, out, out0, ostride, sign, product); break; case 7: pass_7(i,in, in0, istride, out, out0, ostride, sign, product); break; default:pass_n(i,in, in0, istride, out, out0, ostride, sign, factor, product); } } if (state == 1){ /* copy results back from scratch to data */ for (int i = 0; i < n; i++) { data[i0+stride*i] = scratch[2*i]; data[i0+stride*i+1] = scratch[2*i+1]; }} } /*______________________________________________________________________*/ void pass_2(int fi, double in[], int in0, int istride, double out[], int out0, int ostride, int sign, int product) { int k, k1; int factor = 2; int m = n / factor; int q = n / product; int product_1 = product / factor; int di = istride * m; int dj = ostride * product_1; int i = in0, j = out0; double x_real, x_imag; for (k = 0; k < q; k++) { double twids[] = twiddle[fi][k]; double w_real = twids[0]; double w_imag = -sign*twids[1]; for (k1 = 0; k1 < product_1; k1++) { double z0_real = in[i]; double z0_imag = in[i+1]; double z1_real = in[i+di]; double z1_imag = in[i+di+1]; i += istride; /* compute x = W(2) z */ /* apply twiddle factors */ /* out0 = 1 * (z0 + z1) */ out[j] = z0_real + z1_real; out[j+1] = z0_imag + z1_imag; /* out1 = w * (z0 - z1) */ x_real = z0_real - z1_real; x_imag = z0_imag - z1_imag; out[j+dj] = w_real * x_real - w_imag * x_imag; out[j+dj+1] = w_real * x_imag + w_imag * x_real; j += ostride; } j += (factor-1)*dj; }} /*______________________________________________________________________*/ void pass_3(int fi, double in[], int in0, int istride, double out[], int out0, int ostride, int sign, int product) { int k, k1; int factor = 3; int m = n / factor; int q = n / product; int product_1 = product / factor; int jump = (factor - 1) * product_1; double tau = sign * Math.sqrt(3.0) / 2.0; int di = istride * m; int dj = ostride * product_1; int i = in0, j = out0; double x_real, x_imag; for (k = 0; k < q; k++) { double twids[] = twiddle[fi][k]; double w1_real = twids[0]; double w1_imag = -sign*twids[1]; double w2_real = twids[2]; double w2_imag = -sign*twids[3]; for (k1 = 0; k1 < product_1; k1++) { double z0_real = in[i]; double z0_imag = in[i+1]; double z1_real = in[i+di]; double z1_imag = in[i+di+1]; double z2_real = in[i+2*di]; double z2_imag = in[i+2*di+1]; i += istride; /* compute x = W(3) z */ /* t1 = z1 + z2 */ double t1_real = z1_real + z2_real; double t1_imag = z1_imag + z2_imag; /* t2 = z0 - t1/2 */ double t2_real = z0_real - t1_real / 2.0; double t2_imag = z0_imag - t1_imag / 2.0; /* t3 = (+/-) sin(pi/3)*(z1 - z2) */ double t3_real = tau * (z1_real - z2_real); double t3_imag = tau * (z1_imag - z2_imag); /* apply twiddle factors */ /* out0 = 1 * (z0 + t1) */ out[j] = z0_real + t1_real; out[j+1] = z0_imag + t1_imag; /* out1 = w1 * (t2 + i t3) */ x_real = t2_real - t3_imag; x_imag = t2_imag + t3_real; out[j+dj] = w1_real * x_real - w1_imag * x_imag; out[j+dj+1] = w1_real * x_imag + w1_imag * x_real; /* out2 = w2 * (t2 - i t3) */ x_real = t2_real + t3_imag; x_imag = t2_imag - t3_real; out[j+2*dj] = w2_real * x_real - w2_imag * x_imag; out[j+2*dj+1] = w2_real * x_imag + w2_imag * x_real; j += ostride; } j += (factor-1) * dj; }} /*______________________________________________________________________*/ void pass_4(int fi, double in[], int in0, int istride, double out[], int out0, int ostride, int sign, int product) { int k, k1; int factor = 4; int m = n / factor; int q = n / product; int p_1 = product / factor; int jump = (factor - 1) * p_1; int i = in0, j = out0; int di = istride * m; int dj = ostride * p_1; double x_real, x_imag; for (k = 0; k < q; k++) { double twids[] = twiddle[fi][k]; double w1_real = twids[0]; double w1_imag = -sign*twids[1]; double w2_real = twids[2]; double w2_imag = -sign*twids[3]; double w3_real = twids[4]; double w3_imag = -sign*twids[5]; for (k1 = 0; k1 < p_1; k1++) { double z0_real = in[i]; double z0_imag = in[i+1]; double z1_real = in[i+di]; double z1_imag = in[i+di+1]; double z2_real = in[i+2*di]; double z2_imag = in[i+2*di+1]; double z3_real = in[i+3*di]; double z3_imag = in[i+3*di+1]; i += istride; /* compute x = W(4) z */ /* t1 = z0 + z2 */ double t1_real = z0_real + z2_real; double t1_imag = z0_imag + z2_imag; /* t2 = z1 + z3 */ double t2_real = z1_real + z3_real; double t2_imag = z1_imag + z3_imag; /* t3 = z0 - z2 */ double t3_real = z0_real - z2_real; double t3_imag = z0_imag - z2_imag; /* t4 = (+/-) (z1 - z3) */ double t4_real = sign * (z1_real - z3_real); double t4_imag = sign * (z1_imag - z3_imag); /* apply twiddle factors */ /* out0 = 1 * (t1 + t2) */ out[j] = t1_real + t2_real; out[j+1] = t1_imag + t2_imag; /* out1 = w1 * (t3 + i t4) */ x_real = t3_real - t4_imag; x_imag = t3_imag + t4_real; out[j + dj] = w1_real * x_real - w1_imag * x_imag; out[j + dj+1] = w1_real * x_imag + w1_imag * x_real; /* out2 = w2 * (t1 - t2) */ x_real = t1_real - t2_real; x_imag = t1_imag - t2_imag; out[j + 2 * dj] = w2_real * x_real - w2_imag * x_imag; out[j + 2 * dj+1] = w2_real * x_imag + w2_imag * x_real; /* out3 = w3 * (t3 - i t4) */ x_real = t3_real + t4_imag; x_imag = t3_imag - t4_real; out[j + 3 * dj] = w3_real * x_real - w3_imag * x_imag; out[j + 3 * dj+1] = w3_real * x_imag + w3_imag * x_real; j += ostride; } j += (factor - 1)*dj; }} /*______________________________________________________________________*/ void pass_5(int fi, double in[], int in0, int istride, double out[], int out0, int ostride, int sign, int product) { int k, k1; int factor = 5; int m = n / factor; int q = n / product; int p_1 = product / factor; int jump = (factor - 1) * p_1; double tau = (Math.sqrt (5.0) / 4.0); double sin_2pi_by_5 = sign * Math.sin (2.0 * PI / 5.0); double sin_2pi_by_10 = sign * Math.sin (2.0 * PI / 10.0); int i = in0, j = out0; int di = istride * m; int dj = ostride * p_1; double x_real, x_imag; for (k = 0; k < q; k++) { double twids[] = twiddle[fi][k]; double w1_real = twids[0]; double w1_imag = -sign*twids[1]; double w2_real = twids[2]; double w2_imag = -sign*twids[3]; double w3_real = twids[4]; double w3_imag = -sign*twids[5]; double w4_real = twids[6]; double w4_imag = -sign*twids[7]; for (k1 = 0; k1 < p_1; k1++) { double z0_real = in[i]; double z0_imag = in[i+1]; double z1_real = in[i + di]; double z1_imag = in[i + di+1]; double z2_real = in[i + 2*di]; double z2_imag = in[i + 2*di+1]; double z3_real = in[i + 3*di]; double z3_imag = in[i + 3*di+1]; double z4_real = in[i + 4*di]; double z4_imag = in[i + 4*di+1]; i += istride; /* compute x = W(5) z */ /* t1 = z1 + z4 */ double t1_real = z1_real + z4_real; double t1_imag = z1_imag + z4_imag; /* t2 = z2 + z3 */ double t2_real = z2_real + z3_real; double t2_imag = z2_imag + z3_imag; /* t3 = z1 - z4 */ double t3_real = z1_real - z4_real; double t3_imag = z1_imag - z4_imag; /* t4 = z2 - z3 */ double t4_real = z2_real - z3_real; double t4_imag = z2_imag - z3_imag; /* t5 = t1 + t2 */ double t5_real = t1_real + t2_real; double t5_imag = t1_imag + t2_imag; /* t6 = (sqrt(5)/4)(t1 - t2) */ double t6_real = tau * (t1_real - t2_real); double t6_imag = tau * (t1_imag - t2_imag); /* t7 = z0 - ((t5)/4) */ double t7_real = z0_real - t5_real / 4.0; double t7_imag = z0_imag - t5_imag / 4.0; /* t8 = t7 + t6 */ double t8_real = t7_real + t6_real; double t8_imag = t7_imag + t6_imag; /* t9 = t7 - t6 */ double t9_real = t7_real - t6_real; double t9_imag = t7_imag - t6_imag; /* t10 = sin(2 pi/5) t3 + sin(2 pi/10) t4 */ double t10_real = sin_2pi_by_5 * t3_real + sin_2pi_by_10 * t4_real; double t10_imag = sin_2pi_by_5 * t3_imag + sin_2pi_by_10 * t4_imag; /* t11 = sin(2 pi/10) t3 - sin(2 pi/5) t4 */ double t11_real = sin_2pi_by_10 * t3_real - sin_2pi_by_5 * t4_real; double t11_imag = sin_2pi_by_10 * t3_imag - sin_2pi_by_5 * t4_imag; /* apply twiddle factors */ /* out0 = 1 * (z0 + t5) */ out[j] = z0_real + t5_real; out[j+1] = z0_imag + t5_imag; /* out1 = w1 * (t8 + i t10) */ x_real = t8_real - t10_imag; x_imag = t8_imag + t10_real; out[j + dj] = w1_real * x_real - w1_imag * x_imag; out[j + dj+1] = w1_real * x_imag + w1_imag * x_real; /* out2 = w2 * (t9 + i t11) */ x_real = t9_real - t11_imag; x_imag = t9_imag + t11_real; out[j+2*dj] = w2_real * x_real - w2_imag * x_imag; out[j+2*dj+1] = w2_real * x_imag + w2_imag * x_real; /* out3 = w3 * (t9 - i t11) */ x_real = t9_real + t11_imag; x_imag = t9_imag - t11_real; out[j+3*dj] = w3_real * x_real - w3_imag * x_imag; out[j+3*dj+1] = w3_real * x_imag + w3_imag * x_real; /* out4 = w4 * (t8 - i t10) */ x_real = t8_real + t10_imag; x_imag = t8_imag - t10_real; out[j+4*dj] = w4_real * x_real - w4_imag * x_imag; out[j+4*dj+1] = w4_real * x_imag + w4_imag * x_real; j += ostride; } j += (factor - 1)*dj; }} /*______________________________________________________________________*/ void pass_6(int fi, double in[], int in0, int istride, double out[], int out0, int ostride, int sign, int product) { int k, k1; int factor = 6; int m = n / factor; int q = n / product; int p_1 = product / factor; int jump = (factor - 1) * p_1; double tau = sign * Math.sqrt (3.0) / 2.0; int i = in0, j = out0; int di = istride * m; int dj = ostride * p_1; double x_real, x_imag; for (k = 0; k < q; k++) { double twids[] = twiddle[fi][k]; double w1_real = twids[0]; double w1_imag = -sign*twids[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -