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.util.FastMath;
34 import org.junit.Assert;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.junit.runners.Parameterized;
38 import org.junit.runners.Parameterized.Parameters;
39
40
41
42
43
44
45
46
47 @RunWith(value = Parameterized.class)
48 public final class FastCosineTransformerTest
49 extends RealTransformerAbstractTest {
50
51 private final DctNormalization normalization;
52
53 private final int[] invalidDataSize;
54
55 private final double[] relativeTolerance;
56
57 private final int[] validDataSize;
58
59 public FastCosineTransformerTest(final DctNormalization normalization) {
60 this.normalization = normalization;
61 this.validDataSize = new int[] {
62 2, 3, 5, 9, 17, 33, 65, 129
63 };
64 this.invalidDataSize = new int[] {
65 128
66 };
67 this.relativeTolerance = new double[] {
68 1E-15, 1E-15, 1E-14, 1E-13, 1E-13, 1E-12, 1E-11, 1E-10
69 };
70 }
71
72
73
74
75
76
77
78 @Parameters
79 public static Collection<Object[]> data() {
80 final DctNormalization[] normalization = DctNormalization.values();
81 final Object[][] data = new DctNormalization[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 @Override
89 RealTransformer createRealTransformer() {
90 return new FastCosineTransformer(normalization);
91 }
92
93 @Override
94 int getInvalidDataSize(final int i) {
95 return invalidDataSize[i];
96 }
97
98 @Override
99 int getNumberOfInvalidDataSizes() {
100 return invalidDataSize.length;
101 }
102
103 @Override
104 int getNumberOfValidDataSizes() {
105 return validDataSize.length;
106 }
107
108 @Override
109 double getRelativeTolerance(final int i) {
110 return relativeTolerance[i];
111 }
112
113 @Override
114 int getValidDataSize(final int i) {
115 return validDataSize[i];
116 }
117
118 @Override
119 UnivariateFunction getValidFunction() {
120 return new Sinc();
121 }
122
123 @Override
124 double getValidLowerBound() {
125 return 0.0;
126 }
127
128 @Override
129 double getValidUpperBound() {
130 return FastMath.PI;
131 }
132
133 @Override
134 double[] transform(final double[] x, final TransformType type) {
135 final int n = x.length;
136 final double[] y = new double[n];
137 final double[] cos = new double[2 * (n - 1)];
138 for (int i = 0; i < cos.length; i++) {
139 cos[i] = FastMath.cos(FastMath.PI * i / (n - 1.0));
140 }
141 int sgn = 1;
142 for (int j = 0; j < n; j++) {
143 double yj = 0.5 * (x[0] + sgn * x[n - 1]);
144 for (int i = 1; i < n - 1; i++) {
145 yj += x[i] * cos[(i * j) % cos.length];
146 }
147 y[j] = yj;
148 sgn *= -1;
149 }
150 final double s;
151 if (type == TransformType.FORWARD) {
152 if (normalization == DctNormalization.STANDARD_DCT_I) {
153 s = 1.0;
154 } else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
155 s = FastMath.sqrt(2.0 / (n - 1.0));
156 } else {
157 throw new MathIllegalStateException(LocalizedCoreFormats.ILLEGAL_STATE);
158 }
159 } else if (type == TransformType.INVERSE) {
160 if (normalization == DctNormalization.STANDARD_DCT_I) {
161 s = 2.0 / (n - 1.0);
162 } else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
163 s = FastMath.sqrt(2.0 / (n - 1.0));
164 } else {
165 throw new MathIllegalStateException(LocalizedCoreFormats.ILLEGAL_STATE);
166 }
167 } else {
168
169
170
171
172 throw new MathIllegalStateException(LocalizedCoreFormats.ILLEGAL_STATE);
173 }
174 TransformUtils.scaleArray(y, s);
175 return y;
176 }
177
178
179
180
181
182
183 @Test
184 public void testAdHocData() {
185 FastCosineTransformer transformer;
186 transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
187 double[] result;
188 double tolerance = 1E-12;
189
190 double[] x = {
191 0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0
192 };
193 double[] y =
194 {
195 172.0, -105.096569476353, 27.3137084989848, -12.9593152353742,
196 8.0, -5.78585076868676, 4.68629150101524, -4.15826451958632,
197 4.0
198 };
199
200 result = transformer.transform(x, TransformType.FORWARD);
201 for (int i = 0; i < result.length; i++) {
202 Assert.assertEquals(y[i], result[i], tolerance);
203 }
204
205 result = transformer.transform(y, TransformType.INVERSE);
206 for (int i = 0; i < result.length; i++) {
207 Assert.assertEquals(x[i], result[i], tolerance);
208 }
209
210 TransformUtils.scaleArray(x, FastMath.sqrt(0.5 * (x.length - 1)));
211
212 transformer = new FastCosineTransformer(DctNormalization.ORTHOGONAL_DCT_I);
213 result = transformer.transform(y, TransformType.FORWARD);
214 for (int i = 0; i < result.length; i++) {
215 Assert.assertEquals(x[i], result[i], tolerance);
216 }
217
218 result = transformer.transform(x, TransformType.INVERSE);
219 for (int i = 0; i < result.length; i++) {
220 Assert.assertEquals(y[i], result[i], tolerance);
221 }
222 }
223
224
225 @Test
226 public void testParameters()
227 throws Exception {
228 UnivariateFunction f = new Sin();
229 FastCosineTransformer transformer;
230 transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
231
232 try {
233
234 transformer.transform(f, 1, -1, 65, TransformType.FORWARD);
235 Assert.fail("Expecting MathIllegalArgumentException - bad interval");
236 } catch (MathIllegalArgumentException ex) {
237
238 }
239 try {
240
241 transformer.transform(f, -1, 1, 1, TransformType.FORWARD);
242 Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
243 } catch (MathIllegalArgumentException ex) {
244
245 }
246 try {
247
248 transformer.transform(f, -1, 1, 64, TransformType.FORWARD);
249 Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
250 } catch (MathIllegalArgumentException ex) {
251
252 }
253 }
254
255
256 @Test
257 public void testSinFunction() {
258 UnivariateFunction f = new Sin();
259 FastCosineTransformer transformer;
260 transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
261 double min;
262 double max;
263 double[] result;
264 double tolerance = 1E-12;
265 int N = 9;
266
267 double[] expected =
268 {
269 0.0, 3.26197262739567, 0.0, -2.17958042710327, 0.0,
270 -0.648846697642915, 0.0, -0.433545502649478, 0.0
271 };
272 min = 0.0;
273 max = 2.0 * FastMath.PI * N / (N - 1);
274 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
275 for (int i = 0; i < N; i++) {
276 Assert.assertEquals(expected[i], result[i], tolerance);
277 }
278
279 min = -FastMath.PI;
280 max = FastMath.PI * (N + 1) / (N - 1);
281 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
282 for (int i = 0; i < N; i++) {
283 Assert.assertEquals(-expected[i], result[i], tolerance);
284 }
285 }
286 }