You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2021/05/23 03:00:02 UTC
[commons-math] branch modularized_master updated (44281ee ->
00e80fe)
This is an automated email from the ASF dual-hosted git repository.
erans pushed a change to branch modularized_master
in repository https://gitbox.apache.org/repos/asf/commons-math.git.
from 44281ee Ordering of modules in POM.
new 92094a0 MATH-1582: Modularization.
new 1b5a9a6 Unnecessary section in POM.
new 7e219ce Move normalization specifiers into their respective corresponding class.
new 00e80fe Javadoc.
The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../math4/legacy/analysis/FunctionUtils.java | 37 --
.../math4/legacy/transform/DctNormalization.java | 66 ---
.../math4/legacy/transform/DftNormalization.java | 56 ---
.../math4/legacy/transform/DstNormalization.java | 56 ---
.../legacy/transform/FastCosineTransformer.java | 183 --------
.../legacy/transform/FastFourierTransformer.java | 416 ------------------
.../legacy/transform/FastSineTransformer.java | 182 --------
.../math4/legacy/transform/RealTransformer.java | 67 ---
.../math4/legacy/transform/TransformType.java | 30 --
.../math4/legacy/transform/package-info.java | 22 -
.../math4/legacy/analysis/FunctionUtilsTest.java | 27 --
.../transform/FastFourierTransformerTest.java | 482 ---------------------
commons-math-neuralnet/pom.xml | 11 -
.../LICENCE | 0
.../NOTICE | 0
.../pom.xml | 23 +-
.../commons/math4/transform/ComplexTransform.java | 66 +++
.../math4/transform/FastCosineTransform.java | 230 ++++++++++
.../math4/transform/FastFourierTransform.java | 429 ++++++++++++++++++
.../math4/transform/FastHadamardTransform.java | 149 +++----
.../commons/math4/transform/FastSineTransform.java | 228 ++++++++++
.../commons/math4/transform/RealTransform.java | 51 +++
.../math4/transform/TransformException.java | 19 +-
.../commons/math4}/transform/TransformUtils.java | 116 +++--
.../commons/math4/transform}/package-info.java | 5 +-
.../transform/FastCosineTransformerTest.java | 167 ++++---
.../transform/FastFourierTransformerTest.java | 451 +++++++++++++++++++
.../transform/FastHadamardTransformerTest.java | 42 +-
.../math4}/transform/FastSineTransformerTest.java | 176 ++++----
.../transform/RealTransformerAbstractTest.java | 184 ++++----
.../math4/transform/TransformUtilsTest.java | 59 +++
pom.xml | 1 +
src/changes/changes.xml | 3 +
33 files changed, 1940 insertions(+), 2094 deletions(-)
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DctNormalization.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DftNormalization.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DstNormalization.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastCosineTransformer.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastFourierTransformer.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastSineTransformer.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/RealTransformer.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformType.java
delete mode 100644 commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/package-info.java
delete mode 100644 commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastFourierTransformerTest.java
copy {commons-math-neuralnet => commons-math-transform}/LICENCE (100%)
copy {commons-math-neuralnet => commons-math-transform}/NOTICE (100%)
copy {commons-math-neuralnet => commons-math-transform}/pom.xml (76%)
create mode 100644 commons-math-transform/src/main/java/org/apache/commons/math4/transform/ComplexTransform.java
create mode 100644 commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
create mode 100644 commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
rename commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformer.java => commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastHadamardTransform.java (67%)
create mode 100644 commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
create mode 100644 commons-math-transform/src/main/java/org/apache/commons/math4/transform/RealTransform.java
copy commons-math-neuralnet/src/main/java/org/apache/commons/math4/neuralnet/internal/NeuralNetException.java => commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformException.java (73%)
rename {commons-math-legacy/src/main/java/org/apache/commons/math4/legacy => commons-math-transform/src/main/java/org/apache/commons/math4}/transform/TransformUtils.java (52%)
copy {commons-math-neuralnet/src/main/java/org/apache/commons/math4/neuralnet => commons-math-transform/src/main/java/org/apache/commons/math4/transform}/package-info.java (90%)
rename {commons-math-legacy/src/test/java/org/apache/commons/math4/legacy => commons-math-transform/src/test/java/org/apache/commons/math4}/transform/FastCosineTransformerTest.java (51%)
create mode 100644 commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
rename {commons-math-legacy/src/test/java/org/apache/commons/math4/legacy => commons-math-transform/src/test/java/org/apache/commons/math4}/transform/FastHadamardTransformerTest.java (70%)
rename {commons-math-legacy/src/test/java/org/apache/commons/math4/legacy => commons-math-transform/src/test/java/org/apache/commons/math4}/transform/FastSineTransformerTest.java (53%)
rename {commons-math-legacy/src/test/java/org/apache/commons/math4/legacy => commons-math-transform/src/test/java/org/apache/commons/math4}/transform/RealTransformerAbstractTest.java (57%)
create mode 100644 commons-math-transform/src/test/java/org/apache/commons/math4/transform/TransformUtilsTest.java
[commons-math] 02/04: Unnecessary section in POM.
Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch modularized_master
in repository https://gitbox.apache.org/repos/asf/commons-math.git
commit 1b5a9a6ed39eef511e75181555824e56dbd99437
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun May 23 04:13:58 2021 +0200
Unnecessary section in POM.
---
commons-math-neuralnet/pom.xml | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/commons-math-neuralnet/pom.xml b/commons-math-neuralnet/pom.xml
index 56357cd..86498a3 100644
--- a/commons-math-neuralnet/pom.xml
+++ b/commons-math-neuralnet/pom.xml
@@ -61,15 +61,4 @@
</dependencies>
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <rerunFailingTestsCount>9</rerunFailingTestsCount>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
</project>
[commons-math] 03/04: Move normalization specifiers into their
respective corresponding class.
Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch modularized_master
in repository https://gitbox.apache.org/repos/asf/commons-math.git
commit 7e219ce34f998335645e28d94462213d8e37c7aa
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun May 23 04:15:52 2021 +0200
Move normalization specifiers into their respective corresponding class.
---
commons-math-transform/pom.xml | 2 +-
.../commons/math4/transform/DctNormalization.java | 62 ---------------------
.../commons/math4/transform/DftNormalization.java | 56 -------------------
.../commons/math4/transform/DstNormalization.java | 52 ------------------
.../math4/transform/FastCosineTransform.java | 58 +++++++++++++++++---
.../math4/transform/FastFourierTransform.java | 48 +++++++++++++---
.../commons/math4/transform/FastSineTransform.java | 48 +++++++++++++---
.../math4/transform/FastCosineTransformerTest.java | 28 +++++-----
.../transform/FastFourierTransformerTest.java | 64 ++++++++++------------
.../math4/transform/FastSineTransformerTest.java | 28 +++++-----
10 files changed, 190 insertions(+), 256 deletions(-)
diff --git a/commons-math-transform/pom.xml b/commons-math-transform/pom.xml
index 632ab2c..ae76e4a 100644
--- a/commons-math-transform/pom.xml
+++ b/commons-math-transform/pom.xml
@@ -73,7 +73,7 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <rerunFailingTestsCount>3</rerunFailingTestsCount>
+ <rerunFailingTestsCount>4</rerunFailingTestsCount>
</configuration>
</plugin>
</plugins>
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java
deleted file mode 100644
index fa77fae..0000000
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.math4.transform;
-
-/**
- * This enumeration defines the various types of normalizations that can be
- * applied to discrete cosine transforms (DCT).
- */
-public enum DctNormalization {
- /**
- * Should be passed to the constructor of {@link FastCosineTransform}
- * to use the <em>standard</em> normalization convention. The standard
- * DCT-I normalization convention is defined as follows
- * <ul>
- * <li>forward transform:
- * y<sub>n</sub> = (1/2) [x<sub>0</sub> + (-1)<sup>n</sup>x<sub>N-1</sub>]
- * + ∑<sub>k=1</sub><sup>N-2</sup>
- * x<sub>k</sub> cos[π nk / (N - 1)],</li>
- * <li>inverse transform:
- * x<sub>k</sub> = [1 / (N - 1)] [y<sub>0</sub>
- * + (-1)<sup>k</sup>y<sub>N-1</sub>]
- * + [2 / (N - 1)] ∑<sub>n=1</sub><sup>N-2</sup>
- * y<sub>n</sub> cos[π nk / (N - 1)],</li>
- * </ul>
- * where N is the size of the data sample.
- */
- STANDARD_DCT_I,
-
- /**
- * Should be passed to the constructor of {@link FastCosineTransform}
- * to use the <em>orthogonal</em> normalization convention. The orthogonal
- * DCT-I normalization convention is defined as follows
- * <ul>
- * <li>forward transform:
- * y<sub>n</sub> = [2(N - 1)]<sup>-1/2</sup> [x<sub>0</sub>
- * + (-1)<sup>n</sup>x<sub>N-1</sub>]
- * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>k=1</sub><sup>N-2</sup>
- * x<sub>k</sub> cos[π nk / (N - 1)],</li>
- * <li>inverse transform:
- * x<sub>k</sub> = [2(N - 1)]<sup>-1/2</sup> [y<sub>0</sub>
- * + (-1)<sup>k</sup>y<sub>N-1</sub>]
- * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>n=1</sub><sup>N-2</sup>
- * y<sub>n</sub> cos[π nk / (N - 1)],</li>
- * </ul>
- * which makes the transform orthogonal. N is the size of the data sample.
- */
- ORTHOGONAL_DCT_I;
-}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java
deleted file mode 100644
index 1198860..0000000
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.math4.transform;
-
-/**
- * This enumeration defines the various types of normalizations that can be
- * applied to discrete Fourier transforms (DFT). The exact definition of these
- * normalizations is detailed below.
- *
- * @see FastFourierTransform
- * @since 3.0
- */
-public enum DftNormalization {
- /**
- * Should be passed to the constructor of {@link FastFourierTransformer}
- * to use the <em>standard</em> normalization convention. This normalization
- * convention is defined as follows
- * <ul>
- * <li>forward transform: y<sub>n</sub> = ∑<sub>k=0</sub><sup>N-1</sup>
- * x<sub>k</sub> exp(-2πi n k / N),</li>
- * <li>inverse transform: x<sub>k</sub> = N<sup>-1</sup>
- * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> exp(2πi n k / N),</li>
- * </ul>
- * where N is the size of the data sample.
- */
- STANDARD,
-
- /**
- * Should be passed to the constructor of {@link FastFourierTransformer}
- * to use the <em>unitary</em> normalization convention. This normalization
- * convention is defined as follows
- * <ul>
- * <li>forward transform: y<sub>n</sub> = (1 / √N)
- * ∑<sub>k=0</sub><sup>N-1</sup> x<sub>k</sub>
- * exp(-2πi n k / N),</li>
- * <li>inverse transform: x<sub>k</sub> = (1 / √N)
- * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> exp(2πi n k / N),</li>
- * </ul>
- * which makes the transform unitary. N is the size of the data sample.
- */
- UNITARY;
-}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java
deleted file mode 100644
index 4e9ab03..0000000
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.math4.transform;
-
-/**
- * This enumeration defines the various types of normalizations that can be
- * applied to discrete sine transforms (DST).
- */
-public enum DstNormalization {
- /**
- * Should be passed to the constructor of {@link FastSineTransform} to
- * use the <em>standard</em> normalization convention. The standard DST-I
- * normalization convention is defined as follows
- * <ul>
- * <li>forward transform: y<sub>n</sub> = ∑<sub>k=0</sub><sup>N-1</sup>
- * x<sub>k</sub> sin(π nk / N),</li>
- * <li>inverse transform: x<sub>k</sub> = (2 / N)
- * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> sin(π nk / N),</li>
- * </ul>
- * where N is the size of the data sample, and x<sub>0</sub> = 0.
- */
- STANDARD_DST_I,
-
- /**
- * Should be passed to the constructor of {@link FastSineTransform} to
- * use the <em>orthogonal</em> normalization convention. The orthogonal
- * DCT-I normalization convention is defined as follows
- * <ul>
- * <li>Forward transform: y<sub>n</sub> = √(2 / N)
- * ∑<sub>k=0</sub><sup>N-1</sup> x<sub>k</sub> sin(π nk / N),</li>
- * <li>Inverse transform: x<sub>k</sub> = √(2 / N)
- * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> sin(π nk / N),</li>
- * </ul>
- * which makes the transform orthogonal. N is the size of the data sample,
- * and x<sub>0</sub> = 0.
- */
- ORTHOGONAL_DST_I
-}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
index 0aa2863..7b47acc 100644
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
@@ -29,7 +29,7 @@ import org.apache.commons.numbers.core.ArithmeticUtils;
* <p>
* There are several variants of the discrete cosine transform. The present
* implementation corresponds to DCT-I, with various normalization conventions,
- * which are specified by the parameter {@link DctNormalization}.
+ * which are specified by the parameter {@link Norm}.
* <p>
* DCT-I is equivalent to DFT of an <em>even extension</em> of the data series.
* More precisely, if x<sub>0</sub>, …, x<sub>N-1</sub> is the data set
@@ -65,7 +65,7 @@ public class FastCosineTransform implements RealTransform {
* transformed data.
* @param inverse Whether to perform the inverse transform.
*/
- public FastCosineTransform(final DctNormalization normalization,
+ public FastCosineTransform(final Norm normalization,
final boolean inverse) {
op = create(normalization, inverse);
}
@@ -74,7 +74,7 @@ public class FastCosineTransform implements RealTransform {
* @param normalization Normalization to be applied to the
* transformed data.
*/
- public FastCosineTransform(final DctNormalization normalization) {
+ public FastCosineTransform(final Norm normalization) {
this(normalization, false);
}
@@ -146,7 +146,7 @@ public class FastCosineTransform implements RealTransform {
x[nMi] = a + b;
t1 += c;
}
- final FastFourierTransform transformer = new FastFourierTransform(DftNormalization.STANDARD,
+ final FastFourierTransform transformer = new FastFourierTransform(FastFourierTransform.Norm.STD,
false);
final Complex[] y = transformer.apply(x);
@@ -171,16 +171,60 @@ public class FastCosineTransform implements RealTransform {
* @param inverse Whether to perform the inverse transform.
* @return the transform operator.
*/
- private UnaryOperator<double[]> create(final DctNormalization normalization,
+ private UnaryOperator<double[]> create(final Norm normalization,
final boolean inverse) {
if (inverse) {
- return normalization == DctNormalization.ORTHOGONAL_DCT_I ?
+ return normalization == Norm.ORTHO ?
(f) -> TransformUtils.scaleInPlace(fct(f), Math.sqrt(2d / (f.length - 1))) :
(f) -> TransformUtils.scaleInPlace(fct(f), 2d / (f.length - 1));
} else {
- return normalization == DctNormalization.ORTHOGONAL_DCT_I ?
+ return normalization == Norm.ORTHO ?
(f) -> TransformUtils.scaleInPlace(fct(f), Math.sqrt(2d / (f.length - 1))) :
(f) -> fct(f);
}
}
+
+ /**
+ * Normalization types.
+ */
+ public enum Norm {
+ /**
+ * Should be passed to the constructor of {@link FastCosineTransform}
+ * to use the <em>standard</em> normalization convention. The standard
+ * DCT-I normalization convention is defined as follows
+ * <ul>
+ * <li>forward transform:
+ * y<sub>n</sub> = (1/2) [x<sub>0</sub> + (-1)<sup>n</sup>x<sub>N-1</sub>]
+ * + ∑<sub>k=1</sub><sup>N-2</sup>
+ * x<sub>k</sub> cos[π nk / (N - 1)],</li>
+ * <li>inverse transform:
+ * x<sub>k</sub> = [1 / (N - 1)] [y<sub>0</sub>
+ * + (-1)<sup>k</sup>y<sub>N-1</sub>]
+ * + [2 / (N - 1)] ∑<sub>n=1</sub><sup>N-2</sup>
+ * y<sub>n</sub> cos[π nk / (N - 1)],</li>
+ * </ul>
+ * where N is the size of the data sample.
+ */
+ STD,
+
+ /**
+ * Should be passed to the constructor of {@link FastCosineTransform}
+ * to use the <em>orthogonal</em> normalization convention. The orthogonal
+ * DCT-I normalization convention is defined as follows
+ * <ul>
+ * <li>forward transform:
+ * y<sub>n</sub> = [2(N - 1)]<sup>-1/2</sup> [x<sub>0</sub>
+ * + (-1)<sup>n</sup>x<sub>N-1</sub>]
+ * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>k=1</sub><sup>N-2</sup>
+ * x<sub>k</sub> cos[π nk / (N - 1)],</li>
+ * <li>inverse transform:
+ * x<sub>k</sub> = [2(N - 1)]<sup>-1/2</sup> [y<sub>0</sub>
+ * + (-1)<sup>k</sup>y<sub>N-1</sub>]
+ * + [2 / (N - 1)]<sup>1/2</sup> ∑<sub>n=1</sub><sup>N-2</sup>
+ * y<sub>n</sub> cos[π nk / (N - 1)],</li>
+ * </ul>
+ * which makes the transform orthogonal. N is the size of the data sample.
+ */
+ ORTHO;
+ }
}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
index be704af..d11d74c 100644
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
@@ -29,7 +29,7 @@ import org.apache.commons.numbers.complex.Complex;
* <p>
* There are several variants of the discrete Fourier transform, with various
* normalization conventions, which are specified by the parameter
- * {@link DftNormalization}.
+ * {@link Norm}.
* <p>
* The current implementation of the discrete Fourier transform as a fast
* Fourier transform requires the length of the data set to be a power of 2.
@@ -38,8 +38,6 @@ import org.apache.commons.numbers.complex.Complex;
* reference, see S. Winograd,
* <i>On computing the discrete Fourier transform</i>, Mathematics of
* Computation, 32 (1978), 175 - 199.
- *
- * @see DftNormalization
*/
public class FastFourierTransform implements ComplexTransform {
/**
@@ -89,7 +87,7 @@ public class FastFourierTransform implements ComplexTransform {
-0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 };
/** Type of DFT. */
- private final DftNormalization normalization;
+ private final Norm normalization;
/** Inverse or forward. */
private final boolean inverse;
@@ -98,7 +96,7 @@ public class FastFourierTransform implements ComplexTransform {
* transformed data.
* @param inverse Whether to perform the inverse transform.
*/
- public FastFourierTransform(final DftNormalization normalization,
+ public FastFourierTransform(final Norm normalization,
final boolean inverse) {
this.normalization = normalization;
this.inverse = inverse;
@@ -108,7 +106,7 @@ public class FastFourierTransform implements ComplexTransform {
* @param normalization Normalization to be applied to the
* transformed data.
*/
- public FastFourierTransform(final DftNormalization normalization) {
+ public FastFourierTransform(final Norm normalization) {
this(normalization, false);
}
@@ -331,7 +329,7 @@ public class FastFourierTransform implements ComplexTransform {
final int n = dataR.length;
switch (normalization) {
- case STANDARD:
+ case STD:
if (inverse) {
final double scaleFactor = 1d / n;
for (int i = 0; i < n; i++) {
@@ -342,7 +340,7 @@ public class FastFourierTransform implements ComplexTransform {
break;
- case UNITARY:
+ case UNIT:
final double scaleFactor = 1d / Math.sqrt(n);
for (int i = 0; i < n; i++) {
dataR[i] *= scaleFactor;
@@ -394,4 +392,38 @@ public class FastFourierTransform implements ComplexTransform {
j += k;
}
}
+
+ /**
+ * Normalization types.
+ */
+ public enum Norm {
+ /**
+ * Should be passed to the constructor of {@link FastFourierTransformer}
+ * to use the <em>standard</em> normalization convention. This normalization
+ * convention is defined as follows
+ * <ul>
+ * <li>forward transform: y<sub>n</sub> = ∑<sub>k=0</sub><sup>N-1</sup>
+ * x<sub>k</sub> exp(-2πi n k / N),</li>
+ * <li>inverse transform: x<sub>k</sub> = N<sup>-1</sup>
+ * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> exp(2πi n k / N),</li>
+ * </ul>
+ * where N is the size of the data sample.
+ */
+ STD,
+
+ /**
+ * Should be passed to the constructor of {@link FastFourierTransformer}
+ * to use the <em>unitary</em> normalization convention. This normalization
+ * convention is defined as follows
+ * <ul>
+ * <li>forward transform: y<sub>n</sub> = (1 / √N)
+ * ∑<sub>k=0</sub><sup>N-1</sup> x<sub>k</sub>
+ * exp(-2πi n k / N),</li>
+ * <li>inverse transform: x<sub>k</sub> = (1 / √N)
+ * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> exp(2πi n k / N),</li>
+ * </ul>
+ * which makes the transform unitary. N is the size of the data sample.
+ */
+ UNIT;
+ }
}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
index da3c63b..4b37646 100644
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
@@ -29,7 +29,7 @@ import org.apache.commons.numbers.core.ArithmeticUtils;
* <p>
* There are several variants of the discrete sine transform. The present
* implementation corresponds to DST-I, with various normalization conventions,
- * which are specified by the parameter {@link DstNormalization}.
+ * which are specified by the parameter {@link Norm}.
* <strong>It should be noted that regardless to the convention, the first
* element of the dataset to be transformed must be zero.</strong>
* <p>
@@ -69,7 +69,7 @@ public class FastSineTransform implements RealTransform {
* @param normalization Normalization to be applied to the transformed data.
* @param inverse Whether to perform the inverse transform.
*/
- public FastSineTransform(final DstNormalization normalization,
+ public FastSineTransform(final Norm normalization,
final boolean inverse) {
op = create(normalization, inverse);
}
@@ -78,7 +78,7 @@ public class FastSineTransform implements RealTransform {
* @param normalization Normalization to be applied to the
* transformed data.
*/
- public FastSineTransform(final DstNormalization normalization) {
+ public FastSineTransform(final Norm normalization) {
this(normalization, false);
}
@@ -156,7 +156,7 @@ public class FastSineTransform implements RealTransform {
x[nMi] = a - b;
}
- final FastFourierTransform transform = new FastFourierTransform(DftNormalization.STANDARD);
+ final FastFourierTransform transform = new FastFourierTransform(FastFourierTransform.Norm.STD);
final Complex[] y = transform.apply(x);
// reconstruct the FST result for the original array
@@ -179,16 +179,50 @@ public class FastSineTransform implements RealTransform {
* @param inverse Whether to perform the inverse transform.
* @return the transform operator.
*/
- private UnaryOperator<double[]> create(final DstNormalization normalization,
+ private UnaryOperator<double[]> create(final Norm normalization,
final boolean inverse) {
if (inverse) {
- return normalization == DstNormalization.ORTHOGONAL_DST_I ?
+ return normalization == Norm.ORTHO ?
(f) -> TransformUtils.scaleInPlace(fst(f), Math.sqrt(2d / f.length)) :
(f) -> TransformUtils.scaleInPlace(fst(f), 2d / f.length);
} else {
- return normalization == DstNormalization.ORTHOGONAL_DST_I ?
+ return normalization == Norm.ORTHO ?
(f) -> TransformUtils.scaleInPlace(fst(f), Math.sqrt(2d / f.length)) :
(f) -> fst(f);
}
}
+
+ /**
+ * Normalization types.
+ */
+ public enum Norm {
+ /**
+ * Should be passed to the constructor of {@link FastSineTransform} to
+ * use the <em>standard</em> normalization convention. The standard DST-I
+ * normalization convention is defined as follows
+ * <ul>
+ * <li>forward transform: y<sub>n</sub> = ∑<sub>k=0</sub><sup>N-1</sup>
+ * x<sub>k</sub> sin(π nk / N),</li>
+ * <li>inverse transform: x<sub>k</sub> = (2 / N)
+ * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> sin(π nk / N),</li>
+ * </ul>
+ * where N is the size of the data sample, and x<sub>0</sub> = 0.
+ */
+ STD,
+
+ /**
+ * Should be passed to the constructor of {@link FastSineTransform} to
+ * use the <em>orthogonal</em> normalization convention. The orthogonal
+ * DCT-I normalization convention is defined as follows
+ * <ul>
+ * <li>Forward transform: y<sub>n</sub> = √(2 / N)
+ * ∑<sub>k=0</sub><sup>N-1</sup> x<sub>k</sub> sin(π nk / N),</li>
+ * <li>Inverse transform: x<sub>k</sub> = √(2 / N)
+ * ∑<sub>n=0</sub><sup>N-1</sup> y<sub>n</sub> sin(π nk / N),</li>
+ * </ul>
+ * which makes the transform orthogonal. N is the size of the data sample,
+ * and x<sub>0</sub> = 0.
+ */
+ ORTHO
+ }
}
diff --git a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
index 41212a4..c4d5a8f 100644
--- a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
@@ -40,7 +40,7 @@ import org.apache.commons.math3.analysis.function.Sinc;
public final class FastCosineTransformerTest
extends RealTransformerAbstractTest {
- private final DctNormalization normalization;
+ private final FastCosineTransform.Norm normalization;
private final int[] invalidDataSize;
@@ -48,7 +48,7 @@ public final class FastCosineTransformerTest
private final int[] validDataSize;
- public FastCosineTransformerTest(final DctNormalization normalization) {
+ public FastCosineTransformerTest(final FastCosineTransform.Norm normalization) {
this.normalization = normalization;
this.validDataSize = new int[] {
2, 3, 5, 9, 17, 33, 65, 129
@@ -69,8 +69,8 @@ public final class FastCosineTransformerTest
*/
@Parameters
public static Collection<Object[]> data() {
- final DctNormalization[] normalization = DctNormalization.values();
- final Object[][] data = new DctNormalization[normalization.length][1];
+ final FastCosineTransform.Norm[] normalization = FastCosineTransform.Norm.values();
+ final Object[][] data = new FastCosineTransform.Norm[normalization.length][1];
for (int i = 0; i < normalization.length; i++){
data[i][0] = normalization[i];
}
@@ -143,17 +143,17 @@ public final class FastCosineTransformerTest
}
final double s;
if (!inverse) {
- if (normalization == DctNormalization.STANDARD_DCT_I) {
+ if (normalization == FastCosineTransform.Norm.STD) {
s = 1.0;
- } else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
+ } else if (normalization == FastCosineTransform.Norm.ORTHO) {
s = Math.sqrt(2.0 / (n - 1.0));
} else {
throw new IllegalStateException();
}
} else {
- if (normalization == DctNormalization.STANDARD_DCT_I) {
+ if (normalization == FastCosineTransform.Norm.STD) {
s = 2.0 / (n - 1.0);
- } else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
+ } else if (normalization == FastCosineTransform.Norm.ORTHO) {
s = Math.sqrt(2.0 / (n - 1.0));
} else {
throw new IllegalStateException();
@@ -180,13 +180,13 @@ public final class FastCosineTransformerTest
4.0
};
- transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
+ transformer = new FastCosineTransform(FastCosineTransform.Norm.STD);
result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
- transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I, true);
+ transformer = new FastCosineTransform(FastCosineTransform.Norm.STD, true);
result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
@@ -194,13 +194,13 @@ public final class FastCosineTransformerTest
TransformUtils.scaleInPlace(x, Math.sqrt(0.5 * (x.length - 1)));
- transformer = new FastCosineTransform(DctNormalization.ORTHOGONAL_DCT_I);
+ transformer = new FastCosineTransform(FastCosineTransform.Norm.ORTHO);
result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- transformer = new FastCosineTransform(DctNormalization.ORTHOGONAL_DCT_I, true);
+ transformer = new FastCosineTransform(FastCosineTransform.Norm.ORTHO, true);
result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
@@ -212,7 +212,7 @@ public final class FastCosineTransformerTest
public void testParameters() throws Exception {
final UnivariateFunction sinFunction = new Sin();
final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
- final FastCosineTransform transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
+ final FastCosineTransform transformer = new FastCosineTransform(FastCosineTransform.Norm.STD);
try {
// bad interval
@@ -242,7 +242,7 @@ public final class FastCosineTransformerTest
public void testSinFunction() {
final UnivariateFunction sinFunction = new Sin();
final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
- final FastCosineTransform transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
+ final FastCosineTransform transformer = new FastCosineTransform(FastCosineTransform.Norm.STD);
double min, max, result[], tolerance = 1e-12;
int N = 9;
diff --git a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
index 4653d02..2e3e3d6 100644
--- a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
@@ -48,8 +48,7 @@ public final class FastFourierTransformerTest {
public void testTransformComplexSizeNotAPowerOfTwo() {
final int n = 127;
final Complex[] x = createComplexData(n);
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
@@ -68,8 +67,7 @@ public final class FastFourierTransformerTest {
public void testTransformRealSizeNotAPowerOfTwo() {
final int n = 127;
final double[] x = createRealData(n);
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
@@ -87,8 +85,7 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127;
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
@@ -106,8 +103,7 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128;
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
@@ -126,8 +122,7 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionInvalidBounds() {
final int n = 128;
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
@@ -192,7 +187,7 @@ public final class FastFourierTransformerTest {
private static void doTestTransformComplex(final int n,
final double tol,
- final DftNormalization normalization,
+ final FastFourierTransform.Norm normalization,
boolean inverse) {
final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final Complex[] x = createComplexData(n);
@@ -200,14 +195,14 @@ public final class FastFourierTransformerTest {
final double s;
if (!inverse) {
expected = dft(x, -1);
- if (normalization == DftNormalization.STANDARD){
+ if (normalization == FastFourierTransform.Norm.STD){
s = 1.0;
} else {
s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(x, 1);
- if (normalization == DftNormalization.STANDARD) {
+ if (normalization == FastFourierTransform.Norm.STD) {
s = 1.0 / n;
} else {
s = 1.0 / Math.sqrt(n);
@@ -228,7 +223,7 @@ public final class FastFourierTransformerTest {
private static void doTestTransformReal(final int n,
final double tol,
- final DftNormalization normalization,
+ final FastFourierTransform.Norm normalization,
final boolean inverse) {
final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final double[] x = createRealData(n);
@@ -240,14 +235,14 @@ public final class FastFourierTransformerTest {
final double s;
if (!inverse) {
expected = dft(xc, -1);
- if (normalization == DftNormalization.STANDARD) {
+ if (normalization == FastFourierTransform.Norm.STD) {
s = 1.0;
} else {
s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(xc, 1);
- if (normalization == DftNormalization.STANDARD) {
+ if (normalization == FastFourierTransform.Norm.STD) {
s = 1.0 / n;
} else {
s = 1.0 / Math.sqrt(n);
@@ -271,7 +266,7 @@ public final class FastFourierTransformerTest {
final double max,
int n,
final double tol,
- final DftNormalization normalization,
+ final FastFourierTransform.Norm normalization,
final boolean inverse) {
final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final Complex[] x = new Complex[n];
@@ -283,14 +278,14 @@ public final class FastFourierTransformerTest {
final double s;
if (!inverse) {
expected = dft(x, -1);
- if (normalization == DftNormalization.STANDARD) {
+ if (normalization == FastFourierTransform.Norm.STD) {
s = 1.0;
} else {
s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(x, 1);
- if (normalization == DftNormalization.STANDARD) {
+ if (normalization == FastFourierTransform.Norm.STD) {
s = 1.0 / n;
} else {
s = 1.0 / Math.sqrt(n);
@@ -312,16 +307,15 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformComplex() {
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
doTestTransformComplex(2, 1e-15, norm[i], type);
doTestTransformComplex(4, 1e-14, norm[i], type);
doTestTransformComplex(8, 1e-13, norm[i], type);
doTestTransformComplex(16, 1e-13, norm[i], type);
- doTestTransformComplex(32, 1e-13, norm[i], type);
- doTestTransformComplex(64, 1e-12, norm[i], type);
+ doTestTransformComplex(32, 1e-12, norm[i], type);
+ doTestTransformComplex(64, 1e-11, norm[i], type);
doTestTransformComplex(128, 1e-11, norm[i], type);
}
}
@@ -329,8 +323,7 @@ public final class FastFourierTransformerTest {
@Test
public void testStandardTransformReal() {
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
doTestTransformReal(2, 1e-15, norm[i], type);
@@ -351,8 +344,7 @@ public final class FastFourierTransformerTest {
final double min = -Math.PI;
final double max = Math.PI;
- final DftNormalization[] norm;
- norm = DftNormalization.values();
+ final FastFourierTransform.Norm[] norm = FastFourierTransform.Norm.values();
for (int i = 0; i < norm.length; i++) {
for (boolean type : new boolean[] { true, false }) {
@@ -388,14 +380,14 @@ public final class FastFourierTransformerTest {
Complex.ofCartesian(-2.6, -2.7),
Complex.ofCartesian(-2.09497474683058, -1.91507575950825)};
- transformer = new FastFourierTransform(DftNormalization.STANDARD);
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.STD);
result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i].getReal(), result[i].getReal(), tolerance);
Assert.assertEquals(y[i].getImaginary(), result[i].getImaginary(), tolerance);
}
- transformer = new FastFourierTransform(DftNormalization.STANDARD, true);
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.STD, true);
result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i].getReal(), tolerance);
@@ -406,14 +398,14 @@ public final class FastFourierTransformerTest {
TransformUtils.scaleInPlace(x2, 1.0 / Math.sqrt(x2.length));
Complex y2[] = y;
- transformer = new FastFourierTransform(DftNormalization.UNITARY);
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.UNIT);
result = transformer.apply(y2);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x2[i], result[i].getReal(), tolerance);
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
}
- transformer = new FastFourierTransform(DftNormalization.UNITARY, true);
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.UNIT, true);
result = transformer.apply(x2);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y2[i].getReal(), result[i].getReal(), tolerance);
@@ -430,8 +422,9 @@ public final class FastFourierTransformerTest {
Complex result[]; int N = 1 << 8;
double min, max, tolerance = 1e-12;
- min = 0.0; max = 2.0 * Math.PI;
- transformer = new FastFourierTransform(DftNormalization.STANDARD);
+ min = 0.0;
+ max = 2 * Math.PI;
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.STD);
result = transformer.apply(SIN, min, max, N);
Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-(N >> 1), result[1].getImaginary(), tolerance);
@@ -442,8 +435,9 @@ public final class FastFourierTransformerTest {
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
}
- min = -Math.PI; max = Math.PI;
- transformer = new FastFourierTransform(DftNormalization.STANDARD, true);
+ min = -Math.PI;
+ max = Math.PI;
+ transformer = new FastFourierTransform(FastFourierTransform.Norm.STD, true);
result = transformer.apply(SIN, min, max, N);
Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-0.5, result[1].getImaginary(), tolerance);
diff --git a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
index aeed09e..e8178f0 100644
--- a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
@@ -39,7 +39,7 @@ import org.apache.commons.math3.analysis.function.Sinc;
@RunWith(value = Parameterized.class)
public final class FastSineTransformerTest extends RealTransformerAbstractTest {
- private final DstNormalization normalization;
+ private final FastSineTransform.Norm normalization;
private final int[] invalidDataSize;
@@ -47,7 +47,7 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
private final int[] validDataSize;
- public FastSineTransformerTest(final DstNormalization normalization) {
+ public FastSineTransformerTest(final FastSineTransform.Norm normalization) {
this.normalization = normalization;
this.validDataSize = new int[] {
1, 2, 4, 8, 16, 32, 64, 128
@@ -68,8 +68,8 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
*/
@Parameters
public static Collection<Object[]> data() {
- final DstNormalization[] normalization = DstNormalization.values();
- final Object[][] data = new DstNormalization[normalization.length][1];
+ final FastSineTransform.Norm[] normalization = FastSineTransform.Norm.values();
+ final Object[][] data = new FastSineTransform.Norm[normalization.length][1];
for (int i = 0; i < normalization.length; i++) {
data[i][0] = normalization[i];
}
@@ -152,17 +152,17 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
}
final double s;
if (!inverse) {
- if (normalization == DstNormalization.STANDARD_DST_I) {
+ if (normalization == FastSineTransform.Norm.STD) {
s = 1;
- } else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
+ } else if (normalization == FastSineTransform.Norm.ORTHO) {
s = Math.sqrt(2d / n);
} else {
throw new IllegalStateException();
}
} else {
- if (normalization == DstNormalization.STANDARD_DST_I) {
+ if (normalization == FastSineTransform.Norm.STD) {
s = 2d / n;
- } else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
+ } else if (normalization == FastSineTransform.Norm.ORTHO) {
s = Math.sqrt(2d / n);
} else {
throw new IllegalStateException();
@@ -210,27 +210,27 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
-1.65685424949238, 0.795649469518633
};
- transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
+ transformer = new FastSineTransform(FastSineTransform.Norm.STD);
result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
- transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I, true);
+ transformer = new FastSineTransform(FastSineTransform.Norm.STD, true);
result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
TransformUtils.scaleInPlace(x, Math.sqrt(x.length / 2d));
- transformer = new FastSineTransform(DstNormalization.ORTHOGONAL_DST_I);
+ transformer = new FastSineTransform(FastSineTransform.Norm.ORTHO);
result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- transformer = new FastSineTransform(DstNormalization.ORTHOGONAL_DST_I, true);
+ transformer = new FastSineTransform(FastSineTransform.Norm.ORTHO, true);
result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
@@ -244,7 +244,7 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
public void testSinFunction() {
final UnivariateFunction sinFunction = new Sin();
final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
- final FastSineTransform transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
+ final FastSineTransform transformer = new FastSineTransform(FastSineTransform.Norm.STD);
double min, max, result[], tolerance = 1e-12; int N = 1 << 8;
min = 0.0;
@@ -271,7 +271,7 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
public void testParameters() throws Exception {
final UnivariateFunction sinFunction = new Sin();
final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
- final FastSineTransform transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
+ final FastSineTransform transformer = new FastSineTransform(FastSineTransform.Norm.STD);
try {
// bad interval
[commons-math] 04/04: Javadoc.
Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch modularized_master
in repository https://gitbox.apache.org/repos/asf/commons-math.git
commit 00e80fe76317b2b2b2869af6f285bab5553699a5
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun May 23 04:29:07 2021 +0200
Javadoc.
---
.../java/org/apache/commons/math4/transform/FastFourierTransform.java | 4 ++--
.../java/org/apache/commons/math4/transform/FastSineTransform.java | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
index d11d74c..6f4d5a9 100644
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
@@ -398,7 +398,7 @@ public class FastFourierTransform implements ComplexTransform {
*/
public enum Norm {
/**
- * Should be passed to the constructor of {@link FastFourierTransformer}
+ * Should be passed to the constructor of {@link FastFourierTransform}
* to use the <em>standard</em> normalization convention. This normalization
* convention is defined as follows
* <ul>
@@ -412,7 +412,7 @@ public class FastFourierTransform implements ComplexTransform {
STD,
/**
- * Should be passed to the constructor of {@link FastFourierTransformer}
+ * Should be passed to the constructor of {@link FastFourierTransform}
* to use the <em>unitary</em> normalization convention. This normalization
* convention is defined as follows
* <ul>
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
index 4b37646..c35c67d 100644
--- a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
@@ -87,7 +87,7 @@ public class FastSineTransform implements RealTransform {
*
* The first element of the specified data set is required to be {@code 0}.
*
- * @throws MathIllegalArgumentException if the length of the data array is
+ * @throws IllegalArgumentException if the length of the data array is
* not a power of two, or the first element of the data array is not zero.
*/
@Override
[commons-math] 01/04: MATH-1582: Modularization.
Posted by er...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch modularized_master
in repository https://gitbox.apache.org/repos/asf/commons-math.git
commit 92094a0993015cbdc2be1c0d6553b31ca76f4fe5
Author: Gilles Sadowski <gi...@gmail.com>
AuthorDate: Sun May 23 01:15:57 2021 +0200
MATH-1582: Modularization.
Code moved from "o.a.c.math4.legacy.transform" into a dedicated module.
---
.../math4/legacy/analysis/FunctionUtils.java | 37 --
.../legacy/transform/FastCosineTransformer.java | 183 ---------
.../legacy/transform/FastFourierTransformer.java | 416 -------------------
.../legacy/transform/FastSineTransformer.java | 182 --------
.../math4/legacy/transform/RealTransformer.java | 67 ---
.../math4/legacy/transform/TransformType.java | 30 --
.../math4/legacy/analysis/FunctionUtilsTest.java | 27 --
commons-math-transform/LICENCE | 457 +++++++++++++++++++++
commons-math-transform/NOTICE | 9 +
commons-math-transform/pom.xml | 82 ++++
.../commons/math4/transform/ComplexTransform.java | 66 +++
.../commons/math4}/transform/DctNormalization.java | 12 +-
.../commons/math4}/transform/DftNormalization.java | 4 +-
.../commons/math4}/transform/DstNormalization.java | 12 +-
.../math4/transform/FastCosineTransform.java | 186 +++++++++
.../math4/transform/FastFourierTransform.java | 397 ++++++++++++++++++
.../math4/transform/FastHadamardTransform.java | 149 ++++---
.../commons/math4/transform/FastSineTransform.java | 194 +++++++++
.../commons/math4/transform/RealTransform.java | 51 +++
.../math4/transform/TransformException.java | 52 +++
.../commons/math4}/transform/TransformUtils.java | 116 +++---
.../commons/math4}/transform/package-info.java | 7 +-
.../transform/FastCosineTransformerTest.java | 151 ++++---
.../transform/FastFourierTransformerTest.java | 325 +++++++--------
.../transform/FastHadamardTransformerTest.java | 42 +-
.../math4}/transform/FastSineTransformerTest.java | 160 ++++----
.../transform/RealTransformerAbstractTest.java | 184 ++++-----
.../math4/transform/TransformUtilsTest.java | 59 +++
pom.xml | 1 +
src/changes/changes.xml | 3 +
30 files changed, 2099 insertions(+), 1562 deletions(-)
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/FunctionUtils.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/FunctionUtils.java
index 6f0e550..cd4ff48 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/FunctionUtils.java
+++ b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/analysis/FunctionUtils.java
@@ -302,43 +302,6 @@ public class FunctionUtils {
};
}
- /**
- * Samples the specified univariate real function on the specified interval.
- * <p>
- * The interval is divided equally into {@code n} sections and sample points
- * are taken from {@code min} to {@code max - (max - min) / n}; therefore
- * {@code f} is not sampled at the upper bound {@code max}.</p>
- *
- * @param f Function to be sampled
- * @param min Lower bound of the interval (included).
- * @param max Upper bound of the interval (excluded).
- * @param n Number of sample points.
- * @return the array of samples.
- * @throws NumberIsTooLargeException if the lower bound {@code min} is
- * greater than, or equal to the upper bound {@code max}.
- * @throws NotStrictlyPositiveException if the number of sample points
- * {@code n} is negative.
- */
- public static double[] sample(UnivariateFunction f, double min, double max, int n)
- throws NumberIsTooLargeException, NotStrictlyPositiveException {
-
- if (n <= 0) {
- throw new NotStrictlyPositiveException(
- LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
- Integer.valueOf(n));
- }
- if (min >= max) {
- throw new NumberIsTooLargeException(min, max, false);
- }
-
- final double[] s = new double[n];
- final double h = (max - min) / n;
- for (int i = 0; i < n; i++) {
- s[i] = f.value(min + i * h);
- }
- return s;
- }
-
/** Convert regular functions to {@link UnivariateDifferentiableFunction}.
* <p>
* This method handle the case with one free parameter and several derivatives.
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastCosineTransformer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastCosineTransformer.java
deleted file mode 100644
index e95d5e4..0000000
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastCosineTransformer.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * 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.math4.legacy.transform;
-
-import java.io.Serializable;
-
-import org.apache.commons.numbers.complex.Complex;
-import org.apache.commons.numbers.core.ArithmeticUtils;
-import org.apache.commons.math4.legacy.analysis.FunctionUtils;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
-import org.apache.commons.math4.legacy.util.FastMath;
-
-/**
- * Implements the Fast Cosine Transform for transformation of one-dimensional
- * real data sets. For reference, see James S. Walker, <em>Fast Fourier
- * Transforms</em>, chapter 3 (ISBN 0849371635).
- * <p>
- * There are several variants of the discrete cosine transform. The present
- * implementation corresponds to DCT-I, with various normalization conventions,
- * which are specified by the parameter {@link DctNormalization}.
- * <p>
- * DCT-I is equivalent to DFT of an <em>even extension</em> of the data series.
- * More precisely, if x<sub>0</sub>, …, x<sub>N-1</sub> is the data set
- * to be cosine transformed, the extended data set
- * x<sub>0</sub><sup>#</sup>, …, x<sub>2N-3</sub><sup>#</sup>
- * is defined as follows
- * <ul>
- * <li>x<sub>k</sub><sup>#</sup> = x<sub>k</sub> if 0 ≤ k < N,</li>
- * <li>x<sub>k</sub><sup>#</sup> = x<sub>2N-2-k</sub>
- * if N ≤ k < 2N - 2.</li>
- * </ul>
- * <p>
- * Then, the standard DCT-I y<sub>0</sub>, …, y<sub>N-1</sub> of the real
- * data set x<sub>0</sub>, …, x<sub>N-1</sub> is equal to <em>half</em>
- * of the N first elements of the DFT of the extended data set
- * x<sub>0</sub><sup>#</sup>, …, x<sub>2N-3</sub><sup>#</sup>
- * <br>
- * y<sub>n</sub> = (1 / 2) ∑<sub>k=0</sub><sup>2N-3</sup>
- * x<sub>k</sub><sup>#</sup> exp[-2πi nk / (2N - 2)]
- * k = 0, …, N-1.
- * <p>
- * The present implementation of the discrete cosine transform as a fast cosine
- * transform requires the length of the data set to be a power of two plus one
- * (N = 2<sup>n</sup> + 1). Besides, it implicitly assumes
- * that the sampled function is even.
- *
- * @since 1.2
- */
-public class FastCosineTransformer implements RealTransformer, Serializable {
-
- /** Serializable version identifier. */
- static final long serialVersionUID = 20120212L;
-
- /** The type of DCT to be performed. */
- private final DctNormalization normalization;
-
- /**
- * Creates a new instance of this class, with various normalization
- * conventions.
- *
- * @param normalization the type of normalization to be applied to the
- * transformed data
- */
- public FastCosineTransformer(final DctNormalization normalization) {
- this.normalization = normalization;
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws MathIllegalArgumentException if the length of the data array is
- * not a power of two plus one
- */
- @Override
- public double[] transform(final double[] f, final TransformType type)
- throws MathIllegalArgumentException {
- if (type == TransformType.FORWARD) {
- if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
- final double s = FastMath.sqrt(2.0 / (f.length - 1));
- return TransformUtils.scaleArray(fct(f), s);
- }
- return fct(f);
- }
- final double s2 = 2.0 / (f.length - 1);
- final double s1;
- if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
- s1 = FastMath.sqrt(s2);
- } else {
- s1 = s2;
- }
- return TransformUtils.scaleArray(fct(f), s1);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException
- * if the lower bound is greater than, or equal to the upper bound
- * @throws org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException
- * if the number of sample points is negative
- * @throws MathIllegalArgumentException if the number of sample points is
- * not a power of two plus one
- */
- @Override
- public double[] transform(final UnivariateFunction f,
- final double min, final double max, final int n,
- final TransformType type) throws MathIllegalArgumentException {
-
- final double[] data = FunctionUtils.sample(f, min, max, n);
- return transform(data, type);
- }
-
- /**
- * Perform the FCT algorithm (including inverse).
- *
- * @param f the real data array to be transformed
- * @return the real transformed array
- * @throws MathIllegalArgumentException if the length of the data array is
- * not a power of two plus one
- */
- protected double[] fct(double[] f)
- throws MathIllegalArgumentException {
-
- final double[] transformed = new double[f.length];
-
- final int n = f.length - 1;
- if (!ArithmeticUtils.isPowerOfTwo(n)) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO_PLUS_ONE,
- Integer.valueOf(f.length));
- }
- if (n == 1) { // trivial case
- transformed[0] = 0.5 * (f[0] + f[1]);
- transformed[1] = 0.5 * (f[0] - f[1]);
- return transformed;
- }
-
- // construct a new array and perform FFT on it
- final double[] x = new double[n];
- x[0] = 0.5 * (f[0] + f[n]);
- x[n >> 1] = f[n >> 1];
- // temporary variable for transformed[1]
- double t1 = 0.5 * (f[0] - f[n]);
- for (int i = 1; i < (n >> 1); i++) {
- final double a = 0.5 * (f[i] + f[n - i]);
- final double b = FastMath.sin(i * FastMath.PI / n) * (f[i] - f[n - i]);
- final double c = FastMath.cos(i * FastMath.PI / n) * (f[i] - f[n - i]);
- x[i] = a - b;
- x[n - i] = a + b;
- t1 += c;
- }
- FastFourierTransformer transformer;
- transformer = new FastFourierTransformer(DftNormalization.STANDARD);
- Complex[] y = transformer.transform(x, TransformType.FORWARD);
-
- // reconstruct the FCT result for the original array
- transformed[0] = y[0].getReal();
- transformed[1] = t1;
- for (int i = 1; i < (n >> 1); i++) {
- transformed[2 * i] = y[i].getReal();
- transformed[2 * i + 1] = transformed[2 * i - 1] - y[i].getImaginary();
- }
- transformed[n] = y[n >> 1].getReal();
-
- return transformed;
- }
-}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastFourierTransformer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastFourierTransformer.java
deleted file mode 100644
index 23d10c4..0000000
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastFourierTransformer.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * 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.math4.legacy.transform;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import org.apache.commons.numbers.complex.Complex;
-import org.apache.commons.numbers.core.ArithmeticUtils;
-import org.apache.commons.math4.legacy.analysis.FunctionUtils;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
-import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
-import org.apache.commons.math4.legacy.util.FastMath;
-
-/**
- * Implements the Fast Fourier Transform for transformation of one-dimensional
- * real or complex data sets. For reference, see <em>Applied Numerical Linear
- * Algebra</em>, ISBN 0898713897, chapter 6.
- * <p>
- * There are several variants of the discrete Fourier transform, with various
- * normalization conventions, which are specified by the parameter
- * {@link DftNormalization}.
- * <p>
- * The current implementation of the discrete Fourier transform as a fast
- * Fourier transform requires the length of the data set to be a power of 2.
- * This greatly simplifies and speeds up the code. Users can pad the data with
- * zeros to meet this requirement. There are other flavors of FFT, for
- * reference, see S. Winograd,
- * <i>On computing the discrete Fourier transform</i>, Mathematics of
- * Computation, 32 (1978), 175 - 199.
- *
- * @see DftNormalization
- * @since 1.2
- */
-public class FastFourierTransformer implements Serializable {
- /** Serializable version identifier. */
- static final long serialVersionUID = 20120210L;
-
- /**
- * {@code W_SUB_N_R[i]} is the real part of
- * {@code exp(- 2 * i * pi / n)}:
- * {@code W_SUB_N_R[i] = cos(2 * pi/ n)}, where {@code n = 2^i}.
- */
- private static final double[] W_SUB_N_R =
- { 0x1.0p0, -0x1.0p0, 0x1.1a62633145c07p-54, 0x1.6a09e667f3bcdp-1
- , 0x1.d906bcf328d46p-1, 0x1.f6297cff75cbp-1, 0x1.fd88da3d12526p-1, 0x1.ff621e3796d7ep-1
- , 0x1.ffd886084cd0dp-1, 0x1.fff62169b92dbp-1, 0x1.fffd8858e8a92p-1, 0x1.ffff621621d02p-1
- , 0x1.ffffd88586ee6p-1, 0x1.fffff62161a34p-1, 0x1.fffffd8858675p-1, 0x1.ffffff621619cp-1
- , 0x1.ffffffd885867p-1, 0x1.fffffff62161ap-1, 0x1.fffffffd88586p-1, 0x1.ffffffff62162p-1
- , 0x1.ffffffffd8858p-1, 0x1.fffffffff6216p-1, 0x1.fffffffffd886p-1, 0x1.ffffffffff621p-1
- , 0x1.ffffffffffd88p-1, 0x1.fffffffffff62p-1, 0x1.fffffffffffd9p-1, 0x1.ffffffffffff6p-1
- , 0x1.ffffffffffffep-1, 0x1.fffffffffffffp-1, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0
- , 0x1.0p0, 0x1.0p0, 0x1.0p0 };
-
- /**
- * {@code W_SUB_N_I[i]} is the imaginary part of
- * {@code exp(- 2 * i * pi / n)}:
- * {@code W_SUB_N_I[i] = -sin(2 * pi/ n)}, where {@code n = 2^i}.
- */
- private static final double[] W_SUB_N_I =
- { 0x1.1a62633145c07p-52, -0x1.1a62633145c07p-53, -0x1.0p0, -0x1.6a09e667f3bccp-1
- , -0x1.87de2a6aea963p-2, -0x1.8f8b83c69a60ap-3, -0x1.917a6bc29b42cp-4, -0x1.91f65f10dd814p-5
- , -0x1.92155f7a3667ep-6, -0x1.921d1fcdec784p-7, -0x1.921f0fe670071p-8, -0x1.921f8becca4bap-9
- , -0x1.921faaee6472dp-10, -0x1.921fb2aecb36p-11, -0x1.921fb49ee4ea6p-12, -0x1.921fb51aeb57bp-13
- , -0x1.921fb539ecf31p-14, -0x1.921fb541ad59ep-15, -0x1.921fb5439d73ap-16, -0x1.921fb544197ap-17
- , -0x1.921fb544387bap-18, -0x1.921fb544403c1p-19, -0x1.921fb544422c2p-20, -0x1.921fb54442a83p-21
- , -0x1.921fb54442c73p-22, -0x1.921fb54442cefp-23, -0x1.921fb54442d0ep-24, -0x1.921fb54442d15p-25
- , -0x1.921fb54442d17p-26, -0x1.921fb54442d18p-27, -0x1.921fb54442d18p-28, -0x1.921fb54442d18p-29
- , -0x1.921fb54442d18p-30, -0x1.921fb54442d18p-31, -0x1.921fb54442d18p-32, -0x1.921fb54442d18p-33
- , -0x1.921fb54442d18p-34, -0x1.921fb54442d18p-35, -0x1.921fb54442d18p-36, -0x1.921fb54442d18p-37
- , -0x1.921fb54442d18p-38, -0x1.921fb54442d18p-39, -0x1.921fb54442d18p-40, -0x1.921fb54442d18p-41
- , -0x1.921fb54442d18p-42, -0x1.921fb54442d18p-43, -0x1.921fb54442d18p-44, -0x1.921fb54442d18p-45
- , -0x1.921fb54442d18p-46, -0x1.921fb54442d18p-47, -0x1.921fb54442d18p-48, -0x1.921fb54442d18p-49
- , -0x1.921fb54442d18p-50, -0x1.921fb54442d18p-51, -0x1.921fb54442d18p-52, -0x1.921fb54442d18p-53
- , -0x1.921fb54442d18p-54, -0x1.921fb54442d18p-55, -0x1.921fb54442d18p-56, -0x1.921fb54442d18p-57
- , -0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 };
-
- /** The type of DFT to be performed. */
- private final DftNormalization normalization;
-
- /**
- * Creates a new instance of this class, with various normalization
- * conventions.
- *
- * @param normalization the type of normalization to be applied to the
- * transformed data
- */
- public FastFourierTransformer(final DftNormalization normalization) {
- this.normalization = normalization;
- }
-
- /**
- * Performs identical index bit reversal shuffles on two arrays of identical
- * size. Each element in the array is swapped with another element based on
- * the bit-reversal of the index. For example, in an array with length 16,
- * item at binary index 0011 (decimal 3) would be swapped with the item at
- * binary index 1100 (decimal 12).
- *
- * @param a the first array to be shuffled
- * @param b the second array to be shuffled
- */
- private static void bitReversalShuffle2(double[] a, double[] b) {
- final int n = a.length;
- assert b.length == n;
- final int halfOfN = n >> 1;
-
- int j = 0;
- for (int i = 0; i < n; i++) {
- if (i < j) {
- // swap indices i & j
- double temp = a[i];
- a[i] = a[j];
- a[j] = temp;
-
- temp = b[i];
- b[i] = b[j];
- b[j] = temp;
- }
-
- int k = halfOfN;
- while (k <= j && k > 0) {
- j -= k;
- k >>= 1;
- }
- j += k;
- }
- }
-
- /**
- * Applies the proper normalization to the specified transformed data.
- *
- * @param dataRI the unscaled transformed data
- * @param normalization the normalization to be applied
- * @param type the type of transform (forward, inverse) which resulted in the specified data
- */
- private static void normalizeTransformedData(final double[][] dataRI,
- final DftNormalization normalization, final TransformType type) {
-
- final double[] dataR = dataRI[0];
- final double[] dataI = dataRI[1];
- final int n = dataR.length;
- assert dataI.length == n;
-
- switch (normalization) {
- case STANDARD:
- if (type == TransformType.INVERSE) {
- final double scaleFactor = 1.0 / ((double) n);
- for (int i = 0; i < n; i++) {
- dataR[i] *= scaleFactor;
- dataI[i] *= scaleFactor;
- }
- }
- break;
- case UNITARY:
- final double scaleFactor = 1.0 / FastMath.sqrt(n);
- for (int i = 0; i < n; i++) {
- dataR[i] *= scaleFactor;
- dataI[i] *= scaleFactor;
- }
- break;
- default:
- /*
- * This should never occur in normal conditions. However this
- * clause has been added as a safeguard if other types of
- * normalizations are ever implemented, and the corresponding
- * test is forgotten in the present switch.
- */
- throw new MathIllegalStateException();
- }
- }
-
- /**
- * Computes the standard transform of the specified complex data. The
- * computation is done in place. The input data is laid out as follows
- * <ul>
- * <li>{@code dataRI[0][i]} is the real part of the {@code i}-th data point,</li>
- * <li>{@code dataRI[1][i]} is the imaginary part of the {@code i}-th data point.</li>
- * </ul>
- *
- * @param dataRI the two dimensional array of real and imaginary parts of the data
- * @param normalization the normalization to be applied to the transformed data
- * @param type the type of transform (forward, inverse) to be performed
- * @throws DimensionMismatchException if the number of rows of the specified
- * array is not two, or the array is not rectangular
- * @throws MathIllegalArgumentException if the number of data points is not
- * a power of two
- */
- public static void transformInPlace(final double[][] dataRI,
- final DftNormalization normalization, final TransformType type) {
-
- if (dataRI.length != 2) {
- throw new DimensionMismatchException(dataRI.length, 2);
- }
- final double[] dataR = dataRI[0];
- final double[] dataI = dataRI[1];
- if (dataR.length != dataI.length) {
- throw new DimensionMismatchException(dataI.length, dataR.length);
- }
-
- final int n = dataR.length;
- if (!ArithmeticUtils.isPowerOfTwo(n)) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
- Integer.valueOf(n));
- }
-
- if (n == 1) {
- return;
- } else if (n == 2) {
- final double srcR0 = dataR[0];
- final double srcI0 = dataI[0];
- final double srcR1 = dataR[1];
- final double srcI1 = dataI[1];
-
- // X_0 = x_0 + x_1
- dataR[0] = srcR0 + srcR1;
- dataI[0] = srcI0 + srcI1;
- // X_1 = x_0 - x_1
- dataR[1] = srcR0 - srcR1;
- dataI[1] = srcI0 - srcI1;
-
- normalizeTransformedData(dataRI, normalization, type);
- return;
- }
-
- bitReversalShuffle2(dataR, dataI);
-
- // Do 4-term DFT.
- if (type == TransformType.INVERSE) {
- for (int i0 = 0; i0 < n; i0 += 4) {
- final int i1 = i0 + 1;
- final int i2 = i0 + 2;
- final int i3 = i0 + 3;
-
- final double srcR0 = dataR[i0];
- final double srcI0 = dataI[i0];
- final double srcR1 = dataR[i2];
- final double srcI1 = dataI[i2];
- final double srcR2 = dataR[i1];
- final double srcI2 = dataI[i1];
- final double srcR3 = dataR[i3];
- final double srcI3 = dataI[i3];
-
- // 4-term DFT
- // X_0 = x_0 + x_1 + x_2 + x_3
- dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
- dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
- // X_1 = x_0 - x_2 + j * (x_3 - x_1)
- dataR[i1] = srcR0 - srcR2 + (srcI3 - srcI1);
- dataI[i1] = srcI0 - srcI2 + (srcR1 - srcR3);
- // X_2 = x_0 - x_1 + x_2 - x_3
- dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
- dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
- // X_3 = x_0 - x_2 + j * (x_1 - x_3)
- dataR[i3] = srcR0 - srcR2 + (srcI1 - srcI3);
- dataI[i3] = srcI0 - srcI2 + (srcR3 - srcR1);
- }
- } else {
- for (int i0 = 0; i0 < n; i0 += 4) {
- final int i1 = i0 + 1;
- final int i2 = i0 + 2;
- final int i3 = i0 + 3;
-
- final double srcR0 = dataR[i0];
- final double srcI0 = dataI[i0];
- final double srcR1 = dataR[i2];
- final double srcI1 = dataI[i2];
- final double srcR2 = dataR[i1];
- final double srcI2 = dataI[i1];
- final double srcR3 = dataR[i3];
- final double srcI3 = dataI[i3];
-
- // 4-term DFT
- // X_0 = x_0 + x_1 + x_2 + x_3
- dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
- dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
- // X_1 = x_0 - x_2 + j * (x_3 - x_1)
- dataR[i1] = srcR0 - srcR2 + (srcI1 - srcI3);
- dataI[i1] = srcI0 - srcI2 + (srcR3 - srcR1);
- // X_2 = x_0 - x_1 + x_2 - x_3
- dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
- dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
- // X_3 = x_0 - x_2 + j * (x_1 - x_3)
- dataR[i3] = srcR0 - srcR2 + (srcI3 - srcI1);
- dataI[i3] = srcI0 - srcI2 + (srcR1 - srcR3);
- }
- }
-
- int lastN0 = 4;
- int lastLogN0 = 2;
- while (lastN0 < n) {
- int n0 = lastN0 << 1;
- int logN0 = lastLogN0 + 1;
- double wSubN0R = W_SUB_N_R[logN0];
- double wSubN0I = W_SUB_N_I[logN0];
- if (type == TransformType.INVERSE) {
- wSubN0I = -wSubN0I;
- }
-
- // Combine even/odd transforms of size lastN0 into a transform of size N0 (lastN0 * 2).
- for (int destEvenStartIndex = 0; destEvenStartIndex < n; destEvenStartIndex += n0) {
- int destOddStartIndex = destEvenStartIndex + lastN0;
-
- double wSubN0ToRR = 1;
- double wSubN0ToRI = 0;
-
- for (int r = 0; r < lastN0; r++) {
- double grR = dataR[destEvenStartIndex + r];
- double grI = dataI[destEvenStartIndex + r];
- double hrR = dataR[destOddStartIndex + r];
- double hrI = dataI[destOddStartIndex + r];
-
- // dest[destEvenStartIndex + r] = Gr + WsubN0ToR * Hr
- dataR[destEvenStartIndex + r] = grR + wSubN0ToRR * hrR - wSubN0ToRI * hrI;
- dataI[destEvenStartIndex + r] = grI + wSubN0ToRR * hrI + wSubN0ToRI * hrR;
- // dest[destOddStartIndex + r] = Gr - WsubN0ToR * Hr
- dataR[destOddStartIndex + r] = grR - (wSubN0ToRR * hrR - wSubN0ToRI * hrI);
- dataI[destOddStartIndex + r] = grI - (wSubN0ToRR * hrI + wSubN0ToRI * hrR);
-
- // WsubN0ToR *= WsubN0R
- double nextWsubN0ToRR = wSubN0ToRR * wSubN0R - wSubN0ToRI * wSubN0I;
- double nextWsubN0ToRI = wSubN0ToRR * wSubN0I + wSubN0ToRI * wSubN0R;
- wSubN0ToRR = nextWsubN0ToRR;
- wSubN0ToRI = nextWsubN0ToRI;
- }
- }
-
- lastN0 = n0;
- lastLogN0 = logN0;
- }
-
- normalizeTransformedData(dataRI, normalization, type);
- }
-
- /**
- * Returns the (forward, inverse) transform of the specified real data set.
- *
- * @param f the real data array to be transformed
- * @param type the type of transform (forward, inverse) to be performed
- * @return the complex transformed array
- * @throws MathIllegalArgumentException if the length of the data array is not a power of two
- */
- public Complex[] transform(final double[] f, final TransformType type) {
- final double[][] dataRI = new double[][] {
- Arrays.copyOf(f, f.length), new double[f.length]
- };
-
- transformInPlace(dataRI, normalization, type);
-
- return TransformUtils.createComplexArray(dataRI);
- }
-
- /**
- * Returns the (forward, inverse) transform of the specified real function,
- * sampled on the specified interval.
- *
- * @param f the function to be sampled and transformed
- * @param min the (inclusive) lower bound for the interval
- * @param max the (exclusive) upper bound for the interval
- * @param n the number of sample points
- * @param type the type of transform (forward, inverse) to be performed
- * @return the complex transformed array
- * @throws org.apache.commons.math4.legacy.exception.NumberIsTooLargeException
- * if the lower bound is greater than, or equal to the upper bound
- * @throws org.apache.commons.math4.legacy.exception.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(final UnivariateFunction f,
- final double min, final double max, final int n,
- final TransformType type) {
-
- final double[] data = FunctionUtils.sample(f, min, max, n);
- return transform(data, type);
- }
-
- /**
- * Returns the (forward, inverse) transform of the specified complex data set.
- *
- * @param f the complex data array to be transformed
- * @param type the type of transform (forward, inverse) to be performed
- * @return the complex transformed array
- * @throws MathIllegalArgumentException if the length of the data array is not a power of two
- */
- public Complex[] transform(final Complex[] f, final TransformType type) {
- final double[][] dataRI = TransformUtils.createRealImaginaryArray(f);
-
- transformInPlace(dataRI, normalization, type);
-
- return TransformUtils.createComplexArray(dataRI);
- }
-}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastSineTransformer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastSineTransformer.java
deleted file mode 100644
index 09707a0..0000000
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastSineTransformer.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 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.math4.legacy.transform;
-
-import java.io.Serializable;
-
-import org.apache.commons.numbers.complex.Complex;
-import org.apache.commons.numbers.core.ArithmeticUtils;
-import org.apache.commons.math4.legacy.analysis.FunctionUtils;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
-import org.apache.commons.math4.legacy.util.FastMath;
-
-/**
- * Implements the Fast Sine Transform for transformation of one-dimensional real
- * data sets. For reference, see James S. Walker, <em>Fast Fourier
- * Transforms</em>, chapter 3 (ISBN 0849371635).
- * <p>
- * There are several variants of the discrete sine transform. The present
- * implementation corresponds to DST-I, with various normalization conventions,
- * which are specified by the parameter {@link DstNormalization}.
- * <strong>It should be noted that regardless to the convention, the first
- * element of the dataset to be transformed must be zero.</strong>
- * <p>
- * DST-I is equivalent to DFT of an <em>odd extension</em> of the data series.
- * More precisely, if x<sub>0</sub>, …, x<sub>N-1</sub> is the data set
- * to be sine transformed, the extended data set x<sub>0</sub><sup>#</sup>,
- * …, x<sub>2N-1</sub><sup>#</sup> is defined as follows
- * <ul>
- * <li>x<sub>0</sub><sup>#</sup> = x<sub>0</sub> = 0,</li>
- * <li>x<sub>k</sub><sup>#</sup> = x<sub>k</sub> if 1 ≤ k < N,</li>
- * <li>x<sub>N</sub><sup>#</sup> = 0,</li>
- * <li>x<sub>k</sub><sup>#</sup> = -x<sub>2N-k</sub> if N + 1 ≤ k <
- * 2N.</li>
- * </ul>
- * <p>
- * Then, the standard DST-I y<sub>0</sub>, …, y<sub>N-1</sub> of the real
- * data set x<sub>0</sub>, …, x<sub>N-1</sub> is equal to <em>half</em>
- * of i (the pure imaginary number) times the N first elements of the DFT of the
- * extended data set x<sub>0</sub><sup>#</sup>, …,
- * x<sub>2N-1</sub><sup>#</sup> <br>
- * y<sub>n</sub> = (i / 2) ∑<sub>k=0</sub><sup>2N-1</sup>
- * x<sub>k</sub><sup>#</sup> exp[-2πi nk / (2N)]
- * k = 0, …, N-1.
- * <p>
- * The present implementation of the discrete sine transform as a fast sine
- * transform requires the length of the data to be a power of two. Besides,
- * it implicitly assumes that the sampled function is odd. In particular, the
- * first element of the data set must be 0, which is enforced in
- * {@link #transform(UnivariateFunction, double, double, int, TransformType)},
- * after sampling.
- *
- * @since 1.2
- */
-public class FastSineTransformer implements RealTransformer, Serializable {
-
- /** Serializable version identifier. */
- static final long serialVersionUID = 20120211L;
-
- /** The type of DST to be performed. */
- private final DstNormalization normalization;
-
- /**
- * Creates a new instance of this class, with various normalization conventions.
- *
- * @param normalization the type of normalization to be applied to the transformed data
- */
- public FastSineTransformer(final DstNormalization normalization) {
- this.normalization = normalization;
- }
-
- /**
- * {@inheritDoc}
- *
- * The first element of the specified data set is required to be {@code 0}.
- *
- * @throws MathIllegalArgumentException if the length of the data array is
- * not a power of two, or the first element of the data array is not zero
- */
- @Override
- public double[] transform(final double[] f, final TransformType type) {
- if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
- final double s = FastMath.sqrt(2.0 / f.length);
- return TransformUtils.scaleArray(fst(f), s);
- }
- if (type == TransformType.FORWARD) {
- return fst(f);
- }
- final double s = 2.0 / f.length;
- return TransformUtils.scaleArray(fst(f), s);
- }
-
- /**
- * {@inheritDoc}
- *
- * This implementation enforces {@code f(x) = 0.0} at {@code x = 0.0}.
- *
- * @throws org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException
- * if the lower bound is greater than, or equal to the upper bound
- * @throws org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException
- * if the number of sample points is negative
- * @throws MathIllegalArgumentException if the number of sample points is not a power of two
- */
- @Override
- public double[] transform(final UnivariateFunction f,
- final double min, final double max, final int n,
- final TransformType type) {
-
- final double[] data = FunctionUtils.sample(f, min, max, n);
- data[0] = 0.0;
- return transform(data, type);
- }
-
- /**
- * Perform the FST algorithm (including inverse). The first element of the
- * data set is required to be {@code 0}.
- *
- * @param f the real data array to be transformed
- * @return the real transformed array
- * @throws MathIllegalArgumentException if the length of the data array is
- * not a power of two, or the first element of the data array is not zero
- */
- protected double[] fst(double[] f) throws MathIllegalArgumentException {
-
- final double[] transformed = new double[f.length];
-
- if (!ArithmeticUtils.isPowerOfTwo(f.length)) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
- Integer.valueOf(f.length));
- }
- if (f[0] != 0.0) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.FIRST_ELEMENT_NOT_ZERO,
- Double.valueOf(f[0]));
- }
- final int n = f.length;
- if (n == 1) { // trivial case
- transformed[0] = 0.0;
- return transformed;
- }
-
- // construct a new array and perform FFT on it
- final double[] x = new double[n];
- x[0] = 0.0;
- x[n >> 1] = 2.0 * f[n >> 1];
- for (int i = 1; i < (n >> 1); i++) {
- final double a = FastMath.sin(i * FastMath.PI / n) * (f[i] + f[n - i]);
- final double b = 0.5 * (f[i] - f[n - i]);
- x[i] = a + b;
- x[n - i] = a - b;
- }
- FastFourierTransformer transformer;
- transformer = new FastFourierTransformer(DftNormalization.STANDARD);
- Complex[] y = transformer.transform(x, TransformType.FORWARD);
-
- // reconstruct the FST result for the original array
- transformed[0] = 0.0;
- transformed[1] = 0.5 * y[0].getReal();
- for (int i = 1; i < (n >> 1); i++) {
- transformed[2 * i] = -y[i].getImaginary();
- transformed[2 * i + 1] = y[i].getReal() + transformed[2 * i - 1];
- }
-
- return transformed;
- }
-}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/RealTransformer.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/RealTransformer.java
deleted file mode 100644
index 3009c77..0000000
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/RealTransformer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.math4.legacy.transform;
-
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
-import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
-
-/**
- * Interface for one-dimensional data sets transformations producing real results.
- * <p>
- * Such transforms include {@link FastSineTransformer sine transform},
- * {@link FastCosineTransformer cosine transform} or {@link
- * FastHadamardTransformer Hadamard transform}.
- *
- * @since 2.0
- */
-public interface RealTransformer {
-
- /**
- * Returns the (forward, inverse) transform of the specified real data set.
- *
- * @param f the real data array to be transformed (signal)
- * @param type the type of transform (forward, inverse) to be performed
- * @return the real transformed array (spectrum)
- * @throws MathIllegalArgumentException if the array cannot be transformed
- * with the given type (this may be for example due to array size, which is
- * constrained in some transforms)
- */
- double[] transform(double[] f, TransformType type) throws MathIllegalArgumentException;
-
- /**
- * Returns the (forward, inverse) transform of the specified real function,
- * sampled on the specified interval.
- *
- * @param f the function to be sampled and transformed
- * @param min the (inclusive) lower bound for the interval
- * @param max the (exclusive) upper bound for the interval
- * @param n the number of sample points
- * @param type the type of transform (forward, inverse) to be performed
- * @return the real transformed array
- * @throws NonMonotonicSequenceException if the lower bound is greater than, or equal to the upper bound
- * @throws NotStrictlyPositiveException if the number of sample points is negative
- * @throws MathIllegalArgumentException if the sample cannot be transformed
- * with the given type (this may be for example due to sample size, which is
- * constrained in some transforms)
- */
- double[] transform(UnivariateFunction f, double min, double max, int n,
- TransformType type)
- throws NonMonotonicSequenceException, NotStrictlyPositiveException, MathIllegalArgumentException;
-
-}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformType.java b/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformType.java
deleted file mode 100644
index 9207cbb..0000000
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformType.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.math4.legacy.transform;
-
-/**
- * This enumeration defines the type of transform which is to be computed.
- *
- * @since 3.0
- */
-public enum TransformType {
- /** The type to be specified for forward transforms. */
- FORWARD,
-
- /** The type to be specified for inverse transforms. */
- INVERSE;
-}
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/FunctionUtilsTest.java b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/FunctionUtilsTest.java
index af69078..01ffeb0 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/FunctionUtilsTest.java
+++ b/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/analysis/FunctionUtilsTest.java
@@ -208,33 +208,6 @@ public class FunctionUtilsTest {
}
}
- @Test(expected = NumberIsTooLargeException.class)
- public void testSampleWrongBounds(){
- FunctionUtils.sample(new Sin(), FastMath.PI, 0.0, 10);
- }
-
- @Test(expected = NotStrictlyPositiveException.class)
- public void testSampleNegativeNumberOfPoints(){
- FunctionUtils.sample(new Sin(), 0.0, FastMath.PI, -1);
- }
-
- @Test(expected = NotStrictlyPositiveException.class)
- public void testSampleNullNumberOfPoints(){
- FunctionUtils.sample(new Sin(), 0.0, FastMath.PI, 0);
- }
-
- @Test
- public void testSample() {
- final int n = 11;
- final double min = 0.0;
- final double max = FastMath.PI;
- final double[] actual = FunctionUtils.sample(new Sin(), min, max, n);
- for (int i = 0; i < n; i++) {
- final double x = min + (max - min) / n * i;
- Assert.assertEquals("x = " + x, FastMath.sin(x), actual[i], 0.0);
- }
- }
-
@Test
public void testToDifferentiableUnivariate() {
diff --git a/commons-math-transform/LICENCE b/commons-math-transform/LICENCE
new file mode 100644
index 0000000..d97b49a
--- /dev/null
+++ b/commons-math-transform/LICENCE
@@ -0,0 +1,457 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
+
+Apache Commons Math includes the following code provided to the ASF under the
+Apache License 2.0:
+
+ - The inverse error function implementation in the Erf class is based on CUDA
+ code developed by Mike Giles, Oxford-Man Institute of Quantitative Finance,
+ and published in GPU Computing Gems, volume 2, 2010 (grant received on
+ March 23th 2013)
+ - The LinearConstraint, LinearObjectiveFunction, LinearOptimizer,
+ RelationShip, SimplexSolver and SimplexTableau classes in package
+ org.apache.commons.math3.optimization.linear include software developed by
+ Benjamin McCann (http://www.benmccann.com) and distributed with
+ the following copyright: Copyright 2009 Google Inc. (grant received on
+ March 16th 2009)
+ - The class "org.apache.commons.math3.exception.util.LocalizedFormatsTest" which
+ is an adapted version of "OrekitMessagesTest" test class for the Orekit library
+ - The "org.apache.commons.math3.analysis.interpolation.HermiteInterpolator"
+ has been imported from the Orekit space flight dynamics library.
+
+===============================================================================
+
+
+
+APACHE COMMONS MATH DERIVATIVE WORKS:
+
+The Apache commons-math library includes a number of subcomponents
+whose implementation is derived from original sources written
+in C or Fortran. License terms of the original sources
+are reproduced below.
+
+===============================================================================
+For the lmder, lmpar and qrsolv Fortran routine from minpack and translated in
+the LevenbergMarquardtOptimizer class in package
+org.apache.commons.math3.optimization.general
+Original source copyright and license statement:
+
+Minpack Copyright Notice (1999) University of Chicago. 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.
+
+3. The end-user documentation included with the
+redistribution, if any, must include the following
+acknowledgment:
+
+ "This product includes software developed by the
+ University of Chicago, as Operator of Argonne National
+ Laboratory.
+
+Alternately, this acknowledgment may appear in the software
+itself, if and wherever such third-party acknowledgments
+normally appear.
+
+4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
+WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
+UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
+THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
+OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
+OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
+USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
+THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
+DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
+UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
+BE CORRECTED.
+
+5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
+HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
+ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
+INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
+ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
+PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
+SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
+(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
+EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
+POSSIBILITY OF SUCH LOSS OR DAMAGES.
+===============================================================================
+
+Copyright and license statement for the odex Fortran routine developed by
+E. Hairer and G. Wanner and translated in GraggBulirschStoerIntegrator class
+in package org.apache.commons.math3.ode.nonstiff:
+
+
+Copyright (c) 2004, Ernst Hairer
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- 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 REGENTS 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.
+===============================================================================
+
+Copyright and license statement for the original Mersenne twister C
+routines translated in MersenneTwister class in package
+org.apache.commons.math3.random:
+
+ Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+ 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.
+
+ 3. The names of its contributors may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ 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.
+
+===============================================================================
+
+The initial code for shuffling an array (originally in class
+"org.apache.commons.math3.random.RandomDataGenerator", now replaced by
+a method in class "org.apache.commons.math3.util.MathArrays") was
+inspired from the algorithm description provided in
+"Algorithms", by Ian Craw and John Pulham (University of Aberdeen 1999).
+The textbook (containing a proof that the shuffle is uniformly random) is
+available here:
+ http://citeseerx.ist.psu.edu/viewdoc/download;?doi=10.1.1.173.1898&rep=rep1&type=pdf
+
+===============================================================================
+License statement for the direction numbers in the resource files for Sobol sequences.
+
+-----------------------------------------------------------------------------
+Licence pertaining to sobol.cc and the accompanying sets of direction numbers
+
+-----------------------------------------------------------------------------
+Copyright (c) 2008, Frances Y. Kuo and Stephen Joe
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the names of the copyright holders nor the names of the
+ University of New South Wales and the University of Waikato
+ and its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 HOLDERS 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.
+===============================================================================
+
+The initial commit of package "org.apache.commons.math3.ml.neuralnet" is
+an adapted version of code developed in the context of the Data Processing
+and Analysis Consortium (DPAC) of the "Gaia" project of the European Space
+Agency (ESA).
+===============================================================================
+
+The initial commit of the class "org.apache.commons.math3.special.BesselJ" is
+an adapted version of code translated from the netlib Fortran program, rjbesl
+http://www.netlib.org/specfun/rjbesl by R.J. Cody at Argonne National
+Laboratory (USA). There is no license or copyright statement included with the
+original Fortran sources.
+===============================================================================
+
+
+The BracketFinder (package org.apache.commons.math3.optimization.univariate)
+and PowellOptimizer (package org.apache.commons.math3.optimization.general)
+classes are based on the Python code in module "optimize.py" (version 0.5)
+developed by Travis E. Oliphant for the SciPy library (http://www.scipy.org/)
+Copyright © 2003-2009 SciPy Developers.
+
+SciPy license
+Copyright © 2001, 2002 Enthought, Inc.
+All rights reserved.
+
+Copyright © 2003-2013 SciPy Developers.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of Enthought nor the names of the SciPy Developers may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+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 REGENTS 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.
+===============================================================================
+
diff --git a/commons-math-transform/NOTICE b/commons-math-transform/NOTICE
new file mode 100644
index 0000000..587cd7f
--- /dev/null
+++ b/commons-math-transform/NOTICE
@@ -0,0 +1,9 @@
+Apache Commons Math
+Copyright 2001-2020 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+This product includes software developed for Orekit by
+CS Systèmes d'Information (http://www.c-s.fr/)
+Copyright 2010-2012 CS Systèmes d'Information
diff --git a/commons-math-transform/pom.xml b/commons-math-transform/pom.xml
new file mode 100644
index 0000000..632ab2c
--- /dev/null
+++ b/commons-math-transform/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-math-parent</artifactId>
+ <version>4.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>commons-math4-transform</artifactId>
+ <name>Transforms</name>
+
+ <description>Fourier, Sine, Cosine, Hadamard.</description>
+
+ <properties>
+ <!-- The Java Module System Name -->
+ <commons.module.name>org.apache.commons.math4.transform</commons.module.name>
+ <!-- This value must reflect the current name of the base package. -->
+ <commons.osgi.symbolicName>org.apache.commons.math4.transform</commons.osgi.symbolicName>
+ <!-- OSGi -->
+ <commons.osgi.export>org.apache.commons.math4.transform</commons.osgi.export>
+ <!-- Workaround to avoid duplicating config files. -->
+ <math.parent.dir>${basedir}/..</math.parent.dir>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-numbers-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-numbers-complex</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-rng-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-math3</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <rerunFailingTestsCount>3</rerunFailingTestsCount>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/ComplexTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/ComplexTransform.java
new file mode 100644
index 0000000..68697da
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/ComplexTransform.java
@@ -0,0 +1,66 @@
+/*
+ * 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.math4.transform;
+
+import java.util.function.DoubleUnaryOperator;
+import java.util.function.UnaryOperator;
+
+import org.apache.commons.numbers.complex.Complex;
+
+/**
+ * {@link Complex} transform.
+ * <p>
+ * Such transforms include {@link FastSineTransform sine transform},
+ * {@link FastCosineTransform cosine transform} or {@link
+ * FastHadamardTransform Hadamard transform}.
+ */
+public interface ComplexTransform extends UnaryOperator<Complex[]> {
+ /**
+ * Returns the transform of the specified data set.
+ *
+ * @param f the data array to be transformed (signal).
+ * @return the transformed array (spectrum).
+ * @throws IllegalArgumentException if the transform cannot be performed.
+ */
+ Complex[] apply(Complex[] f);
+
+ /**
+ * Returns the transform of the specified data set.
+ *
+ * @param f the data array to be transformed (signal).
+ * @return the transformed array (spectrum).
+ * @throws IllegalArgumentException if the transform cannot be performed.
+ */
+ Complex[] apply(double[] f);
+
+ /**
+ * Returns the transform of the specified function.
+ *
+ * @param f Function to be sampled and transformed.
+ * @param min Lower bound (inclusive) of the interval.
+ * @param max Upper bound (exclusive) of the interval.
+ * @param n Number of sample points.
+ * @return the result.
+ * @throws IllegalArgumentException if the transform cannot be performed.
+ */
+ default Complex[] apply(DoubleUnaryOperator f,
+ double min,
+ double max,
+ int n) {
+ return apply(TransformUtils.sample(f, min, max, n));
+ }
+}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DctNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java
similarity index 91%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DctNormalization.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java
index cddc688..fa77fae 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DctNormalization.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DctNormalization.java
@@ -14,19 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
/**
* This enumeration defines the various types of normalizations that can be
- * applied to discrete cosine transforms (DCT). The exact definition of these
- * normalizations is detailed below.
- *
- * @see FastCosineTransformer
- * @since 3.0
+ * applied to discrete cosine transforms (DCT).
*/
public enum DctNormalization {
/**
- * Should be passed to the constructor of {@link FastCosineTransformer}
+ * Should be passed to the constructor of {@link FastCosineTransform}
* to use the <em>standard</em> normalization convention. The standard
* DCT-I normalization convention is defined as follows
* <ul>
@@ -45,7 +41,7 @@ public enum DctNormalization {
STANDARD_DCT_I,
/**
- * Should be passed to the constructor of {@link FastCosineTransformer}
+ * Should be passed to the constructor of {@link FastCosineTransform}
* to use the <em>orthogonal</em> normalization convention. The orthogonal
* DCT-I normalization convention is defined as follows
* <ul>
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DftNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java
similarity index 96%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DftNormalization.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java
index 695feb9..1198860 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DftNormalization.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DftNormalization.java
@@ -14,14 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
/**
* This enumeration defines the various types of normalizations that can be
* applied to discrete Fourier transforms (DFT). The exact definition of these
* normalizations is detailed below.
*
- * @see FastFourierTransformer
+ * @see FastFourierTransform
* @since 3.0
*/
public enum DftNormalization {
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DstNormalization.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java
similarity index 90%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DstNormalization.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java
index e8dcab7..4e9ab03 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/DstNormalization.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/DstNormalization.java
@@ -14,19 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
/**
* This enumeration defines the various types of normalizations that can be
- * applied to discrete sine transforms (DST). The exact definition of these
- * normalizations is detailed below.
- *
- * @see FastSineTransformer
- * @since 3.0
+ * applied to discrete sine transforms (DST).
*/
public enum DstNormalization {
/**
- * Should be passed to the constructor of {@link FastSineTransformer} to
+ * Should be passed to the constructor of {@link FastSineTransform} to
* use the <em>standard</em> normalization convention. The standard DST-I
* normalization convention is defined as follows
* <ul>
@@ -40,7 +36,7 @@ public enum DstNormalization {
STANDARD_DST_I,
/**
- * Should be passed to the constructor of {@link FastSineTransformer} to
+ * Should be passed to the constructor of {@link FastSineTransform} to
* use the <em>orthogonal</em> normalization convention. The orthogonal
* DCT-I normalization convention is defined as follows
* <ul>
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
new file mode 100644
index 0000000..0aa2863
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastCosineTransform.java
@@ -0,0 +1,186 @@
+/*
+ * 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.math4.transform;
+
+import java.util.function.UnaryOperator;
+import java.util.function.DoubleUnaryOperator;
+
+import org.apache.commons.numbers.complex.Complex;
+import org.apache.commons.numbers.core.ArithmeticUtils;
+
+/**
+ * Implements the Fast Cosine Transform for transformation of one-dimensional
+ * real data sets. For reference, see James S. Walker, <em>Fast Fourier
+ * Transforms</em>, chapter 3 (ISBN 0849371635).
+ * <p>
+ * There are several variants of the discrete cosine transform. The present
+ * implementation corresponds to DCT-I, with various normalization conventions,
+ * which are specified by the parameter {@link DctNormalization}.
+ * <p>
+ * DCT-I is equivalent to DFT of an <em>even extension</em> of the data series.
+ * More precisely, if x<sub>0</sub>, …, x<sub>N-1</sub> is the data set
+ * to be cosine transformed, the extended data set
+ * x<sub>0</sub><sup>#</sup>, …, x<sub>2N-3</sub><sup>#</sup>
+ * is defined as follows
+ * <ul>
+ * <li>x<sub>k</sub><sup>#</sup> = x<sub>k</sub> if 0 ≤ k < N,</li>
+ * <li>x<sub>k</sub><sup>#</sup> = x<sub>2N-2-k</sub>
+ * if N ≤ k < 2N - 2.</li>
+ * </ul>
+ * <p>
+ * Then, the standard DCT-I y<sub>0</sub>, …, y<sub>N-1</sub> of the real
+ * data set x<sub>0</sub>, …, x<sub>N-1</sub> is equal to <em>half</em>
+ * of the N first elements of the DFT of the extended data set
+ * x<sub>0</sub><sup>#</sup>, …, x<sub>2N-3</sub><sup>#</sup>
+ * <br>
+ * y<sub>n</sub> = (1 / 2) ∑<sub>k=0</sub><sup>2N-3</sup>
+ * x<sub>k</sub><sup>#</sup> exp[-2πi nk / (2N - 2)]
+ * k = 0, …, N-1.
+ * <p>
+ * The present implementation of the discrete cosine transform as a fast cosine
+ * transform requires the length of the data set to be a power of two plus one
+ * (N = 2<sup>n</sup> + 1). Besides, it implicitly assumes
+ * that the sampled function is even.
+ */
+public class FastCosineTransform implements RealTransform {
+ /** Operation to be performed. */
+ private final UnaryOperator<double[]> op;
+
+ /**
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ * @param inverse Whether to perform the inverse transform.
+ */
+ public FastCosineTransform(final DctNormalization normalization,
+ final boolean inverse) {
+ op = create(normalization, inverse);
+ }
+
+ /**
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ */
+ public FastCosineTransform(final DctNormalization normalization) {
+ this(normalization, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two plus one.
+ */
+ @Override
+ public double[] apply(final double[] f) {
+ return op.apply(f);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if the number of sample points is
+ * not a power of two plus one, if the lower bound is greater than or
+ * equal to the upper bound, if the number of sample points is negative.
+ */
+ @Override
+ public double[] apply(final DoubleUnaryOperator f,
+ final double min,
+ final double max,
+ final int n) {
+ return apply(TransformUtils.sample(f, min, max, n));
+ }
+
+ /**
+ * Perform the FCT algorithm (including inverse).
+ *
+ * @param f Data to be transformed.
+ * @return the transformed array.
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two plus one.
+ */
+ private double[] fct(double[] f) {
+ final double[] transformed = new double[f.length];
+
+ final int n = f.length - 1;
+ if (!ArithmeticUtils.isPowerOfTwo(n)) {
+ throw new TransformException(TransformException.NOT_POWER_OF_TWO_PLUS_ONE,
+ Integer.valueOf(f.length));
+ }
+ if (n == 1) { // trivial case
+ transformed[0] = 0.5 * (f[0] + f[1]);
+ transformed[1] = 0.5 * (f[0] - f[1]);
+ return transformed;
+ }
+
+ // construct a new array and perform FFT on it
+ final double[] x = new double[n];
+ x[0] = 0.5 * (f[0] + f[n]);
+ final int nShifted = n >> 1;
+ x[nShifted] = f[nShifted];
+ // temporary variable for transformed[1]
+ double t1 = 0.5 * (f[0] - f[n]);
+ final double piOverN = Math.PI / n;
+ for (int i = 1; i < nShifted; i++) {
+ final int nMi = n - i;
+ final double fi = f[i];
+ final double fnMi = f[nMi];
+ final double a = 0.5 * (fi + fnMi);
+ final double arg = i * piOverN;
+ final double b = Math.sin(arg) * (fi - fnMi);
+ final double c = Math.cos(arg) * (fi - fnMi);
+ x[i] = a - b;
+ x[nMi] = a + b;
+ t1 += c;
+ }
+ final FastFourierTransform transformer = new FastFourierTransform(DftNormalization.STANDARD,
+ false);
+ final Complex[] y = transformer.apply(x);
+
+ // reconstruct the FCT result for the original array
+ transformed[0] = y[0].getReal();
+ transformed[1] = t1;
+ for (int i = 1; i < nShifted; i++) {
+ final int i2 = 2 * i;
+ transformed[i2] = y[i].getReal();
+ transformed[i2 + 1] = transformed[i2 - 1] - y[i].getImaginary();
+ }
+ transformed[n] = y[nShifted].getReal();
+
+ return transformed;
+ }
+
+ /**
+ * Factory method.
+ *
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ * @param inverse Whether to perform the inverse transform.
+ * @return the transform operator.
+ */
+ private UnaryOperator<double[]> create(final DctNormalization normalization,
+ final boolean inverse) {
+ if (inverse) {
+ return normalization == DctNormalization.ORTHOGONAL_DCT_I ?
+ (f) -> TransformUtils.scaleInPlace(fct(f), Math.sqrt(2d / (f.length - 1))) :
+ (f) -> TransformUtils.scaleInPlace(fct(f), 2d / (f.length - 1));
+ } else {
+ return normalization == DctNormalization.ORTHOGONAL_DCT_I ?
+ (f) -> TransformUtils.scaleInPlace(fct(f), Math.sqrt(2d / (f.length - 1))) :
+ (f) -> fct(f);
+ }
+ }
+}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
new file mode 100644
index 0000000..be704af
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastFourierTransform.java
@@ -0,0 +1,397 @@
+/*
+ * 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.math4.transform;
+
+import java.util.Arrays;
+import java.util.function.DoubleUnaryOperator;
+
+import org.apache.commons.numbers.core.ArithmeticUtils;
+import org.apache.commons.numbers.complex.Complex;
+
+/**
+ * Implements the Fast Fourier Transform for transformation of one-dimensional
+ * real or complex data sets. For reference, see <em>Applied Numerical Linear
+ * Algebra</em>, ISBN 0898713897, chapter 6.
+ * <p>
+ * There are several variants of the discrete Fourier transform, with various
+ * normalization conventions, which are specified by the parameter
+ * {@link DftNormalization}.
+ * <p>
+ * The current implementation of the discrete Fourier transform as a fast
+ * Fourier transform requires the length of the data set to be a power of 2.
+ * This greatly simplifies and speeds up the code. Users can pad the data with
+ * zeros to meet this requirement. There are other flavors of FFT, for
+ * reference, see S. Winograd,
+ * <i>On computing the discrete Fourier transform</i>, Mathematics of
+ * Computation, 32 (1978), 175 - 199.
+ *
+ * @see DftNormalization
+ */
+public class FastFourierTransform implements ComplexTransform {
+ /**
+ * {@code W_SUB_N_R[i]} is the real part of
+ * {@code exp(- 2 * i * pi / n)}:
+ * {@code W_SUB_N_R[i] = cos(2 * pi/ n)}, where {@code n = 2^i}.
+ */
+ private static final double[] W_SUB_N_R = {
+ 0x1.0p0, -0x1.0p0, 0x1.1a62633145c07p-54, 0x1.6a09e667f3bcdp-1,
+ 0x1.d906bcf328d46p-1, 0x1.f6297cff75cbp-1, 0x1.fd88da3d12526p-1, 0x1.ff621e3796d7ep-1,
+ 0x1.ffd886084cd0dp-1, 0x1.fff62169b92dbp-1, 0x1.fffd8858e8a92p-1, 0x1.ffff621621d02p-1,
+ 0x1.ffffd88586ee6p-1, 0x1.fffff62161a34p-1, 0x1.fffffd8858675p-1, 0x1.ffffff621619cp-1,
+ 0x1.ffffffd885867p-1, 0x1.fffffff62161ap-1, 0x1.fffffffd88586p-1, 0x1.ffffffff62162p-1,
+ 0x1.ffffffffd8858p-1, 0x1.fffffffff6216p-1, 0x1.fffffffffd886p-1, 0x1.ffffffffff621p-1,
+ 0x1.ffffffffffd88p-1, 0x1.fffffffffff62p-1, 0x1.fffffffffffd9p-1, 0x1.ffffffffffff6p-1,
+ 0x1.ffffffffffffep-1, 0x1.fffffffffffffp-1, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0, 0x1.0p0,
+ 0x1.0p0, 0x1.0p0, 0x1.0p0 };
+
+ /**
+ * {@code W_SUB_N_I[i]} is the imaginary part of
+ * {@code exp(- 2 * i * pi / n)}:
+ * {@code W_SUB_N_I[i] = -sin(2 * pi/ n)}, where {@code n = 2^i}.
+ */
+ private static final double[] W_SUB_N_I = {
+ 0x1.1a62633145c07p-52, -0x1.1a62633145c07p-53, -0x1.0p0, -0x1.6a09e667f3bccp-1,
+ -0x1.87de2a6aea963p-2, -0x1.8f8b83c69a60ap-3, -0x1.917a6bc29b42cp-4, -0x1.91f65f10dd814p-5,
+ -0x1.92155f7a3667ep-6, -0x1.921d1fcdec784p-7, -0x1.921f0fe670071p-8, -0x1.921f8becca4bap-9,
+ -0x1.921faaee6472dp-10, -0x1.921fb2aecb36p-11, -0x1.921fb49ee4ea6p-12, -0x1.921fb51aeb57bp-13,
+ -0x1.921fb539ecf31p-14, -0x1.921fb541ad59ep-15, -0x1.921fb5439d73ap-16, -0x1.921fb544197ap-17,
+ -0x1.921fb544387bap-18, -0x1.921fb544403c1p-19, -0x1.921fb544422c2p-20, -0x1.921fb54442a83p-21,
+ -0x1.921fb54442c73p-22, -0x1.921fb54442cefp-23, -0x1.921fb54442d0ep-24, -0x1.921fb54442d15p-25,
+ -0x1.921fb54442d17p-26, -0x1.921fb54442d18p-27, -0x1.921fb54442d18p-28, -0x1.921fb54442d18p-29,
+ -0x1.921fb54442d18p-30, -0x1.921fb54442d18p-31, -0x1.921fb54442d18p-32, -0x1.921fb54442d18p-33,
+ -0x1.921fb54442d18p-34, -0x1.921fb54442d18p-35, -0x1.921fb54442d18p-36, -0x1.921fb54442d18p-37,
+ -0x1.921fb54442d18p-38, -0x1.921fb54442d18p-39, -0x1.921fb54442d18p-40, -0x1.921fb54442d18p-41,
+ -0x1.921fb54442d18p-42, -0x1.921fb54442d18p-43, -0x1.921fb54442d18p-44, -0x1.921fb54442d18p-45,
+ -0x1.921fb54442d18p-46, -0x1.921fb54442d18p-47, -0x1.921fb54442d18p-48, -0x1.921fb54442d18p-49,
+ -0x1.921fb54442d18p-50, -0x1.921fb54442d18p-51, -0x1.921fb54442d18p-52, -0x1.921fb54442d18p-53,
+ -0x1.921fb54442d18p-54, -0x1.921fb54442d18p-55, -0x1.921fb54442d18p-56, -0x1.921fb54442d18p-57,
+ -0x1.921fb54442d18p-58, -0x1.921fb54442d18p-59, -0x1.921fb54442d18p-60 };
+
+ /** Type of DFT. */
+ private final DftNormalization normalization;
+ /** Inverse or forward. */
+ private final boolean inverse;
+
+ /**
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ * @param inverse Whether to perform the inverse transform.
+ */
+ public FastFourierTransform(final DftNormalization normalization,
+ final boolean inverse) {
+ this.normalization = normalization;
+ this.inverse = inverse;
+ }
+
+ /**
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ */
+ public FastFourierTransform(final DftNormalization normalization) {
+ this(normalization, false);
+ }
+
+ /**
+ * Computes the standard transform of the data.
+ * Computation is done in place.
+ * Assumed layout of the input data:
+ * <ul>
+ * <li>{@code dataRI[0][i]}: Real part of the {@code i}-th data point,</li>
+ * <li>{@code dataRI[1][i]}: Imaginary part of the {@code i}-th data point.</li>
+ * </ul>
+ *
+ * @param dataRI Two-dimensional array of real and imaginary parts of the data.
+ * @throws IllegalArgumentException if the number of data points is not
+ * a power of two, if the number of rows of the specified array is not two,
+ * or the array is not rectangular.
+ */
+ public void transformInPlace(final double[][] dataRI) {
+ if (dataRI.length != 2) {
+ throw new TransformException(TransformException.SIZE_MISMATCH,
+ dataRI.length, 2);
+ }
+ final double[] dataR = dataRI[0];
+ final double[] dataI = dataRI[1];
+ if (dataR.length != dataI.length) {
+ throw new TransformException(TransformException.SIZE_MISMATCH,
+ dataI.length, dataR.length);
+ }
+
+ final int n = dataR.length;
+ if (!ArithmeticUtils.isPowerOfTwo(n)) {
+ throw new TransformException(TransformException.NOT_POWER_OF_TWO,
+ Integer.valueOf(n));
+ }
+
+ if (n == 1) {
+ return;
+ } else if (n == 2) {
+ final double srcR0 = dataR[0];
+ final double srcI0 = dataI[0];
+ final double srcR1 = dataR[1];
+ final double srcI1 = dataI[1];
+
+ // X_0 = x_0 + x_1
+ dataR[0] = srcR0 + srcR1;
+ dataI[0] = srcI0 + srcI1;
+ // X_1 = x_0 - x_1
+ dataR[1] = srcR0 - srcR1;
+ dataI[1] = srcI0 - srcI1;
+
+ normalizeTransformedData(dataRI);
+ return;
+ }
+
+ bitReversalShuffle2(dataR, dataI);
+
+ // Do 4-term DFT.
+ if (inverse) {
+ for (int i0 = 0; i0 < n; i0 += 4) {
+ final int i1 = i0 + 1;
+ final int i2 = i0 + 2;
+ final int i3 = i0 + 3;
+
+ final double srcR0 = dataR[i0];
+ final double srcI0 = dataI[i0];
+ final double srcR1 = dataR[i2];
+ final double srcI1 = dataI[i2];
+ final double srcR2 = dataR[i1];
+ final double srcI2 = dataI[i1];
+ final double srcR3 = dataR[i3];
+ final double srcI3 = dataI[i3];
+
+ // 4-term DFT
+ // X_0 = x_0 + x_1 + x_2 + x_3
+ dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
+ dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
+ // X_1 = x_0 - x_2 + j * (x_3 - x_1)
+ dataR[i1] = srcR0 - srcR2 + (srcI3 - srcI1);
+ dataI[i1] = srcI0 - srcI2 + (srcR1 - srcR3);
+ // X_2 = x_0 - x_1 + x_2 - x_3
+ dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
+ dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
+ // X_3 = x_0 - x_2 + j * (x_1 - x_3)
+ dataR[i3] = srcR0 - srcR2 + (srcI1 - srcI3);
+ dataI[i3] = srcI0 - srcI2 + (srcR3 - srcR1);
+ }
+ } else {
+ for (int i0 = 0; i0 < n; i0 += 4) {
+ final int i1 = i0 + 1;
+ final int i2 = i0 + 2;
+ final int i3 = i0 + 3;
+
+ final double srcR0 = dataR[i0];
+ final double srcI0 = dataI[i0];
+ final double srcR1 = dataR[i2];
+ final double srcI1 = dataI[i2];
+ final double srcR2 = dataR[i1];
+ final double srcI2 = dataI[i1];
+ final double srcR3 = dataR[i3];
+ final double srcI3 = dataI[i3];
+
+ // 4-term DFT
+ // X_0 = x_0 + x_1 + x_2 + x_3
+ dataR[i0] = srcR0 + srcR1 + srcR2 + srcR3;
+ dataI[i0] = srcI0 + srcI1 + srcI2 + srcI3;
+ // X_1 = x_0 - x_2 + j * (x_3 - x_1)
+ dataR[i1] = srcR0 - srcR2 + (srcI1 - srcI3);
+ dataI[i1] = srcI0 - srcI2 + (srcR3 - srcR1);
+ // X_2 = x_0 - x_1 + x_2 - x_3
+ dataR[i2] = srcR0 - srcR1 + srcR2 - srcR3;
+ dataI[i2] = srcI0 - srcI1 + srcI2 - srcI3;
+ // X_3 = x_0 - x_2 + j * (x_1 - x_3)
+ dataR[i3] = srcR0 - srcR2 + (srcI3 - srcI1);
+ dataI[i3] = srcI0 - srcI2 + (srcR1 - srcR3);
+ }
+ }
+
+ int lastN0 = 4;
+ int lastLogN0 = 2;
+ while (lastN0 < n) {
+ int n0 = lastN0 << 1;
+ int logN0 = lastLogN0 + 1;
+ double wSubN0R = W_SUB_N_R[logN0];
+ double wSubN0I = W_SUB_N_I[logN0];
+ if (inverse) {
+ wSubN0I = -wSubN0I;
+ }
+
+ // Combine even/odd transforms of size lastN0 into a transform of size N0 (lastN0 * 2).
+ for (int destEvenStartIndex = 0;
+ destEvenStartIndex < n;
+ destEvenStartIndex += n0) {
+ final int destOddStartIndex = destEvenStartIndex + lastN0;
+
+ double wSubN0ToRR = 1;
+ double wSubN0ToRI = 0;
+
+ for (int r = 0; r < lastN0; r++) {
+ final int destEvenStartIndexPlusR = destEvenStartIndex + r;
+ final int destOddStartIndexPlusR = destOddStartIndex + r;
+
+ final double grR = dataR[destEvenStartIndexPlusR];
+ final double grI = dataI[destEvenStartIndexPlusR];
+ final double hrR = dataR[destOddStartIndexPlusR];
+ final double hrI = dataI[destOddStartIndexPlusR];
+
+ // dest[destEvenStartIndex + r] = Gr + WsubN0ToR * Hr
+ dataR[destEvenStartIndexPlusR] = grR + wSubN0ToRR * hrR - wSubN0ToRI * hrI;
+ dataI[destEvenStartIndexPlusR] = grI + wSubN0ToRR * hrI + wSubN0ToRI * hrR;
+ // dest[destOddStartIndex + r] = Gr - WsubN0ToR * Hr
+ dataR[destOddStartIndexPlusR] = grR - (wSubN0ToRR * hrR - wSubN0ToRI * hrI);
+ dataI[destOddStartIndexPlusR] = grI - (wSubN0ToRR * hrI + wSubN0ToRI * hrR);
+
+ // WsubN0ToR *= WsubN0R
+ final double nextWsubN0ToRR = wSubN0ToRR * wSubN0R - wSubN0ToRI * wSubN0I;
+ final double nextWsubN0ToRI = wSubN0ToRR * wSubN0I + wSubN0ToRI * wSubN0R;
+ wSubN0ToRR = nextWsubN0ToRR;
+ wSubN0ToRI = nextWsubN0ToRI;
+ }
+ }
+
+ lastN0 = n0;
+ lastLogN0 = logN0;
+ }
+
+ normalizeTransformedData(dataRI);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if the length of the data array is not a power of two.
+ */
+ public Complex[] apply(final double[] f) {
+ final double[][] dataRI = new double[][] {
+ Arrays.copyOf(f, f.length),
+ new double[f.length]
+ };
+ transformInPlace(dataRI);
+ return TransformUtils.createComplex(dataRI);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if the number of sample points
+ * {@code n} is not a power of two, if the lower bound is greater than,
+ * or equal to the upper bound, if the number of sample points {@code n}
+ * is negative
+ */
+ @Override
+ public Complex[] apply(final DoubleUnaryOperator f,
+ final double min,
+ final double max,
+ final int n) {
+ return apply(TransformUtils.sample(f, min, max, n));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two.
+ */
+ @Override
+ public Complex[] apply(final Complex[] f) {
+ final double[][] dataRI = TransformUtils.createRealImaginary(f);
+ transformInPlace(dataRI);
+ return TransformUtils.createComplex(dataRI);
+ }
+
+ /**
+ * Applies normalization to the transformed data.
+ *
+ * @param dataRI Unscaled transformed data.
+ */
+ private void normalizeTransformedData(final double[][] dataRI) {
+ final double[] dataR = dataRI[0];
+ final double[] dataI = dataRI[1];
+ final int n = dataR.length;
+
+ switch (normalization) {
+ case STANDARD:
+ if (inverse) {
+ final double scaleFactor = 1d / n;
+ for (int i = 0; i < n; i++) {
+ dataR[i] *= scaleFactor;
+ dataI[i] *= scaleFactor;
+ }
+ }
+
+ break;
+
+ case UNITARY:
+ final double scaleFactor = 1d / Math.sqrt(n);
+ for (int i = 0; i < n; i++) {
+ dataR[i] *= scaleFactor;
+ dataI[i] *= scaleFactor;
+ }
+
+ break;
+
+ default:
+ throw new IllegalStateException(); // Should never happen.
+ }
+ }
+
+ /**
+ * Performs identical index bit reversal shuffles on two arrays of
+ * identical size.
+ * Each element in the array is swapped with another element based
+ * on the bit-reversal of the index.
+ * For example, in an array with length 16, item at binary index 0011
+ * (decimal 3) would be swapped with the item at binary index 1100
+ * (decimal 12).
+ *
+ * @param a Array to be shuffled.
+ * @param b Array to be shuffled.
+ */
+ private static void bitReversalShuffle2(double[] a,
+ double[] b) {
+ final int n = a.length;
+ final int halfOfN = n >> 1;
+
+ int j = 0;
+ for (int i = 0; i < n; i++) {
+ if (i < j) {
+ // swap indices i & j
+ double temp = a[i];
+ a[i] = a[j];
+ a[j] = temp;
+
+ temp = b[i];
+ b[i] = b[j];
+ b[j] = temp;
+ }
+
+ int k = halfOfN;
+ while (k <= j && k > 0) {
+ j -= k;
+ k >>= 1;
+ }
+ j += k;
+ }
+ }
+}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformer.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastHadamardTransform.java
similarity index 67%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformer.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastHadamardTransform.java
index 90a3aa8..ab37285 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformer.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastHadamardTransform.java
@@ -14,80 +14,66 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
-import java.io.Serializable;
+import java.util.function.UnaryOperator;
-import org.apache.commons.math4.legacy.analysis.FunctionUtils;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
import org.apache.commons.numbers.core.ArithmeticUtils;
/**
- * Implements the <a href="http://www.archive.chipcenter.com/dsp/DSP000517F1.html">Fast Hadamard Transform</a> (FHT).
- * Transformation of an input vector x to the output vector y.
+ * <a href="http://www.archive.chipcenter.com/dsp/DSP000517F1.html">Fast Hadamard Transform</a> (FHT).
* <p>
- * In addition to transformation of real vectors, the Hadamard transform can
- * transform integer vectors into integer vectors. However, this integer transform
- * cannot be inverted directly. Due to a scaling factor it may lead to rational results.
- * As an example, the inverse transform of integer vector (0, 1, 0, 1) is rational
- * vector (1/2, -1/2, 0, 0).
- *
- * @since 2.0
+ * The FHT can also transform integer vectors into integer vectors.
+ * However, this transform cannot be inverted directly, due to a scaling
+ * factor that may lead to rational results (for example, the inverse
+ * transform of integer vector (0, 1, 0, 1) is vector (1/2, -1/2, 0, 0).
*/
-public class FastHadamardTransformer implements RealTransformer, Serializable {
+public class FastHadamardTransform implements RealTransform {
+ /** Operation to be performed. */
+ private final UnaryOperator<double[]> op;
- /** Serializable version identifier. */
- static final long serialVersionUID = 20120211L;
+ /**
+ * Default constructor.
+ */
+ public FastHadamardTransform() {
+ this(false);
+ }
/**
- * {@inheritDoc}
- *
- * @throws MathIllegalArgumentException if the length of the data array is
- * not a power of two
+ * @param inverse Whether to perform the inverse transform.
*/
- @Override
- public double[] transform(final double[] f, final TransformType type) {
- if (type == TransformType.FORWARD) {
- return fht(f);
- }
- return TransformUtils.scaleArray(fht(f), 1.0 / f.length);
+ public FastHadamardTransform(final boolean inverse) {
+ op = create(inverse);
}
/**
* {@inheritDoc}
*
- * @throws org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException
- * if the lower bound is greater than, or equal to the upper bound
- * @throws org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException
- * if the number of sample points is negative
- * @throws MathIllegalArgumentException if the number of sample points is not a power of two
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two.
*/
@Override
- public double[] transform(final UnivariateFunction f,
- final double min, final double max, final int n,
- final TransformType type) {
-
- return transform(FunctionUtils.sample(f, min, max, n), type);
+ public double[] apply(final double[] f) {
+ return op.apply(f);
}
/**
- * Returns the forward transform of the specified integer data set.The
- * integer transform cannot be inverted directly, due to a scaling factor
- * which may lead to double results.
+ * Returns the forward transform of the given data set.
+ * The integer transform cannot be inverted directly, due to a scaling
+ * factor which may lead to double results.
*
- * @param f the integer data array to be transformed (signal)
- * @return the integer transformed array (spectrum)
- * @throws MathIllegalArgumentException if the length of the data array is not a power of two
+ * @param f Data array to be transformed (signal).
+ * @return the transformed array (spectrum).
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two.
*/
- public int[] transform(final int[] f) {
+ public int[] apply(final int[] f) {
return fht(f);
}
/**
- * The FHT (Fast Hadamard Transformation) which uses only subtraction and
- * addition. Requires {@code N * log2(N) = n * 2^n} additions.
+ * FHT uses only subtraction and addition.
+ * It requires {@code N * log2(N) = n * 2^n} additions.
*
* <h3>Short Table of manual calculation for N=8</h3>
* <ol>
@@ -180,7 +166,7 @@ public class FastHadamardTransformer implements RealTransformer, Serializable {
* of the previous column.</li>
* </ul>
* </li>
- * <li>The consputation of {@code D_top} and {@code D_bottom} are best
+ * <li>The computation of {@code D_top} and {@code D_bottom} are best
* understood with the above example (for {@code N = 8}).
* <li>The output vector {@code y} is now in the last column of
* {@code hadm}.</li>
@@ -223,25 +209,22 @@ public class FastHadamardTransformer implements RealTransformer, Serializable {
* </tbody>
* </table>
*
- * @param x the real data array to be transformed
- * @return the real transformed array, {@code y}
- * @throws MathIllegalArgumentException if the length of the data array is not a power of two
+ * @param x Data to be transformed.
+ * @return the transformed array.
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two.
*/
- protected double[] fht(double[] x) throws MathIllegalArgumentException {
-
- final int n = x.length;
+ private double[] fht(double[] x) {
+ final int n = x.length;
final int halfN = n / 2;
if (!ArithmeticUtils.isPowerOfTwo(n)) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO,
- Integer.valueOf(n));
+ throw new TransformException(TransformException.NOT_POWER_OF_TWO,
+ n);
}
- /*
- * Instead of creating a matrix with p+1 columns and n rows, we use two
- * one dimension arrays which we are used in an alternating way.
- */
+ // Instead of creating a matrix with p+1 columns and n rows, we use two
+ // one dimension arrays which we are used in an alternating way.
double[] yPrevious = new double[n];
double[] yCurrent = x.clone();
@@ -267,38 +250,34 @@ public class FastHadamardTransformer implements RealTransformer, Serializable {
}
return yCurrent;
-
}
/**
- * Returns the forward transform of the specified integer data set. The FHT
- * (Fast Hadamard Transform) uses only subtraction and addition.
+ * Returns the forward transform of the specified integer data set.
+ * FHT only uses subtraction and addition.
*
- * @param x the integer data array to be transformed
- * @return the integer transformed array, {@code y}
- * @throws MathIllegalArgumentException if the length of the data array is not a power of two
+ * @param x Data to be transformed.
+ * @return the transformed array.
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two.
*/
- protected int[] fht(int[] x) throws MathIllegalArgumentException {
-
- final int n = x.length;
+ private int[] fht(int[] x) {
+ final int n = x.length;
final int halfN = n / 2;
if (!ArithmeticUtils.isPowerOfTwo(n)) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO,
- Integer.valueOf(n));
+ throw new TransformException(TransformException.NOT_POWER_OF_TWO,
+ n);
}
- /*
- * Instead of creating a matrix with p+1 columns and n rows, we use two
- * one dimension arrays which we are used in an alternating way.
- */
+ // Instead of creating a matrix with p+1 columns and n rows, we use two
+ // one dimension arrays which we are used in an alternating way.
+
int[] yPrevious = new int[n];
int[] yCurrent = x.clone();
// iterate from left to right (column)
for (int j = 1; j < n; j <<= 1) {
-
// switch columns
final int[] yTmp = yCurrent;
yCurrent = yPrevious;
@@ -319,7 +298,19 @@ public class FastHadamardTransformer implements RealTransformer, Serializable {
// return the last computed output vector y
return yCurrent;
-
}
+ /**
+ * Factory method.
+ *
+ * @param inverse Whether to perform the inverse transform.
+ * @return the transform operator.
+ */
+ private UnaryOperator<double[]> create(final boolean inverse) {
+ if (inverse) {
+ return (f) -> TransformUtils.scaleInPlace(fht(f), 1d / f.length);
+ } else {
+ return (f) -> fht(f);
+ }
+ }
}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
new file mode 100644
index 0000000..da3c63b
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/FastSineTransform.java
@@ -0,0 +1,194 @@
+/*
+ * 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.math4.transform;
+
+import java.util.function.UnaryOperator;
+import java.util.function.DoubleUnaryOperator;
+
+import org.apache.commons.numbers.complex.Complex;
+import org.apache.commons.numbers.core.ArithmeticUtils;
+
+/**
+ * Implements the Fast Sine Transform for transformation of one-dimensional real
+ * data sets. For reference, see James S. Walker, <em>Fast Fourier
+ * Transforms</em>, chapter 3 (ISBN 0849371635).
+ * <p>
+ * There are several variants of the discrete sine transform. The present
+ * implementation corresponds to DST-I, with various normalization conventions,
+ * which are specified by the parameter {@link DstNormalization}.
+ * <strong>It should be noted that regardless to the convention, the first
+ * element of the dataset to be transformed must be zero.</strong>
+ * <p>
+ * DST-I is equivalent to DFT of an <em>odd extension</em> of the data series.
+ * More precisely, if x<sub>0</sub>, …, x<sub>N-1</sub> is the data set
+ * to be sine transformed, the extended data set x<sub>0</sub><sup>#</sup>,
+ * …, x<sub>2N-1</sub><sup>#</sup> is defined as follows
+ * <ul>
+ * <li>x<sub>0</sub><sup>#</sup> = x<sub>0</sub> = 0,</li>
+ * <li>x<sub>k</sub><sup>#</sup> = x<sub>k</sub> if 1 ≤ k < N,</li>
+ * <li>x<sub>N</sub><sup>#</sup> = 0,</li>
+ * <li>x<sub>k</sub><sup>#</sup> = -x<sub>2N-k</sub> if N + 1 ≤ k <
+ * 2N.</li>
+ * </ul>
+ * <p>
+ * Then, the standard DST-I y<sub>0</sub>, …, y<sub>N-1</sub> of the real
+ * data set x<sub>0</sub>, …, x<sub>N-1</sub> is equal to <em>half</em>
+ * of i (the pure imaginary number) times the N first elements of the DFT of the
+ * extended data set x<sub>0</sub><sup>#</sup>, …,
+ * x<sub>2N-1</sub><sup>#</sup> <br>
+ * y<sub>n</sub> = (i / 2) ∑<sub>k=0</sub><sup>2N-1</sup>
+ * x<sub>k</sub><sup>#</sup> exp[-2πi nk / (2N)]
+ * k = 0, …, N-1.
+ * <p>
+ * The present implementation of the discrete sine transform as a fast sine
+ * transform requires the length of the data to be a power of two. Besides,
+ * it implicitly assumes that the sampled function is odd. In particular, the
+ * first element of the data set must be 0, which is enforced in
+ * {@link #apply(DoubleUnaryOperator, double, double, int)},
+ * after sampling.
+ */
+public class FastSineTransform implements RealTransform {
+ /** Operation to be performed. */
+ private final UnaryOperator<double[]> op;
+
+ /**
+ * @param normalization Normalization to be applied to the transformed data.
+ * @param inverse Whether to perform the inverse transform.
+ */
+ public FastSineTransform(final DstNormalization normalization,
+ final boolean inverse) {
+ op = create(normalization, inverse);
+ }
+
+ /**
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ */
+ public FastSineTransform(final DstNormalization normalization) {
+ this(normalization, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * The first element of the specified data set is required to be {@code 0}.
+ *
+ * @throws MathIllegalArgumentException if the length of the data array is
+ * not a power of two, or the first element of the data array is not zero.
+ */
+ @Override
+ public double[] apply(final double[] f) {
+ return op.apply(f);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * The implementation enforces {@code f(x) = 0} at {@code x = 0}.
+ *
+ * @throws IllegalArgumentException if the number of sample points is not a
+ * power of two, if the lower bound is greater than, or equal to the upper bound,
+ * if the number of sample points is negative.
+ */
+ @Override
+ public double[] apply(final DoubleUnaryOperator f,
+ final double min,
+ final double max,
+ final int n) {
+ final double[] data = TransformUtils.sample(f, min, max, n);
+ data[0] = 0;
+ return apply(data);
+ }
+
+ /**
+ * Perform the FST algorithm (including inverse).
+ * The first element of the data set is required to be {@code 0}.
+ *
+ * @param f Data array to be transformed.
+ * @return the transformed array.
+ * @throws IllegalArgumentException if the length of the data array is
+ * not a power of two, or the first element of the data array is not zero.
+ */
+ private double[] fst(double[] f) {
+ if (!ArithmeticUtils.isPowerOfTwo(f.length)) {
+ throw new TransformException(TransformException.NOT_POWER_OF_TWO,
+ f.length);
+ }
+ if (f[0] != 0) {
+ throw new TransformException(TransformException.FIRST_ELEMENT_NOT_ZERO,
+ f[0]);
+ }
+
+ final double[] transformed = new double[f.length];
+ final int n = f.length;
+ if (n == 1) {
+ transformed[0] = 0;
+ return transformed;
+ }
+
+ // construct a new array and perform FFT on it
+ final double[] x = new double[n];
+ x[0] = 0;
+ final int nShifted = n >> 1;
+ x[nShifted] = 2 * f[nShifted];
+ final double piOverN = Math.PI / n;
+ for (int i = 1; i < nShifted; i++) {
+ final int nMi = n - i;
+ final double fi = f[i];
+ final double fnMi = f[nMi];
+ final double a = Math.sin(i * piOverN) * (fi + fnMi);
+ final double b = 0.5 * (fi - fnMi);
+ x[i] = a + b;
+ x[nMi] = a - b;
+ }
+
+ final FastFourierTransform transform = new FastFourierTransform(DftNormalization.STANDARD);
+ final Complex[] y = transform.apply(x);
+
+ // reconstruct the FST result for the original array
+ transformed[0] = 0;
+ transformed[1] = 0.5 * y[0].getReal();
+ for (int i = 1; i < nShifted; i++) {
+ final int i2 = 2 * i;
+ transformed[i2] = -y[i].getImaginary();
+ transformed[i2 + 1] = y[i].getReal() + transformed[i2 - 1];
+ }
+
+ return transformed;
+ }
+
+ /**
+ * Factory method.
+ *
+ * @param normalization Normalization to be applied to the
+ * transformed data.
+ * @param inverse Whether to perform the inverse transform.
+ * @return the transform operator.
+ */
+ private UnaryOperator<double[]> create(final DstNormalization normalization,
+ final boolean inverse) {
+ if (inverse) {
+ return normalization == DstNormalization.ORTHOGONAL_DST_I ?
+ (f) -> TransformUtils.scaleInPlace(fst(f), Math.sqrt(2d / f.length)) :
+ (f) -> TransformUtils.scaleInPlace(fst(f), 2d / f.length);
+ } else {
+ return normalization == DstNormalization.ORTHOGONAL_DST_I ?
+ (f) -> TransformUtils.scaleInPlace(fst(f), Math.sqrt(2d / f.length)) :
+ (f) -> fst(f);
+ }
+ }
+}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/RealTransform.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/RealTransform.java
new file mode 100644
index 0000000..8f8f6af
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/RealTransform.java
@@ -0,0 +1,51 @@
+/*
+ * 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.math4.transform;
+
+import java.util.function.DoubleUnaryOperator;
+import java.util.function.UnaryOperator;
+
+/**
+ * Real transforms.
+ */
+public interface RealTransform extends UnaryOperator<double[]> {
+ /**
+ * Returns the transform of the specified data set.
+ *
+ * @param f the data array to be transformed (signal).
+ * @return the transformed array (spectrum).
+ * @throws IllegalArgumentException if the transform cannot be performed.
+ */
+ double[] apply(double[] f);
+
+ /**
+ * Returns the transform of the specified function.
+ *
+ * @param f Function to be sampled and transformed.
+ * @param min Lower bound (inclusive) of the interval.
+ * @param max Upper bound (exclusive) of the interval.
+ * @param n Number of sample points.
+ * @return the result.
+ * @throws IllegalArgumentException if the transform cannot be performed.
+ */
+ default double[] apply(DoubleUnaryOperator f,
+ double min,
+ double max,
+ int n) {
+ return apply(TransformUtils.sample(f, min, max, n));
+ }
+}
diff --git a/commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformException.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformException.java
new file mode 100644
index 0000000..0c298ee
--- /dev/null
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformException.java
@@ -0,0 +1,52 @@
+/*
+ * 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.math4.transform;
+
+import java.text.MessageFormat;
+
+/**
+ * Exception class with constants for frequently used messages.
+ * Class is package-private (for internal use only).
+ */
+class TransformException extends IllegalArgumentException {
+ /** Error message for "out of range" condition. */
+ public static final String FIRST_ELEMENT_NOT_ZERO = "First element ({0}) must be 0";
+ /** Error message for "not strictly positive" condition. */
+ public static final String NOT_STRICTLY_POSITIVE = "Number {0} is not strictly positive";
+ /** Error message for "too large" condition. */
+ public static final String TOO_LARGE = "Number {0} is larger than {1}";
+ /** Error message for "size mismatch" condition. */
+ public static final String SIZE_MISMATCH = "Size mismatch: {0} != {1}";
+ /** Error message for "pow(2, n) + 1". */
+ public static final String NOT_POWER_OF_TWO_PLUS_ONE = "{0} is not equal to 1 + pow(2, n), for some n";
+ /** Error message for "pow(2, n)". */
+ public static final String NOT_POWER_OF_TWO = "{0} is not equal to pow(2, n), for some n";
+
+ /** Serializable version identifier. */
+ private static final long serialVersionUID = 20210522L;
+
+ /**
+ * Create an exception where the message is constructed by applying
+ * the {@code format()} method from {@code java.text.MessageFormat}.
+ *
+ * @param message Message format (with replaceable parameters).
+ * @param formatArguments Actual arguments to be displayed in the message.
+ */
+ public TransformException(String message, Object... formatArguments) {
+ super(MessageFormat.format(message, formatArguments));
+ }
+}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformUtils.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformUtils.java
similarity index 52%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformUtils.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformUtils.java
index 09d4e8a..bf1fa5e 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/TransformUtils.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/TransformUtils.java
@@ -14,50 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
import java.util.Arrays;
+import java.util.function.DoubleUnaryOperator;
import org.apache.commons.numbers.complex.Complex;
-import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
/**
* Useful functions for the implementation of various transforms.
- *
- * @since 3.0
+ * Class is package-private (for internal use only).
*/
-public class TransformUtils {
- /**
- * Table of the powers of 2 to facilitate binary search lookup.
- *
- * @see #exactLog2(int)
- */
- private static final int[] POWERS_OF_TWO = {
- 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020,
- 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800,
- 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000,
- 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000,
- 0x40000000
- };
-
- /** Private constructor. */
- private TransformUtils() {
- super();
- }
+class TransformUtils {
+ /** Utility class. */
+ private TransformUtils() {}
/**
* Multiply every component in the given real array by the
* given real number. The change is made in place.
*
- * @param f the real array to be scaled
- * @param d the real scaling coefficient
- * @return a reference to the scaled array
+ * @param f Array to be scaled.
+ * @param d Scaling coefficient.
+ * @return a reference to the scaled array.
*/
- public static double[] scaleArray(double[] f, double d) {
-
+ static double[] scaleInPlace(double[] f, double d) {
for (int i = 0; i < f.length; i++) {
f[i] *= d;
}
@@ -68,12 +48,11 @@ public class TransformUtils {
* Multiply every component in the given complex array by the
* given real number. The change is made in place.
*
- * @param f the complex array to be scaled
- * @param d the real scaling coefficient
- * @return a reference to the scaled array
+ * @param f Array to be scaled.
+ * @param d Scaling coefficient.
+ * @return the scaled array.
*/
- public static Complex[] scaleArray(Complex[] f, double d) {
-
+ static Complex[] scaleInPlace(Complex[] f, double d) {
for (int i = 0; i < f.length; i++) {
f[i] = Complex.ofCartesian(d * f[i].getReal(), d * f[i].getImaginary());
}
@@ -90,11 +69,11 @@ public class TransformUtils {
* <li>{@code dataRI[1][i] = dataC[i].getImaginary()}.</li>
* </ul>
*
- * @param dataC the array of {@link Complex} data to be transformed
+ * @param dataC Array of {@link Complex} data to be transformed.
* @return a two dimensional array filled with the real and imaginary parts
- * of the specified complex input
+ * of the specified complex input.
*/
- public static double[][] createRealImaginaryArray(final Complex[] dataC) {
+ static double[][] createRealImaginary(final Complex[] dataC) {
final double[][] dataRI = new double[2][dataC.length];
final double[] dataR = dataRI[0];
final double[] dataI = dataRI[1];
@@ -115,21 +94,21 @@ public class TransformUtils {
* <li>{@code dataC[i].getImaginary() = dataRI[1][i]}.</li>
* </ul>
*
- * @param dataRI the array of real and imaginary parts to be transformed
- * @return an array of {@link Complex} with specified real and imaginary parts.
- * @throws DimensionMismatchException if the number of rows of the specified
- * array is not two, or the array is not rectangular
+ * @param dataRI Array of real and imaginary parts to be transformed.
+ * @return a {@link Complex} array.
+ * @throws IllegalArgumentException if the number of rows of the specified
+ * array is not two, or the array is not rectangular.
*/
- public static Complex[] createComplexArray(final double[][] dataRI)
- throws DimensionMismatchException{
-
+ static Complex[] createComplex(final double[][] dataRI) {
if (dataRI.length != 2) {
- throw new DimensionMismatchException(dataRI.length, 2);
+ throw new TransformException(TransformException.SIZE_MISMATCH,
+ dataRI.length, 2);
}
final double[] dataR = dataRI[0];
final double[] dataI = dataRI[1];
if (dataR.length != dataI.length) {
- throw new DimensionMismatchException(dataI.length, dataR.length);
+ throw new TransformException(TransformException.SIZE_MISMATCH,
+ dataI.length, dataR.length);
}
final int n = dataR.length;
@@ -140,24 +119,39 @@ public class TransformUtils {
return c;
}
-
/**
- * Returns the base-2 logarithm of the specified {@code int}. Throws an
- * exception if {@code n} is not a power of two.
+ * Samples the specified univariate real function on the specified interval.
+ * <p>
+ * The interval is divided equally into {@code n} sections and sample points
+ * are taken from {@code min} to {@code max - (max - min) / n}; therefore
+ * {@code f} is not sampled at the upper bound {@code max}.</p>
*
- * @param n the {@code int} whose base-2 logarithm is to be evaluated
- * @return the base-2 logarithm of {@code n}
- * @throws MathIllegalArgumentException if {@code n} is not a power of two
+ * @param f Function to be sampled
+ * @param min Lower bound of the interval (included).
+ * @param max Upper bound of the interval (excluded).
+ * @param n Number of sample points.
+ * @return the array of samples.
+ * @throws IllegalArgumentException if the lower bound {@code min} is
+ * greater than, or equal to the upper bound {@code max}, if the number
+ * of sample points {@code n} is negative.
*/
- public static int exactLog2(final int n)
- throws MathIllegalArgumentException {
+ static double[] sample(DoubleUnaryOperator f,
+ double min,
+ double max,
+ int n) {
+ if (n <= 0) {
+ throw new TransformException(TransformException.NOT_STRICTLY_POSITIVE,
+ Integer.valueOf(n));
+ }
+ if (min >= max) {
+ throw new TransformException(TransformException.TOO_LARGE, min, max);
+ }
- int index = Arrays.binarySearch(TransformUtils.POWERS_OF_TWO, n);
- if (index < 0) {
- throw new MathIllegalArgumentException(
- LocalizedFormats.NOT_POWER_OF_TWO_CONSIDER_PADDING,
- Integer.valueOf(n));
+ final double[] s = new double[n];
+ final double h = (max - min) / n;
+ for (int i = 0; i < n; i++) {
+ s[i] = f.applyAsDouble(min + i * h);
}
- return index;
+ return s;
}
}
diff --git a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/package-info.java b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/package-info.java
similarity index 85%
rename from commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/package-info.java
rename to commons-math-transform/src/main/java/org/apache/commons/math4/transform/package-info.java
index dfe1eed..5febfd4 100644
--- a/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/transform/package-info.java
+++ b/commons-math-transform/src/main/java/org/apache/commons/math4/transform/package-info.java
@@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/**
- *
- * Implementations of transform methods, including Fast Fourier transforms.
- *
+ * Implementations of transform methods.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastCosineTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
similarity index 57%
rename from commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastCosineTransformerTest.java
rename to commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
index 0543f6f..41212a4 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastCosineTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastCosineTransformerTest.java
@@ -14,29 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
import java.util.Arrays;
import java.util.Collection;
+import java.util.function.DoubleUnaryOperator;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.analysis.function.Sin;
-import org.apache.commons.math4.legacy.analysis.function.Sinc;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
-import org.apache.commons.math4.legacy.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import org.apache.commons.math3.analysis.UnivariateFunction;
+import org.apache.commons.math3.analysis.function.Sin;
+import org.apache.commons.math3.analysis.function.Sinc;
+
/**
- * Test case for fast cosine transformer.
+ * Test case for {@link FastCosineTransform}.
* <p>
* FCT algorithm is exact, the small tolerance number is used only to account
* for round-off errors.
- *
*/
@RunWith(value = Parameterized.class)
public final class FastCosineTransformerTest
@@ -59,13 +57,13 @@ public final class FastCosineTransformerTest
128
};
this.relativeTolerance = new double[] {
- 1E-15, 1E-15, 1E-14, 1E-13, 1E-13, 1E-12, 1E-11, 1E-10
+ 1e-15, 1e-15, 1e-14, 1e-13, 1e-13, 1e-12, 1e-11, 1e-10
};
}
/**
- * Returns an array containing {@code true, false} in order to check both
- * standard and orthogonal DCTs.
+ * Returns an array containing {@code true, false} in order to
+ * check both standard and orthogonal DCTs.
*
* @return an array of parameters for this parameterized test
*/
@@ -80,8 +78,8 @@ public final class FastCosineTransformerTest
}
@Override
- RealTransformer createRealTransformer() {
- return new FastCosineTransformer(normalization);
+ RealTransform createRealTransformer(boolean inverse) {
+ return new FastCosineTransform(normalization, inverse);
}
@Override
@@ -110,8 +108,9 @@ public final class FastCosineTransformerTest
}
@Override
- UnivariateFunction getValidFunction() {
- return new Sinc();
+ DoubleUnaryOperator getValidFunction() {
+ final UnivariateFunction sinc = new Sinc();
+ return (x) -> sinc.value(x);
}
@Override
@@ -121,16 +120,17 @@ public final class FastCosineTransformerTest
@Override
double getValidUpperBound() {
- return FastMath.PI;
+ return Math.PI;
}
@Override
- double[] transform(final double[] x, final TransformType type) {
+ double[] transform(final double[] x,
+ final boolean inverse) {
final int n = x.length;
final double[] y = new double[n];
final double[] cos = new double[2 * (n - 1)];
for (int i = 0; i < cos.length; i++) {
- cos[i] = FastMath.cos(FastMath.PI * i / (n - 1.0));
+ cos[i] = Math.cos(Math.PI * i / (n - 1.0));
}
int sgn = 1;
for (int j = 0; j < n; j++) {
@@ -142,73 +142,66 @@ public final class FastCosineTransformerTest
sgn *= -1;
}
final double s;
- if (type == TransformType.FORWARD) {
+ if (!inverse) {
if (normalization == DctNormalization.STANDARD_DCT_I) {
s = 1.0;
} else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
- s = FastMath.sqrt(2.0 / (n - 1.0));
+ s = Math.sqrt(2.0 / (n - 1.0));
} else {
- throw new MathIllegalStateException();
+ throw new IllegalStateException();
}
- } else if (type == TransformType.INVERSE) {
+ } else {
if (normalization == DctNormalization.STANDARD_DCT_I) {
s = 2.0 / (n - 1.0);
} else if (normalization == DctNormalization.ORTHOGONAL_DCT_I) {
- s = FastMath.sqrt(2.0 / (n - 1.0));
+ s = Math.sqrt(2.0 / (n - 1.0));
} else {
- throw new MathIllegalStateException();
+ throw new IllegalStateException();
}
- } else {
- /*
- * Should never occur. This clause is a safeguard in case other
- * types are used to TransformType (which should not be done).
- */
- throw new MathIllegalStateException();
}
- TransformUtils.scaleArray(y, s);
+ TransformUtils.scaleInPlace(y, s);
return y;
}
- /*
- * Additional tests.
- */
+ // Additional tests.
/** Test of transformer for the ad hoc data. */
@Test
public void testAdHocData() {
- FastCosineTransformer transformer;
- transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
- double result[], tolerance = 1E-12;
+ FastCosineTransform transformer;
+ double result[], tolerance = 1e-12;
- double x[] = {
+ final double x[] = {
0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0
};
- double y[] =
- {
- 172.0, -105.096569476353, 27.3137084989848, -12.9593152353742,
- 8.0, -5.78585076868676, 4.68629150101524, -4.15826451958632,
- 4.0
- };
-
- result = transformer.transform(x, TransformType.FORWARD);
+ final double y[] = {
+ 172.0, -105.096569476353, 27.3137084989848, -12.9593152353742,
+ 8.0, -5.78585076868676, 4.68629150101524, -4.15826451958632,
+ 4.0
+ };
+
+ transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
+ result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
- result = transformer.transform(y, TransformType.INVERSE);
+ transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I, true);
+ result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- TransformUtils.scaleArray(x, FastMath.sqrt(0.5 * (x.length - 1)));
+ TransformUtils.scaleInPlace(x, Math.sqrt(0.5 * (x.length - 1)));
- transformer = new FastCosineTransformer(DctNormalization.ORTHOGONAL_DCT_I);
- result = transformer.transform(y, TransformType.FORWARD);
+ transformer = new FastCosineTransform(DctNormalization.ORTHOGONAL_DCT_I);
+ result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- result = transformer.transform(x, TransformType.INVERSE);
+ transformer = new FastCosineTransform(DctNormalization.ORTHOGONAL_DCT_I, true);
+ result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
@@ -216,31 +209,30 @@ public final class FastCosineTransformerTest
/** Test of parameters for the transformer. */
@Test
- public void testParameters()
- throws Exception {
- UnivariateFunction f = new Sin();
- FastCosineTransformer transformer;
- transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
+ public void testParameters() throws Exception {
+ final UnivariateFunction sinFunction = new Sin();
+ final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
+ final FastCosineTransform transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
try {
// bad interval
- transformer.transform(f, 1, -1, 65, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad interval");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, 1, -1, 65);
+ Assert.fail("Expecting IllegalArgumentException - bad interval");
+ } catch (IllegalArgumentException ex) {
// expected
}
try {
// bad samples number
- transformer.transform(f, -1, 1, 1, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, -1, 1, 1);
+ Assert.fail("Expecting IllegalArgumentException - bad samples number");
+ } catch (IllegalArgumentException ex) {
// expected
}
try {
// bad samples number
- transformer.transform(f, -1, 1, 64, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, -1, 1, 64);
+ Assert.fail("Expecting IllegalArgumentException - bad samples number");
+ } catch (IllegalArgumentException ex) {
// expected
}
}
@@ -248,27 +240,26 @@ public final class FastCosineTransformerTest
/** Test of transformer for the sine function. */
@Test
public void testSinFunction() {
- UnivariateFunction f = new Sin();
- FastCosineTransformer transformer;
- transformer = new FastCosineTransformer(DctNormalization.STANDARD_DCT_I);
- double min, max, result[], tolerance = 1E-12;
+ final UnivariateFunction sinFunction = new Sin();
+ final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
+ final FastCosineTransform transformer = new FastCosineTransform(DctNormalization.STANDARD_DCT_I);
+ double min, max, result[], tolerance = 1e-12;
int N = 9;
- double expected[] =
- {
- 0.0, 3.26197262739567, 0.0, -2.17958042710327, 0.0,
- -0.648846697642915, 0.0, -0.433545502649478, 0.0
- };
+ final double expected[] = {
+ 0.0, 3.26197262739567, 0.0, -2.17958042710327, 0.0,
+ -0.648846697642915, 0.0, -0.433545502649478, 0.0
+ };
min = 0.0;
- max = 2.0 * FastMath.PI * N / (N - 1);
- result = transformer.transform(f, min, max, N, TransformType.FORWARD);
+ max = 2.0 * Math.PI * N / (N - 1);
+ result = transformer.apply(f, min, max, N);
for (int i = 0; i < N; i++) {
Assert.assertEquals(expected[i], result[i], tolerance);
}
- min = -FastMath.PI;
- max = FastMath.PI * (N + 1) / (N - 1);
- result = transformer.transform(f, min, max, N, TransformType.FORWARD);
+ min = -Math.PI;
+ max = Math.PI * (N + 1) / (N - 1);
+ result = transformer.apply(f, min, max, N);
for (int i = 0; i < N; i++) {
Assert.assertEquals(-expected[i], result[i], tolerance);
}
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastFourierTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
similarity index 53%
rename from commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastFourierTransformerTest.java
rename to commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
index 3b964bd..4653d02 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastFourierTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastFourierTransformerTest.java
@@ -14,35 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
-import java.util.Random;
+import java.util.function.DoubleUnaryOperator;
-import org.apache.commons.numbers.complex.Complex;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.analysis.function.Sin;
-import org.apache.commons.math4.legacy.analysis.function.Sinc;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
-import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
-import org.apache.commons.math4.legacy.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
+import org.apache.commons.rng.UniformRandomProvider;
+import org.apache.commons.rng.simple.RandomSource;
+import org.apache.commons.numbers.complex.Complex;
+
+import org.apache.commons.math3.analysis.UnivariateFunction;
+import org.apache.commons.math3.analysis.function.Sin;
+import org.apache.commons.math3.analysis.function.Sinc;
+
/**
- * Test case for fast Fourier transformer.
+ * Test case for {@link FastFourierTransform}.
* <p>
* FFT algorithm is exact, the small tolerance number is used only
* to account for round-off errors.
- *
*/
public final class FastFourierTransformerTest {
- /** The common seed of all random number generators used in this test. */
- private final static long SEED = 20110111L;
+ private static final Sin SIN_FUNCTION = new Sin();
+ private static final DoubleUnaryOperator SIN = (x) -> SIN_FUNCTION.value(x);
- /*
- * Precondition checks.
- */
+ /** RNG. */
+ private static final UniformRandomProvider RNG = RandomSource.create(RandomSource.MWC_256);
+
+ // Precondition checks.
@Test
public void testTransformComplexSizeNotAPowerOfTwo() {
@@ -50,17 +50,14 @@ public final class FastFourierTransformerTest {
final Complex[] x = createComplexData(n);
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(norm[i]);
+ for (boolean type : new boolean[] { true, false }) {
+ final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
try {
- fft.transform(x, type[j]);
- Assert.fail(norm[i] + ", " + type[j] +
- ": MathIllegalArgumentException was expected");
- } catch (MathIllegalArgumentException e) {
+ fft.apply(x);
+ Assert.fail(norm[i] + ", " + type +
+ ": IllegalArgumentException was expected");
+ } catch (IllegalArgumentException e) {
// Expected behaviour
}
}
@@ -73,17 +70,14 @@ public final class FastFourierTransformerTest {
final double[] x = createRealData(n);
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(norm[i]);
+ for (boolean type : new boolean[] { true, false }) {
+ final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
try {
- fft.transform(x, type[j]);
- Assert.fail(norm[i] + ", " + type[j] +
- ": MathIllegalArgumentException was expected");
- } catch (MathIllegalArgumentException e) {
+ fft.apply(x);
+ Assert.fail(norm[i] + ", " + type +
+ ": IllegalArgumentException was expected");
+ } catch (IllegalArgumentException e) {
// Expected behaviour
}
}
@@ -93,20 +87,16 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionSizeNotAPowerOfTwo() {
final int n = 127;
- final UnivariateFunction f = new Sin();
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(norm[i]);
+ for (boolean type : new boolean[] { true, false }) {
+ final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
try {
- fft.transform(f, 0.0, Math.PI, n, type[j]);
- Assert.fail(norm[i] + ", " + type[j] +
- ": MathIllegalArgumentException was expected");
- } catch (MathIllegalArgumentException e) {
+ fft.apply(SIN, 0.0, Math.PI, n);
+ Assert.fail(norm[i] + ", " + type +
+ ": IllegalArgumentException was expected");
+ } catch (IllegalArgumentException e) {
// Expected behaviour
}
}
@@ -116,21 +106,17 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionNotStrictlyPositiveNumberOfSamples() {
final int n = -128;
- final UnivariateFunction f = new Sin();
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(norm[i]);
+ for (boolean type : new boolean[] { true, false }) {
+ final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
try {
- fft.transform(f, 0.0, Math.PI, n, type[j]);
- fft.transform(f, 0.0, Math.PI, n, type[j]);
- Assert.fail(norm[i] + ", " + type[j] +
- ": NotStrictlyPositiveException was expected");
- } catch (NotStrictlyPositiveException e) {
+ fft.apply(SIN, 0.0, Math.PI, n);
+ fft.apply(SIN, 0.0, Math.PI, n);
+ Assert.fail(norm[i] + ", " + type +
+ ": IllegalArgumentException was expected");
+ } catch (IllegalArgumentException e) {
// Expected behaviour
}
}
@@ -140,46 +126,38 @@ public final class FastFourierTransformerTest {
@Test
public void testTransformFunctionInvalidBounds() {
final int n = 128;
- final UnivariateFunction f = new Sin();
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(norm[i]);
+ for (boolean type : new boolean[] { true, false }) {
+ final FastFourierTransform fft = new FastFourierTransform(norm[i], type);
try {
- fft.transform(f, Math.PI, 0.0, n, type[j]);
- Assert.fail(norm[i] + ", " + type[j] +
- ": NumberIsTooLargeException was expected");
- } catch (NumberIsTooLargeException e) {
+ fft.apply(SIN, Math.PI, 0.0, n);
+ Assert.fail(norm[i] + ", " + type +
+ ": IllegalArgumentException was expected");
+ } catch (IllegalArgumentException e) {
// Expected behaviour
}
}
}
}
- /*
- * Utility methods for checking (successful) transforms.
- */
+ // Utility methods for checking (successful) transforms.
private static Complex[] createComplexData(final int n) {
- final Random random = new Random(SEED);
final Complex[] data = new Complex[n];
for (int i = 0; i < n; i++) {
- final double re = 2.0 * random.nextDouble() - 1.0;
- final double im = 2.0 * random.nextDouble() - 1.0;
+ final double re = 2 * RNG.nextDouble() - 1;
+ final double im = 2 * RNG.nextDouble() - 1;
data[i] = Complex.ofCartesian(re, im);
}
return data;
}
private static double[] createRealData(final int n) {
- final Random random = new Random(SEED);
final double[] data = new double[n];
for (int i = 0; i < n; i++) {
- data[i] = 2.0 * random.nextDouble() - 1.0;
+ data[i] = 2 * RNG.nextDouble() - 1;
}
return data;
}
@@ -191,9 +169,9 @@ public final class FastFourierTransformerTest {
final double[] sin = new double[n];
final Complex[] y = new Complex[n];
for (int i = 0; i < n; i++) {
- final double arg = 2.0 * FastMath.PI * i / n;
- cos[i] = FastMath.cos(arg);
- sin[i] = FastMath.sin(arg);
+ final double arg = 2.0 * Math.PI * i / n;
+ cos[i] = Math.cos(arg);
+ sin[i] = Math.sin(arg);
}
for (int i = 0; i < n; i++) {
double yr = 0.0;
@@ -212,47 +190,47 @@ public final class FastFourierTransformerTest {
return y;
}
- private static void doTestTransformComplex(final int n, final double tol,
- final DftNormalization normalization,
- final TransformType type) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(normalization);
+ private static void doTestTransformComplex(final int n,
+ final double tol,
+ final DftNormalization normalization,
+ boolean inverse) {
+ final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final Complex[] x = createComplexData(n);
final Complex[] expected;
final double s;
- if (type==TransformType.FORWARD) {
+ if (!inverse) {
expected = dft(x, -1);
if (normalization == DftNormalization.STANDARD){
s = 1.0;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(x, 1);
if (normalization == DftNormalization.STANDARD) {
s = 1.0 / n;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
}
- final Complex[] actual = fft.transform(x, type);
+ final Complex[] actual = fft.apply(x);
for (int i = 0; i < n; i++) {
final String msg;
- msg = String.format("%s, %s, %d, %d", normalization, type, n, i);
+ msg = String.format("%s, %s, %d, %d", normalization, inverse, n, i);
final double re = s * expected[i].getReal();
Assert.assertEquals(msg, re, actual[i].getReal(),
- tol * FastMath.abs(re));
+ tol * Math.abs(re));
final double im = s * expected[i].getImaginary();
- Assert.assertEquals(msg, im, actual[i].getImaginary(), tol *
- FastMath.abs(re));
+ Assert.assertEquals(msg, im, actual[i].getImaginary(),
+ tol * Math.abs(re));
}
}
- private static void doTestTransformReal(final int n, final double tol,
- final DftNormalization normalization,
- final TransformType type) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(normalization);
+ private static void doTestTransformReal(final int n,
+ final double tol,
+ final DftNormalization normalization,
+ final boolean inverse) {
+ final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final double[] x = createRealData(n);
final Complex[] xc = new Complex[n];
for (int i = 0; i < n; i++) {
@@ -260,93 +238,91 @@ public final class FastFourierTransformerTest {
}
final Complex[] expected;
final double s;
- if (type == TransformType.FORWARD) {
+ if (!inverse) {
expected = dft(xc, -1);
if (normalization == DftNormalization.STANDARD) {
s = 1.0;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(xc, 1);
if (normalization == DftNormalization.STANDARD) {
s = 1.0 / n;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
}
- final Complex[] actual = fft.transform(x, type);
+ final Complex[] actual = fft.apply(x);
for (int i = 0; i < n; i++) {
final String msg;
- msg = String.format("%s, %s, %d, %d", normalization, type, n, i);
+ msg = String.format("%s, %s, %d, %d", normalization, inverse, n, i);
final double re = s * expected[i].getReal();
Assert.assertEquals(msg, re, actual[i].getReal(),
- tol * FastMath.abs(re));
+ tol * Math.abs(re));
final double im = s * expected[i].getImaginary();
- Assert.assertEquals(msg, im, actual[i].getImaginary(), tol *
- FastMath.abs(re));
+ Assert.assertEquals(msg, im, actual[i].getImaginary(),
+ tol * Math.abs(re));
}
}
- private static void doTestTransformFunction(final UnivariateFunction f,
- final double min, final double max, int n, final double tol,
- final DftNormalization normalization,
- final TransformType type) {
- final FastFourierTransformer fft;
- fft = new FastFourierTransformer(normalization);
+ private static void doTestTransformFunction(final DoubleUnaryOperator f,
+ final double min,
+ final double max,
+ int n,
+ final double tol,
+ final DftNormalization normalization,
+ final boolean inverse) {
+ final FastFourierTransform fft = new FastFourierTransform(normalization, inverse);
final Complex[] x = new Complex[n];
for (int i = 0; i < n; i++) {
final double t = min + i * (max - min) / n;
- x[i] = Complex.ofCartesian(f.value(t), 0);
+ x[i] = Complex.ofCartesian(f.applyAsDouble(t), 0);
}
final Complex[] expected;
final double s;
- if (type == TransformType.FORWARD) {
+ if (!inverse) {
expected = dft(x, -1);
if (normalization == DftNormalization.STANDARD) {
s = 1.0;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
} else {
expected = dft(x, 1);
if (normalization == DftNormalization.STANDARD) {
s = 1.0 / n;
} else {
- s = 1.0 / FastMath.sqrt(n);
+ s = 1.0 / Math.sqrt(n);
}
}
- final Complex[] actual = fft.transform(f, min, max, n, type);
+ final Complex[] actual = fft.apply(f, min, max, n);
for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i);
final double re = s * expected[i].getReal();
Assert.assertEquals(msg, re, actual[i].getReal(),
- tol * FastMath.abs(re));
+ tol * Math.abs(re));
final double im = s * expected[i].getImaginary();
- Assert.assertEquals(msg, im, actual[i].getImaginary(), tol *
- FastMath.abs(re));
+ Assert.assertEquals(msg, im, actual[i].getImaginary(),
+ tol * Math.abs(re));
}
}
- /*
- * Tests of standard transform (when data is valid).
- */
+ // Tests of standard transform (when data is valid).
@Test
public void testTransformComplex() {
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- doTestTransformComplex(2, 1.0E-15, norm[i], type[j]);
- doTestTransformComplex(4, 1.0E-14, norm[i], type[j]);
- doTestTransformComplex(8, 1.0E-14, norm[i], type[j]);
- doTestTransformComplex(16, 1.0E-13, norm[i], type[j]);
- doTestTransformComplex(32, 1.0E-13, norm[i], type[j]);
- doTestTransformComplex(64, 1.0E-12, norm[i], type[j]);
- doTestTransformComplex(128, 1.0E-12, norm[i], type[j]);
+ for (boolean type : new boolean[] { true, false }) {
+ doTestTransformComplex(2, 1e-15, norm[i], type);
+ doTestTransformComplex(4, 1e-14, norm[i], type);
+ doTestTransformComplex(8, 1e-13, norm[i], type);
+ doTestTransformComplex(16, 1e-13, norm[i], type);
+ doTestTransformComplex(32, 1e-13, norm[i], type);
+ doTestTransformComplex(64, 1e-12, norm[i], type);
+ doTestTransformComplex(128, 1e-11, norm[i], type);
}
}
}
@@ -355,58 +331,54 @@ public final class FastFourierTransformerTest {
public void testStandardTransformReal() {
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- doTestTransformReal(2, 1.0E-15, norm[i], type[j]);
- doTestTransformReal(4, 1.0E-14, norm[i], type[j]);
- doTestTransformReal(8, 1.0E-14, norm[i], type[j]);
- doTestTransformReal(16, 1.0E-13, norm[i], type[j]);
- doTestTransformReal(32, 1.0E-13, norm[i], type[j]);
- doTestTransformReal(64, 1.0E-13, norm[i], type[j]);
- doTestTransformReal(128, 1.0E-11, norm[i], type[j]);
+ for (boolean type : new boolean[] { true, false }) {
+ doTestTransformReal(2, 1e-15, norm[i], type);
+ doTestTransformReal(4, 1e-14, norm[i], type);
+ doTestTransformReal(8, 1e-13, norm[i], type);
+ doTestTransformReal(16, 1e-13, norm[i], type);
+ doTestTransformReal(32, 1e-12, norm[i], type);
+ doTestTransformReal(64, 1e-12, norm[i], type);
+ doTestTransformReal(128, 1e-11, norm[i], type);
}
}
}
@Test
public void testStandardTransformFunction() {
- final UnivariateFunction f = new Sinc();
- final double min = -FastMath.PI;
- final double max = FastMath.PI;
+ final UnivariateFunction sinc = new Sinc();
+ final DoubleUnaryOperator f = (x) -> sinc.value(x);
+
+ final double min = -Math.PI;
+ final double max = Math.PI;
final DftNormalization[] norm;
norm = DftNormalization.values();
- final TransformType[] type;
- type = TransformType.values();
+
for (int i = 0; i < norm.length; i++) {
- for (int j = 0; j < type.length; j++) {
- doTestTransformFunction(f, min, max, 2, 1.0E-15, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 4, 1.0E-14, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 8, 1.0E-14, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 16, 1.0E-13, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 32, 1.0E-13, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 64, 1.0E-12, norm[i], type[j]);
- doTestTransformFunction(f, min, max, 128, 1.0E-11, norm[i], type[j]);
+ for (boolean type : new boolean[] { true, false }) {
+ doTestTransformFunction(f, min, max, 2, 1e-15, norm[i], type);
+ doTestTransformFunction(f, min, max, 4, 1e-14, norm[i], type);
+ doTestTransformFunction(f, min, max, 8, 1e-14, norm[i], type);
+ doTestTransformFunction(f, min, max, 16, 1e-13, norm[i], type);
+ doTestTransformFunction(f, min, max, 32, 1e-13, norm[i], type);
+ doTestTransformFunction(f, min, max, 64, 1e-12, norm[i], type);
+ doTestTransformFunction(f, min, max, 128, 1e-11, norm[i], type);
}
}
}
- /*
- * Additional tests for 1D data.
- */
+ // Additional tests for 1D data.
/**
* Test of transformer for the ad hoc data taken from Mathematica.
*/
@Test
public void testAdHocData() {
- FastFourierTransformer transformer;
- transformer = new FastFourierTransformer(DftNormalization.STANDARD);
- Complex result[]; double tolerance = 1E-12;
+ FastFourierTransform transformer;
+ Complex result[]; double tolerance = 1e-12;
- double x[] = {1.3, 2.4, 1.7, 4.1, 2.9, 1.7, 5.1, 2.7};
- Complex y[] = {
+ final double x[] = {1.3, 2.4, 1.7, 4.1, 2.9, 1.7, 5.1, 2.7};
+ final Complex y[] = {
Complex.ofCartesian(21.9, 0.0),
Complex.ofCartesian(-2.09497474683058, 1.91507575950825),
Complex.ofCartesian(-2.6, 2.7),
@@ -416,30 +388,33 @@ public final class FastFourierTransformerTest {
Complex.ofCartesian(-2.6, -2.7),
Complex.ofCartesian(-2.09497474683058, -1.91507575950825)};
- result = transformer.transform(x, TransformType.FORWARD);
+ transformer = new FastFourierTransform(DftNormalization.STANDARD);
+ result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i].getReal(), result[i].getReal(), tolerance);
Assert.assertEquals(y[i].getImaginary(), result[i].getImaginary(), tolerance);
}
- result = transformer.transform(y, TransformType.INVERSE);
+ transformer = new FastFourierTransform(DftNormalization.STANDARD, true);
+ result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i].getReal(), tolerance);
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
}
double x2[] = {10.4, 21.6, 40.8, 13.6, 23.2, 32.8, 13.6, 19.2};
- TransformUtils.scaleArray(x2, 1.0 / FastMath.sqrt(x2.length));
+ TransformUtils.scaleInPlace(x2, 1.0 / Math.sqrt(x2.length));
Complex y2[] = y;
- transformer = new FastFourierTransformer(DftNormalization.UNITARY);
- result = transformer.transform(y2, TransformType.FORWARD);
+ transformer = new FastFourierTransform(DftNormalization.UNITARY);
+ result = transformer.apply(y2);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x2[i], result[i].getReal(), tolerance);
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
}
- result = transformer.transform(x2, TransformType.INVERSE);
+ transformer = new FastFourierTransform(DftNormalization.UNITARY, true);
+ result = transformer.apply(x2);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y2[i].getReal(), result[i].getReal(), tolerance);
Assert.assertEquals(y2[i].getImaginary(), result[i].getImaginary(), tolerance);
@@ -451,14 +426,13 @@ public final class FastFourierTransformerTest {
*/
@Test
public void testSinFunction() {
- UnivariateFunction f = new Sin();
- FastFourierTransformer transformer;
- transformer = new FastFourierTransformer(DftNormalization.STANDARD);
+ FastFourierTransform transformer;
Complex result[]; int N = 1 << 8;
- double min, max, tolerance = 1E-12;
+ double min, max, tolerance = 1e-12;
- min = 0.0; max = 2.0 * FastMath.PI;
- result = transformer.transform(f, min, max, N, TransformType.FORWARD);
+ min = 0.0; max = 2.0 * Math.PI;
+ transformer = new FastFourierTransform(DftNormalization.STANDARD);
+ result = transformer.apply(SIN, min, max, N);
Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-(N >> 1), result[1].getImaginary(), tolerance);
Assert.assertEquals(0.0, result[N-1].getReal(), tolerance);
@@ -468,8 +442,9 @@ public final class FastFourierTransformerTest {
Assert.assertEquals(0.0, result[i].getImaginary(), tolerance);
}
- min = -FastMath.PI; max = FastMath.PI;
- result = transformer.transform(f, min, max, N, TransformType.INVERSE);
+ min = -Math.PI; max = Math.PI;
+ transformer = new FastFourierTransform(DftNormalization.STANDARD, true);
+ result = transformer.apply(SIN, min, max, N);
Assert.assertEquals(0.0, result[1].getReal(), tolerance);
Assert.assertEquals(-0.5, result[1].getImaginary(), tolerance);
Assert.assertEquals(0.0, result[N-1].getReal(), tolerance);
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastHadamardTransformerTest.java
similarity index 70%
rename from commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformerTest.java
rename to commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastHadamardTransformerTest.java
index fd783ee..3499317 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastHadamardTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastHadamardTransformerTest.java
@@ -14,27 +14,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.numbers.core.Precision;
import org.junit.Assert;
import org.junit.Test;
+import org.apache.commons.numbers.core.Precision;
+
/**
- * JUnit Test for HadamardTransformerTest
- * @see org.apache.commons.math4.legacy.transform.FastHadamardTransformer
+ * Test for {@link FestHadamardTransform}.
*/
public final class FastHadamardTransformerTest {
-
/**
* Test of transformer for the a 8-point FHT (means n=8)
*/
@Test
public void test8Points() {
checkAllTransforms(new int[] { 1, 4, -2, 3, 0, 1, 4, -1 },
- new int[] { 10, -4, 2, -4, 2, -12, 6, 8 });
+ new int[] { 10, -4, 2, -4, 2, -12, 6, 8 });
}
/**
@@ -51,8 +49,8 @@ public final class FastHadamardTransformerTest {
*/
@Test
public void testNoIntInverse() {
- FastHadamardTransformer transformer = new FastHadamardTransformer();
- double[] x = transformer.transform(new double[] { 0, 1, 0, 1}, TransformType.INVERSE);
+ final FastHadamardTransform transformer = new FastHadamardTransform(true);
+ final double[] x = transformer.apply(new double[] { 0, 1, 0, 1});
Assert.assertEquals( 0.5, x[0], 0);
Assert.assertEquals(-0.5, x[1], 0);
Assert.assertEquals( 0.0, x[2], 0);
@@ -65,41 +63,41 @@ public final class FastHadamardTransformerTest {
@Test
public void test3Points() {
try {
- new FastHadamardTransformer().transform(new double[3], TransformType.FORWARD);
+ new FastHadamardTransform().apply(new double[3]);
Assert.fail("an exception should have been thrown");
- } catch (MathIllegalArgumentException iae) {
+ } catch (IllegalArgumentException iae) {
// expected
}
}
- private void checkAllTransforms(int[]x, int[] y) {
+ private void checkAllTransforms(int[] x, int[] y) {
checkDoubleTransform(x, y);
checkInverseDoubleTransform(x, y);
checkIntTransform(x, y);
}
- private void checkDoubleTransform(int[]x, int[] y) {
+ private void checkDoubleTransform(int[] x, int[] y) {
// Initiate the transformer
- FastHadamardTransformer transformer = new FastHadamardTransformer();
+ final FastHadamardTransform transformer = new FastHadamardTransform();
// check double transform
- double[] dX = new double[x.length];
+ final double[] dX = new double[x.length];
for (int i = 0; i < dX.length; ++i) {
dX[i] = x[i];
}
- double dResult[] = transformer.transform(dX, TransformType.FORWARD);
+ final double dResult[] = transformer.apply(dX);
for (int i = 0; i < dResult.length; i++) {
// compare computed results to precomputed results
Assert.assertTrue(Precision.equals(y[i], dResult[i], 1));
}
}
- private void checkIntTransform(int[]x, int[] y) {
+ private void checkIntTransform(int[] x, int[] y) {
// Initiate the transformer
- FastHadamardTransformer transformer = new FastHadamardTransformer();
+ final FastHadamardTransform transformer = new FastHadamardTransform();
// check integer transform
- int iResult[] = transformer.transform(x);
+ final int iResult[] = transformer.apply(x);
for (int i = 0; i < iResult.length; i++) {
// compare computed results to precomputed results
Assert.assertEquals(y[i], iResult[i]);
@@ -109,14 +107,14 @@ public final class FastHadamardTransformerTest {
private void checkInverseDoubleTransform(int[]x, int[] y) {
// Initiate the transformer
- FastHadamardTransformer transformer = new FastHadamardTransformer();
+ final FastHadamardTransform transformer = new FastHadamardTransform(true);
// check double transform
- double[] dY = new double[y.length];
+ final double[] dY = new double[y.length];
for (int i = 0; i < dY.length; ++i) {
dY[i] = y[i];
}
- double dResult[] = transformer.transform(dY, TransformType.INVERSE);
+ final double dResult[] = transformer.apply(dY);
for (int i = 0; i < dResult.length; i++) {
// compare computed results to precomputed results
Assert.assertTrue(Precision.equals(x[i], dResult[i], 1));
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastSineTransformerTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
similarity index 58%
rename from commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastSineTransformerTest.java
rename to commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
index 21df571..aeed09e 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/FastSineTransformerTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/FastSineTransformerTest.java
@@ -14,29 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
import java.util.Arrays;
import java.util.Collection;
+import java.util.function.DoubleUnaryOperator;
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.analysis.function.Sin;
-import org.apache.commons.math4.legacy.analysis.function.Sinc;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
-import org.apache.commons.math4.legacy.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import org.apache.commons.math3.analysis.UnivariateFunction;
+import org.apache.commons.math3.analysis.function.Sin;
+import org.apache.commons.math3.analysis.function.Sinc;
+
/**
- * Test case for fast sine transformer.
+ * Test case for {@link FastSineTransform}.
* <p>
* FST algorithm is exact, the small tolerance number is used only
* to account for round-off errors.
- *
*/
@RunWith(value = Parameterized.class)
public final class FastSineTransformerTest extends RealTransformerAbstractTest {
@@ -58,7 +56,7 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
129
};
this.relativeTolerance = new double[] {
- 1E-15, 1E-15, 1E-14, 1E-14, 1E-13, 1E-12, 1E-11, 1E-11
+ 1e-15, 1e-15, 1e-14, 1e-14, 1e-13, 1e-12, 1e-11, 1e-11
};
}
@@ -66,7 +64,7 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
* Returns an array containing {@code true, false} in order to check both
* standard and orthogonal DSTs.
*
- * @return an array of parameters for this parameterized test
+ * @return an array of parameters for this parameterized test.
*/
@Parameters
public static Collection<Object[]> data() {
@@ -87,13 +85,13 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
@Override
double[] createRealData(final int n) {
final double[] data = super.createRealData(n);
- data[0] = 0.0;
+ data[0] = 0;
return data;
}
@Override
- RealTransformer createRealTransformer() {
- return new FastSineTransformer(normalization);
+ RealTransform createRealTransformer(boolean inverse) {
+ return new FastSineTransform(normalization, inverse);
}
@Override
@@ -122,8 +120,9 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
}
@Override
- UnivariateFunction getValidFunction() {
- return new Sinc();
+ DoubleUnaryOperator getValidFunction() {
+ final UnivariateFunction sinc = new Sinc();
+ return (x) -> sinc.value(x);
}
@Override
@@ -133,16 +132,16 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
@Override
double getValidUpperBound() {
- return FastMath.PI;
+ return Math.PI;
}
@Override
- double[] transform(final double[] x, final TransformType type) {
+ double[] transform(final double[] x, boolean inverse) {
final int n = x.length;
final double[] y = new double[n];
final double[] sin = new double[2 * n];
for (int i = 0; i < sin.length; i++) {
- sin[i] = FastMath.sin(FastMath.PI * i / n);
+ sin[i] = Math.sin(Math.PI * i / n);
}
for (int j = 0; j < n; j++) {
double yj = 0.0;
@@ -152,90 +151,87 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
y[j] = yj;
}
final double s;
- if (type == TransformType.FORWARD) {
+ if (!inverse) {
if (normalization == DstNormalization.STANDARD_DST_I) {
- s = 1.0;
+ s = 1;
} else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
- s = FastMath.sqrt(2.0 / n);
+ s = Math.sqrt(2d / n);
} else {
- throw new MathIllegalStateException();
+ throw new IllegalStateException();
}
- } else if (type == TransformType.INVERSE) {
+ } else {
if (normalization == DstNormalization.STANDARD_DST_I) {
- s = 2.0 / n;
+ s = 2d / n;
} else if (normalization == DstNormalization.ORTHOGONAL_DST_I) {
- s = FastMath.sqrt(2.0 / n);
+ s = Math.sqrt(2d / n);
} else {
- throw new MathIllegalStateException();
+ throw new IllegalStateException();
}
- } else {
- /*
- * Should never occur. This clause is a safeguard in case other
- * types are used to TransformType (which should not be done).
- */
- throw new MathIllegalStateException();
}
- TransformUtils.scaleArray(y, s);
+
+ TransformUtils.scaleInPlace(y, s);
return y;
}
- /*
- * Additional tests.
- */
+ // Additional tests.
+
@Test
public void testTransformRealFirstElementNotZero() {
- final TransformType[] type = TransformType.values();
final double[] data = new double[] {
- 1.0, 1.0, 1.0, 1.0
+ 1, 1, 1, 1
};
- final RealTransformer transformer = createRealTransformer();
- for (int j = 0; j < type.length; j++) {
+ for (boolean type : new boolean[] { true, false }) {
try {
- transformer.transform(data, type[j]);
- Assert.fail(type[j].toString());
- } catch (MathIllegalArgumentException e) {
+ final RealTransform transformer = createRealTransformer(type);
+ transformer.apply(data);
+ Assert.fail("type=" + type);
+ } catch (IllegalArgumentException e) {
// Expected: do nothing
}
}
}
- /*
- * Additional (legacy) tests.
- */
+ // Additional (legacy) tests.
/**
* Test of transformer for the ad hoc data.
*/
@Test
public void testAdHocData() {
- FastSineTransformer transformer;
- transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
- double result[], tolerance = 1E-12;
+ FastSineTransform transformer;
+ double result[], tolerance = 1e-12;
- double x[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
- double y[] = { 0.0, 20.1093579685034, -9.65685424949238,
- 5.98642305066196, -4.0, 2.67271455167720,
- -1.65685424949238, 0.795649469518633 };
+ final double x[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7
+ };
+ final double y[] = {
+ 0.0, 20.1093579685034, -9.65685424949238,
+ 5.98642305066196, -4.0, 2.67271455167720,
+ -1.65685424949238, 0.795649469518633
+ };
- result = transformer.transform(x, TransformType.FORWARD);
+ transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
+ result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
- result = transformer.transform(y, TransformType.INVERSE);
+ transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I, true);
+ result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- TransformUtils.scaleArray(x, FastMath.sqrt(x.length / 2.0));
- transformer = new FastSineTransformer(DstNormalization.ORTHOGONAL_DST_I);
+ TransformUtils.scaleInPlace(x, Math.sqrt(x.length / 2d));
+ transformer = new FastSineTransform(DstNormalization.ORTHOGONAL_DST_I);
- result = transformer.transform(y, TransformType.FORWARD);
+ result = transformer.apply(y);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(x[i], result[i], tolerance);
}
- result = transformer.transform(x, TransformType.INVERSE);
+ transformer = new FastSineTransform(DstNormalization.ORTHOGONAL_DST_I, true);
+ result = transformer.apply(x);
for (int i = 0; i < result.length; i++) {
Assert.assertEquals(y[i], result[i], tolerance);
}
@@ -246,20 +242,22 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
*/
@Test
public void testSinFunction() {
- UnivariateFunction f = new Sin();
- FastSineTransformer transformer;
- transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
- double min, max, result[], tolerance = 1E-12; int N = 1 << 8;
-
- min = 0.0; max = 2.0 * FastMath.PI;
- result = transformer.transform(f, min, max, N, TransformType.FORWARD);
+ final UnivariateFunction sinFunction = new Sin();
+ final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
+ final FastSineTransform transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
+ double min, max, result[], tolerance = 1e-12; int N = 1 << 8;
+
+ min = 0.0;
+ max = 2 * Math.PI;
+ result = transformer.apply(f, min, max, N);
Assert.assertEquals(N >> 1, result[2], tolerance);
for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
Assert.assertEquals(0.0, result[i], tolerance);
}
- min = -FastMath.PI; max = FastMath.PI;
- result = transformer.transform(f, min, max, N, TransformType.FORWARD);
+ min = -Math.PI;
+ max = Math.PI;
+ result = transformer.apply(f, min, max, N);
Assert.assertEquals(-(N >> 1), result[2], tolerance);
for (int i = 0; i < N; i += (i == 1 ? 2 : 1)) {
Assert.assertEquals(0.0, result[i], tolerance);
@@ -271,29 +269,29 @@ public final class FastSineTransformerTest extends RealTransformerAbstractTest {
*/
@Test
public void testParameters() throws Exception {
- UnivariateFunction f = new Sin();
- FastSineTransformer transformer;
- transformer = new FastSineTransformer(DstNormalization.STANDARD_DST_I);
+ final UnivariateFunction sinFunction = new Sin();
+ final DoubleUnaryOperator f = (x) -> sinFunction.value(x);
+ final FastSineTransform transformer = new FastSineTransform(DstNormalization.STANDARD_DST_I);
try {
// bad interval
- transformer.transform(f, 1, -1, 64, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad interval");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, 1, -1, 64);
+ Assert.fail("Expecting IllegalArgumentException - bad interval");
+ } catch (IllegalArgumentException ex) {
// expected
}
try {
// bad samples number
- transformer.transform(f, -1, 1, 0, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, -1, 1, 0);
+ Assert.fail("Expecting IllegalArgumentException - bad samples number");
+ } catch (IllegalArgumentException ex) {
// expected
}
try {
// bad samples number
- transformer.transform(f, -1, 1, 100, TransformType.FORWARD);
- Assert.fail("Expecting MathIllegalArgumentException - bad samples number");
- } catch (MathIllegalArgumentException ex) {
+ transformer.apply(f, -1, 1, 100);
+ Assert.fail("Expecting IllegalArgumentException - bad samples number");
+ } catch (IllegalArgumentException ex) {
// expected
}
}
diff --git a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/RealTransformerAbstractTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/RealTransformerAbstractTest.java
similarity index 57%
rename from commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/RealTransformerAbstractTest.java
rename to commons-math-transform/src/test/java/org/apache/commons/math4/transform/RealTransformerAbstractTest.java
index a28d29c..a419110 100644
--- a/commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/transform/RealTransformerAbstractTest.java
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/RealTransformerAbstractTest.java
@@ -14,40 +14,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.math4.legacy.transform;
+package org.apache.commons.math4.transform;
-import java.util.Random;
-
-import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
-import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
-import org.apache.commons.math4.legacy.exception.NotStrictlyPositiveException;
-import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
-import org.apache.commons.math4.legacy.util.FastMath;
import org.junit.Assert;
import org.junit.Test;
+import java.util.function.DoubleUnaryOperator;
+
+import org.apache.commons.rng.UniformRandomProvider;
+import org.apache.commons.rng.simple.RandomSource;
+
/**
- * Abstract test for classes implementing the {@link RealTransformer} interface.
+ * Abstract test for classes implementing the {@link RealTransform} interface.
* This abstract test handles the automatic generation of random data of various
* sizes. For each generated data array, actual values (returned by the
* transformer to be tested) are compared to expected values, returned by the
- * {@link #transform(double[], TransformType)} (to be implemented by the user:
- * a naive method may be used). Methods are also provided to test that invalid
- * parameters throw the expected exceptions.
+ * {@link #apply(double[])} (to be implemented by the user: a naive method may
+ * be used). Methods are also provided to test that invalid parameters throw the
+ * expected exceptions.
*
* @since 3.0
*/
public abstract class RealTransformerAbstractTest {
-
- /** The common seed of all random number generators used in this test. */
- private final static long SEED = 20110119L;
+ /** RNG. */
+ private static final UniformRandomProvider RNG = RandomSource.create(RandomSource.MWC_256);
/**
- * Returns a new instance of the {@link RealTransformer} to be tested.
+ * Returns a new instance of the {@link RealTransform} to be tested.
*
+ * @param inverse Whether to apply the inverse transform.
* @return a the transformer to be tested
*/
- abstract RealTransformer createRealTransformer();
+ abstract RealTransform createRealTransformer(boolean inverse);
/**
* Returns an invalid data size. Transforms with this data size should
@@ -62,7 +60,7 @@ public abstract class RealTransformerAbstractTest {
/**
* Returns the total number of invalid data sizes to be tested. If data
* array of any
- * size can be handled by the {@link RealTransformer} to be tested, this
+ * size can be handled by the {@link RealTransform} to be tested, this
* method should return {@code 0}.
*
* @return the total number of invalid data sizes
@@ -98,17 +96,17 @@ public abstract class RealTransformerAbstractTest {
/**
* Returns a function for the accuracy check of
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}.
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int)}.
* This function should be valid. In other words, none of the above methods
* should throw an exception when passed this function.
*
* @return a valid function
*/
- abstract UnivariateFunction getValidFunction();
+ abstract DoubleUnaryOperator getValidFunction();
/**
* Returns a sampling lower bound for the accuracy check of
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}.
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int)}.
* This lower bound should be valid. In other words, none of the above
* methods should throw an exception when passed this bound.
*
@@ -118,7 +116,7 @@ public abstract class RealTransformerAbstractTest {
/**
* Returns a sampling upper bound for the accuracy check of
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}.
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int, TransformType)}.
* This upper bound should be valid. In other words, none of the above
* methods should throw an exception when passed this bound.
*
@@ -129,31 +127,28 @@ public abstract class RealTransformerAbstractTest {
/**
* Returns the expected transform of the specified real data array.
*
- * @param x the real data array to be transformed
- * @param type the type of transform (forward, inverse) to be performed
- * @return the expected transform
+ * @param x Data to be transformed.
+ * @param type Whether to perform the inverse) transform.
+ * @return the expected transform.
*/
- abstract double[] transform(double[] x, TransformType type);
+ abstract double[] transform(double[] x, boolean type);
- /*
- * Check of preconditions.
- */
+ // Check of preconditions.
/**
- * {@link RealTransformer#transform(double[], TransformType)} should throw a
- * {@link MathIllegalArgumentException} if data size is invalid.
+ * {@link RealTransform#apply(double[])} should throw a
+ * {@link IllegalArgumentException} if data size is invalid.
*/
@Test
public void testTransformRealInvalidDataSize() {
- final TransformType[] type = TransformType.values();
- final RealTransformer transformer = createRealTransformer();
for (int i = 0; i < getNumberOfInvalidDataSizes(); i++) {
final int n = getInvalidDataSize(i);
- for (int j = 0; j < type.length; j++) {
+ for (boolean type : new boolean[] { true, false }) {
try {
- transformer.transform(createRealData(n), type[j]);
- Assert.fail(type[j] + ", " + n);
- } catch (MathIllegalArgumentException e) {
+ final RealTransform transformer = createRealTransformer(type);
+ transformer.apply(createRealData(n));
+ Assert.fail(type + ", " + n);
+ } catch (IllegalArgumentException e) {
// Expected: do nothing
}
}
@@ -161,24 +156,23 @@ public abstract class RealTransformerAbstractTest {
}
/**
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}
- * should throw a {@link MathIllegalArgumentException} if number of samples
- * is invalid.
+ * {@link RealTransformer#(DoubleUnaryOperator, double, double, int)}
+ * should throw {@link IllegalArgumentException} if number of samples is
+ * invalid.
*/
@Test
public void testTransformFunctionInvalidDataSize() {
- final TransformType[] type = TransformType.values();
- final RealTransformer transformer = createRealTransformer();
- final UnivariateFunction f = getValidFunction();
+ final DoubleUnaryOperator f = getValidFunction();
final double a = getValidLowerBound();
final double b = getValidUpperBound();
for (int i = 0; i < getNumberOfInvalidDataSizes(); i++) {
final int n = getInvalidDataSize(i);
- for (int j = 0; j < type.length; j++) {
+ for (boolean type : new boolean[] { true, false }) {
try {
- transformer.transform(f, a, b, n, type[j]);
- Assert.fail(type[j] + ", " + n);
- } catch (MathIllegalArgumentException e) {
+ final RealTransform transformer = createRealTransformer(type);
+ transformer.apply(f, a, b, n);
+ Assert.fail(type + ", " + n);
+ } catch (IllegalArgumentException e) {
// Expected: do nothing
}
}
@@ -186,24 +180,23 @@ public abstract class RealTransformerAbstractTest {
}
/**
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}
- * should throw a {@link NotStrictlyPositiveException} if number of samples
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int)}
+ * should throw {@link IllegalArgumentException} if number of samples
* is not strictly positive.
*/
@Test
public void testTransformFunctionNotStrictlyPositiveNumberOfSamples() {
- final TransformType[] type = TransformType.values();
- final RealTransformer transformer = createRealTransformer();
- final UnivariateFunction f = getValidFunction();
+ final DoubleUnaryOperator f = getValidFunction();
final double a = getValidLowerBound();
final double b = getValidUpperBound();
for (int i = 0; i < getNumberOfValidDataSizes(); i++) {
final int n = getValidDataSize(i);
- for (int j = 0; j < type.length; j++) {
+ for (boolean type : new boolean[] { true, false }) {
try {
- transformer.transform(f, a, b, -n, type[j]);
- Assert.fail(type[j] + ", " + (-n));
- } catch (NotStrictlyPositiveException e) {
+ final RealTransform transformer = createRealTransformer(type);
+ transformer.apply(f, a, b, -n);
+ Assert.fail(type + ", " + (-n));
+ } catch (IllegalArgumentException e) {
// Expected: do nothing
}
}
@@ -211,133 +204,124 @@ public abstract class RealTransformerAbstractTest {
}
/**
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}
- * should throw a {@link NumberIsTooLargeException} if sampling bounds are
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int)}
+ * should throw {@link IllegalArgumentException} if sampling bounds are
* not correctly ordered.
*/
@Test
public void testTransformFunctionInvalidBounds() {
- final TransformType[] type = TransformType.values();
- final RealTransformer transformer = createRealTransformer();
- final UnivariateFunction f = getValidFunction();
+ final DoubleUnaryOperator f = getValidFunction();
final double a = getValidLowerBound();
final double b = getValidUpperBound();
for (int i = 0; i < getNumberOfValidDataSizes(); i++) {
final int n = getValidDataSize(i);
- for (int j = 0; j < type.length; j++) {
+ for (boolean type : new boolean[] { true, false }) {
try {
- transformer.transform(f, b, a, n, type[j]);
- Assert.fail(type[j] + ", " + b + ", " + a);
- } catch (NumberIsTooLargeException e) {
+ final RealTransform transformer = createRealTransformer(type);
+ transformer.apply(f, b, a, n);
+ Assert.fail(type + ", " + b + ", " + a);
+ } catch (IllegalArgumentException e) {
// Expected: do nothing
}
}
}
}
- /*
- * Accuracy tests of transform of valid data.
- */
+ // Accuracy tests of transform of valid data.
/**
- * Accuracy check of {@link RealTransformer#transform(double[], TransformType)}.
+ * Accuracy check of {@link RealTransform#apply(double[])}.
* For each valid data size returned by
* {@link #getValidDataSize(int) getValidDataSize(i)},
* a random data array is generated with
* {@link #createRealData(int) createRealData(i)}. The actual
* transform is computed and compared to the expected transform, return by
- * {@link #transform(double[], TransformType)}. Actual and expected values
+ * {@link #transform(double[], boolean)}. Actual and expected values
* should be equal to within the relative error returned by
* {@link #getRelativeTolerance(int) getRelativeTolerance(i)}.
*/
@Test
public void testTransformReal() {
- final TransformType[] type = TransformType.values();
for (int i = 0; i < getNumberOfValidDataSizes(); i++) {
final int n = getValidDataSize(i);
final double tol = getRelativeTolerance(i);
- for (int j = 0; j < type.length; j++) {
- doTestTransformReal(n, tol, type[j]);
+ for (boolean type : new boolean[] { true, false }) {
+ doTestTransformReal(n, tol, type);
}
}
}
/**
* Accuracy check of
- * {@link RealTransformer#transform(UnivariateFunction, double, double, int, TransformType)}.
+ * {@link RealTransform#apply(DoubleUnaryOperator, double, double, int, TransformType)}.
* For each valid data size returned by
* {@link #getValidDataSize(int) getValidDataSize(i)},
* the {@link UnivariateFunction} returned by {@link #getValidFunction()} is
* sampled. The actual transform is computed and compared to the expected
- * transform, return by {@link #transform(double[], TransformType)}. Actual
+ * transform, return by {@link #transform(double[], boolean)}. Actual
* and expected values should be equal to within the relative error returned
* by {@link #getRelativeTolerance(int) getRelativeTolerance(i)}.
*/
@Test
public void testTransformFunction() {
- final TransformType[] type = TransformType.values();
for (int i = 0; i < getNumberOfValidDataSizes(); i++) {
final int n = getValidDataSize(i);
final double tol = getRelativeTolerance(i);
- for (int j = 0; j < type.length; j++) {
- doTestTransformFunction(n, tol, type[j]);
+ for (boolean type : new boolean[] { true, false }) {
+ doTestTransformFunction(n, tol, type);
}
}
}
- /*
- * Utility methods.
- */
+ // Utility methods.
/**
- * Returns a random array of doubles. Random generator always uses the same
- * seed.
+ * Returns a random array of doubles.
*
* @param n the size of the array to be returned
* @return a random array of specified size
*/
double[] createRealData(final int n) {
- final Random random = new Random(SEED);
final double[] data = new double[n];
for (int i = 0; i < n; i++) {
- data[i] = 2.0 * random.nextDouble() - 1.0;
+ data[i] = 2 * RNG.nextDouble() - 1;
}
return data;
}
- /*
- * The tests per se.
- */
+ // Actual tests.
- private void doTestTransformReal(final int n, final double tol,
- final TransformType type) {
- final RealTransformer transformer = createRealTransformer();
+ private void doTestTransformReal(final int n,
+ final double tol,
+ final boolean type) {
+ final RealTransform transformer = createRealTransformer(type);
final double[] x = createRealData(n);
final double[] expected = transform(x, type);
- final double[] actual = transformer.transform(x, type);
+ final double[] actual = transformer.apply(x);
for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i);
- final double delta = tol * FastMath.abs(expected[i]);
+ final double delta = tol * Math.abs(expected[i]);
Assert.assertEquals(msg, expected[i], actual[i], delta);
}
}
- private void doTestTransformFunction(final int n, final double tol,
- final TransformType type) {
- final RealTransformer transformer = createRealTransformer();
- final UnivariateFunction f = getValidFunction();
+ private void doTestTransformFunction(final int n,
+ final double tol,
+ final boolean type) {
+ final RealTransform transformer = createRealTransformer(type);
+ final DoubleUnaryOperator f = getValidFunction();
final double a = getValidLowerBound();
final double b = getValidUpperBound();
final double[] x = createRealData(n);
for (int i = 0; i < n; i++) {
final double t = a + i * (b - a) / n;
- x[i] = f.value(t);
+ x[i] = f.applyAsDouble(t);
}
final double[] expected = transform(x, type);
- final double[] actual = transformer.transform(f, a, b, n, type);
+ final double[] actual = transformer.apply(f, a, b, n);
for (int i = 0; i < n; i++) {
final String msg = String.format("%d, %d", n, i);
- final double delta = tol * FastMath.abs(expected[i]);
+ final double delta = tol * Math.abs(expected[i]);
Assert.assertEquals(msg, expected[i], actual[i], delta);
}
}
diff --git a/commons-math-transform/src/test/java/org/apache/commons/math4/transform/TransformUtilsTest.java b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/TransformUtilsTest.java
new file mode 100644
index 0000000..817ae69
--- /dev/null
+++ b/commons-math-transform/src/test/java/org/apache/commons/math4/transform/TransformUtilsTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.math4.transform;
+
+import java.util.function.DoubleUnaryOperator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.commons.math3.analysis.function.Sin;
+
+/**
+ * Tests for {@link TransformUtils}.
+ */
+public class TransformUtilsTest {
+ private static final Sin SIN_FUNCTION = new Sin();
+ private static final DoubleUnaryOperator SIN = (x) -> SIN_FUNCTION.value(x);
+
+ @Test(expected = TransformException.class)
+ public void testSampleWrongBounds(){
+ TransformUtils.sample(SIN, Math.PI, 0.0, 10);
+ }
+
+ @Test(expected = TransformException.class)
+ public void testSampleNegativeNumberOfPoints(){
+ TransformUtils.sample(SIN, 0.0, Math.PI, -1);
+ }
+
+ @Test(expected = TransformException.class)
+ public void testSampleNullNumberOfPoints(){
+ TransformUtils.sample(SIN, 0.0, Math.PI, 0);
+ }
+
+ @Test
+ public void testSample() {
+ final int n = 11;
+ final double min = 0.0;
+ final double max = Math.PI;
+ final double[] actual = TransformUtils.sample(SIN, min, max, n);
+ for (int i = 0; i < n; i++) {
+ final double x = min + (max - min) / n * i;
+ Assert.assertEquals("x = " + x, Math.sin(x), actual[i], 1e-15);
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
index e8c4149..134c52b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -107,6 +107,7 @@
<modules>
<!-- Modules that do not depend on "legacy" codes. -->
<module>commons-math-neuralnet</module>
+ <module>commons-math-transform</module>
<!-- Non-modularized functionalities. -->
<module>commons-math-legacy</module>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a9f80b2..2019541 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible trailing spaces!
</release>
<release version="4.0" date="XXXX-XX-XX" description="">
+ <action dev="erans" type="update" issue="MATH-1582">
+ Transforms codes moved into a dedicated maven module.
+ </action>
<action dev="erans" type="update" issue="MATH-1578">
ANN codes moved into a dedicated maven module.
</action>