NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.

To learn about what's going on, see About the Archive Site.

[visad] Modification to FFT.java

Hello,

I found the VisAD project via a code excerpt for your FFT algorithm. I've
been looking at VisAD itself, and it looks very interesting, but in the
short term I just wanted to use your FFT algorithm. I've removed the VisAD
dependencies from the FFT code, just leaving the FT2D and FT1D methods, etc.
I just wanted to check whether it is acceptable (under the LGPL) to package
this as a (very small) library to use from my commercial code. I've attached
the modified code - really all I needed to do was remove the first few
methods and change the VisAD exceptions to IllegalArgumentExceptions.

Best Regards,
Ben.

-- 
Ben Webster
Director

IT-IS International Ltd
1 Wainstones Court
StokesleyBusiness Park
Stokesley
North Yorkshire
TS9 5JY
United Kingdom

T: +44 (0) 1642 714222
www.itisint.com

Company no: 5098475
Registered in the UK

The information contained in this e-mail and any files transmitted with
it is strictly Confidential and intended for the addressee only. If you have
received this e-mail in error please notify the originator. Reasonable
endeavours have been used to check for virus infection in this email,
including attachments; however, this does not warrant freedom from such
infection and you are responsible for conducting your own virus checking.
import java.text.DecimalFormat;

/*
 VisAD system for interactive analysis and visualization of numerical
 data.  Copyright (C) 1996 - 2007 Bill Hibbard, Curtis Rueden, Tom
 Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
 Tommy Jasmin.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.

 You should have received a copy of the GNU Library General Public
 License along with this library; if not, write to the Free
 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 MA 02111-1307, USA
 */

/**
 * FFT is the VisAD class for Fourier Transforms, using the Fast Fourier
 * Transform when the domain length is a power of two.
 * <p>
 */

public class FFT {

