/** * JWave - Java implementation of wavelet transform algorithms * * Copyright 2010-2012 Christian Scheiblich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file DiscreteFourierTransform.java is part of JWave. * * @author Christian Scheiblich * date 25.03.2010 19:56:29 * contact graetz@mailfish.de */ package math.transform.jwave.handlers; import math.transform.jwave.types.Complex; /** * The Discrete Fourier Transform (DFT) is - as the name says - the discrete * version of the Fourier Transform applied to a discrete complex valued series. * While the DFT can be applied to any complex valued series; of any length, in * practice for large series it can take considerable time to compute, while the * time taken being proportional to the square of the number on points in the * series. * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich */ public class DiscreteFourierTransform extends BasicTransform { /** * Constructor; does nothing * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich */ public DiscreteFourierTransform( ) { } // DiscreteFourierTransform /** * The 1-D forward version of the Discrete Fourier Transform (DFT); The input * array arrTime is organized by real and imaginary parts of a complex number * using even and odd places for the index. For example: arrTime[ 0 ] = real1, * arrTime[ 1 ] = imag1, arrTime[ 2 ] = real2, arrTime[ 3 ] = imag2, ... The * output arrFreq is organized by the same scheme. * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#forward(double[]) */ @Override public double[ ] forward( double[ ] arrTime ) { int m = arrTime.length; double[ ] arrFreq = new double[ m ]; // result int n = m >> 1; // half of m for( int i = 0; i < n; i++ ) { int iR = i * 2; int iC = i * 2 + 1; arrFreq[ iR ] = 0.; arrFreq[ iC ] = 0.; double arg = -2. * Math.PI * (double)i / (double)n; for( int k = 0; k < n; k++ ) { int kR = k * 2; int kC = k * 2 + 1; double cos = Math.cos( k * arg ); double sin = Math.sin( k * arg ); arrFreq[ iR ] += arrTime[ kR ] * cos - arrTime[ kC ] * sin; arrFreq[ iC ] += arrTime[ kR ] * sin + arrTime[ kC ] * cos; } // k arrFreq[ iR ] /= (double)n; arrFreq[ iC ] /= (double)n; } // i return arrFreq; } // forward /** * The 1-D reverse version of the Discrete Fourier Transform (DFT); The input * array arrFreq is organized by real and imaginary parts of a complex number * using even and odd places for the index. For example: arrTime[ 0 ] = real1, * arrTime[ 1 ] = imag1, arrTime[ 2 ] = real2, arrTime[ 3 ] = imag2, ... The * output arrTime is organized by the same scheme. * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#reverse(double[]) */ @Override public double[ ] reverse( double[ ] arrFreq ) { int m = arrFreq.length; double[ ] arrTime = new double[ m ]; // result int n = m >> 1; // half of m for( int i = 0; i < n; i++ ) { int iR = i * 2; int iC = i * 2 + 1; arrTime[ iR ] = 0.; arrTime[ iC ] = 0.; double arg = 2. * Math.PI * (double)i / (double)n; for( int k = 0; k < n; k++ ) { int kR = k * 2; int kC = k * 2 + 1; double cos = Math.cos( k * arg ); double sin = Math.sin( k * arg ); arrTime[ iR ] += arrFreq[ kR ] * cos - arrFreq[ kC ] * sin; arrTime[ iC ] += arrFreq[ kR ] * sin + arrFreq[ kC ] * cos; } // k } // i return arrTime; } // reverse /** * The 1-D forward version of the Discrete Fourier Transform (DFT); The input * array arrTime is organized by a class called Complex keeping real and * imaginary part of a complex number. The output arrFreq is organized by the * same scheme. * * @date 23.11.2010 18:57:34 * @author Christian Scheiblich * @param arrTime * array of type Complex keeping coefficients of complex numbers * @return array of type Complex keeping the discrete fourier transform * coefficients */ public Complex[ ] forward( Complex[ ] arrTime ) { int n = arrTime.length; Complex[ ] arrFreq = new Complex[ n ]; // result for( int i = 0; i < n; i++ ) { arrFreq[ i ] = new Complex( ); // 0. , 0. double arg = -2. * Math.PI * (double)i / (double)n; for( int k = 0; k < n; k++ ) { double cos = Math.cos( k * arg ); double sin = Math.sin( k * arg ); double real = arrTime[ k ].getReal( ); double imag = arrTime[ k ].getImag( ); arrFreq[ i ].addReal( real * cos - imag * sin ); arrFreq[ i ].addImag( real * sin + imag * cos ); } // k arrFreq[ i ].mulReal( 1. / (double)n ); arrFreq[ i ].mulImag( 1. / (double)n ); } // i return arrFreq; } // forward /** * The 1-D reverse version of the Discrete Fourier Transform (DFT); The input * array arrFreq is organized by a class called Complex keeping real and * imaginary part of a complex number. The output arrTime is organized by the * same scheme. * * @date 23.11.2010 19:02:12 * @author Christian Scheiblich * @param arrFreq * array of type Complex keeping the discrete fourier transform * coefficients * @return array of type Complex keeping coefficients of tiem domain */ public Complex[ ] reverse( Complex[ ] arrFreq ) { int n = arrFreq.length; Complex[ ] arrTime = new Complex[ n ]; // result for( int i = 0; i < n; i++ ) { arrTime[ i ] = new Complex( ); // 0. , 0. double arg = 2. * Math.PI * (double)i / (double)n; for( int k = 0; k < n; k++ ) { double cos = Math.cos( k * arg ); double sin = Math.sin( k * arg ); double real = arrFreq[ k ].getReal( ); double imag = arrFreq[ k ].getImag( ); arrTime[ i ].addReal( real * cos - imag * sin ); arrTime[ i ].addImag( real * sin + imag * cos ); } // k } // i return arrTime; } // reverse /** * The 2-D forward version of the Discrete Fourier Transform (DFT); The input * array matTime is organized by real and imaginary parts of a complex number * using even and odd places for the indices. For example: matTime[0][0] = * real11, matTime[0][1] = imag11, matTime[0][2] = real12, matTime[0][3] = * imag12, matTime[1][0] = real21, matTime[1][1] = imag21, matTime[1][2] = * real22, matTime[1][3] = imag2... The output matFreq is organized by the * same scheme. * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#forward(double[][]) */ @Override public double[ ][ ] forward( double[ ][ ] matTime ) { // TODO someone should implement this method return null; } // forward /** * The 2-D reverse version of the Discrete Fourier Transform (DFT); The input * array matFreq is organized by real and imaginary parts of a complex number * using even and odd places for the indices. For example: matFreq[0][0] = * real11, matFreq[0][1] = imag11, matFreq[0][2] = real12, matFreq[0][3] = * imag12, matFreq[1][0] = real21, matFreq[1][1] = imag21, matFreq[1][2] = * real22, matFreq[1][3] = imag2... The output matTime is organized by the * same scheme. * * @date 25.03.2010 19:56:29 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#reverse(double[][]) */ @Override public double[ ][ ] reverse( double[ ][ ] matFreq ) { // TODO someone should implement this method return null; } // reverse /** * The 3-D forward version of the Discrete Fourier Transform (DFT); * * @date 10.07.2010 18:10:43 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#forward(double[][][]) */ @Override public double[ ][ ][ ] forward( double[ ][ ][ ] spcTime ) { // TODO someone should implement this method return null; } // forward /** * The 3-D reverse version of the Discrete Fourier Transform (DFT); * * @date 10.07.2010 18:10:45 * @author Christian Scheiblich * @see math.transform.jwave.handlers.BasicTransform#reverse(double[][][]) */ @Override public double[ ][ ][ ] reverse( double[ ][ ][ ] spcHilb ) { // TODO someone should implement this method return null; } // reverse } // class