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 import ffx.utilities.FFXTest;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.junit.runners.Parameterized;
44 import org.junit.runners.Parameterized.Parameters;
45
46 import java.util.Arrays;
47 import java.util.Collection;
48 import java.util.Random;
49
50 import static org.junit.Assert.assertEquals;
51
52
53
54
55
56
57 @RunWith(Parameterized.class)
58 public class Complex1DTest extends FFXTest {
59
60 private final String info;
61 private final int n;
62
63 public Complex1DTest(String info, int n) {
64 this.info = info;
65 this.n = n;
66 }
67
68 @Parameters
69 public static Collection<Object[]> data() {
70 return Arrays.asList(
71 new Object[][]{
72 {"Test n = 6", 6},
73 {"Test n = 8", 8},
74 {"Test n = 10", 10},
75 {"Test n = 12", 12},
76 {"Test n = 15", 15},
77 {"Test n = 18", 18},
78 {"Test n = 20", 20},
79 {"Test n = 21", 21},
80 {"Test n = 27", 27},
81 {"Test n = 30", 30},
82 {"Test n = 32", 32},
83 {"Test n = 38", 38},
84 {"Test n = 45", 45}
85 });
86 }
87
88 @Test
89 public void testForwardFFTMatchesComplex() {
90 double tolerance = 1.0e-11;
91 double[] expected = createRandomComplexData();
92 double[] actual = expected.clone();
93
94 Complex complex = new Complex(n);
95 Complex1D complex1D = new Complex1D(n);
96 complex.fft(expected, 0, 2);
97 complex1D.fft(actual, 0, 2);
98
99 for (int i = 0; i < 2 * n; i++) {
100 assertEquals(info + " at position: " + i, expected[i], actual[i], tolerance);
101 }
102 }
103
104 @Test
105 public void testInverseFFTMatchesComplex() {
106 double tolerance = 1.0e-11;
107 double[] expected = createRandomComplexData();
108 double[] actual = expected.clone();
109
110 Complex complex = new Complex(n);
111 Complex1D complex1D = new Complex1D(n);
112 complex.ifft(expected, 0, 2);
113 complex1D.ifft(actual, 0, 2);
114
115 for (int i = 0; i < 2 * n; i++) {
116 assertEquals(info + " inverse at position: " + i, expected[i], actual[i], tolerance);
117 }
118 }
119
120 @Test
121 public void testForwardInverseRoundTrip() {
122 double tolerance = 1.0e-11;
123 double[] original = createRandomComplexData();
124 double[] actual = original.clone();
125
126 Complex1D complex1D = new Complex1D(n);
127 complex1D.fft(actual, 0, 2);
128 complex1D.ifft(actual, 0, 2);
129
130 for (int i = 0; i < 2 * n; i++) {
131 assertEquals(info + " round-trip at position: " + i, original[i], actual[i] / n, tolerance);
132 }
133 }
134
135 @Test
136 public void testBlockedForwardFFTMatchesComplex() {
137 if (!Complex.preferredDimension(n)) {
138 return;
139 }
140 double tolerance = 1.0e-11;
141 double[] expected = createRandomBlockedComplexData();
142 double[] actual = expected.clone();
143
144 Complex complex = new Complex(n, DataLayout1D.BLOCKED, n);
145 Complex1D complex1D = new Complex1D(n, DataLayout1D.BLOCKED, n);
146 complex.fft(expected, 0, 1);
147 complex1D.fft(actual, 0, 1);
148
149 for (int i = 0; i < 2 * n; i++) {
150 assertEquals(info + " blocked at position: " + i, expected[i], actual[i], tolerance);
151 }
152 }
153
154 @Test
155 public void testBlockedInverseFFTMatchesComplex() {
156 if (!Complex.preferredDimension(n)) {
157 return;
158 }
159 double tolerance = 1.0e-11;
160 double[] expected = createRandomBlockedComplexData();
161 double[] actual = expected.clone();
162
163 Complex complex = new Complex(n, DataLayout1D.BLOCKED, n);
164 Complex1D complex1D = new Complex1D(n, DataLayout1D.BLOCKED, n);
165 complex.ifft(expected, 0, 1);
166 complex1D.ifft(actual, 0, 1);
167
168 for (int i = 0; i < 2 * n; i++) {
169 assertEquals(info + " blocked inverse at position: " + i, expected[i], actual[i], tolerance);
170 }
171 }
172
173 @Test
174 public void testBlockedForwardInverseRoundTrip() {
175 if (!Complex.preferredDimension(n)) {
176 return;
177 }
178 double tolerance = 1.0e-11;
179 double[] original = createRandomBlockedComplexData();
180 double[] actual = original.clone();
181
182 Complex1D complex1D = new Complex1D(n, DataLayout1D.BLOCKED, n);
183 complex1D.fft(actual, 0, 1);
184 complex1D.ifft(actual, 0, 1);
185
186 for (int i = 0; i < 2 * n; i++) {
187 assertEquals(info + " blocked round-trip at position: " + i, original[i], actual[i] / n, tolerance);
188 }
189 }
190
191 private double[] createRandomComplexData() {
192 double[] data = new double[2 * n];
193 Random random = new Random(1);
194 for (int i = 0; i < n; i++) {
195 int index = 2 * i;
196 data[index] = random.nextDouble();
197 data[index + 1] = random.nextDouble();
198 }
199 return data;
200 }
201
202 private double[] createRandomBlockedComplexData() {
203 double[] data = new double[2 * n];
204 Random random = new Random(1);
205 for (int i = 0; i < n; i++) {
206 data[i] = random.nextDouble();
207 data[i + n] = random.nextDouble();
208 }
209 return data;
210 }
211 }