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[], tolerance = 1E-12;
188
189 double x[] = {
190 0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0
191 };
192 double y[] =
193 {
194 172.0, -105.096569476353, 27.3137084989848, -12.9593152353742,
195 8.0, -5.78585076868676, 4.68629150101524, -4.15826451958632,
196 4.0
197 };
198
199 result = transformer.transform(x, TransformType.FORWARD);
200 for (int i = 0; i < result.length; i++) {
201 Assert.assertEquals(y[i], result[i], tolerance);
202 }
203
204 result = transformer.transform(y, TransformType.INVERSE);
205 for (int i = 0; i < result.length; i++) {
206 Assert.assertEquals(x[i], result[i], tolerance);
207 }
208
209 TransformUtils.scaleArray(x, FastMath.sqrt(0.5 * (x.length - 1)));
210
211 transformer = new FastCosineTransformer(DctNormalization.ORTHOGONAL_DCT_I);
212 result = transformer.transform(y, TransformType.FORWARD);
213 for (int i = 0; i < result.length; i++) {
214 Assert.assertEquals(x[i], result[i], tolerance);
215 }
216
217 result = transformer.transform(x, TransformType.INVERSE);
218 for (int i = 0; i < result.length; i++) {
219 Assert.assertEquals(y[i], result[i], tolerance);
220 }
221 }
222
223
224 @Test
225 public void testParameters()
226 throws Exception {
227 UnivariateFunction f = new Sin();
228 FastCosineTransformer transformer;
229 transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
230
231 try {
232
233 transformer.transform(f, 1, -1, 65, TransformType.FORWARD);
234 Assert.fail("Expecting MathIllegalArgumentException - bad interval");
235 } catch (MathIllegalArgumentException ex) {
236
237 }
238 try {
239
240 transformer.transform(f, -1, 1, 1, TransformType.FORWARD);
241 Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
242 } catch (MathIllegalArgumentException ex) {
243
244 }
245 try {
246
247 transformer.transform(f, -1, 1, 64, TransformType.FORWARD);
248 Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
249 } catch (MathIllegalArgumentException ex) {
250
251 }
252 }
253
254
255 @Test
256 public void testSinFunction() {
257 UnivariateFunction f = new Sin();
258 FastCosineTransformer transformer;
259 transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
260 double min, max, result[], tolerance = 1E-12;
261 int N = 9;
262
263 double expected[] =
264 {
265 0.0, 3.26197262739567, 0.0, -2.17958042710327, 0.0,
266 -0.648846697642915, 0.0, -0.433545502649478, 0.0
267 };
268 min = 0.0;
269 max = 2.0 * FastMath.PI * N / (N - 1);
270 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
271 for (int i = 0; i < N; i++) {
272 Assert.assertEquals(expected[i], result[i], tolerance);
273 }
274
275 min = -FastMath.PI;
276 max = FastMath.PI * (N + 1) / (N - 1);
277 result = transformer.transform(f, min, max, N, TransformType.FORWARD);
278 for (int i = 0; i < N; i++) {
279 Assert.assertEquals(-expected[i], result[i], tolerance);
280 }
281 }
282 }