Removed references to MathRuntimeException (MATH-677).

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1226053 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastien Brisard 2011-12-31 09:38:11 +00:00
parent a21d5ae301
commit 37d642ec30
1 changed files with 263 additions and 177 deletions

View File

@ -19,9 +19,15 @@ package org.apache.commons.math.transform;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.analysis.UnivariateFunction; import org.apache.commons.math.analysis.UnivariateFunction;
import org.apache.commons.math.complex.Complex; import org.apache.commons.math.complex.Complex;
import org.apache.commons.math.exception.DimensionMismatchException;
import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.MathIllegalStateException;
import org.apache.commons.math.exception.NonMonotonicSequenceException;
import org.apache.commons.math.exception.NotStrictlyPositiveException;
import org.apache.commons.math.exception.OutOfRangeException;
import org.apache.commons.math.exception.ZeroException;
import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.util.FastMath; import org.apache.commons.math.util.FastMath;
@ -75,8 +81,7 @@ import org.apache.commons.math.util.FastMath;
* factory method {@link #createUnitary()}. * factory method {@link #createUnitary()}.
* </p> * </p>
* *
* @version $Id: FastFourierTransformer.java 1212260 2011-12-09 06:45:09Z * @version $Id$
* celestin $
* @since 1.2 * @since 1.2
*/ */
public class FastFourierTransformer implements Serializable { public class FastFourierTransformer implements Serializable {
@ -139,10 +144,12 @@ public class FastFourierTransformer implements Serializable {
* *
* @param f the real data array to be transformed * @param f the real data array to be transformed
* @return the complex transformed array * @return the complex transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/ */
public Complex[] transform(double[] f) public Complex[] transform(double[] f)
throws IllegalArgumentException { throws MathIllegalArgumentException {
if (unitary) { if (unitary) {
final double s = 1.0 / FastMath.sqrt(f.length); final double s = 1.0 / FastMath.sqrt(f.length);
return scaleArray(fft(f, false), s); return scaleArray(fft(f, false), s);
@ -159,11 +166,19 @@ public class FastFourierTransformer implements Serializable {
* @param max the (exclusive) upper bound for the interval * @param max the (exclusive) upper bound for the interval
* @param n the number of sample points * @param n the number of sample points
* @return the complex transformed array * @return the complex transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws NonMonotonicSequenceException if the lower bound is greater
* than, or equal to the upper bound
* @throws NotStrictlyPositiveException if the number of sample points
* {@code n} is negative
* @throws MathIllegalArgumentException if the number of sample points
* {@code n} is not a power of two
*/ */
public Complex[] transform(UnivariateFunction f, public Complex[] transform(UnivariateFunction f,
double min, double max, int n) double min, double max, int n) throws
throws IllegalArgumentException { NonMonotonicSequenceException,
NotStrictlyPositiveException,
MathIllegalArgumentException {
final double[] data = sample(f, min, max, n); final double[] data = sample(f, min, max, n);
if (unitary) { if (unitary) {
final double s = 1.0 / FastMath.sqrt(n); final double s = 1.0 / FastMath.sqrt(n);
@ -177,10 +192,13 @@ public class FastFourierTransformer implements Serializable {
* *
* @param f the complex data array to be transformed * @param f the complex data array to be transformed
* @return the complex transformed array * @return the complex transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/ */
public Complex[] transform(Complex[] f) public Complex[] transform(Complex[] f)
throws IllegalArgumentException { throws MathIllegalArgumentException {
// TODO Is this necessary?
roots.computeOmega(f.length); roots.computeOmega(f.length);
if (unitary) { if (unitary) {
final double s = 1.0 / FastMath.sqrt(f.length); final double s = 1.0 / FastMath.sqrt(f.length);
@ -194,10 +212,11 @@ public class FastFourierTransformer implements Serializable {
* *
* @param f the real data array to be inversely transformed * @param f the real data array to be inversely transformed
* @return the complex inversely transformed array * @return the complex inversely transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/ */
public Complex[] inverseTransform(double[] f) public Complex[] inverseTransform(double[] f)
throws IllegalArgumentException { throws MathIllegalArgumentException {
final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length); final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length);
return scaleArray(fft(f, true), s); return scaleArray(fft(f, true), s);
@ -212,11 +231,18 @@ public class FastFourierTransformer implements Serializable {
* @param max the (exclusive) upper bound for the interval * @param max the (exclusive) upper bound for the interval
* @param n the number of sample points * @param n the number of sample points
* @return the complex inversely transformed array * @return the complex inversely transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws NonMonotonicSequenceException if the lower bound is greater
* than, or equal to the upper bound
* @throws NotStrictlyPositiveException if the number of sample points
* {@code n} is negative
* @throws MathIllegalArgumentException if the number of sample points
* {@code n} is not a power of two
*/ */
public Complex[] inverseTransform(UnivariateFunction f, public Complex[] inverseTransform(UnivariateFunction f,
double min, double max, int n) double min, double max, int n) throws
throws IllegalArgumentException { NonMonotonicSequenceException,
NotStrictlyPositiveException,
MathIllegalArgumentException {
final double[] data = sample(f, min, max, n); final double[] data = sample(f, min, max, n);
final double s = 1.0 / (unitary ? FastMath.sqrt(n) : n); final double s = 1.0 / (unitary ? FastMath.sqrt(n) : n);
@ -228,10 +254,11 @@ public class FastFourierTransformer implements Serializable {
* *
* @param f the complex data array to be inversely transformed * @param f the complex data array to be inversely transformed
* @return the complex inversely transformed array * @return the complex inversely transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws MathIllegalArgumentException if the length of the data array is
* not a power of two
*/ */
public Complex[] inverseTransform(Complex[] f) public Complex[] inverseTransform(Complex[] f)
throws IllegalArgumentException { throws MathIllegalArgumentException {
roots.computeOmega(-f.length); // pass negative argument roots.computeOmega(-f.length); // pass negative argument
final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length); final double s = 1.0 / (unitary ? FastMath.sqrt(f.length) : f.length);
@ -245,9 +272,10 @@ public class FastFourierTransformer implements Serializable {
* @param isInverse the indicator of forward or inverse transform * @param isInverse the indicator of forward or inverse transform
* @return the complex transformed array * @return the complex transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws IllegalArgumentException if any parameters are invalid
* @throws MathIllegalArgumentException if array length is not a power of 2
*/ */
protected Complex[] fft(double[] f, boolean isInverse) protected Complex[] fft(double[] f, boolean isInverse)
throws IllegalArgumentException { throws MathIllegalArgumentException {
verifyDataSet(f); verifyDataSet(f);
Complex[] transformed = new Complex[f.length]; Complex[] transformed = new Complex[f.length];
@ -290,15 +318,17 @@ public class FastFourierTransformer implements Serializable {
* @param data the complex data array to be transformed * @param data the complex data array to be transformed
* @return the complex transformed array * @return the complex transformed array
* @throws IllegalArgumentException if any parameters are invalid * @throws IllegalArgumentException if any parameters are invalid
* @throws MathIllegalArgumentException if array length is not a power of 2
*/ */
protected Complex[] fft(Complex[] data) protected Complex[] fft(Complex[] data)
throws IllegalArgumentException { throws MathIllegalArgumentException {
verifyDataSet(data);
final int n = data.length; final int n = data.length;
final Complex[] f = new Complex[n]; final Complex[] f = new Complex[n];
// initial simple cases // initial simple cases
verifyDataSet(data);
if (n == 1) { if (n == 1) {
f[0] = data[0]; f[0] = data[0];
return f; return f;
@ -372,15 +402,20 @@ public class FastFourierTransformer implements Serializable {
* @param max the (exclusive) upper bound for the interval * @param max the (exclusive) upper bound for the interval
* @param n the number of sample points * @param n the number of sample points
* @return the samples array * @return the samples array
* @throws IllegalArgumentException if any parameters are invalid * @throws NonMonotonicSequenceException if the lower bound is greater
* than, or equal to the upper bound
* @throws NotStrictlyPositiveException if the number of sample points
* {@code n} is negative
*/ */
public static double[] sample(UnivariateFunction f, double min, double max, int n) public static double[] sample(UnivariateFunction f,
throws IllegalArgumentException { double min, double max, int n) throws
NonMonotonicSequenceException,
NotStrictlyPositiveException {
if (n <= 0) { if (n <= 0) {
throw MathRuntimeException.createIllegalArgumentException( throw new NotStrictlyPositiveException(
LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES, LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
n); Integer.valueOf(n));
} }
verifyInterval(min, max); verifyInterval(min, max);
@ -401,6 +436,7 @@ public class FastFourierTransformer implements Serializable {
* @return a reference to the scaled array * @return a reference to the scaled array
*/ */
public static double[] scaleArray(double[] f, double d) { public static double[] scaleArray(double[] f, double d) {
for (int i = 0; i < f.length; i++) { for (int i = 0; i < f.length; i++) {
f[i] *= d; f[i] *= d;
} }
@ -416,6 +452,7 @@ public class FastFourierTransformer implements Serializable {
* @return a reference to the scaled array * @return a reference to the scaled array
*/ */
public static Complex[] scaleArray(Complex[] f, double d) { public static Complex[] scaleArray(Complex[] f, double d) {
for (int i = 0; i < f.length; i++) { for (int i = 0; i < f.length; i++) {
f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary()); f[i] = new Complex(d * f[i].getReal(), d * f[i].getImaginary());
} }
@ -436,12 +473,15 @@ public class FastFourierTransformer implements Serializable {
* Verifies that the data set has length of power of 2. * Verifies that the data set has length of power of 2.
* *
* @param d the data array * @param d the data array
* @throws IllegalArgumentException if array length is not power of 2 * @throws MathIllegalArgumentException if array length is not a power of 2
*/ */
public static void verifyDataSet(double[] d) throws IllegalArgumentException { public static void verifyDataSet(double[] d)
throws MathIllegalArgumentException {
if (!isPowerOf2(d.length)) { if (!isPowerOf2(d.length)) {
throw MathRuntimeException.createIllegalArgumentException( throw new MathIllegalArgumentException(
LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING, d.length); LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
Integer.valueOf(d.length));
} }
} }
@ -449,29 +489,34 @@ public class FastFourierTransformer implements Serializable {
* Verifies that the data set has length of power of 2. * Verifies that the data set has length of power of 2.
* *
* @param o the data array * @param o the data array
* @throws IllegalArgumentException if array length is not power of 2 * @throws MathIllegalArgumentException if array length is not a power of 2
*/ */
public static void verifyDataSet(Object[] o) throws IllegalArgumentException { public static void verifyDataSet(Object[] o)
throws MathIllegalArgumentException {
if (!isPowerOf2(o.length)) { if (!isPowerOf2(o.length)) {
throw MathRuntimeException.createIllegalArgumentException( throw new MathIllegalArgumentException(
LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING, o.length); LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
Integer.valueOf(o.length));
} }
} }
/** /**
* Verifies that the endpoints specify an interval. * Verifies that the end-points specify an interval.
* *
* @param lower lower endpoint * @param lower the lower end-point
* @param upper upper endpoint * @param upper the upper end-point
* @throws IllegalArgumentException if not interval * @throws NonMonotonicSequenceException if the lower end-point is greater
* than, or equal to the upper end-point
*/ */
public static void verifyInterval(double lower, double upper) public static void verifyInterval(double lower, double upper)
throws IllegalArgumentException { throws NonMonotonicSequenceException {
if (lower >= upper) { if (lower >= upper) {
throw MathRuntimeException.createIllegalArgumentException( throw new NonMonotonicSequenceException(
LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL, Double.valueOf(upper),
lower, upper); Double.valueOf(lower),
1);
} }
} }
@ -494,6 +539,7 @@ public class FastFourierTransformer implements Serializable {
*/ */
public Object mdfft(Object mdca, boolean forward) public Object mdfft(Object mdca, boolean forward)
throws IllegalArgumentException { throws IllegalArgumentException {
MultiDimensionalComplexMatrix mdcm = (MultiDimensionalComplexMatrix) MultiDimensionalComplexMatrix mdcm = (MultiDimensionalComplexMatrix)
new MultiDimensionalComplexMatrix(mdca).clone(); new MultiDimensionalComplexMatrix(mdca).clone();
int[] dimensionSize = mdcm.getDimensionSizes(); int[] dimensionSize = mdcm.getDimensionSizes();
@ -514,9 +560,10 @@ public class FastFourierTransformer implements Serializable {
* @param subVector recursion subvector * @param subVector recursion subvector
* @throws IllegalArgumentException if any dimension is not a power of two * @throws IllegalArgumentException if any dimension is not a power of two
*/ */
private void mdfft(MultiDimensionalComplexMatrix mdcm, boolean forward, private void mdfft(MultiDimensionalComplexMatrix mdcm,
int d, int[] subVector) boolean forward, int d, int[] subVector) throws
throws IllegalArgumentException { IllegalArgumentException {
int[] dimensionSize = mdcm.getDimensionSizes(); int[] dimensionSize = mdcm.getDimensionSizes();
//if done //if done
if (subVector.length == dimensionSize.length) { if (subVector.length == dimensionSize.length) {
@ -557,9 +604,8 @@ public class FastFourierTransformer implements Serializable {
} }
/** /**
* Complex matrix implementation. * Complex matrix implementation. Not designed for synchronized access may
* Not designed for synchronized access * eventually be replaced by jsr-83 of the java community process
* may eventually be replaced by jsr-83 of the java community process
* http://jcp.org/en/jsr/detail?id=83 * http://jcp.org/en/jsr/detail?id=83
* may require additional exception throws for other basic requirements. * may require additional exception throws for other basic requirements.
*/ */
@ -572,10 +618,14 @@ public class FastFourierTransformer implements Serializable {
/** Storage array. */ /** Storage array. */
protected Object multiDimensionalComplexArray; protected Object multiDimensionalComplexArray;
/** Simple constructor. /**
* @param multiDimensionalComplexArray array containing the matrix elements * Simple constructor.
*
* @param multiDimensionalComplexArray array containing the matrix
* elements
*/ */
public MultiDimensionalComplexMatrix(Object multiDimensionalComplexArray) { public MultiDimensionalComplexMatrix(
Object multiDimensionalComplexArray) {
this.multiDimensionalComplexArray = multiDimensionalComplexArray; this.multiDimensionalComplexArray = multiDimensionalComplexArray;
@ -604,22 +654,26 @@ public class FastFourierTransformer implements Serializable {
/** /**
* Get a matrix element. * Get a matrix element.
*
* @param vector indices of the element * @param vector indices of the element
* @return matrix element * @return matrix element
* @exception IllegalArgumentException if dimensions do not match * @exception DimensionMismatchException if dimensions do not match
*/ */
public Complex get(int... vector) public Complex get(int... vector)
throws IllegalArgumentException { throws DimensionMismatchException {
if (vector == null) { if (vector == null) {
if (dimensionSize.length > 0) { if (dimensionSize.length > 0) {
throw MathRuntimeException.createIllegalArgumentException( throw new DimensionMismatchException(
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, 0, dimensionSize.length); 0,
dimensionSize.length);
} }
return null; return null;
} }
if (vector.length != dimensionSize.length) { if (vector.length != dimensionSize.length) {
throw MathRuntimeException.createIllegalArgumentException( throw new DimensionMismatchException(
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, vector.length, dimensionSize.length); vector.length,
dimensionSize.length);
} }
Object lastDimension = multiDimensionalComplexArray; Object lastDimension = multiDimensionalComplexArray;
@ -632,23 +686,27 @@ public class FastFourierTransformer implements Serializable {
/** /**
* Set a matrix element. * Set a matrix element.
*
* @param magnitude magnitude of the element * @param magnitude magnitude of the element
* @param vector indices of the element * @param vector indices of the element
* @return the previous value * @return the previous value
* @exception IllegalArgumentException if dimensions do not match * @exception DimensionMismatchException if dimensions do not match
*/ */
public Complex set(Complex magnitude, int... vector) public Complex set(Complex magnitude, int... vector)
throws IllegalArgumentException { throws DimensionMismatchException {
if (vector == null) { if (vector == null) {
if (dimensionSize.length > 0) { if (dimensionSize.length > 0) {
throw MathRuntimeException.createIllegalArgumentException( throw new DimensionMismatchException(
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, 0, dimensionSize.length); 0,
dimensionSize.length);
} }
return null; return null;
} }
if (vector.length != dimensionSize.length) { if (vector.length != dimensionSize.length) {
throw MathRuntimeException.createIllegalArgumentException( throw new DimensionMismatchException(
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, vector.length, dimensionSize.length); vector.length,
dimensionSize.length);
} }
Object[] lastDimension = (Object[]) multiDimensionalComplexArray; Object[] lastDimension = (Object[]) multiDimensionalComplexArray;
@ -664,6 +722,7 @@ public class FastFourierTransformer implements Serializable {
/** /**
* Get the size in all dimensions. * Get the size in all dimensions.
*
* @return size in all dimensions * @return size in all dimensions
*/ */
public int[] getDimensionSizes() { public int[] getDimensionSizes() {
@ -672,6 +731,7 @@ public class FastFourierTransformer implements Serializable {
/** /**
* Get the underlying storage array. * Get the underlying storage array.
*
* @return underlying storage array * @return underlying storage array
*/ */
public Object getArray() { public Object getArray() {
@ -690,9 +750,11 @@ public class FastFourierTransformer implements Serializable {
/** /**
* Copy contents of current array into mdcm. * Copy contents of current array into mdcm.
*
* @param mdcm array where to copy data * @param mdcm array where to copy data
*/ */
private void clone(MultiDimensionalComplexMatrix mdcm) { private void clone(MultiDimensionalComplexMatrix mdcm) {
int[] vector = new int[dimensionSize.length]; int[] vector = new int[dimensionSize.length];
int size = 1; int size = 1;
for (int i = 0; i < dimensionSize.length; i++) { for (int i = 0; i < dimensionSize.length; i++) {
@ -719,146 +781,170 @@ public class FastFourierTransformer implements Serializable {
} }
/** Computes the n<sup>th</sup> roots of unity. /**
* A cache of already computed values is maintained. * Computes the {@code n}<sup>th</sup> roots of unity. A cache of already
* computed values is maintained.
*/ */
private static class RootsOfUnity implements Serializable { private static class RootsOfUnity implements Serializable {
/** Serializable version id. */ /** Serializable version id. */
private static final long serialVersionUID = 6404784357747329667L; private static final long serialVersionUID = 6404784357747329667L;
/** Number of roots of unity. */ /** Number of roots of unity. */
private int omegaCount; private int omegaCount;
/** Real part of the roots. */ /** Real part of the roots. */
private double[] omegaReal; private double[] omegaReal;
/** Imaginary part of the roots for forward transform. */ /** Imaginary part of the roots for forward transform. */
private double[] omegaImaginaryForward; private double[] omegaImaginaryForward;
/** Imaginary part of the roots for reverse transform. */ /** Imaginary part of the roots for reverse transform. */
private double[] omegaImaginaryInverse; private double[] omegaImaginaryInverse;
/** Forward/reverse indicator. */ /** Forward/reverse indicator. */
private boolean isForward; private boolean isForward;
/** /**
* Build an engine for computing then <sup>th</sup> roots of unity. * Build an engine for computing the {@code n}<sup>th</sup> roots of
*/ * unity.
public RootsOfUnity() { */
public RootsOfUnity() {
omegaCount = 0; omegaCount = 0;
omegaReal = null; omegaReal = null;
omegaImaginaryForward = null; omegaImaginaryForward = null;
omegaImaginaryInverse = null; omegaImaginaryInverse = null;
isForward = true; isForward = true;
}
/**
* Check if computation has been done for forward or reverse transform.
* @return true if computation has been done for forward transform
* @throws IllegalStateException if no roots of unity have been computed yet
*/
public synchronized boolean isForward() throws IllegalStateException {
if (omegaCount == 0) {
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET);
}
return isForward;
}
/** Computes the n<sup>th</sup> roots of unity.
* <p>The computed omega[] = { 1, w, w<sup>2</sup>, ... w<sup>(n-1)</sup> } where
* w = exp(-2 &pi; i / n), i = &sqrt;(-1).</p>
* <p>Note that n is positive for
* forward transform and negative for inverse transform.</p>
* @param n number of roots of unity to compute,
* positive for forward transform, negative for inverse transform
* @throws IllegalArgumentException if n = 0
*/
public synchronized void computeOmega(int n) throws IllegalArgumentException {
if (n == 0) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.CANNOT_COMPUTE_0TH_ROOT_OF_UNITY);
} }
isForward = n > 0; /**
* Check if computation has been done for forward or reverse transform.
*
* @return {@code true} if computation has been done for forward transform
* @throws MathIllegalStateException if no roots of unity have been computed
* yet
*/
public synchronized boolean isForward()
throws MathIllegalStateException {
// avoid repetitive calculations if (omegaCount == 0) {
final int absN = FastMath.abs(n); throw new MathIllegalStateException(
LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET);
if (absN == omegaCount) { }
return; return isForward;
} }
// calculate everything from scratch, for both forward and inverse versions /**
final double t = 2.0 * FastMath.PI / absN; * <p>
final double cosT = FastMath.cos(t); * Computes the {@code n}<sup>th</sup> roots of unity. The roots are
final double sinT = FastMath.sin(t); * stored in {@code omega[]}, such that {@code omega[k] = w ^ k}, where
omegaReal = new double[absN]; * {@code k = 0, ..., n - 1}, {@code w = exp(-2 &pi; i / n)} and
omegaImaginaryForward = new double[absN]; * {@code i = sqrt(-1)}.
omegaImaginaryInverse = new double[absN]; * </p>
omegaReal[0] = 1.0; * <p>
omegaImaginaryForward[0] = 0.0; * Note that {@code n} is positive for forward transform and negative
omegaImaginaryInverse[0] = 0.0; * for inverse transform.
for (int i = 1; i < absN; i++) { * </p>
omegaReal[i] = omegaReal[i - 1] * cosT + *
omegaImaginaryForward[i - 1] * sinT; * @param n number of roots of unity to compute, positive for forward
omegaImaginaryForward[i] = omegaImaginaryForward[i - 1] * cosT - * transform, negative for inverse transform
omegaReal[i - 1] * sinT; * @throws ZeroException if {@code n = 0}
omegaImaginaryInverse[i] = -omegaImaginaryForward[i]; */
} public synchronized void computeOmega(int n) throws ZeroException {
omegaCount = absN;
} if (n == 0) {
throw new ZeroException(
LocalizedFormats.CANNOT_COMPUTE_0TH_ROOT_OF_UNITY);
}
/** isForward = n > 0;
* Get the real part of the k<sup>th</sup> n<sup>th</sup> root of unity.
* @param k index of the n<sup>th</sup> root of unity
* @return real part of the k<sup>th</sup> n<sup>th</sup> root of unity
* @throws IllegalStateException if no roots of unity have been computed yet
* @throws IllegalArgumentException if k is out of range
*/
public synchronized double getOmegaReal(int k)
throws IllegalStateException, IllegalArgumentException {
if (omegaCount == 0) { // avoid repetitive calculations
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET); final int absN = FastMath.abs(n);
}
if ((k < 0) || (k >= omegaCount)) { if (absN == omegaCount) {
throw MathRuntimeException.createIllegalArgumentException( return;
LocalizedFormats.OUT_OF_RANGE_ROOT_OF_UNITY_INDEX, k, 0, omegaCount - 1); }
// calculate everything from scratch, for both forward and inverse
// versions
final double t = 2.0 * FastMath.PI / absN;
final double cosT = FastMath.cos(t);
final double sinT = FastMath.sin(t);
omegaReal = new double[absN];
omegaImaginaryForward = new double[absN];
omegaImaginaryInverse = new double[absN];
omegaReal[0] = 1.0;
omegaImaginaryForward[0] = 0.0;
omegaImaginaryInverse[0] = 0.0;
for (int i = 1; i < absN; i++) {
omegaReal[i] = omegaReal[i - 1] * cosT +
omegaImaginaryForward[i - 1] * sinT;
omegaImaginaryForward[i] = omegaImaginaryForward[i - 1] * cosT -
omegaReal[i - 1] * sinT;
omegaImaginaryInverse[i] = -omegaImaginaryForward[i];
}
omegaCount = absN;
} }
return omegaReal[k]; /**
* Get the real part of the {@code k}<sup>th</sup>
* {@code n}<sup>th</sup> root of unity.
*
* @param k index of the {@code n}<sup>th</sup> root of unity
* @return real part of the {@code k}<sup>th</sup>
* {@code n}<sup>th</sup> root of unity
* @throws MathIllegalStateException if no roots of unity have been
* computed yet
* @throws MathIllegalArgumentException if {@code k} is out of range
*/
public synchronized double getOmegaReal(int k)
throws MathIllegalStateException, MathIllegalArgumentException {
} if (omegaCount == 0) {
throw new MathIllegalStateException(
LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET);
}
if ((k < 0) || (k >= omegaCount)) {
throw new OutOfRangeException(
LocalizedFormats.OUT_OF_RANGE_ROOT_OF_UNITY_INDEX,
Integer.valueOf(k),
Integer.valueOf(0),
Integer.valueOf(omegaCount - 1));
}
/** return omegaReal[k];
* Get the imaginary part of the k<sup>th</sup> n<sup>th</sup> root of unity.
* @param k index of the n<sup>th</sup> root of unity
* @return imaginary part of the k<sup>th</sup> n<sup>th</sup> root of unity
* @throws IllegalStateException if no roots of unity have been computed yet
* @throws IllegalArgumentException if k is out of range
*/
public synchronized double getOmegaImaginary(int k)
throws IllegalStateException, IllegalArgumentException {
if (omegaCount == 0) {
throw MathRuntimeException.createIllegalStateException(LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET);
}
if ((k < 0) || (k >= omegaCount)) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.OUT_OF_RANGE_ROOT_OF_UNITY_INDEX, k, 0, omegaCount - 1);
} }
return isForward ? omegaImaginaryForward[k] : omegaImaginaryInverse[k]; /**
* Get the imaginary part of the {@code k}<sup>th</sup>
* {@code n}<sup>th</sup> root of unity.
*
* @param k index of the {@code n}<sup>th</sup> root of unity
* @return imaginary part of the {@code k}<sup>th</sup>
* {@code n}<sup>th</sup> root of unity
* @throws MathIllegalStateException if no roots of unity have been
* computed yet
* @throws OutOfRangeException if {@code k} is out of range
*/
public synchronized double getOmegaImaginary(int k)
throws MathIllegalStateException, OutOfRangeException {
} if (omegaCount == 0) {
throw new MathIllegalStateException(
LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET);
}
if ((k < 0) || (k >= omegaCount)) {
throw new OutOfRangeException(
LocalizedFormats.OUT_OF_RANGE_ROOT_OF_UNITY_INDEX,
Integer.valueOf(k),
Integer.valueOf(0),
Integer.valueOf(omegaCount - 1));
}
return isForward ? omegaImaginaryForward[k] :
omegaImaginaryInverse[k];
}
} }
} }