        /**
         * compute 2-D Fourier transform, calling 1-D FT twice use FFT if rows 
and
         * cols are powers of 2
         * 
         * @param rows
         *            first dimension for 2-D
         * @param cols
         *            second dimension for 2-D
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length]
         *            where length = rows * cols, and the first index (2) is 
over
         *            real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static float[][] FT2D(int rows, int cols, float[][] x,
                        boolean forward) throws IllegalArgumentException {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                if (rows * cols != n) {
                        throw new IllegalArgumentException(rows + " * " + cols 
+ " must equal " + n);
                }
                float[][] y = new float[2][n];
                float[][] z = new float[2][rows];
                for (int c = 0; c < cols; c++) {
                        int i = c * rows;
                        for (int r = 0; r < rows; r++) {
                                z[0][r] = x[0][i + r];
                                z[1][r] = x[1][i + r];
                        }
                        z = FT1D(z, forward);
                        for (int r = 0; r < rows; r++) {
                                y[0][i + r] = z[0][r];
                                y[1][i + r] = z[1][r];
                        }
                }

                float[][] u = new float[2][n];
                float[][] v = new float[2][cols];
                for (int r = 0; r < rows; r++) {
                        int i = r;
                        for (int c = 0; c < cols; c++) {
                                v[0][c] = y[0][i + c * rows];
                                v[1][c] = y[1][i + c * rows];
                        }
                        v = FT1D(v, forward);
                        for (int c = 0; c < cols; c++) {
                                u[0][i + c * rows] = v[0][c];
                                u[1][i + c * rows] = v[1][c];
                        }
                }
                return u;
        }

        /**
         * compute 2-D Fourier transform, calling 1-D FT twice use FFT if rows 
and
         * cols are powers of 2
         * 
         * @param rows
         *            first dimension for 2-D
         * @param cols
         *            second dimension for 2-D
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length]
         *            where length = rows * cols, and the first index (2) is 
over
         *            real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static double[][] FT2D(int rows, int cols, double[][] x,
                        boolean forward) throws IllegalArgumentException {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                if (rows * cols != n) {
                        throw new IllegalArgumentException(rows + " * " + cols 
+ " must equal " + n);
                }
                double[][] y = new double[2][n];
                double[][] z = new double[2][rows];
                for (int c = 0; c < cols; c++) {
                        int i = c * rows;
                        for (int r = 0; r < rows; r++) {
                                z[0][r] = x[0][i + r];
                                z[1][r] = x[1][i + r];
                        }
                        z = FT1D(z, forward);
                        for (int r = 0; r < rows; r++) {
                                y[0][i + r] = z[0][r];
                                y[1][i + r] = z[1][r];
                        }
                }

                double[][] u = new double[2][n];
                double[][] v = new double[2][cols];
                for (int r = 0; r < rows; r++) {
                        int i = r;
                        for (int c = 0; c < cols; c++) {
                                v[0][c] = y[0][i + c * rows];
                                v[1][c] = y[1][i + c * rows];
                        }
                        v = FT1D(v, forward);
                        for (int c = 0; c < cols; c++) {
                                u[0][i + c * rows] = v[0][c];
                                u[1][i + c * rows] = v[1][c];
                        }
                }
                return u;
        }

        /**
         * compute 1-D Fourier transform use FFT if length (2nd dimension of x) 
is a
         * power of 2
         * 
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length],
         *            the first index (2) is over real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static float[][] FT1D(float[][] x, boolean forward) {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                int n2 = 1;
                boolean fft = true;
                while (n2 < n) {
                        n2 *= 2;
                        if (n2 > n) {
                                fft = false;
                        }
                }
                if (fft)
                        return FFT1D(x, forward);

                float[][] temp = new float[2][n];
                float angle = (float) (-2.0 * Math.PI / n);
                if (!forward)
                        angle = -angle;
                for (int i = 0; i < n; i++) {
                        temp[0][i] = (float) Math.cos(i * angle);
                        temp[1][i] = (float) Math.sin(i * angle);
                }
                float[][] y = new float[2][n];
                for (int i = 0; i < n; i++) {
                        float re = 0.0f;
                        float im = 0.0f;
                        for (int j = 0; j < n; j++) {
                                int m = (i * j) % n;
                                re += x[0][j] * temp[0][m] - x[1][j] * 
temp[1][m];
                                im += x[0][j] * temp[1][m] + x[1][j] * 
temp[0][m];
                        }
                        y[0][i] = re;
                        y[1][i] = im;
                }
                if (!forward) {
                        for (int i = 0; i < n; i++) {
                                y[0][i] /= n;
                                y[1][i] /= n;
                        }
                }
                return y;
        }

        /**
         * compute 1-D FFT transform length (2nd dimension of x) must be a 
power of
         * 2
         * 
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length],
         *            the first index (2) is over real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static float[][] FFT1D(float[][] x, boolean forward) {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                int n2 = 1;
                while (n2 < n) {
                        n2 *= 2;
                        if (n2 > n) {
                                throw new IllegalArgumentException(
                                                "x length must be power of 2");
                        }
                }
                n2 = n / 2;
                float[][] temp = new float[2][n2];
                float angle = (float) (-2.0 * Math.PI / n);
                if (!forward)
                        angle = -angle;
                for (int i = 0; i < n2; i++) {
                        temp[0][i] = (float) Math.cos(i * angle);
                        temp[1][i] = (float) Math.sin(i * angle);
                }
                float[][] y = FFT1D(x, temp);
                if (!forward) {
                        for (int i = 0; i < n; i++) {
                                y[0][i] /= n;
                                y[1][i] /= n;
                        }
                }
                return y;
        }

        /** inner function for 1-D Fast Fourier Transform */
        private static float[][] FFT1D(float[][] x, float[][] temp) {
                int n = x[0].length;
                int n2 = n / 2;
                int k = 0;
                int butterfly;
                int buttered = 0;
                if (n == 1) {
                        float[][] z1 = { { x[0][0] }, { x[1][0] } };
                        return z1;
                }

                butterfly = (temp[0].length / n2);

                float[][] z = new float[2][n2];
                float[][] w = new float[2][n2];

                for (k = 0; k < n / 2; k++) {
                        int k2 = 2 * k;
                        z[0][k] = x[0][k2];
                        z[1][k] = x[1][k2];
                        w[0][k] = x[0][k2 + 1];
                        w[1][k] = x[1][k2 + 1];
                }

                z = FFT1D(z, temp);
                w = FFT1D(w, temp);

                float[][] y = new float[2][n];
                for (k = 0; k < n2; k++) {
                        y[0][k] = z[0][k];
                        y[1][k] = z[1][k];

                        float re = w[0][k] * temp[0][buttered] - w[1][k]
                                        * temp[1][buttered];
                        float im = w[0][k] * temp[1][buttered] + w[1][k]
                                        * temp[0][buttered];
                        w[0][k] = re;
                        w[1][k] = im;

                        y[0][k] += w[0][k];
                        y[1][k] += w[1][k];
                        y[0][k + n2] = z[0][k] - w[0][k];
                        y[1][k + n2] = z[1][k] - w[1][k];
                        buttered += butterfly;
                }
                return y;
        }

