001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.transform;
018    
019    import org.apache.commons.math.analysis.*;
020    import org.apache.commons.math.complex.*;
021    import org.apache.commons.math.MathException;
022    import junit.framework.TestCase;
023    
024    /**
025     * Testcase for fast Fourier transformer.
026     * <p>
027     * FFT algorithm is exact, the small tolerance number is used only
028     * to account for round-off errors.
029     * 
030     * @version $Revision: 762118 $ $Date: 2009-04-05 12:55:59 -0400 (Sun, 05 Apr 2009) $ 
031     */
032    public final class FastFourierTransformerTest extends TestCase {
033    
034        /**
035         * Test of transformer for the ad hoc data taken from Mathematica.
036         */
037        public void testAdHocData() {
038            FastFourierTransformer transformer = new FastFourierTransformer();
039            Complex result[]; double tolerance = 1E-12;
040    
041            double x[] = {1.3, 2.4, 1.7, 4.1, 2.9, 1.7, 5.1, 2.7};
042            Complex y[] = {
043                new Complex(21.9, 0.0),
044                new Complex(-2.09497474683058, 1.91507575950825),
045                new Complex(-2.6, 2.7),
046                new Complex(-1.10502525316942, -4.88492424049175),
047                new Complex(0.1, 0.0),
048                new Complex(-1.10502525316942, 4.88492424049175),
049                new Complex(-2.6, -2.7),
050                new Complex(-2.09497474683058, -1.91507575950825)};
051    
052            result = transformer.transform(x);
053            for (int i = 0; i < result.length; i++) {
054                assertEquals(y[i].getReal(), result[i].getReal(), tolerance);
055                assertEquals(y[i].getImaginary(), result[i].getImaginary(), tolerance);
056            }
057    
058            result = transformer.inversetransform(y);
059            for (int i = 0; i < result.length; i++) {
060                assertEquals(x[i], result[i].getReal(), tolerance);
061                assertEquals(0.0, result[i].getImaginary(), tolerance);
062            }
063    
064            double x2[] = {10.4, 21.6, 40.8, 13.6, 23.2, 32.8, 13.6, 19.2};
065            FastFourierTransformer.scaleArray(x2, 1.0 / Math.sqrt(x2.length));
066            Complex y2[] = y;
067    
068            result = transformer.transform2(y2);
069            for (int i = 0; i < result.length; i++) {
070                assertEquals(x2[i], result[i].getReal(), tolerance);
071                assertEquals(0.0, result[i].getImaginary(), tolerance);
072            }
073    
074            result = transformer.inversetransform2(x2);
075            for (int i = 0; i < result.length; i++) {
076                assertEquals(y2[i].getReal(), result[i].getReal(), tolerance);
077                assertEquals(y2[i].getImaginary(), result[i].getImaginary(), tolerance);
078            }
079        }
080        
081        public void test2DData() {
082            FastFourierTransformer transformer = new FastFourierTransformer();
083            double tolerance = 1E-12;
084            Complex[][] input = new Complex[][] {new Complex[] {new Complex(1, 0),
085                                                                new Complex(2, 0)},
086                                                 new Complex[] {new Complex(3, 1),
087                                                                new Complex(4, 2)}};
088            Complex[][] goodOutput = new Complex[][] {new Complex[] {new Complex(5,
089                    1.5), new Complex(-1, -.5)}, new Complex[] {new Complex(-2,
090                    -1.5), new Complex(0, .5)}};
091            Complex[][] output = (Complex[][])transformer.mdfft(input, true);
092            Complex[][] output2 = (Complex[][])transformer.mdfft(output, false);
093            
094            assertEquals(input.length, output.length);
095            assertEquals(input.length, output2.length);
096            assertEquals(input[0].length, output[0].length);
097            assertEquals(input[0].length, output2[0].length);
098            assertEquals(input[1].length, output[1].length);
099            assertEquals(input[1].length, output2[1].length);
100            
101            for (int i = 0; i < input.length; i++) {
102                for (int j = 0; j < input[0].length; j++) {
103                    assertEquals(input[i][j].getImaginary(), output2[i][j].getImaginary(),
104                                 tolerance);
105                    assertEquals(input[i][j].getReal(), output2[i][j].getReal(), tolerance);
106                    assertEquals(goodOutput[i][j].getImaginary(), output[i][j].getImaginary(),
107                                 tolerance);
108                    assertEquals(goodOutput[i][j].getReal(), output[i][j].getReal(), tolerance);
109                }
110            }
111        }
112        
113        /**
114         * Test of transformer for the sine function.
115         */
116        public void testSinFunction() throws MathException {
117            UnivariateRealFunction f = new SinFunction();
118            FastFourierTransformer transformer = new FastFourierTransformer();
119            Complex result[]; int N = 1 << 8;
120            double min, max, tolerance = 1E-12;
121    
122            min = 0.0; max = 2.0 * Math.PI;
123            result = transformer.transform(f, min, max, N);
124            assertEquals(0.0, result[1].getReal(), tolerance);
125            assertEquals(-(N >> 1), result[1].getImaginary(), tolerance);
126            assertEquals(0.0, result[N-1].getReal(), tolerance);
127            assertEquals(N >> 1, result[N-1].getImaginary(), tolerance);
128            for (int i = 0; i < N-1; i += (i == 0 ? 2 : 1)) {
129                assertEquals(0.0, result[i].getReal(), tolerance);
130                assertEquals(0.0, result[i].getImaginary(), tolerance);
131            }
132    
133            min = -Math.PI; max = Math.PI;
134            result = transformer.inversetransform(f, min, max, N);
135            assertEquals(0.0, result[1].getReal(), tolerance);
136            assertEquals(-0.5, result[1].getImaginary(), tolerance);
137            assertEquals(0.0, result[N-1].getReal(), tolerance);
138            assertEquals(0.5, result[N-1].getImaginary(), tolerance);
139            for (int i = 0; i < N-1; i += (i == 0 ? 2 : 1)) {
140                assertEquals(0.0, result[i].getReal(), tolerance);
141                assertEquals(0.0, result[i].getImaginary(), tolerance);
142            }
143        }
144    
145        /**
146         * Test of parameters for the transformer.
147         */
148        public void testParameters() throws Exception {
149            UnivariateRealFunction f = new SinFunction();
150            FastFourierTransformer transformer = new FastFourierTransformer();
151    
152            try {
153                // bad interval
154                transformer.transform(f, 1, -1, 64);
155                fail("Expecting IllegalArgumentException - bad interval");
156            } catch (IllegalArgumentException ex) {
157                // expected
158            }
159            try {
160                // bad samples number
161                transformer.transform(f, -1, 1, 0);
162                fail("Expecting IllegalArgumentException - bad samples number");
163            } catch (IllegalArgumentException ex) {
164                // expected
165            }
166            try {
167                // bad samples number
168                transformer.transform(f, -1, 1, 100);
169                fail("Expecting IllegalArgumentException - bad samples number");
170            } catch (IllegalArgumentException ex) {
171                // expected
172            }
173        }
174    }