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