1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.numerics.fft;
39
40
41
42
43
44
45
46
47
48
49 public class Real3D {
50
51 private final int nextX, nextY, nextZ;
52 private final int nX, nY, nZ;
53 private final int nX1, nZ2;
54 private final double[] work;
55 private final double[] recip;
56 private final Real fftX;
57 private final Complex fftY, fftZ;
58
59
60
61
62
63
64
65
66 public Real3D(int nX, int nY, int nZ) {
67 this.nX = nX / 2;
68 this.nY = nY;
69 this.nZ = nZ;
70 nX1 = this.nX + 1;
71 nZ2 = 2 * nZ;
72 nextX = 2;
73 nextY = nX + 2;
74 nextZ = nextY * nY;
75 work = new double[nZ2];
76 recip = new double[nX1 * nY * nZ];
77 fftX = new Real(nX);
78 fftY = new Complex(nY);
79 fftZ = new Complex(nZ);
80 }
81
82
83
84
85
86
87
88
89
90
91
92 public static int iReal3D(int i, int j, int k, int nX, int nY) {
93 int xSide = nX + 2;
94 int xySlice = xSide * nY;
95 return i + j * xSide + k * xySlice;
96 }
97
98
99
100
101
102
103 public void convolution(final double[] input) {
104 for (int z = 0; z < nZ; z++) {
105 for (int offset = z * nextZ, y = 0; y < nY; y++, offset += nextY) {
106 fftX.fft(input, offset);
107 }
108 for (int offset = z * nextZ, x = 0; x < nX1; x++, offset += nextX) {
109 fftY.fft(input, offset, nextY);
110 }
111 }
112 for (int index = 0, offset = 0, y = 0; y < nY; y++) {
113 for (int x = 0; x < nX1; x++, offset += nextX) {
114 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
115 work[i] = input[z];
116 work[i + 1] = input[z + 1];
117 }
118 fftZ.fft(work, 0, 2);
119 for (int i = 0; i < nZ2; i += 2) {
120 double r = recip[index++];
121 work[i] *= r;
122 work[i + 1] *= r;
123 }
124 fftZ.ifft(work, 0, 2);
125 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
126 input[z] = work[i];
127 input[z + 1] = work[i + 1];
128 }
129 }
130 }
131 for (int z = 0; z < nZ; z++) {
132 for (int offset = z * nextZ, x = 0; x < nX1; x++, offset += nextX) {
133 fftY.ifft(input, offset, nextY);
134 }
135 for (int offset = z * nextZ, y = 0; y < nY; y++, offset += nextY) {
136 fftX.ifft(input, offset);
137 }
138 }
139 }
140
141
142
143
144
145
146 public void fft(final double[] input) {
147 for (int z = 0; z < nZ; z++) {
148 for (int offset = z * nextZ, y = 0; y < nY; y++, offset += nextY) {
149 fftX.fft(input, offset);
150 }
151 for (int offset = z * nextZ, x = 0; x < nX1; x++, offset += nextX) {
152 fftY.fft(input, offset, nextY);
153 }
154 }
155 for (int x = 0; x < nX1; x++) {
156 for (int offset = x * 2, y = 0; y < nY; y++, offset += nextY) {
157 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
158 work[i] = input[z];
159 work[i + 1] = input[z + 1];
160 }
161 fftZ.fft(work, 0, 2);
162 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
163 input[z] = work[i];
164 input[z + 1] = work[i + 1];
165 }
166 }
167 }
168 }
169
170
171
172
173
174
175 public void ifft(final double[] input) {
176 for (int x = 0; x < nX1; x++) {
177 for (int offset = x * 2, y = 0; y < nY; y++, offset += nextY) {
178 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
179 work[i] = input[z];
180 work[i + 1] = input[z + 1];
181 }
182 fftZ.ifft(work, 0, 2);
183 for (int i = 0, z = offset; i < nZ2; i += 2, z += nextZ) {
184 input[z] = work[i];
185 input[z + 1] = work[i + 1];
186 }
187 }
188 }
189 for (int z = 0; z < nZ; z++) {
190 for (int offset = z * nextZ, x = 0; x < nX1; x++, offset += nextX) {
191 fftY.ifft(input, offset, nextY);
192 }
193 for (int offset = z * nextZ, y = 0; y < nY; y++, offset += nextY) {
194 fftX.ifft(input, offset);
195 }
196 }
197 }
198
199
200
201
202
203
204 public void setRecip(double[] recip) {
205
206 for (int index = 0, offset = 0, y = 0; y < nY; y++) {
207 for (int x = 0; x < nX1; x++, offset += 1) {
208 for (int i = 0, z = offset; i < nZ; i++, z += nX1 * nY) {
209 this.recip[index++] = recip[z];
210 }
211 }
212 }
213 }
214 }