        /**
         * compute 1-D Fourier transform use FFT if length (2nd dimension of x) 
is a
         * power of 2
         * 
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length],
         *            the first index (2) is over real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static double[][] FT1D(double[][] x, boolean forward)
                        throws IllegalArgumentException {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                int n2 = 1;
                boolean fft = true;
                while (n2 < n) {
                        n2 *= 2;
                        if (n2 > n) {
                                fft = false;
                        }
                }
                if (fft)
                        return FFT1D(x, forward);

                double[][] temp = new double[2][n];
                double angle = -2.0 * Math.PI / n;
                if (!forward)
                        angle = -angle;
                for (int i = 0; i < n; i++) {
                        temp[0][i] = Math.cos(i * angle);
                        temp[1][i] = Math.sin(i * angle);
                }
                double[][] y = new double[2][n];
                for (int i = 0; i < n; i++) {
                        double re = 0.0;
                        double im = 0.0;
                        for (int j = 0; j < n; j++) {
                                int m = (i * j) % n;
                                re += x[0][j] * temp[0][m] - x[1][j] * 
temp[1][m];
                                im += x[0][j] * temp[1][m] + x[1][j] * 
temp[0][m];
                        }
                        y[0][i] = re;
                        y[1][i] = im;
                }
                if (!forward) {
                        for (int i = 0; i < n; i++) {
                                y[0][i] /= n;
                                y[1][i] /= n;
                        }
                }
                return y;
        }

        /**
         * compute 1-D FFT transform length (2nd dimension of x) must be a 
power of
         * 2
         * 
         * @param x
         *            array for take Fourier transform of, dimensioned 
[2][length],
         *            the first index (2) is over real & imaginary parts
         * @param forward
         *            true for forward and false for backward
         * @return Fourier transform of x
         * @throws VisADException
         *             a VisAD error occurred
         */
        public static double[][] FFT1D(double[][] x, boolean forward)
                        throws IllegalArgumentException {
                if (x == null)
                        return null;
                if (x.length != 2 || x[0].length != x[1].length) {
                        throw new IllegalArgumentException("bad x lengths");
                }
                int n = x[0].length;
                int n2 = 1;
                while (n2 < n) {
                        n2 *= 2;
                        if (n2 > n) {
                                throw new IllegalArgumentException(
                                                "x length must be power of 2");
                        }
                }
                n2 = n / 2;
                double[][] temp = new double[2][n2];
                double angle = (double) (-2.0 * Math.PI / n);
                if (!forward)
                        angle = -angle;
                for (int i = 0; i < n2; i++) {
                        temp[0][i] = (double) Math.cos(i * angle);
                        temp[1][i] = (double) Math.sin(i * angle);
                }
                double[][] y = FFT1D(x, temp);
                if (!forward) {
                        for (int i = 0; i < n; i++) {
                                y[0][i] /= n;
                                y[1][i] /= n;
                        }
                }
                return y;
        }

        /** inner function for 1-D Fast Fourier Transform */
        private static double[][] FFT1D(double[][] x, double[][] temp) {
                int n = x[0].length;
                int n2 = n / 2;
                int k = 0;
                int butterfly;
                int buttered = 0;
                if (n == 1) {
                        double[][] z1 = { { x[0][0] }, { x[1][0] } };
                        return z1;
                }

                butterfly = (temp[0].length / n2);

                double[][] z = new double[2][n2];
                double[][] w = new double[2][n2];

                for (k = 0; k < n2; k++) {
                        int k2 = 2 * k;
                        z[0][k] = x[0][k2];
                        z[1][k] = x[1][k2];
                        w[0][k] = x[0][k2 + 1];
                        w[1][k] = x[1][k2 + 1];
                }

                z = FFT1D(z, temp);
                w = FFT1D(w, temp);

                double[][] y = new double[2][n];
                for (k = 0; k < n2; k++) {
                        y[0][k] = z[0][k];
                        y[1][k] = z[1][k];

                        double re = w[0][k] * temp[0][buttered] - w[1][k]
                                        * temp[1][buttered];
                        double im = w[0][k] * temp[1][buttered] + w[1][k]
                                        * temp[0][buttered];
                        w[0][k] = re;
                        w[1][k] = im;

                        y[0][k] += w[0][k];
                        y[1][k] += w[1][k];
                        y[0][k + n2] = z[0][k] - w[0][k];
                        y[1][k + n2] = z[1][k] - w[1][k];
                        buttered += butterfly;
                }
                return y;
        }

