1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.transform;
23
24 import org.hipparchus.analysis.UnivariateFunction;
25 import org.hipparchus.analysis.function.Sin;
26 import org.hipparchus.analysis.function.Sinc;
27 import org.hipparchus.exception.LocalizedCoreFormats;
28 import org.hipparchus.exception.MathIllegalArgumentException;
29 import org.hipparchus.exception.MathIllegalStateException;
30 import org.hipparchus.exception.MathRuntimeException;
31 import org.hipparchus.util.FastMath;
32 import org.junit.jupiter.params.ParameterizedTest;
33 import org.junit.jupiter.params.provider.MethodSource;
34
35 import java.util.Arrays;
36 import java.util.Collection;
37
38 import static org.junit.jupiter.api.Assertions.assertEquals;
39 import static org.junit.jupiter.api.Assertions.fail;
40
41
42
43
44
45
46
47
48 public final class FastSineTransformerTest extends RealTransformerAbstractTest<DstNormalization> {
49
50 private DstNormalization normalization;
51
52 private int[] invalidDataSize;
53
54 private double[] relativeTolerance;
55
56 private int[] validDataSize;
57
58 public void initFastSineTransformerTest(final DstNormalization normalization) {
59 this.normalization = normalization;
60 this.validDataSize = new int[] {
61 1, 2, 4, 8, 16, 32, 64, 128
62 };
63 this.invalidDataSize = new int[] {
64 129
65 };
66 this.relativeTolerance = new double[] {
67 1E-15, 1E-15, 1E-14, 1E-14, 1E-13, 1E-12, 1E-11, 1E-11
68 };
69 }
70
71
72
73
74
75
76
77 public static Collection<Object[]> data() {
78 final DstNormalization[] normalization = DstNormalization.values();
79 final Object[][] data = new DstNormalization[normalization.length][1];
80 for (int i = 0; i < normalization.length; i++) {
81 data[i][0] = normalization[i];
82 }
83 return Arrays.asList(data);
84 }
85
86
87
88
89
90
91
92 @Override
93 double[] createRealData(final int n) {
94 final double[] data = super.createRealData(n);
95 data[0] = 0.0;
96 return data;
97 }
98
99 @Override
100 RealTransformer createRealTransformer() {
101 return new FastSineTransformer(normalization);
102 }
103
104 @Override
105 int getInvalidDataSize(final int i) {
106 return invalidDataSize[i];
107 }
108
109 @Override
110 int getNumberOfInvalidDataSizes() {
111 return invalidDataSize.length;
112 }
113
114 @Override
115 int getNumberOfValidDataSizes() {
116 return validDataSize.length;
117 }
118
119 @Override
120 double getRelativeTolerance(final int i) {
121 return relativeTolerance[i];
122 }
123
124 @Override
125 int getValidDataSize(final int i) {
126 return validDataSize[i];
127 }
128
129 @Override
130 UnivariateFunction getValidFunction() {
131 return new Sinc();
132 }
133
134 @Override
135 double getValidLowerBound() {
136 return 0.0;
137 }
138
139 @Override
140 double getValidUpperBound() {
141 return FastMath.PI;
142 }
143
144 @Override
145 double[] transform(final double[] x, final TransformType type) {
146 final int n = x.length;
147 final double[] y = new double[n];
148 final double[] sin = new double[2 * n];
149 for (int i = 0; i < sin.length; i++) {
150 sin[i] = FastMath.sin(FastMath.PI * i / n);
151 }
152 for (int j = 0; j < n; j++) {
153 double yj = 0.0;
154 for (int i = 0; i < n; i++) {
155 yj += x[i] * sin[(i * j) % sin.length];
156 }
157 y[j] = yj;
158 }
159 final double s;
160 if (type == TransformType.FORWARD) {
161 if (normalization == DstNormalization.STANDARD_DST_I) {
162 s = 1.0;
163 } else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
164 s = FastMath.sqrt(2.0 / n);
165 } else {
166 throw new MathIllegalStateException(LocalizedCoreFormats.ILLEGAL_STATE);
167 }
168 } else if (type == TransformType.INVERSE) {
169 if (normalization == DstNormalization.STANDARD_DST_I) {
170 s = 2.0 / n;
171 } else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
172 s = FastMath.sqrt(2.0 / n);
173 } else {
174 throw new MathIllegalStateException(LocalizedCoreFormats.ILLEGAL_STATE);
175 }
176 } else {
177
178
179 throw MathRuntimeException.createInternalError();
180 }
181 TransformUtils.scaleArray(y, s);
182 return y;
183 }
184
185 @Override
186 void init(DstNormalization normalization) {
187 initFastSineTransformerTest(normalization);
188 }
189
190
191
192
193 @MethodSource("data")
194 @ParameterizedTest
195 void testTransformRealFirstElementNotZero(final DstNormalization normalization) {
196 initFastSineTransformerTest(normalization);
197 final TransformType[] type = TransformType.values();
198 final double[] data = new double[] {
199 1.0, 1.0, 1.0, 1.0
200 };
201 final RealTransformer transformer = createRealTransformer();
202 for (int j = 0; j < type.length; j++) {
203 try {
204 transformer.transform(data, type[j]);
205 fail(type[j].toString());
206 } catch (MathIllegalArgumentException e) {
207
208 }
209 }
210 }
211
212
213
214
215
216
217
218
219 @MethodSource("data")
220 @ParameterizedTest
221 void testAdHocData(final DstNormalization normalization) {
222 initFastSineTransformerTest(normalization);
223 FastSineTransformer transformer;
224 transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
225 double[] result;
226 double tolerance = 1E-12;
227
228 double[] x = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
229 double[] y = { 0.0, 20.1093579685034, -9.65685424949238,
230 5.98642305066196, -4.0, 2.67271455167720,
231 -1.65685424949238, 0.795649469518633 };
232
233 result = transformer.transform(x, TransformType.FORWARD);
234 for (int i = 0; i < result.length; i++) {
235 assertEquals(y[i], result[i], tolerance);
236 }
237
238 result = transformer.transform(y, TransformType.INVERSE);
239 for (int i = 0; i < result.length; i++) {
240 assertEquals(x[i], result[i], tolerance);
241 }
242
243 TransformUtils.scaleArray(x, FastMath.sqrt(x.length / 2.0));
244 transformer = new FastSineTransformer(DstNormalization.ORTHOGONAL_DST_I);
245
246 result = transformer.transform(y, TransformType.FORWARD);
247 for (int i = 0; i < result.length; i++) {
248 assertEquals(x[i], result[i], tolerance);
249 }
250
251 result = transformer.transform(x, TransformType.INVERSE);
252 for (int i = 0; i < result.length; i++) {
253 assertEquals(y[i], result[i], tolerance);
254 }
255 }
256
257
258
259
260 @MethodSource("data")
261 @ParameterizedTest
262 void testSinFunction(final DstNormalization normalization) {
263 initFastSineTransformerTest(normalization);
264 UnivariateFunction f = new Sin();
265 FastSineTransformer transformer;
266 transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
267 double min;
268 double max;
269 double[] result;
270 double tolerance = 1E-12;
271 int N = 1 << 8;
272
273 min = 0.0; max = 2.0 * FastMath.PI;
274 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
275 assertEquals(N >> 1, result[2], tolerance);
276 for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
277 assertEquals(0.0, result[i], tolerance);
278 }
279
280 min = -FastMath.PI; max = FastMath.PI;
281 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
282 assertEquals(-(N >> 1), result[2], tolerance);
283 for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
284 assertEquals(0.0, result[i], tolerance);
285 }
286 }
287
288
289
290
291 @MethodSource("data")
292 @ParameterizedTest
293 void testParameters(final DstNormalization normalization) throws Exception {
294 initFastSineTransformerTest(normalization);
295 UnivariateFunction f = new Sin();
296 FastSineTransformer transformer;
297 transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
298
299 try {
300
301 transformer.transform(f, 1, -1, 64, TransformType.FORWARD);
302 fail("Expecting MathIllegalArgumentException - bad interval");
303 } catch (MathIllegalArgumentException ex) {
304
305 }
306 try {
307
308 transformer.transform(f, -1, 1, 0, TransformType.FORWARD);
309 fail("Expecting MathIllegalArgumentException - bad samples number");
310 } catch (MathIllegalArgumentException ex) {
311
312 }
313 try {
314
315 transformer.transform(f, -1, 1, 100, TransformType.FORWARD);
316 fail("Expecting MathIllegalArgumentException - bad samples number");
317 } catch (MathIllegalArgumentException ex) {
318
319 }
320 }
321 }