From 74813500be92159bc18d4d7f7ca6d881db0a497d Mon Sep 17 00:00:00 2001 From: Sebastien Brisard Date: Mon, 30 Jan 2012 06:30:46 +0000 Subject: [PATCH] Moved private class o.a.c.m.transform.FastFourierTransformer.RootsOfUnity to o.a.c.m.complex.RootsOfUnity (MATH-677). git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1237544 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/math/complex/RootsOfUnity.java | 196 ++++++++++++++++++ .../transform/FastFourierTransformer.java | 172 +-------------- 2 files changed, 197 insertions(+), 171 deletions(-) create mode 100644 src/main/java/org/apache/commons/math/complex/RootsOfUnity.java diff --git a/src/main/java/org/apache/commons/math/complex/RootsOfUnity.java b/src/main/java/org/apache/commons/math/complex/RootsOfUnity.java new file mode 100644 index 000000000..0b53bfbdc --- /dev/null +++ b/src/main/java/org/apache/commons/math/complex/RootsOfUnity.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.commons.math.complex; + +import java.io.Serializable; + +import org.apache.commons.math.exception.MathIllegalArgumentException; +import org.apache.commons.math.exception.MathIllegalStateException; +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.util.FastMath; + +/** + * A helper class for the computation and caching of the {@code n}th + * roots of unity. + * + * @version $Id$ + * @since 3.0 + */ +public class RootsOfUnity implements Serializable { + + /** Serializable version id. */ + private static final long serialVersionUID = 6404784357747329667L; + + /** Number of roots of unity. */ + private int omegaCount; + + /** Real part of the roots. */ + private double[] omegaReal; + + /** Imaginary part of the roots for forward transform. */ + private double[] omegaImaginaryForward; + + /** Imaginary part of the roots for reverse transform. */ + private double[] omegaImaginaryInverse; + + /** Forward/reverse indicator. */ + private boolean isForward; + + /** + * Build an engine for computing the {@code n}th roots of + * unity. + */ + public RootsOfUnity() { + + omegaCount = 0; + omegaReal = null; + omegaImaginaryForward = null; + omegaImaginaryInverse = null; + isForward = true; + } + + /** + * 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 { + + if (omegaCount == 0) { + throw new MathIllegalStateException( + LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET); + } + return isForward; + } + + /** + *

+ * Computes the {@code n}th roots of unity. The roots are + * stored in {@code omega[]}, such that {@code omega[k] = w ^ k}, where + * {@code k = 0, ..., n - 1}, {@code w = exp(-2 π i / n)} and + * {@code i = sqrt(-1)}. + *

+ *

+ * Note that {@code n} is positive for forward transform and negative + * for inverse transform. + *

+ * + * @param n number of roots of unity to compute, positive for forward + * transform, negative for inverse transform + * @throws ZeroException if {@code n = 0} + */ + public synchronized void computeOmega(int n) throws ZeroException { + + if (n == 0) { + throw new ZeroException( + LocalizedFormats.CANNOT_COMPUTE_0TH_ROOT_OF_UNITY); + } + + isForward = n > 0; + + // avoid repetitive calculations + final int absN = FastMath.abs(n); + + if (absN == omegaCount) { + return; + } + + // 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; + } + + /** + * Get the real part of the {@code k}th + * {@code n}th root of unity. + * + * @param k index of the {@code n}th root of unity + * @return real part of the {@code k}th + * {@code n}th 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 {@code k}th + * {@code n}th root of unity. + * + * @param k index of the {@code n}th root of unity + * @return imaginary part of the {@code k}th + * {@code n}th 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]; + } +} \ No newline at end of file diff --git a/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java b/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java index 52d6c8201..836e563f0 100644 --- a/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java +++ b/src/main/java/org/apache/commons/math/transform/FastFourierTransformer.java @@ -22,11 +22,9 @@ import java.lang.reflect.Array; import org.apache.commons.math.analysis.FunctionUtils; import org.apache.commons.math.analysis.UnivariateFunction; import org.apache.commons.math.complex.Complex; +import org.apache.commons.math.complex.RootsOfUnity; 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.OutOfRangeException; -import org.apache.commons.math.exception.ZeroException; import org.apache.commons.math.exception.util.LocalizedFormats; import org.apache.commons.math.util.ArithmeticUtils; import org.apache.commons.math.util.FastMath; @@ -638,172 +636,4 @@ public class FastFourierTransformer implements Serializable { } } } - - - /** - * Computes the {@code n}th roots of unity. A cache of already - * computed values is maintained. - */ - private static class RootsOfUnity implements Serializable { - - /** Serializable version id. */ - private static final long serialVersionUID = 6404784357747329667L; - - /** Number of roots of unity. */ - private int omegaCount; - - /** Real part of the roots. */ - private double[] omegaReal; - - /** Imaginary part of the roots for forward transform. */ - private double[] omegaImaginaryForward; - - /** Imaginary part of the roots for reverse transform. */ - private double[] omegaImaginaryInverse; - - /** Forward/reverse indicator. */ - private boolean isForward; - - /** - * Build an engine for computing the {@code n}th roots of - * unity. - */ - public RootsOfUnity() { - - omegaCount = 0; - omegaReal = null; - omegaImaginaryForward = null; - omegaImaginaryInverse = null; - isForward = true; - } - - /** - * 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 { - - if (omegaCount == 0) { - throw new MathIllegalStateException( - LocalizedFormats.ROOTS_OF_UNITY_NOT_COMPUTED_YET); - } - return isForward; - } - - /** - *

- * Computes the {@code n}th roots of unity. The roots are - * stored in {@code omega[]}, such that {@code omega[k] = w ^ k}, where - * {@code k = 0, ..., n - 1}, {@code w = exp(-2 π i / n)} and - * {@code i = sqrt(-1)}. - *

- *

- * Note that {@code n} is positive for forward transform and negative - * for inverse transform. - *

- * - * @param n number of roots of unity to compute, positive for forward - * transform, negative for inverse transform - * @throws ZeroException if {@code n = 0} - */ - public synchronized void computeOmega(int n) throws ZeroException { - - if (n == 0) { - throw new ZeroException( - LocalizedFormats.CANNOT_COMPUTE_0TH_ROOT_OF_UNITY); - } - - isForward = n > 0; - - // avoid repetitive calculations - final int absN = FastMath.abs(n); - - if (absN == omegaCount) { - return; - } - - // 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; - } - - /** - * Get the real part of the {@code k}th - * {@code n}th root of unity. - * - * @param k index of the {@code n}th root of unity - * @return real part of the {@code k}th - * {@code n}th 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 {@code k}th - * {@code n}th root of unity. - * - * @param k index of the {@code n}th root of unity - * @return imaginary part of the {@code k}th - * {@code n}th 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]; - } - } }