        /** test Fourier Transform methods */
        public static void main(String args[]) throws IllegalArgumentException {
                int n = 16;
                int rows = 1, cols = 1;
                boolean twod = false;

                DecimalFormat format = new DecimalFormat("0.0000");

                /*
                 * if (args.length > 0 && args[0].startsWith("AREA")) { 
DisplayImpl
                 * display1 = new DisplayImplJ3D("display"); DisplayImpl 
display1 = new
                 * DisplayImplJ3D("display"); AreaAdapter areaAdapter = new
                 * AreaAdapter(args[0]); Data image = areaAdapter.getData();
                 * FunctionType imageFunctionType = (FunctionType) 
image.getType();
                 * RealType radianceType = (RealType) ((RealTupleType)
                 * imageFunctionType.getRange()).getComponent(0); 
display.addMap(new
                 * ScalarMap(RealType.Latitude, Display.Latitude)); 
display.addMap(new
                 * ScalarMap(RealType.Longitude, Display.Longitude)); ScalarMap 
rgbMap =
                 * new ScalarMap(radianceType, Display.RGB); 
display.addMap(rgbMap); }
                 */

                if (args.length > 0)
                        n = Integer.valueOf(args[0]).intValue();
                if (args.length > 1) {
                        rows = Integer.valueOf(args[0]).intValue();
                        cols = Integer.valueOf(args[1]).intValue();
                        n = rows * cols;
                        twod = true;
                }

                float[][] x = new float[2][n];
                // double[][] x = new double[2][n];
                System.out.println("  initial values");
                if (twod) {
                        int i = 0;
                        for (int c = 0; c < cols; c++) {
                                for (int r = 0; r < rows; r++) {
                                        x[0][i] = (float) (Math.sin(2 * Math.PI 
* r / rows) * Math
                                                        .sin(2 * Math.PI * c / 
cols));
                                        x[1][i] = 0.0f;
                                        // x[0][i] = (Math.sin(2 * Math.PI * r 
/ rows) *
                                        // Math.sin(2 * Math.PI * c / cols));
                                        // x[1][i] = 0.0;
                                        System.out.println("x[" + r + "][" + c 
+ "] = "
                                                        + 
format.format(x[0][i]) + " "
                                                        + 
format.format(x[1][i]));
                                        i++;
                                }
                        }
                } else {
                        for (int i = 0; i < n; i++) {
                                x[0][i] = (float) Math.sin(2 * Math.PI * i / n);
                                x[1][i] = 0.0f;
                                // x[0][i] = Math.sin(2 * Math.PI * i / n);
                                // x[1][i] = 0.0;
                                System.out.println("x[" + i + "] = " + 
format.format(x[0][i])
                                                + " " + format.format(x[1][i]));
                        }
                }
                x = twod ? FT2D(rows, cols, x, true) : FT1D(x, true);
                System.out.println("\n  fft");
                if (twod) {
                        int i = 0;
                        for (int c = 0; c < cols; c++) {
                                for (int r = 0; r < rows; r++) {
                                        System.out.println("x[" + r + "][" + c 
+ "] = "
                                                        + 
format.format(x[0][i]) + " "
                                                        + 
format.format(x[1][i]));
                                        i++;
                                }
                        }
                } else {
                        for (int i = 0; i < n; i++) {
                                System.out.println("x[" + i + "] = " + 
format.format(x[0][i])
                                                + " " + format.format(x[1][i]));
                        }
                }
                x = twod ? FT2D(rows, cols, x, false) : FT1D(x, false);
                System.out.println("\n  back fft");
                if (twod) {
                        int i = 0;
                        for (int c = 0; c < cols; c++) {
                                for (int r = 0; r < rows; r++) {
                                        System.out.println("x[" + r + "][" + c 
+ "] = "
                                                        + 
format.format(x[0][i]) + " "
                                                        + 
format.format(x[1][i]));
                                        i++;
                                }
                        }
                } else {
                        for (int i = 0; i < n; i++) {
                                System.out.println("x[" + i + "] = " + 
format.format(x[0][i])
                                                + " " + format.format(x[1][i]));
                        }
                }
        }
}
  • 2007 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the visad archives: