All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jtransforms.fft.RealFFTUtils_2D Maven / Gradle / Ivy

There is a newer version: 3.1
Show newest version
/* ***** BEGIN LICENSE BLOCK *****
 * JTransforms
 * Copyright (c) 2007 onward, Piotr Wendykier
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */
package org.jtransforms.fft;

// @formatter:off
import pl.edu.icm.jlargearrays.DoubleLargeArray;
import pl.edu.icm.jlargearrays.FloatLargeArray;

/**
 * 
 * This is a set of utility methods for R/W access to data resulting from a call
 * to the Fourier transform of real data. Memory optimized methods,
 * namely
 * 
    *
  • {@link DoubleFFT_2D#realForward(double[])}
  • *
  • {@link DoubleFFT_2D#realForward(DoubleLargeArray)}
  • *
  • {@link DoubleFFT_2D#realForward(double[][])}
  • *
  • {@link FloatFFT_2D#realForward(float[])}
  • *
  • {@link FloatFFT_2D#realForward(FloatLargeArray)}
  • *
  • {@link FloatFFT_2D#realForward(float[][])}
  • *
* are implemented to handle this case specifically. However, packing of the * data in the data array is somewhat obscure. This class provides methods for * direct access to the data, without the burden of all necessary tests. *

Example for Fourier Transform of real, double precision 1d data

* *
 * DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
 * double[] data = new double[2 * rows * columns];
 * ...
 * fft.realForwardFull(data);
 * data[r1 * 2 * columns + c1] = val1;
 * val2 = data[r2 * 2 * columns + c2];
 * 
* is equivalent to *
 *   DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
 *   RealFFTUtils_2D unpacker = new RealFFTUtils_2D(rows, columns);
 *   double[] data = new double[rows * columns];
 *   ...
 *   fft.realForward(data);
 *   unpacker.pack(val1, r1, c1, data);
 *   val2 = unpacker.unpack(r2, c2, data, 0);
 * 
* Even (resp. odd) values of c correspond to the real (resp. * imaginary) part of the Fourier mode. *

Example for Fourier Transform of real, double precision 2d data

* *
 * DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
 * double[][] data = new double[rows][2 * columns];
 * ...
 * fft.realForwardFull(data);
 * data[r1][c1] = val1;
 * val2 = data[r2][c2];
 * 
* is equivalent to *
 *   DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
 *   RealFFTUtils_2D unpacker = new RealFFTUtils_2D(rows, columns);
 *   double[][] data = new double[rows][columns];
 *   ...
 *   fft.realForward(data);
 *   unpacker.pack(val1, r1, c1, data);
 *   val2 = unpacker.unpack(r2, c2, data, 0);
 * 
* Even (resp. odd) values of c correspond to the real (resp. * imaginary) part of the Fourier mode. * * @author Sébastien Brisard */ // @formatter:on public class RealFFTUtils_2D { /** * The constant int value of 1. */ private static final int ONE = 1; /** * The constant int value of 2. */ private static final int TWO = 2; /** * The constant int value of 0. */ private static final int ZERO = 0; /** * The constant int value of 1. */ private static final long ONEL = 1; /** * The constant int value of 2. */ private static final long TWOL = 2; /** * The constant int value of 0. */ private static final long ZEROL = 0; /** * The size of the data in the second direction. */ private final int columns; /** * The size of the data in the first direction. */ private final int rows; /** * The size of the data in the second direction. */ private final long columnsl; /** * The size of the data in the first direction. */ private final long rowsl; /** * Creates a new instance of this class. The size of the underlying * {@link DoubleFFT_2D} or {@link FloatFFT_2D} must be specified. * * @param rows * number of rows * @param columns * number of columns */ public RealFFTUtils_2D(final long rows, final long columns) { this.columns = (int) columns; this.rows = (int) rows; this.columnsl = columns; this.rowsl = rows; } /** * * Returns the 1d index of the specified 2d Fourier mode. In other words, if * packed contains the transformed data following a call to * {@link DoubleFFT_2D#realForward(double[])} or * {@link FloatFFT_2D#realForward(float[])}, then the returned value * index gives access to the [r][c] Fourier mode *
    *
  • if index == {@link Integer#MIN_VALUE}, then the Fourier * mode is zero,
  • *
  • if index >= 0, then the Fourier mode is * packed[index],
  • *
  • if index < 0, then the Fourier mode is * -packed[-index],
  • *
* * @param r * the row index * @param c * the column index * * @return the value of index */ public int getIndex(final int r, final int c) { final int cmod2 = c & ONE; final int rmul2 = r << ONE; if (r != ZERO) { if (c <= ONE) { if (rmul2 == rows) { if (cmod2 == ONE) { return Integer.MIN_VALUE; } return ((rows * columns) >> ONE); } else if (rmul2 < rows) { return columns * r + cmod2; } else { if (cmod2 == ZERO) { return columns * (rows - r); } else { return -(columns * (rows - r) + ONE); } } } else if ((c == columns) || (c == columns + ONE)) { if (rmul2 == rows) { if (cmod2 == ONE) { return Integer.MIN_VALUE; } return ((rows * columns) >> ONE) + ONE; } else if (rmul2 < rows) { if (cmod2 == ZERO) { return columns * (rows - r) + ONE; } else { return -(columns * (rows - r)); } } else { return columns * r + ONE - cmod2; } } else if (c < columns) { return columns * r + c; } else { if (cmod2 == ZERO) { return columns * (rows + TWO - r) - c; } else { return -(columns * (rows + TWO - r) - c + TWO); } } } else { if ((c == ONE) || (c == columns + ONE)) { return Integer.MIN_VALUE; } else if (c == columns) { return ONE; } else if (c < columns) { return c; } else { if (cmod2 == ZERO) { return (columns << ONE) - c; } else { return -((columns << ONE) - c + TWO); } } } } /** * * Returns the 1d index of the specified 2d Fourier mode. In other words, if * packed contains the transformed data following a call to * {@link DoubleFFT_2D#realForward(DoubleLargeArray)} or * {@link FloatFFT_2D#realForward(FloatLargeArray)}, then the returned value * index gives access to the [r][c] Fourier mode *
    *
  • if index == {@link Long#MIN_VALUE}, then the Fourier * mode is zero,
  • *
  • if index >= 0, then the Fourier mode is * packed[index],
  • *
  • if index < 0, then the Fourier mode is * -packed[-index],
  • *
* * @param r * the row index * @param c * the column index * * @return the value of index */ public long getIndex(final long r, final long c) { final long cmod2 = c & ONEL; final long rmul2 = r << ONEL; if (r != ZERO) { if (c <= ONEL) { if (rmul2 == rowsl) { if (cmod2 == ONEL) { return Long.MIN_VALUE; } return ((rowsl * columnsl) >> ONEL); } else if (rmul2 < rowsl) { return columnsl * r + cmod2; } else { if (cmod2 == ZEROL) { return columnsl * (rowsl - r); } else { return -(columnsl * (rowsl - r) + ONEL); } } } else if ((c == columnsl) || (c == columnsl + ONEL)) { if (rmul2 == rowsl) { if (cmod2 == ONEL) { return Long.MIN_VALUE; } return ((rowsl * columnsl) >> ONEL) + ONEL; } else if (rmul2 < rowsl) { if (cmod2 == ZEROL) { return columnsl * (rowsl - r) + ONEL; } else { return -(columnsl * (rowsl - r)); } } else { return columnsl * r + ONEL - cmod2; } } else if (c < columnsl) { return columnsl * r + c; } else { if (cmod2 == ZEROL) { return columnsl * (rowsl + TWOL - r) - c; } else { return -(columnsl * (rowsl + TWOL - r) - c + TWOL); } } } else { if ((c == ONEL) || (c == columnsl + ONEL)) { return Long.MIN_VALUE; } else if (c == columnsl) { return ONEL; } else if (c < columnsl) { return c; } else { if (cmod2 == ZEROL) { return (columnsl << ONEL) - c; } else { return -((columnsl << ONEL) - c + TWOL); } } } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link DoubleFFT_2D#realForward(double[])}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed */ public void pack(final double val, final int r, final int c, final double[] packed, final int pos) { final int index = getIndex(r, c); if (index >= 0) { packed[pos + index] = val; } else if (index > Integer.MIN_VALUE) { packed[pos - index] = -val; } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link DoubleFFT_2D#realForward(DoubleLargeArray)}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed */ public void pack(final double val, final long r, final long c, final DoubleLargeArray packed, final long pos) { final long index = getIndex(r, c); if (index >= 0) { packed.setDouble(pos + index, val); } else if (index > Long.MIN_VALUE) { packed.setDouble(pos - index, -val); } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link DoubleFFT_2D#realForward(double[][])}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data */ public void pack(final double val, final int r, final int c, final double[][] packed) { final int index = getIndex(r, c); if (index >= 0) { packed[index / columns][index % columns] = val; } else if (index > Integer.MIN_VALUE) { packed[(-index) / columns][(-index) % columns] = -val; } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link FloatFFT_2D#realForward(float[])}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed */ public void pack(final float val, final int r, final int c, final float[] packed, final int pos) { final int index = getIndex(r, c); if (index >= 0) { packed[pos + index] = val; } else if (index > Integer.MIN_VALUE) { packed[pos - index] = -val; } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link FloatFFT_2D#realForward(FloatLargeArray)}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed */ public void pack(final float val, final long r, final long c, final FloatLargeArray packed, final long pos) { final long index = getIndex(r, c); if (index >= 0) { packed.setFloat(pos + index, val); } else if (index > Long.MIN_VALUE) { packed.setFloat(pos - index, -val); } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Sets the specified Fourier mode of the transformed data. The data array * results from a call to {@link FloatFFT_2D#realForward(float[][])}. * * @param val * the new value of the [r][c] Fourier mode * @param r * the row index * @param c * the column index * @param packed * the transformed data */ public void pack(final float val, final int r, final int c, final float[][] packed) { final int index = getIndex(r, c); if (index >= 0) { packed[index / columns][index % columns] = val; } else if (index > Integer.MIN_VALUE) { packed[(-index) / columns][(-index) % columns] = -val; } else { throw new IllegalArgumentException( String.format( "[%d][%d] component cannot be modified (always zero)", r, c)); } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link DoubleFFT_2D#realForward(double[])}. * * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed * * @return the value of the [r][c] Fourier mode */ public double unpack(final int r, final int c, final double[] packed, final int pos) { final int index = getIndex(r, c); if (index >= 0) { return packed[pos + index]; } else if (index > Integer.MIN_VALUE) { return -packed[pos - index]; } else { return ZERO; } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link DoubleFFT_2D#realForward(DoubleLargeArray)}. * * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed * * @return the value of the [r][c] Fourier mode */ public double unpack(final long r, final long c, final DoubleLargeArray packed, final long pos) { final long index = getIndex(r, c); if (index >= 0) { return packed.getDouble(pos + index); } else if (index > Long.MIN_VALUE) { return -packed.getDouble(pos - index); } else { return ZEROL; } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link DoubleFFT_2D#realForward(double[][])} * . * * @param r * the row index * @param c * the column index * @param packed * the transformed data * * @return the value of the [r][c] Fourier mode */ public double unpack(final int r, final int c, final double[][] packed) { final int index = getIndex(r, c); if (index >= 0) { return packed[index / columns][index % columns]; } else if (index > Integer.MIN_VALUE) { return -packed[(-index) / columns][(-index) % columns]; } else { return ZERO; } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link FloatFFT_2D#realForward(float[])} * . * * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed * * @return the value of the [r][c] Fourier mode */ public float unpack(final int r, final int c, final float[] packed, final int pos) { final int index = getIndex(r, c); if (index >= 0) { return packed[pos + index]; } else if (index > Integer.MIN_VALUE) { return -packed[pos - index]; } else { return ZERO; } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link FloatFFT_2D#realForward(FloatLargeArray)} * . * * @param r * the row index * @param c * the column index * @param packed * the transformed data * @param pos * index of the first element in array packed * * @return the value of the [r][c] Fourier mode */ public float unpack(final long r, final long c, final FloatLargeArray packed, final long pos) { final long index = getIndex(r, c); if (index >= 0) { return packed.getFloat(pos + index); } else if (index > Long.MIN_VALUE) { return -packed.getFloat(pos - index); } else { return ZEROL; } } /** * Returns the specified Fourier mode of the transformed data. The data * array results from a call to {@link FloatFFT_2D#realForward(float[][])} . * * @param r * the row index * @param c * the column index * @param packed * the transformed data * * @return the value of the [r][c] Fourier mode */ public float unpack(final int r, final int c, final float[][] packed) { final int index = getIndex(r, c); if (index >= 0) { return packed[index / columns][index % columns]; } else if (index > Integer.MIN_VALUE) { return -packed[(-index) / columns][(-index) % columns]; } else { return ZERO; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy