diff --git a/.gitignore b/.gitignore index a6f89c2..a1c5b32 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -/target/ \ No newline at end of file +/target/ +/org/fairsim/extern/jtransforms/*.class +/external/*.jar +/*.jar +/org/fairsim/git-version-jtransforms.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..913d23c --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +# +# fairSIM JTransforms make file +# +JC = javac +JAR = jar + +# Options for the java compiler +EXTDIR="./external" + +JFLAGS = -g -Xlint:unchecked -Xlint:deprecation -extdirs ./external -d ./ +JFLAGS+= -target 1.6 -source 1.6 -bootclasspath ./external/rt-1.6.jar + +# remove command to clean up +RM = rm -vf + +.PHONY: all + +all: + $(JC) $(JFLAGS) org/fairsim/extern/jtransforms/*.java + + +# misc rules +git-version : + git rev-parse HEAD > org/fairsim/git-version-jtransforms.txt ; \ + git tag --contains >> org/fairsim/git-version-jtransforms.txt ; \ + echo "n/a" >> org/fairsim/git-version-jtransforms.txt + +jar: git-version + $(JAR) -cvf jtransforms_fairSIM_fork_$(shell head -c 10 org/fairsim/git-version-jtransforms.txt).jar \ + org/fairsim/extern/*/*.class \ + org/fairsim/git-version-jtransforms.txt + +doc: doc/index.html + +doc/index.html : $(wildcard org/fairsim/*/*.java) + javadoc -d doc/ -classpath ./ -extdirs ${EXTDIR} \ + -subpackages org.fairsim -exclude org.fairsim.extern.jtransforms + +clean : + $(RM) jtransforms_fairSIM_*.jar jtransforms_fairSIM_*.tar.bz2 + $(RM) org/fairsim/extern/jtransforms/*.class org/fairsim/git-version-jtransforms.txt + $(RM) -r doc/* + $(RM) -rf target + + diff --git a/external/get-dependencies.sh b/external/get-dependencies.sh new file mode 100755 index 0000000..a612e4c --- /dev/null +++ b/external/get-dependencies.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +fileMissing=0 + +# Get the ImageJ base library (in version 1.47, which is the lowest we currently support) +if [ ! -e ij147v.jar ] ; then + fileMissing=1 + wget https://imagej.nih.gov/ij/download/jars/ij147v.jar +fi + + +# This fetches the java 1.6 runtime, needed for backwards-compatible +# compilation to Java 6 with newer compilers +# unfortunately, Java 6's rt.jar does not seem to be on Maven, so +# fetch it by extracting it from Ubuntu's openjdk deb. +# Java 9 will make it much more easier with the "-release" option +if [ ! -e rt-1.6.jar ] ; then + fileMissing=1 + + mkdir tmp-rt-jar + cd tmp-rt-jar + + # download the 'openjdk-6-jre-headless' deb file + wget http://security.ubuntu.com/ubuntu/pool/universe/o/openjdk-6/openjdk-6-jre-headless_6b41-1.13.13-0ubuntu0.14.04.1_amd64.deb -O openjdk.deb + + + # extract the deb + echo "Extracting rt.jar from the .deb file" + echo "This might take a few moments... " + ar -x openjdk.deb + + # extract the rt.jar from the data.tar + tar -xf data.tar.xz ./usr/lib/jvm/java-6-openjdk-amd64/jre/lib/rt.jar + mv ./usr/lib/jvm/java-6-openjdk-amd64/jre/lib/rt.jar ../rt-1.6.jar + cd .. + + rm -rf tmp-rt-jar + echo "Done." + +fi + +if [ $fileMissing -eq 0 ] ; then + echo "All files found, fairSIM should compile" +fi + diff --git a/src/main/java/org/jtransforms/utils/CommonUtils.java b/org/fairsim/extern/jtransforms/CommonUtils.java similarity index 99% rename from src/main/java/org/jtransforms/utils/CommonUtils.java rename to org/fairsim/extern/jtransforms/CommonUtils.java index 799e480..fac67a2 100644 --- a/src/main/java/org/jtransforms/utils/CommonUtils.java +++ b/org/fairsim/extern/jtransforms/CommonUtils.java @@ -24,12 +24,18 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.utils; + +// Code modified for inclusion with fairSIM: +// - changed package name +// - Commented out all dependence on ...LargeArray +// - based on JTransforms 3.1, git ede249c9824262bd9b5f571e56f7a0fa596f6f20 + +package org.fairsim.extern.jtransforms; import java.util.concurrent.Future; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; -import pl.edu.icm.jlargearrays.LongLargeArray; +//import pl.edu.icm.jlargearrays.DoubleLargeArray; +//import pl.edu.icm.jlargearrays.FloatLargeArray; +//import pl.edu.icm.jlargearrays.LongLargeArray; /** * Static methods used internally in FFT and DCT code. @@ -78,7 +84,7 @@ public static void makeipt(int nw, int[] ip) m = m2; } } - +/* public static void makeipt(long nw, LongLargeArray ipl) { long j, l, m, m2, p, q; @@ -97,7 +103,7 @@ public static void makeipt(long nw, LongLargeArray ipl) m = m2; } } - +*/ public static void makewt(int nw, int[] ip, double[] w) { int j, nwh, nw0, nw1; @@ -163,6 +169,7 @@ public static void makewt(int nw, int[] ip, double[] w) } } +/* public static void makewt(long nw, LongLargeArray ipl, DoubleLargeArray wl) { long j, nwh, nw0, nw1; @@ -227,7 +234,7 @@ public static void makewt(long nw, LongLargeArray ipl, DoubleLargeArray wl) } } } - +*/ public static void makect(int nc, double[] c, int startc, int[] ip) { int j, nch; @@ -246,7 +253,7 @@ public static void makect(int nc, double[] c, int startc, int[] ip) } } } - +/* public static void makect(long nc, DoubleLargeArray c, long startc, LongLargeArray ipl) { long j, nch; @@ -265,7 +272,7 @@ public static void makect(long nc, DoubleLargeArray c, long startc, LongLargeArr } } } - +*/ public static void makect(int nc, float[] c, int startc, int[] ip) { int j, nch; @@ -284,7 +291,7 @@ public static void makect(int nc, float[] c, int startc, int[] ip) } } } - +/* public static void makect(long nc, FloatLargeArray c, long startc, LongLargeArray ipl) { long j, nch; @@ -303,7 +310,7 @@ public static void makect(long nc, FloatLargeArray c, long startc, LongLargeArra } } } - +*/ public static void makewt(int nw, int[] ip, float[] w) { int j, nwh, nw0, nw1; @@ -368,7 +375,7 @@ public static void makewt(int nw, int[] ip, float[] w) } } } - +/* public static void makewt(long nw, LongLargeArray ipl, FloatLargeArray wl) { long j, nwh, nw0, nw1; @@ -433,7 +440,7 @@ public static void makewt(long nw, LongLargeArray ipl, FloatLargeArray wl) } } } - +*/ public static void cftfsub(int n, double[] a, int offa, int[] ip, int nw, double[] w) { if (n > 8) { @@ -462,7 +469,7 @@ public static void cftfsub(int n, double[] a, int offa, int[] ip, int nw, double cftxb020(a, offa); } } - +/* public static void cftfsub(long n, DoubleLargeArray a, long offa, LongLargeArray ip, long nw, DoubleLargeArray w) { if (n > 8) { @@ -491,7 +498,7 @@ public static void cftfsub(long n, DoubleLargeArray a, long offa, LongLargeArray cftxb020(a, offa); } } - +*/ public static void cftbsub(int n, double[] a, int offa, int[] ip, int nw, double[] w) { if (n > 8) { @@ -520,7 +527,7 @@ public static void cftbsub(int n, double[] a, int offa, int[] ip, int nw, double cftxb020(a, offa); } } - +/* public static void cftbsub(long n, DoubleLargeArray a, long offa, LongLargeArray ip, long nw, DoubleLargeArray w) { if (n > 8) { @@ -549,7 +556,7 @@ public static void cftbsub(long n, DoubleLargeArray a, long offa, LongLargeArray cftxb020(a, offa); } } - +*/ public static void bitrv2(int n, int[] ip, double[] a, int offa) { int j1, k1, l, m, nh, nm; @@ -962,7 +969,7 @@ public static void bitrv2(int n, int[] ip, double[] a, int offa) } } } - +/* public static void bitrv2l(long n, LongLargeArray ip, DoubleLargeArray a, long offa) { long j1, k1, l, m, nh, nm; @@ -1375,7 +1382,7 @@ public static void bitrv2l(long n, LongLargeArray ip, DoubleLargeArray a, long o } } } - +*/ public static void bitrv2conj(int n, int[] ip, double[] a, int offa) { int j1, k1, l, m, nh, nm; @@ -1796,7 +1803,7 @@ public static void bitrv2conj(int n, int[] ip, double[] a, int offa) } } } - +/* public static void bitrv2conj(long n, LongLargeArray ip, DoubleLargeArray a, long offa) { long j1, k1, l, m, nh, nm; @@ -2217,7 +2224,7 @@ public static void bitrv2conj(long n, LongLargeArray ip, DoubleLargeArray a, lon } } } - +*/ public static void bitrv216(double[] a, int offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; @@ -2271,7 +2278,7 @@ public static void bitrv216(double[] a, int offa) a[offa + 28] = x7r; a[offa + 29] = x7i; } - +/* public static void bitrv216(DoubleLargeArray a, long offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; @@ -2325,7 +2332,7 @@ public static void bitrv216(DoubleLargeArray a, long offa) a.setDouble(offa + 28, x7r); a.setDouble(offa + 29, x7i); } - +*/ public static void bitrv216neg(double[] a, int offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; @@ -2391,7 +2398,7 @@ public static void bitrv216neg(double[] a, int offa) a[offa + 30] = x8r; a[offa + 31] = x8i; } - +/* public static void bitrv216neg(DoubleLargeArray a, long offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; @@ -2457,7 +2464,7 @@ public static void bitrv216neg(DoubleLargeArray a, long offa) a.setDouble(offa + 30, x8r); a.setDouble(offa + 31, x8i); } - +*/ public static void bitrv208(double[] a, int offa) { double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; @@ -2479,7 +2486,7 @@ public static void bitrv208(double[] a, int offa) a[offa + 12] = x3r; a[offa + 13] = x3i; } - +/* public static void bitrv208(DoubleLargeArray a, long offa) { double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; @@ -2501,7 +2508,7 @@ public static void bitrv208(DoubleLargeArray a, long offa) a.setDouble(offa + 12, x3r); a.setDouble(offa + 13, x3i); } - +*/ public static void bitrv208neg(double[] a, int offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; @@ -2535,7 +2542,7 @@ public static void bitrv208neg(double[] a, int offa) a[offa + 14] = x4r; a[offa + 15] = x4i; } - +/* public static void bitrv208neg(DoubleLargeArray a, long offa) { double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; @@ -2569,7 +2576,7 @@ public static void bitrv208neg(DoubleLargeArray a, long offa) a.setDouble(offa + 14, x4r); a.setDouble(offa + 15, x4i); } - +*/ public static void cftf1st(int n, double[] a, int offa, double[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -2788,7 +2795,7 @@ public static void cftf1st(int n, double[] a, int offa, double[] w, int startw) a[idx3 + 2] = wk3i * x0r + wk3r * x0i; a[idx3 + 3] = wk3i * x0i - wk3r * x0r; } - +/* public static void cftf1st(long n, DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -3007,7 +3014,7 @@ public static void cftf1st(long n, DoubleLargeArray a, long offa, DoubleLargeArr a.setDouble(idx3 + 2, wk3i * x0r + wk3r * x0i); a.setDouble(idx3 + 3, wk3i * x0i - wk3r * x0r); } - +*/ public static void cftb1st(int n, double[] a, int offa, double[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -3227,7 +3234,7 @@ public static void cftb1st(int n, double[] a, int offa, double[] w, int startw) a[idx3 + 2] = wk3i * x0r + wk3r * x0i; a[idx3 + 3] = wk3i * x0i - wk3r * x0r; } - +/* public static void cftb1st(long n, DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -3447,7 +3454,7 @@ public static void cftb1st(long n, DoubleLargeArray a, long offa, DoubleLargeArr a.setDouble(idx3 + 2, wk3i * x0r + wk3r * x0i); a.setDouble(idx3 + 3, wk3i * x0i - wk3r * x0r); } - +*/ public static void cftrec4_th(final int n, final double[] a, final int offa, final int nw, final double[] w) { int i; @@ -3515,7 +3522,7 @@ public void run() } ConcurrencyUtils.waitForCompletion(futures); } - +/* public static void cftrec4_th(final long n, final DoubleLargeArray a, final long offa, final long nw, final DoubleLargeArray w) { int i, idx = 0; @@ -3583,7 +3590,7 @@ public void run() } ConcurrencyUtils.waitForCompletion(futures); } - +*/ public static void cftrec4(int n, double[] a, int offa, int nw, double[] w) { int isplt, j, k, m; @@ -3603,7 +3610,7 @@ public static void cftrec4(int n, double[] a, int offa, int nw, double[] w) cftleaf(m, isplt, a, idx2 + j, nw, w); } } - +/* public static void cftrec4(long n, DoubleLargeArray a, long offa, long nw, DoubleLargeArray w) { long isplt, j, k, m; @@ -3623,7 +3630,7 @@ public static void cftrec4(long n, DoubleLargeArray a, long offa, long nw, Doubl cftleaf(m, isplt, a, idx2 + j, nw, w); } } - +*/ public static int cfttree(int n, int j, int k, double[] a, int offa, int nw, double[] w) { int i, isplt, m; @@ -3656,7 +3663,7 @@ public static int cfttree(int n, int j, int k, double[] a, int offa, int nw, dou } return isplt; } - +/* public static long cfttree(long n, long j, long k, DoubleLargeArray a, long offa, long nw, DoubleLargeArray w) { long i, isplt, m; @@ -3689,7 +3696,7 @@ public static long cfttree(long n, long j, long k, DoubleLargeArray a, long offa } return isplt; } - +*/ public static void cftleaf(int n, int isplt, double[] a, int offa, int nw, double[] w) { if (n == 512) { @@ -3746,7 +3753,7 @@ public static void cftleaf(int n, int isplt, double[] a, int offa, int nw, doubl cftf081(a, offa + 224, w, nw - 8); } } - +/* public static void cftleaf(long n, long isplt, DoubleLargeArray a, long offa, long nw, DoubleLargeArray w) { if (n == 512) { @@ -3803,7 +3810,7 @@ public static void cftleaf(long n, long isplt, DoubleLargeArray a, long offa, lo cftf081(a, offa + 224, w, nw - 8); } } - +*/ public static void cftmdl1(int n, double[] a, int offa, double[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -3929,7 +3936,7 @@ public static void cftmdl1(int n, double[] a, int offa, double[] w, int startw) a[idx3] = -wn4r * (x0r + x0i); a[idx3 + 1] = -wn4r * (x0i - x0r); } - +/* public static void cftmdl1(long n, DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -4055,7 +4062,7 @@ public static void cftmdl1(long n, DoubleLargeArray a, long offa, DoubleLargeArr a.setDouble(idx3, -wn4r * (x0r + x0i)); a.setDouble(idx3 + 1, -wn4r * (x0i - x0r)); } - +*/ public static void cftmdl2(int n, double[] a, int offa, double[] w, int startw) { int j0, j1, j2, j3, k, kr, m, mh; @@ -4206,7 +4213,7 @@ public static void cftmdl2(int n, double[] a, int offa, double[] w, int startw) a[idx3] = y0r + y2r; a[idx3 + 1] = y0i + y2i; } - +/* public static void cftmdl2(long n, DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { long j0, j1, j2, j3, k, kr, m, mh; @@ -4357,7 +4364,7 @@ public static void cftmdl2(long n, DoubleLargeArray a, long offa, DoubleLargeArr a.setDouble(idx3, y0r + y2r); a.setDouble(idx3 + 1, y0i + y2i); } - +*/ public static void cftfx41(int n, double[] a, int offa, int nw, double[] w) { if (n == 128) { @@ -4372,7 +4379,7 @@ public static void cftfx41(int n, double[] a, int offa, int nw, double[] w) cftf081(a, offa + 48, w, nw - 8); } } - +/* public static void cftfx41(long n, DoubleLargeArray a, long offa, long nw, DoubleLargeArray w) { if (n == 128) { @@ -4387,7 +4394,7 @@ public static void cftfx41(long n, DoubleLargeArray a, long offa, long nw, Doubl cftf081(a, offa + 48, w, nw - 8); } } - +*/ public static void cftf161(double[] a, int offa, double[] w, int startw) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -4541,7 +4548,7 @@ public static void cftf161(double[] a, int offa, double[] w, int startw) a[offa + 6] = x1r + x3i; a[offa + 7] = x1i - x3r; } - +/* public static void cftf161(DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -4695,7 +4702,7 @@ public static void cftf161(DoubleLargeArray a, long offa, DoubleLargeArray w, lo a.setDouble(offa + 6, x1r + x3i); a.setDouble(offa + 7, x1i - x3r); } - +*/ public static void cftf162(double[] a, int offa, double[] w, int startw) { double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -4872,7 +4879,7 @@ public static void cftf162(double[] a, int offa, double[] w, int startw) a[offa + 30] = x1r + x2i; a[offa + 31] = x1i - x2r; } - +/* public static void cftf162(DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -5049,7 +5056,7 @@ public static void cftf162(DoubleLargeArray a, long offa, DoubleLargeArray w, lo a.setDouble(offa + 30, x1r + x2i); a.setDouble(offa + 31, x1i - x2r); } - +*/ public static void cftf081(double[] a, int offa, double[] w, int startw) { double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -5108,7 +5115,7 @@ public static void cftf081(double[] a, int offa, double[] w, int startw) a[offa + 6] = y2r + y6i; a[offa + 7] = y2i - y6r; } - +/* public static void cftf081(DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -5167,7 +5174,7 @@ public static void cftf081(DoubleLargeArray a, long offa, DoubleLargeArray w, lo a.setDouble(offa + 6, y2r + y6i); a.setDouble(offa + 7, y2i - y6r); } - +*/ public static void cftf082(double[] a, int offa, double[] w, int startw) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -5236,7 +5243,7 @@ public static void cftf082(double[] a, int offa, double[] w, int startw) a[offa + 14] = x0r + x1i; a[offa + 15] = x0i - x1r; } - +/* public static void cftf082(DoubleLargeArray a, long offa, DoubleLargeArray w, long startw) { double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -5305,7 +5312,7 @@ public static void cftf082(DoubleLargeArray a, long offa, DoubleLargeArray w, lo a.setDouble(offa + 14, x0r + x1i); a.setDouble(offa + 15, x0i - x1r); } - +*/ public static void cftf040(double[] a, int offa) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -5327,7 +5334,7 @@ public static void cftf040(double[] a, int offa) a[offa + 6] = x1r + x3i; a[offa + 7] = x1i - x3r; } - +/* public static void cftf040(DoubleLargeArray a, long offa) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -5349,7 +5356,7 @@ public static void cftf040(DoubleLargeArray a, long offa) a.setDouble(offa + 6, x1r + x3i); a.setDouble(offa + 7, x1i - x3r); } - +*/ public static void cftb040(double[] a, int offa) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -5371,7 +5378,7 @@ public static void cftb040(double[] a, int offa) a[offa + 6] = x1r - x3i; a[offa + 7] = x1i + x3r; } - +/* public static void cftb040(DoubleLargeArray a, long offa) { double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -5393,7 +5400,7 @@ public static void cftb040(DoubleLargeArray a, long offa) a.setDouble(offa + 6, x1r - x3i); a.setDouble(offa + 7, x1i + x3r); } - +*/ public static void cftx020(double[] a, int offa) { double x0r, x0i; @@ -5404,7 +5411,7 @@ public static void cftx020(double[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftx020(DoubleLargeArray a, long offa) { double x0r, x0i; @@ -5415,7 +5422,7 @@ public static void cftx020(DoubleLargeArray a, long offa) a.setDouble(offa + 2, x0r); a.setDouble(offa + 3, x0i); } - +*/ public static void cftxb020(double[] a, int offa) { double x0r, x0i; @@ -5427,7 +5434,7 @@ public static void cftxb020(double[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftxb020(DoubleLargeArray a, long offa) { double x0r, x0i; @@ -5439,7 +5446,7 @@ public static void cftxb020(DoubleLargeArray a, long offa) a.setDouble(offa + 2, x0r); a.setDouble(offa + 3, x0i); } - +*/ public static void cftxc020(double[] a, int offa) { double x0r, x0i; @@ -5450,7 +5457,7 @@ public static void cftxc020(double[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftxc020(DoubleLargeArray a, long offa) { double x0r, x0i; @@ -5461,7 +5468,7 @@ public static void cftxc020(DoubleLargeArray a, long offa) a.setDouble(offa + 2, x0r); a.setDouble(offa + 3, x0i); } - +*/ public static void rftfsub(int n, double[] a, int offa, int nc, double[] c, int startc) { int k, kk, ks, m; @@ -5489,7 +5496,7 @@ public static void rftfsub(int n, double[] a, int offa, int nc, double[] c, int } a[offa + m + 1] = -a[offa + m + 1]; } - +/* public static void rftfsub(long n, DoubleLargeArray a, long offa, long nc, DoubleLargeArray c, long startc) { long k, kk, ks, m; @@ -5517,7 +5524,7 @@ public static void rftfsub(long n, DoubleLargeArray a, long offa, long nc, Doubl } a.setDouble(offa + m + 1, -a.getDouble(offa + m + 1)); } - +*/ public static void rftbsub(int n, double[] a, int offa, int nc, double[] c, int startc) { int k, kk, ks, m; @@ -5544,7 +5551,7 @@ public static void rftbsub(int n, double[] a, int offa, int nc, double[] c, int a[idx2 + 1] -= yi; } } - +/* public static void rftbsub(long n, DoubleLargeArray a, long offa, long nc, DoubleLargeArray c, long startc) { long k, kk, ks, m; @@ -5571,7 +5578,7 @@ public static void rftbsub(long n, DoubleLargeArray a, long offa, long nc, Doubl a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - yi); } } - +*/ public static void dctsub(int n, double[] a, int offa, int nc, double[] c, int startc) { int k, kk, ks, m; @@ -5595,7 +5602,7 @@ public static void dctsub(int n, double[] a, int offa, int nc, double[] c, int s } a[offa + m] *= c[startc]; } - +/* public static void dctsub(long n, DoubleLargeArray a, long offa, long nc, DoubleLargeArray c, long startc) { long k, kk, ks, m; @@ -5619,7 +5626,7 @@ public static void dctsub(long n, DoubleLargeArray a, long offa, long nc, Double } a.setDouble(offa + m, a.getDouble(offa + m) * c.getDouble(startc)); } - +*/ public static void cftfsub(int n, float[] a, int offa, int[] ip, int nw, float[] w) { if (n > 8) { @@ -5648,7 +5655,7 @@ public static void cftfsub(int n, float[] a, int offa, int[] ip, int nw, float[] cftxb020(a, offa); } } - +/* public static void cftfsub(long n, FloatLargeArray a, long offa, LongLargeArray ip, long nw, FloatLargeArray w) { if (n > 8) { @@ -5677,7 +5684,7 @@ public static void cftfsub(long n, FloatLargeArray a, long offa, LongLargeArray cftxb020(a, offa); } } - +*/ public static void cftbsub(int n, float[] a, int offa, int[] ip, int nw, float[] w) { if (n > 8) { @@ -5706,7 +5713,7 @@ public static void cftbsub(int n, float[] a, int offa, int[] ip, int nw, float[] cftxb020(a, offa); } } - +/* public static void cftbsub(long n, FloatLargeArray a, long offa, LongLargeArray ip, long nw, FloatLargeArray w) { if (n > 8) { @@ -5735,7 +5742,7 @@ public static void cftbsub(long n, FloatLargeArray a, long offa, LongLargeArray cftxb020(a, offa); } } - +*/ public static void bitrv2(int n, int[] ip, float[] a, int offa) { int j1, k1, l, m, nh, nm; @@ -6148,7 +6155,7 @@ public static void bitrv2(int n, int[] ip, float[] a, int offa) } } } - +/* public static void bitrv2l(long n, LongLargeArray ip, FloatLargeArray a, long offa) { long j1, k1, l, m, nh, nm; @@ -6561,7 +6568,7 @@ public static void bitrv2l(long n, LongLargeArray ip, FloatLargeArray a, long of } } } - +*/ public static void bitrv2conj(int n, int[] ip, float[] a, int offa) { int j1, k1, l, m, nh, nm; @@ -6982,7 +6989,7 @@ public static void bitrv2conj(int n, int[] ip, float[] a, int offa) } } } - +/* public static void bitrv2conj(long n, LongLargeArray ip, FloatLargeArray a, long offa) { long j1, k1, l, m, nh, nm; @@ -7403,7 +7410,7 @@ public static void bitrv2conj(long n, LongLargeArray ip, FloatLargeArray a, long } } } - +*/ public static void bitrv216(float[] a, int offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; @@ -7457,7 +7464,7 @@ public static void bitrv216(float[] a, int offa) a[offa + 28] = x7r; a[offa + 29] = x7i; } - +/* public static void bitrv216(FloatLargeArray a, long offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i; @@ -7511,7 +7518,7 @@ public static void bitrv216(FloatLargeArray a, long offa) a.setFloat(offa + 28, x7r); a.setFloat(offa + 29, x7i); } - +*/ public static void bitrv216neg(float[] a, int offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; @@ -7577,7 +7584,7 @@ public static void bitrv216neg(float[] a, int offa) a[offa + 30] = x8r; a[offa + 31] = x8i; } - +/* public static void bitrv216neg(FloatLargeArray a, long offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i, x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i, x15r, x15i; @@ -7643,7 +7650,7 @@ public static void bitrv216neg(FloatLargeArray a, long offa) a.setFloat(offa + 30, x8r); a.setFloat(offa + 31, x8i); } - +*/ public static void bitrv208(float[] a, int offa) { float x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; @@ -7665,7 +7672,7 @@ public static void bitrv208(float[] a, int offa) a[offa + 12] = x3r; a[offa + 13] = x3i; } - +/* public static void bitrv208(FloatLargeArray a, long offa) { float x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i; @@ -7687,7 +7694,7 @@ public static void bitrv208(FloatLargeArray a, long offa) a.setFloat(offa + 12, x3r); a.setFloat(offa + 13, x3i); } - +*/ public static void bitrv208neg(float[] a, int offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; @@ -7721,7 +7728,7 @@ public static void bitrv208neg(float[] a, int offa) a[offa + 14] = x4r; a[offa + 15] = x4i; } - +/* public static void bitrv208neg(FloatLargeArray a, long offa) { float x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i; @@ -7755,7 +7762,7 @@ public static void bitrv208neg(FloatLargeArray a, long offa) a.setFloat(offa + 14, x4r); a.setFloat(offa + 15, x4i); } - +*/ public static void cftf1st(int n, float[] a, int offa, float[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -7974,7 +7981,7 @@ public static void cftf1st(int n, float[] a, int offa, float[] w, int startw) a[idx3 + 2] = wk3i * x0r + wk3r * x0i; a[idx3 + 3] = wk3i * x0i - wk3r * x0r; } - +/* public static void cftf1st(long n, FloatLargeArray a, long offa, FloatLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -8193,7 +8200,7 @@ public static void cftf1st(long n, FloatLargeArray a, long offa, FloatLargeArray a.setFloat(idx3 + 2, wk3i * x0r + wk3r * x0i); a.setFloat(idx3 + 3, wk3i * x0i - wk3r * x0r); } - +*/ public static void cftb1st(int n, float[] a, int offa, float[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -8413,7 +8420,7 @@ public static void cftb1st(int n, float[] a, int offa, float[] w, int startw) a[idx3 + 2] = wk3i * x0r + wk3r * x0i; a[idx3 + 3] = wk3i * x0i - wk3r * x0r; } - +/* public static void cftb1st(long n, FloatLargeArray a, long offa, FloatLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -8633,7 +8640,7 @@ public static void cftb1st(long n, FloatLargeArray a, long offa, FloatLargeArray a.setFloat(idx3 + 2, wk3i * x0r + wk3r * x0i); a.setFloat(idx3 + 3, wk3i * x0i - wk3r * x0r); } - +*/ public static void cftrec4_th(final int n, final float[] a, final int offa, final int nw, final float[] w) { int i; @@ -8701,7 +8708,7 @@ public void run() } ConcurrencyUtils.waitForCompletion(futures); } - +/* public static void cftrec4_th(final long n, final FloatLargeArray a, final long offa, final long nw, final FloatLargeArray w) { int i, idx = 0; @@ -8769,7 +8776,7 @@ public void run() } ConcurrencyUtils.waitForCompletion(futures); } - +*/ public static void cftrec4(int n, float[] a, int offa, int nw, float[] w) { int isplt, j, k, m; @@ -8789,7 +8796,7 @@ public static void cftrec4(int n, float[] a, int offa, int nw, float[] w) cftleaf(m, isplt, a, idx2 + j, nw, w); } } - +/* public static void cftrec4(long n, FloatLargeArray a, long offa, long nw, FloatLargeArray w) { long isplt, j, k, m; @@ -8809,7 +8816,7 @@ public static void cftrec4(long n, FloatLargeArray a, long offa, long nw, FloatL cftleaf(m, isplt, a, idx2 + j, nw, w); } } - +*/ public static int cfttree(int n, int j, int k, float[] a, int offa, int nw, float[] w) { int i, isplt, m; @@ -8842,7 +8849,7 @@ public static int cfttree(int n, int j, int k, float[] a, int offa, int nw, floa } return isplt; } - +/* public static long cfttree(long n, long j, long k, FloatLargeArray a, long offa, long nw, FloatLargeArray w) { long i, isplt, m; @@ -8875,7 +8882,7 @@ public static long cfttree(long n, long j, long k, FloatLargeArray a, long offa, } return isplt; } - +*/ public static void cftleaf(int n, int isplt, float[] a, int offa, int nw, float[] w) { if (n == 512) { @@ -8932,7 +8939,7 @@ public static void cftleaf(int n, int isplt, float[] a, int offa, int nw, float[ cftf081(a, offa + 224, w, nw - 8); } } - +/* public static void cftleaf(long n, long isplt, FloatLargeArray a, long offa, long nw, FloatLargeArray w) { if (n == 512) { @@ -8989,7 +8996,7 @@ public static void cftleaf(long n, long isplt, FloatLargeArray a, long offa, lon cftf081(a, offa + 224, w, nw - 8); } } - +*/ public static void cftmdl1(int n, float[] a, int offa, float[] w, int startw) { int j0, j1, j2, j3, k, m, mh; @@ -9115,7 +9122,7 @@ public static void cftmdl1(int n, float[] a, int offa, float[] w, int startw) a[idx3] = -wn4r * (x0r + x0i); a[idx3 + 1] = -wn4r * (x0i - x0r); } - +/* public static void cftmdl1(long n, FloatLargeArray a, long offa, FloatLargeArray w, long startw) { long j0, j1, j2, j3, k, m, mh; @@ -9241,7 +9248,7 @@ public static void cftmdl1(long n, FloatLargeArray a, long offa, FloatLargeArray a.setFloat(idx3, -wn4r * (x0r + x0i)); a.setFloat(idx3 + 1, -wn4r * (x0i - x0r)); } - +*/ public static void cftmdl2(int n, float[] a, int offa, float[] w, int startw) { int j0, j1, j2, j3, k, kr, m, mh; @@ -9392,7 +9399,7 @@ public static void cftmdl2(int n, float[] a, int offa, float[] w, int startw) a[idx3] = y0r + y2r; a[idx3 + 1] = y0i + y2i; } - +/* public static void cftmdl2(long n, FloatLargeArray a, long offa, FloatLargeArray w, long startw) { long j0, j1, j2, j3, k, kr, m, mh; @@ -9543,7 +9550,7 @@ public static void cftmdl2(long n, FloatLargeArray a, long offa, FloatLargeArray a.setFloat(idx3, y0r + y2r); a.setFloat(idx3 + 1, y0i + y2i); } - +*/ public static void cftfx41(int n, float[] a, int offa, int nw, float[] w) { if (n == 128) { @@ -9558,7 +9565,7 @@ public static void cftfx41(int n, float[] a, int offa, int nw, float[] w) cftf081(a, offa + 48, w, nw - 8); } } - +/* public static void cftfx41(long n, FloatLargeArray a, long offa, long nw, FloatLargeArray w) { if (n == 128) { @@ -9573,7 +9580,7 @@ public static void cftfx41(long n, FloatLargeArray a, long offa, long nw, FloatL cftf081(a, offa + 48, w, nw - 8); } } - +*/ public static void cftf161(float[] a, int offa, float[] w, int startw) { float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -9727,7 +9734,7 @@ public static void cftf161(float[] a, int offa, float[] w, int startw) a[offa + 6] = x1r + x3i; a[offa + 7] = x1i - x3r; } - +/* public static void cftf161(FloatLargeArray a, long offa, FloatLargeArray w, long startw) { float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -9881,7 +9888,7 @@ public static void cftf161(FloatLargeArray a, long offa, FloatLargeArray w, long a.setFloat(offa + 6, x1r + x3i); a.setFloat(offa + 7, x1i - x3r); } - +*/ public static void cftf162(float[] a, int offa, float[] w, int startw) { float wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -10058,7 +10065,7 @@ public static void cftf162(float[] a, int offa, float[] w, int startw) a[offa + 30] = x1r + x2i; a[offa + 31] = x1i - x2r; } - +/* public static void cftf162(FloatLargeArray a, long offa, FloatLargeArray w, long startw) { float wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i, x0r, x0i, x1r, x1i, x2r, x2i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i, y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i, y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i; @@ -10235,7 +10242,7 @@ public static void cftf162(FloatLargeArray a, long offa, FloatLargeArray w, long a.setFloat(offa + 30, x1r + x2i); a.setFloat(offa + 31, x1i - x2r); } - +*/ public static void cftf081(float[] a, int offa, float[] w, int startw) { float wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -10294,7 +10301,7 @@ public static void cftf081(float[] a, int offa, float[] w, int startw) a[offa + 6] = y2r + y6i; a[offa + 7] = y2i - y6r; } - +/* public static void cftf081(FloatLargeArray a, long offa, FloatLargeArray w, long startw) { float wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -10353,7 +10360,7 @@ public static void cftf081(FloatLargeArray a, long offa, FloatLargeArray w, long a.setFloat(offa + 6, y2r + y6i); a.setFloat(offa + 7, y2i - y6r); } - +*/ public static void cftf082(float[] a, int offa, float[] w, int startw) { float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -10422,7 +10429,7 @@ public static void cftf082(float[] a, int offa, float[] w, int startw) a[offa + 14] = x0r + x1i; a[offa + 15] = x0i - x1r; } - +/* public static void cftf082(FloatLargeArray a, long offa, FloatLargeArray w, long startw) { float wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i, y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i, y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i; @@ -10491,7 +10498,7 @@ public static void cftf082(FloatLargeArray a, long offa, FloatLargeArray w, long a.setFloat(offa + 14, x0r + x1i); a.setFloat(offa + 15, x0i - x1r); } - +*/ public static void cftf040(float[] a, int offa) { float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -10513,7 +10520,7 @@ public static void cftf040(float[] a, int offa) a[offa + 6] = x1r + x3i; a[offa + 7] = x1i - x3r; } - +/* public static void cftf040(FloatLargeArray a, long offa) { float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -10535,7 +10542,7 @@ public static void cftf040(FloatLargeArray a, long offa) a.setFloat(offa + 6, x1r + x3i); a.setFloat(offa + 7, x1i - x3r); } - +*/ public static void cftb040(float[] a, int offa) { float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -10557,7 +10564,7 @@ public static void cftb040(float[] a, int offa) a[offa + 6] = x1r - x3i; a[offa + 7] = x1i + x3r; } - +/* public static void cftb040(FloatLargeArray a, long offa) { float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; @@ -10579,7 +10586,7 @@ public static void cftb040(FloatLargeArray a, long offa) a.setFloat(offa + 6, x1r - x3i); a.setFloat(offa + 7, x1i + x3r); } - +*/ public static void cftx020(float[] a, int offa) { float x0r, x0i; @@ -10590,7 +10597,7 @@ public static void cftx020(float[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftx020(FloatLargeArray a, long offa) { float x0r, x0i; @@ -10601,7 +10608,7 @@ public static void cftx020(FloatLargeArray a, long offa) a.setFloat(offa + 2, x0r); a.setFloat(offa + 3, x0i); } - +*/ public static void cftxb020(float[] a, int offa) { float x0r, x0i; @@ -10613,7 +10620,7 @@ public static void cftxb020(float[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftxb020(FloatLargeArray a, long offa) { float x0r, x0i; @@ -10625,7 +10632,7 @@ public static void cftxb020(FloatLargeArray a, long offa) a.setFloat(offa + 2, x0r); a.setFloat(offa + 3, x0i); } - +*/ public static void cftxc020(float[] a, int offa) { float x0r, x0i; @@ -10636,7 +10643,7 @@ public static void cftxc020(float[] a, int offa) a[offa + 2] = x0r; a[offa + 3] = x0i; } - +/* public static void cftxc020(FloatLargeArray a, long offa) { float x0r, x0i; @@ -10647,7 +10654,7 @@ public static void cftxc020(FloatLargeArray a, long offa) a.setFloat(offa + 2, x0r); a.setFloat(offa + 3, x0i); } - +*/ public static void rftfsub(int n, float[] a, int offa, int nc, float[] c, int startc) { int k, kk, ks, m; @@ -10675,7 +10682,7 @@ public static void rftfsub(int n, float[] a, int offa, int nc, float[] c, int st } a[offa + m + 1] = -a[offa + m + 1]; } - +/* public static void rftfsub(long n, FloatLargeArray a, long offa, long nc, FloatLargeArray c, long startc) { long k, kk, ks, m; @@ -10703,7 +10710,7 @@ public static void rftfsub(long n, FloatLargeArray a, long offa, long nc, FloatL } a.setFloat(offa + m + 1, -a.getFloat(offa + m + 1)); } - +*/ public static void rftbsub(int n, float[] a, int offa, int nc, float[] c, int startc) { int k, kk, ks, m; @@ -10730,7 +10737,7 @@ public static void rftbsub(int n, float[] a, int offa, int nc, float[] c, int st a[idx2 + 1] -= yi; } } - +/* public static void rftbsub(long n, FloatLargeArray a, long offa, long nc, FloatLargeArray c, long startc) { long k, kk, ks, m; @@ -10757,7 +10764,7 @@ public static void rftbsub(long n, FloatLargeArray a, long offa, long nc, FloatL a.setFloat(idx2 + 1, a.getFloat(idx2 + 1) - yi); } } - +*/ public static void dctsub(int n, float[] a, int offa, int nc, float[] c, int startc) { int k, kk, ks, m; @@ -10781,7 +10788,7 @@ public static void dctsub(int n, float[] a, int offa, int nc, float[] c, int sta } a[offa + m] *= c[startc]; } - +/* public static void dctsub(long n, FloatLargeArray a, long offa, long nc, FloatLargeArray c, long startc) { long k, kk, ks, m; @@ -10805,7 +10812,7 @@ public static void dctsub(long n, FloatLargeArray a, long offa, long nc, FloatLa } a.setFloat(offa + m, a.getFloat(offa + m) * c.getFloat(startc)); } - +*/ public static void scale(final int n, final double m, final double[] a, final int offa, boolean complex) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -10842,7 +10849,7 @@ public void run() } } } - +/* public static void scale(final long nl, final double m, final DoubleLargeArray a, long offa, boolean complex) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -10877,7 +10884,7 @@ public void run() } } - +*/ public static void scale(final int n, final float m, final float[] a, final int offa, boolean complex) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -10914,7 +10921,7 @@ public void run() } } } - +/* public static void scale(final long nl, final float m, final FloatLargeArray a, long offa, boolean complex) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -10949,5 +10956,5 @@ public void run() } } - +*/ } diff --git a/src/main/java/org/jtransforms/utils/ConcurrencyUtils.java b/org/fairsim/extern/jtransforms/ConcurrencyUtils.java similarity index 96% rename from src/main/java/org/jtransforms/utils/ConcurrencyUtils.java rename to org/fairsim/extern/jtransforms/ConcurrencyUtils.java index 920be80..adcf934 100644 --- a/src/main/java/org/jtransforms/utils/ConcurrencyUtils.java +++ b/org/fairsim/extern/jtransforms/ConcurrencyUtils.java @@ -1,444 +1,448 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.utils; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -/** - * Concurrency utilities. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class ConcurrencyUtils -{ - - /** - * Thread pool. - */ - private static ExecutorService THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler())); - - private static long THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; - - private static long THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; - - private static long THREADS_BEGIN_N_2D = 65536; - - private static long LARGE_ARAYS_BEGIN_N = (1 << 28); - - private static long THREADS_BEGIN_N_3D = 65536; - - private static int NTHREADS = prevPow2(getNumberOfProcessors()); - - private ConcurrencyUtils() - { - - } - - private static class CustomExceptionHandler implements Thread.UncaughtExceptionHandler - { - - public void uncaughtException(Thread t, Throwable e) - { - e.printStackTrace(); - } - - } - - private static class CustomThreadFactory implements ThreadFactory - { - - private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); - - private final Thread.UncaughtExceptionHandler handler; - - CustomThreadFactory(Thread.UncaughtExceptionHandler handler) - { - this.handler = handler; - } - - public Thread newThread(Runnable r) - { - Thread t = defaultFactory.newThread(r); - t.setUncaughtExceptionHandler(handler); - return t; - } - }; - - /** - * Returns the number of available processors. - * - * @return number of available processors - */ - public static int getNumberOfProcessors() - { - return Runtime.getRuntime().availableProcessors(); - } - - /** - * Returns the current number of threads. - * - * @return the current number of threads. - */ - public static int getNumberOfThreads() - { - return NTHREADS; - } - - /** - * Sets the number of threads. If n is not a power-of-two number, then the - * number of threads is set to the closest power-of-two number less than n. - * - * @param n number of threads - */ - public static void setNumberOfThreads(int n) - { - NTHREADS = prevPow2(n); - } - - /** - * Returns the minimal size of 1D data for which two threads are used. - * - * @return the minimal size of 1D data for which two threads are used - */ - public static long getThreadsBeginN_1D_FFT_2Threads() - { - return THREADS_BEGIN_N_1D_FFT_2THREADS; - } - - /** - * Returns the minimal size of 1D data for which four threads are used. - * - * @return the minimal size of 1D data for which four threads are used - */ - public static long getThreadsBeginN_1D_FFT_4Threads() - { - return THREADS_BEGIN_N_1D_FFT_4THREADS; - } - - /** - * Returns the minimal size of 2D data for which threads are used. - * - * @return the minimal size of 2D data for which threads are used - */ - public static long getThreadsBeginN_2D() - { - return THREADS_BEGIN_N_2D; - } - - /** - * Returns the minimal size of 3D data for which threads are used. - * - * @return the minimal size of 3D data for which threads are used - */ - public static long getThreadsBeginN_3D() - { - return THREADS_BEGIN_N_3D; - } - - /** - * Returns the minimal size for which JLargeArrays are used. - * - * @return the minimal size for which JLargeArrays are used - */ - public static long getLargeArraysBeginN() - { - return LARGE_ARAYS_BEGIN_N; - } - - /** - * Sets the minimal size of 1D data for which two threads are used. - * - * @param n the minimal size of 1D data for which two threads are used - */ - public static void setThreadsBeginN_1D_FFT_2Threads(long n) - { - if (n < 1024) { - THREADS_BEGIN_N_1D_FFT_2THREADS = 1024; - } else { - THREADS_BEGIN_N_1D_FFT_2THREADS = n; - } - } - - /** - * Sets the minimal size of 1D data for which four threads are used. - * - * @param n the minimal size of 1D data for which four threads are used - */ - public static void setThreadsBeginN_1D_FFT_4Threads(long n) - { - if (n < 1024) { - THREADS_BEGIN_N_1D_FFT_4THREADS = 1024; - } else { - THREADS_BEGIN_N_1D_FFT_4THREADS = n; - } - } - - /** - * Sets the minimal size of 2D data for which threads are used. - * - * @param n the minimal size of 2D data for which threads are used - */ - public static void setThreadsBeginN_2D(long n) - { - if (n < 4096) { - THREADS_BEGIN_N_2D = 4096; - } else { - THREADS_BEGIN_N_2D = n; - } - } - - /** - * Sets the minimal size of 3D data for which threads are used. - * - * @param n the minimal size of 3D data for which threads are used - */ - public static void setThreadsBeginN_3D(long n) - { - THREADS_BEGIN_N_3D = n; - } - - /** - * Resets the minimal size of 1D data for which two and four threads are - * used. - */ - public static void resetThreadsBeginN_FFT() - { - THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; - THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; - } - - /** - * Resets the minimal size of 2D and 3D data for which threads are used. - */ - public static void resetThreadsBeginN() - { - THREADS_BEGIN_N_2D = 65536; - THREADS_BEGIN_N_3D = 65536; - } - - /** - * Sets the minimal size for which JLargeArrays are used. - * - * @param n the maximal size for which JLargeArrays are used - */ - public static void setLargeArraysBeginN(long n) - { - if (n < 1) { - LARGE_ARAYS_BEGIN_N = 1; - } else if (n > (1 << 28)) { - LARGE_ARAYS_BEGIN_N = (1 << 28); - } else { - LARGE_ARAYS_BEGIN_N = n; - } - } - - /** - * Returns the closest power-of-two number greater than or equal to x. - * - * @param x input value - * - * @return the closest power-of-two number greater than or equal to x - */ - public static int nextPow2(int x) - { - if (x < 1) { - throw new IllegalArgumentException("x must be greater or equal 1"); - } - if ((x & (x - 1)) == 0) { - return x; // x is already a power-of-two number - } - x |= (x >>> 1); - x |= (x >>> 2); - x |= (x >>> 4); - x |= (x >>> 8); - x |= (x >>> 16); - return x + 1; - } - - /** - * Returns the closest power-of-two number greater than or equal to x. - * - * @param x input value - * - * @return the closest power-of-two number greater than or equal to x - */ - public static long nextPow2(long x) - { - if (x < 1) { - throw new IllegalArgumentException("x must be greater or equal 1"); - } - if ((x & (x - 1l)) == 0) { - return x; // x is already a power-of-two number - } - x |= (x >>> 1l); - x |= (x >>> 2l); - x |= (x >>> 4l); - x |= (x >>> 8l); - x |= (x >>> 16l); - x |= (x >>> 32l); - return x + 1l; - } - - /** - * Returns the closest power-of-two number less than or equal to x. - * - * @param x input value - * - * @return the closest power-of-two number less then or equal to x - */ - public static int prevPow2(int x) - { - if (x < 1) { - throw new IllegalArgumentException("x must be greater or equal 1"); - } - return (int) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); - } - - /** - * Returns the closest power-of-two number less than or equal to x. - * - * @param x input value - * - * @return the closest power-of-two number less then or equal to x - */ - public static long prevPow2(long x) - { - if (x < 1) { - throw new IllegalArgumentException("x must be greater or equal 1"); - } - return (long) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); - } - - /** - * Checks if x is a power-of-two number. - * - * @param x input value - * - * @return true if x is a power-of-two number - */ - public static boolean isPowerOf2(int x) - { - if (x <= 0) { - return false; - } else { - return (x & (x - 1)) == 0; - } - } - - /** - * Checks if x is a power-of-two number. - * - * @param x input value - * - * @return true if x is a power-of-two number - */ - public static boolean isPowerOf2(long x) - { - if (x <= 0) { - return false; - } else { - return (x & (x - 1l)) == 0; - } - } - - /** - * Causes the currently executing thread to sleep (temporarily cease - * execution) for the specified number of milliseconds. - * - * @param millis the length of time to sleep in milliseconds - */ - public static void sleep(long millis) - { - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - /** - * Submits a Runnable task for execution and returns a Future representing - * that task. - * - * @param task a Runnable task for execution - * - * @return a Future representing the task - */ - public static Future submit(Runnable task) - { - if (THREAD_POOL.isShutdown() || THREAD_POOL.isTerminated()) { - THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler())); - } - return THREAD_POOL.submit(task); - } - - /** - * Shutdowns all submitted tasks. - */ - public static void shutdownAndAwaitTermination() - { - THREAD_POOL.shutdown(); // Disable new tasks from being submitted - try { - // Wait a while for existing tasks to terminate - if (!THREAD_POOL.awaitTermination(60, TimeUnit.SECONDS)) { - THREAD_POOL.shutdownNow(); // Cancel currently executing tasks - // Wait a while for tasks to respond to being cancelled - if (!THREAD_POOL.awaitTermination(60, TimeUnit.SECONDS)) - System.err.println("Pool did not terminate"); - } - } catch (InterruptedException ie) { - // (Re-)Cancel if current thread also interrupted - THREAD_POOL.shutdownNow(); - // Preserve interrupt status - Thread.currentThread().interrupt(); - } - } - - /** - * Waits for all threads to complete computation. - * - * @param futures array of Future objects - */ - public static void waitForCompletion(Future[] futures) - { - int size = futures.length; - try { - for (int j = 0; j < size; j++) { - futures[j].get(); - } - } catch (ExecutionException ex) { - ex.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } -} +/* ***** BEGIN LICENSE BLOCK ***** + * JTransforms + * Copyright (c) 2007 onward, Piotr Wendykier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +// Code modified for inclusion with fairSIM: +// - changed package name + +package org.fairsim.extern.jtransforms; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +/** + * Concurrency utilities. + * + * @author Piotr Wendykier (piotr.wendykier@gmail.com) + */ +public class ConcurrencyUtils +{ + + /** + * Thread pool. + */ + private static ExecutorService THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler())); + + private static long THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; + + private static long THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; + + private static long THREADS_BEGIN_N_2D = 65536; + + private static long LARGE_ARAYS_BEGIN_N = (1 << 28); + + private static long THREADS_BEGIN_N_3D = 65536; + + private static int NTHREADS = prevPow2(getNumberOfProcessors()); + + private ConcurrencyUtils() + { + + } + + private static class CustomExceptionHandler implements Thread.UncaughtExceptionHandler + { + + public void uncaughtException(Thread t, Throwable e) + { + e.printStackTrace(); + } + + } + + private static class CustomThreadFactory implements ThreadFactory + { + + private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + + private final Thread.UncaughtExceptionHandler handler; + + CustomThreadFactory(Thread.UncaughtExceptionHandler handler) + { + this.handler = handler; + } + + public Thread newThread(Runnable r) + { + Thread t = defaultFactory.newThread(r); + t.setUncaughtExceptionHandler(handler); + return t; + } + }; + + /** + * Returns the number of available processors. + * + * @return number of available processors + */ + public static int getNumberOfProcessors() + { + return Runtime.getRuntime().availableProcessors(); + } + + /** + * Returns the current number of threads. + * + * @return the current number of threads. + */ + public static int getNumberOfThreads() + { + return NTHREADS; + } + + /** + * Sets the number of threads. If n is not a power-of-two number, then the + * number of threads is set to the closest power-of-two number less than n. + * + * @param n number of threads + */ + public static void setNumberOfThreads(int n) + { + NTHREADS = prevPow2(n); + } + + /** + * Returns the minimal size of 1D data for which two threads are used. + * + * @return the minimal size of 1D data for which two threads are used + */ + public static long getThreadsBeginN_1D_FFT_2Threads() + { + return THREADS_BEGIN_N_1D_FFT_2THREADS; + } + + /** + * Returns the minimal size of 1D data for which four threads are used. + * + * @return the minimal size of 1D data for which four threads are used + */ + public static long getThreadsBeginN_1D_FFT_4Threads() + { + return THREADS_BEGIN_N_1D_FFT_4THREADS; + } + + /** + * Returns the minimal size of 2D data for which threads are used. + * + * @return the minimal size of 2D data for which threads are used + */ + public static long getThreadsBeginN_2D() + { + return THREADS_BEGIN_N_2D; + } + + /** + * Returns the minimal size of 3D data for which threads are used. + * + * @return the minimal size of 3D data for which threads are used + */ + public static long getThreadsBeginN_3D() + { + return THREADS_BEGIN_N_3D; + } + + /** + * Returns the minimal size for which JLargeArrays are used. + * + * @return the minimal size for which JLargeArrays are used + */ + public static long getLargeArraysBeginN() + { + return LARGE_ARAYS_BEGIN_N; + } + + /** + * Sets the minimal size of 1D data for which two threads are used. + * + * @param n the minimal size of 1D data for which two threads are used + */ + public static void setThreadsBeginN_1D_FFT_2Threads(long n) + { + if (n < 1024) { + THREADS_BEGIN_N_1D_FFT_2THREADS = 1024; + } else { + THREADS_BEGIN_N_1D_FFT_2THREADS = n; + } + } + + /** + * Sets the minimal size of 1D data for which four threads are used. + * + * @param n the minimal size of 1D data for which four threads are used + */ + public static void setThreadsBeginN_1D_FFT_4Threads(long n) + { + if (n < 1024) { + THREADS_BEGIN_N_1D_FFT_4THREADS = 1024; + } else { + THREADS_BEGIN_N_1D_FFT_4THREADS = n; + } + } + + /** + * Sets the minimal size of 2D data for which threads are used. + * + * @param n the minimal size of 2D data for which threads are used + */ + public static void setThreadsBeginN_2D(long n) + { + if (n < 4096) { + THREADS_BEGIN_N_2D = 4096; + } else { + THREADS_BEGIN_N_2D = n; + } + } + + /** + * Sets the minimal size of 3D data for which threads are used. + * + * @param n the minimal size of 3D data for which threads are used + */ + public static void setThreadsBeginN_3D(long n) + { + THREADS_BEGIN_N_3D = n; + } + + /** + * Resets the minimal size of 1D data for which two and four threads are + * used. + */ + public static void resetThreadsBeginN_FFT() + { + THREADS_BEGIN_N_1D_FFT_2THREADS = 8192; + THREADS_BEGIN_N_1D_FFT_4THREADS = 65536; + } + + /** + * Resets the minimal size of 2D and 3D data for which threads are used. + */ + public static void resetThreadsBeginN() + { + THREADS_BEGIN_N_2D = 65536; + THREADS_BEGIN_N_3D = 65536; + } + + /** + * Sets the minimal size for which JLargeArrays are used. + * + * @param n the maximal size for which JLargeArrays are used + */ + public static void setLargeArraysBeginN(long n) + { + if (n < 1) { + LARGE_ARAYS_BEGIN_N = 1; + } else if (n > (1 << 28)) { + LARGE_ARAYS_BEGIN_N = (1 << 28); + } else { + LARGE_ARAYS_BEGIN_N = n; + } + } + + /** + * Returns the closest power-of-two number greater than or equal to x. + * + * @param x input value + * + * @return the closest power-of-two number greater than or equal to x + */ + public static int nextPow2(int x) + { + if (x < 1) { + throw new IllegalArgumentException("x must be greater or equal 1"); + } + if ((x & (x - 1)) == 0) { + return x; // x is already a power-of-two number + } + x |= (x >>> 1); + x |= (x >>> 2); + x |= (x >>> 4); + x |= (x >>> 8); + x |= (x >>> 16); + return x + 1; + } + + /** + * Returns the closest power-of-two number greater than or equal to x. + * + * @param x input value + * + * @return the closest power-of-two number greater than or equal to x + */ + public static long nextPow2(long x) + { + if (x < 1) { + throw new IllegalArgumentException("x must be greater or equal 1"); + } + if ((x & (x - 1l)) == 0) { + return x; // x is already a power-of-two number + } + x |= (x >>> 1l); + x |= (x >>> 2l); + x |= (x >>> 4l); + x |= (x >>> 8l); + x |= (x >>> 16l); + x |= (x >>> 32l); + return x + 1l; + } + + /** + * Returns the closest power-of-two number less than or equal to x. + * + * @param x input value + * + * @return the closest power-of-two number less then or equal to x + */ + public static int prevPow2(int x) + { + if (x < 1) { + throw new IllegalArgumentException("x must be greater or equal 1"); + } + return (int) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); + } + + /** + * Returns the closest power-of-two number less than or equal to x. + * + * @param x input value + * + * @return the closest power-of-two number less then or equal to x + */ + public static long prevPow2(long x) + { + if (x < 1) { + throw new IllegalArgumentException("x must be greater or equal 1"); + } + return (long) Math.pow(2, Math.floor(Math.log(x) / Math.log(2))); + } + + /** + * Checks if x is a power-of-two number. + * + * @param x input value + * + * @return true if x is a power-of-two number + */ + public static boolean isPowerOf2(int x) + { + if (x <= 0) { + return false; + } else { + return (x & (x - 1)) == 0; + } + } + + /** + * Checks if x is a power-of-two number. + * + * @param x input value + * + * @return true if x is a power-of-two number + */ + public static boolean isPowerOf2(long x) + { + if (x <= 0) { + return false; + } else { + return (x & (x - 1l)) == 0; + } + } + + /** + * Causes the currently executing thread to sleep (temporarily cease + * execution) for the specified number of milliseconds. + * + * @param millis the length of time to sleep in milliseconds + */ + public static void sleep(long millis) + { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Submits a Runnable task for execution and returns a Future representing + * that task. + * + * @param task a Runnable task for execution + * + * @return a Future representing the task + */ + public static Future submit(Runnable task) + { + if (THREAD_POOL.isShutdown() || THREAD_POOL.isTerminated()) { + THREAD_POOL = Executors.newCachedThreadPool(new CustomThreadFactory(new CustomExceptionHandler())); + } + return THREAD_POOL.submit(task); + } + + /** + * Shutdowns all submitted tasks. + */ + public static void shutdownAndAwaitTermination() + { + THREAD_POOL.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!THREAD_POOL.awaitTermination(60, TimeUnit.SECONDS)) { + THREAD_POOL.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!THREAD_POOL.awaitTermination(60, TimeUnit.SECONDS)) + System.err.println("Pool did not terminate"); + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + THREAD_POOL.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + } + + /** + * Waits for all threads to complete computation. + * + * @param futures array of Future objects + */ + public static void waitForCompletion(Future[] futures) + { + int size = futures.length; + try { + for (int j = 0; j < size; j++) { + futures[j].get(); + } + } catch (ExecutionException ex) { + ex.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/org/jtransforms/fft/FloatFFT_1D.java b/org/fairsim/extern/jtransforms/FloatFFT_1D.java similarity index 97% rename from src/main/java/org/jtransforms/fft/FloatFFT_1D.java rename to org/fairsim/extern/jtransforms/FloatFFT_1D.java index a6e7971..e13b0dd 100644 --- a/src/main/java/org/jtransforms/fft/FloatFFT_1D.java +++ b/org/fairsim/extern/jtransforms/FloatFFT_1D.java @@ -1,7682 +1,7724 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.concurrent.Future; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; -import pl.edu.icm.jlargearrays.LongLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Fourier Transform (DFT) of complex and real, single - * precision data. The size of the data can be an arbitrary number. This is a - * parallel implementation of split-radix and mixed-radix algorithms optimized - * for SMP systems.
- *
- * This code is derived from General Purpose FFT Package written by Takuya Ooura - * (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) and from JFFTPack written - * by Baoshe Zhang (http://jfftpack.sourceforge.net/) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public final class FloatFFT_1D { - - private static enum Plans { - - SPLIT_RADIX, MIXED_RADIX, BLUESTEIN - } - - private int n; - - private long nl; - - private int nBluestein; - - private long nBluesteinl; - - private int[] ip; - - private LongLargeArray ipl; - - private float[] w; - - private FloatLargeArray wl; - - private int nw; - - private long nwl; - - private int nc; - - private long ncl; - - private float[] wtable; - - private FloatLargeArray wtablel; - - private float[] wtable_r; - - private FloatLargeArray wtable_rl; - - private float[] bk1; - - private FloatLargeArray bk1l; - - private float[] bk2; - - private FloatLargeArray bk2l; - - private Plans plan; - - private boolean useLargeArrays; - - private static final int[] factors = {4, 2, 3, 5}; - - private static final float PI = 3.14159265358979311599796346854418516f; - - private static final float TWO_PI = 6.28318530717958623199592693708837032f; - - /** - * Creates new instance of FloatFFT_1D. - * - * @param n size of data - */ - public FloatFFT_1D(long n) { - if (n < 1) { - throw new IllegalArgumentException("n must be greater than 0"); - } - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - if(this.useLargeArrays == false) { - this.n = (int) n; - if (!ConcurrencyUtils.isPowerOf2(n)) { - if (CommonUtils.getReminder(n, factors) >= 211) { - plan = Plans.BLUESTEIN; - nBluestein = ConcurrencyUtils.nextPow2(this.n * 2 - 1); - bk1 = new float[2 * nBluestein]; - bk2 = new float[2 * nBluestein]; - this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(nBluestein + 0.5f) / Math.log(2)) / 2))]; - this.w = new float[nBluestein]; - int twon = 2 * nBluestein; - nw = twon >> 2; - CommonUtils.makewt(nw, ip, w); - nc = nBluestein >> 2; - CommonUtils.makect(nc, w, nw, ip); - bluesteini(); - } else { - plan = Plans.MIXED_RADIX; - wtable = new float[4 * this.n + 15]; - wtable_r = new float[2 * this.n + 15]; - cffti(); - rffti(); - } - } else { - plan = Plans.SPLIT_RADIX; - this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(n + 0.5f) / Math.log(2)) / 2))]; - this.w = new float[this.n]; - int twon = 2 * this.n; - nw = twon >> 2; - CommonUtils.makewt(nw, ip, w); - nc = this.n >> 2; - CommonUtils.makect(nc, w, nw, ip); - } - } else { - this.nl = n; - if (!ConcurrencyUtils.isPowerOf2(nl)) { - if (CommonUtils.getReminder(nl, factors) >= 211) { - plan = Plans.BLUESTEIN; - nBluesteinl = ConcurrencyUtils.nextPow2(nl * 2 - 1); - bk1l = new FloatLargeArray(2l * nBluesteinl, false); - bk2l = new FloatLargeArray(2l * nBluesteinl, false); - this.ipl = new LongLargeArray(2l + (long) Math.ceil(2l + (1l << (long) (Math.log(nBluesteinl + 0.5f) / Math.log(2.)) / 2)), false); - this.wl = new FloatLargeArray(nBluesteinl, false); - long twon = 2 * nBluesteinl; - nwl = twon >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - ncl = nBluesteinl >> 2l; - CommonUtils.makect(ncl, wl, nwl, ipl); - bluesteinil(); - } else { - plan = Plans.MIXED_RADIX; - wtablel = new FloatLargeArray(4 * nl + 15, false); - wtable_rl = new FloatLargeArray(2 * nl + 15, false); - cfftil(); - rfftil(); - } - } else { - plan = Plans.SPLIT_RADIX; - this.ipl = new LongLargeArray(2l + (long) Math.ceil(2 + (1l << (long) (Math.log(nl + 0.5f) / Math.log(2)) / 2)), false); - this.wl = new FloatLargeArray(nl, false); - long twon = 2 * nl; - nwl = twon >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - ncl = nl >> 2l; - CommonUtils.makect(ncl, wl, nwl, ipl); - } - } - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - */ - public void complexForward(float[] a) { - complexForward(a, 0); - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - */ - public void complexForward(FloatLargeArray a) { - complexForward(a, 0); - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void complexForward(float[] a, int offa) { - if (useLargeArrays) { - complexForward(new FloatLargeArray(a), offa); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftbsub(2 * n, a, offa, ip, nw, w); - break; - case MIXED_RADIX: - cfftf(a, offa, -1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void complexForward(FloatLargeArray a, long offa) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - complexForward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftbsub(2 * nl, a, offa, ipl, nwl, wl); - break; - case MIXED_RADIX: - cfftf(a, offa, -1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(float[] a, boolean scale) { - complexInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(FloatLargeArray a, boolean scale) { - complexInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void complexInverse(float[] a, int offa, boolean scale) { - if (useLargeArrays) { - complexInverse(new FloatLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftfsub(2 * n, a, offa, ip, nw, w); - break; - case MIXED_RADIX: - cfftf(a, offa, +1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, 1); - break; - } - if (scale) { - CommonUtils.scale(n, 1.0f / (float) n, a, offa, true); - } - } - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two float values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void complexInverse(FloatLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - complexInverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftfsub(2 * nl, a, offa, ipl, nwl, wl); - break; - case MIXED_RADIX: - cfftf(a, offa, +1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, 1); - break; - } - if (scale) { - CommonUtils.scale(nl, 1.0f / (float) nl, a, offa, true); - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(float[] a) { - realForward(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(FloatLargeArray a) { - realForward(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForward(float[] a, int offa) { - if (useLargeArrays) { - realForward(new FloatLargeArray(a), offa); - } else { - if (n == 1) { - return; - } - - switch (plan) { - case SPLIT_RADIX: - float xi; - - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - CommonUtils.rftfsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftx020(a, offa); - } - xi = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - a[offa + 1] = xi; - break; - case MIXED_RADIX: - rfftf(a, offa); - for (int k = n - 1; k >= 2; k--) { - int idx = offa + k; - float tmp = a[idx]; - a[idx] = a[idx - 1]; - a[idx - 1] = tmp; - } - break; - case BLUESTEIN: - bluestein_real_forward(a, offa); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForward(FloatLargeArray a, long offa) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realForward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - - switch (plan) { - case SPLIT_RADIX: - float xi; - - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftx020(a, offa); - } - xi = a.getFloat(offa) - a.getFloat(offa + 1); - a.setFloat(offa, a.getFloat(offa) + a.getFloat(offa + 1)); - a.setFloat(offa + 1, xi); - break; - case MIXED_RADIX: - rfftf(a, offa); - for (long k = nl - 1; k >= 2; k--) { - long idx = offa + k; - float tmp = a.getFloat(idx); - a.setFloat(idx, a.getFloat(idx - 1)); - a.setFloat(idx - 1, tmp); - } - break; - case BLUESTEIN: - bluestein_real_forward(a, offa); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary parts equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(float[] a) { - realForwardFull(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary parts equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(FloatLargeArray a) { - realForwardFull(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForwardFull(final float[] a, final int offa) { - - if (useLargeArrays) { - realForwardFull(new FloatLargeArray(a), offa); - } else { - final int twon = 2 * n; - switch (plan) { - case SPLIT_RADIX: - realForward(a, offa); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - int k = n / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - for (int k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int k = 0; k < n / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - a[offa + n] = -a[offa + 1]; - a[offa + 1] = 0; - break; - case MIXED_RADIX: - rfftf(a, offa); - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - for (int k = 1; k < m; k++) { - int idx1 = offa + twon - 2 * k; - int idx2 = offa + 2 * k; - a[idx1 + 1] = -a[idx2]; - a[idx1] = a[idx2 - 1]; - } - for (int k = 1; k < n; k++) { - int idx = offa + n - k; - float tmp = a[idx + 1]; - a[idx + 1] = a[idx]; - a[idx] = tmp; - } - a[offa + 1] = 0; - break; - case BLUESTEIN: - bluestein_real_full(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForwardFull(final FloatLargeArray a, final long offa) { - - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realForwardFull(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - final long twon = 2 * nl; - switch (plan) { - case SPLIT_RADIX: - realForward(a, offa); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - long k = nl / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - for (long k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setFloat(idx2, a.getFloat(offa + idx1)); - a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long k = 0; k < nl / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setFloat(idx2, a.getFloat(offa + idx1)); - a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); - } - } - a.setFloat(offa + nl, -a.getFloat(offa + 1)); - a.setFloat(offa + 1, 0); - break; - case MIXED_RADIX: - rfftf(a, offa); - long m; - if (nl % 2 == 0) { - m = nl / 2; - } else { - m = (nl + 1) / 2; - } - for (long k = 1; k < m; k++) { - long idx1 = offa + twon - 2 * k; - long idx2 = offa + 2 * k; - a.setFloat(idx1 + 1, -a.getFloat(idx2)); - a.setFloat(idx1, a.getFloat(idx2 - 1)); - } - for (long k = 1; k < nl; k++) { - long idx = offa + nl - k; - float tmp = a.getFloat(idx + 1); - a.setFloat(idx + 1, a.getFloat(idx)); - a.setFloat(idx, tmp); - } - a.setFloat(offa + 1, 0); - break; - case BLUESTEIN: - bluestein_real_full(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - * - */ - public void realInverse(float[] a, boolean scale) { - realInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - * - */ - public void realInverse(FloatLargeArray a, boolean scale) { - realInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - * - */ - public void realInverse(float[] a, int offa, boolean scale) { - if (useLargeArrays) { - realInverse(new FloatLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - a[offa + 1] = 0.5f * (a[offa] - a[offa + 1]); - a[offa] -= a[offa + 1]; - if (n > 4) { - CommonUtils.rftfsub(n, a, offa, nc, w, nw); - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } else if (n == 4) { - CommonUtils.cftxc020(a, offa); - } - if (scale) { - CommonUtils.scale(n, 1.0f / (n / 2.0f), a, offa, false); - } - break; - case MIXED_RADIX: - for (int k = 2; k < n; k++) { - int idx = offa + k; - float tmp = a[idx - 1]; - a[idx - 1] = a[idx]; - a[idx] = tmp; - } - rfftb(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - break; - case BLUESTEIN: - bluestein_real_inverse(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - break; - } - } - - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - * - */ - public void realInverse(FloatLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - a.setFloat(offa + 1, 0.5f * (a.getFloat(offa) - a.getFloat(offa + 1))); - a.setFloat(offa, a.getFloat(offa) - a.getFloat(offa + 1)); - if (nl > 4) { - CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } else if (nl == 4) { - CommonUtils.cftxc020(a, offa); - } - if (scale) { - CommonUtils.scale(nl, 1.0f / (nl / 2.0f), a, offa, false); - } - break; - case MIXED_RADIX: - for (long k = 2; k < nl; k++) { - long idx = offa + k; - float tmp = a.getFloat(idx - 1); - a.setFloat(idx - 1, a.getFloat(idx)); - a.setFloat(idx, tmp); - } - rfftb(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - break; - case BLUESTEIN: - bluestein_real_inverse(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - break; - } - } - - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(float[] a, boolean scale) { - realInverseFull(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(FloatLargeArray a, boolean scale) { - realInverseFull(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void realInverseFull(final float[] a, final int offa, boolean scale) { - if (useLargeArrays) { - realInverseFull(new FloatLargeArray(a), offa, scale); - } else { - final int twon = 2 * n; - switch (plan) { - case SPLIT_RADIX: - realInverse2(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - int k = n / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - for (int k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int k = 0; k < n / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - a[offa + n] = -a[offa + 1]; - a[offa + 1] = 0; - break; - case MIXED_RADIX: - rfftf(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - for (int k = 1; k < m; k++) { - int idx1 = offa + 2 * k; - int idx2 = offa + twon - 2 * k; - a[idx1] = -a[idx1]; - a[idx2 + 1] = -a[idx1]; - a[idx2] = a[idx1 - 1]; - } - for (int k = 1; k < n; k++) { - int idx = offa + n - k; - float tmp = a[idx + 1]; - a[idx + 1] = a[idx]; - a[idx] = tmp; - } - a[offa + 1] = 0; - break; - case BLUESTEIN: - bluestein_real_full(a, offa, 1); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, true); - } - break; - } - } - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void realInverseFull(final FloatLargeArray a, final long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverseFull(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - final long twon = 2 * nl; - switch (plan) { - case SPLIT_RADIX: - realInverse2(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - long k = nl / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - for (long k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setFloat(idx2, a.getFloat(offa + idx1)); - a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long k = 0; k < nl / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setFloat(idx2, a.getFloat(offa + idx1)); - a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); - } - } - a.setFloat(offa + nl, -a.getFloat(offa + 1)); - a.setFloat(offa + 1, 0); - break; - case MIXED_RADIX: - rfftf(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - long m; - if (nl % 2 == 0) { - m = nl / 2; - } else { - m = (nl + 1) / 2; - } - for (long k = 1; k < m; k++) { - long idx1 = offa + 2 * k; - long idx2 = offa + twon - 2 * k; - a.setFloat(idx1, -a.getFloat(idx1)); - a.setFloat(idx2 + 1, -a.getFloat(idx1)); - a.setFloat(idx2, a.getFloat(idx1 - 1)); - } - for (long k = 1; k < nl; k++) { - long idx = offa + nl - k; - float tmp = a.getFloat(idx + 1); - a.setFloat(idx + 1, a.getFloat(idx)); - a.setFloat(idx, tmp); - } - a.setFloat(offa + 1, 0); - break; - case BLUESTEIN: - bluestein_real_full(a, offa, 1); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, true); - } - break; - } - } - } - - protected void realInverse2(float[] a, int offa, boolean scale) { - if (useLargeArrays) { - realInverse2(new FloatLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - float xi; - - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - CommonUtils.rftbsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } - xi = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - a[offa + 1] = xi; - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - break; - case MIXED_RADIX: - rfftf(a, offa); - for (int k = n - 1; k >= 2; k--) { - int idx = offa + k; - float tmp = a[idx]; - a[idx] = a[idx - 1]; - a[idx - 1] = tmp; - } - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - int m; - if (n % 2 == 0) { - m = n / 2; - for (int i = 1; i < m; i++) { - int idx = offa + 2 * i + 1; - a[idx] = -a[idx]; - } - } else { - m = (n - 1) / 2; - for (int i = 0; i < m; i++) { - int idx = offa + 2 * i + 1; - a[idx] = -a[idx]; - } - } - break; - case BLUESTEIN: - bluestein_real_inverse2(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - break; - } - } - } - - protected void realInverse2(FloatLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverse2(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - float xi; - - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - CommonUtils.rftbsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } - xi = a.getFloat(offa) - a.getFloat(offa + 1); - a.setFloat(offa, a.getFloat(offa) + a.getFloat(offa + 1)); - a.setFloat(offa + 1, xi); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - break; - case MIXED_RADIX: - rfftf(a, offa); - for (long k = nl - 1; k >= 2; k--) { - long idx = offa + k; - float tmp = a.getFloat(idx); - a.setFloat(idx, a.getFloat(idx - 1)); - a.setFloat(idx - 1, tmp); - } - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - long m; - if (nl % 2 == 0) { - m = nl / 2; - for (long i = 1; i < m; i++) { - long idx = offa + 2 * i + 1; - a.setFloat(idx, -a.getFloat(idx)); - } - } else { - m = (nl - 1) / 2; - for (long i = 0; i < m; i++) { - long idx = offa + 2 * i + 1; - a.setFloat(idx, -a.getFloat(idx)); - } - } - break; - case BLUESTEIN: - bluestein_real_inverse2(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0f / nl, a, offa, false); - } - break; - } - } - } - - - /* -------- initializing routines -------- */ - - /*--------------------------------------------------------- - cffti: initialization of Complex FFT - --------------------------------------------------------*/ - void cffti(int n, int offw) { - if (n == 1) { - return; - } - - final int twon = 2 * n; - final int fourn = 4 * n; - float argh; - int idot, ntry = 0, i, j; - float argld; - int i1, k1, l1, l2, ib; - float fi; - int ld, ii, nf, ipll, nll, nq, nr; - float arg; - int ido, ipm; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtable[offw + nf + 1 + fourn] = ntry; - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + fourn; - wtable[offw + idx + 1] = wtable[offw + idx]; - } - wtable[offw + 2 + fourn] = 2; - } - } while (nll != 1); - break; - } - wtable[offw + fourn] = n; - wtable[offw + 1 + fourn] = nf; - argh = TWO_PI / (float) n; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable[offw + k1 + 1 + fourn]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtable[offw + i - 1 + twon] = 1; - wtable[offw + i + twon] = 0; - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + twon; - wtable[offw + idx - 1] = (float)Math.cos(arg); - wtable[offw + idx] = (float)Math.sin(arg); - } - if (ipll > 5) { - int idx1 = i1 + twon; - int idx2 = i + twon; - wtable[offw + idx1 - 1] = wtable[offw + idx2 - 1]; - wtable[offw + idx1] = wtable[offw + idx2]; - } - } - l1 = l2; - } - - } - - final void cffti() { - if (n == 1) { - return; - } - - final int twon = 2 * n; - final int fourn = 4 * n; - float argh; - int idot, ntry = 0, i, j; - float argld; - int i1, k1, l1, l2, ib; - float fi; - int ld, ii, nf, ipll, nll, nq, nr; - float arg; - int ido, ipm; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtable[nf + 1 + fourn] = ntry; - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + fourn; - wtable[idx + 1] = wtable[idx]; - } - wtable[2 + fourn] = 2; - } - } while (nll != 1); - break; - } - wtable[fourn] = n; - wtable[1 + fourn] = nf; - argh = TWO_PI / (float) n; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable[k1 + 1 + fourn]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtable[i - 1 + twon] = 1; - wtable[i + twon] = 0; - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + twon; - wtable[idx - 1] = (float)Math.cos(arg); - wtable[idx] = (float)Math.sin(arg); - } - if (ipll > 5) { - int idx1 = i1 + twon; - int idx2 = i + twon; - wtable[idx1 - 1] = wtable[idx2 - 1]; - wtable[idx1] = wtable[idx2]; - } - } - l1 = l2; - } - - } - - final void cfftil() { - if (nl == 1) { - return; - } - - final long twon = 2 * nl; - final long fourn = 4 * nl; - float argh; - long idot, ntry = 0, i, j; - float argld; - long i1, k1, l1, l2, ib; - float fi; - long ld, ii, nf, ipll, nl2, nq, nr; - float arg; - long ido, ipm; - - nl2 = nl; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[(int) (j - 1)]; - } else { - ntry += 2; - } - do { - nq = nl2 / ntry; - nr = nl2 - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtablel.setFloat(nf + 1 + fourn, ntry); - nl2 = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - long idx = ib + fourn; - wtablel.setFloat(idx + 1, wtablel.getFloat(idx)); - } - wtablel.setFloat(2 + fourn, 2); - } - } while (nl2 != 1); - break; - } - wtablel.setFloat(fourn, nl); - wtablel.setFloat(1 + fourn, nf); - argh = TWO_PI / (float) nl; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (long) wtablel.getFloat(k1 + 1 + fourn); - ld = 0; - l2 = l1 * ipll; - ido = nl / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtablel.setFloat(i - 1 + twon, 1); - wtablel.setFloat(i + twon, 0); - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - long idx = i + twon; - wtablel.setFloat(idx - 1, (float)Math.cos(arg)); - wtablel.setFloat(idx, (float)Math.sin(arg)); - } - if (ipll > 5) { - long idx1 = i1 + twon; - long idx2 = i + twon; - wtablel.setFloat(idx1 - 1, wtablel.getFloat(idx2 - 1)); - wtablel.setFloat(idx1, wtablel.getFloat(idx2)); - } - } - l1 = l2; - } - - } - - void rffti() { - - if (n == 1) { - return; - } - final int twon = 2 * n; - float argh; - int ntry = 0, i, j; - float argld; - int k1, l1, l2, ib; - float fi; - int ld, ii, nf, ipll, nll, is, nq, nr; - float arg; - int ido, ipm; - int nfm1; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - ++j; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - ++nf; - wtable_r[nf + 1 + twon] = ntry; - - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + twon; - wtable_r[idx + 1] = wtable_r[idx]; - } - wtable_r[2 + twon] = 2; - } - } while (nll != 1); - break; - } - wtable_r[twon] = n; - wtable_r[1 + twon] = nf; - argh = TWO_PI / (float) (n); - is = 0; - nfm1 = nf - 1; - l1 = 1; - if (nfm1 == 0) { - return; - } - for (k1 = 1; k1 <= nfm1; k1++) { - ipll = (int) wtable_r[k1 + 1 + twon]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - ipm = ipll - 1; - for (j = 1; j <= ipm; ++j) { - ld += l1; - i = is; - argld = (float) ld * argh; - - fi = 0; - for (ii = 3; ii <= ido; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + n; - wtable_r[idx - 2] = (float)Math.cos(arg); - wtable_r[idx - 1] = (float)Math.sin(arg); - } - is += ido; - } - l1 = l2; - } - } - - void rfftil() { - - if (nl == 1) { - return; - } - final long twon = 2 * nl; - float argh; - long ntry = 0, i, j; - float argld; - long k1, l1, l2, ib; - float fi; - long ld, ii, nf, ipll, nl2, is, nq, nr; - float arg; - long ido, ipm; - long nfm1; - - nl2 = nl; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - ++j; - if (j <= 4) { - ntry = factors[(int) (j - 1)]; - } else { - ntry += 2; - } - do { - nq = nl2 / ntry; - nr = nl2 - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - ++nf; - wtable_rl.setFloat(nf + 1 + twon, ntry); - - nl2 = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - long idx = ib + twon; - wtable_rl.setFloat(idx + 1, wtable_rl.getFloat(idx)); - } - wtable_rl.setFloat(2 + twon, 2); - } - } while (nl2 != 1); - break; - } - wtable_rl.setFloat(twon, nl); - wtable_rl.setFloat(1 + twon, nf); - argh = TWO_PI / (float) (nl); - is = 0; - nfm1 = nf - 1; - l1 = 1; - if (nfm1 == 0) { - return; - } - for (k1 = 1; k1 <= nfm1; k1++) { - ipll = (long) wtable_rl.getFloat(k1 + 1 + twon); - ld = 0; - l2 = l1 * ipll; - ido = nl / l2; - ipm = ipll - 1; - for (j = 1; j <= ipm; ++j) { - ld += l1; - i = is; - argld = (float) ld * argh; - - fi = 0; - for (ii = 3; ii <= ido; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - long idx = i + nl; - wtable_rl.setFloat(idx - 2, (float)Math.cos(arg)); - wtable_rl.setFloat(idx - 1, (float)Math.sin(arg)); - } - is += ido; - } - l1 = l2; - } - } - - private void bluesteini() { - int k = 0; - float arg; - float pi_n = PI / n; - bk1[0] = 1; - bk1[1] = 0; - for (int i = 1; i < n; i++) { - k += 2 * i - 1; - if (k >= 2 * n) { - k -= 2 * n; - } - arg = pi_n * k; - bk1[2 * i] = (float)Math.cos(arg); - bk1[2 * i + 1] = (float)Math.sin(arg); - } - float scale = 1.0f / nBluestein; - bk2[0] = bk1[0] * scale; - bk2[1] = bk1[1] * scale; - for (int i = 2; i < 2 * n; i += 2) { - bk2[i] = bk1[i] * scale; - bk2[i + 1] = bk1[i + 1] * scale; - bk2[2 * nBluestein - i] = bk2[i]; - bk2[2 * nBluestein - i + 1] = bk2[i + 1]; - } - CommonUtils.cftbsub(2 * nBluestein, bk2, 0, ip, nw, w); - } - - private void bluesteinil() { - long k = 0; - float arg; - float pi_n = PI / nl; - bk1l.setFloat(0, 1); - bk1l.setFloat(1, 0); - for (int i = 1; i < nl; i++) { - k += 2 * i - 1; - if (k >= 2 * nl) { - k -= 2 * nl; - } - arg = pi_n * k; - bk1l.setFloat(2 * i, (float)Math.cos(arg)); - bk1l.setFloat(2 * i + 1, (float)Math.sin(arg)); - } - float scale = 1.0f / nBluesteinl; - bk2l.setFloat(0, bk1l.getFloat(0) * scale); - bk2l.setFloat(1, bk1l.getFloat(1) * scale); - for (int i = 2; i < 2 * nl; i += 2) { - bk2l.setFloat(i, bk1l.getFloat(i) * scale); - bk2l.setFloat(i + 1, bk1l.getFloat(i + 1) * scale); - bk2l.setFloat(2 * nBluesteinl - i, bk2l.getFloat(i)); - bk2l.setFloat(2 * nBluesteinl - i + 1, bk2l.getFloat(i + 1)); - } - CommonUtils.cftbsub(2 * nBluesteinl, bk2l, 0, ipl, nwl, wl); - } - - private void bluestein_complex(final float[] a, final int offa, final int isign) { - final float[] ak = new float[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - } - - private void bluestein_complex(final FloatLargeArray a, final long offa, final int isign) { - final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(idx4, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(idx4, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } else { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(idx4, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(idx4, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } - } - } - - private void bluestein_real_full(final float[] a, final int offa, final int isign) { - final float[] ak = new float[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - } - - private void bluestein_real_full(final FloatLargeArray a, final long offa, final long isign) { - final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } else { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } - } - } - - private void bluestein_real_forward(final float[] a, final int offa) { - final float[] ak = new float[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (n % 2 == 0) { - a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n] + bk1[n + 1] * ak[n + 1]; - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; - a[offa + 1] = -bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - a[offa + n - 1] = bk1[n - 1] * ak[n - 1] + bk1[n] * ak[n]; - } - - } - - private void bluestein_real_forward(final FloatLargeArray a, final long offa) { - final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (nl % 2 == 0) { - a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) + bk1l.getFloat(1) * ak.getFloat(1)); - a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl) + bk1l.getFloat(nl + 1) * ak.getFloat(nl + 1)); - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) + bk1l.getFloat(1) * ak.getFloat(1)); - a.setFloat(offa + 1, -bk1l.getFloat(nl) * ak.getFloat(nl - 1) + bk1l.getFloat(nl - 1) * ak.getFloat(nl)); - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - a.setFloat(offa + nl - 1, bk1l.getFloat(nl - 1) * ak.getFloat(nl - 1) + bk1l.getFloat(nl) * ak.getFloat(nl)); - } - - } - - private void bluestein_real_inverse(final float[] a, final int offa) { - final float[] ak = new float[2 * nBluestein]; - if (n % 2 == 0) { - ak[0] = a[offa] * bk1[0]; - ak[1] = a[offa] * bk1[1]; - - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - - ak[n] = a[offa + 1] * bk1[n]; - ak[n + 1] = a[offa + 1] * bk1[n + 1]; - - for (int i = n / 2 + 1; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + 2 * n - idx1; - int idx4 = idx3 + 1; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; - } - - } else { - ak[0] = a[offa] * bk1[0]; - ak[1] = a[offa] * bk1[1]; - - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - - ak[n - 1] = a[offa + n - 1] * bk1[n - 1] - a[offa + 1] * bk1[n]; - ak[n] = a[offa + n - 1] * bk1[n] + a[offa + 1] * bk1[n - 1]; - - ak[n + 1] = a[offa + n - 1] * bk1[n + 1] + a[offa + 1] * bk1[n + 2]; - ak[n + 2] = a[offa + n - 1] * bk1[n + 2] - a[offa + 1] * bk1[n + 1]; - - for (int i = (n - 1) / 2 + 2; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + 2 * n - idx1; - int idx4 = idx3 + 1; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - } - } - } - - private void bluestein_real_inverse(final FloatLargeArray a, final long offa) { - final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); - if (nl % 2 == 0) { - ak.setFloat(0, a.getFloat(offa) * bk1l.getFloat(0)); - ak.setFloat(1, a.getFloat(offa) * bk1l.getFloat(1)); - - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - - ak.setFloat(nl, a.getFloat(offa + 1) * bk1l.getFloat(nl)); - ak.setFloat(nl + 1, a.getFloat(offa + 1) * bk1l.getFloat(nl + 1)); - - for (long i = nl / 2 + 1; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + 2 * nl - idx1; - long idx4 = idx3 + 1; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) - a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - - } else { - ak.setFloat(0, a.getFloat(offa) * bk1l.getFloat(0)); - ak.setFloat(1, a.getFloat(offa) * bk1l.getFloat(1)); - - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - - ak.setFloat(nl - 1, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl - 1) - a.getFloat(offa + 1) * bk1l.getFloat(nl)); - ak.setFloat(nl, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl) + a.getFloat(offa + 1) * bk1l.getFloat(nl - 1)); - - ak.setFloat(nl + 1, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl + 1) + a.getFloat(offa + 1) * bk1l.getFloat(nl + 2)); - ak.setFloat(nl + 2, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl + 2) - a.getFloat(offa + 1) * bk1l.getFloat(nl + 1)); - - for (long i = (nl - 1) / 2 + 2; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + 2 * nl - idx1; - long idx4 = idx3 + 1; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) - a.getFloat(idx4) * bk1l.getFloat(idx1)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + i, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + i, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - } - } - } - - private void bluestein_real_inverse2(final float[] a, final int offa) { - final float[] ak = new float[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (n % 2 == 0) { - a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n] - bk1[n + 1] * ak[n + 1]; - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - a[offa + n - 1] = bk1[n - 1] * ak[n - 1] - bk1[n] * ak[n]; - } - } - - private void bluestein_real_inverse2(final FloatLargeArray a, final long offa) { - final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); - ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); - ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); - ak.setFloat(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (nl % 2 == 0) { - a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) - bk1l.getFloat(1) * ak.getFloat(1)); - a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl) - bk1l.getFloat(nl + 1) * ak.getFloat(nl + 1)); - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - } else { - a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) - bk1l.getFloat(1) * ak.getFloat(1)); - a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl - 1) + bk1l.getFloat(nl - 1) * ak.getFloat(nl)); - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); - a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); - } - a.setFloat(offa + nl - 1, bk1l.getFloat(nl - 1) * ak.getFloat(nl - 1) - bk1l.getFloat(nl) * ak.getFloat(nl)); - } - } - - /*--------------------------------------------------------- - rfftf1: further processing of Real forward FFT - --------------------------------------------------------*/ - void rfftf(final float a[], final int offa) { - if (n == 1) { - return; - } - int l1, l2, na, kh, nf, ipll, iw, ido, idl1; - - final float[] ch = new float[n]; - final int twon = 2 * n; - nf = (int) wtable_r[1 + twon]; - na = 1; - l2 = n; - iw = twon - 1; - for (int k1 = 1; k1 <= nf; ++k1) { - kh = nf - k1; - ipll = (int) wtable_r[kh + 2 + twon]; - l1 = l2 / ipll; - ido = n / l2; - idl1 = ido * l1; - iw -= (ipll - 1) * ido; - na = 1 - na; - switch (ipll) { - case 2: - if (na == 0) { - radf2(ido, l1, a, offa, ch, 0, iw); - } else { - radf2(ido, l1, ch, 0, a, offa, iw); - } - break; - case 3: - if (na == 0) { - radf3(ido, l1, a, offa, ch, 0, iw); - } else { - radf3(ido, l1, ch, 0, a, offa, iw); - } - break; - case 4: - if (na == 0) { - radf4(ido, l1, a, offa, ch, 0, iw); - } else { - radf4(ido, l1, ch, 0, a, offa, iw); - } - break; - case 5: - if (na == 0) { - radf5(ido, l1, a, offa, ch, 0, iw); - } else { - radf5(ido, l1, ch, 0, a, offa, iw); - } - break; - default: - if (ido == 1) { - na = 1 - na; - } - if (na == 0) { - radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - na = 1; - } else { - radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - na = 0; - } - break; - } - l2 = l1; - } - if (na == 1) { - return; - } - System.arraycopy(ch, 0, a, offa, n); - } - - /*--------------------------------------------------------- - rfftf1: further processing of Real forward FFT - --------------------------------------------------------*/ - void rfftf(final FloatLargeArray a, final long offa) { - if (nl == 1) { - return; - } - long l1, l2, na, kh, nf, iw, ido, idl1; - int ipll; - - final FloatLargeArray ch = new FloatLargeArray(nl, false); - final long twon = 2 * nl; - nf = (long) wtable_rl.getFloat(1 + twon); - na = 1; - l2 = nl; - iw = twon - 1; - for (long k1 = 1; k1 <= nf; ++k1) { - kh = nf - k1; - ipll = (int) wtable_rl.getFloat(kh + 2 + twon); - l1 = l2 / ipll; - ido = nl / l2; - idl1 = ido * l1; - iw -= (ipll - 1) * ido; - na = 1 - na; - switch (ipll) { - case 2: - if (na == 0) { - radf2(ido, l1, a, offa, ch, 0, iw); - } else { - radf2(ido, l1, ch, 0, a, offa, iw); - } - break; - case 3: - if (na == 0) { - radf3(ido, l1, a, offa, ch, 0, iw); - } else { - radf3(ido, l1, ch, 0, a, offa, iw); - } - break; - case 4: - if (na == 0) { - radf4(ido, l1, a, offa, ch, 0, iw); - } else { - radf4(ido, l1, ch, 0, a, offa, iw); - } - break; - case 5: - if (na == 0) { - radf5(ido, l1, a, offa, ch, 0, iw); - } else { - radf5(ido, l1, ch, 0, a, offa, iw); - } - break; - default: - if (ido == 1) { - na = 1 - na; - } - if (na == 0) { - radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - na = 1; - } else { - radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - na = 0; - } - break; - } - l2 = l1; - } - if (na == 1) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, nl); - } - - /*--------------------------------------------------------- - rfftb1: further processing of Real backward FFT - --------------------------------------------------------*/ - void rfftb(final float a[], final int offa) { - if (n == 1) { - return; - } - int l1, l2, na, nf, ipll, iw, ido, idl1; - - float[] ch = new float[n]; - final int twon = 2 * n; - nf = (int) wtable_r[1 + twon]; - na = 0; - l1 = 1; - iw = n; - for (int k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable_r[k1 + 1 + twon]; - l2 = ipll * l1; - ido = n / l2; - idl1 = ido * l1; - switch (ipll) { - case 2: - if (na == 0) { - radb2(ido, l1, a, offa, ch, 0, iw); - } else { - radb2(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - radb3(ido, l1, a, offa, ch, 0, iw); - } else { - radb3(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 4: - if (na == 0) { - radb4(ido, l1, a, offa, ch, 0, iw); - } else { - radb4(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - radb5(ido, l1, a, offa, ch, 0, iw); - } else { - radb5(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - default: - if (na == 0) { - radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - } else { - radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - } - if (ido == 1) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * ido; - } - if (na == 0) { - return; - } - System.arraycopy(ch, 0, a, offa, n); - } - - /*--------------------------------------------------------- - rfftb1: further processing of Real backward FFT - --------------------------------------------------------*/ - void rfftb(final FloatLargeArray a, final long offa) { - if (nl == 1) { - return; - } - long l1, l2, na, nf, iw, ido, idl1; - int ipll; - FloatLargeArray ch = new FloatLargeArray(nl, false); - final long twon = 2 * nl; - nf = (long) wtable_rl.getFloat(1 + twon); - na = 0; - l1 = 1; - iw = nl; - for (long k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable_rl.getFloat(k1 + 1 + twon); - l2 = ipll * l1; - ido = nl / l2; - idl1 = ido * l1; - switch (ipll) { - case 2: - if (na == 0) { - radb2(ido, l1, a, offa, ch, 0, iw); - } else { - radb2(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - radb3(ido, l1, a, offa, ch, 0, iw); - } else { - radb3(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 4: - if (na == 0) { - radb4(ido, l1, a, offa, ch, 0, iw); - } else { - radb4(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - radb5(ido, l1, a, offa, ch, 0, iw); - } else { - radb5(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - default: - if (na == 0) { - radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - } else { - radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - } - if (ido == 1) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * ido; - } - if (na == 0) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, nl); - } - - /*------------------------------------------------- - radf2: Real FFT's forward processing of factor 2 - -------------------------------------------------*/ - void radf2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - int i, ic, idx0, idx1, idx2, idx3, idx4; - float t1i, t1r, w1r, w1i; - int iw1; - iw1 = offset; - idx0 = l1 * ido; - idx1 = 2 * ido; - for (int k = 0; k < l1; k++) { - int oidx1 = out_off + k * idx1; - int oidx2 = oidx1 + idx1 - 1; - int iidx1 = in_off + k * ido; - int iidx2 = iidx1 + idx0; - - float i1r = in[iidx1]; - float i2r = in[iidx2]; - - out[oidx1] = i1r + i2r; - out[oidx2] = i1r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; k++) { - idx1 = k * ido; - idx2 = 2 * idx1; - idx3 = idx2 + ido; - idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int oidx1 = out_off + i + idx2; - int oidx2 = out_off + ic + idx3; - int iidx1 = in_off + i + idx1; - int iidx2 = in_off + i + idx4; - - float a1i = in[iidx1 - 1]; - float a1r = in[iidx1]; - float a2i = in[iidx2 - 1]; - float a2r = in[iidx2]; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - - t1r = w1r * a2i + w1i * a2r; - t1i = w1r * a2r - w1i * a2i; - - out[oidx1] = a1r + t1i; - out[oidx1 - 1] = a1i + t1r; - - out[oidx2] = t1i - a1r; - out[oidx2 - 1] = a1i - t1r; - } - } - if (ido % 2 == 1) { - return; - } - } - idx2 = 2 * idx1; - for (int k = 0; k < l1; k++) { - idx1 = k * ido; - int oidx1 = out_off + idx2 + ido; - int iidx1 = in_off + ido - 1 + idx1; - - out[oidx1] = -in[iidx1 + idx0]; - out[oidx1 - 1] = in[iidx1]; - } - } - - /*------------------------------------------------- - radf2: Real FFT's forward processing of factor 2 - -------------------------------------------------*/ - void radf2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - long i, ic, idx0, idx1, idx2, idx3, idx4; - float t1i, t1r, w1r, w1i; - long iw1; - iw1 = offset; - idx0 = l1 * ido; - idx1 = 2 * ido; - for (long k = 0; k < l1; k++) { - long oidx1 = out_off + k * idx1; - long oidx2 = oidx1 + idx1 - 1; - long iidx1 = in_off + k * ido; - long iidx2 = iidx1 + idx0; - - float i1r = in.getFloat(iidx1); - float i2r = in.getFloat(iidx2); - - out.setFloat(oidx1, i1r + i2r); - out.setFloat(oidx2, i1r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; k++) { - idx1 = k * ido; - idx2 = 2 * idx1; - idx3 = idx2 + ido; - idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long oidx1 = out_off + i + idx2; - long oidx2 = out_off + ic + idx3; - long iidx1 = in_off + i + idx1; - long iidx2 = in_off + i + idx4; - - float a1i = in.getFloat(iidx1 - 1); - float a1r = in.getFloat(iidx1); - float a2i = in.getFloat(iidx2 - 1); - float a2r = in.getFloat(iidx2); - - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - - t1r = w1r * a2i + w1i * a2r; - t1i = w1r * a2r - w1i * a2i; - - out.setFloat(oidx1, a1r + t1i); - out.setFloat(oidx1 - 1, a1i + t1r); - - out.setFloat(oidx2, t1i - a1r); - out.setFloat(oidx2 - 1, a1i - t1r); - } - } - if (ido % 2 == 1) { - return; - } - } - idx2 = 2 * idx1; - for (long k = 0; k < l1; k++) { - idx1 = k * ido; - long oidx1 = out_off + idx2 + ido; - long iidx1 = in_off + ido - 1 + idx1; - - out.setFloat(oidx1, -in.getFloat(iidx1 + idx0)); - out.setFloat(oidx1 - 1, in.getFloat(iidx1)); - } - } - - /*------------------------------------------------- - radb2: Real FFT's backward processing of factor 2 - -------------------------------------------------*/ - void radb2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - int i, ic; - float t1i, t1r, w1r, w1i; - int iw1 = offset; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int idx3 = idx2 + ido; - int oidx1 = out_off + idx1; - int iidx1 = in_off + idx2; - int iidx2 = in_off + ido - 1 + idx3; - float i1r = in[iidx1]; - float i2r = in[iidx2]; - out[oidx1] = i1r + i2r; - out[oidx1 + idx0] = i1r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int idx5 = i - 1 + iw1; - int idx6 = out_off + i; - int idx7 = in_off + i; - int idx8 = in_off + ic; - w1r = wtable_r[idx5 - 1]; - w1i = wtable_r[idx5]; - int iidx1 = idx7 + idx2; - int iidx2 = idx8 + idx3; - int oidx1 = idx6 + idx1; - int oidx2 = idx6 + idx4; - t1r = in[iidx1 - 1] - in[iidx2 - 1]; - t1i = in[iidx1] + in[iidx2]; - float i1i = in[iidx1]; - float i1r = in[iidx1 - 1]; - float i2i = in[iidx2]; - float i2r = in[iidx2 - 1]; - - out[oidx1 - 1] = i1r + i2r; - out[oidx1] = i1i - i2i; - out[oidx2 - 1] = w1r * t1r - w1i * t1i; - out[oidx2] = w1r * t1i + w1i * t1r; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int oidx1 = out_off + ido - 1 + idx1; - int iidx1 = in_off + idx2 + ido; - out[oidx1] = 2 * in[iidx1 - 1]; - out[oidx1 + idx0] = -2 * in[iidx1]; - } - } - - /*------------------------------------------------- - radb2: Real FFT's backward processing of factor 2 - -------------------------------------------------*/ - void radb2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - long i, ic; - float t1i, t1r, w1r, w1i; - long iw1 = offset; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long idx3 = idx2 + ido; - long oidx1 = out_off + idx1; - long iidx1 = in_off + idx2; - long iidx2 = in_off + ido - 1 + idx3; - float i1r = in.getFloat(iidx1); - float i2r = in.getFloat(iidx2); - out.setFloat(oidx1, i1r + i2r); - out.setFloat(oidx1 + idx0, i1r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long idx5 = i - 1 + iw1; - long idx6 = out_off + i; - long idx7 = in_off + i; - long idx8 = in_off + ic; - w1r = wtable_rl.getFloat(idx5 - 1); - w1i = wtable_rl.getFloat(idx5); - long iidx1 = idx7 + idx2; - long iidx2 = idx8 + idx3; - long oidx1 = idx6 + idx1; - long oidx2 = idx6 + idx4; - t1r = in.getFloat(iidx1 - 1) - in.getFloat(iidx2 - 1); - t1i = in.getFloat(iidx1) + in.getFloat(iidx2); - float i1i = in.getFloat(iidx1); - float i1r = in.getFloat(iidx1 - 1); - float i2i = in.getFloat(iidx2); - float i2r = in.getFloat(iidx2 - 1); - - out.setFloat(oidx1 - 1, i1r + i2r); - out.setFloat(oidx1, i1i - i2i); - out.setFloat(oidx2 - 1, w1r * t1r - w1i * t1i); - out.setFloat(oidx2, w1r * t1i + w1i * t1r); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long oidx1 = out_off + ido - 1 + idx1; - long iidx1 = in_off + idx2 + ido; - out.setFloat(oidx1, 2 * in.getFloat(iidx1 - 1)); - out.setFloat(oidx1 + idx0, -2 * in.getFloat(iidx1)); - } - } - - /*------------------------------------------------- - radf3: Real FFT's forward processing of factor 3 - -------------------------------------------------*/ - void radf3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - int i, ic; - float ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; - int iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx3 = 2 * idx0; - int idx4 = (3 * k + 1) * ido; - int iidx1 = in_off + idx1; - int iidx2 = iidx1 + idx0; - int iidx3 = iidx1 + idx3; - float i1r = in[iidx1]; - float i2r = in[iidx2]; - float i3r = in[iidx3]; - cr2 = i2r + i3r; - out[out_off + 3 * idx1] = i1r + cr2; - out[out_off + idx4 + ido] = taui * (i3r - i2r); - out[out_off + ido - 1 + idx4] = i1r + taur * cr2; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int idx4 = 3 * idx3; - int idx5 = idx3 + idx0; - int idx6 = idx5 + idx0; - int idx7 = idx4 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - - int idx9 = in_off + i; - int idx10 = out_off + i; - int idx11 = out_off + ic; - int iidx1 = idx9 + idx3; - int iidx2 = idx9 + idx5; - int iidx3 = idx9 + idx6; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - cr2 = dr2 + dr3; - ci2 = di2 + di3; - tr2 = i1i + taur * cr2; - ti2 = i1r + taur * ci2; - tr3 = taui * (di2 - di3); - ti3 = taui * (dr3 - dr2); - - int oidx1 = idx10 + idx4; - int oidx2 = idx11 + idx7; - int oidx3 = idx10 + idx8; - - out[oidx1 - 1] = i1i + cr2; - out[oidx1] = i1r + ci2; - out[oidx2 - 1] = tr2 - tr3; - out[oidx2] = ti3 - ti2; - out[oidx3 - 1] = tr2 + tr3; - out[oidx3] = ti2 + ti3; - } - } - } - - /*------------------------------------------------- - radf3: Real FFT's forward processing of factor 3 - -------------------------------------------------*/ - void radf3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - long i, ic; - float ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; - long iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx3 = 2 * idx0; - long idx4 = (3 * k + 1) * ido; - long iidx1 = in_off + idx1; - long iidx2 = iidx1 + idx0; - long iidx3 = iidx1 + idx3; - float i1r = in.getFloat(iidx1); - float i2r = in.getFloat(iidx2); - float i3r = in.getFloat(iidx3); - cr2 = i2r + i3r; - out.setFloat(out_off + 3 * idx1, i1r + cr2); - out.setFloat(out_off + idx4 + ido, taui * (i3r - i2r)); - out.setFloat(out_off + ido - 1 + idx4, i1r + taur * cr2); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long idx4 = 3 * idx3; - long idx5 = idx3 + idx0; - long idx6 = idx5 + idx0; - long idx7 = idx4 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - - long idx9 = in_off + i; - long idx10 = out_off + i; - long idx11 = out_off + ic; - long iidx1 = idx9 + idx3; - long iidx2 = idx9 + idx5; - long iidx3 = idx9 + idx6; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - cr2 = dr2 + dr3; - ci2 = di2 + di3; - tr2 = i1i + taur * cr2; - ti2 = i1r + taur * ci2; - tr3 = taui * (di2 - di3); - ti3 = taui * (dr3 - dr2); - - long oidx1 = idx10 + idx4; - long oidx2 = idx11 + idx7; - long oidx3 = idx10 + idx8; - - out.setFloat(oidx1 - 1, i1i + cr2); - out.setFloat(oidx1, i1r + ci2); - out.setFloat(oidx2 - 1, tr2 - tr3); - out.setFloat(oidx2, ti3 - ti2); - out.setFloat(oidx3 - 1, tr2 + tr3); - out.setFloat(oidx3, ti2 + ti3); - } - } - } - - /*------------------------------------------------- - radb3: Real FFT's backward processing of factor 3 - -------------------------------------------------*/ - void radb3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - int i, ic; - float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; - int iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int iidx1 = in_off + 3 * idx1; - int iidx2 = iidx1 + 2 * ido; - float i1i = in[iidx1]; - - tr2 = 2 * in[iidx2 - 1]; - cr2 = i1i + taur * tr2; - ci3 = 2 * taui * in[iidx2]; - - out[out_off + idx1] = i1i + tr2; - out[out_off + (k + l1) * ido] = cr2 - ci3; - out[out_off + (k + 2 * l1) * ido] = cr2 + ci3; - } - if (ido == 1) { - return; - } - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 3 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx1 + idx0; - int idx6 = idx5 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = in_off + i; - int idx8 = in_off + ic; - int idx9 = out_off + i; - int iidx1 = idx7 + idx2; - int iidx2 = idx7 + idx4; - int iidx3 = idx8 + idx3; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - - tr2 = i2i + i3i; - cr2 = i1i + taur * tr2; - ti2 = i2r - i3r; - ci2 = i1r + taur * ti2; - cr3 = taui * (i2i - i3i); - ci3 = taui * (i2r + i3r); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - - int oidx1 = idx9 + idx1; - int oidx2 = idx9 + idx5; - int oidx3 = idx9 + idx6; - - out[oidx1 - 1] = i1i + tr2; - out[oidx1] = i1r + ti2; - out[oidx2 - 1] = w1r * dr2 - w1i * di2; - out[oidx2] = w1r * di2 + w1i * dr2; - out[oidx3 - 1] = w2r * dr3 - w2i * di3; - out[oidx3] = w2r * di3 + w2i * dr3; - } - } - } - - /*------------------------------------------------- - radb3: Real FFT's backward processing of factor 3 - -------------------------------------------------*/ - void radb3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - long i, ic; - float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; - long iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long iidx1 = in_off + 3 * idx1; - long iidx2 = iidx1 + 2 * ido; - float i1i = in.getFloat(iidx1); - - tr2 = 2 * in.getFloat(iidx2 - 1); - cr2 = i1i + taur * tr2; - ci3 = 2 * taui * in.getFloat(iidx2); - - out.setFloat(out_off + idx1, i1i + tr2); - out.setFloat(out_off + (k + l1) * ido, cr2 - ci3); - out.setFloat(out_off + (k + 2 * l1) * ido, cr2 + ci3); - } - if (ido == 1) { - return; - } - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 3 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx1 + idx0; - long idx6 = idx5 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = in_off + i; - long idx8 = in_off + ic; - long idx9 = out_off + i; - long iidx1 = idx7 + idx2; - long iidx2 = idx7 + idx4; - long iidx3 = idx8 + idx3; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - - tr2 = i2i + i3i; - cr2 = i1i + taur * tr2; - ti2 = i2r - i3r; - ci2 = i1r + taur * ti2; - cr3 = taui * (i2i - i3i); - ci3 = taui * (i2r + i3r); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - - long oidx1 = idx9 + idx1; - long oidx2 = idx9 + idx5; - long oidx3 = idx9 + idx6; - - out.setFloat(oidx1 - 1, i1i + tr2); - out.setFloat(oidx1, i1r + ti2); - out.setFloat(oidx2 - 1, w1r * dr2 - w1i * di2); - out.setFloat(oidx2, w1r * di2 + w1i * dr2); - out.setFloat(oidx3 - 1, w2r * dr3 - w2i * di3); - out.setFloat(oidx3, w2r * di3 + w2i * dr3); - } - } - } - - /*------------------------------------------------- - radf4: Real FFT's forward processing of factor 4 - -------------------------------------------------*/ - void radf4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float hsqt2 = 0.707106781186547572737310929369414225f; - int i, ic; - float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = offset + ido; - iw3 = iw2 + ido; - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - float i1r = in[in_off + idx1]; - float i2r = in[in_off + idx3]; - float i3r = in[in_off + idx4]; - float i4r = in[in_off + idx5]; - - tr1 = i2r + i4r; - tr2 = i1r + i3r; - - int oidx1 = out_off + idx2; - int oidx2 = out_off + idx6 + ido; - - out[oidx1] = tr1 + tr2; - out[oidx2 - 1 + ido + ido] = tr2 - tr1; - out[oidx2 - 1] = i1r - i3r; - out[oidx2] = i4r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 + idx0; - int idx3 = idx2 + idx0; - int idx4 = idx3 + idx0; - int idx5 = 4 * idx1; - int idx6 = idx5 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - - int idx9 = in_off + i; - int idx10 = out_off + i; - int idx11 = out_off + ic; - int iidx1 = idx9 + idx1; - int iidx2 = idx9 + idx2; - int iidx3 = idx9 + idx3; - int iidx4 = idx9 + idx4; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - - cr2 = w1r * i2i + w1i * i2r; - ci2 = w1r * i2r - w1i * i2i; - cr3 = w2r * i3i + w2i * i3r; - ci3 = w2r * i3r - w2i * i3i; - cr4 = w3r * i4i + w3i * i4r; - ci4 = w3r * i4r - w3i * i4i; - tr1 = cr2 + cr4; - tr4 = cr4 - cr2; - ti1 = ci2 + ci4; - ti4 = ci2 - ci4; - ti2 = i1r + ci3; - ti3 = i1r - ci3; - tr2 = i1i + cr3; - tr3 = i1i - cr3; - - int oidx1 = idx10 + idx5; - int oidx2 = idx11 + idx6; - int oidx3 = idx10 + idx7; - int oidx4 = idx11 + idx8; - - out[oidx1 - 1] = tr1 + tr2; - out[oidx4 - 1] = tr2 - tr1; - out[oidx1] = ti1 + ti2; - out[oidx4] = ti1 - ti2; - out[oidx3 - 1] = ti4 + tr3; - out[oidx2 - 1] = tr3 - ti4; - out[oidx3] = tr4 + ti3; - out[oidx2] = tr4 - ti3; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - int idx9 = in_off + ido; - int idx10 = out_off + ido; - - float i1i = in[idx9 - 1 + idx1]; - float i2i = in[idx9 - 1 + idx3]; - float i3i = in[idx9 - 1 + idx4]; - float i4i = in[idx9 - 1 + idx5]; - - ti1 = -hsqt2 * (i2i + i4i); - tr1 = hsqt2 * (i2i - i4i); - - out[idx10 - 1 + idx2] = tr1 + i1i; - out[idx10 - 1 + idx7] = i1i - tr1; - out[out_off + idx6] = ti1 - i3i; - out[out_off + idx8] = ti1 + i3i; - } - } - - /*------------------------------------------------- - radf4: Real FFT's forward processing of factor 4 - -------------------------------------------------*/ - void radf4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float hsqt2 = 0.707106781186547572737310929369414225f; - long i, ic; - float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = offset + ido; - iw3 = iw2 + ido; - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - float i1r = in.getFloat(in_off + idx1); - float i2r = in.getFloat(in_off + idx3); - float i3r = in.getFloat(in_off + idx4); - float i4r = in.getFloat(in_off + idx5); - - tr1 = i2r + i4r; - tr2 = i1r + i3r; - - long oidx1 = out_off + idx2; - long oidx2 = out_off + idx6 + ido; - - out.setFloat(oidx1, tr1 + tr2); - out.setFloat(oidx2 - 1 + ido + ido, tr2 - tr1); - out.setFloat(oidx2 - 1, i1r - i3r); - out.setFloat(oidx2, i4r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 + idx0; - long idx3 = idx2 + idx0; - long idx4 = idx3 + idx0; - long idx5 = 4 * idx1; - long idx6 = idx5 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - w3r = wtable_rl.getFloat(widx3 - 1); - w3i = wtable_rl.getFloat(widx3); - - long idx9 = in_off + i; - long idx10 = out_off + i; - long idx11 = out_off + ic; - long iidx1 = idx9 + idx1; - long iidx2 = idx9 + idx2; - long iidx3 = idx9 + idx3; - long iidx4 = idx9 + idx4; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - - cr2 = w1r * i2i + w1i * i2r; - ci2 = w1r * i2r - w1i * i2i; - cr3 = w2r * i3i + w2i * i3r; - ci3 = w2r * i3r - w2i * i3i; - cr4 = w3r * i4i + w3i * i4r; - ci4 = w3r * i4r - w3i * i4i; - tr1 = cr2 + cr4; - tr4 = cr4 - cr2; - ti1 = ci2 + ci4; - ti4 = ci2 - ci4; - ti2 = i1r + ci3; - ti3 = i1r - ci3; - tr2 = i1i + cr3; - tr3 = i1i - cr3; - - long oidx1 = idx10 + idx5; - long oidx2 = idx11 + idx6; - long oidx3 = idx10 + idx7; - long oidx4 = idx11 + idx8; - - out.setFloat(oidx1 - 1, tr1 + tr2); - out.setFloat(oidx4 - 1, tr2 - tr1); - out.setFloat(oidx1, ti1 + ti2); - out.setFloat(oidx4, ti1 - ti2); - out.setFloat(oidx3 - 1, ti4 + tr3); - out.setFloat(oidx2 - 1, tr3 - ti4); - out.setFloat(oidx3, tr4 + ti3); - out.setFloat(oidx2, tr4 - ti3); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - long idx9 = in_off + ido; - long idx10 = out_off + ido; - - float i1i = in.getFloat(idx9 - 1 + idx1); - float i2i = in.getFloat(idx9 - 1 + idx3); - float i3i = in.getFloat(idx9 - 1 + idx4); - float i4i = in.getFloat(idx9 - 1 + idx5); - - ti1 = -hsqt2 * (i2i + i4i); - tr1 = hsqt2 * (i2i - i4i); - - out.setFloat(idx10 - 1 + idx2, tr1 + i1i); - out.setFloat(idx10 - 1 + idx7, i1i - tr1); - out.setFloat(out_off + idx6, ti1 - i3i); - out.setFloat(out_off + idx8, ti1 + i3i); - } - } - - /*------------------------------------------------- - radb4: Real FFT's backward processing of factor 4 - -------------------------------------------------*/ - void radb4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float sqrt2 = 1.41421356237309514547462185873882845f; - int i, ic; - float ci2, ci3, ci4, cr2, cr3, cr4; - float ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - - float i1r = in[in_off + idx2]; - float i2r = in[in_off + idx7]; - float i3r = in[in_off + ido - 1 + idx8]; - float i4r = in[in_off + ido - 1 + idx6]; - - tr1 = i1r - i3r; - tr2 = i1r + i3r; - tr3 = i4r + i4r; - tr4 = i2r + i2r; - - out[out_off + idx1] = tr2 + tr3; - out[out_off + idx3] = tr1 - tr4; - out[out_off + idx4] = tr2 - tr3; - out[out_off + idx5] = tr1 + tr4; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = idx1 + idx0; - int idx3 = idx2 + idx0; - int idx4 = idx3 + idx0; - int idx5 = 4 * idx1; - int idx6 = idx5 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - - int idx12 = in_off + i; - int idx13 = in_off + ic; - int idx14 = out_off + i; - - int iidx1 = idx12 + idx5; - int iidx2 = idx13 + idx6; - int iidx3 = idx12 + idx7; - int iidx4 = idx13 + idx8; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - - ti1 = i1r + i4r; - ti2 = i1r - i4r; - ti3 = i3r - i2r; - tr4 = i3r + i2r; - tr1 = i1i - i4i; - tr2 = i1i + i4i; - ti4 = i3i - i2i; - tr3 = i3i + i2i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 - tr4; - cr4 = tr1 + tr4; - ci2 = ti1 + ti4; - ci4 = ti1 - ti4; - - int oidx1 = idx14 + idx1; - int oidx2 = idx14 + idx2; - int oidx3 = idx14 + idx3; - int oidx4 = idx14 + idx4; - - out[oidx1 - 1] = tr2 + tr3; - out[oidx1] = ti2 + ti3; - out[oidx2 - 1] = w1r * cr2 - w1i * ci2; - out[oidx2] = w1r * ci2 + w1i * cr2; - out[oidx3 - 1] = w2r * cr3 - w2i * ci3; - out[oidx3] = w2r * ci3 + w2i * cr3; - out[oidx4 - 1] = w3r * cr4 - w3i * ci4; - out[oidx4] = w3r * ci4 + w3i * cr4; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - int idx9 = in_off + ido; - int idx10 = out_off + ido; - - float i1r = in[idx9 - 1 + idx2]; - float i2r = in[idx9 - 1 + idx7]; - float i3r = in[in_off + idx6]; - float i4r = in[in_off + idx8]; - - ti1 = i3r + i4r; - ti2 = i4r - i3r; - tr1 = i1r - i2r; - tr2 = i1r + i2r; - - out[idx10 - 1 + idx1] = tr2 + tr2; - out[idx10 - 1 + idx3] = sqrt2 * (tr1 - ti1); - out[idx10 - 1 + idx4] = ti2 + ti2; - out[idx10 - 1 + idx5] = -sqrt2 * (tr1 + ti1); - } - } - - /*------------------------------------------------- - radb4: Real FFT's backward processing of factor 4 - -------------------------------------------------*/ - void radb4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float sqrt2 = 1.41421356237309514547462185873882845f; - long i, ic; - float ci2, ci3, ci4, cr2, cr3, cr4; - float ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - - float i1r = in.getFloat(in_off + idx2); - float i2r = in.getFloat(in_off + idx7); - float i3r = in.getFloat(in_off + ido - 1 + idx8); - float i4r = in.getFloat(in_off + ido - 1 + idx6); - - tr1 = i1r - i3r; - tr2 = i1r + i3r; - tr3 = i4r + i4r; - tr4 = i2r + i2r; - - out.setFloat(out_off + idx1, tr2 + tr3); - out.setFloat(out_off + idx3, tr1 - tr4); - out.setFloat(out_off + idx4, tr2 - tr3); - out.setFloat(out_off + idx5, tr1 + tr4); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = idx1 + idx0; - long idx3 = idx2 + idx0; - long idx4 = idx3 + idx0; - long idx5 = 4 * idx1; - long idx6 = idx5 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - w3r = wtable_rl.getFloat(widx3 - 1); - w3i = wtable_rl.getFloat(widx3); - - long idx12 = in_off + i; - long idx13 = in_off + ic; - long idx14 = out_off + i; - - long iidx1 = idx12 + idx5; - long iidx2 = idx13 + idx6; - long iidx3 = idx12 + idx7; - long iidx4 = idx13 + idx8; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - - ti1 = i1r + i4r; - ti2 = i1r - i4r; - ti3 = i3r - i2r; - tr4 = i3r + i2r; - tr1 = i1i - i4i; - tr2 = i1i + i4i; - ti4 = i3i - i2i; - tr3 = i3i + i2i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 - tr4; - cr4 = tr1 + tr4; - ci2 = ti1 + ti4; - ci4 = ti1 - ti4; - - long oidx1 = idx14 + idx1; - long oidx2 = idx14 + idx2; - long oidx3 = idx14 + idx3; - long oidx4 = idx14 + idx4; - - out.setFloat(oidx1 - 1, tr2 + tr3); - out.setFloat(oidx1, ti2 + ti3); - out.setFloat(oidx2 - 1, w1r * cr2 - w1i * ci2); - out.setFloat(oidx2, w1r * ci2 + w1i * cr2); - out.setFloat(oidx3 - 1, w2r * cr3 - w2i * ci3); - out.setFloat(oidx3, w2r * ci3 + w2i * cr3); - out.setFloat(oidx4 - 1, w3r * cr4 - w3i * ci4); - out.setFloat(oidx4, w3r * ci4 + w3i * cr4); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - long idx9 = in_off + ido; - long idx10 = out_off + ido; - - float i1r = in.getFloat(idx9 - 1 + idx2); - float i2r = in.getFloat(idx9 - 1 + idx7); - float i3r = in.getFloat(in_off + idx6); - float i4r = in.getFloat(in_off + idx8); - - ti1 = i3r + i4r; - ti2 = i4r - i3r; - tr1 = i1r - i2r; - tr2 = i1r + i2r; - - out.setFloat(idx10 - 1 + idx1, tr2 + tr2); - out.setFloat(idx10 - 1 + idx3, sqrt2 * (tr1 - ti1)); - out.setFloat(idx10 - 1 + idx4, ti2 + ti2); - out.setFloat(idx10 - 1 + idx5, -sqrt2 * (tr1 + ti1)); - } - } - - /*------------------------------------------------- - radf5: Real FFT's forward processing of factor 5 - -------------------------------------------------*/ - void radf5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - int i, ic; - float ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - int iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - int idx11 = out_off + ido - 1; - - float i1r = in[in_off + idx1]; - float i2r = in[in_off + idx7]; - float i3r = in[in_off + idx8]; - float i4r = in[in_off + idx9]; - float i5r = in[in_off + idx10]; - - cr2 = i5r + i2r; - ci5 = i5r - i2r; - cr3 = i4r + i3r; - ci4 = i4r - i3r; - - out[out_off + idx2] = i1r + cr2 + cr3; - out[idx11 + idx3] = i1r + tr11 * cr2 + tr12 * cr3; - out[out_off + idx4] = ti11 * ci5 + ti12 * ci4; - out[idx11 + idx5] = i1r + tr12 * cr2 + tr11 * cr3; - out[out_off + idx6] = ti12 * ci5 - ti11 * ci4; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - int widx4 = i - 1 + iw4; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - w4r = wtable_r[widx4 - 1]; - w4i = wtable_r[widx4]; - - ic = ido - i; - int idx15 = in_off + i; - int idx16 = out_off + i; - int idx17 = out_off + ic; - - int iidx1 = idx15 + idx1; - int iidx2 = idx15 + idx7; - int iidx3 = idx15 + idx8; - int iidx4 = idx15 + idx9; - int iidx5 = idx15 + idx10; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - float i5i = in[iidx5 - 1]; - float i5r = in[iidx5]; - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - dr4 = w3r * i4i + w3i * i4r; - di4 = w3r * i4r - w3i * i4i; - dr5 = w4r * i5i + w4i * i5r; - di5 = w4r * i5r - w4i * i5i; - - cr2 = dr2 + dr5; - ci5 = dr5 - dr2; - cr5 = di2 - di5; - ci2 = di2 + di5; - cr3 = dr3 + dr4; - ci4 = dr4 - dr3; - cr4 = di3 - di4; - ci3 = di3 + di4; - - tr2 = i1i + tr11 * cr2 + tr12 * cr3; - ti2 = i1r + tr11 * ci2 + tr12 * ci3; - tr3 = i1i + tr12 * cr2 + tr11 * cr3; - ti3 = i1r + tr12 * ci2 + tr11 * ci3; - tr5 = ti11 * cr5 + ti12 * cr4; - ti5 = ti11 * ci5 + ti12 * ci4; - tr4 = ti12 * cr5 - ti11 * cr4; - ti4 = ti12 * ci5 - ti11 * ci4; - - int oidx1 = idx16 + idx2; - int oidx2 = idx17 + idx3; - int oidx3 = idx16 + idx4; - int oidx4 = idx17 + idx5; - int oidx5 = idx16 + idx6; - - out[oidx1 - 1] = i1i + cr2 + cr3; - out[oidx1] = i1r + ci2 + ci3; - out[oidx3 - 1] = tr2 + tr5; - out[oidx2 - 1] = tr2 - tr5; - out[oidx3] = ti2 + ti5; - out[oidx2] = ti5 - ti2; - out[oidx5 - 1] = tr3 + tr4; - out[oidx4 - 1] = tr3 - tr4; - out[oidx5] = ti3 + ti4; - out[oidx4] = ti4 - ti3; - } - } - } - - /*------------------------------------------------- - radf5: Real FFT's forward processing of factor 5 - -------------------------------------------------*/ - void radf5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - long i, ic; - float ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - long iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - long idx11 = out_off + ido - 1; - - float i1r = in.getFloat(in_off + idx1); - float i2r = in.getFloat(in_off + idx7); - float i3r = in.getFloat(in_off + idx8); - float i4r = in.getFloat(in_off + idx9); - float i5r = in.getFloat(in_off + idx10); - - cr2 = i5r + i2r; - ci5 = i5r - i2r; - cr3 = i4r + i3r; - ci4 = i4r - i3r; - - out.setFloat(out_off + idx2, i1r + cr2 + cr3); - out.setFloat(idx11 + idx3, i1r + tr11 * cr2 + tr12 * cr3); - out.setFloat(out_off + idx4, ti11 * ci5 + ti12 * ci4); - out.setFloat(idx11 + idx5, i1r + tr12 * cr2 + tr11 * cr3); - out.setFloat(out_off + idx6, ti12 * ci5 - ti11 * ci4); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - long widx4 = i - 1 + iw4; - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - w3r = wtable_rl.getFloat(widx3 - 1); - w3i = wtable_rl.getFloat(widx3); - w4r = wtable_rl.getFloat(widx4 - 1); - w4i = wtable_rl.getFloat(widx4); - - ic = ido - i; - long idx15 = in_off + i; - long idx16 = out_off + i; - long idx17 = out_off + ic; - - long iidx1 = idx15 + idx1; - long iidx2 = idx15 + idx7; - long iidx3 = idx15 + idx8; - long iidx4 = idx15 + idx9; - long iidx5 = idx15 + idx10; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - float i5i = in.getFloat(iidx5 - 1); - float i5r = in.getFloat(iidx5); - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - dr4 = w3r * i4i + w3i * i4r; - di4 = w3r * i4r - w3i * i4i; - dr5 = w4r * i5i + w4i * i5r; - di5 = w4r * i5r - w4i * i5i; - - cr2 = dr2 + dr5; - ci5 = dr5 - dr2; - cr5 = di2 - di5; - ci2 = di2 + di5; - cr3 = dr3 + dr4; - ci4 = dr4 - dr3; - cr4 = di3 - di4; - ci3 = di3 + di4; - - tr2 = i1i + tr11 * cr2 + tr12 * cr3; - ti2 = i1r + tr11 * ci2 + tr12 * ci3; - tr3 = i1i + tr12 * cr2 + tr11 * cr3; - ti3 = i1r + tr12 * ci2 + tr11 * ci3; - tr5 = ti11 * cr5 + ti12 * cr4; - ti5 = ti11 * ci5 + ti12 * ci4; - tr4 = ti12 * cr5 - ti11 * cr4; - ti4 = ti12 * ci5 - ti11 * ci4; - - long oidx1 = idx16 + idx2; - long oidx2 = idx17 + idx3; - long oidx3 = idx16 + idx4; - long oidx4 = idx17 + idx5; - long oidx5 = idx16 + idx6; - - out.setFloat(oidx1 - 1, i1i + cr2 + cr3); - out.setFloat(oidx1, i1r + ci2 + ci3); - out.setFloat(oidx3 - 1, tr2 + tr5); - out.setFloat(oidx2 - 1, tr2 - tr5); - out.setFloat(oidx3, ti2 + ti5); - out.setFloat(oidx2, ti5 - ti2); - out.setFloat(oidx5 - 1, tr3 + tr4); - out.setFloat(oidx4 - 1, tr3 - tr4); - out.setFloat(oidx5, ti3 + ti4); - out.setFloat(oidx4, ti4 - ti3); - } - } - } - - /*------------------------------------------------- - radb5: Real FFT's backward processing of factor 5 - -------------------------------------------------*/ - void radb5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - int i, ic; - float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - int iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - int idx11 = in_off + ido - 1; - - float i1r = in[in_off + idx2]; - - ti5 = 2 * in[in_off + idx4]; - ti4 = 2 * in[in_off + idx6]; - tr2 = 2 * in[idx11 + idx3]; - tr3 = 2 * in[idx11 + idx5]; - cr2 = i1r + tr11 * tr2 + tr12 * tr3; - cr3 = i1r + tr12 * tr2 + tr11 * tr3; - ci5 = ti11 * ti5 + ti12 * ti4; - ci4 = ti12 * ti5 - ti11 * ti4; - - out[out_off + idx1] = i1r + tr2 + tr3; - out[out_off + idx7] = cr2 - ci5; - out[out_off + idx8] = cr3 - ci4; - out[out_off + idx9] = cr3 + ci4; - out[out_off + idx10] = cr2 + ci5; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - int widx4 = i - 1 + iw4; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - w4r = wtable_r[widx4 - 1]; - w4i = wtable_r[widx4]; - - int idx15 = in_off + i; - int idx16 = in_off + ic; - int idx17 = out_off + i; - - int iidx1 = idx15 + idx2; - int iidx2 = idx16 + idx3; - int iidx3 = idx15 + idx4; - int iidx4 = idx16 + idx5; - int iidx5 = idx15 + idx6; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - float i5i = in[iidx5 - 1]; - float i5r = in[iidx5]; - - ti5 = i3r + i2r; - ti2 = i3r - i2r; - ti4 = i5r + i4r; - ti3 = i5r - i4r; - tr5 = i3i - i2i; - tr2 = i3i + i2i; - tr4 = i5i - i4i; - tr3 = i5i + i4i; - - cr2 = i1i + tr11 * tr2 + tr12 * tr3; - ci2 = i1r + tr11 * ti2 + tr12 * ti3; - cr3 = i1i + tr12 * tr2 + tr11 * tr3; - ci3 = i1r + tr12 * ti2 + tr11 * ti3; - cr5 = ti11 * tr5 + ti12 * tr4; - ci5 = ti11 * ti5 + ti12 * ti4; - cr4 = ti12 * tr5 - ti11 * tr4; - ci4 = ti12 * ti5 - ti11 * ti4; - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - int oidx1 = idx17 + idx1; - int oidx2 = idx17 + idx7; - int oidx3 = idx17 + idx8; - int oidx4 = idx17 + idx9; - int oidx5 = idx17 + idx10; - - out[oidx1 - 1] = i1i + tr2 + tr3; - out[oidx1] = i1r + ti2 + ti3; - out[oidx2 - 1] = w1r * dr2 - w1i * di2; - out[oidx2] = w1r * di2 + w1i * dr2; - out[oidx3 - 1] = w2r * dr3 - w2i * di3; - out[oidx3] = w2r * di3 + w2i * dr3; - out[oidx4 - 1] = w3r * dr4 - w3i * di4; - out[oidx4] = w3r * di4 + w3i * dr4; - out[oidx5 - 1] = w4r * dr5 - w4i * di5; - out[oidx5] = w4r * di5 + w4i * dr5; - } - } - } - - /*------------------------------------------------- - radb5: Real FFT's backward processing of factor 5 - -------------------------------------------------*/ - void radb5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - long i, ic; - float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - long iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - long idx11 = in_off + ido - 1; - - float i1r = in.getFloat(in_off + idx2); - - ti5 = 2 * in.getFloat(in_off + idx4); - ti4 = 2 * in.getFloat(in_off + idx6); - tr2 = 2 * in.getFloat(idx11 + idx3); - tr3 = 2 * in.getFloat(idx11 + idx5); - cr2 = i1r + tr11 * tr2 + tr12 * tr3; - cr3 = i1r + tr12 * tr2 + tr11 * tr3; - ci5 = ti11 * ti5 + ti12 * ti4; - ci4 = ti12 * ti5 - ti11 * ti4; - - out.setFloat(out_off + idx1, i1r + tr2 + tr3); - out.setFloat(out_off + idx7, cr2 - ci5); - out.setFloat(out_off + idx8, cr3 - ci4); - out.setFloat(out_off + idx9, cr3 + ci4); - out.setFloat(out_off + idx10, cr2 + ci5); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - long widx4 = i - 1 + iw4; - w1r = wtable_rl.getFloat(widx1 - 1); - w1i = wtable_rl.getFloat(widx1); - w2r = wtable_rl.getFloat(widx2 - 1); - w2i = wtable_rl.getFloat(widx2); - w3r = wtable_rl.getFloat(widx3 - 1); - w3i = wtable_rl.getFloat(widx3); - w4r = wtable_rl.getFloat(widx4 - 1); - w4i = wtable_rl.getFloat(widx4); - - long idx15 = in_off + i; - long idx16 = in_off + ic; - long idx17 = out_off + i; - - long iidx1 = idx15 + idx2; - long iidx2 = idx16 + idx3; - long iidx3 = idx15 + idx4; - long iidx4 = idx16 + idx5; - long iidx5 = idx15 + idx6; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - float i5i = in.getFloat(iidx5 - 1); - float i5r = in.getFloat(iidx5); - - ti5 = i3r + i2r; - ti2 = i3r - i2r; - ti4 = i5r + i4r; - ti3 = i5r - i4r; - tr5 = i3i - i2i; - tr2 = i3i + i2i; - tr4 = i5i - i4i; - tr3 = i5i + i4i; - - cr2 = i1i + tr11 * tr2 + tr12 * tr3; - ci2 = i1r + tr11 * ti2 + tr12 * ti3; - cr3 = i1i + tr12 * tr2 + tr11 * tr3; - ci3 = i1r + tr12 * ti2 + tr11 * ti3; - cr5 = ti11 * tr5 + ti12 * tr4; - ci5 = ti11 * ti5 + ti12 * ti4; - cr4 = ti12 * tr5 - ti11 * tr4; - ci4 = ti12 * ti5 - ti11 * ti4; - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - long oidx1 = idx17 + idx1; - long oidx2 = idx17 + idx7; - long oidx3 = idx17 + idx8; - long oidx4 = idx17 + idx9; - long oidx5 = idx17 + idx10; - - out.setFloat(oidx1 - 1, i1i + tr2 + tr3); - out.setFloat(oidx1, i1r + ti2 + ti3); - out.setFloat(oidx2 - 1, w1r * dr2 - w1i * di2); - out.setFloat(oidx2, w1r * di2 + w1i * dr2); - out.setFloat(oidx3 - 1, w2r * dr3 - w2i * di3); - out.setFloat(oidx3, w2r * di3 + w2i * dr3); - out.setFloat(oidx4 - 1, w3r * dr4 - w3i * di4); - out.setFloat(oidx4, w3r * di4 + w3i * dr4); - out.setFloat(oidx5 - 1, w4r * dr5 - w4i * di5); - out.setFloat(oidx5, w4r * di5 + w4i * dr5); - } - } - } - - /*--------------------------------------------------------- - radfg: Real FFT's forward processing of general factor - --------------------------------------------------------*/ - void radfg(final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - int idij, ipph, j2, ic, jc, lc, is, nbd; - float dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; - int iw1 = offset; - - arg = TWO_PI / (float) ip; - dcp = (float)Math.cos(arg); - dsp = (float)Math.sin(arg); - ipph = (ip + 1) / 2; - nbd = (ido - 1) / 2; - if (ido != 1) { - for (int ik = 0; ik < idl1; ik++) { - out[out_off + ik] = in[in_off + ik]; - } - for (int j = 1; j < ip; j++) { - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido + idx1; - out[out_off + idx2] = in[in_off + idx2]; - } - } - if (nbd <= l1) { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - int idx1 = j * l1 * ido; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - int idx4 = in_off + i; - int idx5 = out_off + i; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int oidx1 = idx5 + idx3; - int iidx1 = idx4 + idx3; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - - out[oidx1 - 1] = w1r * i1i + w1i * i1r; - out[oidx1] = w1r * i1r - w1i * i1i; - } - } - } - } else { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = is - 1; - int idx3 = k * ido + idx1; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int oidx1 = out_off + i + idx3; - int iidx1 = in_off + i + idx3; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - - out[oidx1 - 1] = w1r * i1i + w1i * i1r; - out[oidx1] = w1r * i1r - w1i * i1i; - } - } - } - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - for (int i = 2; i < ido; i += 2) { - int idx5 = in_off + i; - int idx6 = out_off + i; - int iidx1 = idx5 + idx3; - int iidx2 = idx5 + idx4; - int oidx1 = idx6 + idx3; - int oidx2 = idx6 + idx4; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - float o2i = out[oidx2 - 1]; - float o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx1] = o1r + o2r; - - in[iidx2 - 1] = o1r - o2r; - in[iidx2] = o2i - o1i; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int i = 2; i < ido; i += 2) { - int idx5 = in_off + i; - int idx6 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - int iidx1 = idx5 + idx3; - int iidx2 = idx5 + idx4; - int oidx1 = idx6 + idx3; - int oidx2 = idx6 + idx4; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - float o2i = out[oidx2 - 1]; - float o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx1] = o1r + o2r; - in[iidx2 - 1] = o1r - o2r; - in[iidx2] = o2i - o1i; - } - } - } - } - } else { - System.arraycopy(out, out_off, in, in_off, idl1); - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - int oidx1 = out_off + idx3; - int oidx2 = out_off + idx4; - float o1r = out[oidx1]; - float o2r = out[oidx2]; - - in[in_off + idx3] = o1r + o2r; - in[in_off + idx4] = o2r - o1r; - } - } - - ar1 = 1; - ai1 = 0; - int idx0 = (ip - 1) * idl1; - for (int l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - int idx1 = l * idl1; - int idx2 = lc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx3 = out_off + ik; - int idx4 = in_off + ik; - out[idx3 + idx1] = in[idx4] + ar1 * in[idx4 + idl1]; - out[idx3 + idx2] = ai1 * in[idx4 + idx0]; - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - int idx3 = j * idl1; - int idx4 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx5 = out_off + ik; - int idx6 = in_off + ik; - out[idx5 + idx1] += ar2 * in[idx6 + idx3]; - out[idx5 + idx2] += ai2 * in[idx6 + idx4]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idx1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - out[out_off + ik] += in[in_off + ik + idx1]; - } - } - - if (ido >= l1) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 * ip; - for (int i = 0; i < ido; i++) { - in[in_off + i + idx2] = out[out_off + i + idx1]; - } - } - } else { - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - in[in_off + i + idx1 * ip] = out[out_off + i + idx1]; - } - } - } - int idx01 = ip * ido; - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido; - int idx5 = idx4 + idx1; - int idx6 = idx4 + idx2; - int idx7 = k * idx01; - in[in_off + ido - 1 + idx3 - ido + idx7] = out[out_off + idx5]; - in[in_off + idx3 + idx7] = out[out_off + idx6]; - } - } - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * idx01; - int idx5 = k * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx6 = in_off + i; - int idx7 = in_off + ic; - int idx8 = out_off + i; - int iidx1 = idx6 + idx3 + idx4; - int iidx2 = idx7 + idx3 - ido + idx4; - int oidx1 = idx8 + idx5 + idx1; - int oidx2 = idx8 + idx5 + idx2; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - float o2i = out[oidx2 - 1]; - float o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx2 - 1] = o1i - o2i; - in[iidx1] = o1r + o2r; - in[iidx2] = o2r - o1r; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx6 = in_off + i; - int idx7 = in_off + ic; - int idx8 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx4 = k * idx01; - int idx5 = k * ido; - int iidx1 = idx6 + idx3 + idx4; - int iidx2 = idx7 + idx3 - ido + idx4; - int oidx1 = idx8 + idx5 + idx1; - int oidx2 = idx8 + idx5 + idx2; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - float o2i = out[oidx2 - 1]; - float o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx2 - 1] = o1i - o2i; - in[iidx1] = o1r + o2r; - in[iidx2] = o2r - o1r; - } - } - } - } - } - - /*--------------------------------------------------------- - radfg: Real FFT's forward processing of general factor - --------------------------------------------------------*/ - void radfg(final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - long idij, ipph, j2, ic, jc, lc, is, nbd; - float dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; - long iw1 = offset; - - arg = TWO_PI / (float) ip; - dcp = (float)Math.cos(arg); - dsp = (float)Math.sin(arg); - ipph = (ip + 1) / 2; - nbd = (ido - 1) / 2; - if (ido != 1) { - for (long ik = 0; ik < idl1; ik++) { - out.setFloat(out_off + ik, in.getFloat(in_off + ik)); - } - for (long j = 1; j < ip; j++) { - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido + idx1; - out.setFloat(out_off + idx2, in.getFloat(in_off + idx2)); - } - } - if (nbd <= l1) { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - long idx1 = j * l1 * ido; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - long idx4 = in_off + i; - long idx5 = out_off + i; - w1r = wtable_rl.getFloat(idx2 - 1); - w1i = wtable_rl.getFloat(idx2); - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long oidx1 = idx5 + idx3; - long iidx1 = idx4 + idx3; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - - out.setFloat(oidx1 - 1, w1r * i1i + w1i * i1r); - out.setFloat(oidx1, w1r * i1r - w1i * i1i); - } - } - } - } else { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = is - 1; - long idx3 = k * ido + idx1; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getFloat(idx2 - 1); - w1i = wtable_rl.getFloat(idx2); - long oidx1 = out_off + i + idx3; - long iidx1 = in_off + i + idx3; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - - out.setFloat(oidx1 - 1, w1r * i1i + w1i * i1r); - out.setFloat(oidx1, w1r * i1r - w1i * i1i); - } - } - } - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - for (long i = 2; i < ido; i += 2) { - long idx5 = in_off + i; - long idx6 = out_off + i; - long iidx1 = idx5 + idx3; - long iidx2 = idx5 + idx4; - long oidx1 = idx6 + idx3; - long oidx2 = idx6 + idx4; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - float o2i = out.getFloat(oidx2 - 1); - float o2r = out.getFloat(oidx2); - - in.setFloat(iidx1 - 1, o1i + o2i); - in.setFloat(iidx1, o1r + o2r); - - in.setFloat(iidx2 - 1, o1r - o2r); - in.setFloat(iidx2, o2i - o1i); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long i = 2; i < ido; i += 2) { - long idx5 = in_off + i; - long idx6 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - long iidx1 = idx5 + idx3; - long iidx2 = idx5 + idx4; - long oidx1 = idx6 + idx3; - long oidx2 = idx6 + idx4; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - float o2i = out.getFloat(oidx2 - 1); - float o2r = out.getFloat(oidx2); - - in.setFloat(iidx1 - 1, o1i + o2i); - in.setFloat(iidx1, o1r + o2r); - in.setFloat(iidx2 - 1, o1r - o2r); - in.setFloat(iidx2, o2i - o1i); - } - } - } - } - } else { - Utilities.arraycopy(out, out_off, in, in_off, idl1); - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - long oidx1 = out_off + idx3; - long oidx2 = out_off + idx4; - float o1r = out.getFloat(oidx1); - float o2r = out.getFloat(oidx2); - - in.setFloat(in_off + idx3, o1r + o2r); - in.setFloat(in_off + idx4, o2r - o1r); - } - } - - ar1 = 1; - ai1 = 0; - long idx0 = (ip - 1) * idl1; - for (long l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - long idx1 = l * idl1; - long idx2 = lc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx3 = out_off + ik; - long idx4 = in_off + ik; - out.setFloat(idx3 + idx1, in.getFloat(idx4) + ar1 * in.getFloat(idx4 + idl1)); - out.setFloat(idx3 + idx2, ai1 * in.getFloat(idx4 + idx0)); - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - long idx3 = j * idl1; - long idx4 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx5 = out_off + ik; - long idx6 = in_off + ik; - out.setFloat(idx5 + idx1, out.getFloat(idx5 + idx1) + ar2 * in.getFloat(idx6 + idx3)); - out.setFloat(idx5 + idx2, out.getFloat(idx5 + idx2) + ai2 * in.getFloat(idx6 + idx4)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idx1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - out.setFloat(out_off + ik, out.getFloat(out_off + ik) + in.getFloat(in_off + ik + idx1)); - } - } - - if (ido >= l1) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 * ip; - for (long i = 0; i < ido; i++) { - in.setFloat(in_off + i + idx2, out.getFloat(out_off + i + idx1)); - } - } - } else { - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - in.setFloat(in_off + i + idx1 * ip, out.getFloat(out_off + i + idx1)); - } - } - } - long idx01 = ip * ido; - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido; - long idx5 = idx4 + idx1; - long idx6 = idx4 + idx2; - long idx7 = k * idx01; - in.setFloat(in_off + ido - 1 + idx3 - ido + idx7, out.getFloat(out_off + idx5)); - in.setFloat(in_off + idx3 + idx7, out.getFloat(out_off + idx6)); - } - } - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * idx01; - long idx5 = k * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx6 = in_off + i; - long idx7 = in_off + ic; - long idx8 = out_off + i; - long iidx1 = idx6 + idx3 + idx4; - long iidx2 = idx7 + idx3 - ido + idx4; - long oidx1 = idx8 + idx5 + idx1; - long oidx2 = idx8 + idx5 + idx2; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - float o2i = out.getFloat(oidx2 - 1); - float o2r = out.getFloat(oidx2); - - in.setFloat(iidx1 - 1, o1i + o2i); - in.setFloat(iidx2 - 1, o1i - o2i); - in.setFloat(iidx1, o1r + o2r); - in.setFloat(iidx2, o2r - o1r); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx6 = in_off + i; - long idx7 = in_off + ic; - long idx8 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx4 = k * idx01; - long idx5 = k * ido; - long iidx1 = idx6 + idx3 + idx4; - long iidx2 = idx7 + idx3 - ido + idx4; - long oidx1 = idx8 + idx5 + idx1; - long oidx2 = idx8 + idx5 + idx2; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - float o2i = out.getFloat(oidx2 - 1); - float o2r = out.getFloat(oidx2); - - in.setFloat(iidx1 - 1, o1i + o2i); - in.setFloat(iidx2 - 1, o1i - o2i); - in.setFloat(iidx1, o1r + o2r); - in.setFloat(iidx2, o2r - o1r); - } - } - } - } - } - - /*--------------------------------------------------------- - radbg: Real FFT's backward processing of general factor - --------------------------------------------------------*/ - void radbg(final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { - int idij, ipph, j2, ic, jc, lc, is; - float dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; - int nbd; - float dcp, arg, dsp, ar1h, ar2h; - int iw1 = offset; - - arg = TWO_PI / (float) ip; - dcp = (float)Math.cos(arg); - dsp = (float)Math.sin(arg); - nbd = (ido - 1) / 2; - ipph = (ip + 1) / 2; - int idx0 = ip * ido; - if (ido >= l1) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = k * idx0; - for (int i = 0; i < ido; i++) { - out[out_off + i + idx1] = in[in_off + i + idx2]; - } - } - } else { - for (int i = 0; i < ido; i++) { - int idx1 = out_off + i; - int idx2 = in_off + i; - for (int k = 0; k < l1; k++) { - out[idx1 + k * ido] = in[idx2 + k * idx0]; - } - } - } - int iidx0 = in_off + ido - 1; - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido; - int idx5 = idx4 * ip; - int iidx1 = iidx0 + idx3 + idx5 - ido; - int iidx2 = in_off + idx3 + idx5; - float i1r = in[iidx1]; - float i2r = in[iidx2]; - - out[out_off + idx4 + idx1] = i1r + i1r; - out[out_off + idx4 + idx2] = i2r + i2r; - } - } - - if (ido != 1) { - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = 2 * j * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido + idx1; - int idx5 = k * ido + idx2; - int idx6 = k * ip * ido + idx3; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = out_off + i; - int idx8 = in_off + ic; - int idx9 = in_off + i; - int oidx1 = idx7 + idx4; - int oidx2 = idx7 + idx5; - int iidx1 = idx9 + idx6; - int iidx2 = idx8 + idx6 - ido; - float a1i = in[iidx1 - 1]; - float a1r = in[iidx1]; - float a2i = in[iidx2 - 1]; - float a2r = in[iidx2]; - - out[oidx1 - 1] = a1i + a2i; - out[oidx2 - 1] = a1i - a2i; - out[oidx1] = a1r - a2r; - out[oidx2] = a1r + a2r; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = 2 * j * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = out_off + i; - int idx8 = in_off + ic; - int idx9 = in_off + i; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido + idx1; - int idx5 = k * ido + idx2; - int idx6 = k * ip * ido + idx3; - int oidx1 = idx7 + idx4; - int oidx2 = idx7 + idx5; - int iidx1 = idx9 + idx6; - int iidx2 = idx8 + idx6 - ido; - float a1i = in[iidx1 - 1]; - float a1r = in[iidx1]; - float a2i = in[iidx2 - 1]; - float a2r = in[iidx2]; - - out[oidx1 - 1] = a1i + a2i; - out[oidx2 - 1] = a1i - a2i; - out[oidx1] = a1r - a2r; - out[oidx2] = a1r + a2r; - } - } - } - } - } - - ar1 = 1; - ai1 = 0; - int idx01 = (ip - 1) * idl1; - for (int l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - int idx1 = l * idl1; - int idx2 = lc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx3 = in_off + ik; - int idx4 = out_off + ik; - in[idx3 + idx1] = out[idx4] + ar1 * out[idx4 + idl1]; - in[idx3 + idx2] = ai1 * out[idx4 + idx01]; - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - int idx5 = j * idl1; - int idx6 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx7 = in_off + ik; - int idx8 = out_off + ik; - in[idx7 + idx1] += ar2 * out[idx8 + idx5]; - in[idx7 + idx2] += ai2 * out[idx8 + idx6]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idx1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx2 = out_off + ik; - out[idx2] += out[idx2 + idx1]; - } - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int oidx1 = out_off + idx3; - int iidx1 = in_off + idx3 + idx1; - int iidx2 = in_off + idx3 + idx2; - float i1r = in[iidx1]; - float i2r = in[iidx2]; - - out[oidx1 + idx1] = i1r - i2r; - out[oidx1 + idx2] = i1r + i2r; - } - } - - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - for (int i = 2; i < ido; i += 2) { - int idx4 = out_off + i; - int idx5 = in_off + i; - int oidx1 = idx4 + idx3 + idx1; - int oidx2 = idx4 + idx3 + idx2; - int iidx1 = idx5 + idx3 + idx1; - int iidx2 = idx5 + idx3 + idx2; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int i = 2; i < ido; i += 2) { - int idx4 = out_off + i; - int idx5 = in_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int oidx1 = idx4 + idx3 + idx1; - int oidx2 = idx4 + idx3 + idx2; - int iidx1 = idx5 + idx3 + idx1; - int iidx2 = idx5 + idx3 + idx2; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - } - } - System.arraycopy(out, out_off, in, in_off, idl1); - for (int j = 1; j < ip; j++) { - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido + idx1; - in[in_off + idx2] = out[out_off + idx2]; - } - } - if (nbd <= l1) { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - int idx1 = j * l1 * ido; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int idx4 = in_off + i; - int idx5 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int iidx1 = idx4 + idx3; - int oidx1 = idx5 + idx3; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } else { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = is - 1; - int idx3 = k * ido + idx1; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int idx4 = in_off + i; - int idx5 = out_off + i; - int iidx1 = idx4 + idx3; - int oidx1 = idx5 + idx3; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - - } - } - } - } - } - - /*--------------------------------------------------------- - radbg: Real FFT's backward processing of general factor - --------------------------------------------------------*/ - void radbg(final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { - long idij, ipph, j2, ic, jc, lc, is; - float dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; - long nbd; - float dcp, arg, dsp, ar1h, ar2h; - long iw1 = offset; - - arg = TWO_PI / (float) ip; - dcp = (float)Math.cos(arg); - dsp = (float)Math.sin(arg); - nbd = (ido - 1) / 2; - ipph = (ip + 1) / 2; - long idx0 = ip * ido; - if (ido >= l1) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = k * idx0; - for (long i = 0; i < ido; i++) { - out.setFloat(out_off + i + idx1, in.getFloat(in_off + i + idx2)); - } - } - } else { - for (long i = 0; i < ido; i++) { - long idx1 = out_off + i; - long idx2 = in_off + i; - for (long k = 0; k < l1; k++) { - out.setFloat(idx1 + k * ido, in.getFloat(idx2 + k * idx0)); - } - } - } - long iidx0 = in_off + ido - 1; - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido; - long idx5 = idx4 * ip; - long iidx1 = iidx0 + idx3 + idx5 - ido; - long iidx2 = in_off + idx3 + idx5; - float i1r = in.getFloat(iidx1); - float i2r = in.getFloat(iidx2); - - out.setFloat(out_off + idx4 + idx1, i1r + i1r); - out.setFloat(out_off + idx4 + idx2, i2r + i2r); - } - } - - if (ido != 1) { - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = 2 * j * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido + idx1; - long idx5 = k * ido + idx2; - long idx6 = k * ip * ido + idx3; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = out_off + i; - long idx8 = in_off + ic; - long idx9 = in_off + i; - long oidx1 = idx7 + idx4; - long oidx2 = idx7 + idx5; - long iidx1 = idx9 + idx6; - long iidx2 = idx8 + idx6 - ido; - float a1i = in.getFloat(iidx1 - 1); - float a1r = in.getFloat(iidx1); - float a2i = in.getFloat(iidx2 - 1); - float a2r = in.getFloat(iidx2); - - out.setFloat(oidx1 - 1, a1i + a2i); - out.setFloat(oidx2 - 1, a1i - a2i); - out.setFloat(oidx1, a1r - a2r); - out.setFloat(oidx2, a1r + a2r); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = 2 * j * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = out_off + i; - long idx8 = in_off + ic; - long idx9 = in_off + i; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido + idx1; - long idx5 = k * ido + idx2; - long idx6 = k * ip * ido + idx3; - long oidx1 = idx7 + idx4; - long oidx2 = idx7 + idx5; - long iidx1 = idx9 + idx6; - long iidx2 = idx8 + idx6 - ido; - float a1i = in.getFloat(iidx1 - 1); - float a1r = in.getFloat(iidx1); - float a2i = in.getFloat(iidx2 - 1); - float a2r = in.getFloat(iidx2); - - out.setFloat(oidx1 - 1, a1i + a2i); - out.setFloat(oidx2 - 1, a1i - a2i); - out.setFloat(oidx1, a1r - a2r); - out.setFloat(oidx2, a1r + a2r); - } - } - } - } - } - - ar1 = 1; - ai1 = 0; - long idx01 = (ip - 1) * idl1; - for (long l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - long idx1 = l * idl1; - long idx2 = lc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx3 = in_off + ik; - long idx4 = out_off + ik; - in.setFloat(idx3 + idx1, out.getFloat(idx4) + ar1 * out.getFloat(idx4 + idl1)); - in.setFloat(idx3 + idx2, ai1 * out.getFloat(idx4 + idx01)); - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - long idx5 = j * idl1; - long idx6 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx7 = in_off + ik; - long idx8 = out_off + ik; - in.setFloat(idx7 + idx1, in.getFloat(idx7 + idx1) + ar2 * out.getFloat(idx8 + idx5)); - in.setFloat(idx7 + idx2, in.getFloat(idx7 + idx2) + ai2 * out.getFloat(idx8 + idx6)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idx1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx2 = out_off + ik; - out.setFloat(idx2, out.getFloat(idx2) + out.getFloat(idx2 + idx1)); - } - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long oidx1 = out_off + idx3; - long iidx1 = in_off + idx3 + idx1; - long iidx2 = in_off + idx3 + idx2; - float i1r = in.getFloat(iidx1); - float i2r = in.getFloat(iidx2); - - out.setFloat(oidx1 + idx1, i1r - i2r); - out.setFloat(oidx1 + idx2, i1r + i2r); - } - } - - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - for (long i = 2; i < ido; i += 2) { - long idx4 = out_off + i; - long idx5 = in_off + i; - long oidx1 = idx4 + idx3 + idx1; - long oidx2 = idx4 + idx3 + idx2; - long iidx1 = idx5 + idx3 + idx1; - long iidx2 = idx5 + idx3 + idx2; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - - out.setFloat(oidx1 - 1, i1i - i2r); - out.setFloat(oidx2 - 1, i1i + i2r); - out.setFloat(oidx1, i1r + i2i); - out.setFloat(oidx2, i1r - i2i); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long i = 2; i < ido; i += 2) { - long idx4 = out_off + i; - long idx5 = in_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long oidx1 = idx4 + idx3 + idx1; - long oidx2 = idx4 + idx3 + idx2; - long iidx1 = idx5 + idx3 + idx1; - long iidx2 = idx5 + idx3 + idx2; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - - out.setFloat(oidx1 - 1, i1i - i2r); - out.setFloat(oidx2 - 1, i1i + i2r); - out.setFloat(oidx1, i1r + i2i); - out.setFloat(oidx2, i1r - i2i); - } - } - } - } - Utilities.arraycopy(out, out_off, in, in_off, idl1); - for (long j = 1; j < ip; j++) { - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido + idx1; - in.setFloat(in_off + idx2, out.getFloat(out_off + idx2)); - } - } - if (nbd <= l1) { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - long idx1 = j * l1 * ido; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getFloat(idx2 - 1); - w1i = wtable_rl.getFloat(idx2); - long idx4 = in_off + i; - long idx5 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long iidx1 = idx4 + idx3; - long oidx1 = idx5 + idx3; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - - in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setFloat(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } else { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = is - 1; - long idx3 = k * ido + idx1; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getFloat(idx2 - 1); - w1i = wtable_rl.getFloat(idx2); - long idx4 = in_off + i; - long idx5 = out_off + i; - long iidx1 = idx4 + idx3; - long oidx1 = idx5 + idx3; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - - in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setFloat(iidx1, w1r * o1r + w1i * o1i); - - } - } - } - } - } - - /*--------------------------------------------------------- - cfftf1: further processing of Complex forward FFT - --------------------------------------------------------*/ - void cfftf(float a[], int offa, int isign) { - int idot; - int l1, l2; - int na, nf, ipll, iw, ido, idl1; - int[] nac = new int[1]; - final int twon = 2 * n; - - int iw1, iw2; - float[] ch = new float[twon]; - - iw1 = twon; - iw2 = 4 * n; - nac[0] = 0; - nf = (int) wtable[1 + iw2]; - na = 0; - l1 = 1; - iw = iw1; - for (int k1 = 2; k1 <= nf + 1; k1++) { - ipll = (int) wtable[k1 + iw2]; - l2 = ipll * l1; - ido = n / l2; - idot = ido + ido; - idl1 = idot * l1; - switch (ipll) { - case 4: - if (na == 0) { - passf4(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf4(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 2: - if (na == 0) { - passf2(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf2(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - passf3(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf3(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - passf5(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf5(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - default: - if (na == 0) { - passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); - } else { - passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); - } - if (nac[0] != 0) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * idot; - } - if (na == 0) { - return; - } - System.arraycopy(ch, 0, a, offa, twon); - - } - - /*--------------------------------------------------------- - cfftf1: further processing of Complex forward FFT - --------------------------------------------------------*/ - void cfftf(FloatLargeArray a, long offa, int isign) { - long idot; - long l1, l2; - long na, nf, iw, ido, idl1; - int[] nac = new int[1]; - final long twon = 2 * nl; - int ipll; - - long iw1, iw2; - FloatLargeArray ch = new FloatLargeArray(twon, false); - - iw1 = twon; - iw2 = 4 * nl; - nac[0] = 0; - nf = (long) wtablel.getFloat(1 + iw2); - na = 0; - l1 = 1; - iw = iw1; - for (long k1 = 2; k1 <= nf + 1; k1++) { - ipll = (int) wtablel.getFloat(k1 + iw2); - l2 = ipll * l1; - ido = nl / l2; - idot = ido + ido; - idl1 = idot * l1; - switch (ipll) { - case 4: - if (na == 0) { - passf4(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf4(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 2: - if (na == 0) { - passf2(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf2(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - passf3(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf3(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - passf5(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf5(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - default: - if (na == 0) { - passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); - } else { - passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); - } - if (nac[0] != 0) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * idot; - } - if (na == 0) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, twon); - - } - - /*---------------------------------------------------------------------- - passf2: Complex FFT's forward/backward processing of factor 2; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { - float t1i, t1r; - int iw1; - iw1 = offset; - int idx = ido * l1; - if (ido <= 2) { - for (int k = 0; k < l1; k++) { - int idx0 = k * ido; - int iidx1 = in_off + 2 * idx0; - int iidx2 = iidx1 + ido; - float a1r = in[iidx1]; - float a1i = in[iidx1 + 1]; - float a2r = in[iidx2]; - float a2i = in[iidx2 + 1]; - - int oidx1 = out_off + idx0; - int oidx2 = oidx1 + idx; - out[oidx1] = a1r + a2r; - out[oidx1 + 1] = a1i + a2i; - out[oidx2] = a1r - a2r; - out[oidx2 + 1] = a1i - a2i; - } - } else { - for (int k = 0; k < l1; k++) { - for (int i = 0; i < ido - 1; i += 2) { - int idx0 = k * ido; - int iidx1 = in_off + i + 2 * idx0; - int iidx2 = iidx1 + ido; - float i1r = in[iidx1]; - float i1i = in[iidx1 + 1]; - float i2r = in[iidx2]; - float i2i = in[iidx2 + 1]; - - int widx1 = i + iw1; - float w1r = wtable[widx1]; - float w1i = isign * wtable[widx1 + 1]; - - t1r = i1r - i2r; - t1i = i1i - i2i; - - int oidx1 = out_off + i + idx0; - int oidx2 = oidx1 + idx; - out[oidx1] = i1r + i2r; - out[oidx1 + 1] = i1i + i2i; - out[oidx2] = w1r * t1r - w1i * t1i; - out[oidx2 + 1] = w1r * t1i + w1i * t1r; - } - } - } - } - - /*---------------------------------------------------------------------- - passf2: Complex FFT's forward/backward processing of factor 2; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { - float t1i, t1r; - long iw1; - iw1 = offset; - long idx = ido * l1; - if (ido <= 2) { - for (long k = 0; k < l1; k++) { - long idx0 = k * ido; - long iidx1 = in_off + 2 * idx0; - long iidx2 = iidx1 + ido; - float a1r = in.getFloat(iidx1); - float a1i = in.getFloat(iidx1 + 1); - float a2r = in.getFloat(iidx2); - float a2i = in.getFloat(iidx2 + 1); - - long oidx1 = out_off + idx0; - long oidx2 = oidx1 + idx; - out.setFloat(oidx1, a1r + a2r); - out.setFloat(oidx1 + 1, a1i + a2i); - out.setFloat(oidx2, a1r - a2r); - out.setFloat(oidx2 + 1, a1i - a2i); - } - } else { - for (long k = 0; k < l1; k++) { - for (long i = 0; i < ido - 1; i += 2) { - long idx0 = k * ido; - long iidx1 = in_off + i + 2 * idx0; - long iidx2 = iidx1 + ido; - float i1r = in.getFloat(iidx1); - float i1i = in.getFloat(iidx1 + 1); - float i2r = in.getFloat(iidx2); - float i2i = in.getFloat(iidx2 + 1); - - long widx1 = i + iw1; - float w1r = wtablel.getFloat(widx1); - float w1i = isign * wtablel.getFloat(widx1 + 1); - - t1r = i1r - i2r; - t1i = i1i - i2i; - - long oidx1 = out_off + i + idx0; - long oidx2 = oidx1 + idx; - out.setFloat(oidx1, i1r + i2r); - out.setFloat(oidx1 + 1, i1i + i2i); - out.setFloat(oidx2, w1r * t1r - w1i * t1i); - out.setFloat(oidx2 + 1, w1r * t1i + w1i * t1r); - } - } - } - } - - /*---------------------------------------------------------------------- - passf3: Complex FFT's forward/backward processing of factor 3; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; - int iw1, iw2; - - iw1 = offset; - iw2 = iw1 + ido; - - final int idxt = l1 * ido; - - if (ido == 2) { - for (int k = 1; k <= l1; k++) { - int iidx1 = in_off + (3 * k - 2) * ido; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - float i1r = in[iidx1]; - float i1i = in[iidx1 + 1]; - float i2r = in[iidx2]; - float i2i = in[iidx2 + 1]; - float i3r = in[iidx3]; - float i3i = in[iidx3 + 1]; - - tr2 = i1r + i2r; - cr2 = i3r + taur * tr2; - ti2 = i1i + i2i; - ci2 = i3i + taur * ti2; - cr3 = isign * taui * (i1r - i2r); - ci3 = isign * taui * (i1i - i2i); - - int oidx1 = out_off + (k - 1) * ido; - int oidx2 = oidx1 + idxt; - int oidx3 = oidx2 + idxt; - out[oidx1] = in[iidx3] + tr2; - out[oidx1 + 1] = i3i + ti2; - out[oidx2] = cr2 - ci3; - out[oidx2 + 1] = ci2 + cr3; - out[oidx3] = cr2 + ci3; - out[oidx3 + 1] = ci2 - cr3; - } - } else { - for (int k = 1; k <= l1; k++) { - int idx1 = in_off + (3 * k - 2) * ido; - int idx2 = out_off + (k - 1) * ido; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - float a1r = in[iidx1]; - float a1i = in[iidx1 + 1]; - float a2r = in[iidx2]; - float a2i = in[iidx2 + 1]; - float a3r = in[iidx3]; - float a3i = in[iidx3 + 1]; - - tr2 = a1r + a2r; - cr2 = a3r + taur * tr2; - ti2 = a1i + a2i; - ci2 = a3i + taur * ti2; - cr3 = isign * taui * (a1r - a2r); - ci3 = isign * taui * (a1i - a2i); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - int widx1 = i + iw1; - int widx2 = i + iw2; - float w1r = wtable[widx1]; - float w1i = isign * wtable[widx1 + 1]; - float w2r = wtable[widx2]; - float w2i = isign * wtable[widx2 + 1]; - - int oidx1 = i + idx2; - int oidx2 = oidx1 + idxt; - int oidx3 = oidx2 + idxt; - out[oidx1] = a3r + tr2; - out[oidx1 + 1] = a3i + ti2; - out[oidx2] = w1r * dr2 - w1i * di2; - out[oidx2 + 1] = w1r * di2 + w1i * dr2; - out[oidx3] = w2r * dr3 - w2i * di3; - out[oidx3 + 1] = w2r * di3 + w2i * dr3; - } - } - } - } - - /*---------------------------------------------------------------------- - passf3: Complex FFT's forward/backward processing of factor 3; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { - final float taur = -0.5f; - final float taui = 0.866025403784438707610604524234076962f; - float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; - long iw1, iw2; - - iw1 = offset; - iw2 = iw1 + ido; - - final long idxt = l1 * ido; - - if (ido == 2) { - for (long k = 1; k <= l1; k++) { - long iidx1 = in_off + (3 * k - 2) * ido; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - float i1r = in.getFloat(iidx1); - float i1i = in.getFloat(iidx1 + 1); - float i2r = in.getFloat(iidx2); - float i2i = in.getFloat(iidx2 + 1); - float i3r = in.getFloat(iidx3); - float i3i = in.getFloat(iidx3 + 1); - - tr2 = i1r + i2r; - cr2 = i3r + taur * tr2; - ti2 = i1i + i2i; - ci2 = i3i + taur * ti2; - cr3 = isign * taui * (i1r - i2r); - ci3 = isign * taui * (i1i - i2i); - - long oidx1 = out_off + (k - 1) * ido; - long oidx2 = oidx1 + idxt; - long oidx3 = oidx2 + idxt; - out.setFloat(oidx1, in.getFloat(iidx3) + tr2); - out.setFloat(oidx1 + 1, i3i + ti2); - out.setFloat(oidx2, cr2 - ci3); - out.setFloat(oidx2 + 1, ci2 + cr3); - out.setFloat(oidx3, cr2 + ci3); - out.setFloat(oidx3 + 1, ci2 - cr3); - } - } else { - for (long k = 1; k <= l1; k++) { - long idx1 = in_off + (3 * k - 2) * ido; - long idx2 = out_off + (k - 1) * ido; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - float a1r = in.getFloat(iidx1); - float a1i = in.getFloat(iidx1 + 1); - float a2r = in.getFloat(iidx2); - float a2i = in.getFloat(iidx2 + 1); - float a3r = in.getFloat(iidx3); - float a3i = in.getFloat(iidx3 + 1); - - tr2 = a1r + a2r; - cr2 = a3r + taur * tr2; - ti2 = a1i + a2i; - ci2 = a3i + taur * ti2; - cr3 = isign * taui * (a1r - a2r); - ci3 = isign * taui * (a1i - a2i); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - long widx1 = i + iw1; - long widx2 = i + iw2; - float w1r = wtablel.getFloat(widx1); - float w1i = isign * wtablel.getFloat(widx1 + 1); - float w2r = wtablel.getFloat(widx2); - float w2i = isign * wtablel.getFloat(widx2 + 1); - - long oidx1 = i + idx2; - long oidx2 = oidx1 + idxt; - long oidx3 = oidx2 + idxt; - out.setFloat(oidx1, a3r + tr2); - out.setFloat(oidx1 + 1, a3i + ti2); - out.setFloat(oidx2, w1r * dr2 - w1i * di2); - out.setFloat(oidx2 + 1, w1r * di2 + w1i * dr2); - out.setFloat(oidx3, w2r * dr3 - w2i * di3); - out.setFloat(oidx3 + 1, w2r * di3 + w2i * dr3); - } - } - } - } - - /*---------------------------------------------------------------------- - passf4: Complex FFT's forward/backward processing of factor 4; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { - float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - int idx0 = l1 * ido; - if (ido == 2) { - for (int k = 0; k < l1; k++) { - int idxt1 = k * ido; - int iidx1 = in_off + 4 * idxt1 + 1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx2 + ido; - int iidx4 = iidx3 + ido; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - tr4 = i4r - i2r; - ti3 = i2r + i4r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - - int oidx1 = out_off + idxt1; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - out[oidx1] = tr2 + tr3; - out[oidx1 + 1] = ti2 + ti3; - out[oidx2] = tr1 + isign * tr4; - out[oidx2 + 1] = ti1 + isign * ti4; - out[oidx3] = tr2 - tr3; - out[oidx3 + 1] = ti2 - ti3; - out[oidx4] = tr1 - isign * tr4; - out[oidx4 + 1] = ti1 - isign * ti4; - } - } else { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = in_off + 1 + 4 * idx1; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx2; - int iidx2 = iidx1 + ido; - int iidx3 = iidx2 + ido; - int iidx4 = iidx3 + ido; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - ti3 = i2r + i4r; - tr4 = i4r - i2r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 + isign * tr4; - cr4 = tr1 - isign * tr4; - ci2 = ti1 + isign * ti4; - ci4 = ti1 - isign * ti4; - - int widx1 = i + iw1; - int widx2 = i + iw2; - int widx3 = i + iw3; - float w1r = wtable[widx1]; - float w1i = isign * wtable[widx1 + 1]; - float w2r = wtable[widx2]; - float w2i = isign * wtable[widx2 + 1]; - float w3r = wtable[widx3]; - float w3i = isign * wtable[widx3 + 1]; - - int oidx1 = out_off + i + idx1; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - out[oidx1] = tr2 + tr3; - out[oidx1 + 1] = ti2 + ti3; - out[oidx2] = w1r * cr2 - w1i * ci2; - out[oidx2 + 1] = w1r * ci2 + w1i * cr2; - out[oidx3] = w2r * cr3 - w2i * ci3; - out[oidx3 + 1] = w2r * ci3 + w2i * cr3; - out[oidx4] = w3r * cr4 - w3i * ci4; - out[oidx4 + 1] = w3r * ci4 + w3i * cr4; - } - } - } - } - - /*---------------------------------------------------------------------- - passf4: Complex FFT's forward/backward processing of factor 4; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final int isign) { - float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - long idx0 = l1 * ido; - if (ido == 2) { - for (long k = 0; k < l1; k++) { - long idxt1 = k * ido; - long iidx1 = in_off + 4 * idxt1 + 1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx2 + ido; - long iidx4 = iidx3 + ido; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - tr4 = i4r - i2r; - ti3 = i2r + i4r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - - long oidx1 = out_off + idxt1; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - out.setFloat(oidx1, tr2 + tr3); - out.setFloat(oidx1 + 1, ti2 + ti3); - out.setFloat(oidx2, tr1 + isign * tr4); - out.setFloat(oidx2 + 1, ti1 + isign * ti4); - out.setFloat(oidx3, tr2 - tr3); - out.setFloat(oidx3 + 1, ti2 - ti3); - out.setFloat(oidx4, tr1 - isign * tr4); - out.setFloat(oidx4 + 1, ti1 - isign * ti4); - } - } else { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = in_off + 1 + 4 * idx1; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx2; - long iidx2 = iidx1 + ido; - long iidx3 = iidx2 + ido; - long iidx4 = iidx3 + ido; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - ti3 = i2r + i4r; - tr4 = i4r - i2r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 + isign * tr4; - cr4 = tr1 - isign * tr4; - ci2 = ti1 + isign * ti4; - ci4 = ti1 - isign * ti4; - - long widx1 = i + iw1; - long widx2 = i + iw2; - long widx3 = i + iw3; - float w1r = wtablel.getFloat(widx1); - float w1i = isign * wtablel.getFloat(widx1 + 1); - float w2r = wtablel.getFloat(widx2); - float w2i = isign * wtablel.getFloat(widx2 + 1); - float w3r = wtablel.getFloat(widx3); - float w3i = isign * wtablel.getFloat(widx3 + 1); - - long oidx1 = out_off + i + idx1; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - out.setFloat(oidx1, tr2 + tr3); - out.setFloat(oidx1 + 1, ti2 + ti3); - out.setFloat(oidx2, w1r * cr2 - w1i * ci2); - out.setFloat(oidx2 + 1, w1r * ci2 + w1i * cr2); - out.setFloat(oidx3, w2r * cr3 - w2i * ci3); - out.setFloat(oidx3 + 1, w2r * ci3 + w2i * cr3); - out.setFloat(oidx4, w3r * cr4 - w3i * ci4); - out.setFloat(oidx4 + 1, w3r * ci4 + w3i * cr4); - } - } - } - } - - /*---------------------------------------------------------------------- - passf5: Complex FFT's forward/backward processing of factor 5; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) /* isign==-1 for forward transform and+1 for backward transform */ { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; - int iw1, iw2, iw3, iw4; - - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - - if (ido == 2) { - for (int k = 1; k <= l1; ++k) { - int iidx1 = in_off + (5 * k - 4) * ido + 1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - int iidx4 = iidx2 + ido; - int iidx5 = iidx4 + ido; - - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - float i5i = in[iidx5 - 1]; - float i5r = in[iidx5]; - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - - int oidx1 = out_off + (k - 1) * ido; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - int oidx5 = oidx4 + idx0; - out[oidx1] = i3i + tr2 + tr3; - out[oidx1 + 1] = i3r + ti2 + ti3; - out[oidx2] = cr2 - ci5; - out[oidx2 + 1] = ci2 + cr5; - out[oidx3] = cr3 - ci4; - out[oidx3 + 1] = ci3 + cr4; - out[oidx4] = cr3 + ci4; - out[oidx4 + 1] = ci3 - cr4; - out[oidx5] = cr2 + ci5; - out[oidx5 + 1] = ci2 - cr5; - } - } else { - for (int k = 1; k <= l1; k++) { - int idx1 = in_off + 1 + (k * 5 - 4) * ido; - int idx2 = out_off + (k - 1) * ido; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - int iidx4 = iidx2 + ido; - int iidx5 = iidx4 + ido; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - float i3i = in[iidx3 - 1]; - float i3r = in[iidx3]; - float i4i = in[iidx4 - 1]; - float i4r = in[iidx4]; - float i5i = in[iidx5 - 1]; - float i5r = in[iidx5]; - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - int widx1 = i + iw1; - int widx2 = i + iw2; - int widx3 = i + iw3; - int widx4 = i + iw4; - float w1r = wtable[widx1]; - float w1i = isign * wtable[widx1 + 1]; - float w2r = wtable[widx2]; - float w2i = isign * wtable[widx2 + 1]; - float w3r = wtable[widx3]; - float w3i = isign * wtable[widx3 + 1]; - float w4r = wtable[widx4]; - float w4i = isign * wtable[widx4 + 1]; - - int oidx1 = i + idx2; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - int oidx5 = oidx4 + idx0; - out[oidx1] = i3i + tr2 + tr3; - out[oidx1 + 1] = i3r + ti2 + ti3; - out[oidx2] = w1r * dr2 - w1i * di2; - out[oidx2 + 1] = w1r * di2 + w1i * dr2; - out[oidx3] = w2r * dr3 - w2i * di3; - out[oidx3 + 1] = w2r * di3 + w2i * dr3; - out[oidx4] = w3r * dr4 - w3i * di4; - out[oidx4 + 1] = w3r * di4 + w3i * dr4; - out[oidx5] = w4r * dr5 - w4i * di5; - out[oidx5 + 1] = w4r * di5 + w4i * dr5; - } - } - } - } - - /*---------------------------------------------------------------------- - passf5: Complex FFT's forward/backward processing of factor 5; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) /* isign==-1 for forward transform and+1 for backward transform */ { - final float tr11 = 0.309016994374947451262869435595348477f; - final float ti11 = 0.951056516295153531181938433292089030f; - final float tr12 = -0.809016994374947340240566973079694435f; - final float ti12 = 0.587785252292473248125759255344746634f; - float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; - long iw1, iw2, iw3, iw4; - - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - - if (ido == 2) { - for (long k = 1; k <= l1; ++k) { - long iidx1 = in_off + (5 * k - 4) * ido + 1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - long iidx4 = iidx2 + ido; - long iidx5 = iidx4 + ido; - - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - float i5i = in.getFloat(iidx5 - 1); - float i5r = in.getFloat(iidx5); - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - - long oidx1 = out_off + (k - 1) * ido; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - long oidx5 = oidx4 + idx0; - out.setFloat(oidx1, i3i + tr2 + tr3); - out.setFloat(oidx1 + 1, i3r + ti2 + ti3); - out.setFloat(oidx2, cr2 - ci5); - out.setFloat(oidx2 + 1, ci2 + cr5); - out.setFloat(oidx3, cr3 - ci4); - out.setFloat(oidx3 + 1, ci3 + cr4); - out.setFloat(oidx4, cr3 + ci4); - out.setFloat(oidx4 + 1, ci3 - cr4); - out.setFloat(oidx5, cr2 + ci5); - out.setFloat(oidx5 + 1, ci2 - cr5); - } - } else { - for (long k = 1; k <= l1; k++) { - long idx1 = in_off + 1 + (k * 5 - 4) * ido; - long idx2 = out_off + (k - 1) * ido; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - long iidx4 = iidx2 + ido; - long iidx5 = iidx4 + ido; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - float i3i = in.getFloat(iidx3 - 1); - float i3r = in.getFloat(iidx3); - float i4i = in.getFloat(iidx4 - 1); - float i4r = in.getFloat(iidx4); - float i5i = in.getFloat(iidx5 - 1); - float i5r = in.getFloat(iidx5); - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - long widx1 = i + iw1; - long widx2 = i + iw2; - long widx3 = i + iw3; - long widx4 = i + iw4; - float w1r = wtablel.getFloat(widx1); - float w1i = isign * wtablel.getFloat(widx1 + 1); - float w2r = wtablel.getFloat(widx2); - float w2i = isign * wtablel.getFloat(widx2 + 1); - float w3r = wtablel.getFloat(widx3); - float w3i = isign * wtablel.getFloat(widx3 + 1); - float w4r = wtablel.getFloat(widx4); - float w4i = isign * wtablel.getFloat(widx4 + 1); - - long oidx1 = i + idx2; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - long oidx5 = oidx4 + idx0; - out.setFloat(oidx1, i3i + tr2 + tr3); - out.setFloat(oidx1 + 1, i3r + ti2 + ti3); - out.setFloat(oidx2, w1r * dr2 - w1i * di2); - out.setFloat(oidx2 + 1, w1r * di2 + w1i * dr2); - out.setFloat(oidx3, w2r * dr3 - w2i * di3); - out.setFloat(oidx3 + 1, w2r * di3 + w2i * dr3); - out.setFloat(oidx4, w3r * dr4 - w3i * di4); - out.setFloat(oidx4 + 1, w3r * di4 + w3i * dr4); - out.setFloat(oidx5, w4r * dr5 - w4i * di5); - out.setFloat(oidx5 + 1, w4r * di5 + w4i * dr5); - } - } - } - } - - /*---------------------------------------------------------------------- - passfg: Complex FFT's forward/backward processing of general factor; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passfg(final int nac[], final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { - int idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; - float w1r, w1i, w2i, w2r; - int iw1; - - iw1 = offset; - idot = ido / 2; - ipph = (ip + 1) / 2; - idp = ip * ido; - if (ido >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * ido; - int idx2 = jc * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int idx4 = idx3 + idx1 * l1; - int idx5 = idx3 + idx2 * l1; - int idx6 = idx3 * ip; - for (int i = 0; i < ido; i++) { - int oidx1 = out_off + i; - float i1r = in[in_off + i + idx1 + idx6]; - float i2r = in[in_off + i + idx2 + idx6]; - out[oidx1 + idx4] = i1r + i2r; - out[oidx1 + idx5] = i1r - i2r; - } - } - } - for (int k = 0; k < l1; k++) { - int idxt1 = k * ido; - int idxt2 = idxt1 * ip; - for (int i = 0; i < ido; i++) { - out[out_off + i + idxt1] = in[in_off + i + idxt2]; - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idxt1 = j * l1 * ido; - int idxt2 = jc * l1 * ido; - int idxt3 = j * ido; - int idxt4 = jc * ido; - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 * ip; - int idx3 = out_off + i; - int idx4 = in_off + i; - float i1r = in[idx4 + idxt3 + idx2]; - float i2r = in[idx4 + idxt4 + idx2]; - out[idx3 + idx1 + idxt1] = i1r + i2r; - out[idx3 + idx1 + idxt2] = i1r - i2r; - } - } - } - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - out[out_off + i + idx1] = in[in_off + i + idx1 * ip]; - } - } - } - - idl = 2 - ido; - inc = 0; - int idxt0 = (ip - 1) * idl1; - for (l = 1; l < ipph; l++) { - lc = ip - l; - idl += ido; - int idxt1 = l * idl1; - int idxt2 = lc * idl1; - int idxt3 = idl + iw1; - w1r = wtable[idxt3 - 2]; - w1i = isign * wtable[idxt3 - 1]; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = in_off + ik; - int idx2 = out_off + ik; - in[idx1 + idxt1] = out[idx2] + w1r * out[idx2 + idl1]; - in[idx1 + idxt2] = w1i * out[idx2 + idxt0]; - } - idlj = idl; - inc += ido; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - idlj += inc; - if (idlj > idp) { - idlj -= idp; - } - int idxt4 = idlj + iw1; - w2r = wtable[idxt4 - 2]; - w2i = isign * wtable[idxt4 - 1]; - int idxt5 = j * idl1; - int idxt6 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = in_off + ik; - int idx2 = out_off + ik; - in[idx1 + idxt1] += w2r * out[idx2 + idxt5]; - in[idx1 + idxt2] += w2i * out[idx2 + idxt6]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idxt1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = out_off + ik; - out[idx1] += out[idx1 + idxt1]; - } - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * idl1; - int idx2 = jc * idl1; - for (int ik = 1; ik < idl1; ik += 2) { - int idx3 = out_off + ik; - int idx4 = in_off + ik; - int iidx1 = idx4 + idx1; - int iidx2 = idx4 + idx2; - float i1i = in[iidx1 - 1]; - float i1r = in[iidx1]; - float i2i = in[iidx2 - 1]; - float i2r = in[iidx2]; - - int oidx1 = idx3 + idx1; - int oidx2 = idx3 + idx2; - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - nac[0] = 1; - if (ido == 2) { - return; - } - nac[0] = 0; - System.arraycopy(out, out_off, in, in_off, idl1); - int idx0 = l1 * ido; - for (int j = 1; j < ip; j++) { - int idx1 = j * idx0; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido; - int oidx1 = out_off + idx2 + idx1; - int iidx1 = in_off + idx2 + idx1; - in[iidx1] = out[oidx1]; - in[iidx1 + 1] = out[oidx1 + 1]; - } - } - if (idot <= l1) { - idij = 0; - for (int j = 1; j < ip; j++) { - idij += 2; - int idx1 = j * l1 * ido; - for (int i = 3; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1 - 1; - w1r = wtable[idx2 - 1]; - w1i = isign * wtable[idx2]; - int idx3 = in_off + i; - int idx4 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx5 = k * ido + idx1; - int iidx1 = idx3 + idx5; - int oidx1 = idx4 + idx5; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } else { - idj = 2 - ido; - for (int j = 1; j < ip; j++) { - idj += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = idj; - int idx3 = k * ido + idx1; - for (int i = 3; i < ido; i += 2) { - idij += 2; - int idx2 = idij - 1 + iw1; - w1r = wtable[idx2 - 1]; - w1i = isign * wtable[idx2]; - int iidx1 = in_off + i + idx3; - int oidx1 = out_off + i + idx3; - float o1i = out[oidx1 - 1]; - float o1r = out[oidx1]; - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } - } - - /*---------------------------------------------------------------------- - passfg: Complex FFT's forward/backward processing of general factor; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passfg(final int nac[], final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { - long idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; - float w1r, w1i, w2i, w2r; - long iw1; - - iw1 = offset; - idot = ido / 2; - ipph = (ip + 1) / 2; - idp = ip * ido; - if (ido >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * ido; - long idx2 = jc * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long idx4 = idx3 + idx1 * l1; - long idx5 = idx3 + idx2 * l1; - long idx6 = idx3 * ip; - for (long i = 0; i < ido; i++) { - long oidx1 = out_off + i; - float i1r = in.getFloat(in_off + i + idx1 + idx6); - float i2r = in.getFloat(in_off + i + idx2 + idx6); - out.setFloat(oidx1 + idx4, i1r + i2r); - out.setFloat(oidx1 + idx5, i1r - i2r); - } - } - } - for (long k = 0; k < l1; k++) { - long idxt1 = k * ido; - long idxt2 = idxt1 * ip; - for (long i = 0; i < ido; i++) { - out.setFloat(out_off + i + idxt1, in.getFloat(in_off + i + idxt2)); - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idxt1 = j * l1 * ido; - long idxt2 = jc * l1 * ido; - long idxt3 = j * ido; - long idxt4 = jc * ido; - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 * ip; - long idx3 = out_off + i; - long idx4 = in_off + i; - float i1r = in.getFloat(idx4 + idxt3 + idx2); - float i2r = in.getFloat(idx4 + idxt4 + idx2); - out.setFloat(idx3 + idx1 + idxt1, i1r + i2r); - out.setFloat(idx3 + idx1 + idxt2, i1r - i2r); - } - } - } - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - out.setFloat(out_off + i + idx1, in.getFloat(in_off + i + idx1 * ip)); - } - } - } - - idl = 2 - ido; - inc = 0; - long idxt0 = (ip - 1) * idl1; - for (l = 1; l < ipph; l++) { - lc = ip - l; - idl += ido; - long idxt1 = l * idl1; - long idxt2 = lc * idl1; - long idxt3 = idl + iw1; - w1r = wtablel.getFloat(idxt3 - 2); - w1i = isign * wtablel.getFloat(idxt3 - 1); - for (long ik = 0; ik < idl1; ik++) { - long idx1 = in_off + ik; - long idx2 = out_off + ik; - in.setFloat(idx1 + idxt1, out.getFloat(idx2) + w1r * out.getFloat(idx2 + idl1)); - in.setFloat(idx1 + idxt2, w1i * out.getFloat(idx2 + idxt0)); - } - idlj = idl; - inc += ido; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - idlj += inc; - if (idlj > idp) { - idlj -= idp; - } - long idxt4 = idlj + iw1; - w2r = wtablel.getFloat(idxt4 - 2); - w2i = isign * wtablel.getFloat(idxt4 - 1); - long idxt5 = j * idl1; - long idxt6 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx1 = in_off + ik; - long idx2 = out_off + ik; - in.setFloat(idx1 + idxt1, in.getFloat(idx1 + idxt1) + w2r * out.getFloat(idx2 + idxt5)); - in.setFloat(idx1 + idxt2, in.getFloat(idx1 + idxt2) + w2i * out.getFloat(idx2 + idxt6)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idxt1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx1 = out_off + ik; - out.setFloat(idx1, out.getFloat(idx1) + out.getFloat(idx1 + idxt1)); - } - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * idl1; - long idx2 = jc * idl1; - for (long ik = 1; ik < idl1; ik += 2) { - long idx3 = out_off + ik; - long idx4 = in_off + ik; - long iidx1 = idx4 + idx1; - long iidx2 = idx4 + idx2; - float i1i = in.getFloat(iidx1 - 1); - float i1r = in.getFloat(iidx1); - float i2i = in.getFloat(iidx2 - 1); - float i2r = in.getFloat(iidx2); - - long oidx1 = idx3 + idx1; - long oidx2 = idx3 + idx2; - out.setFloat(oidx1 - 1, i1i - i2r); - out.setFloat(oidx2 - 1, i1i + i2r); - out.setFloat(oidx1, i1r + i2i); - out.setFloat(oidx2, i1r - i2i); - } - } - nac[0] = 1; - if (ido == 2) { - return; - } - nac[0] = 0; - Utilities.arraycopy(out, out_off, in, in_off, idl1); - long idx0 = l1 * ido; - for (long j = 1; j < ip; j++) { - long idx1 = j * idx0; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido; - long oidx1 = out_off + idx2 + idx1; - long iidx1 = in_off + idx2 + idx1; - in.setFloat(iidx1, out.getFloat(oidx1)); - in.setFloat(iidx1 + 1, out.getFloat(oidx1 + 1)); - } - } - if (idot <= l1) { - idij = 0; - for (long j = 1; j < ip; j++) { - idij += 2; - long idx1 = j * l1 * ido; - for (long i = 3; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1 - 1; - w1r = wtablel.getFloat(idx2 - 1); - w1i = isign * wtablel.getFloat(idx2); - long idx3 = in_off + i; - long idx4 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx5 = k * ido + idx1; - long iidx1 = idx3 + idx5; - long oidx1 = idx4 + idx5; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setFloat(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } else { - idj = 2 - ido; - for (long j = 1; j < ip; j++) { - idj += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = idj; - long idx3 = k * ido + idx1; - for (long i = 3; i < ido; i += 2) { - idij += 2; - long idx2 = idij - 1 + iw1; - w1r = wtablel.getFloat(idx2 - 1); - w1i = isign * wtablel.getFloat(idx2); - long iidx1 = in_off + i + idx3; - long oidx1 = out_off + i + idx3; - float o1i = out.getFloat(oidx1 - 1); - float o1r = out.getFloat(oidx1); - in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setFloat(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } - } -} +/* ***** BEGIN LICENSE BLOCK ***** + * JTransforms + * Copyright (c) 2007 onward, Piotr Wendykier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +// Code modified for inclusion with fairSIM: +// - changed package name +// - Commented out all dependence on ...LargeArray +// - based on JTransforms 3.1, git ede249c9824262bd9b5f571e56f7a0fa596f6f20 + +package org.fairsim.extern.jtransforms; + +import java.util.concurrent.Future; +//import org.jtransforms.utils.CommonUtils; +//import org.jtransforms.utils.ConcurrencyUtils; +//import pl.edu.icm.jlargearrays.FloatLargeArray; +//import pl.edu.icm.jlargearrays.LongLargeArray; +//import pl.edu.icm.jlargearrays.Utilities; + +/** + * Computes 1D Discrete Fourier Transform (DFT) of complex and real, single + * precision data. The size of the data can be an arbitrary number. This is a + * parallel implementation of split-radix and mixed-radix algorithms optimized + * for SMP systems.
+ *
+ * This code is derived from General Purpose FFT Package written by Takuya Ooura + * (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) and from JFFTPack written + * by Baoshe Zhang (http://jfftpack.sourceforge.net/) + * + * @author Piotr Wendykier (piotr.wendykier@gmail.com) + */ +public final class FloatFFT_1D { + + private static enum Plans { + + SPLIT_RADIX, MIXED_RADIX, BLUESTEIN + } + + private int n; + + private long nl; + + private int nBluestein; + + private long nBluesteinl; + + private int[] ip; + + //private LongLargeArray ipl; + + private float[] w; + + //private FloatLargeArray wl; + + private int nw; + + private long nwl; + + private int nc; + + private long ncl; + + private float[] wtable; + + //private FloatLargeArray wtablel; + + private float[] wtable_r; + + //private FloatLargeArray wtable_rl; + + private float[] bk1; + + //private FloatLargeArray bk1l; + + private float[] bk2; + + //private FloatLargeArray bk2l; + + private Plans plan; + + private boolean useLargeArrays; + + private static final int[] factors = {4, 2, 3, 5}; + + private static final float PI = 3.14159265358979311599796346854418516f; + + private static final float TWO_PI = 6.28318530717958623199592693708837032f; + + /** + * Creates new instance of FloatFFT_1D. + * + * @param n size of data + */ + public FloatFFT_1D(long n) { + if (n < 1) { + throw new IllegalArgumentException("n must be greater than 0"); + } + + //this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); + //if(this.useLargeArrays == false) + if (true) // <-- we dont need LargeArray support + { + this.n = (int) n; + if (!ConcurrencyUtils.isPowerOf2(n)) { + if (CommonUtils.getReminder(n, factors) >= 211) { + plan = Plans.BLUESTEIN; + nBluestein = ConcurrencyUtils.nextPow2(this.n * 2 - 1); + bk1 = new float[2 * nBluestein]; + bk2 = new float[2 * nBluestein]; + this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(nBluestein + 0.5f) / Math.log(2)) / 2))]; + this.w = new float[nBluestein]; + int twon = 2 * nBluestein; + nw = twon >> 2; + CommonUtils.makewt(nw, ip, w); + nc = nBluestein >> 2; + CommonUtils.makect(nc, w, nw, ip); + bluesteini(); + } else { + plan = Plans.MIXED_RADIX; + wtable = new float[4 * this.n + 15]; + wtable_r = new float[2 * this.n + 15]; + cffti(); + rffti(); + } + } else { + plan = Plans.SPLIT_RADIX; + this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(n + 0.5f) / Math.log(2)) / 2))]; + this.w = new float[this.n]; + int twon = 2 * this.n; + nw = twon >> 2; + CommonUtils.makewt(nw, ip, w); + nc = this.n >> 2; + CommonUtils.makect(nc, w, nw, ip); + } + } + /* + else { + this.nl = n; + if (!ConcurrencyUtils.isPowerOf2(nl)) { + if (CommonUtils.getReminder(nl, factors) >= 211) { + plan = Plans.BLUESTEIN; + nBluesteinl = ConcurrencyUtils.nextPow2(nl * 2 - 1); + bk1l = new FloatLargeArray(2l * nBluesteinl, false); + bk2l = new FloatLargeArray(2l * nBluesteinl, false); + this.ipl = new LongLargeArray(2l + (long) Math.ceil(2l + (1l << (long) (Math.log(nBluesteinl + 0.5f) / Math.log(2.)) / 2)), false); + this.wl = new FloatLargeArray(nBluesteinl, false); + long twon = 2 * nBluesteinl; + nwl = twon >> 2l; + CommonUtils.makewt(nwl, ipl, wl); + ncl = nBluesteinl >> 2l; + CommonUtils.makect(ncl, wl, nwl, ipl); + bluesteinil(); + } else { + plan = Plans.MIXED_RADIX; + wtablel = new FloatLargeArray(4 * nl + 15, false); + wtable_rl = new FloatLargeArray(2 * nl + 15, false); + cfftil(); + rfftil(); + } + } else { + plan = Plans.SPLIT_RADIX; + this.ipl = new LongLargeArray(2l + (long) Math.ceil(2 + (1l << (long) (Math.log(nl + 0.5f) / Math.log(2)) / 2)), false); + this.wl = new FloatLargeArray(nl, false); + long twon = 2 * nl; + nwl = twon >> 2l; + CommonUtils.makewt(nwl, ipl, wl); + ncl = nl >> 2l; + CommonUtils.makect(ncl, wl, nwl, ipl); + } + } */ + } + + /** + * Computes 1D forward DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + */ + public void complexForward(float[] a) { + complexForward(a, 0); + } + + /** + * Computes 1D forward DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * + public void complexForward(FloatLargeArray a) { + complexForward(a, 0); + } */ + + /** + * Computes 1D forward DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param offa index of the first element in array a + */ + public void complexForward(float[] a, int offa) { + /* + if (useLargeArrays) { + complexForward(new FloatLargeArray(a), offa); + } else */ // <-- no LargeArray support + if (true) { + if (n == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + CommonUtils.cftbsub(2 * n, a, offa, ip, nw, w); + break; + case MIXED_RADIX: + cfftf(a, offa, -1); + break; + case BLUESTEIN: + bluestein_complex(a, offa, -1); + break; + } + } + } + + /** + * Computes 1D forward DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param offa index of the first element in array a + * + public void complexForward(FloatLargeArray a, long offa) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + complexForward(a.getData(), (int) offa); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + if (nl == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + CommonUtils.cftbsub(2 * nl, a, offa, ipl, nwl, wl); + break; + case MIXED_RADIX: + cfftf(a, offa, -1); + break; + case BLUESTEIN: + bluestein_complex(a, offa, -1); + break; + } + } + } */ + + /** + * Computes 1D inverse DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param scale if true then scaling is performed + */ + public void complexInverse(float[] a, boolean scale) { + complexInverse(a, 0, scale); + } + + /** + * Computes 1D inverse DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param scale if true then scaling is performed + * + public void complexInverse(FloatLargeArray a, boolean scale) { + complexInverse(a, 0, scale); + } */ + + /** + * Computes 1D inverse DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + */ + public void complexInverse(float[] a, int offa, boolean scale) { + /* + if (useLargeArrays) { + complexInverse(new FloatLargeArray(a), offa, scale); + } else */ // <-- no LargeArray support + if (true) { + if (n == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + CommonUtils.cftfsub(2 * n, a, offa, ip, nw, w); + break; + case MIXED_RADIX: + cfftf(a, offa, +1); + break; + case BLUESTEIN: + bluestein_complex(a, offa, 1); + break; + } + if (scale) { + CommonUtils.scale(n, 1.0f / (float) n, a, offa, true); + } + } + } + + /** + * Computes 1D inverse DFT of complex data leaving the result in + * a. Complex number is stored as two float values in + * sequence: the real and imaginary part, i.e. the size of the input array + * must be greater or equal 2*n. The physical layout of the input data has + * to be as follows:
+ * + * *
+     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
+     * 
+ * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + * + public void complexInverse(FloatLargeArray a, long offa, boolean scale) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + complexInverse(a.getData(), (int) offa, scale); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + if (nl == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + CommonUtils.cftfsub(2 * nl, a, offa, ipl, nwl, wl); + break; + case MIXED_RADIX: + cfftf(a, offa, +1); + break; + case BLUESTEIN: + bluestein_complex(a, offa, 1); + break; + } + if (scale) { + CommonUtils.scale(nl, 1.0f / (float) nl, a, offa, true); + } + } + } */ + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . The physical layout of the output data is as follows:
+ * + * if n is even then + * + * *
+     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
+     * Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
+     * a[1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + */ + public void realForward(float[] a) { + realForward(a, 0); + } + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . The physical layout of the output data is as follows:
+ * + * if n is even then + * + * *
+     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
+     * Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
+     * a[1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + * + public void realForward(FloatLargeArray a) { + realForward(a, 0); + } */ + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . The physical layout of the output data is as follows:
+ * + * if n is even then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
+     * a[offa+1] = Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
+     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + * @param offa index of the first element in array a + */ + public void realForward(float[] a, int offa) { + /* if (useLargeArrays) { + realForward(new FloatLargeArray(a), offa); + } else { */ // <-- no LargeArray support + if (true) { + if (n == 1) { + return; + } + + switch (plan) { + case SPLIT_RADIX: + float xi; + + if (n > 4) { + CommonUtils.cftfsub(n, a, offa, ip, nw, w); + CommonUtils.rftfsub(n, a, offa, nc, w, nw); + } else if (n == 4) { + CommonUtils.cftx020(a, offa); + } + xi = a[offa] - a[offa + 1]; + a[offa] += a[offa + 1]; + a[offa + 1] = xi; + break; + case MIXED_RADIX: + rfftf(a, offa); + for (int k = n - 1; k >= 2; k--) { + int idx = offa + k; + float tmp = a[idx]; + a[idx] = a[idx - 1]; + a[idx - 1] = tmp; + } + break; + case BLUESTEIN: + bluestein_real_forward(a, offa); + break; + } + } + } + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . The physical layout of the output data is as follows:
+ * + * if n is even then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
+     * a[offa+1] = Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
+     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + * @param offa index of the first element in array a + * + public void realForward(FloatLargeArray a, long offa) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + realForward(a.getData(), (int) offa); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + if (nl == 1) { + return; + } + + switch (plan) { + case SPLIT_RADIX: + float xi; + + if (nl > 4) { + CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); + CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); + } else if (nl == 4) { + CommonUtils.cftx020(a, offa); + } + xi = a.getFloat(offa) - a.getFloat(offa + 1); + a.setFloat(offa, a.getFloat(offa) + a.getFloat(offa + 1)); + a.setFloat(offa + 1, xi); + break; + case MIXED_RADIX: + rfftf(a, offa); + for (long k = nl - 1; k >= 2; k--) { + long idx = offa + k; + float tmp = a.getFloat(idx); + a.setFloat(idx, a.getFloat(idx - 1)); + a.setFloat(idx - 1, tmp); + } + break; + case BLUESTEIN: + bluestein_real_forward(a, offa); + break; + } + } + } */ + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . This method computes the full real forward transform, i.e. you will get + * the same result as from complexForward called with all + * imaginary parts equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. To get back the original data, + * use complexInverse on the output of this method. + * + * @param a data to transform + */ + public void realForwardFull(float[] a) { + realForwardFull(a, 0); + } + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . This method computes the full real forward transform, i.e. you will get + * the same result as from complexForward called with all + * imaginary parts equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. To get back the original data, + * use complexInverse on the output of this method. + * + * @param a data to transform + * + public void realForwardFull(FloatLargeArray a) { + realForwardFull(a, 0); + } */ + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . This method computes the full real forward transform, i.e. you will get + * the same result as from complexForward called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. To get back the original data, + * use complexInverse on the output of this method. + * + * @param a data to transform + * @param offa index of the first element in array a + */ + public void realForwardFull(final float[] a, final int offa) { + /* + if (useLargeArrays) { + realForwardFull(new FloatLargeArray(a), offa); + } else { */ // <-- no LargeArray support + if (true) { + final int twon = 2 * n; + switch (plan) { + case SPLIT_RADIX: + realForward(a, offa); + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + Future[] futures = new Future[nthreads]; + int k = n / 2 / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx1, idx2; + for (int k = firstIdx; k < lastIdx; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a[idx2] = a[offa + idx1]; + a[idx2 + 1] = -a[offa + idx1 + 1]; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + int idx1, idx2; + for (int k = 0; k < n / 2; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a[idx2] = a[offa + idx1]; + a[idx2 + 1] = -a[offa + idx1 + 1]; + } + } + a[offa + n] = -a[offa + 1]; + a[offa + 1] = 0; + break; + case MIXED_RADIX: + rfftf(a, offa); + int m; + if (n % 2 == 0) { + m = n / 2; + } else { + m = (n + 1) / 2; + } + for (int k = 1; k < m; k++) { + int idx1 = offa + twon - 2 * k; + int idx2 = offa + 2 * k; + a[idx1 + 1] = -a[idx2]; + a[idx1] = a[idx2 - 1]; + } + for (int k = 1; k < n; k++) { + int idx = offa + n - k; + float tmp = a[idx + 1]; + a[idx + 1] = a[idx]; + a[idx] = tmp; + } + a[offa + 1] = 0; + break; + case BLUESTEIN: + bluestein_real_full(a, offa, -1); + break; + } + } + } + + /** + * Computes 1D forward DFT of real data leaving the result in a + * . This method computes the full real forward transform, i.e. you will get + * the same result as from complexForward called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. To get back the original data, + * use complexInverse on the output of this method. + * + * @param a data to transform + * @param offa index of the first element in array a + * + public void realForwardFull(final FloatLargeArray a, final long offa) { + + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + realForwardFull(a.getData(), (int) offa); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + final long twon = 2 * nl; + switch (plan) { + case SPLIT_RADIX: + realForward(a, offa); + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + Future[] futures = new Future[nthreads]; + long k = nl / 2 / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + long idx1, idx2; + for (long k = firstIdx; k < lastIdx; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a.setFloat(idx2, a.getFloat(offa + idx1)); + a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + long idx1, idx2; + for (long k = 0; k < nl / 2; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a.setFloat(idx2, a.getFloat(offa + idx1)); + a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); + } + } + a.setFloat(offa + nl, -a.getFloat(offa + 1)); + a.setFloat(offa + 1, 0); + break; + case MIXED_RADIX: + rfftf(a, offa); + long m; + if (nl % 2 == 0) { + m = nl / 2; + } else { + m = (nl + 1) / 2; + } + for (long k = 1; k < m; k++) { + long idx1 = offa + twon - 2 * k; + long idx2 = offa + 2 * k; + a.setFloat(idx1 + 1, -a.getFloat(idx2)); + a.setFloat(idx1, a.getFloat(idx2 - 1)); + } + for (long k = 1; k < nl; k++) { + long idx = offa + nl - k; + float tmp = a.getFloat(idx + 1); + a.setFloat(idx + 1, a.getFloat(idx)); + a.setFloat(idx, tmp); + } + a.setFloat(offa + 1, 0); + break; + case BLUESTEIN: + bluestein_real_full(a, offa, -1); + break; + } + } + } */ + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . The physical layout of the input data has to be as follows:
+ * + * if n is even then + * + * *
+     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
+     * Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
+     * a[1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + * + */ + public void realInverse(float[] a, boolean scale) { + realInverse(a, 0, scale); + } + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . The physical layout of the input data has to be as follows:
+ * + * if n is even then + * + * *
+     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
+     * Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
+     * a[1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + * + * + public void realInverse(FloatLargeArray a, boolean scale) { + realInverse(a, 0, scale); + } */ + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . The physical layout of the input data has to be as follows:
+ * + * if n is even then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
+     * a[offa+1] = Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
+     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + * + */ + public void realInverse(float[] a, int offa, boolean scale) { + /* + if (useLargeArrays) { + realInverse(new FloatLargeArray(a), offa, scale); + } else { */ // <-- no LargeArray support + if (true) { + if (n == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + a[offa + 1] = 0.5f * (a[offa] - a[offa + 1]); + a[offa] -= a[offa + 1]; + if (n > 4) { + CommonUtils.rftfsub(n, a, offa, nc, w, nw); + CommonUtils.cftbsub(n, a, offa, ip, nw, w); + } else if (n == 4) { + CommonUtils.cftxc020(a, offa); + } + if (scale) { + CommonUtils.scale(n, 1.0f / (n / 2.0f), a, offa, false); + } + break; + case MIXED_RADIX: + for (int k = 2; k < n; k++) { + int idx = offa + k; + float tmp = a[idx - 1]; + a[idx - 1] = a[idx]; + a[idx] = tmp; + } + rfftb(a, offa); + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + break; + case BLUESTEIN: + bluestein_real_inverse(a, offa); + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + break; + } + } + + } + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . The physical layout of the input data has to be as follows:
+ * + * if n is even then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
+     * a[offa+1] = Re[n/2]
+     * 
+ * + * if n is odd then + * + * *
+     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
+     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + * + * + public void realInverse(FloatLargeArray a, long offa, boolean scale) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + realInverse(a.getData(), (int) offa, scale); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + if (nl == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + a.setFloat(offa + 1, 0.5f * (a.getFloat(offa) - a.getFloat(offa + 1))); + a.setFloat(offa, a.getFloat(offa) - a.getFloat(offa + 1)); + if (nl > 4) { + CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); + CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); + } else if (nl == 4) { + CommonUtils.cftxc020(a, offa); + } + if (scale) { + CommonUtils.scale(nl, 1.0f / (nl / 2.0f), a, offa, false); + } + break; + case MIXED_RADIX: + for (long k = 2; k < nl; k++) { + long idx = offa + k; + float tmp = a.getFloat(idx - 1); + a.setFloat(idx - 1, a.getFloat(idx)); + a.setFloat(idx, tmp); + } + rfftb(a, offa); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + break; + case BLUESTEIN: + bluestein_real_inverse(a, offa); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + break; + } + } + + } */ + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . This method computes the full real inverse transform, i.e. you will get + * the same result as from complexInverse called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. + * + * @param a data to transform + * @param scale if true then scaling is performed + */ + public void realInverseFull(float[] a, boolean scale) { + realInverseFull(a, 0, scale); + } + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . This method computes the full real inverse transform, i.e. you will get + * the same result as from complexInverse called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. + * + * @param a data to transform + * @param scale if true then scaling is performed + * + public void realInverseFull(FloatLargeArray a, boolean scale) { + realInverseFull(a, 0, scale); + } */ + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . This method computes the full real inverse transform, i.e. you will get + * the same result as from complexInverse called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. + * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + */ + public void realInverseFull(final float[] a, final int offa, boolean scale) { + /* + if (useLargeArrays) { + realInverseFull(new FloatLargeArray(a), offa, scale); + } else { */ // <-- no LargeArray support + if (true) { + final int twon = 2 * n; + switch (plan) { + case SPLIT_RADIX: + realInverse2(a, offa, scale); + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + Future[] futures = new Future[nthreads]; + int k = n / 2 / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx1, idx2; + for (int k = firstIdx; k < lastIdx; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a[idx2] = a[offa + idx1]; + a[idx2 + 1] = -a[offa + idx1 + 1]; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + int idx1, idx2; + for (int k = 0; k < n / 2; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a[idx2] = a[offa + idx1]; + a[idx2 + 1] = -a[offa + idx1 + 1]; + } + } + a[offa + n] = -a[offa + 1]; + a[offa + 1] = 0; + break; + case MIXED_RADIX: + rfftf(a, offa); + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + int m; + if (n % 2 == 0) { + m = n / 2; + } else { + m = (n + 1) / 2; + } + for (int k = 1; k < m; k++) { + int idx1 = offa + 2 * k; + int idx2 = offa + twon - 2 * k; + a[idx1] = -a[idx1]; + a[idx2 + 1] = -a[idx1]; + a[idx2] = a[idx1 - 1]; + } + for (int k = 1; k < n; k++) { + int idx = offa + n - k; + float tmp = a[idx + 1]; + a[idx + 1] = a[idx]; + a[idx] = tmp; + } + a[offa + 1] = 0; + break; + case BLUESTEIN: + bluestein_real_full(a, offa, 1); + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, true); + } + break; + } + } + } + + /** + * Computes 1D inverse DFT of real data leaving the result in a + * . This method computes the full real inverse transform, i.e. you will get + * the same result as from complexInverse called with all + * imaginary part equal 0. Because the result is stored in a, + * the size of the input array must greater or equal 2*n, with only the + * first n elements filled with real data. + * + * @param a data to transform + * @param offa index of the first element in array a + * @param scale if true then scaling is performed + * + public void realInverseFull(final FloatLargeArray a, final long offa, boolean scale) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + realInverseFull(a.getData(), (int) offa, scale); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + final long twon = 2 * nl; + switch (plan) { + case SPLIT_RADIX: + realInverse2(a, offa, scale); + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + Future[] futures = new Future[nthreads]; + long k = nl / 2 / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + long idx1, idx2; + for (long k = firstIdx; k < lastIdx; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a.setFloat(idx2, a.getFloat(offa + idx1)); + a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + long idx1, idx2; + for (long k = 0; k < nl / 2; k++) { + idx1 = 2 * k; + idx2 = offa + ((twon - idx1) % twon); + a.setFloat(idx2, a.getFloat(offa + idx1)); + a.setFloat(idx2 + 1, -a.getFloat(offa + idx1 + 1)); + } + } + a.setFloat(offa + nl, -a.getFloat(offa + 1)); + a.setFloat(offa + 1, 0); + break; + case MIXED_RADIX: + rfftf(a, offa); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + long m; + if (nl % 2 == 0) { + m = nl / 2; + } else { + m = (nl + 1) / 2; + } + for (long k = 1; k < m; k++) { + long idx1 = offa + 2 * k; + long idx2 = offa + twon - 2 * k; + a.setFloat(idx1, -a.getFloat(idx1)); + a.setFloat(idx2 + 1, -a.getFloat(idx1)); + a.setFloat(idx2, a.getFloat(idx1 - 1)); + } + for (long k = 1; k < nl; k++) { + long idx = offa + nl - k; + float tmp = a.getFloat(idx + 1); + a.setFloat(idx + 1, a.getFloat(idx)); + a.setFloat(idx, tmp); + } + a.setFloat(offa + 1, 0); + break; + case BLUESTEIN: + bluestein_real_full(a, offa, 1); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, true); + } + break; + } + } + } */ + + protected void realInverse2(float[] a, int offa, boolean scale) { + /* + if (useLargeArrays) { + realInverse2(new FloatLargeArray(a), offa, scale); + } else { */ // <-- no LargeArray support + if (true) { + if (n == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + float xi; + + if (n > 4) { + CommonUtils.cftfsub(n, a, offa, ip, nw, w); + CommonUtils.rftbsub(n, a, offa, nc, w, nw); + } else if (n == 4) { + CommonUtils.cftbsub(n, a, offa, ip, nw, w); + } + xi = a[offa] - a[offa + 1]; + a[offa] += a[offa + 1]; + a[offa + 1] = xi; + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + break; + case MIXED_RADIX: + rfftf(a, offa); + for (int k = n - 1; k >= 2; k--) { + int idx = offa + k; + float tmp = a[idx]; + a[idx] = a[idx - 1]; + a[idx - 1] = tmp; + } + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + int m; + if (n % 2 == 0) { + m = n / 2; + for (int i = 1; i < m; i++) { + int idx = offa + 2 * i + 1; + a[idx] = -a[idx]; + } + } else { + m = (n - 1) / 2; + for (int i = 0; i < m; i++) { + int idx = offa + 2 * i + 1; + a[idx] = -a[idx]; + } + } + break; + case BLUESTEIN: + bluestein_real_inverse2(a, offa); + if (scale) { + CommonUtils.scale(n, 1.0f / n, a, offa, false); + } + break; + } + } + } +/* + protected void realInverse2(FloatLargeArray a, long offa, boolean scale) { + if (!useLargeArrays) { + if (a.getData() != null && offa < Integer.MAX_VALUE) { + realInverse2(a.getData(), (int) offa, scale); + } else { + throw new IllegalArgumentException("The data array is too big."); + } + } else { + if (nl == 1) { + return; + } + switch (plan) { + case SPLIT_RADIX: + float xi; + + if (nl > 4) { + CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); + CommonUtils.rftbsub(nl, a, offa, ncl, wl, nwl); + } else if (nl == 4) { + CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); + } + xi = a.getFloat(offa) - a.getFloat(offa + 1); + a.setFloat(offa, a.getFloat(offa) + a.getFloat(offa + 1)); + a.setFloat(offa + 1, xi); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + break; + case MIXED_RADIX: + rfftf(a, offa); + for (long k = nl - 1; k >= 2; k--) { + long idx = offa + k; + float tmp = a.getFloat(idx); + a.setFloat(idx, a.getFloat(idx - 1)); + a.setFloat(idx - 1, tmp); + } + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + long m; + if (nl % 2 == 0) { + m = nl / 2; + for (long i = 1; i < m; i++) { + long idx = offa + 2 * i + 1; + a.setFloat(idx, -a.getFloat(idx)); + } + } else { + m = (nl - 1) / 2; + for (long i = 0; i < m; i++) { + long idx = offa + 2 * i + 1; + a.setFloat(idx, -a.getFloat(idx)); + } + } + break; + case BLUESTEIN: + bluestein_real_inverse2(a, offa); + if (scale) { + CommonUtils.scale(nl, 1.0f / nl, a, offa, false); + } + break; + } + } + } +*/ + + /* -------- initializing routines -------- */ + + /*--------------------------------------------------------- + cffti: initialization of Complex FFT + --------------------------------------------------------*/ + void cffti(int n, int offw) { + if (n == 1) { + return; + } + + final int twon = 2 * n; + final int fourn = 4 * n; + float argh; + int idot, ntry = 0, i, j; + float argld; + int i1, k1, l1, l2, ib; + float fi; + int ld, ii, nf, ipll, nll, nq, nr; + float arg; + int ido, ipm; + + nll = n; + nf = 0; + j = 0; + + factorize_loop: + while (true) { + j++; + if (j <= 4) { + ntry = factors[j - 1]; + } else { + ntry += 2; + } + do { + nq = nll / ntry; + nr = nll - ntry * nq; + if (nr != 0) { + continue factorize_loop; + } + nf++; + wtable[offw + nf + 1 + fourn] = ntry; + nll = nq; + if (ntry == 2 && nf != 1) { + for (i = 2; i <= nf; i++) { + ib = nf - i + 2; + int idx = ib + fourn; + wtable[offw + idx + 1] = wtable[offw + idx]; + } + wtable[offw + 2 + fourn] = 2; + } + } while (nll != 1); + break; + } + wtable[offw + fourn] = n; + wtable[offw + 1 + fourn] = nf; + argh = TWO_PI / (float) n; + i = 1; + l1 = 1; + for (k1 = 1; k1 <= nf; k1++) { + ipll = (int) wtable[offw + k1 + 1 + fourn]; + ld = 0; + l2 = l1 * ipll; + ido = n / l2; + idot = ido + ido + 2; + ipm = ipll - 1; + for (j = 1; j <= ipm; j++) { + i1 = i; + wtable[offw + i - 1 + twon] = 1; + wtable[offw + i + twon] = 0; + ld += l1; + fi = 0; + argld = ld * argh; + for (ii = 4; ii <= idot; ii += 2) { + i += 2; + fi += 1; + arg = fi * argld; + int idx = i + twon; + wtable[offw + idx - 1] = (float)Math.cos(arg); + wtable[offw + idx] = (float)Math.sin(arg); + } + if (ipll > 5) { + int idx1 = i1 + twon; + int idx2 = i + twon; + wtable[offw + idx1 - 1] = wtable[offw + idx2 - 1]; + wtable[offw + idx1] = wtable[offw + idx2]; + } + } + l1 = l2; + } + + } + + final void cffti() { + if (n == 1) { + return; + } + + final int twon = 2 * n; + final int fourn = 4 * n; + float argh; + int idot, ntry = 0, i, j; + float argld; + int i1, k1, l1, l2, ib; + float fi; + int ld, ii, nf, ipll, nll, nq, nr; + float arg; + int ido, ipm; + + nll = n; + nf = 0; + j = 0; + + factorize_loop: + while (true) { + j++; + if (j <= 4) { + ntry = factors[j - 1]; + } else { + ntry += 2; + } + do { + nq = nll / ntry; + nr = nll - ntry * nq; + if (nr != 0) { + continue factorize_loop; + } + nf++; + wtable[nf + 1 + fourn] = ntry; + nll = nq; + if (ntry == 2 && nf != 1) { + for (i = 2; i <= nf; i++) { + ib = nf - i + 2; + int idx = ib + fourn; + wtable[idx + 1] = wtable[idx]; + } + wtable[2 + fourn] = 2; + } + } while (nll != 1); + break; + } + wtable[fourn] = n; + wtable[1 + fourn] = nf; + argh = TWO_PI / (float) n; + i = 1; + l1 = 1; + for (k1 = 1; k1 <= nf; k1++) { + ipll = (int) wtable[k1 + 1 + fourn]; + ld = 0; + l2 = l1 * ipll; + ido = n / l2; + idot = ido + ido + 2; + ipm = ipll - 1; + for (j = 1; j <= ipm; j++) { + i1 = i; + wtable[i - 1 + twon] = 1; + wtable[i + twon] = 0; + ld += l1; + fi = 0; + argld = ld * argh; + for (ii = 4; ii <= idot; ii += 2) { + i += 2; + fi += 1; + arg = fi * argld; + int idx = i + twon; + wtable[idx - 1] = (float)Math.cos(arg); + wtable[idx] = (float)Math.sin(arg); + } + if (ipll > 5) { + int idx1 = i1 + twon; + int idx2 = i + twon; + wtable[idx1 - 1] = wtable[idx2 - 1]; + wtable[idx1] = wtable[idx2]; + } + } + l1 = l2; + } + + } +/* + final void cfftil() { + if (nl == 1) { + return; + } + + final long twon = 2 * nl; + final long fourn = 4 * nl; + float argh; + long idot, ntry = 0, i, j; + float argld; + long i1, k1, l1, l2, ib; + float fi; + long ld, ii, nf, ipll, nl2, nq, nr; + float arg; + long ido, ipm; + + nl2 = nl; + nf = 0; + j = 0; + + factorize_loop: + while (true) { + j++; + if (j <= 4) { + ntry = factors[(int) (j - 1)]; + } else { + ntry += 2; + } + do { + nq = nl2 / ntry; + nr = nl2 - ntry * nq; + if (nr != 0) { + continue factorize_loop; + } + nf++; + wtablel.setFloat(nf + 1 + fourn, ntry); + nl2 = nq; + if (ntry == 2 && nf != 1) { + for (i = 2; i <= nf; i++) { + ib = nf - i + 2; + long idx = ib + fourn; + wtablel.setFloat(idx + 1, wtablel.getFloat(idx)); + } + wtablel.setFloat(2 + fourn, 2); + } + } while (nl2 != 1); + break; + } + wtablel.setFloat(fourn, nl); + wtablel.setFloat(1 + fourn, nf); + argh = TWO_PI / (float) nl; + i = 1; + l1 = 1; + for (k1 = 1; k1 <= nf; k1++) { + ipll = (long) wtablel.getFloat(k1 + 1 + fourn); + ld = 0; + l2 = l1 * ipll; + ido = nl / l2; + idot = ido + ido + 2; + ipm = ipll - 1; + for (j = 1; j <= ipm; j++) { + i1 = i; + wtablel.setFloat(i - 1 + twon, 1); + wtablel.setFloat(i + twon, 0); + ld += l1; + fi = 0; + argld = ld * argh; + for (ii = 4; ii <= idot; ii += 2) { + i += 2; + fi += 1; + arg = fi * argld; + long idx = i + twon; + wtablel.setFloat(idx - 1, (float)Math.cos(arg)); + wtablel.setFloat(idx, (float)Math.sin(arg)); + } + if (ipll > 5) { + long idx1 = i1 + twon; + long idx2 = i + twon; + wtablel.setFloat(idx1 - 1, wtablel.getFloat(idx2 - 1)); + wtablel.setFloat(idx1, wtablel.getFloat(idx2)); + } + } + l1 = l2; + } + + } +*/ + void rffti() { + + if (n == 1) { + return; + } + final int twon = 2 * n; + float argh; + int ntry = 0, i, j; + float argld; + int k1, l1, l2, ib; + float fi; + int ld, ii, nf, ipll, nll, is, nq, nr; + float arg; + int ido, ipm; + int nfm1; + + nll = n; + nf = 0; + j = 0; + + factorize_loop: + while (true) { + ++j; + if (j <= 4) { + ntry = factors[j - 1]; + } else { + ntry += 2; + } + do { + nq = nll / ntry; + nr = nll - ntry * nq; + if (nr != 0) { + continue factorize_loop; + } + ++nf; + wtable_r[nf + 1 + twon] = ntry; + + nll = nq; + if (ntry == 2 && nf != 1) { + for (i = 2; i <= nf; i++) { + ib = nf - i + 2; + int idx = ib + twon; + wtable_r[idx + 1] = wtable_r[idx]; + } + wtable_r[2 + twon] = 2; + } + } while (nll != 1); + break; + } + wtable_r[twon] = n; + wtable_r[1 + twon] = nf; + argh = TWO_PI / (float) (n); + is = 0; + nfm1 = nf - 1; + l1 = 1; + if (nfm1 == 0) { + return; + } + for (k1 = 1; k1 <= nfm1; k1++) { + ipll = (int) wtable_r[k1 + 1 + twon]; + ld = 0; + l2 = l1 * ipll; + ido = n / l2; + ipm = ipll - 1; + for (j = 1; j <= ipm; ++j) { + ld += l1; + i = is; + argld = (float) ld * argh; + + fi = 0; + for (ii = 3; ii <= ido; ii += 2) { + i += 2; + fi += 1; + arg = fi * argld; + int idx = i + n; + wtable_r[idx - 2] = (float)Math.cos(arg); + wtable_r[idx - 1] = (float)Math.sin(arg); + } + is += ido; + } + l1 = l2; + } + } +/* + void rfftil() { + + if (nl == 1) { + return; + } + final long twon = 2 * nl; + float argh; + long ntry = 0, i, j; + float argld; + long k1, l1, l2, ib; + float fi; + long ld, ii, nf, ipll, nl2, is, nq, nr; + float arg; + long ido, ipm; + long nfm1; + + nl2 = nl; + nf = 0; + j = 0; + + factorize_loop: + while (true) { + ++j; + if (j <= 4) { + ntry = factors[(int) (j - 1)]; + } else { + ntry += 2; + } + do { + nq = nl2 / ntry; + nr = nl2 - ntry * nq; + if (nr != 0) { + continue factorize_loop; + } + ++nf; + wtable_rl.setFloat(nf + 1 + twon, ntry); + + nl2 = nq; + if (ntry == 2 && nf != 1) { + for (i = 2; i <= nf; i++) { + ib = nf - i + 2; + long idx = ib + twon; + wtable_rl.setFloat(idx + 1, wtable_rl.getFloat(idx)); + } + wtable_rl.setFloat(2 + twon, 2); + } + } while (nl2 != 1); + break; + } + wtable_rl.setFloat(twon, nl); + wtable_rl.setFloat(1 + twon, nf); + argh = TWO_PI / (float) (nl); + is = 0; + nfm1 = nf - 1; + l1 = 1; + if (nfm1 == 0) { + return; + } + for (k1 = 1; k1 <= nfm1; k1++) { + ipll = (long) wtable_rl.getFloat(k1 + 1 + twon); + ld = 0; + l2 = l1 * ipll; + ido = nl / l2; + ipm = ipll - 1; + for (j = 1; j <= ipm; ++j) { + ld += l1; + i = is; + argld = (float) ld * argh; + + fi = 0; + for (ii = 3; ii <= ido; ii += 2) { + i += 2; + fi += 1; + arg = fi * argld; + long idx = i + nl; + wtable_rl.setFloat(idx - 2, (float)Math.cos(arg)); + wtable_rl.setFloat(idx - 1, (float)Math.sin(arg)); + } + is += ido; + } + l1 = l2; + } + } +*/ + private void bluesteini() { + int k = 0; + float arg; + float pi_n = PI / n; + bk1[0] = 1; + bk1[1] = 0; + for (int i = 1; i < n; i++) { + k += 2 * i - 1; + if (k >= 2 * n) { + k -= 2 * n; + } + arg = pi_n * k; + bk1[2 * i] = (float)Math.cos(arg); + bk1[2 * i + 1] = (float)Math.sin(arg); + } + float scale = 1.0f / nBluestein; + bk2[0] = bk1[0] * scale; + bk2[1] = bk1[1] * scale; + for (int i = 2; i < 2 * n; i += 2) { + bk2[i] = bk1[i] * scale; + bk2[i + 1] = bk1[i + 1] * scale; + bk2[2 * nBluestein - i] = bk2[i]; + bk2[2 * nBluestein - i + 1] = bk2[i + 1]; + } + CommonUtils.cftbsub(2 * nBluestein, bk2, 0, ip, nw, w); + } +/* + private void bluesteinil() { + long k = 0; + float arg; + float pi_n = PI / nl; + bk1l.setFloat(0, 1); + bk1l.setFloat(1, 0); + for (int i = 1; i < nl; i++) { + k += 2 * i - 1; + if (k >= 2 * nl) { + k -= 2 * nl; + } + arg = pi_n * k; + bk1l.setFloat(2 * i, (float)Math.cos(arg)); + bk1l.setFloat(2 * i + 1, (float)Math.sin(arg)); + } + float scale = 1.0f / nBluesteinl; + bk2l.setFloat(0, bk1l.getFloat(0) * scale); + bk2l.setFloat(1, bk1l.getFloat(1) * scale); + for (int i = 2; i < 2 * nl; i += 2) { + bk2l.setFloat(i, bk1l.getFloat(i) * scale); + bk2l.setFloat(i + 1, bk1l.getFloat(i + 1) * scale); + bk2l.setFloat(2 * nBluesteinl - i, bk2l.getFloat(i)); + bk2l.setFloat(2 * nBluesteinl - i + 1, bk2l.getFloat(i + 1)); + } + CommonUtils.cftbsub(2 * nBluesteinl, bk2l, 0, ipl, nwl, wl); + } +*/ + private void bluestein_complex(final float[] a, final int offa, final int isign) { + final float[] ak = new float[2 * nBluestein]; + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + int k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; + ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = nBluestein / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + if (isign > 0) { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + } else { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; + ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + } + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + if (isign > 0) { + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } else { + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + if (isign > 0) { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } + } + } +/* + private void bluestein_complex(final FloatLargeArray a, final long offa, final int isign) { + final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + long k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nBluesteinl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(idx4, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(idx4, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + if (isign > 0) { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + } else { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + } + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + if (isign > 0) { + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } else { + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + if (isign > 0) { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(idx4, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + a.setFloat(idx3, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(idx4, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } + } + } +*/ + private void bluestein_real_full(final float[] a, final int offa, final int isign) { + final float[] ak = new float[2 * nBluestein]; + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + int k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = a[idx3] * bk1[idx2]; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = -a[idx3] * bk1[idx2]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = nBluestein / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + if (isign > 0) { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = a[idx3] * bk1[idx2]; + } + } else { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = -a[idx3] * bk1[idx2]; + } + } + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + if (isign > 0) { + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } else { + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + if (isign > 0) { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } + } + } +/* + private void bluestein_real_full(final FloatLargeArray a, final long offa, final long isign) { + final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + long k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nBluesteinl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (isign > 0) { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + if (isign > 0) { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } else { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + if (isign > 0) { + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } else { + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + if (isign > 0) { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } + } + } +*/ + private void bluestein_real_forward(final float[] a, final int offa) { + final float[] ak = new float[2 * nBluestein]; + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + int k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = -a[idx3] * bk1[idx2]; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = nBluestein / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = -a[idx3] * bk1[idx2]; + } + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + if (n % 2 == 0) { + a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; + a[offa + 1] = bk1[n] * ak[n] + bk1[n + 1] * ak[n + 1]; + for (int i = 1; i < n / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; + a[offa + 1] = -bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; + for (int i = 1; i < (n - 1) / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; + a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + a[offa + n - 1] = bk1[n - 1] * ak[n - 1] + bk1[n] * ak[n]; + } + + } +/* + private void bluestein_real_forward(final FloatLargeArray a, final long offa) { + final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + long k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nBluesteinl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, -a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) - ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + if (nl % 2 == 0) { + a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) + bk1l.getFloat(1) * ak.getFloat(1)); + a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl) + bk1l.getFloat(nl + 1) * ak.getFloat(nl + 1)); + for (long i = 1; i < nl / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) + bk1l.getFloat(1) * ak.getFloat(1)); + a.setFloat(offa + 1, -bk1l.getFloat(nl) * ak.getFloat(nl - 1) + bk1l.getFloat(nl - 1) * ak.getFloat(nl)); + for (long i = 1; i < (nl - 1) / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) + bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, -bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + a.setFloat(offa + nl - 1, bk1l.getFloat(nl - 1) * ak.getFloat(nl - 1) + bk1l.getFloat(nl) * ak.getFloat(nl)); + } + + } +*/ + private void bluestein_real_inverse(final float[] a, final int offa) { + final float[] ak = new float[2 * nBluestein]; + if (n % 2 == 0) { + ak[0] = a[offa] * bk1[0]; + ak[1] = a[offa] * bk1[1]; + + for (int i = 1; i < n / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + + ak[n] = a[offa + 1] * bk1[n]; + ak[n + 1] = a[offa + 1] * bk1[n + 1]; + + for (int i = n / 2 + 1; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + 2 * n - idx1; + int idx4 = idx3 + 1; + ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; + } + + } else { + ak[0] = a[offa] * bk1[0]; + ak[1] = a[offa] * bk1[1]; + + for (int i = 1; i < (n - 1) / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + idx1; + int idx4 = offa + idx2; + ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; + } + + ak[n - 1] = a[offa + n - 1] * bk1[n - 1] - a[offa + 1] * bk1[n]; + ak[n] = a[offa + n - 1] * bk1[n] + a[offa + 1] * bk1[n - 1]; + + ak[n + 1] = a[offa + n - 1] * bk1[n + 1] + a[offa + 1] * bk1[n + 2]; + ak[n + 2] = a[offa + n - 1] * bk1[n + 2] - a[offa + 1] * bk1[n + 1]; + + for (int i = (n - 1) / 2 + 2; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + 2 * n - idx1; + int idx4 = idx3 + 1; + ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; + ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; + } + } + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + int k = nBluestein / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + } + } + } +/* + private void bluestein_real_inverse(final FloatLargeArray a, final long offa) { + final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); + if (nl % 2 == 0) { + ak.setFloat(0, a.getFloat(offa) * bk1l.getFloat(0)); + ak.setFloat(1, a.getFloat(offa) * bk1l.getFloat(1)); + + for (long i = 1; i < nl / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + + ak.setFloat(nl, a.getFloat(offa + 1) * bk1l.getFloat(nl)); + ak.setFloat(nl + 1, a.getFloat(offa + 1) * bk1l.getFloat(nl + 1)); + + for (long i = nl / 2 + 1; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + 2 * nl - idx1; + long idx4 = idx3 + 1; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) - a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + + } else { + ak.setFloat(0, a.getFloat(offa) * bk1l.getFloat(0)); + ak.setFloat(1, a.getFloat(offa) * bk1l.getFloat(1)); + + for (long i = 1; i < (nl - 1) / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + idx1; + long idx4 = offa + idx2; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) - a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) + a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + + ak.setFloat(nl - 1, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl - 1) - a.getFloat(offa + 1) * bk1l.getFloat(nl)); + ak.setFloat(nl, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl) + a.getFloat(offa + 1) * bk1l.getFloat(nl - 1)); + + ak.setFloat(nl + 1, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl + 1) + a.getFloat(offa + 1) * bk1l.getFloat(nl + 2)); + ak.setFloat(nl + 2, a.getFloat(offa + nl - 1) * bk1l.getFloat(nl + 2) - a.getFloat(offa + 1) * bk1l.getFloat(nl + 1)); + + for (long i = (nl - 1) / 2 + 2; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + 2 * nl - idx1; + long idx4 = idx3 + 1; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1) + a.getFloat(idx4) * bk1l.getFloat(idx2)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2) - a.getFloat(idx4) * bk1l.getFloat(idx1)); + } + } + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + long k = nBluesteinl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + i, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + i, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + } + } + } +*/ + private void bluestein_real_inverse2(final float[] a, final int offa) { + final float[] ak = new float[2 * nBluestein]; + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + int k = n / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = a[idx3] * bk1[idx2]; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + k = nBluestein / nthreads; + for (int i = 0; i < nthreads; i++) { + final int firstIdx = i * k; + final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstIdx; i < lastIdx; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (int i = 0; i < n; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + int idx3 = offa + i; + ak[idx1] = a[idx3] * bk1[idx1]; + ak[idx2] = a[idx3] * bk1[idx2]; + } + + CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); + + for (int i = 0; i < nBluestein; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + float im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; + ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; + ak[idx2] = im; + } + } + + CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); + + if (n % 2 == 0) { + a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; + a[offa + 1] = bk1[n] * ak[n] - bk1[n + 1] * ak[n + 1]; + for (int i = 1; i < n / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + } else { + a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; + a[offa + 1] = bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; + for (int i = 1; i < (n - 1) / 2; i++) { + int idx1 = 2 * i; + int idx2 = idx1 + 1; + a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; + a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; + } + a[offa + n - 1] = bk1[n - 1] * ak[n - 1] - bk1[n] * ak[n]; + } + } +/* + private void bluestein_real_inverse2(final FloatLargeArray a, final long offa) { + final FloatLargeArray ak = new FloatLargeArray(2 * nBluesteinl, false); + int threads = ConcurrencyUtils.getNumberOfThreads(); + if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { + int nthreads = 2; + if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { + nthreads = 4; + } + Future[] futures = new Future[nthreads]; + long k = nl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + k = nBluesteinl / nthreads; + for (int i = 0; i < nthreads; i++) { + final long firstIdx = i * k; + final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstIdx; i < lastIdx; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (long i = 0; i < nl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + long idx3 = offa + i; + ak.setFloat(idx1, a.getFloat(idx3) * bk1l.getFloat(idx1)); + ak.setFloat(idx2, a.getFloat(idx3) * bk1l.getFloat(idx2)); + } + + CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + for (long i = 0; i < nBluesteinl; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + float im = -ak.getFloat(idx1) * bk2l.getFloat(idx2) + ak.getFloat(idx2) * bk2l.getFloat(idx1); + ak.setFloat(idx1, ak.getFloat(idx1) * bk2l.getFloat(idx1) + ak.getFloat(idx2) * bk2l.getFloat(idx2)); + ak.setFloat(idx2, im); + } + } + + CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); + + if (nl % 2 == 0) { + a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) - bk1l.getFloat(1) * ak.getFloat(1)); + a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl) - bk1l.getFloat(nl + 1) * ak.getFloat(nl + 1)); + for (long i = 1; i < nl / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + } else { + a.setFloat(offa, bk1l.getFloat(0) * ak.getFloat(0) - bk1l.getFloat(1) * ak.getFloat(1)); + a.setFloat(offa + 1, bk1l.getFloat(nl) * ak.getFloat(nl - 1) + bk1l.getFloat(nl - 1) * ak.getFloat(nl)); + for (long i = 1; i < (nl - 1) / 2; i++) { + long idx1 = 2 * i; + long idx2 = idx1 + 1; + a.setFloat(offa + idx1, bk1l.getFloat(idx1) * ak.getFloat(idx1) - bk1l.getFloat(idx2) * ak.getFloat(idx2)); + a.setFloat(offa + idx2, bk1l.getFloat(idx2) * ak.getFloat(idx1) + bk1l.getFloat(idx1) * ak.getFloat(idx2)); + } + a.setFloat(offa + nl - 1, bk1l.getFloat(nl - 1) * ak.getFloat(nl - 1) - bk1l.getFloat(nl) * ak.getFloat(nl)); + } + } +*/ + /*--------------------------------------------------------- + rfftf1: further processing of Real forward FFT + --------------------------------------------------------*/ + void rfftf(final float a[], final int offa) { + if (n == 1) { + return; + } + int l1, l2, na, kh, nf, ipll, iw, ido, idl1; + + final float[] ch = new float[n]; + final int twon = 2 * n; + nf = (int) wtable_r[1 + twon]; + na = 1; + l2 = n; + iw = twon - 1; + for (int k1 = 1; k1 <= nf; ++k1) { + kh = nf - k1; + ipll = (int) wtable_r[kh + 2 + twon]; + l1 = l2 / ipll; + ido = n / l2; + idl1 = ido * l1; + iw -= (ipll - 1) * ido; + na = 1 - na; + switch (ipll) { + case 2: + if (na == 0) { + radf2(ido, l1, a, offa, ch, 0, iw); + } else { + radf2(ido, l1, ch, 0, a, offa, iw); + } + break; + case 3: + if (na == 0) { + radf3(ido, l1, a, offa, ch, 0, iw); + } else { + radf3(ido, l1, ch, 0, a, offa, iw); + } + break; + case 4: + if (na == 0) { + radf4(ido, l1, a, offa, ch, 0, iw); + } else { + radf4(ido, l1, ch, 0, a, offa, iw); + } + break; + case 5: + if (na == 0) { + radf5(ido, l1, a, offa, ch, 0, iw); + } else { + radf5(ido, l1, ch, 0, a, offa, iw); + } + break; + default: + if (ido == 1) { + na = 1 - na; + } + if (na == 0) { + radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); + na = 1; + } else { + radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); + na = 0; + } + break; + } + l2 = l1; + } + if (na == 1) { + return; + } + System.arraycopy(ch, 0, a, offa, n); + } + + /*--------------------------------------------------------- + rfftf1: further processing of Real forward FFT + --------------------------------------------------------*/ +/* + void rfftf(final FloatLargeArray a, final long offa) { + if (nl == 1) { + return; + } + long l1, l2, na, kh, nf, iw, ido, idl1; + int ipll; + + final FloatLargeArray ch = new FloatLargeArray(nl, false); + final long twon = 2 * nl; + nf = (long) wtable_rl.getFloat(1 + twon); + na = 1; + l2 = nl; + iw = twon - 1; + for (long k1 = 1; k1 <= nf; ++k1) { + kh = nf - k1; + ipll = (int) wtable_rl.getFloat(kh + 2 + twon); + l1 = l2 / ipll; + ido = nl / l2; + idl1 = ido * l1; + iw -= (ipll - 1) * ido; + na = 1 - na; + switch (ipll) { + case 2: + if (na == 0) { + radf2(ido, l1, a, offa, ch, 0, iw); + } else { + radf2(ido, l1, ch, 0, a, offa, iw); + } + break; + case 3: + if (na == 0) { + radf3(ido, l1, a, offa, ch, 0, iw); + } else { + radf3(ido, l1, ch, 0, a, offa, iw); + } + break; + case 4: + if (na == 0) { + radf4(ido, l1, a, offa, ch, 0, iw); + } else { + radf4(ido, l1, ch, 0, a, offa, iw); + } + break; + case 5: + if (na == 0) { + radf5(ido, l1, a, offa, ch, 0, iw); + } else { + radf5(ido, l1, ch, 0, a, offa, iw); + } + break; + default: + if (ido == 1) { + na = 1 - na; + } + if (na == 0) { + radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); + na = 1; + } else { + radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); + na = 0; + } + break; + } + l2 = l1; + } + if (na == 1) { + return; + } + Utilities.arraycopy(ch, 0, a, offa, nl); + } +*/ + /*--------------------------------------------------------- + rfftb1: further processing of Real backward FFT + --------------------------------------------------------*/ + void rfftb(final float a[], final int offa) { + if (n == 1) { + return; + } + int l1, l2, na, nf, ipll, iw, ido, idl1; + + float[] ch = new float[n]; + final int twon = 2 * n; + nf = (int) wtable_r[1 + twon]; + na = 0; + l1 = 1; + iw = n; + for (int k1 = 1; k1 <= nf; k1++) { + ipll = (int) wtable_r[k1 + 1 + twon]; + l2 = ipll * l1; + ido = n / l2; + idl1 = ido * l1; + switch (ipll) { + case 2: + if (na == 0) { + radb2(ido, l1, a, offa, ch, 0, iw); + } else { + radb2(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 3: + if (na == 0) { + radb3(ido, l1, a, offa, ch, 0, iw); + } else { + radb3(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 4: + if (na == 0) { + radb4(ido, l1, a, offa, ch, 0, iw); + } else { + radb4(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 5: + if (na == 0) { + radb5(ido, l1, a, offa, ch, 0, iw); + } else { + radb5(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + default: + if (na == 0) { + radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); + } else { + radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); + } + if (ido == 1) { + na = 1 - na; + } + break; + } + l1 = l2; + iw += (ipll - 1) * ido; + } + if (na == 0) { + return; + } + System.arraycopy(ch, 0, a, offa, n); + } + + /*--------------------------------------------------------- + rfftb1: further processing of Real backward FFT + --------------------------------------------------------*/ +/* + void rfftb(final FloatLargeArray a, final long offa) { + if (nl == 1) { + return; + } + long l1, l2, na, nf, iw, ido, idl1; + int ipll; + FloatLargeArray ch = new FloatLargeArray(nl, false); + final long twon = 2 * nl; + nf = (long) wtable_rl.getFloat(1 + twon); + na = 0; + l1 = 1; + iw = nl; + for (long k1 = 1; k1 <= nf; k1++) { + ipll = (int) wtable_rl.getFloat(k1 + 1 + twon); + l2 = ipll * l1; + ido = nl / l2; + idl1 = ido * l1; + switch (ipll) { + case 2: + if (na == 0) { + radb2(ido, l1, a, offa, ch, 0, iw); + } else { + radb2(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 3: + if (na == 0) { + radb3(ido, l1, a, offa, ch, 0, iw); + } else { + radb3(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 4: + if (na == 0) { + radb4(ido, l1, a, offa, ch, 0, iw); + } else { + radb4(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + case 5: + if (na == 0) { + radb5(ido, l1, a, offa, ch, 0, iw); + } else { + radb5(ido, l1, ch, 0, a, offa, iw); + } + na = 1 - na; + break; + default: + if (na == 0) { + radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); + } else { + radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); + } + if (ido == 1) { + na = 1 - na; + } + break; + } + l1 = l2; + iw += (ipll - 1) * ido; + } + if (na == 0) { + return; + } + Utilities.arraycopy(ch, 0, a, offa, nl); + } +*/ + /*------------------------------------------------- + radf2: Real FFT's forward processing of factor 2 + -------------------------------------------------*/ + void radf2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + int i, ic, idx0, idx1, idx2, idx3, idx4; + float t1i, t1r, w1r, w1i; + int iw1; + iw1 = offset; + idx0 = l1 * ido; + idx1 = 2 * ido; + for (int k = 0; k < l1; k++) { + int oidx1 = out_off + k * idx1; + int oidx2 = oidx1 + idx1 - 1; + int iidx1 = in_off + k * ido; + int iidx2 = iidx1 + idx0; + + float i1r = in[iidx1]; + float i2r = in[iidx2]; + + out[oidx1] = i1r + i2r; + out[oidx2] = i1r - i2r; + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (int k = 0; k < l1; k++) { + idx1 = k * ido; + idx2 = 2 * idx1; + idx3 = idx2 + ido; + idx4 = idx1 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int widx1 = i - 1 + iw1; + int oidx1 = out_off + i + idx2; + int oidx2 = out_off + ic + idx3; + int iidx1 = in_off + i + idx1; + int iidx2 = in_off + i + idx4; + + float a1i = in[iidx1 - 1]; + float a1r = in[iidx1]; + float a2i = in[iidx2 - 1]; + float a2r = in[iidx2]; + + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + + t1r = w1r * a2i + w1i * a2r; + t1i = w1r * a2r - w1i * a2i; + + out[oidx1] = a1r + t1i; + out[oidx1 - 1] = a1i + t1r; + + out[oidx2] = t1i - a1r; + out[oidx2 - 1] = a1i - t1r; + } + } + if (ido % 2 == 1) { + return; + } + } + idx2 = 2 * idx1; + for (int k = 0; k < l1; k++) { + idx1 = k * ido; + int oidx1 = out_off + idx2 + ido; + int iidx1 = in_off + ido - 1 + idx1; + + out[oidx1] = -in[iidx1 + idx0]; + out[oidx1 - 1] = in[iidx1]; + } + } + + /*------------------------------------------------- + radf2: Real FFT's forward processing of factor 2 + -------------------------------------------------*/ +/* + void radf2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + long i, ic, idx0, idx1, idx2, idx3, idx4; + float t1i, t1r, w1r, w1i; + long iw1; + iw1 = offset; + idx0 = l1 * ido; + idx1 = 2 * ido; + for (long k = 0; k < l1; k++) { + long oidx1 = out_off + k * idx1; + long oidx2 = oidx1 + idx1 - 1; + long iidx1 = in_off + k * ido; + long iidx2 = iidx1 + idx0; + + float i1r = in.getFloat(iidx1); + float i2r = in.getFloat(iidx2); + + out.setFloat(oidx1, i1r + i2r); + out.setFloat(oidx2, i1r - i2r); + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (long k = 0; k < l1; k++) { + idx1 = k * ido; + idx2 = 2 * idx1; + idx3 = idx2 + ido; + idx4 = idx1 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long widx1 = i - 1 + iw1; + long oidx1 = out_off + i + idx2; + long oidx2 = out_off + ic + idx3; + long iidx1 = in_off + i + idx1; + long iidx2 = in_off + i + idx4; + + float a1i = in.getFloat(iidx1 - 1); + float a1r = in.getFloat(iidx1); + float a2i = in.getFloat(iidx2 - 1); + float a2r = in.getFloat(iidx2); + + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + + t1r = w1r * a2i + w1i * a2r; + t1i = w1r * a2r - w1i * a2i; + + out.setFloat(oidx1, a1r + t1i); + out.setFloat(oidx1 - 1, a1i + t1r); + + out.setFloat(oidx2, t1i - a1r); + out.setFloat(oidx2 - 1, a1i - t1r); + } + } + if (ido % 2 == 1) { + return; + } + } + idx2 = 2 * idx1; + for (long k = 0; k < l1; k++) { + idx1 = k * ido; + long oidx1 = out_off + idx2 + ido; + long iidx1 = in_off + ido - 1 + idx1; + + out.setFloat(oidx1, -in.getFloat(iidx1 + idx0)); + out.setFloat(oidx1 - 1, in.getFloat(iidx1)); + } + } +*/ + /*------------------------------------------------- + radb2: Real FFT's backward processing of factor 2 + -------------------------------------------------*/ + void radb2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + int i, ic; + float t1i, t1r, w1r, w1i; + int iw1 = offset; + + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 2 * idx1; + int idx3 = idx2 + ido; + int oidx1 = out_off + idx1; + int iidx1 = in_off + idx2; + int iidx2 = in_off + ido - 1 + idx3; + float i1r = in[iidx1]; + float i2r = in[iidx2]; + out[oidx1] = i1r + i2r; + out[oidx1 + idx0] = i1r - i2r; + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (int k = 0; k < l1; ++k) { + int idx1 = k * ido; + int idx2 = 2 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx1 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int idx5 = i - 1 + iw1; + int idx6 = out_off + i; + int idx7 = in_off + i; + int idx8 = in_off + ic; + w1r = wtable_r[idx5 - 1]; + w1i = wtable_r[idx5]; + int iidx1 = idx7 + idx2; + int iidx2 = idx8 + idx3; + int oidx1 = idx6 + idx1; + int oidx2 = idx6 + idx4; + t1r = in[iidx1 - 1] - in[iidx2 - 1]; + t1i = in[iidx1] + in[iidx2]; + float i1i = in[iidx1]; + float i1r = in[iidx1 - 1]; + float i2i = in[iidx2]; + float i2r = in[iidx2 - 1]; + + out[oidx1 - 1] = i1r + i2r; + out[oidx1] = i1i - i2i; + out[oidx2 - 1] = w1r * t1r - w1i * t1i; + out[oidx2] = w1r * t1i + w1i * t1r; + } + } + if (ido % 2 == 1) { + return; + } + } + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 2 * idx1; + int oidx1 = out_off + ido - 1 + idx1; + int iidx1 = in_off + idx2 + ido; + out[oidx1] = 2 * in[iidx1 - 1]; + out[oidx1 + idx0] = -2 * in[iidx1]; + } + } + + /*------------------------------------------------- + radb2: Real FFT's backward processing of factor 2 + -------------------------------------------------*/ +/* + void radb2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + long i, ic; + float t1i, t1r, w1r, w1i; + long iw1 = offset; + + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 2 * idx1; + long idx3 = idx2 + ido; + long oidx1 = out_off + idx1; + long iidx1 = in_off + idx2; + long iidx2 = in_off + ido - 1 + idx3; + float i1r = in.getFloat(iidx1); + float i2r = in.getFloat(iidx2); + out.setFloat(oidx1, i1r + i2r); + out.setFloat(oidx1 + idx0, i1r - i2r); + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (long k = 0; k < l1; ++k) { + long idx1 = k * ido; + long idx2 = 2 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx1 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long idx5 = i - 1 + iw1; + long idx6 = out_off + i; + long idx7 = in_off + i; + long idx8 = in_off + ic; + w1r = wtable_rl.getFloat(idx5 - 1); + w1i = wtable_rl.getFloat(idx5); + long iidx1 = idx7 + idx2; + long iidx2 = idx8 + idx3; + long oidx1 = idx6 + idx1; + long oidx2 = idx6 + idx4; + t1r = in.getFloat(iidx1 - 1) - in.getFloat(iidx2 - 1); + t1i = in.getFloat(iidx1) + in.getFloat(iidx2); + float i1i = in.getFloat(iidx1); + float i1r = in.getFloat(iidx1 - 1); + float i2i = in.getFloat(iidx2); + float i2r = in.getFloat(iidx2 - 1); + + out.setFloat(oidx1 - 1, i1r + i2r); + out.setFloat(oidx1, i1i - i2i); + out.setFloat(oidx2 - 1, w1r * t1r - w1i * t1i); + out.setFloat(oidx2, w1r * t1i + w1i * t1r); + } + } + if (ido % 2 == 1) { + return; + } + } + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 2 * idx1; + long oidx1 = out_off + ido - 1 + idx1; + long iidx1 = in_off + idx2 + ido; + out.setFloat(oidx1, 2 * in.getFloat(iidx1 - 1)); + out.setFloat(oidx1 + idx0, -2 * in.getFloat(iidx1)); + } + } +*/ + /*------------------------------------------------- + radf3: Real FFT's forward processing of factor 3 + -------------------------------------------------*/ + void radf3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + int i, ic; + float ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; + int iw1, iw2; + iw1 = offset; + iw2 = iw1 + ido; + + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx3 = 2 * idx0; + int idx4 = (3 * k + 1) * ido; + int iidx1 = in_off + idx1; + int iidx2 = iidx1 + idx0; + int iidx3 = iidx1 + idx3; + float i1r = in[iidx1]; + float i2r = in[iidx2]; + float i3r = in[iidx3]; + cr2 = i2r + i3r; + out[out_off + 3 * idx1] = i1r + cr2; + out[out_off + idx4 + ido] = taui * (i3r - i2r); + out[out_off + ido - 1 + idx4] = i1r + taur * cr2; + } + if (ido == 1) { + return; + } + for (int k = 0; k < l1; k++) { + int idx3 = k * ido; + int idx4 = 3 * idx3; + int idx5 = idx3 + idx0; + int idx6 = idx5 + idx0; + int idx7 = idx4 + ido; + int idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + + int idx9 = in_off + i; + int idx10 = out_off + i; + int idx11 = out_off + ic; + int iidx1 = idx9 + idx3; + int iidx2 = idx9 + idx5; + int iidx3 = idx9 + idx6; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + + dr2 = w1r * i2i + w1i * i2r; + di2 = w1r * i2r - w1i * i2i; + dr3 = w2r * i3i + w2i * i3r; + di3 = w2r * i3r - w2i * i3i; + cr2 = dr2 + dr3; + ci2 = di2 + di3; + tr2 = i1i + taur * cr2; + ti2 = i1r + taur * ci2; + tr3 = taui * (di2 - di3); + ti3 = taui * (dr3 - dr2); + + int oidx1 = idx10 + idx4; + int oidx2 = idx11 + idx7; + int oidx3 = idx10 + idx8; + + out[oidx1 - 1] = i1i + cr2; + out[oidx1] = i1r + ci2; + out[oidx2 - 1] = tr2 - tr3; + out[oidx2] = ti3 - ti2; + out[oidx3 - 1] = tr2 + tr3; + out[oidx3] = ti2 + ti3; + } + } + } + + /*------------------------------------------------- + radf3: Real FFT's forward processing of factor 3 + -------------------------------------------------*/ +/* + void radf3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + long i, ic; + float ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; + long iw1, iw2; + iw1 = offset; + iw2 = iw1 + ido; + + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx3 = 2 * idx0; + long idx4 = (3 * k + 1) * ido; + long iidx1 = in_off + idx1; + long iidx2 = iidx1 + idx0; + long iidx3 = iidx1 + idx3; + float i1r = in.getFloat(iidx1); + float i2r = in.getFloat(iidx2); + float i3r = in.getFloat(iidx3); + cr2 = i2r + i3r; + out.setFloat(out_off + 3 * idx1, i1r + cr2); + out.setFloat(out_off + idx4 + ido, taui * (i3r - i2r)); + out.setFloat(out_off + ido - 1 + idx4, i1r + taur * cr2); + } + if (ido == 1) { + return; + } + for (long k = 0; k < l1; k++) { + long idx3 = k * ido; + long idx4 = 3 * idx3; + long idx5 = idx3 + idx0; + long idx6 = idx5 + idx0; + long idx7 = idx4 + ido; + long idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + + long idx9 = in_off + i; + long idx10 = out_off + i; + long idx11 = out_off + ic; + long iidx1 = idx9 + idx3; + long iidx2 = idx9 + idx5; + long iidx3 = idx9 + idx6; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + + dr2 = w1r * i2i + w1i * i2r; + di2 = w1r * i2r - w1i * i2i; + dr3 = w2r * i3i + w2i * i3r; + di3 = w2r * i3r - w2i * i3i; + cr2 = dr2 + dr3; + ci2 = di2 + di3; + tr2 = i1i + taur * cr2; + ti2 = i1r + taur * ci2; + tr3 = taui * (di2 - di3); + ti3 = taui * (dr3 - dr2); + + long oidx1 = idx10 + idx4; + long oidx2 = idx11 + idx7; + long oidx3 = idx10 + idx8; + + out.setFloat(oidx1 - 1, i1i + cr2); + out.setFloat(oidx1, i1r + ci2); + out.setFloat(oidx2 - 1, tr2 - tr3); + out.setFloat(oidx2, ti3 - ti2); + out.setFloat(oidx3 - 1, tr2 + tr3); + out.setFloat(oidx3, ti2 + ti3); + } + } + } +*/ + /*------------------------------------------------- + radb3: Real FFT's backward processing of factor 3 + -------------------------------------------------*/ + void radb3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + int i, ic; + float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; + int iw1, iw2; + iw1 = offset; + iw2 = iw1 + ido; + + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int iidx1 = in_off + 3 * idx1; + int iidx2 = iidx1 + 2 * ido; + float i1i = in[iidx1]; + + tr2 = 2 * in[iidx2 - 1]; + cr2 = i1i + taur * tr2; + ci3 = 2 * taui * in[iidx2]; + + out[out_off + idx1] = i1i + tr2; + out[out_off + (k + l1) * ido] = cr2 - ci3; + out[out_off + (k + 2 * l1) * ido] = cr2 + ci3; + } + if (ido == 1) { + return; + } + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 3 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx3 + ido; + int idx5 = idx1 + idx0; + int idx6 = idx5 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int idx7 = in_off + i; + int idx8 = in_off + ic; + int idx9 = out_off + i; + int iidx1 = idx7 + idx2; + int iidx2 = idx7 + idx4; + int iidx3 = idx8 + idx3; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + + tr2 = i2i + i3i; + cr2 = i1i + taur * tr2; + ti2 = i2r - i3r; + ci2 = i1r + taur * ti2; + cr3 = taui * (i2i - i3i); + ci3 = taui * (i2r + i3r); + dr2 = cr2 - ci3; + dr3 = cr2 + ci3; + di2 = ci2 + cr3; + di3 = ci2 - cr3; + + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + + int oidx1 = idx9 + idx1; + int oidx2 = idx9 + idx5; + int oidx3 = idx9 + idx6; + + out[oidx1 - 1] = i1i + tr2; + out[oidx1] = i1r + ti2; + out[oidx2 - 1] = w1r * dr2 - w1i * di2; + out[oidx2] = w1r * di2 + w1i * dr2; + out[oidx3 - 1] = w2r * dr3 - w2i * di3; + out[oidx3] = w2r * di3 + w2i * dr3; + } + } + } + + /*------------------------------------------------- + radb3: Real FFT's backward processing of factor 3 + -------------------------------------------------*/ +/* + void radb3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + long i, ic; + float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; + long iw1, iw2; + iw1 = offset; + iw2 = iw1 + ido; + + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long iidx1 = in_off + 3 * idx1; + long iidx2 = iidx1 + 2 * ido; + float i1i = in.getFloat(iidx1); + + tr2 = 2 * in.getFloat(iidx2 - 1); + cr2 = i1i + taur * tr2; + ci3 = 2 * taui * in.getFloat(iidx2); + + out.setFloat(out_off + idx1, i1i + tr2); + out.setFloat(out_off + (k + l1) * ido, cr2 - ci3); + out.setFloat(out_off + (k + 2 * l1) * ido, cr2 + ci3); + } + if (ido == 1) { + return; + } + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 3 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx3 + ido; + long idx5 = idx1 + idx0; + long idx6 = idx5 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long idx7 = in_off + i; + long idx8 = in_off + ic; + long idx9 = out_off + i; + long iidx1 = idx7 + idx2; + long iidx2 = idx7 + idx4; + long iidx3 = idx8 + idx3; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + + tr2 = i2i + i3i; + cr2 = i1i + taur * tr2; + ti2 = i2r - i3r; + ci2 = i1r + taur * ti2; + cr3 = taui * (i2i - i3i); + ci3 = taui * (i2r + i3r); + dr2 = cr2 - ci3; + dr3 = cr2 + ci3; + di2 = ci2 + cr3; + di3 = ci2 - cr3; + + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + + long oidx1 = idx9 + idx1; + long oidx2 = idx9 + idx5; + long oidx3 = idx9 + idx6; + + out.setFloat(oidx1 - 1, i1i + tr2); + out.setFloat(oidx1, i1r + ti2); + out.setFloat(oidx2 - 1, w1r * dr2 - w1i * di2); + out.setFloat(oidx2, w1r * di2 + w1i * dr2); + out.setFloat(oidx3 - 1, w2r * dr3 - w2i * di3); + out.setFloat(oidx3, w2r * di3 + w2i * dr3); + } + } + } +*/ + /*------------------------------------------------- + radf4: Real FFT's forward processing of factor 4 + -------------------------------------------------*/ + void radf4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float hsqt2 = 0.707106781186547572737310929369414225f; + int i, ic; + float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; + int iw1, iw2, iw3; + iw1 = offset; + iw2 = offset + ido; + iw3 = iw2 + ido; + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 4 * idx1; + int idx3 = idx1 + idx0; + int idx4 = idx3 + idx0; + int idx5 = idx4 + idx0; + int idx6 = idx2 + ido; + float i1r = in[in_off + idx1]; + float i2r = in[in_off + idx3]; + float i3r = in[in_off + idx4]; + float i4r = in[in_off + idx5]; + + tr1 = i2r + i4r; + tr2 = i1r + i3r; + + int oidx1 = out_off + idx2; + int oidx2 = out_off + idx6 + ido; + + out[oidx1] = tr1 + tr2; + out[oidx2 - 1 + ido + ido] = tr2 - tr1; + out[oidx2 - 1] = i1r - i3r; + out[oidx2] = i4r - i2r; + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = idx1 + idx0; + int idx3 = idx2 + idx0; + int idx4 = idx3 + idx0; + int idx5 = 4 * idx1; + int idx6 = idx5 + ido; + int idx7 = idx6 + ido; + int idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + int widx3 = i - 1 + iw3; + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + w3r = wtable_r[widx3 - 1]; + w3i = wtable_r[widx3]; + + int idx9 = in_off + i; + int idx10 = out_off + i; + int idx11 = out_off + ic; + int iidx1 = idx9 + idx1; + int iidx2 = idx9 + idx2; + int iidx3 = idx9 + idx3; + int iidx4 = idx9 + idx4; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + + cr2 = w1r * i2i + w1i * i2r; + ci2 = w1r * i2r - w1i * i2i; + cr3 = w2r * i3i + w2i * i3r; + ci3 = w2r * i3r - w2i * i3i; + cr4 = w3r * i4i + w3i * i4r; + ci4 = w3r * i4r - w3i * i4i; + tr1 = cr2 + cr4; + tr4 = cr4 - cr2; + ti1 = ci2 + ci4; + ti4 = ci2 - ci4; + ti2 = i1r + ci3; + ti3 = i1r - ci3; + tr2 = i1i + cr3; + tr3 = i1i - cr3; + + int oidx1 = idx10 + idx5; + int oidx2 = idx11 + idx6; + int oidx3 = idx10 + idx7; + int oidx4 = idx11 + idx8; + + out[oidx1 - 1] = tr1 + tr2; + out[oidx4 - 1] = tr2 - tr1; + out[oidx1] = ti1 + ti2; + out[oidx4] = ti1 - ti2; + out[oidx3 - 1] = ti4 + tr3; + out[oidx2 - 1] = tr3 - ti4; + out[oidx3] = tr4 + ti3; + out[oidx2] = tr4 - ti3; + } + } + if (ido % 2 == 1) { + return; + } + } + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 4 * idx1; + int idx3 = idx1 + idx0; + int idx4 = idx3 + idx0; + int idx5 = idx4 + idx0; + int idx6 = idx2 + ido; + int idx7 = idx6 + ido; + int idx8 = idx7 + ido; + int idx9 = in_off + ido; + int idx10 = out_off + ido; + + float i1i = in[idx9 - 1 + idx1]; + float i2i = in[idx9 - 1 + idx3]; + float i3i = in[idx9 - 1 + idx4]; + float i4i = in[idx9 - 1 + idx5]; + + ti1 = -hsqt2 * (i2i + i4i); + tr1 = hsqt2 * (i2i - i4i); + + out[idx10 - 1 + idx2] = tr1 + i1i; + out[idx10 - 1 + idx7] = i1i - tr1; + out[out_off + idx6] = ti1 - i3i; + out[out_off + idx8] = ti1 + i3i; + } + } + + /*------------------------------------------------- + radf4: Real FFT's forward processing of factor 4 + -------------------------------------------------*/ +/* + void radf4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float hsqt2 = 0.707106781186547572737310929369414225f; + long i, ic; + float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; + long iw1, iw2, iw3; + iw1 = offset; + iw2 = offset + ido; + iw3 = iw2 + ido; + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 4 * idx1; + long idx3 = idx1 + idx0; + long idx4 = idx3 + idx0; + long idx5 = idx4 + idx0; + long idx6 = idx2 + ido; + float i1r = in.getFloat(in_off + idx1); + float i2r = in.getFloat(in_off + idx3); + float i3r = in.getFloat(in_off + idx4); + float i4r = in.getFloat(in_off + idx5); + + tr1 = i2r + i4r; + tr2 = i1r + i3r; + + long oidx1 = out_off + idx2; + long oidx2 = out_off + idx6 + ido; + + out.setFloat(oidx1, tr1 + tr2); + out.setFloat(oidx2 - 1 + ido + ido, tr2 - tr1); + out.setFloat(oidx2 - 1, i1r - i3r); + out.setFloat(oidx2, i4r - i2r); + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = idx1 + idx0; + long idx3 = idx2 + idx0; + long idx4 = idx3 + idx0; + long idx5 = 4 * idx1; + long idx6 = idx5 + ido; + long idx7 = idx6 + ido; + long idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + long widx3 = i - 1 + iw3; + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + w3r = wtable_rl.getFloat(widx3 - 1); + w3i = wtable_rl.getFloat(widx3); + + long idx9 = in_off + i; + long idx10 = out_off + i; + long idx11 = out_off + ic; + long iidx1 = idx9 + idx1; + long iidx2 = idx9 + idx2; + long iidx3 = idx9 + idx3; + long iidx4 = idx9 + idx4; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + + cr2 = w1r * i2i + w1i * i2r; + ci2 = w1r * i2r - w1i * i2i; + cr3 = w2r * i3i + w2i * i3r; + ci3 = w2r * i3r - w2i * i3i; + cr4 = w3r * i4i + w3i * i4r; + ci4 = w3r * i4r - w3i * i4i; + tr1 = cr2 + cr4; + tr4 = cr4 - cr2; + ti1 = ci2 + ci4; + ti4 = ci2 - ci4; + ti2 = i1r + ci3; + ti3 = i1r - ci3; + tr2 = i1i + cr3; + tr3 = i1i - cr3; + + long oidx1 = idx10 + idx5; + long oidx2 = idx11 + idx6; + long oidx3 = idx10 + idx7; + long oidx4 = idx11 + idx8; + + out.setFloat(oidx1 - 1, tr1 + tr2); + out.setFloat(oidx4 - 1, tr2 - tr1); + out.setFloat(oidx1, ti1 + ti2); + out.setFloat(oidx4, ti1 - ti2); + out.setFloat(oidx3 - 1, ti4 + tr3); + out.setFloat(oidx2 - 1, tr3 - ti4); + out.setFloat(oidx3, tr4 + ti3); + out.setFloat(oidx2, tr4 - ti3); + } + } + if (ido % 2 == 1) { + return; + } + } + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 4 * idx1; + long idx3 = idx1 + idx0; + long idx4 = idx3 + idx0; + long idx5 = idx4 + idx0; + long idx6 = idx2 + ido; + long idx7 = idx6 + ido; + long idx8 = idx7 + ido; + long idx9 = in_off + ido; + long idx10 = out_off + ido; + + float i1i = in.getFloat(idx9 - 1 + idx1); + float i2i = in.getFloat(idx9 - 1 + idx3); + float i3i = in.getFloat(idx9 - 1 + idx4); + float i4i = in.getFloat(idx9 - 1 + idx5); + + ti1 = -hsqt2 * (i2i + i4i); + tr1 = hsqt2 * (i2i - i4i); + + out.setFloat(idx10 - 1 + idx2, tr1 + i1i); + out.setFloat(idx10 - 1 + idx7, i1i - tr1); + out.setFloat(out_off + idx6, ti1 - i3i); + out.setFloat(out_off + idx8, ti1 + i3i); + } + } +*/ + /*------------------------------------------------- + radb4: Real FFT's backward processing of factor 4 + -------------------------------------------------*/ + void radb4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float sqrt2 = 1.41421356237309514547462185873882845f; + int i, ic; + float ci2, ci3, ci4, cr2, cr3, cr4; + float ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; + int iw1, iw2, iw3; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 4 * idx1; + int idx3 = idx1 + idx0; + int idx4 = idx3 + idx0; + int idx5 = idx4 + idx0; + int idx6 = idx2 + ido; + int idx7 = idx6 + ido; + int idx8 = idx7 + ido; + + float i1r = in[in_off + idx2]; + float i2r = in[in_off + idx7]; + float i3r = in[in_off + ido - 1 + idx8]; + float i4r = in[in_off + ido - 1 + idx6]; + + tr1 = i1r - i3r; + tr2 = i1r + i3r; + tr3 = i4r + i4r; + tr4 = i2r + i2r; + + out[out_off + idx1] = tr2 + tr3; + out[out_off + idx3] = tr1 - tr4; + out[out_off + idx4] = tr2 - tr3; + out[out_off + idx5] = tr1 + tr4; + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (int k = 0; k < l1; ++k) { + int idx1 = k * ido; + int idx2 = idx1 + idx0; + int idx3 = idx2 + idx0; + int idx4 = idx3 + idx0; + int idx5 = 4 * idx1; + int idx6 = idx5 + ido; + int idx7 = idx6 + ido; + int idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + int widx3 = i - 1 + iw3; + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + w3r = wtable_r[widx3 - 1]; + w3i = wtable_r[widx3]; + + int idx12 = in_off + i; + int idx13 = in_off + ic; + int idx14 = out_off + i; + + int iidx1 = idx12 + idx5; + int iidx2 = idx13 + idx6; + int iidx3 = idx12 + idx7; + int iidx4 = idx13 + idx8; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + + ti1 = i1r + i4r; + ti2 = i1r - i4r; + ti3 = i3r - i2r; + tr4 = i3r + i2r; + tr1 = i1i - i4i; + tr2 = i1i + i4i; + ti4 = i3i - i2i; + tr3 = i3i + i2i; + cr3 = tr2 - tr3; + ci3 = ti2 - ti3; + cr2 = tr1 - tr4; + cr4 = tr1 + tr4; + ci2 = ti1 + ti4; + ci4 = ti1 - ti4; + + int oidx1 = idx14 + idx1; + int oidx2 = idx14 + idx2; + int oidx3 = idx14 + idx3; + int oidx4 = idx14 + idx4; + + out[oidx1 - 1] = tr2 + tr3; + out[oidx1] = ti2 + ti3; + out[oidx2 - 1] = w1r * cr2 - w1i * ci2; + out[oidx2] = w1r * ci2 + w1i * cr2; + out[oidx3 - 1] = w2r * cr3 - w2i * ci3; + out[oidx3] = w2r * ci3 + w2i * cr3; + out[oidx4 - 1] = w3r * cr4 - w3i * ci4; + out[oidx4] = w3r * ci4 + w3i * cr4; + } + } + if (ido % 2 == 1) { + return; + } + } + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 4 * idx1; + int idx3 = idx1 + idx0; + int idx4 = idx3 + idx0; + int idx5 = idx4 + idx0; + int idx6 = idx2 + ido; + int idx7 = idx6 + ido; + int idx8 = idx7 + ido; + int idx9 = in_off + ido; + int idx10 = out_off + ido; + + float i1r = in[idx9 - 1 + idx2]; + float i2r = in[idx9 - 1 + idx7]; + float i3r = in[in_off + idx6]; + float i4r = in[in_off + idx8]; + + ti1 = i3r + i4r; + ti2 = i4r - i3r; + tr1 = i1r - i2r; + tr2 = i1r + i2r; + + out[idx10 - 1 + idx1] = tr2 + tr2; + out[idx10 - 1 + idx3] = sqrt2 * (tr1 - ti1); + out[idx10 - 1 + idx4] = ti2 + ti2; + out[idx10 - 1 + idx5] = -sqrt2 * (tr1 + ti1); + } + } + + /*------------------------------------------------- + radb4: Real FFT's backward processing of factor 4 + -------------------------------------------------*/ +/* + void radb4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float sqrt2 = 1.41421356237309514547462185873882845f; + long i, ic; + float ci2, ci3, ci4, cr2, cr3, cr4; + float ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; + long iw1, iw2, iw3; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 4 * idx1; + long idx3 = idx1 + idx0; + long idx4 = idx3 + idx0; + long idx5 = idx4 + idx0; + long idx6 = idx2 + ido; + long idx7 = idx6 + ido; + long idx8 = idx7 + ido; + + float i1r = in.getFloat(in_off + idx2); + float i2r = in.getFloat(in_off + idx7); + float i3r = in.getFloat(in_off + ido - 1 + idx8); + float i4r = in.getFloat(in_off + ido - 1 + idx6); + + tr1 = i1r - i3r; + tr2 = i1r + i3r; + tr3 = i4r + i4r; + tr4 = i2r + i2r; + + out.setFloat(out_off + idx1, tr2 + tr3); + out.setFloat(out_off + idx3, tr1 - tr4); + out.setFloat(out_off + idx4, tr2 - tr3); + out.setFloat(out_off + idx5, tr1 + tr4); + } + if (ido < 2) { + return; + } + if (ido != 2) { + for (long k = 0; k < l1; ++k) { + long idx1 = k * ido; + long idx2 = idx1 + idx0; + long idx3 = idx2 + idx0; + long idx4 = idx3 + idx0; + long idx5 = 4 * idx1; + long idx6 = idx5 + ido; + long idx7 = idx6 + ido; + long idx8 = idx7 + ido; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + long widx3 = i - 1 + iw3; + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + w3r = wtable_rl.getFloat(widx3 - 1); + w3i = wtable_rl.getFloat(widx3); + + long idx12 = in_off + i; + long idx13 = in_off + ic; + long idx14 = out_off + i; + + long iidx1 = idx12 + idx5; + long iidx2 = idx13 + idx6; + long iidx3 = idx12 + idx7; + long iidx4 = idx13 + idx8; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + + ti1 = i1r + i4r; + ti2 = i1r - i4r; + ti3 = i3r - i2r; + tr4 = i3r + i2r; + tr1 = i1i - i4i; + tr2 = i1i + i4i; + ti4 = i3i - i2i; + tr3 = i3i + i2i; + cr3 = tr2 - tr3; + ci3 = ti2 - ti3; + cr2 = tr1 - tr4; + cr4 = tr1 + tr4; + ci2 = ti1 + ti4; + ci4 = ti1 - ti4; + + long oidx1 = idx14 + idx1; + long oidx2 = idx14 + idx2; + long oidx3 = idx14 + idx3; + long oidx4 = idx14 + idx4; + + out.setFloat(oidx1 - 1, tr2 + tr3); + out.setFloat(oidx1, ti2 + ti3); + out.setFloat(oidx2 - 1, w1r * cr2 - w1i * ci2); + out.setFloat(oidx2, w1r * ci2 + w1i * cr2); + out.setFloat(oidx3 - 1, w2r * cr3 - w2i * ci3); + out.setFloat(oidx3, w2r * ci3 + w2i * cr3); + out.setFloat(oidx4 - 1, w3r * cr4 - w3i * ci4); + out.setFloat(oidx4, w3r * ci4 + w3i * cr4); + } + } + if (ido % 2 == 1) { + return; + } + } + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 4 * idx1; + long idx3 = idx1 + idx0; + long idx4 = idx3 + idx0; + long idx5 = idx4 + idx0; + long idx6 = idx2 + ido; + long idx7 = idx6 + ido; + long idx8 = idx7 + ido; + long idx9 = in_off + ido; + long idx10 = out_off + ido; + + float i1r = in.getFloat(idx9 - 1 + idx2); + float i2r = in.getFloat(idx9 - 1 + idx7); + float i3r = in.getFloat(in_off + idx6); + float i4r = in.getFloat(in_off + idx8); + + ti1 = i3r + i4r; + ti2 = i4r - i3r; + tr1 = i1r - i2r; + tr2 = i1r + i2r; + + out.setFloat(idx10 - 1 + idx1, tr2 + tr2); + out.setFloat(idx10 - 1 + idx3, sqrt2 * (tr1 - ti1)); + out.setFloat(idx10 - 1 + idx4, ti2 + ti2); + out.setFloat(idx10 - 1 + idx5, -sqrt2 * (tr1 + ti1)); + } + } +*/ + /*------------------------------------------------- + radf5: Real FFT's forward processing of factor 5 + -------------------------------------------------*/ + void radf5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + int i, ic; + float ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; + int iw1, iw2, iw3, iw4; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 5 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx3 + ido; + int idx5 = idx4 + ido; + int idx6 = idx5 + ido; + int idx7 = idx1 + idx0; + int idx8 = idx7 + idx0; + int idx9 = idx8 + idx0; + int idx10 = idx9 + idx0; + int idx11 = out_off + ido - 1; + + float i1r = in[in_off + idx1]; + float i2r = in[in_off + idx7]; + float i3r = in[in_off + idx8]; + float i4r = in[in_off + idx9]; + float i5r = in[in_off + idx10]; + + cr2 = i5r + i2r; + ci5 = i5r - i2r; + cr3 = i4r + i3r; + ci4 = i4r - i3r; + + out[out_off + idx2] = i1r + cr2 + cr3; + out[idx11 + idx3] = i1r + tr11 * cr2 + tr12 * cr3; + out[out_off + idx4] = ti11 * ci5 + ti12 * ci4; + out[idx11 + idx5] = i1r + tr12 * cr2 + tr11 * cr3; + out[out_off + idx6] = ti12 * ci5 - ti11 * ci4; + } + if (ido == 1) { + return; + } + for (int k = 0; k < l1; ++k) { + int idx1 = k * ido; + int idx2 = 5 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx3 + ido; + int idx5 = idx4 + ido; + int idx6 = idx5 + ido; + int idx7 = idx1 + idx0; + int idx8 = idx7 + idx0; + int idx9 = idx8 + idx0; + int idx10 = idx9 + idx0; + for (i = 2; i < ido; i += 2) { + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + int widx3 = i - 1 + iw3; + int widx4 = i - 1 + iw4; + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + w3r = wtable_r[widx3 - 1]; + w3i = wtable_r[widx3]; + w4r = wtable_r[widx4 - 1]; + w4i = wtable_r[widx4]; + + ic = ido - i; + int idx15 = in_off + i; + int idx16 = out_off + i; + int idx17 = out_off + ic; + + int iidx1 = idx15 + idx1; + int iidx2 = idx15 + idx7; + int iidx3 = idx15 + idx8; + int iidx4 = idx15 + idx9; + int iidx5 = idx15 + idx10; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + float i5i = in[iidx5 - 1]; + float i5r = in[iidx5]; + + dr2 = w1r * i2i + w1i * i2r; + di2 = w1r * i2r - w1i * i2i; + dr3 = w2r * i3i + w2i * i3r; + di3 = w2r * i3r - w2i * i3i; + dr4 = w3r * i4i + w3i * i4r; + di4 = w3r * i4r - w3i * i4i; + dr5 = w4r * i5i + w4i * i5r; + di5 = w4r * i5r - w4i * i5i; + + cr2 = dr2 + dr5; + ci5 = dr5 - dr2; + cr5 = di2 - di5; + ci2 = di2 + di5; + cr3 = dr3 + dr4; + ci4 = dr4 - dr3; + cr4 = di3 - di4; + ci3 = di3 + di4; + + tr2 = i1i + tr11 * cr2 + tr12 * cr3; + ti2 = i1r + tr11 * ci2 + tr12 * ci3; + tr3 = i1i + tr12 * cr2 + tr11 * cr3; + ti3 = i1r + tr12 * ci2 + tr11 * ci3; + tr5 = ti11 * cr5 + ti12 * cr4; + ti5 = ti11 * ci5 + ti12 * ci4; + tr4 = ti12 * cr5 - ti11 * cr4; + ti4 = ti12 * ci5 - ti11 * ci4; + + int oidx1 = idx16 + idx2; + int oidx2 = idx17 + idx3; + int oidx3 = idx16 + idx4; + int oidx4 = idx17 + idx5; + int oidx5 = idx16 + idx6; + + out[oidx1 - 1] = i1i + cr2 + cr3; + out[oidx1] = i1r + ci2 + ci3; + out[oidx3 - 1] = tr2 + tr5; + out[oidx2 - 1] = tr2 - tr5; + out[oidx3] = ti2 + ti5; + out[oidx2] = ti5 - ti2; + out[oidx5 - 1] = tr3 + tr4; + out[oidx4 - 1] = tr3 - tr4; + out[oidx5] = ti3 + ti4; + out[oidx4] = ti4 - ti3; + } + } + } + + /*------------------------------------------------- + radf5: Real FFT's forward processing of factor 5 + -------------------------------------------------*/ +/* + void radf5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + long i, ic; + float ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; + long iw1, iw2, iw3, iw4; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 5 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx3 + ido; + long idx5 = idx4 + ido; + long idx6 = idx5 + ido; + long idx7 = idx1 + idx0; + long idx8 = idx7 + idx0; + long idx9 = idx8 + idx0; + long idx10 = idx9 + idx0; + long idx11 = out_off + ido - 1; + + float i1r = in.getFloat(in_off + idx1); + float i2r = in.getFloat(in_off + idx7); + float i3r = in.getFloat(in_off + idx8); + float i4r = in.getFloat(in_off + idx9); + float i5r = in.getFloat(in_off + idx10); + + cr2 = i5r + i2r; + ci5 = i5r - i2r; + cr3 = i4r + i3r; + ci4 = i4r - i3r; + + out.setFloat(out_off + idx2, i1r + cr2 + cr3); + out.setFloat(idx11 + idx3, i1r + tr11 * cr2 + tr12 * cr3); + out.setFloat(out_off + idx4, ti11 * ci5 + ti12 * ci4); + out.setFloat(idx11 + idx5, i1r + tr12 * cr2 + tr11 * cr3); + out.setFloat(out_off + idx6, ti12 * ci5 - ti11 * ci4); + } + if (ido == 1) { + return; + } + for (long k = 0; k < l1; ++k) { + long idx1 = k * ido; + long idx2 = 5 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx3 + ido; + long idx5 = idx4 + ido; + long idx6 = idx5 + ido; + long idx7 = idx1 + idx0; + long idx8 = idx7 + idx0; + long idx9 = idx8 + idx0; + long idx10 = idx9 + idx0; + for (i = 2; i < ido; i += 2) { + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + long widx3 = i - 1 + iw3; + long widx4 = i - 1 + iw4; + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + w3r = wtable_rl.getFloat(widx3 - 1); + w3i = wtable_rl.getFloat(widx3); + w4r = wtable_rl.getFloat(widx4 - 1); + w4i = wtable_rl.getFloat(widx4); + + ic = ido - i; + long idx15 = in_off + i; + long idx16 = out_off + i; + long idx17 = out_off + ic; + + long iidx1 = idx15 + idx1; + long iidx2 = idx15 + idx7; + long iidx3 = idx15 + idx8; + long iidx4 = idx15 + idx9; + long iidx5 = idx15 + idx10; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + float i5i = in.getFloat(iidx5 - 1); + float i5r = in.getFloat(iidx5); + + dr2 = w1r * i2i + w1i * i2r; + di2 = w1r * i2r - w1i * i2i; + dr3 = w2r * i3i + w2i * i3r; + di3 = w2r * i3r - w2i * i3i; + dr4 = w3r * i4i + w3i * i4r; + di4 = w3r * i4r - w3i * i4i; + dr5 = w4r * i5i + w4i * i5r; + di5 = w4r * i5r - w4i * i5i; + + cr2 = dr2 + dr5; + ci5 = dr5 - dr2; + cr5 = di2 - di5; + ci2 = di2 + di5; + cr3 = dr3 + dr4; + ci4 = dr4 - dr3; + cr4 = di3 - di4; + ci3 = di3 + di4; + + tr2 = i1i + tr11 * cr2 + tr12 * cr3; + ti2 = i1r + tr11 * ci2 + tr12 * ci3; + tr3 = i1i + tr12 * cr2 + tr11 * cr3; + ti3 = i1r + tr12 * ci2 + tr11 * ci3; + tr5 = ti11 * cr5 + ti12 * cr4; + ti5 = ti11 * ci5 + ti12 * ci4; + tr4 = ti12 * cr5 - ti11 * cr4; + ti4 = ti12 * ci5 - ti11 * ci4; + + long oidx1 = idx16 + idx2; + long oidx2 = idx17 + idx3; + long oidx3 = idx16 + idx4; + long oidx4 = idx17 + idx5; + long oidx5 = idx16 + idx6; + + out.setFloat(oidx1 - 1, i1i + cr2 + cr3); + out.setFloat(oidx1, i1r + ci2 + ci3); + out.setFloat(oidx3 - 1, tr2 + tr5); + out.setFloat(oidx2 - 1, tr2 - tr5); + out.setFloat(oidx3, ti2 + ti5); + out.setFloat(oidx2, ti5 - ti2); + out.setFloat(oidx5 - 1, tr3 + tr4); + out.setFloat(oidx4 - 1, tr3 - tr4); + out.setFloat(oidx5, ti3 + ti4); + out.setFloat(oidx4, ti4 - ti3); + } + } + } +*/ + /*------------------------------------------------- + radb5: Real FFT's backward processing of factor 5 + -------------------------------------------------*/ + void radb5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + int i, ic; + float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; + int iw1, iw2, iw3, iw4; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + int idx0 = l1 * ido; + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = 5 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx3 + ido; + int idx5 = idx4 + ido; + int idx6 = idx5 + ido; + int idx7 = idx1 + idx0; + int idx8 = idx7 + idx0; + int idx9 = idx8 + idx0; + int idx10 = idx9 + idx0; + int idx11 = in_off + ido - 1; + + float i1r = in[in_off + idx2]; + + ti5 = 2 * in[in_off + idx4]; + ti4 = 2 * in[in_off + idx6]; + tr2 = 2 * in[idx11 + idx3]; + tr3 = 2 * in[idx11 + idx5]; + cr2 = i1r + tr11 * tr2 + tr12 * tr3; + cr3 = i1r + tr12 * tr2 + tr11 * tr3; + ci5 = ti11 * ti5 + ti12 * ti4; + ci4 = ti12 * ti5 - ti11 * ti4; + + out[out_off + idx1] = i1r + tr2 + tr3; + out[out_off + idx7] = cr2 - ci5; + out[out_off + idx8] = cr3 - ci4; + out[out_off + idx9] = cr3 + ci4; + out[out_off + idx10] = cr2 + ci5; + } + if (ido == 1) { + return; + } + for (int k = 0; k < l1; ++k) { + int idx1 = k * ido; + int idx2 = 5 * idx1; + int idx3 = idx2 + ido; + int idx4 = idx3 + ido; + int idx5 = idx4 + ido; + int idx6 = idx5 + ido; + int idx7 = idx1 + idx0; + int idx8 = idx7 + idx0; + int idx9 = idx8 + idx0; + int idx10 = idx9 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + int widx1 = i - 1 + iw1; + int widx2 = i - 1 + iw2; + int widx3 = i - 1 + iw3; + int widx4 = i - 1 + iw4; + w1r = wtable_r[widx1 - 1]; + w1i = wtable_r[widx1]; + w2r = wtable_r[widx2 - 1]; + w2i = wtable_r[widx2]; + w3r = wtable_r[widx3 - 1]; + w3i = wtable_r[widx3]; + w4r = wtable_r[widx4 - 1]; + w4i = wtable_r[widx4]; + + int idx15 = in_off + i; + int idx16 = in_off + ic; + int idx17 = out_off + i; + + int iidx1 = idx15 + idx2; + int iidx2 = idx16 + idx3; + int iidx3 = idx15 + idx4; + int iidx4 = idx16 + idx5; + int iidx5 = idx15 + idx6; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + float i5i = in[iidx5 - 1]; + float i5r = in[iidx5]; + + ti5 = i3r + i2r; + ti2 = i3r - i2r; + ti4 = i5r + i4r; + ti3 = i5r - i4r; + tr5 = i3i - i2i; + tr2 = i3i + i2i; + tr4 = i5i - i4i; + tr3 = i5i + i4i; + + cr2 = i1i + tr11 * tr2 + tr12 * tr3; + ci2 = i1r + tr11 * ti2 + tr12 * ti3; + cr3 = i1i + tr12 * tr2 + tr11 * tr3; + ci3 = i1r + tr12 * ti2 + tr11 * ti3; + cr5 = ti11 * tr5 + ti12 * tr4; + ci5 = ti11 * ti5 + ti12 * ti4; + cr4 = ti12 * tr5 - ti11 * tr4; + ci4 = ti12 * ti5 - ti11 * ti4; + dr3 = cr3 - ci4; + dr4 = cr3 + ci4; + di3 = ci3 + cr4; + di4 = ci3 - cr4; + dr5 = cr2 + ci5; + dr2 = cr2 - ci5; + di5 = ci2 - cr5; + di2 = ci2 + cr5; + + int oidx1 = idx17 + idx1; + int oidx2 = idx17 + idx7; + int oidx3 = idx17 + idx8; + int oidx4 = idx17 + idx9; + int oidx5 = idx17 + idx10; + + out[oidx1 - 1] = i1i + tr2 + tr3; + out[oidx1] = i1r + ti2 + ti3; + out[oidx2 - 1] = w1r * dr2 - w1i * di2; + out[oidx2] = w1r * di2 + w1i * dr2; + out[oidx3 - 1] = w2r * dr3 - w2i * di3; + out[oidx3] = w2r * di3 + w2i * dr3; + out[oidx4 - 1] = w3r * dr4 - w3i * di4; + out[oidx4] = w3r * di4 + w3i * dr4; + out[oidx5 - 1] = w4r * dr5 - w4i * di5; + out[oidx5] = w4r * di5 + w4i * dr5; + } + } + } + + /*------------------------------------------------- + radb5: Real FFT's backward processing of factor 5 + -------------------------------------------------*/ +/* + void radb5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + long i, ic; + float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; + long iw1, iw2, iw3, iw4; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + long idx0 = l1 * ido; + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = 5 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx3 + ido; + long idx5 = idx4 + ido; + long idx6 = idx5 + ido; + long idx7 = idx1 + idx0; + long idx8 = idx7 + idx0; + long idx9 = idx8 + idx0; + long idx10 = idx9 + idx0; + long idx11 = in_off + ido - 1; + + float i1r = in.getFloat(in_off + idx2); + + ti5 = 2 * in.getFloat(in_off + idx4); + ti4 = 2 * in.getFloat(in_off + idx6); + tr2 = 2 * in.getFloat(idx11 + idx3); + tr3 = 2 * in.getFloat(idx11 + idx5); + cr2 = i1r + tr11 * tr2 + tr12 * tr3; + cr3 = i1r + tr12 * tr2 + tr11 * tr3; + ci5 = ti11 * ti5 + ti12 * ti4; + ci4 = ti12 * ti5 - ti11 * ti4; + + out.setFloat(out_off + idx1, i1r + tr2 + tr3); + out.setFloat(out_off + idx7, cr2 - ci5); + out.setFloat(out_off + idx8, cr3 - ci4); + out.setFloat(out_off + idx9, cr3 + ci4); + out.setFloat(out_off + idx10, cr2 + ci5); + } + if (ido == 1) { + return; + } + for (long k = 0; k < l1; ++k) { + long idx1 = k * ido; + long idx2 = 5 * idx1; + long idx3 = idx2 + ido; + long idx4 = idx3 + ido; + long idx5 = idx4 + ido; + long idx6 = idx5 + ido; + long idx7 = idx1 + idx0; + long idx8 = idx7 + idx0; + long idx9 = idx8 + idx0; + long idx10 = idx9 + idx0; + for (i = 2; i < ido; i += 2) { + ic = ido - i; + long widx1 = i - 1 + iw1; + long widx2 = i - 1 + iw2; + long widx3 = i - 1 + iw3; + long widx4 = i - 1 + iw4; + w1r = wtable_rl.getFloat(widx1 - 1); + w1i = wtable_rl.getFloat(widx1); + w2r = wtable_rl.getFloat(widx2 - 1); + w2i = wtable_rl.getFloat(widx2); + w3r = wtable_rl.getFloat(widx3 - 1); + w3i = wtable_rl.getFloat(widx3); + w4r = wtable_rl.getFloat(widx4 - 1); + w4i = wtable_rl.getFloat(widx4); + + long idx15 = in_off + i; + long idx16 = in_off + ic; + long idx17 = out_off + i; + + long iidx1 = idx15 + idx2; + long iidx2 = idx16 + idx3; + long iidx3 = idx15 + idx4; + long iidx4 = idx16 + idx5; + long iidx5 = idx15 + idx6; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + float i5i = in.getFloat(iidx5 - 1); + float i5r = in.getFloat(iidx5); + + ti5 = i3r + i2r; + ti2 = i3r - i2r; + ti4 = i5r + i4r; + ti3 = i5r - i4r; + tr5 = i3i - i2i; + tr2 = i3i + i2i; + tr4 = i5i - i4i; + tr3 = i5i + i4i; + + cr2 = i1i + tr11 * tr2 + tr12 * tr3; + ci2 = i1r + tr11 * ti2 + tr12 * ti3; + cr3 = i1i + tr12 * tr2 + tr11 * tr3; + ci3 = i1r + tr12 * ti2 + tr11 * ti3; + cr5 = ti11 * tr5 + ti12 * tr4; + ci5 = ti11 * ti5 + ti12 * ti4; + cr4 = ti12 * tr5 - ti11 * tr4; + ci4 = ti12 * ti5 - ti11 * ti4; + dr3 = cr3 - ci4; + dr4 = cr3 + ci4; + di3 = ci3 + cr4; + di4 = ci3 - cr4; + dr5 = cr2 + ci5; + dr2 = cr2 - ci5; + di5 = ci2 - cr5; + di2 = ci2 + cr5; + + long oidx1 = idx17 + idx1; + long oidx2 = idx17 + idx7; + long oidx3 = idx17 + idx8; + long oidx4 = idx17 + idx9; + long oidx5 = idx17 + idx10; + + out.setFloat(oidx1 - 1, i1i + tr2 + tr3); + out.setFloat(oidx1, i1r + ti2 + ti3); + out.setFloat(oidx2 - 1, w1r * dr2 - w1i * di2); + out.setFloat(oidx2, w1r * di2 + w1i * dr2); + out.setFloat(oidx3 - 1, w2r * dr3 - w2i * di3); + out.setFloat(oidx3, w2r * di3 + w2i * dr3); + out.setFloat(oidx4 - 1, w3r * dr4 - w3i * di4); + out.setFloat(oidx4, w3r * di4 + w3i * dr4); + out.setFloat(oidx5 - 1, w4r * dr5 - w4i * di5); + out.setFloat(oidx5, w4r * di5 + w4i * dr5); + } + } + } +*/ + /*--------------------------------------------------------- + radfg: Real FFT's forward processing of general factor + --------------------------------------------------------*/ + void radfg(final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + int idij, ipph, j2, ic, jc, lc, is, nbd; + float dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; + int iw1 = offset; + + arg = TWO_PI / (float) ip; + dcp = (float)Math.cos(arg); + dsp = (float)Math.sin(arg); + ipph = (ip + 1) / 2; + nbd = (ido - 1) / 2; + if (ido != 1) { + for (int ik = 0; ik < idl1; ik++) { + out[out_off + ik] = in[in_off + ik]; + } + for (int j = 1; j < ip; j++) { + int idx1 = j * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx2 = k * ido + idx1; + out[out_off + idx2] = in[in_off + idx2]; + } + } + if (nbd <= l1) { + is = -ido; + for (int j = 1; j < ip; j++) { + is += ido; + idij = is - 1; + int idx1 = j * l1 * ido; + for (int i = 2; i < ido; i += 2) { + idij += 2; + int idx2 = idij + iw1; + int idx4 = in_off + i; + int idx5 = out_off + i; + w1r = wtable_r[idx2 - 1]; + w1i = wtable_r[idx2]; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido + idx1; + int oidx1 = idx5 + idx3; + int iidx1 = idx4 + idx3; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + + out[oidx1 - 1] = w1r * i1i + w1i * i1r; + out[oidx1] = w1r * i1r - w1i * i1i; + } + } + } + } else { + is = -ido; + for (int j = 1; j < ip; j++) { + is += ido; + int idx1 = j * l1 * ido; + for (int k = 0; k < l1; k++) { + idij = is - 1; + int idx3 = k * ido + idx1; + for (int i = 2; i < ido; i += 2) { + idij += 2; + int idx2 = idij + iw1; + w1r = wtable_r[idx2 - 1]; + w1i = wtable_r[idx2]; + int oidx1 = out_off + i + idx3; + int iidx1 = in_off + i + idx3; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + + out[oidx1 - 1] = w1r * i1i + w1i * i1r; + out[oidx1] = w1r * i1r - w1i * i1i; + } + } + } + } + if (nbd >= l1) { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido + idx1; + int idx4 = k * ido + idx2; + for (int i = 2; i < ido; i += 2) { + int idx5 = in_off + i; + int idx6 = out_off + i; + int iidx1 = idx5 + idx3; + int iidx2 = idx5 + idx4; + int oidx1 = idx6 + idx3; + int oidx2 = idx6 + idx4; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + float o2i = out[oidx2 - 1]; + float o2r = out[oidx2]; + + in[iidx1 - 1] = o1i + o2i; + in[iidx1] = o1r + o2r; + + in[iidx2 - 1] = o1r - o2r; + in[iidx2] = o2i - o1i; + } + } + } + } else { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int i = 2; i < ido; i += 2) { + int idx5 = in_off + i; + int idx6 = out_off + i; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido + idx1; + int idx4 = k * ido + idx2; + int iidx1 = idx5 + idx3; + int iidx2 = idx5 + idx4; + int oidx1 = idx6 + idx3; + int oidx2 = idx6 + idx4; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + float o2i = out[oidx2 - 1]; + float o2r = out[oidx2]; + + in[iidx1 - 1] = o1i + o2i; + in[iidx1] = o1r + o2r; + in[iidx2 - 1] = o1r - o2r; + in[iidx2] = o2i - o1i; + } + } + } + } + } else { + System.arraycopy(out, out_off, in, in_off, idl1); + } + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido + idx1; + int idx4 = k * ido + idx2; + int oidx1 = out_off + idx3; + int oidx2 = out_off + idx4; + float o1r = out[oidx1]; + float o2r = out[oidx2]; + + in[in_off + idx3] = o1r + o2r; + in[in_off + idx4] = o2r - o1r; + } + } + + ar1 = 1; + ai1 = 0; + int idx0 = (ip - 1) * idl1; + for (int l = 1; l < ipph; l++) { + lc = ip - l; + ar1h = dcp * ar1 - dsp * ai1; + ai1 = dcp * ai1 + dsp * ar1; + ar1 = ar1h; + int idx1 = l * idl1; + int idx2 = lc * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx3 = out_off + ik; + int idx4 = in_off + ik; + out[idx3 + idx1] = in[idx4] + ar1 * in[idx4 + idl1]; + out[idx3 + idx2] = ai1 * in[idx4 + idx0]; + } + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + for (int j = 2; j < ipph; j++) { + jc = ip - j; + ar2h = dc2 * ar2 - ds2 * ai2; + ai2 = dc2 * ai2 + ds2 * ar2; + ar2 = ar2h; + int idx3 = j * idl1; + int idx4 = jc * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx5 = out_off + ik; + int idx6 = in_off + ik; + out[idx5 + idx1] += ar2 * in[idx6 + idx3]; + out[idx5 + idx2] += ai2 * in[idx6 + idx4]; + } + } + } + for (int j = 1; j < ipph; j++) { + int idx1 = j * idl1; + for (int ik = 0; ik < idl1; ik++) { + out[out_off + ik] += in[in_off + ik + idx1]; + } + } + + if (ido >= l1) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = idx1 * ip; + for (int i = 0; i < ido; i++) { + in[in_off + i + idx2] = out[out_off + i + idx1]; + } + } + } else { + for (int i = 0; i < ido; i++) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + in[in_off + i + idx1 * ip] = out[out_off + i + idx1]; + } + } + } + int idx01 = ip * ido; + for (int j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = j2 * ido; + for (int k = 0; k < l1; k++) { + int idx4 = k * ido; + int idx5 = idx4 + idx1; + int idx6 = idx4 + idx2; + int idx7 = k * idx01; + in[in_off + ido - 1 + idx3 - ido + idx7] = out[out_off + idx5]; + in[in_off + idx3 + idx7] = out[out_off + idx6]; + } + } + if (ido == 1) { + return; + } + if (nbd >= l1) { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = j2 * ido; + for (int k = 0; k < l1; k++) { + int idx4 = k * idx01; + int idx5 = k * ido; + for (int i = 2; i < ido; i += 2) { + ic = ido - i; + int idx6 = in_off + i; + int idx7 = in_off + ic; + int idx8 = out_off + i; + int iidx1 = idx6 + idx3 + idx4; + int iidx2 = idx7 + idx3 - ido + idx4; + int oidx1 = idx8 + idx5 + idx1; + int oidx2 = idx8 + idx5 + idx2; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + float o2i = out[oidx2 - 1]; + float o2r = out[oidx2]; + + in[iidx1 - 1] = o1i + o2i; + in[iidx2 - 1] = o1i - o2i; + in[iidx1] = o1r + o2r; + in[iidx2] = o2r - o1r; + } + } + } + } else { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = j2 * ido; + for (int i = 2; i < ido; i += 2) { + ic = ido - i; + int idx6 = in_off + i; + int idx7 = in_off + ic; + int idx8 = out_off + i; + for (int k = 0; k < l1; k++) { + int idx4 = k * idx01; + int idx5 = k * ido; + int iidx1 = idx6 + idx3 + idx4; + int iidx2 = idx7 + idx3 - ido + idx4; + int oidx1 = idx8 + idx5 + idx1; + int oidx2 = idx8 + idx5 + idx2; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + float o2i = out[oidx2 - 1]; + float o2r = out[oidx2]; + + in[iidx1 - 1] = o1i + o2i; + in[iidx2 - 1] = o1i - o2i; + in[iidx1] = o1r + o2r; + in[iidx2] = o2r - o1r; + } + } + } + } + } + + /*--------------------------------------------------------- + radfg: Real FFT's forward processing of general factor + --------------------------------------------------------*/ +/* + void radfg(final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + long idij, ipph, j2, ic, jc, lc, is, nbd; + float dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; + long iw1 = offset; + + arg = TWO_PI / (float) ip; + dcp = (float)Math.cos(arg); + dsp = (float)Math.sin(arg); + ipph = (ip + 1) / 2; + nbd = (ido - 1) / 2; + if (ido != 1) { + for (long ik = 0; ik < idl1; ik++) { + out.setFloat(out_off + ik, in.getFloat(in_off + ik)); + } + for (long j = 1; j < ip; j++) { + long idx1 = j * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx2 = k * ido + idx1; + out.setFloat(out_off + idx2, in.getFloat(in_off + idx2)); + } + } + if (nbd <= l1) { + is = -ido; + for (long j = 1; j < ip; j++) { + is += ido; + idij = is - 1; + long idx1 = j * l1 * ido; + for (long i = 2; i < ido; i += 2) { + idij += 2; + long idx2 = idij + iw1; + long idx4 = in_off + i; + long idx5 = out_off + i; + w1r = wtable_rl.getFloat(idx2 - 1); + w1i = wtable_rl.getFloat(idx2); + for (long k = 0; k < l1; k++) { + long idx3 = k * ido + idx1; + long oidx1 = idx5 + idx3; + long iidx1 = idx4 + idx3; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + + out.setFloat(oidx1 - 1, w1r * i1i + w1i * i1r); + out.setFloat(oidx1, w1r * i1r - w1i * i1i); + } + } + } + } else { + is = -ido; + for (long j = 1; j < ip; j++) { + is += ido; + long idx1 = j * l1 * ido; + for (long k = 0; k < l1; k++) { + idij = is - 1; + long idx3 = k * ido + idx1; + for (long i = 2; i < ido; i += 2) { + idij += 2; + long idx2 = idij + iw1; + w1r = wtable_rl.getFloat(idx2 - 1); + w1i = wtable_rl.getFloat(idx2); + long oidx1 = out_off + i + idx3; + long iidx1 = in_off + i + idx3; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + + out.setFloat(oidx1 - 1, w1r * i1i + w1i * i1r); + out.setFloat(oidx1, w1r * i1r - w1i * i1i); + } + } + } + } + if (nbd >= l1) { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido + idx1; + long idx4 = k * ido + idx2; + for (long i = 2; i < ido; i += 2) { + long idx5 = in_off + i; + long idx6 = out_off + i; + long iidx1 = idx5 + idx3; + long iidx2 = idx5 + idx4; + long oidx1 = idx6 + idx3; + long oidx2 = idx6 + idx4; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + float o2i = out.getFloat(oidx2 - 1); + float o2r = out.getFloat(oidx2); + + in.setFloat(iidx1 - 1, o1i + o2i); + in.setFloat(iidx1, o1r + o2r); + + in.setFloat(iidx2 - 1, o1r - o2r); + in.setFloat(iidx2, o2i - o1i); + } + } + } + } else { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long i = 2; i < ido; i += 2) { + long idx5 = in_off + i; + long idx6 = out_off + i; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido + idx1; + long idx4 = k * ido + idx2; + long iidx1 = idx5 + idx3; + long iidx2 = idx5 + idx4; + long oidx1 = idx6 + idx3; + long oidx2 = idx6 + idx4; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + float o2i = out.getFloat(oidx2 - 1); + float o2r = out.getFloat(oidx2); + + in.setFloat(iidx1 - 1, o1i + o2i); + in.setFloat(iidx1, o1r + o2r); + in.setFloat(iidx2 - 1, o1r - o2r); + in.setFloat(iidx2, o2i - o1i); + } + } + } + } + } else { + Utilities.arraycopy(out, out_off, in, in_off, idl1); + } + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido + idx1; + long idx4 = k * ido + idx2; + long oidx1 = out_off + idx3; + long oidx2 = out_off + idx4; + float o1r = out.getFloat(oidx1); + float o2r = out.getFloat(oidx2); + + in.setFloat(in_off + idx3, o1r + o2r); + in.setFloat(in_off + idx4, o2r - o1r); + } + } + + ar1 = 1; + ai1 = 0; + long idx0 = (ip - 1) * idl1; + for (long l = 1; l < ipph; l++) { + lc = ip - l; + ar1h = dcp * ar1 - dsp * ai1; + ai1 = dcp * ai1 + dsp * ar1; + ar1 = ar1h; + long idx1 = l * idl1; + long idx2 = lc * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx3 = out_off + ik; + long idx4 = in_off + ik; + out.setFloat(idx3 + idx1, in.getFloat(idx4) + ar1 * in.getFloat(idx4 + idl1)); + out.setFloat(idx3 + idx2, ai1 * in.getFloat(idx4 + idx0)); + } + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + for (long j = 2; j < ipph; j++) { + jc = ip - j; + ar2h = dc2 * ar2 - ds2 * ai2; + ai2 = dc2 * ai2 + ds2 * ar2; + ar2 = ar2h; + long idx3 = j * idl1; + long idx4 = jc * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx5 = out_off + ik; + long idx6 = in_off + ik; + out.setFloat(idx5 + idx1, out.getFloat(idx5 + idx1) + ar2 * in.getFloat(idx6 + idx3)); + out.setFloat(idx5 + idx2, out.getFloat(idx5 + idx2) + ai2 * in.getFloat(idx6 + idx4)); + } + } + } + for (long j = 1; j < ipph; j++) { + long idx1 = j * idl1; + for (long ik = 0; ik < idl1; ik++) { + out.setFloat(out_off + ik, out.getFloat(out_off + ik) + in.getFloat(in_off + ik + idx1)); + } + } + + if (ido >= l1) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = idx1 * ip; + for (long i = 0; i < ido; i++) { + in.setFloat(in_off + i + idx2, out.getFloat(out_off + i + idx1)); + } + } + } else { + for (long i = 0; i < ido; i++) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + in.setFloat(in_off + i + idx1 * ip, out.getFloat(out_off + i + idx1)); + } + } + } + long idx01 = ip * ido; + for (long j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = j2 * ido; + for (long k = 0; k < l1; k++) { + long idx4 = k * ido; + long idx5 = idx4 + idx1; + long idx6 = idx4 + idx2; + long idx7 = k * idx01; + in.setFloat(in_off + ido - 1 + idx3 - ido + idx7, out.getFloat(out_off + idx5)); + in.setFloat(in_off + idx3 + idx7, out.getFloat(out_off + idx6)); + } + } + if (ido == 1) { + return; + } + if (nbd >= l1) { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = j2 * ido; + for (long k = 0; k < l1; k++) { + long idx4 = k * idx01; + long idx5 = k * ido; + for (long i = 2; i < ido; i += 2) { + ic = ido - i; + long idx6 = in_off + i; + long idx7 = in_off + ic; + long idx8 = out_off + i; + long iidx1 = idx6 + idx3 + idx4; + long iidx2 = idx7 + idx3 - ido + idx4; + long oidx1 = idx8 + idx5 + idx1; + long oidx2 = idx8 + idx5 + idx2; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + float o2i = out.getFloat(oidx2 - 1); + float o2r = out.getFloat(oidx2); + + in.setFloat(iidx1 - 1, o1i + o2i); + in.setFloat(iidx2 - 1, o1i - o2i); + in.setFloat(iidx1, o1r + o2r); + in.setFloat(iidx2, o2r - o1r); + } + } + } + } else { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = j2 * ido; + for (long i = 2; i < ido; i += 2) { + ic = ido - i; + long idx6 = in_off + i; + long idx7 = in_off + ic; + long idx8 = out_off + i; + for (long k = 0; k < l1; k++) { + long idx4 = k * idx01; + long idx5 = k * ido; + long iidx1 = idx6 + idx3 + idx4; + long iidx2 = idx7 + idx3 - ido + idx4; + long oidx1 = idx8 + idx5 + idx1; + long oidx2 = idx8 + idx5 + idx2; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + float o2i = out.getFloat(oidx2 - 1); + float o2r = out.getFloat(oidx2); + + in.setFloat(iidx1 - 1, o1i + o2i); + in.setFloat(iidx2 - 1, o1i - o2i); + in.setFloat(iidx1, o1r + o2r); + in.setFloat(iidx2, o2r - o1r); + } + } + } + } + } +*/ + /*--------------------------------------------------------- + radbg: Real FFT's backward processing of general factor + --------------------------------------------------------*/ + void radbg(final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset) { + int idij, ipph, j2, ic, jc, lc, is; + float dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; + int nbd; + float dcp, arg, dsp, ar1h, ar2h; + int iw1 = offset; + + arg = TWO_PI / (float) ip; + dcp = (float)Math.cos(arg); + dsp = (float)Math.sin(arg); + nbd = (ido - 1) / 2; + ipph = (ip + 1) / 2; + int idx0 = ip * ido; + if (ido >= l1) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = k * idx0; + for (int i = 0; i < ido; i++) { + out[out_off + i + idx1] = in[in_off + i + idx2]; + } + } + } else { + for (int i = 0; i < ido; i++) { + int idx1 = out_off + i; + int idx2 = in_off + i; + for (int k = 0; k < l1; k++) { + out[idx1 + k * ido] = in[idx2 + k * idx0]; + } + } + } + int iidx0 = in_off + ido - 1; + for (int j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = j2 * ido; + for (int k = 0; k < l1; k++) { + int idx4 = k * ido; + int idx5 = idx4 * ip; + int iidx1 = iidx0 + idx3 + idx5 - ido; + int iidx2 = in_off + idx3 + idx5; + float i1r = in[iidx1]; + float i2r = in[iidx2]; + + out[out_off + idx4 + idx1] = i1r + i1r; + out[out_off + idx4 + idx2] = i2r + i2r; + } + } + + if (ido != 1) { + if (nbd >= l1) { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = 2 * j * ido; + for (int k = 0; k < l1; k++) { + int idx4 = k * ido + idx1; + int idx5 = k * ido + idx2; + int idx6 = k * ip * ido + idx3; + for (int i = 2; i < ido; i += 2) { + ic = ido - i; + int idx7 = out_off + i; + int idx8 = in_off + ic; + int idx9 = in_off + i; + int oidx1 = idx7 + idx4; + int oidx2 = idx7 + idx5; + int iidx1 = idx9 + idx6; + int iidx2 = idx8 + idx6 - ido; + float a1i = in[iidx1 - 1]; + float a1r = in[iidx1]; + float a2i = in[iidx2 - 1]; + float a2r = in[iidx2]; + + out[oidx1 - 1] = a1i + a2i; + out[oidx2 - 1] = a1i - a2i; + out[oidx1] = a1r - a2r; + out[oidx2] = a1r + a2r; + } + } + } + } else { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + int idx3 = 2 * j * ido; + for (int i = 2; i < ido; i += 2) { + ic = ido - i; + int idx7 = out_off + i; + int idx8 = in_off + ic; + int idx9 = in_off + i; + for (int k = 0; k < l1; k++) { + int idx4 = k * ido + idx1; + int idx5 = k * ido + idx2; + int idx6 = k * ip * ido + idx3; + int oidx1 = idx7 + idx4; + int oidx2 = idx7 + idx5; + int iidx1 = idx9 + idx6; + int iidx2 = idx8 + idx6 - ido; + float a1i = in[iidx1 - 1]; + float a1r = in[iidx1]; + float a2i = in[iidx2 - 1]; + float a2r = in[iidx2]; + + out[oidx1 - 1] = a1i + a2i; + out[oidx2 - 1] = a1i - a2i; + out[oidx1] = a1r - a2r; + out[oidx2] = a1r + a2r; + } + } + } + } + } + + ar1 = 1; + ai1 = 0; + int idx01 = (ip - 1) * idl1; + for (int l = 1; l < ipph; l++) { + lc = ip - l; + ar1h = dcp * ar1 - dsp * ai1; + ai1 = dcp * ai1 + dsp * ar1; + ar1 = ar1h; + int idx1 = l * idl1; + int idx2 = lc * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx3 = in_off + ik; + int idx4 = out_off + ik; + in[idx3 + idx1] = out[idx4] + ar1 * out[idx4 + idl1]; + in[idx3 + idx2] = ai1 * out[idx4 + idx01]; + } + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + for (int j = 2; j < ipph; j++) { + jc = ip - j; + ar2h = dc2 * ar2 - ds2 * ai2; + ai2 = dc2 * ai2 + ds2 * ar2; + ar2 = ar2h; + int idx5 = j * idl1; + int idx6 = jc * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx7 = in_off + ik; + int idx8 = out_off + ik; + in[idx7 + idx1] += ar2 * out[idx8 + idx5]; + in[idx7 + idx2] += ai2 * out[idx8 + idx6]; + } + } + } + for (int j = 1; j < ipph; j++) { + int idx1 = j * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx2 = out_off + ik; + out[idx2] += out[idx2 + idx1]; + } + } + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido; + int oidx1 = out_off + idx3; + int iidx1 = in_off + idx3 + idx1; + int iidx2 = in_off + idx3 + idx2; + float i1r = in[iidx1]; + float i2r = in[iidx2]; + + out[oidx1 + idx1] = i1r - i2r; + out[oidx1 + idx2] = i1r + i2r; + } + } + + if (ido == 1) { + return; + } + if (nbd >= l1) { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido; + for (int i = 2; i < ido; i += 2) { + int idx4 = out_off + i; + int idx5 = in_off + i; + int oidx1 = idx4 + idx3 + idx1; + int oidx2 = idx4 + idx3 + idx2; + int iidx1 = idx5 + idx3 + idx1; + int iidx2 = idx5 + idx3 + idx2; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + + out[oidx1 - 1] = i1i - i2r; + out[oidx2 - 1] = i1i + i2r; + out[oidx1] = i1r + i2i; + out[oidx2] = i1r - i2i; + } + } + } + } else { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * l1 * ido; + int idx2 = jc * l1 * ido; + for (int i = 2; i < ido; i += 2) { + int idx4 = out_off + i; + int idx5 = in_off + i; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido; + int oidx1 = idx4 + idx3 + idx1; + int oidx2 = idx4 + idx3 + idx2; + int iidx1 = idx5 + idx3 + idx1; + int iidx2 = idx5 + idx3 + idx2; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + + out[oidx1 - 1] = i1i - i2r; + out[oidx2 - 1] = i1i + i2r; + out[oidx1] = i1r + i2i; + out[oidx2] = i1r - i2i; + } + } + } + } + System.arraycopy(out, out_off, in, in_off, idl1); + for (int j = 1; j < ip; j++) { + int idx1 = j * l1 * ido; + for (int k = 0; k < l1; k++) { + int idx2 = k * ido + idx1; + in[in_off + idx2] = out[out_off + idx2]; + } + } + if (nbd <= l1) { + is = -ido; + for (int j = 1; j < ip; j++) { + is += ido; + idij = is - 1; + int idx1 = j * l1 * ido; + for (int i = 2; i < ido; i += 2) { + idij += 2; + int idx2 = idij + iw1; + w1r = wtable_r[idx2 - 1]; + w1i = wtable_r[idx2]; + int idx4 = in_off + i; + int idx5 = out_off + i; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido + idx1; + int iidx1 = idx4 + idx3; + int oidx1 = idx5 + idx3; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + + in[iidx1 - 1] = w1r * o1i - w1i * o1r; + in[iidx1] = w1r * o1r + w1i * o1i; + } + } + } + } else { + is = -ido; + for (int j = 1; j < ip; j++) { + is += ido; + int idx1 = j * l1 * ido; + for (int k = 0; k < l1; k++) { + idij = is - 1; + int idx3 = k * ido + idx1; + for (int i = 2; i < ido; i += 2) { + idij += 2; + int idx2 = idij + iw1; + w1r = wtable_r[idx2 - 1]; + w1i = wtable_r[idx2]; + int idx4 = in_off + i; + int idx5 = out_off + i; + int iidx1 = idx4 + idx3; + int oidx1 = idx5 + idx3; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + + in[iidx1 - 1] = w1r * o1i - w1i * o1r; + in[iidx1] = w1r * o1r + w1i * o1i; + + } + } + } + } + } + + /*--------------------------------------------------------- + radbg: Real FFT's backward processing of general factor + --------------------------------------------------------*/ +/* + void radbg(final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset) { + long idij, ipph, j2, ic, jc, lc, is; + float dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; + long nbd; + float dcp, arg, dsp, ar1h, ar2h; + long iw1 = offset; + + arg = TWO_PI / (float) ip; + dcp = (float)Math.cos(arg); + dsp = (float)Math.sin(arg); + nbd = (ido - 1) / 2; + ipph = (ip + 1) / 2; + long idx0 = ip * ido; + if (ido >= l1) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = k * idx0; + for (long i = 0; i < ido; i++) { + out.setFloat(out_off + i + idx1, in.getFloat(in_off + i + idx2)); + } + } + } else { + for (long i = 0; i < ido; i++) { + long idx1 = out_off + i; + long idx2 = in_off + i; + for (long k = 0; k < l1; k++) { + out.setFloat(idx1 + k * ido, in.getFloat(idx2 + k * idx0)); + } + } + } + long iidx0 = in_off + ido - 1; + for (long j = 1; j < ipph; j++) { + jc = ip - j; + j2 = 2 * j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = j2 * ido; + for (long k = 0; k < l1; k++) { + long idx4 = k * ido; + long idx5 = idx4 * ip; + long iidx1 = iidx0 + idx3 + idx5 - ido; + long iidx2 = in_off + idx3 + idx5; + float i1r = in.getFloat(iidx1); + float i2r = in.getFloat(iidx2); + + out.setFloat(out_off + idx4 + idx1, i1r + i1r); + out.setFloat(out_off + idx4 + idx2, i2r + i2r); + } + } + + if (ido != 1) { + if (nbd >= l1) { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = 2 * j * ido; + for (long k = 0; k < l1; k++) { + long idx4 = k * ido + idx1; + long idx5 = k * ido + idx2; + long idx6 = k * ip * ido + idx3; + for (long i = 2; i < ido; i += 2) { + ic = ido - i; + long idx7 = out_off + i; + long idx8 = in_off + ic; + long idx9 = in_off + i; + long oidx1 = idx7 + idx4; + long oidx2 = idx7 + idx5; + long iidx1 = idx9 + idx6; + long iidx2 = idx8 + idx6 - ido; + float a1i = in.getFloat(iidx1 - 1); + float a1r = in.getFloat(iidx1); + float a2i = in.getFloat(iidx2 - 1); + float a2r = in.getFloat(iidx2); + + out.setFloat(oidx1 - 1, a1i + a2i); + out.setFloat(oidx2 - 1, a1i - a2i); + out.setFloat(oidx1, a1r - a2r); + out.setFloat(oidx2, a1r + a2r); + } + } + } + } else { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + long idx3 = 2 * j * ido; + for (long i = 2; i < ido; i += 2) { + ic = ido - i; + long idx7 = out_off + i; + long idx8 = in_off + ic; + long idx9 = in_off + i; + for (long k = 0; k < l1; k++) { + long idx4 = k * ido + idx1; + long idx5 = k * ido + idx2; + long idx6 = k * ip * ido + idx3; + long oidx1 = idx7 + idx4; + long oidx2 = idx7 + idx5; + long iidx1 = idx9 + idx6; + long iidx2 = idx8 + idx6 - ido; + float a1i = in.getFloat(iidx1 - 1); + float a1r = in.getFloat(iidx1); + float a2i = in.getFloat(iidx2 - 1); + float a2r = in.getFloat(iidx2); + + out.setFloat(oidx1 - 1, a1i + a2i); + out.setFloat(oidx2 - 1, a1i - a2i); + out.setFloat(oidx1, a1r - a2r); + out.setFloat(oidx2, a1r + a2r); + } + } + } + } + } + + ar1 = 1; + ai1 = 0; + long idx01 = (ip - 1) * idl1; + for (long l = 1; l < ipph; l++) { + lc = ip - l; + ar1h = dcp * ar1 - dsp * ai1; + ai1 = dcp * ai1 + dsp * ar1; + ar1 = ar1h; + long idx1 = l * idl1; + long idx2 = lc * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx3 = in_off + ik; + long idx4 = out_off + ik; + in.setFloat(idx3 + idx1, out.getFloat(idx4) + ar1 * out.getFloat(idx4 + idl1)); + in.setFloat(idx3 + idx2, ai1 * out.getFloat(idx4 + idx01)); + } + dc2 = ar1; + ds2 = ai1; + ar2 = ar1; + ai2 = ai1; + for (long j = 2; j < ipph; j++) { + jc = ip - j; + ar2h = dc2 * ar2 - ds2 * ai2; + ai2 = dc2 * ai2 + ds2 * ar2; + ar2 = ar2h; + long idx5 = j * idl1; + long idx6 = jc * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx7 = in_off + ik; + long idx8 = out_off + ik; + in.setFloat(idx7 + idx1, in.getFloat(idx7 + idx1) + ar2 * out.getFloat(idx8 + idx5)); + in.setFloat(idx7 + idx2, in.getFloat(idx7 + idx2) + ai2 * out.getFloat(idx8 + idx6)); + } + } + } + for (long j = 1; j < ipph; j++) { + long idx1 = j * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx2 = out_off + ik; + out.setFloat(idx2, out.getFloat(idx2) + out.getFloat(idx2 + idx1)); + } + } + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido; + long oidx1 = out_off + idx3; + long iidx1 = in_off + idx3 + idx1; + long iidx2 = in_off + idx3 + idx2; + float i1r = in.getFloat(iidx1); + float i2r = in.getFloat(iidx2); + + out.setFloat(oidx1 + idx1, i1r - i2r); + out.setFloat(oidx1 + idx2, i1r + i2r); + } + } + + if (ido == 1) { + return; + } + if (nbd >= l1) { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido; + for (long i = 2; i < ido; i += 2) { + long idx4 = out_off + i; + long idx5 = in_off + i; + long oidx1 = idx4 + idx3 + idx1; + long oidx2 = idx4 + idx3 + idx2; + long iidx1 = idx5 + idx3 + idx1; + long iidx2 = idx5 + idx3 + idx2; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + + out.setFloat(oidx1 - 1, i1i - i2r); + out.setFloat(oidx2 - 1, i1i + i2r); + out.setFloat(oidx1, i1r + i2i); + out.setFloat(oidx2, i1r - i2i); + } + } + } + } else { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * l1 * ido; + long idx2 = jc * l1 * ido; + for (long i = 2; i < ido; i += 2) { + long idx4 = out_off + i; + long idx5 = in_off + i; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido; + long oidx1 = idx4 + idx3 + idx1; + long oidx2 = idx4 + idx3 + idx2; + long iidx1 = idx5 + idx3 + idx1; + long iidx2 = idx5 + idx3 + idx2; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + + out.setFloat(oidx1 - 1, i1i - i2r); + out.setFloat(oidx2 - 1, i1i + i2r); + out.setFloat(oidx1, i1r + i2i); + out.setFloat(oidx2, i1r - i2i); + } + } + } + } + Utilities.arraycopy(out, out_off, in, in_off, idl1); + for (long j = 1; j < ip; j++) { + long idx1 = j * l1 * ido; + for (long k = 0; k < l1; k++) { + long idx2 = k * ido + idx1; + in.setFloat(in_off + idx2, out.getFloat(out_off + idx2)); + } + } + if (nbd <= l1) { + is = -ido; + for (long j = 1; j < ip; j++) { + is += ido; + idij = is - 1; + long idx1 = j * l1 * ido; + for (long i = 2; i < ido; i += 2) { + idij += 2; + long idx2 = idij + iw1; + w1r = wtable_rl.getFloat(idx2 - 1); + w1i = wtable_rl.getFloat(idx2); + long idx4 = in_off + i; + long idx5 = out_off + i; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido + idx1; + long iidx1 = idx4 + idx3; + long oidx1 = idx5 + idx3; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + + in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); + in.setFloat(iidx1, w1r * o1r + w1i * o1i); + } + } + } + } else { + is = -ido; + for (long j = 1; j < ip; j++) { + is += ido; + long idx1 = j * l1 * ido; + for (long k = 0; k < l1; k++) { + idij = is - 1; + long idx3 = k * ido + idx1; + for (long i = 2; i < ido; i += 2) { + idij += 2; + long idx2 = idij + iw1; + w1r = wtable_rl.getFloat(idx2 - 1); + w1i = wtable_rl.getFloat(idx2); + long idx4 = in_off + i; + long idx5 = out_off + i; + long iidx1 = idx4 + idx3; + long oidx1 = idx5 + idx3; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + + in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); + in.setFloat(iidx1, w1r * o1r + w1i * o1i); + + } + } + } + } + } +*/ + /*--------------------------------------------------------- + cfftf1: further processing of Complex forward FFT + --------------------------------------------------------*/ + void cfftf(float a[], int offa, int isign) { + int idot; + int l1, l2; + int na, nf, ipll, iw, ido, idl1; + int[] nac = new int[1]; + final int twon = 2 * n; + + int iw1, iw2; + float[] ch = new float[twon]; + + iw1 = twon; + iw2 = 4 * n; + nac[0] = 0; + nf = (int) wtable[1 + iw2]; + na = 0; + l1 = 1; + iw = iw1; + for (int k1 = 2; k1 <= nf + 1; k1++) { + ipll = (int) wtable[k1 + iw2]; + l2 = ipll * l1; + ido = n / l2; + idot = ido + ido; + idl1 = idot * l1; + switch (ipll) { + case 4: + if (na == 0) { + passf4(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf4(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 2: + if (na == 0) { + passf2(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf2(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 3: + if (na == 0) { + passf3(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf3(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 5: + if (na == 0) { + passf5(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf5(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + default: + if (na == 0) { + passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); + } else { + passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); + } + if (nac[0] != 0) { + na = 1 - na; + } + break; + } + l1 = l2; + iw += (ipll - 1) * idot; + } + if (na == 0) { + return; + } + System.arraycopy(ch, 0, a, offa, twon); + + } + + /*--------------------------------------------------------- + cfftf1: further processing of Complex forward FFT + --------------------------------------------------------*/ +/* + void cfftf(FloatLargeArray a, long offa, int isign) { + long idot; + long l1, l2; + long na, nf, iw, ido, idl1; + int[] nac = new int[1]; + final long twon = 2 * nl; + int ipll; + + long iw1, iw2; + FloatLargeArray ch = new FloatLargeArray(twon, false); + + iw1 = twon; + iw2 = 4 * nl; + nac[0] = 0; + nf = (long) wtablel.getFloat(1 + iw2); + na = 0; + l1 = 1; + iw = iw1; + for (long k1 = 2; k1 <= nf + 1; k1++) { + ipll = (int) wtablel.getFloat(k1 + iw2); + l2 = ipll * l1; + ido = nl / l2; + idot = ido + ido; + idl1 = idot * l1; + switch (ipll) { + case 4: + if (na == 0) { + passf4(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf4(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 2: + if (na == 0) { + passf2(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf2(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 3: + if (na == 0) { + passf3(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf3(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + case 5: + if (na == 0) { + passf5(idot, l1, a, offa, ch, 0, iw, isign); + } else { + passf5(idot, l1, ch, 0, a, offa, iw, isign); + } + na = 1 - na; + break; + default: + if (na == 0) { + passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); + } else { + passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); + } + if (nac[0] != 0) { + na = 1 - na; + } + break; + } + l1 = l2; + iw += (ipll - 1) * idot; + } + if (na == 0) { + return; + } + Utilities.arraycopy(ch, 0, a, offa, twon); + + } +*/ + /*---------------------------------------------------------------------- + passf2: Complex FFT's forward/backward processing of factor 2; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ + void passf2(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { + float t1i, t1r; + int iw1; + iw1 = offset; + int idx = ido * l1; + if (ido <= 2) { + for (int k = 0; k < l1; k++) { + int idx0 = k * ido; + int iidx1 = in_off + 2 * idx0; + int iidx2 = iidx1 + ido; + float a1r = in[iidx1]; + float a1i = in[iidx1 + 1]; + float a2r = in[iidx2]; + float a2i = in[iidx2 + 1]; + + int oidx1 = out_off + idx0; + int oidx2 = oidx1 + idx; + out[oidx1] = a1r + a2r; + out[oidx1 + 1] = a1i + a2i; + out[oidx2] = a1r - a2r; + out[oidx2 + 1] = a1i - a2i; + } + } else { + for (int k = 0; k < l1; k++) { + for (int i = 0; i < ido - 1; i += 2) { + int idx0 = k * ido; + int iidx1 = in_off + i + 2 * idx0; + int iidx2 = iidx1 + ido; + float i1r = in[iidx1]; + float i1i = in[iidx1 + 1]; + float i2r = in[iidx2]; + float i2i = in[iidx2 + 1]; + + int widx1 = i + iw1; + float w1r = wtable[widx1]; + float w1i = isign * wtable[widx1 + 1]; + + t1r = i1r - i2r; + t1i = i1i - i2i; + + int oidx1 = out_off + i + idx0; + int oidx2 = oidx1 + idx; + out[oidx1] = i1r + i2r; + out[oidx1 + 1] = i1i + i2i; + out[oidx2] = w1r * t1r - w1i * t1i; + out[oidx2 + 1] = w1r * t1i + w1i * t1r; + } + } + } + } + + /*---------------------------------------------------------------------- + passf2: Complex FFT's forward/backward processing of factor 2; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ +/* + void passf2(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { + float t1i, t1r; + long iw1; + iw1 = offset; + long idx = ido * l1; + if (ido <= 2) { + for (long k = 0; k < l1; k++) { + long idx0 = k * ido; + long iidx1 = in_off + 2 * idx0; + long iidx2 = iidx1 + ido; + float a1r = in.getFloat(iidx1); + float a1i = in.getFloat(iidx1 + 1); + float a2r = in.getFloat(iidx2); + float a2i = in.getFloat(iidx2 + 1); + + long oidx1 = out_off + idx0; + long oidx2 = oidx1 + idx; + out.setFloat(oidx1, a1r + a2r); + out.setFloat(oidx1 + 1, a1i + a2i); + out.setFloat(oidx2, a1r - a2r); + out.setFloat(oidx2 + 1, a1i - a2i); + } + } else { + for (long k = 0; k < l1; k++) { + for (long i = 0; i < ido - 1; i += 2) { + long idx0 = k * ido; + long iidx1 = in_off + i + 2 * idx0; + long iidx2 = iidx1 + ido; + float i1r = in.getFloat(iidx1); + float i1i = in.getFloat(iidx1 + 1); + float i2r = in.getFloat(iidx2); + float i2i = in.getFloat(iidx2 + 1); + + long widx1 = i + iw1; + float w1r = wtablel.getFloat(widx1); + float w1i = isign * wtablel.getFloat(widx1 + 1); + + t1r = i1r - i2r; + t1i = i1i - i2i; + + long oidx1 = out_off + i + idx0; + long oidx2 = oidx1 + idx; + out.setFloat(oidx1, i1r + i2r); + out.setFloat(oidx1 + 1, i1i + i2i); + out.setFloat(oidx2, w1r * t1r - w1i * t1i); + out.setFloat(oidx2 + 1, w1r * t1i + w1i * t1r); + } + } + } + } +*/ + /*---------------------------------------------------------------------- + passf3: Complex FFT's forward/backward processing of factor 3; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ + void passf3(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; + int iw1, iw2; + + iw1 = offset; + iw2 = iw1 + ido; + + final int idxt = l1 * ido; + + if (ido == 2) { + for (int k = 1; k <= l1; k++) { + int iidx1 = in_off + (3 * k - 2) * ido; + int iidx2 = iidx1 + ido; + int iidx3 = iidx1 - ido; + float i1r = in[iidx1]; + float i1i = in[iidx1 + 1]; + float i2r = in[iidx2]; + float i2i = in[iidx2 + 1]; + float i3r = in[iidx3]; + float i3i = in[iidx3 + 1]; + + tr2 = i1r + i2r; + cr2 = i3r + taur * tr2; + ti2 = i1i + i2i; + ci2 = i3i + taur * ti2; + cr3 = isign * taui * (i1r - i2r); + ci3 = isign * taui * (i1i - i2i); + + int oidx1 = out_off + (k - 1) * ido; + int oidx2 = oidx1 + idxt; + int oidx3 = oidx2 + idxt; + out[oidx1] = in[iidx3] + tr2; + out[oidx1 + 1] = i3i + ti2; + out[oidx2] = cr2 - ci3; + out[oidx2 + 1] = ci2 + cr3; + out[oidx3] = cr2 + ci3; + out[oidx3 + 1] = ci2 - cr3; + } + } else { + for (int k = 1; k <= l1; k++) { + int idx1 = in_off + (3 * k - 2) * ido; + int idx2 = out_off + (k - 1) * ido; + for (int i = 0; i < ido - 1; i += 2) { + int iidx1 = i + idx1; + int iidx2 = iidx1 + ido; + int iidx3 = iidx1 - ido; + float a1r = in[iidx1]; + float a1i = in[iidx1 + 1]; + float a2r = in[iidx2]; + float a2i = in[iidx2 + 1]; + float a3r = in[iidx3]; + float a3i = in[iidx3 + 1]; + + tr2 = a1r + a2r; + cr2 = a3r + taur * tr2; + ti2 = a1i + a2i; + ci2 = a3i + taur * ti2; + cr3 = isign * taui * (a1r - a2r); + ci3 = isign * taui * (a1i - a2i); + dr2 = cr2 - ci3; + dr3 = cr2 + ci3; + di2 = ci2 + cr3; + di3 = ci2 - cr3; + + int widx1 = i + iw1; + int widx2 = i + iw2; + float w1r = wtable[widx1]; + float w1i = isign * wtable[widx1 + 1]; + float w2r = wtable[widx2]; + float w2i = isign * wtable[widx2 + 1]; + + int oidx1 = i + idx2; + int oidx2 = oidx1 + idxt; + int oidx3 = oidx2 + idxt; + out[oidx1] = a3r + tr2; + out[oidx1 + 1] = a3i + ti2; + out[oidx2] = w1r * dr2 - w1i * di2; + out[oidx2 + 1] = w1r * di2 + w1i * dr2; + out[oidx3] = w2r * dr3 - w2i * di3; + out[oidx3 + 1] = w2r * di3 + w2i * dr3; + } + } + } + } + + /*---------------------------------------------------------------------- + passf3: Complex FFT's forward/backward processing of factor 3; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ +/* + void passf3(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { + final float taur = -0.5f; + final float taui = 0.866025403784438707610604524234076962f; + float ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; + long iw1, iw2; + + iw1 = offset; + iw2 = iw1 + ido; + + final long idxt = l1 * ido; + + if (ido == 2) { + for (long k = 1; k <= l1; k++) { + long iidx1 = in_off + (3 * k - 2) * ido; + long iidx2 = iidx1 + ido; + long iidx3 = iidx1 - ido; + float i1r = in.getFloat(iidx1); + float i1i = in.getFloat(iidx1 + 1); + float i2r = in.getFloat(iidx2); + float i2i = in.getFloat(iidx2 + 1); + float i3r = in.getFloat(iidx3); + float i3i = in.getFloat(iidx3 + 1); + + tr2 = i1r + i2r; + cr2 = i3r + taur * tr2; + ti2 = i1i + i2i; + ci2 = i3i + taur * ti2; + cr3 = isign * taui * (i1r - i2r); + ci3 = isign * taui * (i1i - i2i); + + long oidx1 = out_off + (k - 1) * ido; + long oidx2 = oidx1 + idxt; + long oidx3 = oidx2 + idxt; + out.setFloat(oidx1, in.getFloat(iidx3) + tr2); + out.setFloat(oidx1 + 1, i3i + ti2); + out.setFloat(oidx2, cr2 - ci3); + out.setFloat(oidx2 + 1, ci2 + cr3); + out.setFloat(oidx3, cr2 + ci3); + out.setFloat(oidx3 + 1, ci2 - cr3); + } + } else { + for (long k = 1; k <= l1; k++) { + long idx1 = in_off + (3 * k - 2) * ido; + long idx2 = out_off + (k - 1) * ido; + for (long i = 0; i < ido - 1; i += 2) { + long iidx1 = i + idx1; + long iidx2 = iidx1 + ido; + long iidx3 = iidx1 - ido; + float a1r = in.getFloat(iidx1); + float a1i = in.getFloat(iidx1 + 1); + float a2r = in.getFloat(iidx2); + float a2i = in.getFloat(iidx2 + 1); + float a3r = in.getFloat(iidx3); + float a3i = in.getFloat(iidx3 + 1); + + tr2 = a1r + a2r; + cr2 = a3r + taur * tr2; + ti2 = a1i + a2i; + ci2 = a3i + taur * ti2; + cr3 = isign * taui * (a1r - a2r); + ci3 = isign * taui * (a1i - a2i); + dr2 = cr2 - ci3; + dr3 = cr2 + ci3; + di2 = ci2 + cr3; + di3 = ci2 - cr3; + + long widx1 = i + iw1; + long widx2 = i + iw2; + float w1r = wtablel.getFloat(widx1); + float w1i = isign * wtablel.getFloat(widx1 + 1); + float w2r = wtablel.getFloat(widx2); + float w2i = isign * wtablel.getFloat(widx2 + 1); + + long oidx1 = i + idx2; + long oidx2 = oidx1 + idxt; + long oidx3 = oidx2 + idxt; + out.setFloat(oidx1, a3r + tr2); + out.setFloat(oidx1 + 1, a3i + ti2); + out.setFloat(oidx2, w1r * dr2 - w1i * di2); + out.setFloat(oidx2 + 1, w1r * di2 + w1i * dr2); + out.setFloat(oidx3, w2r * dr3 - w2i * di3); + out.setFloat(oidx3 + 1, w2r * di3 + w2i * dr3); + } + } + } + } +*/ + /*---------------------------------------------------------------------- + passf4: Complex FFT's forward/backward processing of factor 4; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ + void passf4(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { + float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; + int iw1, iw2, iw3; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + + int idx0 = l1 * ido; + if (ido == 2) { + for (int k = 0; k < l1; k++) { + int idxt1 = k * ido; + int iidx1 = in_off + 4 * idxt1 + 1; + int iidx2 = iidx1 + ido; + int iidx3 = iidx2 + ido; + int iidx4 = iidx3 + ido; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + + ti1 = i1r - i3r; + ti2 = i1r + i3r; + tr4 = i4r - i2r; + ti3 = i2r + i4r; + tr1 = i1i - i3i; + tr2 = i1i + i3i; + ti4 = i2i - i4i; + tr3 = i2i + i4i; + + int oidx1 = out_off + idxt1; + int oidx2 = oidx1 + idx0; + int oidx3 = oidx2 + idx0; + int oidx4 = oidx3 + idx0; + out[oidx1] = tr2 + tr3; + out[oidx1 + 1] = ti2 + ti3; + out[oidx2] = tr1 + isign * tr4; + out[oidx2 + 1] = ti1 + isign * ti4; + out[oidx3] = tr2 - tr3; + out[oidx3 + 1] = ti2 - ti3; + out[oidx4] = tr1 - isign * tr4; + out[oidx4 + 1] = ti1 - isign * ti4; + } + } else { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = in_off + 1 + 4 * idx1; + for (int i = 0; i < ido - 1; i += 2) { + int iidx1 = i + idx2; + int iidx2 = iidx1 + ido; + int iidx3 = iidx2 + ido; + int iidx4 = iidx3 + ido; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + + ti1 = i1r - i3r; + ti2 = i1r + i3r; + ti3 = i2r + i4r; + tr4 = i4r - i2r; + tr1 = i1i - i3i; + tr2 = i1i + i3i; + ti4 = i2i - i4i; + tr3 = i2i + i4i; + cr3 = tr2 - tr3; + ci3 = ti2 - ti3; + cr2 = tr1 + isign * tr4; + cr4 = tr1 - isign * tr4; + ci2 = ti1 + isign * ti4; + ci4 = ti1 - isign * ti4; + + int widx1 = i + iw1; + int widx2 = i + iw2; + int widx3 = i + iw3; + float w1r = wtable[widx1]; + float w1i = isign * wtable[widx1 + 1]; + float w2r = wtable[widx2]; + float w2i = isign * wtable[widx2 + 1]; + float w3r = wtable[widx3]; + float w3i = isign * wtable[widx3 + 1]; + + int oidx1 = out_off + i + idx1; + int oidx2 = oidx1 + idx0; + int oidx3 = oidx2 + idx0; + int oidx4 = oidx3 + idx0; + out[oidx1] = tr2 + tr3; + out[oidx1 + 1] = ti2 + ti3; + out[oidx2] = w1r * cr2 - w1i * ci2; + out[oidx2 + 1] = w1r * ci2 + w1i * cr2; + out[oidx3] = w2r * cr3 - w2i * ci3; + out[oidx3 + 1] = w2r * ci3 + w2i * cr3; + out[oidx4] = w3r * cr4 - w3i * ci4; + out[oidx4 + 1] = w3r * ci4 + w3i * cr4; + } + } + } + } + + /*---------------------------------------------------------------------- + passf4: Complex FFT's forward/backward processing of factor 4; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ +/* + void passf4(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final int isign) { + float ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; + long iw1, iw2, iw3; + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + + long idx0 = l1 * ido; + if (ido == 2) { + for (long k = 0; k < l1; k++) { + long idxt1 = k * ido; + long iidx1 = in_off + 4 * idxt1 + 1; + long iidx2 = iidx1 + ido; + long iidx3 = iidx2 + ido; + long iidx4 = iidx3 + ido; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + + ti1 = i1r - i3r; + ti2 = i1r + i3r; + tr4 = i4r - i2r; + ti3 = i2r + i4r; + tr1 = i1i - i3i; + tr2 = i1i + i3i; + ti4 = i2i - i4i; + tr3 = i2i + i4i; + + long oidx1 = out_off + idxt1; + long oidx2 = oidx1 + idx0; + long oidx3 = oidx2 + idx0; + long oidx4 = oidx3 + idx0; + out.setFloat(oidx1, tr2 + tr3); + out.setFloat(oidx1 + 1, ti2 + ti3); + out.setFloat(oidx2, tr1 + isign * tr4); + out.setFloat(oidx2 + 1, ti1 + isign * ti4); + out.setFloat(oidx3, tr2 - tr3); + out.setFloat(oidx3 + 1, ti2 - ti3); + out.setFloat(oidx4, tr1 - isign * tr4); + out.setFloat(oidx4 + 1, ti1 - isign * ti4); + } + } else { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = in_off + 1 + 4 * idx1; + for (long i = 0; i < ido - 1; i += 2) { + long iidx1 = i + idx2; + long iidx2 = iidx1 + ido; + long iidx3 = iidx2 + ido; + long iidx4 = iidx3 + ido; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + + ti1 = i1r - i3r; + ti2 = i1r + i3r; + ti3 = i2r + i4r; + tr4 = i4r - i2r; + tr1 = i1i - i3i; + tr2 = i1i + i3i; + ti4 = i2i - i4i; + tr3 = i2i + i4i; + cr3 = tr2 - tr3; + ci3 = ti2 - ti3; + cr2 = tr1 + isign * tr4; + cr4 = tr1 - isign * tr4; + ci2 = ti1 + isign * ti4; + ci4 = ti1 - isign * ti4; + + long widx1 = i + iw1; + long widx2 = i + iw2; + long widx3 = i + iw3; + float w1r = wtablel.getFloat(widx1); + float w1i = isign * wtablel.getFloat(widx1 + 1); + float w2r = wtablel.getFloat(widx2); + float w2i = isign * wtablel.getFloat(widx2 + 1); + float w3r = wtablel.getFloat(widx3); + float w3i = isign * wtablel.getFloat(widx3 + 1); + + long oidx1 = out_off + i + idx1; + long oidx2 = oidx1 + idx0; + long oidx3 = oidx2 + idx0; + long oidx4 = oidx3 + idx0; + out.setFloat(oidx1, tr2 + tr3); + out.setFloat(oidx1 + 1, ti2 + ti3); + out.setFloat(oidx2, w1r * cr2 - w1i * ci2); + out.setFloat(oidx2 + 1, w1r * ci2 + w1i * cr2); + out.setFloat(oidx3, w2r * cr3 - w2i * ci3); + out.setFloat(oidx3 + 1, w2r * ci3 + w2i * cr3); + out.setFloat(oidx4, w3r * cr4 - w3i * ci4); + out.setFloat(oidx4 + 1, w3r * ci4 + w3i * cr4); + } + } + } + } +*/ + /*---------------------------------------------------------------------- + passf5: Complex FFT's forward/backward processing of factor 5; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ + void passf5(final int ido, final int l1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) /* isign==-1 for forward transform and+1 for backward transform */ { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; + int iw1, iw2, iw3, iw4; + + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + int idx0 = l1 * ido; + + if (ido == 2) { + for (int k = 1; k <= l1; ++k) { + int iidx1 = in_off + (5 * k - 4) * ido + 1; + int iidx2 = iidx1 + ido; + int iidx3 = iidx1 - ido; + int iidx4 = iidx2 + ido; + int iidx5 = iidx4 + ido; + + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + float i5i = in[iidx5 - 1]; + float i5r = in[iidx5]; + + ti5 = i1r - i5r; + ti2 = i1r + i5r; + ti4 = i2r - i4r; + ti3 = i2r + i4r; + tr5 = i1i - i5i; + tr2 = i1i + i5i; + tr4 = i2i - i4i; + tr3 = i2i + i4i; + cr2 = i3i + tr11 * tr2 + tr12 * tr3; + ci2 = i3r + tr11 * ti2 + tr12 * ti3; + cr3 = i3i + tr12 * tr2 + tr11 * tr3; + ci3 = i3r + tr12 * ti2 + tr11 * ti3; + cr5 = isign * (ti11 * tr5 + ti12 * tr4); + ci5 = isign * (ti11 * ti5 + ti12 * ti4); + cr4 = isign * (ti12 * tr5 - ti11 * tr4); + ci4 = isign * (ti12 * ti5 - ti11 * ti4); + + int oidx1 = out_off + (k - 1) * ido; + int oidx2 = oidx1 + idx0; + int oidx3 = oidx2 + idx0; + int oidx4 = oidx3 + idx0; + int oidx5 = oidx4 + idx0; + out[oidx1] = i3i + tr2 + tr3; + out[oidx1 + 1] = i3r + ti2 + ti3; + out[oidx2] = cr2 - ci5; + out[oidx2 + 1] = ci2 + cr5; + out[oidx3] = cr3 - ci4; + out[oidx3 + 1] = ci3 + cr4; + out[oidx4] = cr3 + ci4; + out[oidx4 + 1] = ci3 - cr4; + out[oidx5] = cr2 + ci5; + out[oidx5 + 1] = ci2 - cr5; + } + } else { + for (int k = 1; k <= l1; k++) { + int idx1 = in_off + 1 + (k * 5 - 4) * ido; + int idx2 = out_off + (k - 1) * ido; + for (int i = 0; i < ido - 1; i += 2) { + int iidx1 = i + idx1; + int iidx2 = iidx1 + ido; + int iidx3 = iidx1 - ido; + int iidx4 = iidx2 + ido; + int iidx5 = iidx4 + ido; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + float i3i = in[iidx3 - 1]; + float i3r = in[iidx3]; + float i4i = in[iidx4 - 1]; + float i4r = in[iidx4]; + float i5i = in[iidx5 - 1]; + float i5r = in[iidx5]; + + ti5 = i1r - i5r; + ti2 = i1r + i5r; + ti4 = i2r - i4r; + ti3 = i2r + i4r; + tr5 = i1i - i5i; + tr2 = i1i + i5i; + tr4 = i2i - i4i; + tr3 = i2i + i4i; + cr2 = i3i + tr11 * tr2 + tr12 * tr3; + ci2 = i3r + tr11 * ti2 + tr12 * ti3; + cr3 = i3i + tr12 * tr2 + tr11 * tr3; + ci3 = i3r + tr12 * ti2 + tr11 * ti3; + cr5 = isign * (ti11 * tr5 + ti12 * tr4); + ci5 = isign * (ti11 * ti5 + ti12 * ti4); + cr4 = isign * (ti12 * tr5 - ti11 * tr4); + ci4 = isign * (ti12 * ti5 - ti11 * ti4); + dr3 = cr3 - ci4; + dr4 = cr3 + ci4; + di3 = ci3 + cr4; + di4 = ci3 - cr4; + dr5 = cr2 + ci5; + dr2 = cr2 - ci5; + di5 = ci2 - cr5; + di2 = ci2 + cr5; + + int widx1 = i + iw1; + int widx2 = i + iw2; + int widx3 = i + iw3; + int widx4 = i + iw4; + float w1r = wtable[widx1]; + float w1i = isign * wtable[widx1 + 1]; + float w2r = wtable[widx2]; + float w2i = isign * wtable[widx2 + 1]; + float w3r = wtable[widx3]; + float w3i = isign * wtable[widx3 + 1]; + float w4r = wtable[widx4]; + float w4i = isign * wtable[widx4 + 1]; + + int oidx1 = i + idx2; + int oidx2 = oidx1 + idx0; + int oidx3 = oidx2 + idx0; + int oidx4 = oidx3 + idx0; + int oidx5 = oidx4 + idx0; + out[oidx1] = i3i + tr2 + tr3; + out[oidx1 + 1] = i3r + ti2 + ti3; + out[oidx2] = w1r * dr2 - w1i * di2; + out[oidx2 + 1] = w1r * di2 + w1i * dr2; + out[oidx3] = w2r * dr3 - w2i * di3; + out[oidx3 + 1] = w2r * di3 + w2i * dr3; + out[oidx4] = w3r * dr4 - w3i * di4; + out[oidx4 + 1] = w3r * di4 + w3i * dr4; + out[oidx5] = w4r * dr5 - w4i * di5; + out[oidx5 + 1] = w4r * di5 + w4i * dr5; + } + } + } + } + + /*---------------------------------------------------------------------- + passf5: Complex FFT's forward/backward processing of factor 5; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ +/* + void passf5(final long ido, final long l1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) // isign==-1 for forward transform and+1 for backward transform { + final float tr11 = 0.309016994374947451262869435595348477f; + final float ti11 = 0.951056516295153531181938433292089030f; + final float tr12 = -0.809016994374947340240566973079694435f; + final float ti12 = 0.587785252292473248125759255344746634f; + float ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; + long iw1, iw2, iw3, iw4; + + iw1 = offset; + iw2 = iw1 + ido; + iw3 = iw2 + ido; + iw4 = iw3 + ido; + + long idx0 = l1 * ido; + + if (ido == 2) { + for (long k = 1; k <= l1; ++k) { + long iidx1 = in_off + (5 * k - 4) * ido + 1; + long iidx2 = iidx1 + ido; + long iidx3 = iidx1 - ido; + long iidx4 = iidx2 + ido; + long iidx5 = iidx4 + ido; + + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + float i5i = in.getFloat(iidx5 - 1); + float i5r = in.getFloat(iidx5); + + ti5 = i1r - i5r; + ti2 = i1r + i5r; + ti4 = i2r - i4r; + ti3 = i2r + i4r; + tr5 = i1i - i5i; + tr2 = i1i + i5i; + tr4 = i2i - i4i; + tr3 = i2i + i4i; + cr2 = i3i + tr11 * tr2 + tr12 * tr3; + ci2 = i3r + tr11 * ti2 + tr12 * ti3; + cr3 = i3i + tr12 * tr2 + tr11 * tr3; + ci3 = i3r + tr12 * ti2 + tr11 * ti3; + cr5 = isign * (ti11 * tr5 + ti12 * tr4); + ci5 = isign * (ti11 * ti5 + ti12 * ti4); + cr4 = isign * (ti12 * tr5 - ti11 * tr4); + ci4 = isign * (ti12 * ti5 - ti11 * ti4); + + long oidx1 = out_off + (k - 1) * ido; + long oidx2 = oidx1 + idx0; + long oidx3 = oidx2 + idx0; + long oidx4 = oidx3 + idx0; + long oidx5 = oidx4 + idx0; + out.setFloat(oidx1, i3i + tr2 + tr3); + out.setFloat(oidx1 + 1, i3r + ti2 + ti3); + out.setFloat(oidx2, cr2 - ci5); + out.setFloat(oidx2 + 1, ci2 + cr5); + out.setFloat(oidx3, cr3 - ci4); + out.setFloat(oidx3 + 1, ci3 + cr4); + out.setFloat(oidx4, cr3 + ci4); + out.setFloat(oidx4 + 1, ci3 - cr4); + out.setFloat(oidx5, cr2 + ci5); + out.setFloat(oidx5 + 1, ci2 - cr5); + } + } else { + for (long k = 1; k <= l1; k++) { + long idx1 = in_off + 1 + (k * 5 - 4) * ido; + long idx2 = out_off + (k - 1) * ido; + for (long i = 0; i < ido - 1; i += 2) { + long iidx1 = i + idx1; + long iidx2 = iidx1 + ido; + long iidx3 = iidx1 - ido; + long iidx4 = iidx2 + ido; + long iidx5 = iidx4 + ido; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + float i3i = in.getFloat(iidx3 - 1); + float i3r = in.getFloat(iidx3); + float i4i = in.getFloat(iidx4 - 1); + float i4r = in.getFloat(iidx4); + float i5i = in.getFloat(iidx5 - 1); + float i5r = in.getFloat(iidx5); + + ti5 = i1r - i5r; + ti2 = i1r + i5r; + ti4 = i2r - i4r; + ti3 = i2r + i4r; + tr5 = i1i - i5i; + tr2 = i1i + i5i; + tr4 = i2i - i4i; + tr3 = i2i + i4i; + cr2 = i3i + tr11 * tr2 + tr12 * tr3; + ci2 = i3r + tr11 * ti2 + tr12 * ti3; + cr3 = i3i + tr12 * tr2 + tr11 * tr3; + ci3 = i3r + tr12 * ti2 + tr11 * ti3; + cr5 = isign * (ti11 * tr5 + ti12 * tr4); + ci5 = isign * (ti11 * ti5 + ti12 * ti4); + cr4 = isign * (ti12 * tr5 - ti11 * tr4); + ci4 = isign * (ti12 * ti5 - ti11 * ti4); + dr3 = cr3 - ci4; + dr4 = cr3 + ci4; + di3 = ci3 + cr4; + di4 = ci3 - cr4; + dr5 = cr2 + ci5; + dr2 = cr2 - ci5; + di5 = ci2 - cr5; + di2 = ci2 + cr5; + + long widx1 = i + iw1; + long widx2 = i + iw2; + long widx3 = i + iw3; + long widx4 = i + iw4; + float w1r = wtablel.getFloat(widx1); + float w1i = isign * wtablel.getFloat(widx1 + 1); + float w2r = wtablel.getFloat(widx2); + float w2i = isign * wtablel.getFloat(widx2 + 1); + float w3r = wtablel.getFloat(widx3); + float w3i = isign * wtablel.getFloat(widx3 + 1); + float w4r = wtablel.getFloat(widx4); + float w4i = isign * wtablel.getFloat(widx4 + 1); + + long oidx1 = i + idx2; + long oidx2 = oidx1 + idx0; + long oidx3 = oidx2 + idx0; + long oidx4 = oidx3 + idx0; + long oidx5 = oidx4 + idx0; + out.setFloat(oidx1, i3i + tr2 + tr3); + out.setFloat(oidx1 + 1, i3r + ti2 + ti3); + out.setFloat(oidx2, w1r * dr2 - w1i * di2); + out.setFloat(oidx2 + 1, w1r * di2 + w1i * dr2); + out.setFloat(oidx3, w2r * dr3 - w2i * di3); + out.setFloat(oidx3 + 1, w2r * di3 + w2i * dr3); + out.setFloat(oidx4, w3r * dr4 - w3i * di4); + out.setFloat(oidx4 + 1, w3r * di4 + w3i * dr4); + out.setFloat(oidx5, w4r * dr5 - w4i * di5); + out.setFloat(oidx5 + 1, w4r * di5 + w4i * dr5); + } + } + } + } +*/ + /*---------------------------------------------------------------------- + passfg: Complex FFT's forward/backward processing of general factor; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ + void passfg(final int nac[], final int ido, final int ip, final int l1, final int idl1, final float in[], final int in_off, final float out[], final int out_off, final int offset, final int isign) { + int idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; + float w1r, w1i, w2i, w2r; + int iw1; + + iw1 = offset; + idot = ido / 2; + ipph = (ip + 1) / 2; + idp = ip * ido; + if (ido >= l1) { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * ido; + int idx2 = jc * ido; + for (int k = 0; k < l1; k++) { + int idx3 = k * ido; + int idx4 = idx3 + idx1 * l1; + int idx5 = idx3 + idx2 * l1; + int idx6 = idx3 * ip; + for (int i = 0; i < ido; i++) { + int oidx1 = out_off + i; + float i1r = in[in_off + i + idx1 + idx6]; + float i2r = in[in_off + i + idx2 + idx6]; + out[oidx1 + idx4] = i1r + i2r; + out[oidx1 + idx5] = i1r - i2r; + } + } + } + for (int k = 0; k < l1; k++) { + int idxt1 = k * ido; + int idxt2 = idxt1 * ip; + for (int i = 0; i < ido; i++) { + out[out_off + i + idxt1] = in[in_off + i + idxt2]; + } + } + } else { + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idxt1 = j * l1 * ido; + int idxt2 = jc * l1 * ido; + int idxt3 = j * ido; + int idxt4 = jc * ido; + for (int i = 0; i < ido; i++) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + int idx2 = idx1 * ip; + int idx3 = out_off + i; + int idx4 = in_off + i; + float i1r = in[idx4 + idxt3 + idx2]; + float i2r = in[idx4 + idxt4 + idx2]; + out[idx3 + idx1 + idxt1] = i1r + i2r; + out[idx3 + idx1 + idxt2] = i1r - i2r; + } + } + } + for (int i = 0; i < ido; i++) { + for (int k = 0; k < l1; k++) { + int idx1 = k * ido; + out[out_off + i + idx1] = in[in_off + i + idx1 * ip]; + } + } + } + + idl = 2 - ido; + inc = 0; + int idxt0 = (ip - 1) * idl1; + for (l = 1; l < ipph; l++) { + lc = ip - l; + idl += ido; + int idxt1 = l * idl1; + int idxt2 = lc * idl1; + int idxt3 = idl + iw1; + w1r = wtable[idxt3 - 2]; + w1i = isign * wtable[idxt3 - 1]; + for (int ik = 0; ik < idl1; ik++) { + int idx1 = in_off + ik; + int idx2 = out_off + ik; + in[idx1 + idxt1] = out[idx2] + w1r * out[idx2 + idl1]; + in[idx1 + idxt2] = w1i * out[idx2 + idxt0]; + } + idlj = idl; + inc += ido; + for (int j = 2; j < ipph; j++) { + jc = ip - j; + idlj += inc; + if (idlj > idp) { + idlj -= idp; + } + int idxt4 = idlj + iw1; + w2r = wtable[idxt4 - 2]; + w2i = isign * wtable[idxt4 - 1]; + int idxt5 = j * idl1; + int idxt6 = jc * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx1 = in_off + ik; + int idx2 = out_off + ik; + in[idx1 + idxt1] += w2r * out[idx2 + idxt5]; + in[idx1 + idxt2] += w2i * out[idx2 + idxt6]; + } + } + } + for (int j = 1; j < ipph; j++) { + int idxt1 = j * idl1; + for (int ik = 0; ik < idl1; ik++) { + int idx1 = out_off + ik; + out[idx1] += out[idx1 + idxt1]; + } + } + for (int j = 1; j < ipph; j++) { + jc = ip - j; + int idx1 = j * idl1; + int idx2 = jc * idl1; + for (int ik = 1; ik < idl1; ik += 2) { + int idx3 = out_off + ik; + int idx4 = in_off + ik; + int iidx1 = idx4 + idx1; + int iidx2 = idx4 + idx2; + float i1i = in[iidx1 - 1]; + float i1r = in[iidx1]; + float i2i = in[iidx2 - 1]; + float i2r = in[iidx2]; + + int oidx1 = idx3 + idx1; + int oidx2 = idx3 + idx2; + out[oidx1 - 1] = i1i - i2r; + out[oidx2 - 1] = i1i + i2r; + out[oidx1] = i1r + i2i; + out[oidx2] = i1r - i2i; + } + } + nac[0] = 1; + if (ido == 2) { + return; + } + nac[0] = 0; + System.arraycopy(out, out_off, in, in_off, idl1); + int idx0 = l1 * ido; + for (int j = 1; j < ip; j++) { + int idx1 = j * idx0; + for (int k = 0; k < l1; k++) { + int idx2 = k * ido; + int oidx1 = out_off + idx2 + idx1; + int iidx1 = in_off + idx2 + idx1; + in[iidx1] = out[oidx1]; + in[iidx1 + 1] = out[oidx1 + 1]; + } + } + if (idot <= l1) { + idij = 0; + for (int j = 1; j < ip; j++) { + idij += 2; + int idx1 = j * l1 * ido; + for (int i = 3; i < ido; i += 2) { + idij += 2; + int idx2 = idij + iw1 - 1; + w1r = wtable[idx2 - 1]; + w1i = isign * wtable[idx2]; + int idx3 = in_off + i; + int idx4 = out_off + i; + for (int k = 0; k < l1; k++) { + int idx5 = k * ido + idx1; + int iidx1 = idx3 + idx5; + int oidx1 = idx4 + idx5; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + in[iidx1 - 1] = w1r * o1i - w1i * o1r; + in[iidx1] = w1r * o1r + w1i * o1i; + } + } + } + } else { + idj = 2 - ido; + for (int j = 1; j < ip; j++) { + idj += ido; + int idx1 = j * l1 * ido; + for (int k = 0; k < l1; k++) { + idij = idj; + int idx3 = k * ido + idx1; + for (int i = 3; i < ido; i += 2) { + idij += 2; + int idx2 = idij - 1 + iw1; + w1r = wtable[idx2 - 1]; + w1i = isign * wtable[idx2]; + int iidx1 = in_off + i + idx3; + int oidx1 = out_off + i + idx3; + float o1i = out[oidx1 - 1]; + float o1r = out[oidx1]; + in[iidx1 - 1] = w1r * o1i - w1i * o1r; + in[iidx1] = w1r * o1r + w1i * o1i; + } + } + } + } + } + + /*---------------------------------------------------------------------- + passfg: Complex FFT's forward/backward processing of general factor; + isign is +1 for backward and -1 for forward transforms + ----------------------------------------------------------------------*/ +/* + void passfg(final int nac[], final long ido, final long ip, final long l1, final long idl1, final FloatLargeArray in, final long in_off, final FloatLargeArray out, final long out_off, final long offset, final long isign) { + long idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; + float w1r, w1i, w2i, w2r; + long iw1; + + iw1 = offset; + idot = ido / 2; + ipph = (ip + 1) / 2; + idp = ip * ido; + if (ido >= l1) { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * ido; + long idx2 = jc * ido; + for (long k = 0; k < l1; k++) { + long idx3 = k * ido; + long idx4 = idx3 + idx1 * l1; + long idx5 = idx3 + idx2 * l1; + long idx6 = idx3 * ip; + for (long i = 0; i < ido; i++) { + long oidx1 = out_off + i; + float i1r = in.getFloat(in_off + i + idx1 + idx6); + float i2r = in.getFloat(in_off + i + idx2 + idx6); + out.setFloat(oidx1 + idx4, i1r + i2r); + out.setFloat(oidx1 + idx5, i1r - i2r); + } + } + } + for (long k = 0; k < l1; k++) { + long idxt1 = k * ido; + long idxt2 = idxt1 * ip; + for (long i = 0; i < ido; i++) { + out.setFloat(out_off + i + idxt1, in.getFloat(in_off + i + idxt2)); + } + } + } else { + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idxt1 = j * l1 * ido; + long idxt2 = jc * l1 * ido; + long idxt3 = j * ido; + long idxt4 = jc * ido; + for (long i = 0; i < ido; i++) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + long idx2 = idx1 * ip; + long idx3 = out_off + i; + long idx4 = in_off + i; + float i1r = in.getFloat(idx4 + idxt3 + idx2); + float i2r = in.getFloat(idx4 + idxt4 + idx2); + out.setFloat(idx3 + idx1 + idxt1, i1r + i2r); + out.setFloat(idx3 + idx1 + idxt2, i1r - i2r); + } + } + } + for (long i = 0; i < ido; i++) { + for (long k = 0; k < l1; k++) { + long idx1 = k * ido; + out.setFloat(out_off + i + idx1, in.getFloat(in_off + i + idx1 * ip)); + } + } + } + + idl = 2 - ido; + inc = 0; + long idxt0 = (ip - 1) * idl1; + for (l = 1; l < ipph; l++) { + lc = ip - l; + idl += ido; + long idxt1 = l * idl1; + long idxt2 = lc * idl1; + long idxt3 = idl + iw1; + w1r = wtablel.getFloat(idxt3 - 2); + w1i = isign * wtablel.getFloat(idxt3 - 1); + for (long ik = 0; ik < idl1; ik++) { + long idx1 = in_off + ik; + long idx2 = out_off + ik; + in.setFloat(idx1 + idxt1, out.getFloat(idx2) + w1r * out.getFloat(idx2 + idl1)); + in.setFloat(idx1 + idxt2, w1i * out.getFloat(idx2 + idxt0)); + } + idlj = idl; + inc += ido; + for (long j = 2; j < ipph; j++) { + jc = ip - j; + idlj += inc; + if (idlj > idp) { + idlj -= idp; + } + long idxt4 = idlj + iw1; + w2r = wtablel.getFloat(idxt4 - 2); + w2i = isign * wtablel.getFloat(idxt4 - 1); + long idxt5 = j * idl1; + long idxt6 = jc * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx1 = in_off + ik; + long idx2 = out_off + ik; + in.setFloat(idx1 + idxt1, in.getFloat(idx1 + idxt1) + w2r * out.getFloat(idx2 + idxt5)); + in.setFloat(idx1 + idxt2, in.getFloat(idx1 + idxt2) + w2i * out.getFloat(idx2 + idxt6)); + } + } + } + for (long j = 1; j < ipph; j++) { + long idxt1 = j * idl1; + for (long ik = 0; ik < idl1; ik++) { + long idx1 = out_off + ik; + out.setFloat(idx1, out.getFloat(idx1) + out.getFloat(idx1 + idxt1)); + } + } + for (long j = 1; j < ipph; j++) { + jc = ip - j; + long idx1 = j * idl1; + long idx2 = jc * idl1; + for (long ik = 1; ik < idl1; ik += 2) { + long idx3 = out_off + ik; + long idx4 = in_off + ik; + long iidx1 = idx4 + idx1; + long iidx2 = idx4 + idx2; + float i1i = in.getFloat(iidx1 - 1); + float i1r = in.getFloat(iidx1); + float i2i = in.getFloat(iidx2 - 1); + float i2r = in.getFloat(iidx2); + + long oidx1 = idx3 + idx1; + long oidx2 = idx3 + idx2; + out.setFloat(oidx1 - 1, i1i - i2r); + out.setFloat(oidx2 - 1, i1i + i2r); + out.setFloat(oidx1, i1r + i2i); + out.setFloat(oidx2, i1r - i2i); + } + } + nac[0] = 1; + if (ido == 2) { + return; + } + nac[0] = 0; + Utilities.arraycopy(out, out_off, in, in_off, idl1); + long idx0 = l1 * ido; + for (long j = 1; j < ip; j++) { + long idx1 = j * idx0; + for (long k = 0; k < l1; k++) { + long idx2 = k * ido; + long oidx1 = out_off + idx2 + idx1; + long iidx1 = in_off + idx2 + idx1; + in.setFloat(iidx1, out.getFloat(oidx1)); + in.setFloat(iidx1 + 1, out.getFloat(oidx1 + 1)); + } + } + if (idot <= l1) { + idij = 0; + for (long j = 1; j < ip; j++) { + idij += 2; + long idx1 = j * l1 * ido; + for (long i = 3; i < ido; i += 2) { + idij += 2; + long idx2 = idij + iw1 - 1; + w1r = wtablel.getFloat(idx2 - 1); + w1i = isign * wtablel.getFloat(idx2); + long idx3 = in_off + i; + long idx4 = out_off + i; + for (long k = 0; k < l1; k++) { + long idx5 = k * ido + idx1; + long iidx1 = idx3 + idx5; + long oidx1 = idx4 + idx5; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); + in.setFloat(iidx1, w1r * o1r + w1i * o1i); + } + } + } + } else { + idj = 2 - ido; + for (long j = 1; j < ip; j++) { + idj += ido; + long idx1 = j * l1 * ido; + for (long k = 0; k < l1; k++) { + idij = idj; + long idx3 = k * ido + idx1; + for (long i = 3; i < ido; i += 2) { + idij += 2; + long idx2 = idij - 1 + iw1; + w1r = wtablel.getFloat(idx2 - 1); + w1i = isign * wtablel.getFloat(idx2); + long iidx1 = in_off + i + idx3; + long oidx1 = out_off + i + idx3; + float o1i = out.getFloat(oidx1 - 1); + float o1r = out.getFloat(oidx1); + in.setFloat(iidx1 - 1, w1r * o1i - w1i * o1r); + in.setFloat(iidx1, w1r * o1r + w1i * o1i); + } + } + } + } + } +*/ +} diff --git a/src/main/java/org/jtransforms/fft/FloatFFT_2D.java b/org/fairsim/extern/jtransforms/FloatFFT_2D.java similarity index 97% rename from src/main/java/org/jtransforms/fft/FloatFFT_2D.java rename to org/fairsim/extern/jtransforms/FloatFFT_2D.java index a294bd1..b78d38b 100644 --- a/src/main/java/org/jtransforms/fft/FloatFFT_2D.java +++ b/org/fairsim/extern/jtransforms/FloatFFT_2D.java @@ -1,3770 +1,3777 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 2D Discrete Fourier Transform (DFT) of complex and real, single - * precision data. The sizes of both dimensions can be arbitrary numbers. This - * is a parallel implementation of split-radix and mixed-radix algorithms - * optimized for SMP systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatFFT_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private FloatFFT_1D fftColumns, fftRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatFFT_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public FloatFFT_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - fftRows = new FloatFFT_1D(rows); - if (rows == columns) { - fftColumns = fftRows; - } else { - fftColumns = new FloatFFT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two float values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - * *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final float[] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - } - columns = columns / 2; - } else { - final int rowStride = 2 * columns; - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a, r * rowStride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - temp[idx1] = a[idx2]; - temp[idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[idx1]; - a[idx2 + 1] = temp[idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, r * rowStride); - } - float[] temp = new float[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - temp[idx1] = a[idx2]; - temp[idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[idx1]; - a[idx2 + 1] = temp[idx1 + 1]; - } - } - } - } - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two float values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - * *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final FloatLargeArray a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columnsl = 2 * columnsl; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - } - columnsl = columnsl / 2; - } else { - final long rowStride = 2 * columnsl; - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a, r * rowStride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - temp.setDouble(idx1, a.getFloat(idx2)); - temp.setDouble(idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(idx1)); - a.setDouble(idx2 + 1, temp.getFloat(idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, r * rowStride); - } - FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); - for (long c = 0; c < columnsl; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - temp.setDouble(idx1, a.getFloat(idx2)); - temp.setDouble(idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(idx1)); - a.setDouble(idx2 + 1, temp.getFloat(idx1 + 1)); - } - } - } - } - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 2D array. Complex data is - * represented by 2 float values in sequence: the real and imaginary part, - * i.e. the input array must be of size rows by 2*columns. The physical - * layout of the input data has to be as follows:
- * - * *
-     * a[k1][2*k2] = Re[k1][k2],
-     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final float[][] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[r]); - } - cdft2d_sub(-1, a, true); - } - columns = columns / 2; - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a[r]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[r]); - } - float[] temp = new float[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two float values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - * *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - * - */ - public void complexInverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, r * columns, scale); - } - cdft2d_sub(1, a, scale); - } - columns = columns / 2; - } else { - final int rowspan = 2 * columns; - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - temp[idx2] = a[idx3]; - temp[idx2 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - a[idx3] = temp[idx2]; - a[idx3 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - float[] temp = new float[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - temp[idx2] = a[idx3]; - temp[idx2 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - a[idx3] = temp[idx2]; - a[idx3 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two float values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - * *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - * - */ - public void complexInverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columnsl = 2 * columnsl; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - cdft2d_sub(1, a, scale); - } - columnsl = columnsl / 2; - } else { - final long rowspan = 2 * columnsl; - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - long idx1 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - temp.setDouble(idx2, a.getFloat(idx3)); - temp.setDouble(idx2 + 1, a.getFloat(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - a.setDouble(idx3, temp.getFloat(idx2)); - a.setDouble(idx3 + 1, temp.getFloat(idx2 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - temp.setDouble(idx2, a.getFloat(idx3)); - temp.setDouble(idx2 + 1, a.getFloat(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - a.setDouble(idx3, temp.getFloat(idx2)); - a.setDouble(idx3 + 1, temp.getFloat(idx2 + 1)); - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 2D array. Complex data is - * represented by 2 float values in sequence: the real and imaginary part, - * i.e. the input array must be of size rows by 2*columns. The physical - * layout of the input data has to be as follows:
- * - * *
-     * a[k1][2*k2] = Re[k1][k2],
-     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - * - */ - public void complexInverse(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[r], scale); - } - cdft2d_sub(1, a, scale); - } - columns = columns / 2; - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a[r], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[r], scale); - } - float[] temp = new float[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - * *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(float[] a) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - * *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(FloatLargeArray a) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - * *
-     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0][0] = Re[0][0],
-     * a[0][1] = Re[0][columns/2],
-     * a[rows/2][0] = Re[rows/2][0],
-     * a[rows/2][1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(float[][] a) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. To get back the original data, use - * complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(float[] a) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. To get back the original data, use - * complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(FloatLargeArray a) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows by 2*columns, with only the first rows by - * columns elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(float[][] a) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - * *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(float[] a, boolean scale) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a, r * columns, scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - * *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(FloatLargeArray a, boolean scale) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse(a, r * columnsl, scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - * *
-     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0][0] = Re[0][0],
-     * a[0][1] = Re[0][columns/2],
-     * a[rows/2][0] = Re[rows/2][0],
-     * a[rows/2][1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(float[][] a, boolean scale) { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a[r], scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverseFull(float[] a, boolean scale) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, r * columns, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverseFull(FloatLargeArray a, boolean scale) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows by 2*columns, with only the first rows by - * columns elements filled with real data. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverseFull(float[][] a, boolean scale) { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[r], 0, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - private void mixedRadixRealForwardFull(final float[][] a) { - final int n2d2 = columns / 2 + 1; - final float[][] temp = new float[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a[i]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int c = firstColumn; c < lastColumn; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - } - - private void mixedRadixRealForwardFull(final float[] a) { - final int rowStride = 2 * columns; - final int n2d2 = columns / 2 + 1; - final float[][] temp = new float[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a, i * columns); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - } - - private void mixedRadixRealForwardFull(final FloatLargeArray a) { - final long rowStride = 2 * columnsl; - final long n2d2 = columnsl / 2 + 1; - final FloatLargeArray temp = new FloatLargeArray(n2d2 * 2 * rowsl, false); - final long temp_stride = 2 * rowsl; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a, i * columnsl); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real - } - fftRows.realForwardFull(temp); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = 1 + l * p; - final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp, c * temp_stride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); - } - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstRow = 1 + l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getFloat(idx2)); - a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getFloat(idx4)); - a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real - } - fftRows.realForwardFull(temp); - - for (long c = 1; c < n2d2 - 1; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp, c * temp_stride); - } - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); - } - - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); - } - } - - //fill symmetric - for (long r = 1; r < rowsl; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getFloat(idx2)); - a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getFloat(idx4)); - a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); - } - } - } - } - - private void mixedRadixRealInverseFull(final float[][] a, final boolean scale) { - final int n2d2 = columns / 2 + 1; - final float[][] temp = new float[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a[i], 0, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int c = firstColumn; c < lastColumn; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[r], 0, scale); - } - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - } - - private void mixedRadixRealInverseFull(final float[] a, final boolean scale) { - final int rowStride = 2 * columns; - final int n2d2 = columns / 2 + 1; - final float[][] temp = new float[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, r * columns, scale); - } - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - } - - private void mixedRadixRealInverseFull(final FloatLargeArray a, final boolean scale) { - final long rowStride = 2 * columnsl; - final long n2d2 = columnsl / 2 + 1; - final FloatLargeArray temp = new FloatLargeArray(n2d2 * 2 * rowsl, false); - final long temp_stride = 2 * rowsl; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real - } - fftRows.realInverseFull(temp, scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = 1 + l * p; - final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexInverse(temp, c * temp_stride, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); - } - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstRow = 1 + l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getFloat(idx2)); - a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getFloat(idx4)); - a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real - } - fftRows.realInverseFull(temp, scale); - - for (long c = 1; c < n2d2 - 1; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexInverse(temp, c * temp_stride, scale); - } - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); - } - fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); - } - - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); - } - } - - //fill symmetric - for (long r = 1; r < rowsl; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getFloat(idx2)); - a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getFloat(idx4)); - a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); - } - } - } - } - - private void rdft2d_sub(int isgn, float[] a) { - int n1h, j; - float xi; - int idx1, idx2; - - n1h = rows >> 1; - if (isgn < 0) { - for (int i = 1; i < n1h; i++) { - j = rows - i; - idx1 = i * columns; - idx2 = j * columns; - xi = a[idx1] - a[idx2]; - a[idx1] += a[idx2]; - a[idx2] = xi; - xi = a[idx2 + 1] - a[idx1 + 1]; - a[idx1 + 1] += a[idx2 + 1]; - a[idx2 + 1] = xi; - } - } else { - for (int i = 1; i < n1h; i++) { - j = rows - i; - idx1 = i * columns; - idx2 = j * columns; - a[idx2] = 0.5f * (a[idx1] - a[idx2]); - a[idx1] -= a[idx2]; - a[idx2 + 1] = 0.5f * (a[idx1 + 1] + a[idx2 + 1]); - a[idx1 + 1] -= a[idx2 + 1]; - } - } - } - - private void rdft2d_sub(int isgn, FloatLargeArray a) { - long n1h, j; - float xi; - long idx1, idx2; - - n1h = rowsl >> 1; - if (isgn < 0) { - for (long i = 1; i < n1h; i++) { - j = rowsl - i; - idx1 = i * columnsl; - idx2 = j * columnsl; - xi = a.getFloat(idx1) - a.getFloat(idx2); - a.setDouble(idx1, a.getFloat(idx1) + a.getFloat(idx2)); - a.setDouble(idx2, xi); - xi = a.getFloat(idx2 + 1) - a.getFloat(idx1 + 1); - a.setDouble(idx1 + 1, a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1)); - a.setDouble(idx2 + 1, xi); - } - } else { - for (long i = 1; i < n1h; i++) { - j = rowsl - i; - idx1 = i * columnsl; - idx2 = j * columnsl; - a.setDouble(idx2, 0.5f * (a.getFloat(idx1) - a.getFloat(idx2))); - a.setDouble(idx1, a.getFloat(idx1) - a.getFloat(idx2)); - a.setDouble(idx2 + 1, 0.5f * (a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1))); - a.setDouble(idx1 + 1, a.getFloat(idx1 + 1) - a.getFloat(idx2 + 1)); - } - } - } - - private void rdft2d_sub(int isgn, float[][] a) { - int n1h, j; - float xi; - - n1h = rows >> 1; - if (isgn < 0) { - for (int i = 1; i < n1h; i++) { - j = rows - i; - xi = a[i][0] - a[j][0]; - a[i][0] += a[j][0]; - a[j][0] = xi; - xi = a[j][1] - a[i][1]; - a[i][1] += a[j][1]; - a[j][1] = xi; - } - } else { - for (int i = 1; i < n1h; i++) { - j = rows - i; - a[j][0] = 0.5f * (a[i][0] - a[j][0]); - a[i][0] -= a[j][0]; - a[j][1] = 0.5f * (a[i][1] + a[j][1]); - a[i][1] -= a[j][1]; - } - } - } - - private void cdft2d_sub(int isgn, float[] a, boolean scale) { - int idx1, idx2, idx3, idx4, idx5; - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - - private void cdft2d_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx1, idx2, idx3, idx4, idx5; - long nt = 8 * rowsl; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - t.setDouble(idx4, a.getFloat(idx1 + 4)); - t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); - t.setDouble(idx5, a.getFloat(idx1 + 6)); - t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - a.setDouble(idx1 + 4, t.getFloat(idx4)); - a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); - a.setDouble(idx1 + 6, t.getFloat(idx5)); - a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - } - } - } else { - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - t.setDouble(idx4, a.getFloat(idx1 + 4)); - t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); - t.setDouble(idx5, a.getFloat(idx1 + 6)); - t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - a.setDouble(idx1 + 4, t.getFloat(idx4)); - a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); - a.setDouble(idx1 + 6, t.getFloat(idx5)); - a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - } - } - } - } - - private void cdft2d_sub(int isgn, float[][] a, boolean scale) { - int idx2, idx3, idx4, idx5; - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - t[idx3] = a[r][2]; - t[idx3 + 1] = a[r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - a[r][2] = t[idx3]; - a[r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - t[idx3] = a[r][2]; - t[idx3 + 1] = a[r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - a[r][2] = t[idx3]; - a[r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - } - } - } - } - - private void xdft2d0_subth1(final int icr, final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a, r * columns, scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse(a, r * columns, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth1(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - } - } else { - if (isgn == 1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realInverse(a, r * columnsl, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final int icr, final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a, r * columns, scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse2(a, r * columns, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - } - } else { - if (isgn == 1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth1(final int icr, final int isgn, final float[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a[r], scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse(a[r], scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final int icr, final int isgn, final float[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a[r], scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse2(a[r], 0, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final float[] a, final boolean scale) { - int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2, idx3, idx4, idx5; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl / 2, ConcurrencyUtils.getNumberOfThreads()); - long nt = 8 * rowsl; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - final long ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthread; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2, idx3, idx4, idx5; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 4 * nthreads) { - for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - t.setDouble(idx4, a.getFloat(idx1 + 4)); - t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); - t.setDouble(idx5, a.getFloat(idx1 + 6)); - t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - a.setDouble(idx1 + 4, t.getFloat(idx4)); - a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); - a.setDouble(idx1 + 6, t.getFloat(idx5)); - a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); - } - } - } else if (columnsl == 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - } - } else if (columnsl == 2 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - } - } - } else { - if (columnsl > 4 * nthreads) { - for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - t.setDouble(idx4, a.getFloat(idx1 + 4)); - t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); - t.setDouble(idx5, a.getFloat(idx1 + 6)); - t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - a.setDouble(idx1 + 4, t.getFloat(idx4)); - a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); - a.setDouble(idx1 + 6, t.getFloat(idx5)); - a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); - } - } - } else if (columnsl == 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - t.setDouble(idx3, a.getFloat(idx1 + 2)); - t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - a.setDouble(idx1 + 2, t.getFloat(idx3)); - a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); - } - } else if (columnsl == 2 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - t.setDouble(idx2, a.getFloat(idx1)); - t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - a.setDouble(idx1, t.getFloat(idx2)); - a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final float[][] a, final boolean scale) { - int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2, idx3, idx4, idx5; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][4 * n0]; - t[idx2 + 1] = a[r][4 * n0 + 1]; - t[idx3] = a[r][4 * n0 + 2]; - t[idx3 + 1] = a[r][4 * n0 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][4 * n0] = t[idx2]; - a[r][4 * n0 + 1] = t[idx2 + 1]; - a[r][4 * n0 + 2] = t[idx3]; - a[r][4 * n0 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][2 * n0]; - t[idx2 + 1] = a[r][2 * n0 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][4 * n0]; - t[idx2 + 1] = a[r][4 * n0 + 1]; - t[idx3] = a[r][4 * n0 + 2]; - t[idx3 + 1] = a[r][4 * n0 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][4 * n0] = t[idx2]; - a[r][4 * n0 + 1] = t[idx2 + 1]; - a[r][4 * n0 + 2] = t[idx3]; - a[r][4 * n0 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][2 * n0]; - t[idx2 + 1] = a[r][2 * n0 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void fillSymmetric(final float[] a) { - final int twon2 = 2 * columns; - int idx1, idx2, idx3, idx4; - int n1d2 = rows / 2; - - for (int r = (rows - 1); r >= 1; r--) { - idx1 = r * columns; - idx2 = 2 * idx1; - for (int c = 0; c < columns; c += 2) { - a[idx2 + c] = a[idx1 + c]; - a[idx1 + c] = 0; - a[idx2 + c + 1] = a[idx1 + c + 1]; - a[idx1 + c + 1] = 0; - } - } - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int l1k = n1d2 / nthreads; - final int newn2 = 2 * columns; - for (int i = 0; i < nthreads; i++) { - final int l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) { - l1offa = i * l1k + 1; - } else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2, idx3, idx4; - - for (int r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx2 = (rows - r) * newn2; - idx3 = idx1 + columns; - a[idx3] = a[idx2 + 1]; - a[idx3 + 1] = -a[idx2]; - } - for (int r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx3 = (rows - r + 1) * newn2; - for (int c = columns + 2; c < newn2; c += 2) { - idx2 = idx3 - c; - idx4 = idx1 + c; - a[idx4] = a[idx2]; - a[idx4 + 1] = -a[idx2 + 1]; - - } - } - for (int r = l2offa; r < l2stopa; r++) { - idx3 = ((rows - r) % rows) * newn2; - idx4 = r * newn2; - for (int c = 0; c < newn2; c += 2) { - idx1 = idx3 + (newn2 - c) % newn2; - idx2 = idx4 + c; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r) * twon2; - a[idx2 + columns] = a[idx3 + 1]; - a[idx2 + columns + 1] = -a[idx3]; - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r + 1) * twon2; - for (int c = columns + 2; c < twon2; c += 2) { - a[idx2 + c] = a[idx3 - c]; - a[idx2 + c + 1] = -a[idx3 - c + 1]; - - } - } - for (int r = 0; r <= rows / 2; r++) { - idx1 = r * twon2; - idx4 = ((rows - r) % rows) * twon2; - for (int c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a[idx3] = a[idx2]; - a[idx3 + 1] = -a[idx2 + 1]; - } - } - } - a[columns] = -a[1]; - a[1] = 0; - idx1 = n1d2 * twon2; - a[idx1 + columns] = -a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx1 + columns + 1] = 0; - } - - private void fillSymmetric(final FloatLargeArray a) { - final long twon2 = 2 * columnsl; - long idx1, idx2, idx3, idx4; - long n1d2 = rowsl / 2; - - for (long r = (rowsl - 1); r >= 1; r--) { - idx1 = r * columnsl; - idx2 = 2 * idx1; - for (long c = 0; c < columnsl; c += 2) { - a.setDouble(idx2 + c, a.getFloat(idx1 + c)); - a.setDouble(idx1 + c, 0); - a.setDouble(idx2 + c + 1, a.getFloat(idx1 + c + 1)); - a.setDouble(idx1 + c + 1, 0); - } - } - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long l1k = n1d2 / nthreads; - final long newn2 = 2 * columnsl; - for (int i = 0; i < nthreads; i++) { - final long l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) { - l1offa = i * l1k + 1; - } else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2, idx3, idx4; - - for (long r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx2 = (rowsl - r) * newn2; - idx3 = idx1 + columnsl; - a.setDouble(idx3, a.getFloat(idx2 + 1)); - a.setDouble(idx3 + 1, -a.getFloat(idx2)); - } - for (long r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx3 = (rowsl - r + 1) * newn2; - for (long c = columnsl + 2; c < newn2; c += 2) { - idx2 = idx3 - c; - idx4 = idx1 + c; - a.setDouble(idx4, a.getFloat(idx2)); - a.setDouble(idx4 + 1, -a.getFloat(idx2 + 1)); - - } - } - for (long r = l2offa; r < l2stopa; r++) { - idx3 = ((rowsl - r) % rowsl) * newn2; - idx4 = r * newn2; - for (long c = 0; c < newn2; c += 2) { - idx1 = idx3 + (newn2 - c) % newn2; - idx2 = idx4 + c; - a.setDouble(idx1, a.getFloat(idx2)); - a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r) * twon2; - a.setDouble(idx2 + columnsl, a.getFloat(idx3 + 1)); - a.setDouble(idx2 + columnsl + 1, -a.getFloat(idx3)); - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r + 1) * twon2; - for (long c = columnsl + 2; c < twon2; c += 2) { - a.setDouble(idx2 + c, a.getFloat(idx3 - c)); - a.setDouble(idx2 + c + 1, -a.getFloat(idx3 - c + 1)); - - } - } - for (long r = 0; r <= rowsl / 2; r++) { - idx1 = r * twon2; - idx4 = ((rowsl - r) % rowsl) * twon2; - for (long c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a.setDouble(idx3, a.getFloat(idx2)); - a.setDouble(idx3 + 1, -a.getFloat(idx2 + 1)); - } - } - } - a.setDouble(columnsl, -a.getFloat(1)); - a.setDouble(1, 0); - idx1 = n1d2 * twon2; - a.setDouble(idx1 + columnsl, -a.getFloat(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx1 + columnsl + 1, 0); - } - - private void fillSymmetric(final float[][] a) { - final int newn2 = 2 * columns; - int n1d2 = rows / 2; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int l1k = n1d2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) { - l1offa = i * l1k + 1; - } else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - for (int r = l1offa; r < l1stopa; r++) { - idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = l1offa; r < l1stopa; r++) { - idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - - } - } - for (int r = l2offa; r < l2stopa; r++) { - idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c = c + 2) { - idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - int idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - } - } - for (int r = 0; r <= rows / 2; r++) { - int idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c += 2) { - int idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - } - a[0][columns] = -a[0][1]; - a[0][1] = 0; - a[n1d2][columns] = -a[n1d2][1]; - a[n1d2][1] = 0; - a[n1d2][columns + 1] = 0; - } -} +/* ***** BEGIN LICENSE BLOCK ***** + * JTransforms + * Copyright (c) 2007 onward, Piotr Wendykier + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +// Code modified for inclusion with fairSIM: +// - changed package name +// - Commented out all dependence on ...LargeArray +// - based on JTransforms 3.1, git ede249c9824262bd9b5f571e56f7a0fa596f6f20 + +package org.fairsim.extern.jtransforms; + +import java.util.concurrent.Future; +//import org.jtransforms.utils.ConcurrencyUtils; +//import pl.edu.icm.jlargearrays.FloatLargeArray; + +/** + * Computes 2D Discrete Fourier Transform (DFT) of complex and real, single + * precision data. The sizes of both dimensions can be arbitrary numbers. This + * is a parallel implementation of split-radix and mixed-radix algorithms + * optimized for SMP systems.
+ *
+ * Part of the code is derived from General Purpose FFT Package written by + * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) + * + * @author Piotr Wendykier (piotr.wendykier@gmail.com) + */ +public class FloatFFT_2D { + + private int rows; + + private int columns; + + private long rowsl; + + private long columnsl; + + private FloatFFT_1D fftColumns, fftRows; + + private boolean isPowerOfTwo = false; + + private boolean useThreads = false; + + /** + * Creates new instance of FloatFFT_2D. + * + * @param rows number of rows + * @param columns number of columns + */ + public FloatFFT_2D(long rows, long columns) { + if (rows <= 1 || columns <= 1) { + throw new IllegalArgumentException("rows and columns must be greater than 1"); + } + + this.rows = (int) rows; + this.columns = (int) columns; + this.rowsl = rows; + this.columnsl = columns; + if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { + this.useThreads = true; + } + if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { + isPowerOfTwo = true; + } + long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); + if (rows * columns > (1 << 28)) { + //ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); + throw new RuntimeException("no LargeArray support"); + } + fftRows = new FloatFFT_1D(rows); + if (rows == columns) { + fftColumns = fftRows; + } else { + fftColumns = new FloatFFT_1D(columns); + } + //ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); + } + + /** + * Computes 2D forward DFT of complex data leaving the result in + * a. The data is stored in 1D array in row-major order. + * Complex number is stored as two float values in sequence: the real and + * imaginary part, i.e. the input array must be of size rows*2*columns. The + * physical layout of the input data has to be as follows:
+ * + * *
+     * a[k1*2*columns+2*k2] = Re[k1][k2],
+     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + */ + public void complexForward(final float[] a) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columns = 2 * columns; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, -1, a, true); + cdft2d_subth(-1, a, true); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexForward(a, r * columns); + } + cdft2d_sub(-1, a, true); + } + columns = columns / 2; + } else { + final int rowStride = 2 * columns; + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + fftColumns.complexForward(a, r * rowStride); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columns / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = l * p; + final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + float[] temp = new float[2 * rows]; + for (int c = firstColumn; c < lastColumn; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * rowStride + idx0; + temp[idx1] = a[idx2]; + temp[idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp); + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[idx1]; + a[idx2 + 1] = temp[idx1 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexForward(a, r * rowStride); + } + float[] temp = new float[2 * rows]; + for (int c = 0; c < columns; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * rowStride + idx0; + temp[idx1] = a[idx2]; + temp[idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp); + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[idx1]; + a[idx2 + 1] = temp[idx1 + 1]; + } + } + } + } + } + + /** + * Computes 2D forward DFT of complex data leaving the result in + * a. The data is stored in 1D array in row-major order. + * Complex number is stored as two float values in sequence: the real and + * imaginary part, i.e. the input array must be of size rows*2*columns. The + * physical layout of the input data has to be as follows:
+ * + * *
+     * a[k1*2*columns+2*k2] = Re[k1][k2],
+     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + * + public void complexForward(final FloatLargeArray a) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columnsl = 2 * columnsl; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, -1, a, true); + cdft2d_subth(-1, a, true); + } else { + for (int r = 0; r < rowsl; r++) { + fftColumns.complexForward(a, r * columnsl); + } + cdft2d_sub(-1, a, true); + } + columnsl = columnsl / 2; + } else { + final long rowStride = 2 * columnsl; + if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { + Future[] futures = new Future[nthreads]; + long p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + fftColumns.complexForward(a, r * rowStride); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columnsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstColumn = l * p; + final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); + for (long c = firstColumn; c < lastColumn; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * rowStride + idx0; + temp.setDouble(idx1, a.getFloat(idx2)); + temp.setDouble(idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp); + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(idx1)); + a.setDouble(idx2 + 1, temp.getFloat(idx1 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.complexForward(a, r * rowStride); + } + FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); + for (long c = 0; c < columnsl; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * rowStride + idx0; + temp.setDouble(idx1, a.getFloat(idx2)); + temp.setDouble(idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp); + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(idx1)); + a.setDouble(idx2 + 1, temp.getFloat(idx1 + 1)); + } + } + } + } + } */ + + /** + * Computes 2D forward DFT of complex data leaving the result in + * a. The data is stored in 2D array. Complex data is + * represented by 2 float values in sequence: the real and imaginary part, + * i.e. the input array must be of size rows by 2*columns. The physical + * layout of the input data has to be as follows:
+ * + * *
+     * a[k1][2*k2] = Re[k1][k2],
+     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + */ + public void complexForward(final float[][] a) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columns = 2 * columns; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, -1, a, true); + cdft2d_subth(-1, a, true); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexForward(a[r]); + } + cdft2d_sub(-1, a, true); + } + columns = columns / 2; + } else { + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + fftColumns.complexForward(a[r]); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columns / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = l * p; + final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + float[] temp = new float[2 * rows]; + for (int c = firstColumn; c < lastColumn; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + temp[idx2] = a[r][idx1]; + temp[idx2 + 1] = a[r][idx1 + 1]; + } + fftRows.complexForward(temp); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + a[r][idx1] = temp[idx2]; + a[r][idx1 + 1] = temp[idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexForward(a[r]); + } + float[] temp = new float[2 * rows]; + for (int c = 0; c < columns; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + temp[idx2] = a[r][idx1]; + temp[idx2 + 1] = a[r][idx1 + 1]; + } + fftRows.complexForward(temp); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + a[r][idx1] = temp[idx2]; + a[r][idx1 + 1] = temp[idx2 + 1]; + } + } + } + } + } + + /** + * Computes 2D inverse DFT of complex data leaving the result in + * a. The data is stored in 1D array in row-major order. + * Complex number is stored as two float values in sequence: the real and + * imaginary part, i.e. the input array must be of size rows*2*columns. The + * physical layout of the input data has to be as follows:
+ * + * *
+     * a[k1*2*columns+2*k2] = Re[k1][k2],
+     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + * @param scale if true then scaling is performed + * + */ + public void complexInverse(final float[] a, final boolean scale) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columns = 2 * columns; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, 1, a, scale); + cdft2d_subth(1, a, scale); + } else { + + for (int r = 0; r < rows; r++) { + fftColumns.complexInverse(a, r * columns, scale); + } + cdft2d_sub(1, a, scale); + } + columns = columns / 2; + } else { + final int rowspan = 2 * columns; + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + fftColumns.complexInverse(a, r * rowspan, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columns / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = l * p; + final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + float[] temp = new float[2 * rows]; + for (int c = firstColumn; c < lastColumn; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + int idx3 = r * rowspan + idx1; + temp[idx2] = a[idx3]; + temp[idx2 + 1] = a[idx3 + 1]; + } + fftRows.complexInverse(temp, scale); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + int idx3 = r * rowspan + idx1; + a[idx3] = temp[idx2]; + a[idx3 + 1] = temp[idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexInverse(a, r * rowspan, scale); + } + float[] temp = new float[2 * rows]; + for (int c = 0; c < columns; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + int idx3 = r * rowspan + idx1; + temp[idx2] = a[idx3]; + temp[idx2 + 1] = a[idx3 + 1]; + } + fftRows.complexInverse(temp, scale); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + int idx3 = r * rowspan + idx1; + a[idx3] = temp[idx2]; + a[idx3 + 1] = temp[idx2 + 1]; + } + } + } + } + } + + /** + * Computes 2D inverse DFT of complex data leaving the result in + * a. The data is stored in 1D array in row-major order. + * Complex number is stored as two float values in sequence: the real and + * imaginary part, i.e. the input array must be of size rows*2*columns. The + * physical layout of the input data has to be as follows:
+ * + * *
+     * a[k1*2*columns+2*k2] = Re[k1][k2],
+     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + * @param scale if true then scaling is performed + * + * + public void complexInverse(final FloatLargeArray a, final boolean scale) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columnsl = 2 * columnsl; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, 1, a, scale); + cdft2d_subth(1, a, scale); + } else { + + for (long r = 0; r < rowsl; r++) { + fftColumns.complexInverse(a, r * columnsl, scale); + } + cdft2d_sub(1, a, scale); + } + columnsl = columnsl / 2; + } else { + final long rowspan = 2 * columnsl; + if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { + Future[] futures = new Future[nthreads]; + long p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + fftColumns.complexInverse(a, r * rowspan, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columnsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstColumn = l * p; + final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); + for (long c = firstColumn; c < lastColumn; c++) { + long idx1 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx2 = 2 * r; + long idx3 = r * rowspan + idx1; + temp.setDouble(idx2, a.getFloat(idx3)); + temp.setDouble(idx2 + 1, a.getFloat(idx3 + 1)); + } + fftRows.complexInverse(temp, scale); + for (long r = 0; r < rowsl; r++) { + long idx2 = 2 * r; + long idx3 = r * rowspan + idx1; + a.setDouble(idx3, temp.getFloat(idx2)); + a.setDouble(idx3 + 1, temp.getFloat(idx2 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.complexInverse(a, r * rowspan, scale); + } + FloatLargeArray temp = new FloatLargeArray(2 * rowsl, false); + for (long c = 0; c < columnsl; c++) { + long idx1 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx2 = 2 * r; + long idx3 = r * rowspan + idx1; + temp.setDouble(idx2, a.getFloat(idx3)); + temp.setDouble(idx2 + 1, a.getFloat(idx3 + 1)); + } + fftRows.complexInverse(temp, scale); + for (long r = 0; r < rowsl; r++) { + long idx2 = 2 * r; + long idx3 = r * rowspan + idx1; + a.setDouble(idx3, temp.getFloat(idx2)); + a.setDouble(idx3 + 1, temp.getFloat(idx2 + 1)); + } + } + } + } + } */ + + /** + * Computes 2D inverse DFT of complex data leaving the result in + * a. The data is stored in 2D array. Complex data is + * represented by 2 float values in sequence: the real and imaginary part, + * i.e. the input array must be of size rows by 2*columns. The physical + * layout of the input data has to be as follows:
+ * + * *
+     * a[k1][2*k2] = Re[k1][k2],
+     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
+     * 
+ * + * @param a data to transform + * @param scale if true then scaling is performed + * + */ + public void complexInverse(final float[][] a, final boolean scale) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if (isPowerOfTwo) { + columns = 2 * columns; + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(0, 1, a, scale); + cdft2d_subth(1, a, scale); + } else { + + for (int r = 0; r < rows; r++) { + fftColumns.complexInverse(a[r], scale); + } + cdft2d_sub(1, a, scale); + } + columns = columns / 2; + } else { + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + fftColumns.complexInverse(a[r], scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + p = columns / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = l * p; + final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + float[] temp = new float[2 * rows]; + for (int c = firstColumn; c < lastColumn; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + temp[idx2] = a[r][idx1]; + temp[idx2 + 1] = a[r][idx1 + 1]; + } + fftRows.complexInverse(temp, scale); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + a[r][idx1] = temp[idx2]; + a[r][idx1 + 1] = temp[idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.complexInverse(a[r], scale); + } + float[] temp = new float[2 * rows]; + for (int c = 0; c < columns; c++) { + int idx1 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + temp[idx2] = a[r][idx1]; + temp[idx2 + 1] = a[r][idx1 + 1]; + } + fftRows.complexInverse(temp, scale); + for (int r = 0; r < rows; r++) { + int idx2 = 2 * r; + a[r][idx1] = temp[idx2]; + a[r][idx1 + 1] = temp[idx2 + 1]; + } + } + } + } + } + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the output data is as + * follows: + * + * *
+     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0] = Re[0][0],
+     * a[1] = Re[0][columns/2],
+     * a[(rows/2)*columns] = Re[rows/2][0],
+     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + */ + public void realForward(float[] a) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a, r * columns); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + } + } + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the output data is as + * follows: + * + * *
+     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0] = Re[0][0],
+     * a[1] = Re[0][columns/2],
+     * a[(rows/2)*columns] = Re[rows/2][0],
+     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + * + public void realForward(FloatLargeArray a) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.realForward(a, r * columnsl); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + } + } */ + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the output data is as + * follows: + * + * *
+     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0][0] = Re[0][0],
+     * a[0][1] = Re[0][columns/2],
+     * a[rows/2][0] = Re[rows/2][0],
+     * a[rows/2][1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * forward transform, use realForwardFull. To get back the + * original data, use realInverse on the output of this method. + * + * @param a data to transform + */ + public void realForward(float[][] a) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a[r]); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + } + } + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method computes full real forward transform, i.e. you will get the + * same result as from complexForward called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows*2*columns, with only the first rows*columns + * elements filled with real data. To get back the original data, use + * complexInverse on the output of this method. + * + * @param a data to transform + */ + public void realForwardFull(float[] a) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a, r * columns); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealForwardFull(a); + } + } + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method computes full real forward transform, i.e. you will get the + * same result as from complexForward called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows*2*columns, with only the first rows*columns + * elements filled with real data. To get back the original data, use + * complexInverse on the output of this method. + * + * @param a data to transform + * + public void realForwardFull(FloatLargeArray a) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.realForward(a, r * columnsl); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealForwardFull(a); + } + } */ + + /** + * Computes 2D forward DFT of real data leaving the result in a + * . This method computes full real forward transform, i.e. you will get the + * same result as from complexForward called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows by 2*columns, with only the first rows by + * columns elements filled with real data. To get back the original data, + * use complexInverse on the output of this method. + * + * @param a data to transform + */ + public void realForwardFull(float[][] a) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth1(1, 1, a, true); + cdft2d_subth(-1, a, true); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a[r]); + } + cdft2d_sub(-1, a, true); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealForwardFull(a); + } + } + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the input data has to be as + * follows: + * + * *
+     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0] = Re[0][0],
+     * a[1] = Re[0][columns/2],
+     * a[(rows/2)*columns] = Re[rows/2][0],
+     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + */ + public void realInverse(float[] a, boolean scale) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + rdft2d_sub(-1, a); + cdft2d_subth(1, a, scale); + xdft2d0_subth1(1, -1, a, scale); + } else { + rdft2d_sub(-1, a); + cdft2d_sub(1, a, scale); + for (int r = 0; r < rows; r++) { + fftColumns.realInverse(a, r * columns, scale); + } + } + } + } + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the input data has to be as + * follows: + * + * *
+     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0] = Re[0][0],
+     * a[1] = Re[0][columns/2],
+     * a[(rows/2)*columns] = Re[rows/2][0],
+     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + * + public void realInverse(FloatLargeArray a, boolean scale) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + rdft2d_sub(-1, a); + cdft2d_subth(1, a, scale); + xdft2d0_subth1(1, -1, a, scale); + } else { + rdft2d_sub(-1, a); + cdft2d_sub(1, a, scale); + for (long r = 0; r < rowsl; r++) { + fftColumns.realInverse(a, r * columnsl, scale); + } + } + } + } */ + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method only works when the sizes of both dimensions are + * power-of-two numbers. The physical layout of the input data has to be as + * follows: + * + * *
+     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
+     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
+     *       0<k1<rows, 0<k2<columns/2,
+     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
+     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
+     *       0<k2<columns/2,
+     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
+     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
+     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
+     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
+     *       0<k1<rows/2,
+     * a[0][0] = Re[0][0],
+     * a[0][1] = Re[0][columns/2],
+     * a[rows/2][0] = Re[rows/2][0],
+     * a[rows/2][1] = Re[rows/2][columns/2]
+     * 
+ * + * This method computes only half of the elements of the real transform. The + * other half satisfies the symmetry condition. If you want the full real + * inverse transform, use realInverseFull. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + */ + public void realInverse(float[][] a, boolean scale) { + if (isPowerOfTwo == false) { + throw new IllegalArgumentException("rows and columns must be power of two numbers"); + } else { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + rdft2d_sub(-1, a); + cdft2d_subth(1, a, scale); + xdft2d0_subth1(1, -1, a, scale); + } else { + rdft2d_sub(-1, a); + cdft2d_sub(1, a, scale); + for (int r = 0; r < rows; r++) { + fftColumns.realInverse(a[r], scale); + } + } + } + } + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method computes full real inverse transform, i.e. you will get the + * same result as from complexInverse called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows*2*columns, with only the first rows*columns + * elements filled with real data. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + */ + public void realInverseFull(float[] a, boolean scale) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth2(1, -1, a, scale); + cdft2d_subth(1, a, scale); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realInverse2(a, r * columns, scale); + } + cdft2d_sub(1, a, scale); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealInverseFull(a, scale); + } + } + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method computes full real inverse transform, i.e. you will get the + * same result as from complexInverse called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows*2*columns, with only the first rows*columns + * elements filled with real data. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + * + public void realInverseFull(FloatLargeArray a, boolean scale) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth2(1, -1, a, scale); + cdft2d_subth(1, a, scale); + rdft2d_sub(1, a); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.realInverse2(a, r * columnsl, scale); + } + cdft2d_sub(1, a, scale); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealInverseFull(a, scale); + } + } */ + + /** + * Computes 2D inverse DFT of real data leaving the result in a + * . This method computes full real inverse transform, i.e. you will get the + * same result as from complexInverse called with all imaginary + * part equal 0. Because the result is stored in a, the input + * array must be of size rows by 2*columns, with only the first rows by + * columns elements filled with real data. + * + * @param a data to transform + * + * @param scale if true then scaling is performed + */ + public void realInverseFull(float[][] a, boolean scale) { + if (isPowerOfTwo) { + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads) { + xdft2d0_subth2(1, -1, a, scale); + cdft2d_subth(1, a, scale); + rdft2d_sub(1, a); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realInverse2(a[r], 0, scale); + } + cdft2d_sub(1, a, scale); + rdft2d_sub(1, a); + } + fillSymmetric(a); + } else { + mixedRadixRealInverseFull(a, scale); + } + } + + private void mixedRadixRealForwardFull(final float[][] a) { + final int n2d2 = columns / 2 + 1; + final float[][] temp = new float[n2d2][2 * rows]; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstRow; i < lastRow; i++) { + fftColumns.realForward(a[i]); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r][0]; //first column is always real + } + fftRows.realForwardFull(temp[0]); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = 1 + l * p; + final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int c = firstColumn; c < lastColumn; c++) { + int idx2 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + temp[c][idx1] = a[r][idx2]; + temp[c][idx1 + 1] = a[r][idx2 + 1]; + } + fftRows.complexForward(temp[c]); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r][1]; + //imaginary part = 0; + } + fftRows.realForwardFull(temp[n2d2 - 1]); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = n2d2 - 1; + temp[idx2][idx1] = a[r][2 * idx2]; + temp[idx2][idx1 + 1] = a[r][1]; + } + fftRows.complexForward(temp[n2d2 - 1]); + + } + + p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx2 = 2 * c; + a[r][idx2] = temp[c][idx1]; + a[r][idx2 + 1] = temp[c][idx1 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final int firstRow = 1 + l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx3 = rows - r; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[0][idx1] = a[0][idx2]; + a[0][idx1 + 1] = -a[0][idx2 + 1]; + a[r][idx1] = a[idx3][idx2]; + a[r][idx1 + 1] = -a[idx3][idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a[r]); + } + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r][0]; //first column is always real + } + fftRows.realForwardFull(temp[0]); + + for (int c = 1; c < n2d2 - 1; c++) { + int idx2 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + temp[c][idx1] = a[r][idx2]; + temp[c][idx1 + 1] = a[r][idx2 + 1]; + } + fftRows.complexForward(temp[c]); + } + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r][1]; + //imaginary part = 0; + } + fftRows.realForwardFull(temp[n2d2 - 1]); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = n2d2 - 1; + temp[idx2][idx1] = a[r][2 * idx2]; + temp[idx2][idx1 + 1] = a[r][1]; + } + fftRows.complexForward(temp[n2d2 - 1]); + + } + + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx2 = 2 * c; + a[r][idx2] = temp[c][idx1]; + a[r][idx2 + 1] = temp[c][idx1 + 1]; + } + } + + //fill symmetric + for (int r = 1; r < rows; r++) { + int idx3 = rows - r; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[0][idx1] = a[0][idx2]; + a[0][idx1 + 1] = -a[0][idx2 + 1]; + a[r][idx1] = a[idx3][idx2]; + a[r][idx1 + 1] = -a[idx3][idx2 + 1]; + } + } + } + } + + private void mixedRadixRealForwardFull(final float[] a) { + final int rowStride = 2 * columns; + final int n2d2 = columns / 2 + 1; + final float[][] temp = new float[n2d2][2 * rows]; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstRow; i < lastRow; i++) { + fftColumns.realForward(a, i * columns); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r * columns]; //first column is always real + } + fftRows.realForwardFull(temp[0]); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = 1 + l * p; + final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int c = firstColumn; c < lastColumn; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns + idx0; + temp[c][idx1] = a[idx2]; + temp[c][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp[c]); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r * columns + 1]; + //imaginary part = 0; + } + fftRows.realForwardFull(temp[n2d2 - 1]); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns; + int idx3 = n2d2 - 1; + temp[idx3][idx1] = a[idx2 + 2 * idx3]; + temp[idx3][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp[n2d2 - 1]); + } + + p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx0 = 2 * c; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[c][idx1]; + a[idx2 + 1] = temp[c][idx1 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final int firstRow = 1 + l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx5 = r * rowStride; + int idx6 = (rows - r + 1) * rowStride; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[idx1] = a[idx2]; + a[idx1 + 1] = -a[idx2 + 1]; + int idx3 = idx5 + idx1; + int idx4 = idx6 - idx1; + a[idx3] = a[idx4]; + a[idx3 + 1] = -a[idx4 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realForward(a, r * columns); + } + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r * columns]; //first column is always real + } + fftRows.realForwardFull(temp[0]); + + for (int c = 1; c < n2d2 - 1; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns + idx0; + temp[c][idx1] = a[idx2]; + temp[c][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp[c]); + } + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r * columns + 1]; + //imaginary part = 0; + } + fftRows.realForwardFull(temp[n2d2 - 1]); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns; + int idx3 = n2d2 - 1; + temp[idx3][idx1] = a[idx2 + 2 * idx3]; + temp[idx3][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexForward(temp[n2d2 - 1]); + } + + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx0 = 2 * c; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[c][idx1]; + a[idx2 + 1] = temp[c][idx1 + 1]; + } + } + + //fill symmetric + for (int r = 1; r < rows; r++) { + int idx5 = r * rowStride; + int idx6 = (rows - r + 1) * rowStride; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[idx1] = a[idx2]; + a[idx1 + 1] = -a[idx2 + 1]; + int idx3 = idx5 + idx1; + int idx4 = idx6 - idx1; + a[idx3] = a[idx4]; + a[idx3 + 1] = -a[idx4 + 1]; + } + } + } + } +/* + private void mixedRadixRealForwardFull(final FloatLargeArray a) { + final long rowStride = 2 * columnsl; + final long n2d2 = columnsl / 2 + 1; + final FloatLargeArray temp = new FloatLargeArray(n2d2 * 2 * rowsl, false); + final long temp_stride = 2 * rowsl; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + long p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstRow; i < lastRow; i++) { + fftColumns.realForward(a, i * columnsl); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (long r = 0; r < rowsl; r++) { + temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real + } + fftRows.realForwardFull(temp); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstColumn = 1 + l * p; + final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long c = firstColumn; c < lastColumn; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl + idx0; + temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); + temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp, c * temp_stride); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columnsl % 2) == 0) { + for (long r = 0; r < rowsl; r++) { + temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); + //imaginary part = 0; + } + fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); + + } else { + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl; + long idx3 = n2d2 - 1; + temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); + temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); + } + + p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + long idx1 = 2 * r; + for (long c = 0; c < n2d2; c++) { + long idx0 = 2 * c; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); + a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final long firstRow = 1 + l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + long idx5 = r * rowStride; + long idx6 = (rowsl - r + 1) * rowStride; + for (long c = n2d2; c < columnsl; c++) { + long idx1 = 2 * c; + long idx2 = 2 * (columnsl - c); + a.setDouble(idx1, a.getFloat(idx2)); + a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); + long idx3 = idx5 + idx1; + long idx4 = idx6 - idx1; + a.setDouble(idx3, a.getFloat(idx4)); + a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.realForward(a, r * columnsl); + } + for (long r = 0; r < rowsl; r++) { + temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real + } + fftRows.realForwardFull(temp); + + for (long c = 1; c < n2d2 - 1; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl + idx0; + temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); + temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp, c * temp_stride); + } + + if ((columnsl % 2) == 0) { + for (long r = 0; r < rowsl; r++) { + temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); + //imaginary part = 0; + } + fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); + + } else { + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl; + long idx3 = n2d2 - 1; + temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); + temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); + } + + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + for (long c = 0; c < n2d2; c++) { + long idx0 = 2 * c; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); + a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); + } + } + + //fill symmetric + for (long r = 1; r < rowsl; r++) { + long idx5 = r * rowStride; + long idx6 = (rowsl - r + 1) * rowStride; + for (long c = n2d2; c < columnsl; c++) { + long idx1 = 2 * c; + long idx2 = 2 * (columnsl - c); + a.setDouble(idx1, a.getFloat(idx2)); + a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); + long idx3 = idx5 + idx1; + long idx4 = idx6 - idx1; + a.setDouble(idx3, a.getFloat(idx4)); + a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); + } + } + } + } +*/ + private void mixedRadixRealInverseFull(final float[][] a, final boolean scale) { + final int n2d2 = columns / 2 + 1; + final float[][] temp = new float[n2d2][2 * rows]; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstRow; i < lastRow; i++) { + fftColumns.realInverse2(a[i], 0, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r][0]; //first column is always real + } + fftRows.realInverseFull(temp[0], scale); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = 1 + l * p; + final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int c = firstColumn; c < lastColumn; c++) { + int idx2 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + temp[c][idx1] = a[r][idx2]; + temp[c][idx1 + 1] = a[r][idx2 + 1]; + } + fftRows.complexInverse(temp[c], scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r][1]; + //imaginary part = 0; + } + fftRows.realInverseFull(temp[n2d2 - 1], scale); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = n2d2 - 1; + temp[idx2][idx1] = a[r][2 * idx2]; + temp[idx2][idx1 + 1] = a[r][1]; + } + fftRows.complexInverse(temp[n2d2 - 1], scale); + + } + + p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx2 = 2 * c; + a[r][idx2] = temp[c][idx1]; + a[r][idx2 + 1] = temp[c][idx1 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final int firstRow = 1 + l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx3 = rows - r; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[0][idx1] = a[0][idx2]; + a[0][idx1 + 1] = -a[0][idx2 + 1]; + a[r][idx1] = a[idx3][idx2]; + a[r][idx1 + 1] = -a[idx3][idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realInverse2(a[r], 0, scale); + } + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r][0]; //first column is always real + } + fftRows.realInverseFull(temp[0], scale); + + for (int c = 1; c < n2d2 - 1; c++) { + int idx2 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + temp[c][idx1] = a[r][idx2]; + temp[c][idx1 + 1] = a[r][idx2 + 1]; + } + fftRows.complexInverse(temp[c], scale); + } + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r][1]; + //imaginary part = 0; + } + fftRows.realInverseFull(temp[n2d2 - 1], scale); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = n2d2 - 1; + temp[idx2][idx1] = a[r][2 * idx2]; + temp[idx2][idx1 + 1] = a[r][1]; + } + fftRows.complexInverse(temp[n2d2 - 1], scale); + + } + + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx2 = 2 * c; + a[r][idx2] = temp[c][idx1]; + a[r][idx2 + 1] = temp[c][idx1 + 1]; + } + } + + //fill symmetric + for (int r = 1; r < rows; r++) { + int idx3 = rows - r; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[0][idx1] = a[0][idx2]; + a[0][idx1 + 1] = -a[0][idx2 + 1]; + a[r][idx1] = a[idx3][idx2]; + a[r][idx1 + 1] = -a[idx3][idx2 + 1]; + } + } + } + } + + private void mixedRadixRealInverseFull(final float[] a, final boolean scale) { + final int rowStride = 2 * columns; + final int n2d2 = columns / 2 + 1; + final float[][] temp = new float[n2d2][2 * rows]; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int i = firstRow; i < lastRow; i++) { + fftColumns.realInverse2(a, i * columns, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r * columns]; //first column is always real + } + fftRows.realInverseFull(temp[0], scale); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstColumn = 1 + l * p; + final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int c = firstColumn; c < lastColumn; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns + idx0; + temp[c][idx1] = a[idx2]; + temp[c][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexInverse(temp[c], scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r * columns + 1]; + //imaginary part = 0; + } + fftRows.realInverseFull(temp[n2d2 - 1], scale); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns; + int idx3 = n2d2 - 1; + temp[idx3][idx1] = a[idx2 + 2 * idx3]; + temp[idx3][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexInverse(temp[n2d2 - 1], scale); + } + + p = rows / nthreads; + for (int l = 0; l < nthreads; l++) { + final int firstRow = l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx0 = 2 * c; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[c][idx1]; + a[idx2 + 1] = temp[c][idx1 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final int firstRow = 1 + l * p; + final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (int r = firstRow; r < lastRow; r++) { + int idx5 = r * rowStride; + int idx6 = (rows - r + 1) * rowStride; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[idx1] = a[idx2]; + a[idx1 + 1] = -a[idx2 + 1]; + int idx3 = idx5 + idx1; + int idx4 = idx6 - idx1; + a[idx3] = a[idx4]; + a[idx3 + 1] = -a[idx4 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (int r = 0; r < rows; r++) { + fftColumns.realInverse2(a, r * columns, scale); + } + for (int r = 0; r < rows; r++) { + temp[0][r] = a[r * columns]; //first column is always real + } + fftRows.realInverseFull(temp[0], scale); + + for (int c = 1; c < n2d2 - 1; c++) { + int idx0 = 2 * c; + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns + idx0; + temp[c][idx1] = a[idx2]; + temp[c][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexInverse(temp[c], scale); + } + + if ((columns % 2) == 0) { + for (int r = 0; r < rows; r++) { + temp[n2d2 - 1][r] = a[r * columns + 1]; + //imaginary part = 0; + } + fftRows.realInverseFull(temp[n2d2 - 1], scale); + + } else { + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + int idx2 = r * columns; + int idx3 = n2d2 - 1; + temp[idx3][idx1] = a[idx2 + 2 * idx3]; + temp[idx3][idx1 + 1] = a[idx2 + 1]; + } + fftRows.complexInverse(temp[n2d2 - 1], scale); + } + + for (int r = 0; r < rows; r++) { + int idx1 = 2 * r; + for (int c = 0; c < n2d2; c++) { + int idx0 = 2 * c; + int idx2 = r * rowStride + idx0; + a[idx2] = temp[c][idx1]; + a[idx2 + 1] = temp[c][idx1 + 1]; + } + } + + //fill symmetric + for (int r = 1; r < rows; r++) { + int idx5 = r * rowStride; + int idx6 = (rows - r + 1) * rowStride; + for (int c = n2d2; c < columns; c++) { + int idx1 = 2 * c; + int idx2 = 2 * (columns - c); + a[idx1] = a[idx2]; + a[idx1 + 1] = -a[idx2 + 1]; + int idx3 = idx5 + idx1; + int idx4 = idx6 - idx1; + a[idx3] = a[idx4]; + a[idx3 + 1] = -a[idx4 + 1]; + } + } + } + } +/* + private void mixedRadixRealInverseFull(final FloatLargeArray a, final boolean scale) { + final long rowStride = 2 * columnsl; + final long n2d2 = columnsl / 2 + 1; + final FloatLargeArray temp = new FloatLargeArray(n2d2 * 2 * rowsl, false); + final long temp_stride = 2 * rowsl; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + long p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long i = firstRow; i < lastRow; i++) { + fftColumns.realInverse2(a, i * columnsl, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (long r = 0; r < rowsl; r++) { + temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real + } + fftRows.realInverseFull(temp, scale); + + p = (n2d2 - 2) / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstColumn = 1 + l * p; + final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long c = firstColumn; c < lastColumn; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl + idx0; + temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); + temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexInverse(temp, c * temp_stride, scale); + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + if ((columnsl % 2) == 0) { + for (long r = 0; r < rowsl; r++) { + temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); + //imaginary part = 0; + } + fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); + + } else { + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl; + long idx3 = n2d2 - 1; + temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); + temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); + } + + p = rowsl / nthreads; + for (int l = 0; l < nthreads; l++) { + final long firstRow = l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + long idx1 = 2 * r; + for (long c = 0; c < n2d2; c++) { + long idx0 = 2 * c; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); + a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + for (int l = 0; l < nthreads; l++) { + final long firstRow = 1 + l * p; + final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; + futures[l] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + for (long r = firstRow; r < lastRow; r++) { + long idx5 = r * rowStride; + long idx6 = (rowsl - r + 1) * rowStride; + for (long c = n2d2; c < columnsl; c++) { + long idx1 = 2 * c; + long idx2 = 2 * (columnsl - c); + a.setDouble(idx1, a.getFloat(idx2)); + a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); + long idx3 = idx5 + idx1; + long idx4 = idx6 - idx1; + a.setDouble(idx3, a.getFloat(idx4)); + a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + for (long r = 0; r < rowsl; r++) { + fftColumns.realInverse2(a, r * columnsl, scale); + } + for (long r = 0; r < rowsl; r++) { + temp.setDouble(r, a.getFloat(r * columnsl)); //first column is always real + } + fftRows.realInverseFull(temp, scale); + + for (long c = 1; c < n2d2 - 1; c++) { + long idx0 = 2 * c; + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl + idx0; + temp.setDouble(c * temp_stride + idx1, a.getFloat(idx2)); + temp.setDouble(c * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexInverse(temp, c * temp_stride, scale); + } + + if ((columnsl % 2) == 0) { + for (long r = 0; r < rowsl; r++) { + temp.setDouble((n2d2 - 1) * temp_stride + r, a.getFloat(r * columnsl + 1)); + //imaginary part = 0; + } + fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); + + } else { + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + long idx2 = r * columnsl; + long idx3 = n2d2 - 1; + temp.setDouble(idx3 * temp_stride + idx1, a.getFloat(idx2 + 2 * idx3)); + temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getFloat(idx2 + 1)); + } + fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); + } + + for (long r = 0; r < rowsl; r++) { + long idx1 = 2 * r; + for (long c = 0; c < n2d2; c++) { + long idx0 = 2 * c; + long idx2 = r * rowStride + idx0; + a.setDouble(idx2, temp.getFloat(c * temp_stride + idx1)); + a.setDouble(idx2 + 1, temp.getFloat(c * temp_stride + idx1 + 1)); + } + } + + //fill symmetric + for (long r = 1; r < rowsl; r++) { + long idx5 = r * rowStride; + long idx6 = (rowsl - r + 1) * rowStride; + for (long c = n2d2; c < columnsl; c++) { + long idx1 = 2 * c; + long idx2 = 2 * (columnsl - c); + a.setDouble(idx1, a.getFloat(idx2)); + a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); + long idx3 = idx5 + idx1; + long idx4 = idx6 - idx1; + a.setDouble(idx3, a.getFloat(idx4)); + a.setDouble(idx3 + 1, -a.getFloat(idx4 + 1)); + } + } + } + } +*/ + private void rdft2d_sub(int isgn, float[] a) { + int n1h, j; + float xi; + int idx1, idx2; + + n1h = rows >> 1; + if (isgn < 0) { + for (int i = 1; i < n1h; i++) { + j = rows - i; + idx1 = i * columns; + idx2 = j * columns; + xi = a[idx1] - a[idx2]; + a[idx1] += a[idx2]; + a[idx2] = xi; + xi = a[idx2 + 1] - a[idx1 + 1]; + a[idx1 + 1] += a[idx2 + 1]; + a[idx2 + 1] = xi; + } + } else { + for (int i = 1; i < n1h; i++) { + j = rows - i; + idx1 = i * columns; + idx2 = j * columns; + a[idx2] = 0.5f * (a[idx1] - a[idx2]); + a[idx1] -= a[idx2]; + a[idx2 + 1] = 0.5f * (a[idx1 + 1] + a[idx2 + 1]); + a[idx1 + 1] -= a[idx2 + 1]; + } + } + } +/* + private void rdft2d_sub(int isgn, FloatLargeArray a) { + long n1h, j; + float xi; + long idx1, idx2; + + n1h = rowsl >> 1; + if (isgn < 0) { + for (long i = 1; i < n1h; i++) { + j = rowsl - i; + idx1 = i * columnsl; + idx2 = j * columnsl; + xi = a.getFloat(idx1) - a.getFloat(idx2); + a.setDouble(idx1, a.getFloat(idx1) + a.getFloat(idx2)); + a.setDouble(idx2, xi); + xi = a.getFloat(idx2 + 1) - a.getFloat(idx1 + 1); + a.setDouble(idx1 + 1, a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1)); + a.setDouble(idx2 + 1, xi); + } + } else { + for (long i = 1; i < n1h; i++) { + j = rowsl - i; + idx1 = i * columnsl; + idx2 = j * columnsl; + a.setDouble(idx2, 0.5f * (a.getFloat(idx1) - a.getFloat(idx2))); + a.setDouble(idx1, a.getFloat(idx1) - a.getFloat(idx2)); + a.setDouble(idx2 + 1, 0.5f * (a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1))); + a.setDouble(idx1 + 1, a.getFloat(idx1 + 1) - a.getFloat(idx2 + 1)); + } + } + } +*/ + private void rdft2d_sub(int isgn, float[][] a) { + int n1h, j; + float xi; + + n1h = rows >> 1; + if (isgn < 0) { + for (int i = 1; i < n1h; i++) { + j = rows - i; + xi = a[i][0] - a[j][0]; + a[i][0] += a[j][0]; + a[j][0] = xi; + xi = a[j][1] - a[i][1]; + a[i][1] += a[j][1]; + a[j][1] = xi; + } + } else { + for (int i = 1; i < n1h; i++) { + j = rows - i; + a[j][0] = 0.5f * (a[i][0] - a[j][0]); + a[i][0] -= a[j][0]; + a[j][1] = 0.5f * (a[i][1] + a[j][1]); + a[i][1] -= a[j][1]; + } + } + } + + private void cdft2d_sub(int isgn, float[] a, boolean scale) { + int idx1, idx2, idx3, idx4, idx5; + int nt = 8 * rows; + if (columns == 4) { + nt >>= 1; + } else if (columns < 4) { + nt >>= 2; + } + float[] t = new float[nt]; + if (isgn == -1) { + if (columns > 4) { + for (int c = 0; c < columns; c += 8) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + t[idx4] = a[idx1 + 4]; + t[idx4 + 1] = a[idx1 + 5]; + t[idx5] = a[idx1 + 6]; + t[idx5 + 1] = a[idx1 + 7]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + fftRows.complexForward(t, 4 * rows); + fftRows.complexForward(t, 6 * rows); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + a[idx1 + 4] = t[idx4]; + a[idx1 + 5] = t[idx4 + 1]; + a[idx1 + 6] = t[idx5]; + a[idx1 + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + } + } else if (columns == 2) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + } + fftRows.complexForward(t, 0); + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + } + } + } else { + if (columns > 4) { + for (int c = 0; c < columns; c += 8) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + t[idx4] = a[idx1 + 4]; + t[idx4 + 1] = a[idx1 + 5]; + t[idx5] = a[idx1 + 6]; + t[idx5 + 1] = a[idx1 + 7]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + fftRows.complexInverse(t, 4 * rows, scale); + fftRows.complexInverse(t, 6 * rows, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + a[idx1 + 4] = t[idx4]; + a[idx1 + 5] = t[idx4 + 1]; + a[idx1 + 6] = t[idx5]; + a[idx1 + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + } + } else if (columns == 2) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + } + fftRows.complexInverse(t, 0, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns; + idx2 = 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + } + } + } + } +/* + private void cdft2d_sub(int isgn, FloatLargeArray a, boolean scale) { + long idx1, idx2, idx3, idx4, idx5; + long nt = 8 * rowsl; + if (columnsl == 4) { + nt >>= 1; + } else if (columnsl < 4) { + nt >>= 2; + } + FloatLargeArray t = new FloatLargeArray(nt, false); + if (isgn == -1) { + if (columnsl > 4) { + for (long c = 0; c < columnsl; c += 8) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + t.setDouble(idx4, a.getFloat(idx1 + 4)); + t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); + t.setDouble(idx5, a.getFloat(idx1 + 6)); + t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rowsl); + fftRows.complexForward(t, 4 * rowsl); + fftRows.complexForward(t, 6 * rowsl); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + a.setDouble(idx1 + 4, t.getFloat(idx4)); + a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); + a.setDouble(idx1 + 6, t.getFloat(idx5)); + a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); + } + } + } else if (columnsl == 4) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rowsl); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + } + } else if (columnsl == 2) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + } + fftRows.complexForward(t, 0); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + } + } + } else { + if (columnsl > 4) { + for (long c = 0; c < columnsl; c += 8) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + t.setDouble(idx4, a.getFloat(idx1 + 4)); + t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); + t.setDouble(idx5, a.getFloat(idx1 + 6)); + t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rowsl, scale); + fftRows.complexInverse(t, 4 * rowsl, scale); + fftRows.complexInverse(t, 6 * rowsl, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + a.setDouble(idx1 + 4, t.getFloat(idx4)); + a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); + a.setDouble(idx1 + 6, t.getFloat(idx5)); + a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); + } + } + } else if (columnsl == 4) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rowsl, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + } + } else if (columnsl == 2) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + } + fftRows.complexInverse(t, 0, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl; + idx2 = 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + } + } + } + } +*/ + private void cdft2d_sub(int isgn, float[][] a, boolean scale) { + int idx2, idx3, idx4, idx5; + int nt = 8 * rows; + if (columns == 4) { + nt >>= 1; + } else if (columns < 4) { + nt >>= 2; + } + float[] t = new float[nt]; + if (isgn == -1) { + if (columns > 4) { + for (int c = 0; c < columns; c += 8) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[r][c]; + t[idx2 + 1] = a[r][c + 1]; + t[idx3] = a[r][c + 2]; + t[idx3 + 1] = a[r][c + 3]; + t[idx4] = a[r][c + 4]; + t[idx4 + 1] = a[r][c + 5]; + t[idx5] = a[r][c + 6]; + t[idx5 + 1] = a[r][c + 7]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + fftRows.complexForward(t, 4 * rows); + fftRows.complexForward(t, 6 * rows); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[r][c] = t[idx2]; + a[r][c + 1] = t[idx2 + 1]; + a[r][c + 2] = t[idx3]; + a[r][c + 3] = t[idx3 + 1]; + a[r][c + 4] = t[idx4]; + a[r][c + 5] = t[idx4 + 1]; + a[r][c + 6] = t[idx5]; + a[r][c + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[r][0]; + t[idx2 + 1] = a[r][1]; + t[idx3] = a[r][2]; + t[idx3 + 1] = a[r][3]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[r][0] = t[idx2]; + a[r][1] = t[idx2 + 1]; + a[r][2] = t[idx3]; + a[r][3] = t[idx3 + 1]; + } + } else if (columns == 2) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + t[idx2] = a[r][0]; + t[idx2 + 1] = a[r][1]; + } + fftRows.complexForward(t, 0); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + a[r][0] = t[idx2]; + a[r][1] = t[idx2 + 1]; + } + } + } else { + if (columns > 4) { + for (int c = 0; c < columns; c += 8) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[r][c]; + t[idx2 + 1] = a[r][c + 1]; + t[idx3] = a[r][c + 2]; + t[idx3 + 1] = a[r][c + 3]; + t[idx4] = a[r][c + 4]; + t[idx4 + 1] = a[r][c + 5]; + t[idx5] = a[r][c + 6]; + t[idx5 + 1] = a[r][c + 7]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + fftRows.complexInverse(t, 4 * rows, scale); + fftRows.complexInverse(t, 6 * rows, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[r][c] = t[idx2]; + a[r][c + 1] = t[idx2 + 1]; + a[r][c + 2] = t[idx3]; + a[r][c + 3] = t[idx3 + 1]; + a[r][c + 4] = t[idx4]; + a[r][c + 5] = t[idx4 + 1]; + a[r][c + 6] = t[idx5]; + a[r][c + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[r][0]; + t[idx2 + 1] = a[r][1]; + t[idx3] = a[r][2]; + t[idx3 + 1] = a[r][3]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[r][0] = t[idx2]; + a[r][1] = t[idx2 + 1]; + a[r][2] = t[idx3]; + a[r][3] = t[idx3 + 1]; + } + } else if (columns == 2) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + t[idx2] = a[r][0]; + t[idx2 + 1] = a[r][1]; + } + fftRows.complexInverse(t, 0, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + a[r][0] = t[idx2]; + a[r][1] = t[idx2 + 1]; + } + } + } + } + + private void xdft2d0_subth1(final int icr, final int isgn, final float[] a, final boolean scale) { + final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexForward(a, r * columns); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexInverse(a, r * columns, scale); + } + } + } else { + if (isgn == 1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realForward(a, r * columns); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realInverse(a, r * columns, scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +/* + private void xdft2d0_subth1(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { + final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.complexForward(a, r * columnsl); + } + } else { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.complexInverse(a, r * columnsl, scale); + } + } + } else { + if (isgn == 1) { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.realForward(a, r * columnsl); + } + } else { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.realInverse(a, r * columnsl, scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +*/ + private void xdft2d0_subth2(final int icr, final int isgn, final float[] a, final boolean scale) { + final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexForward(a, r * columns); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexInverse(a, r * columns, scale); + } + } + } else { + if (isgn == 1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realForward(a, r * columns); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realInverse2(a, r * columns, scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +/* + private void xdft2d0_subth2(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { + final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final long n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.complexForward(a, r * columnsl); + } + } else { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.complexInverse(a, r * columnsl, scale); + } + } + } else { + if (isgn == 1) { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.realForward(a, r * columnsl); + } + } else { + for (long r = n0; r < rowsl; r += nthreads) { + fftColumns.realInverse2(a, r * columnsl, scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +*/ + private void xdft2d0_subth1(final int icr, final int isgn, final float[][] a, final boolean scale) { + final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexForward(a[r]); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexInverse(a[r], scale); + } + } + } else { + if (isgn == 1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realForward(a[r]); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realInverse(a[r], scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } + + private void xdft2d0_subth2(final int icr, final int isgn, final float[][] a, final boolean scale) { + final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); + + Future[] futures = new Future[nthreads]; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + if (icr == 0) { + if (isgn == -1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexForward(a[r]); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.complexInverse(a[r], scale); + } + } + } else { + if (isgn == 1) { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realForward(a[r]); + } + } else { + for (int r = n0; r < rows; r += nthreads) { + fftColumns.realInverse2(a[r], 0, scale); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } + + private void cdft2d_subth(final int isgn, final float[] a, final boolean scale) { + int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); + int nt = 8 * rows; + if (columns == 4) { + nt >>= 1; + } else if (columns < 4) { + nt >>= 2; + } + final int ntf = nt; + Future[] futures = new Future[nthread]; + final int nthreads = nthread; + for (int i = 0; i < nthread; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx1, idx2, idx3, idx4, idx5; + float[] t = new float[ntf]; + if (isgn == -1) { + if (columns > 4 * nthreads) { + for (int c = 8 * n0; c < columns; c += 8 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + t[idx4] = a[idx1 + 4]; + t[idx4 + 1] = a[idx1 + 5]; + t[idx5] = a[idx1 + 6]; + t[idx5 + 1] = a[idx1 + 7]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + fftRows.complexForward(t, 4 * rows); + fftRows.complexForward(t, 6 * rows); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + a[idx1 + 4] = t[idx4]; + a[idx1 + 5] = t[idx4 + 1]; + a[idx1 + 6] = t[idx5]; + a[idx1 + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + } + } else if (columns == 2 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 2 * n0; + idx2 = 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + } + fftRows.complexForward(t, 0); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 2 * n0; + idx2 = 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + } + } + } else { + if (columns > 4 * nthreads) { + for (int c = 8 * n0; c < columns; c += 8 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + t[idx4] = a[idx1 + 4]; + t[idx4 + 1] = a[idx1 + 5]; + t[idx5] = a[idx1 + 6]; + t[idx5 + 1] = a[idx1 + 7]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + fftRows.complexInverse(t, 4 * rows, scale); + fftRows.complexInverse(t, 6 * rows, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + c; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + a[idx1 + 4] = t[idx4]; + a[idx1 + 5] = t[idx4 + 1]; + a[idx1 + 6] = t[idx5]; + a[idx1 + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + t[idx3] = a[idx1 + 2]; + t[idx3 + 1] = a[idx1 + 3]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + a[idx1 + 2] = t[idx3]; + a[idx1 + 3] = t[idx3 + 1]; + } + } else if (columns == 2 * nthreads) { + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 2 * n0; + idx2 = 2 * r; + t[idx2] = a[idx1]; + t[idx2 + 1] = a[idx1 + 1]; + } + fftRows.complexInverse(t, 0, scale); + for (int r = 0; r < rows; r++) { + idx1 = r * columns + 2 * n0; + idx2 = 2 * r; + a[idx1] = t[idx2]; + a[idx1 + 1] = t[idx2 + 1]; + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +/* + private void cdft2d_subth(final int isgn, final FloatLargeArray a, final boolean scale) { + int nthread = (int) Math.min(columnsl / 2, ConcurrencyUtils.getNumberOfThreads()); + long nt = 8 * rowsl; + if (columnsl == 4) { + nt >>= 1; + } else if (columnsl < 4) { + nt >>= 2; + } + final long ntf = nt; + Future[] futures = new Future[nthread]; + final int nthreads = nthread; + for (int i = 0; i < nthread; i++) { + final long n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + long idx1, idx2, idx3, idx4, idx5; + FloatLargeArray t = new FloatLargeArray(ntf, false); + if (isgn == -1) { + if (columnsl > 4 * nthreads) { + for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + t.setDouble(idx4, a.getFloat(idx1 + 4)); + t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); + t.setDouble(idx5, a.getFloat(idx1 + 6)); + t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rowsl); + fftRows.complexForward(t, 4 * rowsl); + fftRows.complexForward(t, 6 * rowsl); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + a.setDouble(idx1 + 4, t.getFloat(idx4)); + a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); + a.setDouble(idx1 + 6, t.getFloat(idx5)); + a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); + } + } + } else if (columnsl == 4 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rowsl); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + } + } else if (columnsl == 2 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 2 * n0; + idx2 = 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + } + fftRows.complexForward(t, 0); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 2 * n0; + idx2 = 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + } + } + } else { + if (columnsl > 4 * nthreads) { + for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + t.setDouble(idx4, a.getFloat(idx1 + 4)); + t.setDouble(idx4 + 1, a.getFloat(idx1 + 5)); + t.setDouble(idx5, a.getFloat(idx1 + 6)); + t.setDouble(idx5 + 1, a.getFloat(idx1 + 7)); + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rowsl, scale); + fftRows.complexInverse(t, 4 * rowsl, scale); + fftRows.complexInverse(t, 6 * rowsl, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + c; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + idx4 = idx3 + 2 * rowsl; + idx5 = idx4 + 2 * rowsl; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + a.setDouble(idx1 + 4, t.getFloat(idx4)); + a.setDouble(idx1 + 5, t.getFloat(idx4 + 1)); + a.setDouble(idx1 + 6, t.getFloat(idx5)); + a.setDouble(idx1 + 7, t.getFloat(idx5 + 1)); + } + } + } else if (columnsl == 4 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + t.setDouble(idx3, a.getFloat(idx1 + 2)); + t.setDouble(idx3 + 1, a.getFloat(idx1 + 3)); + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rowsl, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 4 * n0; + idx2 = 2 * r; + idx3 = 2 * rowsl + 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + a.setDouble(idx1 + 2, t.getFloat(idx3)); + a.setDouble(idx1 + 3, t.getFloat(idx3 + 1)); + } + } else if (columnsl == 2 * nthreads) { + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 2 * n0; + idx2 = 2 * r; + t.setDouble(idx2, a.getFloat(idx1)); + t.setDouble(idx2 + 1, a.getFloat(idx1 + 1)); + } + fftRows.complexInverse(t, 0, scale); + for (long r = 0; r < rowsl; r++) { + idx1 = r * columnsl + 2 * n0; + idx2 = 2 * r; + a.setDouble(idx1, t.getFloat(idx2)); + a.setDouble(idx1 + 1, t.getFloat(idx2 + 1)); + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } +*/ + private void cdft2d_subth(final int isgn, final float[][] a, final boolean scale) { + int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); + int nt = 8 * rows; + if (columns == 4) { + nt >>= 1; + } else if (columns < 4) { + nt >>= 2; + } + final int ntf = nt; + Future[] futures = new Future[nthread]; + final int nthreads = nthread; + for (int i = 0; i < nthreads; i++) { + final int n0 = i; + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx2, idx3, idx4, idx5; + float[] t = new float[ntf]; + if (isgn == -1) { + if (columns > 4 * nthreads) { + for (int c = 8 * n0; c < columns; c += 8 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[r][c]; + t[idx2 + 1] = a[r][c + 1]; + t[idx3] = a[r][c + 2]; + t[idx3 + 1] = a[r][c + 3]; + t[idx4] = a[r][c + 4]; + t[idx4 + 1] = a[r][c + 5]; + t[idx5] = a[r][c + 6]; + t[idx5 + 1] = a[r][c + 7]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + fftRows.complexForward(t, 4 * rows); + fftRows.complexForward(t, 6 * rows); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[r][c] = t[idx2]; + a[r][c + 1] = t[idx2 + 1]; + a[r][c + 2] = t[idx3]; + a[r][c + 3] = t[idx3 + 1]; + a[r][c + 4] = t[idx4]; + a[r][c + 5] = t[idx4 + 1]; + a[r][c + 6] = t[idx5]; + a[r][c + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[r][4 * n0]; + t[idx2 + 1] = a[r][4 * n0 + 1]; + t[idx3] = a[r][4 * n0 + 2]; + t[idx3 + 1] = a[r][4 * n0 + 3]; + } + fftRows.complexForward(t, 0); + fftRows.complexForward(t, 2 * rows); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[r][4 * n0] = t[idx2]; + a[r][4 * n0 + 1] = t[idx2 + 1]; + a[r][4 * n0 + 2] = t[idx3]; + a[r][4 * n0 + 3] = t[idx3 + 1]; + } + } else if (columns == 2 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + t[idx2] = a[r][2 * n0]; + t[idx2 + 1] = a[r][2 * n0 + 1]; + } + fftRows.complexForward(t, 0); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + a[r][2 * n0] = t[idx2]; + a[r][2 * n0 + 1] = t[idx2 + 1]; + } + } + } else { + if (columns > 4 * nthreads) { + for (int c = 8 * n0; c < columns; c += 8 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + t[idx2] = a[r][c]; + t[idx2 + 1] = a[r][c + 1]; + t[idx3] = a[r][c + 2]; + t[idx3 + 1] = a[r][c + 3]; + t[idx4] = a[r][c + 4]; + t[idx4 + 1] = a[r][c + 5]; + t[idx5] = a[r][c + 6]; + t[idx5 + 1] = a[r][c + 7]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + fftRows.complexInverse(t, 4 * rows, scale); + fftRows.complexInverse(t, 6 * rows, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + idx4 = idx3 + 2 * rows; + idx5 = idx4 + 2 * rows; + a[r][c] = t[idx2]; + a[r][c + 1] = t[idx2 + 1]; + a[r][c + 2] = t[idx3]; + a[r][c + 3] = t[idx3 + 1]; + a[r][c + 4] = t[idx4]; + a[r][c + 5] = t[idx4 + 1]; + a[r][c + 6] = t[idx5]; + a[r][c + 7] = t[idx5 + 1]; + } + } + } else if (columns == 4 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + t[idx2] = a[r][4 * n0]; + t[idx2 + 1] = a[r][4 * n0 + 1]; + t[idx3] = a[r][4 * n0 + 2]; + t[idx3 + 1] = a[r][4 * n0 + 3]; + } + fftRows.complexInverse(t, 0, scale); + fftRows.complexInverse(t, 2 * rows, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + idx3 = 2 * rows + 2 * r; + a[r][4 * n0] = t[idx2]; + a[r][4 * n0 + 1] = t[idx2 + 1]; + a[r][4 * n0 + 2] = t[idx3]; + a[r][4 * n0 + 3] = t[idx3 + 1]; + } + } else if (columns == 2 * nthreads) { + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + t[idx2] = a[r][2 * n0]; + t[idx2 + 1] = a[r][2 * n0 + 1]; + } + fftRows.complexInverse(t, 0, scale); + for (int r = 0; r < rows; r++) { + idx2 = 2 * r; + a[r][2 * n0] = t[idx2]; + a[r][2 * n0 + 1] = t[idx2 + 1]; + } + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } + + private void fillSymmetric(final float[] a) { + final int twon2 = 2 * columns; + int idx1, idx2, idx3, idx4; + int n1d2 = rows / 2; + + for (int r = (rows - 1); r >= 1; r--) { + idx1 = r * columns; + idx2 = 2 * idx1; + for (int c = 0; c < columns; c += 2) { + a[idx2 + c] = a[idx1 + c]; + a[idx1 + c] = 0; + a[idx2 + c + 1] = a[idx1 + c + 1]; + a[idx1 + c + 1] = 0; + } + } + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int l1k = n1d2 / nthreads; + final int newn2 = 2 * columns; + for (int i = 0; i < nthreads; i++) { + final int l1offa, l1stopa, l2offa, l2stopa; + if (i == 0) { + l1offa = i * l1k + 1; + } else { + l1offa = i * l1k; + } + l1stopa = i * l1k + l1k; + l2offa = i * l1k; + if (i == nthreads - 1) { + l2stopa = i * l1k + l1k + 1; + } else { + l2stopa = i * l1k + l1k; + } + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx1, idx2, idx3, idx4; + + for (int r = l1offa; r < l1stopa; r++) { + idx1 = r * newn2; + idx2 = (rows - r) * newn2; + idx3 = idx1 + columns; + a[idx3] = a[idx2 + 1]; + a[idx3 + 1] = -a[idx2]; + } + for (int r = l1offa; r < l1stopa; r++) { + idx1 = r * newn2; + idx3 = (rows - r + 1) * newn2; + for (int c = columns + 2; c < newn2; c += 2) { + idx2 = idx3 - c; + idx4 = idx1 + c; + a[idx4] = a[idx2]; + a[idx4 + 1] = -a[idx2 + 1]; + + } + } + for (int r = l2offa; r < l2stopa; r++) { + idx3 = ((rows - r) % rows) * newn2; + idx4 = r * newn2; + for (int c = 0; c < newn2; c += 2) { + idx1 = idx3 + (newn2 - c) % newn2; + idx2 = idx4 + c; + a[idx1] = a[idx2]; + a[idx1 + 1] = -a[idx2 + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (int r = 1; r < n1d2; r++) { + idx2 = r * twon2; + idx3 = (rows - r) * twon2; + a[idx2 + columns] = a[idx3 + 1]; + a[idx2 + columns + 1] = -a[idx3]; + } + + for (int r = 1; r < n1d2; r++) { + idx2 = r * twon2; + idx3 = (rows - r + 1) * twon2; + for (int c = columns + 2; c < twon2; c += 2) { + a[idx2 + c] = a[idx3 - c]; + a[idx2 + c + 1] = -a[idx3 - c + 1]; + + } + } + for (int r = 0; r <= rows / 2; r++) { + idx1 = r * twon2; + idx4 = ((rows - r) % rows) * twon2; + for (int c = 0; c < twon2; c += 2) { + idx2 = idx1 + c; + idx3 = idx4 + (twon2 - c) % twon2; + a[idx3] = a[idx2]; + a[idx3 + 1] = -a[idx2 + 1]; + } + } + } + a[columns] = -a[1]; + a[1] = 0; + idx1 = n1d2 * twon2; + a[idx1 + columns] = -a[idx1 + 1]; + a[idx1 + 1] = 0; + a[idx1 + columns + 1] = 0; + } +/* + private void fillSymmetric(final FloatLargeArray a) { + final long twon2 = 2 * columnsl; + long idx1, idx2, idx3, idx4; + long n1d2 = rowsl / 2; + + for (long r = (rowsl - 1); r >= 1; r--) { + idx1 = r * columnsl; + idx2 = 2 * idx1; + for (long c = 0; c < columnsl; c += 2) { + a.setDouble(idx2 + c, a.getFloat(idx1 + c)); + a.setDouble(idx1 + c, 0); + a.setDouble(idx2 + c + 1, a.getFloat(idx1 + c + 1)); + a.setDouble(idx1 + c + 1, 0); + } + } + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + long l1k = n1d2 / nthreads; + final long newn2 = 2 * columnsl; + for (int i = 0; i < nthreads; i++) { + final long l1offa, l1stopa, l2offa, l2stopa; + if (i == 0) { + l1offa = i * l1k + 1; + } else { + l1offa = i * l1k; + } + l1stopa = i * l1k + l1k; + l2offa = i * l1k; + if (i == nthreads - 1) { + l2stopa = i * l1k + l1k + 1; + } else { + l2stopa = i * l1k + l1k; + } + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + long idx1, idx2, idx3, idx4; + + for (long r = l1offa; r < l1stopa; r++) { + idx1 = r * newn2; + idx2 = (rowsl - r) * newn2; + idx3 = idx1 + columnsl; + a.setDouble(idx3, a.getFloat(idx2 + 1)); + a.setDouble(idx3 + 1, -a.getFloat(idx2)); + } + for (long r = l1offa; r < l1stopa; r++) { + idx1 = r * newn2; + idx3 = (rowsl - r + 1) * newn2; + for (long c = columnsl + 2; c < newn2; c += 2) { + idx2 = idx3 - c; + idx4 = idx1 + c; + a.setDouble(idx4, a.getFloat(idx2)); + a.setDouble(idx4 + 1, -a.getFloat(idx2 + 1)); + + } + } + for (long r = l2offa; r < l2stopa; r++) { + idx3 = ((rowsl - r) % rowsl) * newn2; + idx4 = r * newn2; + for (long c = 0; c < newn2; c += 2) { + idx1 = idx3 + (newn2 - c) % newn2; + idx2 = idx4 + c; + a.setDouble(idx1, a.getFloat(idx2)); + a.setDouble(idx1 + 1, -a.getFloat(idx2 + 1)); + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + + } else { + + for (long r = 1; r < n1d2; r++) { + idx2 = r * twon2; + idx3 = (rowsl - r) * twon2; + a.setDouble(idx2 + columnsl, a.getFloat(idx3 + 1)); + a.setDouble(idx2 + columnsl + 1, -a.getFloat(idx3)); + } + + for (long r = 1; r < n1d2; r++) { + idx2 = r * twon2; + idx3 = (rowsl - r + 1) * twon2; + for (long c = columnsl + 2; c < twon2; c += 2) { + a.setDouble(idx2 + c, a.getFloat(idx3 - c)); + a.setDouble(idx2 + c + 1, -a.getFloat(idx3 - c + 1)); + + } + } + for (long r = 0; r <= rowsl / 2; r++) { + idx1 = r * twon2; + idx4 = ((rowsl - r) % rowsl) * twon2; + for (long c = 0; c < twon2; c += 2) { + idx2 = idx1 + c; + idx3 = idx4 + (twon2 - c) % twon2; + a.setDouble(idx3, a.getFloat(idx2)); + a.setDouble(idx3 + 1, -a.getFloat(idx2 + 1)); + } + } + } + a.setDouble(columnsl, -a.getFloat(1)); + a.setDouble(1, 0); + idx1 = n1d2 * twon2; + a.setDouble(idx1 + columnsl, -a.getFloat(idx1 + 1)); + a.setDouble(idx1 + 1, 0); + a.setDouble(idx1 + columnsl + 1, 0); + } +*/ + private void fillSymmetric(final float[][] a) { + final int newn2 = 2 * columns; + int n1d2 = rows / 2; + + int nthreads = ConcurrencyUtils.getNumberOfThreads(); + if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { + Future[] futures = new Future[nthreads]; + int l1k = n1d2 / nthreads; + for (int i = 0; i < nthreads; i++) { + final int l1offa, l1stopa, l2offa, l2stopa; + if (i == 0) { + l1offa = i * l1k + 1; + } else { + l1offa = i * l1k; + } + l1stopa = i * l1k + l1k; + l2offa = i * l1k; + if (i == nthreads - 1) { + l2stopa = i * l1k + l1k + 1; + } else { + l2stopa = i * l1k + l1k; + } + futures[i] = ConcurrencyUtils.submit(new Runnable() { + public void run() { + int idx1, idx2; + for (int r = l1offa; r < l1stopa; r++) { + idx1 = rows - r; + a[r][columns] = a[idx1][1]; + a[r][columns + 1] = -a[idx1][0]; + } + for (int r = l1offa; r < l1stopa; r++) { + idx1 = rows - r; + for (int c = columns + 2; c < newn2; c += 2) { + idx2 = newn2 - c; + a[r][c] = a[idx1][idx2]; + a[r][c + 1] = -a[idx1][idx2 + 1]; + + } + } + for (int r = l2offa; r < l2stopa; r++) { + idx1 = (rows - r) % rows; + for (int c = 0; c < newn2; c = c + 2) { + idx2 = (newn2 - c) % newn2; + a[idx1][idx2] = a[r][c]; + a[idx1][idx2 + 1] = -a[r][c + 1]; + } + } + } + }); + } + ConcurrencyUtils.waitForCompletion(futures); + } else { + + for (int r = 1; r < n1d2; r++) { + int idx1 = rows - r; + a[r][columns] = a[idx1][1]; + a[r][columns + 1] = -a[idx1][0]; + } + for (int r = 1; r < n1d2; r++) { + int idx1 = rows - r; + for (int c = columns + 2; c < newn2; c += 2) { + int idx2 = newn2 - c; + a[r][c] = a[idx1][idx2]; + a[r][c + 1] = -a[idx1][idx2 + 1]; + } + } + for (int r = 0; r <= rows / 2; r++) { + int idx1 = (rows - r) % rows; + for (int c = 0; c < newn2; c += 2) { + int idx2 = (newn2 - c) % newn2; + a[idx1][idx2] = a[r][c]; + a[idx1][idx2 + 1] = -a[r][c + 1]; + } + } + } + a[0][columns] = -a[0][1]; + a[0][1] = 0; + a[n1d2][columns] = -a[n1d2][1]; + a[n1d2][1] = 0; + a[n1d2][columns + 1] = 0; + } +} diff --git a/src/main/java/org/jtransforms/fft/FloatFFT_3D.java b/org/fairsim/extern/jtransforms/FloatFFT_3D.java similarity index 97% rename from src/main/java/org/jtransforms/fft/FloatFFT_3D.java rename to org/fairsim/extern/jtransforms/FloatFFT_3D.java index f24b208..dc72845 100644 --- a/src/main/java/org/jtransforms/fft/FloatFFT_3D.java +++ b/org/fairsim/extern/jtransforms/FloatFFT_3D.java @@ -24,12 +24,18 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; + +// Code modified for inclusion with fairSIM: +// - changed package name +// - Commented out all dependence on ...LargeArray +// - based on JTransforms 3.1, git ede249c9824262bd9b5f571e56f7a0fa596f6f20 + +package org.fairsim.extern.jtransforms; import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; -import pl.edu.icm.jlargearrays.Utilities; +//import org.jtransforms.utils.ConcurrencyUtils; +//import pl.edu.icm.jlargearrays.FloatLargeArray; +//import pl.edu.icm.jlargearrays.Utilities; /** * Computes 3D Discrete Fourier Transform (DFT) of complex and real, single @@ -314,6 +320,7 @@ public void run() { * * @param a data to transform */ + /* public void complexForward(final FloatLargeArray a) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); if (isPowerOfTwo) { @@ -469,7 +476,7 @@ public void run() { sliceStridel = rowsl * columnsl; rowStridel = columnsl; } - } + } */ /** * Computes 3D forward DFT of complex data leaving the result in @@ -824,6 +831,7 @@ public void run() { * @param a data to transform * @param scale if true then scaling is performed */ + /* public void complexInverse(final FloatLargeArray a, final boolean scale) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -980,7 +988,7 @@ public void run() { sliceStridel = rowsl * columnsl; rowStridel = columnsl; } - } + } */ /** * Computes 3D inverse DFT of complex data leaving the result in @@ -1254,6 +1262,7 @@ public void realForward(float[] a) { * * @param a data to transform */ + /* public void realForward(FloatLargeArray a) { if (isPowerOfTwo == false) { throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); @@ -1269,7 +1278,7 @@ public void realForward(FloatLargeArray a) { rdft3d_sub(1, a); } } - } + } */ /** * Computes 3D forward DFT of real data leaving the result in a @@ -1371,6 +1380,7 @@ public void realForwardFull(float[] a) { * * @param a data to transform */ + /* public void realForwardFull(FloatLargeArray a) { if (isPowerOfTwo) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -1388,6 +1398,7 @@ public void realForwardFull(FloatLargeArray a) { mixedRadixRealForwardFull(a); } } + */ /** * Computes 3D forward DFT of real data leaving the result in a @@ -1538,6 +1549,7 @@ public void realInverse(float[] a, boolean scale) { * * @param scale if true then scaling is performed */ + /* public void realInverse(FloatLargeArray a, boolean scale) { if (isPowerOfTwo == false) { throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); @@ -1553,7 +1565,7 @@ public void realInverse(FloatLargeArray a, boolean scale) { xdft3da_sub1(1, 1, a, scale); } } - } + } */ /** * Computes 3D inverse DFT of real data leaving the result in a @@ -1653,6 +1665,7 @@ public void realInverseFull(float[] a, boolean scale) { * @param a data to transform * @param scale if true then scaling is performed */ + /* public void realInverseFull(FloatLargeArray a, boolean scale) { if (isPowerOfTwo) { int nthreads = ConcurrencyUtils.getNumberOfThreads(); @@ -1669,7 +1682,7 @@ public void realInverseFull(FloatLargeArray a, boolean scale) { } else { mixedRadixRealInverseFull(a, scale); } - } + } */ /** * Computes 3D inverse DFT of real data leaving the result in a @@ -2288,7 +2301,7 @@ public void run() { } } - + /* private void mixedRadixRealForwardFull(final FloatLargeArray a) { final long twon3 = 2 * columnsl; FloatLargeArray temp = new FloatLargeArray(twon3, false); @@ -2530,7 +2543,7 @@ public void run() { } } - } + } */ private void mixedRadixRealInverseFull(final float[] a, final boolean scale) { final int twon3 = 2 * columns; @@ -2777,6 +2790,7 @@ public void run() { } } + /* private void mixedRadixRealInverseFull(final FloatLargeArray a, final boolean scale) { final long twon3 = 2 * columnsl; FloatLargeArray temp = new FloatLargeArray(twon3, false); @@ -3020,7 +3034,7 @@ public void run() { } } - } + } */ private void xdft3da_sub1(int icr, int isgn, float[] a, boolean scale) { int idx0, idx1, idx2, idx3, idx4, idx5; @@ -3211,6 +3225,7 @@ private void xdft3da_sub1(int icr, int isgn, float[] a, boolean scale) { } } + /* private void xdft3da_sub1(long icr, int isgn, FloatLargeArray a, boolean scale) { long idx0, idx1, idx2, idx3, idx4, idx5; long nt = slicesl; @@ -3398,7 +3413,7 @@ private void xdft3da_sub1(long icr, int isgn, FloatLargeArray a, boolean scale) } } } - } + } */ private void xdft3da_sub2(int icr, int isgn, float[] a, boolean scale) { int idx0, idx1, idx2, idx3, idx4, idx5; @@ -3588,6 +3603,7 @@ private void xdft3da_sub2(int icr, int isgn, float[] a, boolean scale) { } } + /* private void xdft3da_sub2(long icr, int isgn, FloatLargeArray a, boolean scale) { long idx0, idx1, idx2, idx3, idx4, idx5; long nt = slicesl; @@ -3774,7 +3790,7 @@ private void xdft3da_sub2(long icr, int isgn, FloatLargeArray a, boolean scale) } } } - } + } */ private void xdft3da_sub1(int icr, int isgn, float[][][] a, boolean scale) { int idx2, idx3, idx4, idx5; @@ -4307,6 +4323,7 @@ private void cdft3db_sub(int isgn, float[] a, boolean scale) { } } + /* private void cdft3db_sub(int isgn, FloatLargeArray a, boolean scale) { long idx0, idx1, idx2, idx3, idx4, idx5; long nt = slicesl; @@ -4487,7 +4504,7 @@ private void cdft3db_sub(int isgn, FloatLargeArray a, boolean scale) { } } } - } + } */ private void cdft3db_sub(int isgn, float[][][] a, boolean scale) { int idx2, idx3, idx4, idx5; @@ -4855,6 +4872,7 @@ public void run() { ConcurrencyUtils.waitForCompletion(futures); } + /* private void xdft3da_subth1(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { int i; final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), slicesl); @@ -5055,7 +5073,7 @@ public void run() { }); } ConcurrencyUtils.waitForCompletion(futures); - } + } */ private void xdft3da_subth2(final int icr, final int isgn, final float[] a, final boolean scale) { int i; @@ -5258,6 +5276,7 @@ public void run() { ConcurrencyUtils.waitForCompletion(futures); } + /* private void xdft3da_subth2(final long icr, final int isgn, final FloatLargeArray a, final boolean scale) { int i; final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), slicesl); @@ -5457,7 +5476,7 @@ public void run() { }); } ConcurrencyUtils.waitForCompletion(futures); - } + } */ private void xdft3da_subth1(final int icr, final int isgn, final float[][][] a, final boolean scale) { int i; @@ -5832,7 +5851,7 @@ public void run() { }); } ConcurrencyUtils.waitForCompletion(futures); - } + } private void cdft3db_subth(final int isgn, final float[] a, final boolean scale) { int i; @@ -6030,6 +6049,7 @@ public void run() { ConcurrencyUtils.waitForCompletion(futures); } + /* private void cdft3db_subth(final int isgn, final FloatLargeArray a, final boolean scale) { int i; final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), rowsl); @@ -6224,7 +6244,7 @@ public void run() { }); } ConcurrencyUtils.waitForCompletion(futures); - } + } */ private void cdft3db_subth(final int isgn, final float[][][] a, final boolean scale) { int i; @@ -6517,6 +6537,7 @@ private void rdft3d_sub(int isgn, float[] a) { } } + /* private void rdft3d_sub(int isgn, FloatLargeArray a) { long n1h, n2h, i, j, k, l, idx1, idx2, idx3, idx4; float xi; @@ -6628,7 +6649,7 @@ private void rdft3d_sub(int isgn, FloatLargeArray a) { a.setFloat(idx4 + 1, a.getFloat(idx4 + 1) - a.getFloat(idx3 + 1)); } } - } + } */ private void rdft3d_sub(int isgn, float[][][] a) { int n1h, n2h, i, j, k, l; @@ -7057,6 +7078,7 @@ public void run() { a[idx3 + columns + 1] = 0; } + /* private void fillSymmetric(final FloatLargeArray a) { final long twon3 = 2 * columnsl; final long n2d2 = rowsl / 2; @@ -7258,5 +7280,5 @@ public void run() { a.setFloat(idx3 + 1, 0); a.setFloat(idx2 + columnsl + 1, 0); a.setFloat(idx3 + columnsl + 1, 0); - } + } */ } diff --git a/pom.xml b/pom.xml index 09b080a..e70184a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,26 +1,30 @@ - - - 4.0.0 - com.github.wendykierp - JTransforms - 3.1-SNAPSHOT - jar - - https://github.com/wendykierp/JTransforms - - - org.sonatype.oss - oss-parent - 9 - - - - - BSD 2-Clause - http://opensource.org/licenses/BSD-2-Clause - repo - - + + 4.0.0 + + + utf-8 + + + org.fairsim + jtransforms_fairSIM_fork + 1.0.0 + jar + + fairSIMs JTransforms fork + + http://www.fairsim.org + 2017 + + + + BSD 2-Clause + http://opensource.org/licenses/BSD-2-Clause + repo + + @@ -30,58 +34,134 @@ +1 - - - - - junit - junit - 4.11 - test - - - pl.edu.icm - JLargeArrays - [1.2,) - - - - - - UTF-8 - 1.6 - 1.6 - -Xdoclint:none - github - - - - - - test/resouces - - **/*.in - **/*.out - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - false - - - - - - - scm:git:ssh://git@github.com/wendykierp/JTransforms.git - scm:git:ssh://git@github.com/wendykierp/JTransforms.git - https://github.com/wendykierp/JTransforms - HEAD - - - \ No newline at end of file + + + + + Marcel Müller + muellerphysics@gmail.com + + + + + scm:git:git://github.com/fairSIM/JTransforms + scm:git:git@github.com:fairSIM/JTransforms + HEAD + http://github.com/fairSIM/JTransforms + + + GitHub Issues + http://github.com/fairSIM/JTransforms/issues + + + + + + + + ${project.artifactId}_mvn-${buildNumber} + + ./ + + + + ./ + true + + org/fairsim/git-version-jtransforms-maven.txt + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 2.3.2 + + 1.6 + 1.6 + + + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.4 + + + validate + + create + + + + + false + false + 10 + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + true + + org/fairsim/**/*.java + org/fairsim/resources/* + + + target + + + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + true + + + + + + + + + diff --git a/src/main/java/org/jtransforms/dct/BenchmarkDoubleDCT.java b/src/main/java/org/jtransforms/dct/BenchmarkDoubleDCT.java deleted file mode 100644 index 164148c..0000000 --- a/src/main/java/org/jtransforms/dct/BenchmarkDoubleDCT.java +++ /dev/null @@ -1,332 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Benchmark of double precision DCT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkDoubleDCT -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkDoubleDCT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDCT_1D dct = new DoubleDCT_1D(sizes1D[i]); - x = new double[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDCT_1D dct = new DoubleDCT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes1D[i]]; - if (doWarmup) { // call the transform twice to warm up - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - } - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dct.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDCT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDCT_2D dct2 = new DoubleDCT_2D(sizes2D[i], sizes2D[i]); - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDCT_2D dct2 = new DoubleDCT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dct2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDCT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDCT_2D dct2 = new DoubleDCT_2D(sizes2D[i], sizes2D[i]); - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDCT_2D dct2 = new DoubleDCT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dct2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDCT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDCT_3D dct3 = new DoubleDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDCT_3D dct3 = new DoubleDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dct3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDCT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDCT_3D dct3 = new DoubleDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDCT_3D dct3 = new DoubleDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dct3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDCT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dct/BenchmarkFloatDCT.java b/src/main/java/org/jtransforms/dct/BenchmarkFloatDCT.java deleted file mode 100644 index 428da5a..0000000 --- a/src/main/java/org/jtransforms/dct/BenchmarkFloatDCT.java +++ /dev/null @@ -1,326 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Benchmark of single precision DCT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkFloatDCT -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkFloatDCT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDCT_1D dct = new FloatDCT_1D(sizes1D[i]); - x = new float[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dct.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDCT_1D dct = new FloatDCT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes1D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dct.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDCT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDCT_2D dct2 = new FloatDCT_2D(sizes2D[i], sizes2D[i]); - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDCT_2D dct2 = new FloatDCT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dct2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDCT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDCT_2D dct2 = new FloatDCT_2D(sizes2D[i], sizes2D[i]); - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dct2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDCT_2D dct2 = new FloatDCT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dct2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDCT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDCT_3D dct3 = new FloatDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDCT_3D dct3 = new FloatDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dct3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDCT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DCT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDCT_3D dct3 = new FloatDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dct3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDCT_3D dct3 = new FloatDCT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dct3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dct3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDCT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dct/DoubleDCT_1D.java b/src/main/java/org/jtransforms/dct/DoubleDCT_1D.java deleted file mode 100644 index 34c96e8..0000000 --- a/src/main/java/org/jtransforms/dct/DoubleDCT_1D.java +++ /dev/null @@ -1,641 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.fft.DoubleFFT_1D; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.LongLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Cosine Transform (DCT) of double precision data. The - * size of data can be an arbitrary number. This is a parallel implementation of - * split-radix and mixed-radix algorithms optimized for SMP systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDCT_1D -{ - - private int n; - - private long nl; - - private int[] ip; - - private LongLargeArray ipl; - - private double[] w; - - private DoubleLargeArray wl; - - private int nw; - - private long nwl; - - private int nc; - - private long ncl; - - private boolean isPowerOfTwo = false; - - private DoubleFFT_1D fft; - - private static final double PI = 3.14159265358979311599796346854418516; - - private boolean useLargeArrays; - - /** - * Creates new instance of DoubleDCT_1D. - * - * @param n size of data - */ - public DoubleDCT_1D(long n) - { - if (n < 1) { - throw new IllegalArgumentException("n must be greater than 0"); - } - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - - if (!useLargeArrays) { - if (n > (1 << 28)) { - throw new IllegalArgumentException("n must be smaller or equal to " + (1 << 28) + " when useLargeArrays argument is set to false"); - } - this.n = (int) n; - if (ConcurrencyUtils.isPowerOf2(n)) { - this.isPowerOfTwo = true; - this.ip = new int[(int) Math.ceil(2 + (1 << (int) (Math.log(n / 2 + 0.5) / Math.log(2)) / 2))]; - this.w = new double[this.n * 5 / 4]; - nw = ip[0]; - if (n > (nw << 2)) { - nw = this.n >> 2; - CommonUtils.makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = this.n; - CommonUtils.makect(nc, w, nw, ip); - } - } else { - this.w = makect(this.n); - fft = new DoubleFFT_1D(2 * n); - } - } else { - this.nl = n; - if (ConcurrencyUtils.isPowerOf2(n)) { - this.isPowerOfTwo = true; - this.ipl = new LongLargeArray((long) Math.ceil(2 + (1l << (long) (Math.log(n / 2 + 0.5) / Math.log(2)) / 2)), false); - this.wl = new DoubleLargeArray(this.nl * 5l / 4l, false); - nwl = ipl.getLong(0); - if (n > (nwl << 2l)) { - nwl = this.nl >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - } - ncl = ipl.getLong(1); - if (n > ncl) { - ncl = this.nl; - CommonUtils.makect(ncl, wl, nwl, ipl); - } - } else { - this.wl = makect(n); - fft = new DoubleFFT_1D(2 * n); - } - } - - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(double[] a, boolean scale) - { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(DoubleLargeArray a, boolean scale) - { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final int offa, boolean scale) - { - if (n == 1) { - return; - } - if (useLargeArrays) { - forward(new DoubleLargeArray(a), offa, scale); - } else { - if (isPowerOfTwo) { - double xr = a[offa + n - 1]; - for (int j = n - 2; j >= 2; j -= 2) { - a[offa + j + 1] = a[offa + j] - a[offa + j - 1]; - a[offa + j] += a[offa + j - 1]; - } - a[offa + 1] = a[offa] - xr; - a[offa] += xr; - if (n > 4) { - rftbsub(n, a, offa, nc, w, nw); - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } else if (n == 4) { - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } - CommonUtils.dctsub(n, a, offa, nc, w, nw); - if (scale) { - CommonUtils.scale(n, Math.sqrt(2.0 / n), a, offa, false); - a[offa] = a[offa] / Math.sqrt(2.0); - } - } else { - final int twon = 2 * n; - final double[] t = new double[twon]; - System.arraycopy(a, offa, t, 0, n); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - for (int i = n; i < twon; i++) { - t[i] = t[twon - i - 1]; - } - fft.realForward(t); - if ((nthreads > 1) && (n > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = n / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? n : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstIdx; i < lastIdx; i++) { - int twoi = 2 * i; - int idx = offa + i; - a[idx] = w[twoi] * t[twoi] - w[twoi + 1] * t[twoi + 1]; - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < n; i++) { - int twoi = 2 * i; - int idx = offa + i; - a[idx] = w[twoi] * t[twoi] - w[twoi + 1] * t[twoi + 1]; - } - } - if (scale) { - CommonUtils.scale(n, 1 / Math.sqrt(twon), a, offa, false); - a[offa] = a[offa] / Math.sqrt(2.0); - } - } - } - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final long offa, boolean scale) - { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (isPowerOfTwo) { - double xr = a.getDouble(offa + nl - 1); - for (long j = nl - 2; j >= 2; j -= 2) { - a.setDouble(offa + j + 1, a.getDouble(offa + j) - a.getDouble(offa + j - 1)); - a.setDouble(offa + j, a.getDouble(offa + j) + a.getDouble(offa + j - 1)); - } - a.setDouble(offa + 1, a.getDouble(offa) - xr); - a.setDouble(offa, a.getDouble(offa) + xr); - if (nl > 4) { - rftbsub(nl, a, offa, ncl, wl, nwl); - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } else if (nl == 4) { - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } - CommonUtils.dctsub(nl, a, offa, ncl, wl, nwl); - if (scale) { - CommonUtils.scale(nl, Math.sqrt(2.0 / nl), a, offa, false); - a.setDouble(offa, a.getDouble(offa) / Math.sqrt(2.0)); - } - } else { - final long twon = 2 * nl; - final DoubleLargeArray t = new DoubleLargeArray(twon, false); - Utilities.arraycopy(a, offa, t, 0, nl); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - for (long i = nl; i < twon; i++) { - t.setDouble(i, t.getDouble(twon - i - 1)); - } - fft.realForward(t); - if ((nthreads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nl / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nl : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstIdx; i < lastIdx; i++) { - long twoi = 2 * i; - long idx = offa + i; - a.setDouble(idx, wl.getDouble(twoi) * t.getDouble(twoi) - wl.getDouble(twoi + 1) * t.getDouble(twoi + 1)); - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < nl; i++) { - long twoi = 2 * i; - long idx = offa + i; - a.setDouble(idx, wl.getDouble(twoi) * t.getDouble(twoi) - wl.getDouble(twoi + 1) * t.getDouble(twoi + 1)); - } - } - if (scale) { - CommonUtils.scale(nl, 1 / Math.sqrt(twon), a, offa, false); - a.setDouble(offa, a.getDouble(offa) / Math.sqrt(2.0)); - } - } - } - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(double[] a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(DoubleLargeArray a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final int offa, boolean scale) - { - if (n == 1) { - return; - } - if (useLargeArrays) { - inverse(new DoubleLargeArray(a), offa, scale); - } else { - if (isPowerOfTwo) { - double xr; - if (scale) { - CommonUtils.scale(n, Math.sqrt(2.0 / n), a, offa, false); - a[offa] = a[offa] / Math.sqrt(2.0); - } - CommonUtils.dctsub(n, a, offa, nc, w, nw); - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - rftfsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - } - xr = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - for (int j = 2; j < n; j += 2) { - a[offa + j - 1] = a[offa + j] - a[offa + j + 1]; - a[offa + j] += a[offa + j + 1]; - } - a[offa + n - 1] = xr; - } else { - final int twon = 2 * n; - if (scale) { - CommonUtils.scale(n, Math.sqrt(twon), a, offa, false); - a[offa] = a[offa] * Math.sqrt(2.0); - } - final double[] t = new double[twon]; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = n / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? n : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstIdx; i < lastIdx; i++) { - int twoi = 2 * i; - double elem = a[offa + i]; - t[twoi] = w[twoi] * elem; - t[twoi + 1] = -w[twoi + 1] * elem; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < n; i++) { - int twoi = 2 * i; - double elem = a[offa + i]; - t[twoi] = w[twoi] * elem; - t[twoi + 1] = -w[twoi + 1] * elem; - } - } - fft.realInverse(t, true); - System.arraycopy(t, 0, a, offa, n); - } - } - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final long offa, boolean scale) - { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (isPowerOfTwo) { - double xr; - if (scale) { - CommonUtils.scale(nl, Math.sqrt(2.0 / nl), a, offa, false); - a.setDouble(offa, a.getDouble(offa) / Math.sqrt(2.0)); - } - CommonUtils.dctsub(nl, a, offa, ncl, wl, nwl); - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - rftfsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - } - xr = a.getDouble(offa) - a.getDouble(offa + 1); - a.setDouble(offa, a.getDouble(offa) + a.getDouble(offa + 1)); - for (long j = 2; j < nl; j += 2) { - a.setDouble(offa + j - 1, a.getDouble(offa + j) - a.getDouble(offa + j + 1)); - a.setDouble(offa + j, a.getDouble(offa + j) + a.getDouble(offa + j + 1)); - } - a.setDouble(offa + nl - 1, xr); - } else { - final long twon = 2 * nl; - if (scale) { - CommonUtils.scale(nl, Math.sqrt(twon), a, offa, false); - a.setDouble(offa, a.getDouble(offa) * Math.sqrt(2.0)); - } - final DoubleLargeArray t = new DoubleLargeArray(twon, false); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nl / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nl : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstIdx; i < lastIdx; i++) { - long twoi = 2 * i; - double elem = a.getDouble(offa + i); - t.setDouble(twoi, wl.getDouble(twoi) * elem); - t.setDouble(twoi + 1, -wl.getDouble(twoi + 1) * elem); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < nl; i++) { - long twoi = 2 * i; - double elem = a.getDouble(offa + i); - t.setDouble(twoi, wl.getDouble(twoi) * elem); - t.setDouble(twoi + 1, -wl.getDouble(twoi + 1) * elem); - } - } - fft.realInverse(t, true); - Utilities.arraycopy(t, 0, a, offa, nl); - } - } - } - - /* -------- initializing routines -------- */ - private double[] makect(int n) - { - int twon = 2 * n; - int idx; - double delta = PI / twon; - double deltaj; - double[] c = new double[twon]; - c[0] = 1; - for (int j = 1; j < n; j++) { - idx = 2 * j; - deltaj = delta * j; - c[idx] = Math.cos(deltaj); - c[idx + 1] = -Math.sin(deltaj); - } - return c; - } - - private DoubleLargeArray makect(long n) - { - long twon = 2 * n; - long idx; - double delta = PI / twon; - double deltaj; - DoubleLargeArray c = new DoubleLargeArray(twon, false); - c.setDouble(0, 1); - for (long j = 1; j < n; j++) { - idx = 2 * j; - deltaj = delta * j; - c.setDouble(idx, Math.cos(deltaj)); - c.setDouble(idx + 1, -Math.sin(deltaj)); - } - return c; - } - - private static void rftfsub(int n, double[] a, int offa, int nc, double[] c, int startc) - { - int k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - int idx1, idx2; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (int j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[startc + nc - kk]; - wki = c[startc + kk]; - idx1 = offa + j; - idx2 = offa + k; - xr = a[idx1] - a[idx2]; - xi = a[idx1 + 1] + a[idx2 + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[idx1] -= yr; - a[idx1 + 1] -= yi; - a[idx2] += yr; - a[idx2 + 1] -= yi; - } - } - - private static void rftfsub(long n, DoubleLargeArray a, long offa, long nc, DoubleLargeArray c, long startc) - { - long k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - long idx1, idx2; - m = n >> 1l; - ks = 2 * nc / m; - kk = 0; - for (long j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c.getDouble(startc + nc - kk); - wki = c.getDouble(startc + kk); - idx1 = offa + j; - idx2 = offa + k; - xr = a.getDouble(idx1) - a.getDouble(idx2); - xi = a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1); - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a.setDouble(idx1, a.getDouble(idx1) - yr); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) - yi); - a.setDouble(idx2, a.getDouble(idx2) + yr); - a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - yi); - } - } - - private static void rftbsub(int n, double[] a, int offa, int nc, double[] c, int startc) - { - int k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - int idx1, idx2; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (int j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c[startc + nc - kk]; - wki = c[startc + kk]; - idx1 = offa + j; - idx2 = offa + k; - xr = a[idx1] - a[idx2]; - xi = a[idx1 + 1] + a[idx2 + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[idx1] -= yr; - a[idx1 + 1] -= yi; - a[idx2] += yr; - a[idx2 + 1] -= yi; - } - } - - private static void rftbsub(long n, DoubleLargeArray a, long offa, long nc, DoubleLargeArray c, long startc) - { - long k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - long idx1, idx2; - m = n >> 1l; - ks = 2 * nc / m; - kk = 0; - for (long j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5 - c.getDouble(startc + nc - kk); - wki = c.getDouble(startc + kk); - idx1 = offa + j; - idx2 = offa + k; - xr = a.getDouble(idx1) - a.getDouble(idx2); - xi = a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1); - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a.setDouble(idx1, a.getDouble(idx1) - yr); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) - yi); - a.setDouble(idx2, a.getDouble(idx2) + yr); - a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - yi); - } - } -} diff --git a/src/main/java/org/jtransforms/dct/DoubleDCT_2D.java b/src/main/java/org/jtransforms/dct/DoubleDCT_2D.java deleted file mode 100644 index 452de2d..0000000 --- a/src/main/java/org/jtransforms/dct/DoubleDCT_2D.java +++ /dev/null @@ -1,1107 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 2D Discrete Cosine Transform (DCT) of double precision data. The - * sizes of both dimensions can be arbitrary numbers. This is a parallel - * implementation of split-radix and mixed-radix algorithms optimized for SMP - * systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - * - */ -public class DoubleDCT_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private DoubleDCT_1D dctColumns, dctRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDCT_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDCT_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dctRows = new DoubleDCT_1D(rows); - if (rows == columns) { - dctColumns = dctRows; - } else { - dctColumns = new DoubleDCT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.forward(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - dctColumns.forward(a, r * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.forward(a, i * columns, scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (long i = 0; i < rowsl; i++) { - dctColumns.forward(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - dctColumns.forward(a, r * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dctColumns.forward(a, i * columnsl, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - } - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.forward(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.forward(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.forward(a[i], scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a, i * columns, scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[r], scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - private void ddxt2d_subth(final int isgn, final double[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final long nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.inverse(t, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final double[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.forward(a, r * columns, scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dctColumns.forward(a, r * columnsl, scale); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - dctColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.forward(a[r], scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, double[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1l; - } else if (columnsl < 2) { - nt >>= 2l; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, double[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } -} diff --git a/src/main/java/org/jtransforms/dct/DoubleDCT_3D.java b/src/main/java/org/jtransforms/dct/DoubleDCT_3D.java deleted file mode 100644 index 2dccd44..0000000 --- a/src/main/java/org/jtransforms/dct/DoubleDCT_3D.java +++ /dev/null @@ -1,2092 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 3D Discrete Cosine Transform (DCT) of double precision data. The - * sizes of all three dimensions can be arbitrary numbers. This is a parallel - * implementation of split-radix and mixed-radix algorithms optimized for SMP - * systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDCT_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private DoubleDCT_1D dctSlices, dctRows, dctColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDCT_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDCT_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dctSlices = new DoubleDCT_1D(slices); - if (slices == rows) { - dctRows = dctSlices; - } else { - dctRows = new DoubleDCT_1D(rows); - } - if (slices == columns) { - dctColumns = dctSlices; - } else if (rows == columns) { - dctColumns = dctRows; - } else { - dctColumns = new DoubleDCT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dctSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dctSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - } - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 3D array - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dctSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dctSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - private void ddxt3da_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - dctSlices.forward(t, 2 * slicesl, scale); - dctSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - dctSlices.inverse(t, 2 * slicesl, scale); - dctSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - Future[] futures = new Future[nthreads]; - final int ntf = nt; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int j = 0; j < rows; j++) { - idx1 = idx0 + j * rowStride + c; - idx2 = rows + j; - t[j] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int j = 0; j < rows; j++) { - idx1 = idx0 + j * rowStride + c; - idx2 = rows + j; - a[idx1] = t[j]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - Future[] futures = new Future[nthreads]; - final long ntf = nt; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long j = 0; j < rowsl; j++) { - idx1 = idx0 + j * rowStridel + c; - idx2 = rowsl + j; - t.setDouble(j, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long j = 0; j < rowsl; j++) { - idx1 = idx0 + j * rowStridel + c; - idx2 = rowsl + j; - a.setDouble(idx1, t.getDouble(j)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - dctSlices.forward(t, 2 * slicesl, scale); - dctSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - dctSlices.inverse(t, 2 * slicesl, scale); - dctSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } -} diff --git a/src/main/java/org/jtransforms/dct/FloatDCT_1D.java b/src/main/java/org/jtransforms/dct/FloatDCT_1D.java deleted file mode 100644 index 5bf38e3..0000000 --- a/src/main/java/org/jtransforms/dct/FloatDCT_1D.java +++ /dev/null @@ -1,658 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.fft.FloatFFT_1D; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; -import pl.edu.icm.jlargearrays.LongLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Cosine Transform (DCT) of single precision data. The - * size of data can be an arbitrary number. This is a parallel implementation of - * split-radix and mixed-radix algorithms optimized for SMP systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by Takuya Ooura - * (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDCT_1D -{ - - private int n; - - private long nl; - - private int[] ip; - - private LongLargeArray ipl; - - private float[] w; - - private FloatLargeArray wl; - - private int nw; - - private long nwl; - - private int nc; - - private long ncl; - - private boolean isPowerOfTwo = false; - - private FloatFFT_1D fft; - - private static final float PI = 3.14159265358979311599796346854418516f; - - private boolean useLargeArrays; - - /** - * Creates new instance of FloatDCT_1D. - * - * @param n size of data - * - */ - public FloatDCT_1D(long n) - { - if (n < 1) { - throw new IllegalArgumentException("n must be greater than 0"); - } - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - - if (!useLargeArrays) { - if (n > (1 << 28)) { - throw new IllegalArgumentException("n must be smaller or equal to " + (1 << 28) + " when useLargeArrays argument is set to false"); - } - this.n = (int) n; - if (ConcurrencyUtils.isPowerOf2(n)) { - this.isPowerOfTwo = true; - this.ip = new int[(int) Math.ceil(2 + (1 << (int) (Math.log(n / 2 + 0.5) / Math.log(2)) / 2))]; - this.w = new float[this.n * 5 / 4]; - nw = ip[0]; - if (n > (nw << 2)) { - nw = this.n >> 2; - CommonUtils.makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = this.n; - CommonUtils.makect(nc, w, nw, ip); - } - } else { - this.w = makect(this.n); - fft = new FloatFFT_1D(2 * n); - } - } else { - this.nl = n; - if (ConcurrencyUtils.isPowerOf2(n)) { - this.isPowerOfTwo = true; - this.ipl = new LongLargeArray((long) Math.ceil(2 + (1l << (long) (Math.log(n / 2 + 0.5) / Math.log(2)) / 2)), false); - this.wl = new FloatLargeArray(this.nl * 5l / 4l, false); - nwl = ipl.getLong(0); - if (n > (nwl << 2l)) { - nwl = this.nl >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - } - ncl = ipl.getLong(1); - if (n > ncl) { - ncl = this.nl; - CommonUtils.makect(ncl, wl, nwl, ipl); - } - } else { - this.wl = makect(n); - fft = new FloatFFT_1D(2 * n); - } - } - - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void forward(float[] a, boolean scale) - { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void forward(FloatLargeArray a, boolean scale) - { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void forward(final float[] a, final int offa, boolean scale) - { - if (n == 1) - return; - if (useLargeArrays) { - forward(new FloatLargeArray(a), offa, scale); - } else { - if (isPowerOfTwo) { - float xr = a[offa + n - 1]; - for (int j = n - 2; j >= 2; j -= 2) { - a[offa + j + 1] = a[offa + j] - a[offa + j - 1]; - a[offa + j] += a[offa + j - 1]; - } - a[offa + 1] = a[offa] - xr; - a[offa] += xr; - if (n > 4) { - rftbsub(n, a, offa, nc, w, nw); - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } else if (n == 4) { - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } - CommonUtils.dctsub(n, a, offa, nc, w, nw); - if (scale) { - CommonUtils.scale(n, (float)Math.sqrt(2.0 / n), a, offa, false); - a[offa] = a[offa] / (float)Math.sqrt(2.0); - } - } else { - final int twon = 2 * n; - final float[] t = new float[twon]; - System.arraycopy(a, offa, t, 0, n); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - for (int i = n; i < twon; i++) { - t[i] = t[twon - i - 1]; - } - fft.realForward(t); - if ((nthreads > 1) && (n > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = n / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? n : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstIdx; i < lastIdx; i++) { - int twoi = 2 * i; - int idx = offa + i; - a[idx] = w[twoi] * t[twoi] - w[twoi + 1] * t[twoi + 1]; - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < n; i++) { - int twoi = 2 * i; - int idx = offa + i; - a[idx] = w[twoi] * t[twoi] - w[twoi + 1] * t[twoi + 1]; - } - } - if (scale) { - CommonUtils.scale(n, 1 / (float)Math.sqrt(twon), a, offa, false); - a[offa] = a[offa] / (float)Math.sqrt(2.0); - } - } - } - } - - /** - * Computes 1D forward DCT (DCT-II) leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final long offa, boolean scale) - { - if (nl == 1) - return; - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (isPowerOfTwo) { - float xr = a.getFloat(offa + nl - 1); - for (long j = nl - 2; j >= 2; j -= 2) { - a.setFloat(offa + j + 1, a.getFloat(offa + j) - a.getFloat(offa + j - 1)); - a.setFloat(offa + j, a.getFloat(offa + j) + a.getFloat(offa + j - 1)); - } - a.setFloat(offa + 1, a.getFloat(offa) - xr); - a.setFloat(offa, a.getFloat(offa) + xr); - if (nl > 4) { - rftbsub(nl, a, offa, ncl, wl, nwl); - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } else if (nl == 4) { - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } - CommonUtils.dctsub(nl, a, offa, ncl, wl, nwl); - if (scale) { - CommonUtils.scale(nl, (float)Math.sqrt(2.0 / nl), a, offa, false); - a.setFloat(offa, a.getFloat(offa) / (float)Math.sqrt(2.0)); - } - } else { - final long twon = 2 * nl; - final FloatLargeArray t = new FloatLargeArray(twon, false); - Utilities.arraycopy(a, offa, t, 0, nl); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - for (long i = nl; i < twon; i++) { - t.setFloat(i, t.getFloat(twon - i - 1)); - } - fft.realForward(t); - if ((nthreads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nl / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nl : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstIdx; i < lastIdx; i++) { - long twoi = 2 * i; - long idx = offa + i; - a.setFloat(idx, wl.getFloat(twoi) * t.getFloat(twoi) - wl.getFloat(twoi + 1) * t.getFloat(twoi + 1)); - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < nl; i++) { - long twoi = 2 * i; - long idx = offa + i; - a.setFloat(idx, wl.getFloat(twoi) * t.getFloat(twoi) - wl.getFloat(twoi + 1) * t.getFloat(twoi + 1)); - } - } - if (scale) { - CommonUtils.scale(nl, 1 / (float)Math.sqrt(twon), a, offa, false); - a.setFloat(offa, a.getFloat(offa) / (float)Math.sqrt(2.0)); - } - } - } - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void inverse(float[] a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void inverse(FloatLargeArray a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void inverse(final float[] a, final int offa, boolean scale) - { - if (n == 1) - return; - if (useLargeArrays) { - inverse(new FloatLargeArray(a), offa, scale); - } else { - if (isPowerOfTwo) { - float xr; - if (scale) { - CommonUtils.scale(n, (float)Math.sqrt(2.0 / n), a, offa, false); - a[offa] = a[offa] / (float)Math.sqrt(2.0); - } - CommonUtils.dctsub(n, a, offa, nc, w, nw); - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - rftfsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - } - xr = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - for (int j = 2; j < n; j += 2) { - a[offa + j - 1] = a[offa + j] - a[offa + j + 1]; - a[offa + j] += a[offa + j + 1]; - } - a[offa + n - 1] = xr; - } else { - final int twon = 2 * n; - if (scale) { - CommonUtils.scale(n, (float)Math.sqrt(twon), a, offa, false); - a[offa] = a[offa] * (float)Math.sqrt(2.0); - } - final float[] t = new float[twon]; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = n / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? n : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstIdx; i < lastIdx; i++) { - int twoi = 2 * i; - float elem = a[offa + i]; - t[twoi] = w[twoi] * elem; - t[twoi + 1] = -w[twoi + 1] * elem; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < n; i++) { - int twoi = 2 * i; - float elem = a[offa + i]; - t[twoi] = w[twoi] * elem; - t[twoi + 1] = -w[twoi + 1] * elem; - } - } - fft.realInverse(t, true); - System.arraycopy(t, 0, a, offa, n); - } - } - } - - /** - * Computes 1D inverse DCT (DCT-III) leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final long offa, boolean scale) - { - if (nl == 1) - return; - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (isPowerOfTwo) { - float xr; - if (scale) { - CommonUtils.scale(nl, (float)Math.sqrt(2.0 / nl), a, offa, false); - a.setFloat(offa, a.getFloat(offa) / (float)Math.sqrt(2.0)); - } - CommonUtils.dctsub(nl, a, offa, ncl, wl, nwl); - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - rftfsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - } - xr = a.getFloat(offa) - a.getFloat(offa + 1); - a.setFloat(offa, a.getFloat(offa) + a.getFloat(offa + 1)); - for (long j = 2; j < nl; j += 2) { - a.setFloat(offa + j - 1, a.getFloat(offa + j) - a.getFloat(offa + j + 1)); - a.setFloat(offa + j, a.getFloat(offa + j) + a.getFloat(offa + j + 1)); - } - a.setFloat(offa + nl - 1, xr); - } else { - final long twon = 2 * nl; - if (scale) { - CommonUtils.scale(nl, (float)Math.sqrt(twon), a, offa, false); - a.setFloat(offa, a.getFloat(offa) * (float)Math.sqrt(2.0)); - } - final FloatLargeArray t = new FloatLargeArray(twon, false); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nl / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nl : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstIdx; i < lastIdx; i++) { - long twoi = 2 * i; - float elem = a.getFloat(offa + i); - t.setFloat(twoi, wl.getFloat(twoi) * elem); - t.setFloat(twoi + 1, -wl.getFloat(twoi + 1) * elem); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < nl; i++) { - long twoi = 2 * i; - float elem = a.getFloat(offa + i); - t.setFloat(twoi, wl.getFloat(twoi) * elem); - t.setFloat(twoi + 1, -wl.getFloat(twoi + 1) * elem); - } - } - fft.realInverse(t, true); - Utilities.arraycopy(t, 0, a, offa, nl); - } - } - } - - /* -------- initializing routines -------- */ - private float[] makect(int n) - { - int twon = 2 * n; - int idx; - float delta = PI / twon; - float deltaj; - float[] c = new float[twon]; - c[0] = 1; - for (int j = 1; j < n; j++) { - idx = 2 * j; - deltaj = delta * j; - c[idx] = (float)Math.cos(deltaj); - c[idx + 1] = -(float)Math.sin(deltaj); - } - return c; - } - - private FloatLargeArray makect(long n) - { - long twon = 2 * n; - long idx; - float delta = PI / twon; - float deltaj; - FloatLargeArray c = new FloatLargeArray(twon, false); - c.setFloat(0, 1); - for (long j = 1; j < n; j++) { - idx = 2 * j; - deltaj = delta * j; - c.setFloat(idx, (float)Math.cos(deltaj)); - c.setFloat(idx + 1, -(float)Math.sin(deltaj)); - } - return c; - } - - private static void rftfsub(int n, float[] a, int offa, int nc, float[] c, int startc) - { - int k, kk, ks, m; - float wkr, wki, xr, xi, yr, yi; - int idx1, idx2; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (int j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5f - c[startc + nc - kk]; - wki = c[startc + kk]; - idx1 = offa + j; - idx2 = offa + k; - xr = a[idx1] - a[idx2]; - xi = a[idx1 + 1] + a[idx2 + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[idx1] -= yr; - a[idx1 + 1] -= yi; - a[idx2] += yr; - a[idx2 + 1] -= yi; - } - } - - private static void rftfsub(long n, FloatLargeArray a, long offa, long nc, FloatLargeArray c, long startc) - { - long k, kk, ks, m; - float wkr, wki, xr, xi, yr, yi; - long idx1, idx2; - m = n >> 1l; - ks = 2 * nc / m; - kk = 0; - for (long j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5f - c.getFloat(startc + nc - kk); - wki = c.getFloat(startc + kk); - idx1 = offa + j; - idx2 = offa + k; - xr = a.getFloat(idx1) - a.getFloat(idx2); - xi = a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1); - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a.setFloat(idx1, a.getFloat(idx1) - yr); - a.setFloat(idx1 + 1, a.getFloat(idx1 + 1) - yi); - a.setFloat(idx2, a.getFloat(idx2) + yr); - a.setFloat(idx2 + 1, a.getFloat(idx2 + 1) - yi); - } - } - - private static void rftbsub(int n, float[] a, int offa, int nc, float[] c, int startc) - { - int k, kk, ks, m; - float wkr, wki, xr, xi, yr, yi; - int idx1, idx2; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (int j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5f - c[startc + nc - kk]; - wki = c[startc + kk]; - idx1 = offa + j; - idx2 = offa + k; - xr = a[idx1] - a[idx2]; - xi = a[idx1 + 1] + a[idx2 + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[idx1] -= yr; - a[idx1 + 1] -= yi; - a[idx2] += yr; - a[idx2 + 1] -= yi; - } - } - - private static void rftbsub(long n, FloatLargeArray a, long offa, long nc, FloatLargeArray c, long startc) - { - long k, kk, ks, m; - float wkr, wki, xr, xi, yr, yi; - long idx1, idx2; - m = n >> 1l; - ks = 2 * nc / m; - kk = 0; - for (long j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = 0.5f - c.getFloat(startc + nc - kk); - wki = c.getFloat(startc + kk); - idx1 = offa + j; - idx2 = offa + k; - xr = a.getFloat(idx1) - a.getFloat(idx2); - xi = a.getFloat(idx1 + 1) + a.getFloat(idx2 + 1); - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a.setFloat(idx1, a.getFloat(idx1) - yr); - a.setFloat(idx1 + 1, a.getFloat(idx1 + 1) - yi); - a.setFloat(idx2, a.getFloat(idx2) + yr); - a.setFloat(idx2 + 1, a.getFloat(idx2 + 1) - yi); - } - } -} diff --git a/src/main/java/org/jtransforms/dct/FloatDCT_2D.java b/src/main/java/org/jtransforms/dct/FloatDCT_2D.java deleted file mode 100644 index b451579..0000000 --- a/src/main/java/org/jtransforms/dct/FloatDCT_2D.java +++ /dev/null @@ -1,1106 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 2D Discrete Cosine Transform (DCT) of single precision data. The - * sizes of both dimensions can be arbitrary numbers. This is a parallel - * implementation of split-radix and mixed-radix algorithms optimized for SMP - * systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDCT_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private FloatDCT_1D dctColumns, dctRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDCT_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public FloatDCT_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dctRows = new FloatDCT_1D(rows); - if (rows == columns) { - dctColumns = dctRows; - } else { - dctColumns = new FloatDCT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.forward(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int r = firstRow; r < lastRow; r++) { - dctColumns.forward(a, r * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.forward(a, i * columns, scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (long i = 0; i < rowsl; i++) { - dctColumns.forward(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long r = firstRow; r < lastRow; r++) { - dctColumns.forward(a, r * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dctColumns.forward(a, i * columnsl, scale); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - } - } - - /** - * Computes 2D forward DCT (DCT-II) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.forward(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.forward(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.forward(a[i], scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a, i * columns, scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dctColumns.inverse(a, i * columnsl, scale); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - } - } - - /** - * Computes 2D inverse DCT (DCT-III) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dctColumns.inverse(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dctColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[r], scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - private void ddxt2d_subth(final int isgn, final float[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final long nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.inverse(t, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setFloat(idx2, a.getFloat(idx1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setFloat(idx1, t.getFloat(idx2)); - a.setFloat(idx1 + 1, t.getFloat(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final float[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthread]; - - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.forward(a, r * columns, scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dctColumns.forward(a, r * columnsl, scale); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - dctColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.forward(a[r], scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dctColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, float[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1l; - } else if (columnsl < 2) { - nt >>= 2l; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, float[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - } else { - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } -} diff --git a/src/main/java/org/jtransforms/dct/FloatDCT_3D.java b/src/main/java/org/jtransforms/dct/FloatDCT_3D.java deleted file mode 100644 index 272d0f9..0000000 --- a/src/main/java/org/jtransforms/dct/FloatDCT_3D.java +++ /dev/null @@ -1,2092 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 3D Discrete Cosine Transform (DCT) of single precision data. The - * sizes of all three dimensions can be arbitrary numbers. This is a parallel - * implementation of split-radix and mixed-radix algorithms optimized for SMP - * systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDCT_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private FloatDCT_1D dctSlices, dctRows, dctColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDCT_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public FloatDCT_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dctSlices = new FloatDCT_1D(slices); - if (slices == rows) { - dctRows = dctSlices; - } else { - dctRows = new FloatDCT_1D(rows); - } - if (slices == columns) { - dctColumns = dctSlices; - } else if (rows == columns) { - dctColumns = dctRows; - } else { - dctColumns = new FloatDCT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx1 + r * rowStride, scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dctSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dctRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dctSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - } - } - - /** - * Computes the 3D forward DCT (DCT-II) leaving the result in a - * . The data is stored in 3D array - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dctSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dctRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dctSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - } - } - - /** - * Computes the 3D inverse DCT (DCT-III) leaving the result in - * a. The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dctRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dctSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - private void ddxt3da_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - dctSlices.forward(t, 2 * slicesl, scale); - dctSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - dctSlices.inverse(t, 2 * slicesl, scale); - dctSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - Future[] futures = new Future[nthreads]; - final int ntf = nt; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int j = 0; j < rows; j++) { - idx1 = idx0 + j * rowStride + c; - idx2 = rows + j; - t[j] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int j = 0; j < rows; j++) { - idx1 = idx0 + j * rowStride + c; - idx2 = rows + j; - a[idx1] = t[j]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - Future[] futures = new Future[nthreads]; - final long ntf = nt; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - dctRows.forward(t, 2 * rowsl, scale); - dctRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dctColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long j = 0; j < rowsl; j++) { - idx1 = idx0 + j * rowStridel + c; - idx2 = rowsl + j; - t.setFloat(j, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - dctRows.inverse(t, 2 * rowsl, scale); - dctRows.inverse(t, 3 * rowsl, scale); - for (long j = 0; j < rowsl; j++) { - idx1 = idx0 + j * rowStridel + c; - idx2 = rowsl + j; - a.setFloat(idx1, t.getFloat(j)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dctColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - dctRows.forward(t, 2 * rows, scale); - dctRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.forward(t, 0, scale); - dctRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dctColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - dctRows.inverse(t, 2 * rows, scale); - dctRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dctRows.inverse(t, 0, scale); - dctRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - dctSlices.forward(t, 2 * slicesl, scale); - dctSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - dctSlices.inverse(t, 2 * slicesl, scale); - dctSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - dctSlices.forward(t, 2 * slices, scale); - dctSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.forward(t, 0, scale); - dctSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - dctSlices.inverse(t, 2 * slices, scale); - dctSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dctSlices.inverse(t, 0, scale); - dctSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } -} diff --git a/src/main/java/org/jtransforms/dct/package.html b/src/main/java/org/jtransforms/dct/package.html deleted file mode 100644 index 6a9f43d..0000000 --- a/src/main/java/org/jtransforms/dct/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Discrete Cosine Transforms. - - diff --git a/src/main/java/org/jtransforms/dht/BenchmarkDoubleDHT.java b/src/main/java/org/jtransforms/dht/BenchmarkDoubleDHT.java deleted file mode 100644 index 26d13b0..0000000 --- a/src/main/java/org/jtransforms/dht/BenchmarkDoubleDHT.java +++ /dev/null @@ -1,326 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Benchmark of double precision DHT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkDoubleDHT -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkDoubleDHT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDHT_1D dht = new DoubleDHT_1D(sizes1D[i]); - x = new double[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dht.forward(x); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dht.forward(x); - } - long elapsedTime = System.nanoTime(); - DoubleDHT_1D dht = new DoubleDHT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes1D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dht.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDHT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDHT_2D dht2 = new DoubleDHT_2D(sizes2D[i], sizes2D[i]); - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - } - long elapsedTime = System.nanoTime(); - DoubleDHT_2D dht2 = new DoubleDHT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dht2.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDHT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDHT_2D dht2 = new DoubleDHT_2D(sizes2D[i], sizes2D[i]); - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - } - long elapsedTime = System.nanoTime(); - DoubleDHT_2D dht2 = new DoubleDHT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dht2.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDHT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDHT_3D dht3 = new DoubleDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - } - long elapsedTime = System.nanoTime(); - DoubleDHT_3D dht3 = new DoubleDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dht3.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDHT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDHT_3D dht3 = new DoubleDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - } - long elapsedTime = System.nanoTime(); - DoubleDHT_3D dht3 = new DoubleDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dht3.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDHT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dht/BenchmarkFloatDHT.java b/src/main/java/org/jtransforms/dht/BenchmarkFloatDHT.java deleted file mode 100644 index 8b63936..0000000 --- a/src/main/java/org/jtransforms/dht/BenchmarkFloatDHT.java +++ /dev/null @@ -1,326 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Benchmark of single precision DHT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkFloatDHT -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkFloatDHT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDHT_1D dht = new FloatDHT_1D(sizes1D[i]); - x = new float[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dht.forward(x); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dht.forward(x); - } - long elapsedTime = System.nanoTime(); - FloatDHT_1D dht = new FloatDHT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes1D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dht.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDHT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDHT_2D dht2 = new FloatDHT_2D(sizes2D[i], sizes2D[i]); - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - } - long elapsedTime = System.nanoTime(); - FloatDHT_2D dht2 = new FloatDHT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dht2.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDHT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDHT_2D dht2 = new FloatDHT_2D(sizes2D[i], sizes2D[i]); - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dht2.forward(x); - } - long elapsedTime = System.nanoTime(); - FloatDHT_2D dht2 = new FloatDHT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dht2.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDHT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDHT_3D dht3 = new FloatDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - } - long elapsedTime = System.nanoTime(); - FloatDHT_3D dht3 = new FloatDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dht3.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDHT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DHT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDHT_3D dht3 = new FloatDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dht3.forward(x); - } - long elapsedTime = System.nanoTime(); - FloatDHT_3D dht3 = new FloatDHT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dht3.forward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dht3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDHT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dht/DoubleDHT_1D.java b/src/main/java/org/jtransforms/dht/DoubleDHT_1D.java deleted file mode 100644 index 19017b2..0000000 --- a/src/main/java/org/jtransforms/dht/DoubleDHT_1D.java +++ /dev/null @@ -1,265 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.fft.DoubleFFT_1D; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Hartley Transform (DHT) of real, double precision data. - * The size of the data can be an arbitrary number. It uses FFT algorithm. This - * is a parallel implementation optimized for SMP systems. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDHT_1D { - - private final int n; - private final long nl; - private final DoubleFFT_1D fft; - private final boolean useLargeArrays; - - /** - * Creates new instance of DoubleDHT_1D. - * - * @param n size of data - */ - public DoubleDHT_1D(long n) { - this.n = (int) n; - this.nl = n; - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - fft = new DoubleFFT_1D(n); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a data to transform - */ - public void forward(double[] a) { - forward(a, 0); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a data to transform - */ - public void forward(DoubleLargeArray a) { - forward(a, 0); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void forward(final double[] a, final int offa) { - if (n == 1) { - return; - } - if (useLargeArrays) { - forward(new DoubleLargeArray(a), offa); - } else { - fft.realForward(a, offa); - final double[] b = new double[n]; - System.arraycopy(a, offa, b, 0, n); - int nd2 = n / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k1 = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = 1 + i * k1; - final int lastIdx = (i == (nthreads - 1)) ? nd2 : firstIdx + k1; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx1, idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a[offa + i] = b[idx1] - b[idx2]; - a[offa + n - i] = b[idx1] + b[idx2]; - } - } - - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int i = 1; i < nd2; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a[offa + i] = b[idx1] - b[idx2]; - a[offa + n - i] = b[idx1] + b[idx2]; - } - } - if ((n % 2) == 0) { - a[offa + nd2] = b[1]; - } else { - a[offa + nd2] = b[n - 1] - b[1]; - a[offa + nd2 + 1] = b[n - 1] + b[1]; - } - } - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void forward(final DoubleLargeArray a, final long offa) { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - fft.realForward(a, offa); - final DoubleLargeArray b = new DoubleLargeArray(nl, false); - Utilities.arraycopy(a, offa, b, 0, nl); - long nd2 = nl / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k1 = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = 1 + i * k1; - final long lastIdx = (i == (nthreads - 1)) ? nd2 : firstIdx + k1; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx1, idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a.setDouble(offa + i, b.getDouble(idx1) - b.getDouble(idx2)); - a.setDouble(offa + nl - i, b.getDouble(idx1) + b.getDouble(idx2)); - } - } - - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long i = 1; i < nd2; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a.setDouble(offa + i, b.getDouble(idx1) - b.getDouble(idx2)); - a.setDouble(offa + nl - i, b.getDouble(idx1) + b.getDouble(idx2)); - } - } - if ((nl % 2) == 0) { - a.setDouble(offa + nd2, b.getDouble(1)); - } else { - a.setDouble(offa + nd2, b.getDouble(nl - 1) - b.getDouble(1)); - a.setDouble(offa + nd2 + 1, b.getDouble(nl - 1) + b.getDouble(1)); - } - } - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(double[] a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(DoubleLargeArray a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final int offa, boolean scale) { - if (n == 1) { - return; - } - if (useLargeArrays) { - inverse(new DoubleLargeArray(a), offa, scale); - } else { - forward(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - } - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final long offa, boolean scale) { - if (n == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - forward(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - } - } -} diff --git a/src/main/java/org/jtransforms/dht/DoubleDHT_2D.java b/src/main/java/org/jtransforms/dht/DoubleDHT_2D.java deleted file mode 100644 index eb3c649..0000000 --- a/src/main/java/org/jtransforms/dht/DoubleDHT_2D.java +++ /dev/null @@ -1,1189 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 2D Discrete Hartley Transform (DHT) of real, double precision data. - * The sizes of both dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDHT_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private DoubleDHT_1D dhtColumns, dhtRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDHT_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDHT_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dhtRows = new DoubleDHT_1D(rows); - if (rows == columns) { - dhtColumns = dhtRows; - } else { - dhtColumns = new DoubleDHT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - */ - public void forward(final double[] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a, i * columns); - } - } - DoubleDHT_2D.this.yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a, i * columns); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a, i * columns); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - */ - public void forward(final DoubleLargeArray a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (long i = 0; i < rowsl; i++) { - dhtColumns.forward(a, i * columnsl); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a, i * columnsl); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long i = 0; i < rowsl; i++) { - dhtColumns.forward(a, i * columnsl); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 2D array. - * - * @param a data to transform - */ - public void forward(final double[][] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a[i]); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a[i]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a[i]); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long i = 0; i < rowsl; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a[i], scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a[i], scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - yTransform(a); - } - } - - private void ddxt2d_subth(final int isgn, final double[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final double[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.forward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dhtColumns.forward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - dhtColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.forward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, double[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, double[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } - - private void yTransform(double[] a) { - int mRow, mCol, idx1, idx2; - double A, B, C, D, E; - for (int r = 0; r <= rows / 2; r++) { - mRow = (rows - r) % rows; - idx1 = r * columns; - idx2 = mRow * columns; - for (int c = 0; c <= columns / 2; c++) { - mCol = (columns - c) % columns; - A = a[idx1 + c]; - B = a[idx2 + c]; - C = a[idx1 + mCol]; - D = a[idx2 + mCol]; - E = ((A + D) - (B + C)) / 2; - a[idx1 + c] = A - E; - a[idx2 + c] = B + E; - a[idx1 + mCol] = C + E; - a[idx2 + mCol] = D - E; - } - } - } - - private void yTransform(DoubleLargeArray a) { - long mRow, mCol, idx1, idx2; - double A, B, C, D, E; - for (long r = 0; r <= rowsl / 2; r++) { - mRow = (rowsl - r) % rowsl; - idx1 = r * columnsl; - idx2 = mRow * columnsl; - for (long c = 0; c <= columnsl / 2; c++) { - mCol = (columnsl - c) % columnsl; - A = a.getDouble(idx1 + c); - B = a.getDouble(idx2 + c); - C = a.getDouble(idx1 + mCol); - D = a.getDouble(idx2 + mCol); - E = ((A + D) - (B + C)) / 2; - a.setDouble(idx1 + c, A - E); - a.setDouble(idx2 + c, B + E); - a.setDouble(idx1 + mCol, C + E); - a.setDouble(idx2 + mCol, D - E); - } - } - } - - private void yTransform(double[][] a) { - int mRow, mCol; - double A, B, C, D, E; - for (int r = 0; r <= rows / 2; r++) { - mRow = (rows - r) % rows; - for (int c = 0; c <= columns / 2; c++) { - mCol = (columns - c) % columns; - A = a[r][c]; - B = a[mRow][c]; - C = a[r][mCol]; - D = a[mRow][mCol]; - E = ((A + D) - (B + C)) / 2; - a[r][c] = A - E; - a[mRow][c] = B + E; - a[r][mCol] = C + E; - a[mRow][mCol] = D - E; - } - } - } - -} diff --git a/src/main/java/org/jtransforms/dht/DoubleDHT_3D.java b/src/main/java/org/jtransforms/dht/DoubleDHT_3D.java deleted file mode 100644 index a4efc7b..0000000 --- a/src/main/java/org/jtransforms/dht/DoubleDHT_3D.java +++ /dev/null @@ -1,2229 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 3D Discrete Hartley Transform (DHT) of real, double precision data. - * The sizes of all three dimensions can be arbitrary numbers. This is a - * parallel implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDHT_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private DoubleDHT_1D dhtSlices, dhtRows, dhtColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDHT_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDHT_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dhtSlices = new DoubleDHT_1D(slices); - if (slices == rows) { - dhtRows = dhtSlices; - } else { - dhtRows = new DoubleDHT_1D(rows); - } - if (slices == columns) { - dhtColumns = dhtSlices; - } else if (rows == columns) { - dhtColumns = dhtRows; - } else { - dhtColumns = new DoubleDHT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - */ - public void forward(final double[] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int startRow = l * p; - final int stopRow; - if (l == nthreads - 1) { - stopRow = rows; - } else { - stopRow = startRow + p; - } - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = startRow; r < stopRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - */ - public void forward(final DoubleLargeArray a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long startRow = l * p; - final long stopRow; - if (l == nthreads - 1) { - stopRow = rowsl; - } else { - stopRow = startRow + p; - } - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = startRow; r < stopRow; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dhtSlices.forward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dhtSlices.forward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 3D array. - * - * @param a data to transform - */ - public void forward(final double[][][] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dhtSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dhtSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - private void ddxt3da_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx0 + r * rowStridel); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columnsl == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - dhtSlices.forward(t, 2 * slicesl); - dhtSlices.forward(t, 3 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - dhtSlices.inverse(t, 2 * slicesl, scale); - dhtSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - dhtSlices.forward(t, 2 * slicesl); - dhtSlices.forward(t, 3 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - dhtSlices.inverse(t, 2 * slicesl, scale); - dhtSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void yTransform(double[] a) { - double A, B, C, D, E, F, G, H; - int cC, rC, sC; - int idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10, idx11, idx12; - for (int s = 0; s <= slices / 2; s++) { - sC = (slices - s) % slices; - idx9 = s * sliceStride; - idx10 = sC * sliceStride; - for (int r = 0; r <= rows / 2; r++) { - rC = (rows - r) % rows; - idx11 = r * rowStride; - idx12 = rC * rowStride; - for (int c = 0; c <= columns / 2; c++) { - cC = (columns - c) % columns; - idx1 = idx9 + idx12 + c; - idx2 = idx9 + idx11 + cC; - idx3 = idx10 + idx11 + c; - idx4 = idx10 + idx12 + cC; - idx5 = idx10 + idx12 + c; - idx6 = idx10 + idx11 + cC; - idx7 = idx9 + idx11 + c; - idx8 = idx9 + idx12 + cC; - A = a[idx1]; - B = a[idx2]; - C = a[idx3]; - D = a[idx4]; - E = a[idx5]; - F = a[idx6]; - G = a[idx7]; - H = a[idx8]; - a[idx7] = (A + B + C - D) / 2; - a[idx3] = (E + F + G - H) / 2; - a[idx1] = (G + H + E - F) / 2; - a[idx5] = (C + D + A - B) / 2; - a[idx2] = (H + G + F - E) / 2; - a[idx6] = (D + C + B - A) / 2; - a[idx8] = (B + A + D - C) / 2; - a[idx4] = (F + E + H - G) / 2; - } - } - } - } - - private void yTransform(DoubleLargeArray a) { - double A, B, C, D, E, F, G, H; - long cC, rC, sC; - long idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10, idx11, idx12; - for (long s = 0; s <= slicesl / 2; s++) { - sC = (slicesl - s) % slicesl; - idx9 = s * sliceStridel; - idx10 = sC * sliceStridel; - for (long r = 0; r <= rowsl / 2; r++) { - rC = (rowsl - r) % rowsl; - idx11 = r * rowStridel; - idx12 = rC * rowStridel; - for (long c = 0; c <= columnsl / 2; c++) { - cC = (columnsl - c) % columnsl; - idx1 = idx9 + idx12 + c; - idx2 = idx9 + idx11 + cC; - idx3 = idx10 + idx11 + c; - idx4 = idx10 + idx12 + cC; - idx5 = idx10 + idx12 + c; - idx6 = idx10 + idx11 + cC; - idx7 = idx9 + idx11 + c; - idx8 = idx9 + idx12 + cC; - A = a.getDouble(idx1); - B = a.getDouble(idx2); - C = a.getDouble(idx3); - D = a.getDouble(idx4); - E = a.getDouble(idx5); - F = a.getDouble(idx6); - G = a.getDouble(idx7); - H = a.getDouble(idx8); - a.setDouble(idx7, (A + B + C - D) / 2); - a.setDouble(idx3, (E + F + G - H) / 2); - a.setDouble(idx1, (G + H + E - F) / 2); - a.setDouble(idx5, (C + D + A - B) / 2); - a.setDouble(idx2, (H + G + F - E) / 2); - a.setDouble(idx6, (D + C + B - A) / 2); - a.setDouble(idx8, (B + A + D - C) / 2); - a.setDouble(idx4, (F + E + H - G) / 2); - } - } - } - } - - private void yTransform(double[][][] a) { - double A, B, C, D, E, F, G, H; - int cC, rC, sC; - for (int s = 0; s <= slices / 2; s++) { - sC = (slices - s) % slices; - for (int r = 0; r <= rows / 2; r++) { - rC = (rows - r) % rows; - for (int c = 0; c <= columns / 2; c++) { - cC = (columns - c) % columns; - A = a[s][rC][c]; - B = a[s][r][cC]; - C = a[sC][r][c]; - D = a[sC][rC][cC]; - E = a[sC][rC][c]; - F = a[sC][r][cC]; - G = a[s][r][c]; - H = a[s][rC][cC]; - a[s][r][c] = (A + B + C - D) / 2; - a[sC][r][c] = (E + F + G - H) / 2; - a[s][rC][c] = (G + H + E - F) / 2; - a[sC][rC][c] = (C + D + A - B) / 2; - a[s][r][cC] = (H + G + F - E) / 2; - a[sC][r][cC] = (D + C + B - A) / 2; - a[s][rC][cC] = (B + A + D - C) / 2; - a[sC][rC][cC] = (F + E + H - G) / 2; - } - } - } - } - -} diff --git a/src/main/java/org/jtransforms/dht/FloatDHT_1D.java b/src/main/java/org/jtransforms/dht/FloatDHT_1D.java deleted file mode 100644 index 4af3e61..0000000 --- a/src/main/java/org/jtransforms/dht/FloatDHT_1D.java +++ /dev/null @@ -1,293 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.fft.FloatFFT_1D; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Hartley Transform (DHT) of real, single precision data. - * The size of the data can be an arbitrary number. It uses FFT algorithm. This - * is a parallel implementation optimized for SMP systems. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDHT_1D -{ - - private final int n; - private final long nl; - private final FloatFFT_1D fft; - private final boolean useLargeArrays; - - /** - * Creates new instance of FloatDHT_1D. - * - * @param n - * size of data - - */ - public FloatDHT_1D(long n) - { - this.n = (int) n; - this.nl = n; - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - fft = new FloatFFT_1D(n); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a - * data to transform - */ - public void forward(float[] a) - { - forward(a, 0); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a - * data to transform - */ - public void forward(FloatLargeArray a) - { - forward(a, 0); - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - */ - public void forward(final float[] a, final int offa) - { - if (n == 1) - return; - if (useLargeArrays) { - forward(new FloatLargeArray(a), offa); - } else { - fft.realForward(a, offa); - final float[] b = new float[n]; - System.arraycopy(a, offa, b, 0, n); - int nd2 = n / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k1 = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = 1 + i * k1; - final int lastIdx = (i == (nthreads - 1)) ? nd2 : firstIdx + k1; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - - public void run() - { - int idx1, idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a[offa + i] = b[idx1] - b[idx2]; - a[offa + n - i] = b[idx1] + b[idx2]; - } - } - - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int i = 1; i < nd2; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a[offa + i] = b[idx1] - b[idx2]; - a[offa + n - i] = b[idx1] + b[idx2]; - } - } - if ((n % 2) == 0) { - a[offa + nd2] = b[1]; - } else { - a[offa + nd2] = b[n - 1] - b[1]; - a[offa + nd2 + 1] = b[n - 1] + b[1]; - } - } - } - - /** - * Computes 1D real, forward DHT leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - */ - public void forward(final FloatLargeArray a, final long offa) - { - if (nl == 1) - return; - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - fft.realForward(a, offa); - final FloatLargeArray b = new FloatLargeArray(nl, false); - Utilities.arraycopy(a, offa, b, 0, nl); - long nd2 = nl / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k1 = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = 1 + i * k1; - final long lastIdx = (i == (nthreads - 1)) ? nd2 : firstIdx + k1; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - - public void run() - { - long idx1, idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a.setFloat(offa + i, b.getFloat(idx1) - b.getFloat(idx2)); - a.setFloat(offa + nl - i, b.getFloat(idx1) + b.getFloat(idx2)); - } - } - - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long i = 1; i < nd2; i++) { - idx1 = 2 * i; - idx2 = idx1 + 1; - a.setFloat(offa + i, b.getFloat(idx1) - b.getFloat(idx2)); - a.setFloat(offa + nl - i, b.getFloat(idx1) + b.getFloat(idx2)); - } - } - if ((nl % 2) == 0) { - a.setFloat(offa + nd2, b.getFloat(1)); - } else { - a.setFloat(offa + nd2, b.getFloat(nl - 1) - b.getFloat(1)); - a.setFloat(offa + nd2 + 1, b.getFloat(nl - 1) + b.getFloat(1)); - } - } - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void inverse(float[] a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - */ - public void inverse(FloatLargeArray a, boolean scale) - { - inverse(a, 0, scale); - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void inverse(final float[] a, final int offa, boolean scale) - { - if (n == 1) - return; - if (useLargeArrays) { - inverse(new FloatLargeArray(a), offa, scale); - } else { - forward(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - } - } - - /** - * Computes 1D real, inverse DHT leaving the result in a. - * - * @param a - * data to transform - * @param offa - * index of the first element in array a - * @param scale - * if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final long offa, boolean scale) - { - if (n == 1) - return; - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - forward(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0f / n, a, offa, false); - } - } - } -} diff --git a/src/main/java/org/jtransforms/dht/FloatDHT_2D.java b/src/main/java/org/jtransforms/dht/FloatDHT_2D.java deleted file mode 100644 index 323a9a6..0000000 --- a/src/main/java/org/jtransforms/dht/FloatDHT_2D.java +++ /dev/null @@ -1,1189 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 2D Discrete Hartley Transform (DHT) of real, single precision data. - * The sizes of both dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDHT_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private FloatDHT_1D dhtColumns, dhtRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDHT_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public FloatDHT_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dhtRows = new FloatDHT_1D(rows); - if (rows == columns) { - dhtColumns = dhtRows; - } else { - dhtColumns = new FloatDHT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - */ - public void forward(final float[] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a, i * columns); - } - } - FloatDHT_2D.this.yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a, i * columns); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a, i * columns); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - */ - public void forward(final FloatLargeArray a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (long i = 0; i < rowsl; i++) { - dhtColumns.forward(a, i * columnsl); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a, i * columnsl); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long i = 0; i < rowsl; i++) { - dhtColumns.forward(a, i * columnsl); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, forward DHT leaving the result in a. The - * data is stored in 2D array. - * - * @param a data to transform - */ - public void forward(final float[][] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, true); - ddxt2d0_subth(-1, a, true); - } else { - ddxt2d_sub(-1, a, true); - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a[i]); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.forward(a[i]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.forward(a[i]); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a, i * columns, scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long i = 0; i < rowsl; i++) { - dhtColumns.inverse(a, i * columnsl, scale); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - yTransform(a); - } - } - - /** - * Computes 2D real, inverse DHT leaving the result in a. The - * data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a[i], scale); - } - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dhtColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int i = 0; i < rows; i++) { - dhtColumns.inverse(a[i], scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - yTransform(a); - } - } - - private void ddxt2d_subth(final int isgn, final float[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setFloat(idx2, a.getFloat(idx1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setFloat(idx1, t.getFloat(idx2)); - a.setFloat(idx1 + 1, t.getFloat(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final float[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.forward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dhtColumns.forward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - dhtColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.forward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dhtColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, float[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, float[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - } else { - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } - - private void yTransform(float[] a) { - int mRow, mCol, idx1, idx2; - float A, B, C, D, E; - for (int r = 0; r <= rows / 2; r++) { - mRow = (rows - r) % rows; - idx1 = r * columns; - idx2 = mRow * columns; - for (int c = 0; c <= columns / 2; c++) { - mCol = (columns - c) % columns; - A = a[idx1 + c]; - B = a[idx2 + c]; - C = a[idx1 + mCol]; - D = a[idx2 + mCol]; - E = ((A + D) - (B + C)) / 2; - a[idx1 + c] = A - E; - a[idx2 + c] = B + E; - a[idx1 + mCol] = C + E; - a[idx2 + mCol] = D - E; - } - } - } - - private void yTransform(FloatLargeArray a) { - long mRow, mCol, idx1, idx2; - float A, B, C, D, E; - for (long r = 0; r <= rowsl / 2; r++) { - mRow = (rowsl - r) % rowsl; - idx1 = r * columnsl; - idx2 = mRow * columnsl; - for (long c = 0; c <= columnsl / 2; c++) { - mCol = (columnsl - c) % columnsl; - A = a.getFloat(idx1 + c); - B = a.getFloat(idx2 + c); - C = a.getFloat(idx1 + mCol); - D = a.getFloat(idx2 + mCol); - E = ((A + D) - (B + C)) / 2; - a.setFloat(idx1 + c, A - E); - a.setFloat(idx2 + c, B + E); - a.setFloat(idx1 + mCol, C + E); - a.setFloat(idx2 + mCol, D - E); - } - } - } - - private void yTransform(float[][] a) { - int mRow, mCol; - float A, B, C, D, E; - for (int r = 0; r <= rows / 2; r++) { - mRow = (rows - r) % rows; - for (int c = 0; c <= columns / 2; c++) { - mCol = (columns - c) % columns; - A = a[r][c]; - B = a[mRow][c]; - C = a[r][mCol]; - D = a[mRow][mCol]; - E = ((A + D) - (B + C)) / 2; - a[r][c] = A - E; - a[mRow][c] = B + E; - a[r][mCol] = C + E; - a[mRow][mCol] = D - E; - } - } - } - -} diff --git a/src/main/java/org/jtransforms/dht/FloatDHT_3D.java b/src/main/java/org/jtransforms/dht/FloatDHT_3D.java deleted file mode 100644 index 8e63038..0000000 --- a/src/main/java/org/jtransforms/dht/FloatDHT_3D.java +++ /dev/null @@ -1,2229 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 3D Discrete Hartley Transform (DHT) of real, single precision data. - * The sizes of all three dimensions can be arbitrary numbers. This is a - * parallel implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDHT_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private FloatDHT_1D dhtSlices, dhtRows, dhtColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDHT_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public FloatDHT_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dhtSlices = new FloatDHT_1D(slices); - if (slices == rows) { - dhtRows = dhtSlices; - } else { - dhtRows = new FloatDHT_1D(rows); - } - if (slices == columns) { - dhtColumns = dhtSlices; - } else if (rows == columns) { - dhtColumns = dhtRows; - } else { - dhtColumns = new FloatDHT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - */ - public void forward(final float[] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int startRow = l * p; - final int stopRow; - if (l == nthreads - 1) { - stopRow = rows; - } else { - stopRow = startRow + p; - } - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = startRow; r < stopRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - */ - public void forward(final FloatLargeArray a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long startRow = l * p; - final long stopRow; - if (l == nthreads - 1) { - stopRow = rowsl; - } else { - stopRow = startRow + p; - } - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = startRow; r < stopRow; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dhtSlices.forward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx1 + r * rowStride); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dhtRows.forward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dhtSlices.forward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, forward DHT leaving the result in a. - * The data is stored in 3D array. - * - * @param a data to transform - */ - public void forward(final float[][][] a) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, true); - ddxt3db_subth(-1, a, true); - } else { - ddxt3da_sub(-1, a, true); - ddxt3db_sub(-1, a, true); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.forward(temp); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.forward(temp); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 1D array addressed in slice-major, then row-major, - * then column-major, in order of significance, i.e. the element (i,j,k) of - * 3D array x[slices][rows][columns] is stored in a[i*sliceStride + - * j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dhtSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx1 + r * rowStridel, scale); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dhtRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dhtSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - yTransform(a); - } - } - - /** - * Computes the 3D real, inverse DHT leaving the result in a. - * The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - yTransform(a); - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dhtRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dhtSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - yTransform(a); - } - } - - private void ddxt3da_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx0 + r * rowStridel); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columnsl == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - dhtSlices.forward(t, 2 * slicesl); - dhtSlices.forward(t, 3 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - dhtSlices.inverse(t, 2 * slicesl, scale); - dhtSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.forward(a, idx0 + r * rowStride); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - dhtRows.forward(t, 2 * rowsl); - dhtRows.forward(t, 3 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dhtColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - dhtRows.inverse(t, 2 * rowsl, scale); - dhtRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStride; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dhtColumns.forward(a[s][r]); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - dhtRows.forward(t, 2 * rows); - dhtRows.forward(t, 3 * rows); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dhtRows.forward(t, 0); - dhtRows.forward(t, rows); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dhtColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - dhtRows.inverse(t, 2 * rows, scale); - dhtRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dhtRows.inverse(t, 0, scale); - dhtRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - dhtSlices.forward(t, 2 * slicesl); - dhtSlices.forward(t, 3 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - dhtSlices.inverse(t, 2 * slicesl, scale); - dhtSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - dhtSlices.forward(t, 2 * slices); - dhtSlices.forward(t, 3 * slices); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dhtSlices.forward(t, 0); - dhtSlices.forward(t, slices); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - dhtSlices.inverse(t, 2 * slices, scale); - dhtSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dhtSlices.inverse(t, 0, scale); - dhtSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void yTransform(float[] a) { - float A, B, C, D, E, F, G, H; - int cC, rC, sC; - int idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10, idx11, idx12; - for (int s = 0; s <= slices / 2; s++) { - sC = (slices - s) % slices; - idx9 = s * sliceStride; - idx10 = sC * sliceStride; - for (int r = 0; r <= rows / 2; r++) { - rC = (rows - r) % rows; - idx11 = r * rowStride; - idx12 = rC * rowStride; - for (int c = 0; c <= columns / 2; c++) { - cC = (columns - c) % columns; - idx1 = idx9 + idx12 + c; - idx2 = idx9 + idx11 + cC; - idx3 = idx10 + idx11 + c; - idx4 = idx10 + idx12 + cC; - idx5 = idx10 + idx12 + c; - idx6 = idx10 + idx11 + cC; - idx7 = idx9 + idx11 + c; - idx8 = idx9 + idx12 + cC; - A = a[idx1]; - B = a[idx2]; - C = a[idx3]; - D = a[idx4]; - E = a[idx5]; - F = a[idx6]; - G = a[idx7]; - H = a[idx8]; - a[idx7] = (A + B + C - D) / 2; - a[idx3] = (E + F + G - H) / 2; - a[idx1] = (G + H + E - F) / 2; - a[idx5] = (C + D + A - B) / 2; - a[idx2] = (H + G + F - E) / 2; - a[idx6] = (D + C + B - A) / 2; - a[idx8] = (B + A + D - C) / 2; - a[idx4] = (F + E + H - G) / 2; - } - } - } - } - - private void yTransform(FloatLargeArray a) { - float A, B, C, D, E, F, G, H; - long cC, rC, sC; - long idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10, idx11, idx12; - for (long s = 0; s <= slicesl / 2; s++) { - sC = (slicesl - s) % slicesl; - idx9 = s * sliceStridel; - idx10 = sC * sliceStridel; - for (long r = 0; r <= rowsl / 2; r++) { - rC = (rowsl - r) % rowsl; - idx11 = r * rowStridel; - idx12 = rC * rowStridel; - for (long c = 0; c <= columnsl / 2; c++) { - cC = (columnsl - c) % columnsl; - idx1 = idx9 + idx12 + c; - idx2 = idx9 + idx11 + cC; - idx3 = idx10 + idx11 + c; - idx4 = idx10 + idx12 + cC; - idx5 = idx10 + idx12 + c; - idx6 = idx10 + idx11 + cC; - idx7 = idx9 + idx11 + c; - idx8 = idx9 + idx12 + cC; - A = a.getFloat(idx1); - B = a.getFloat(idx2); - C = a.getFloat(idx3); - D = a.getFloat(idx4); - E = a.getFloat(idx5); - F = a.getFloat(idx6); - G = a.getFloat(idx7); - H = a.getFloat(idx8); - a.setFloat(idx7, (A + B + C - D) / 2); - a.setFloat(idx3, (E + F + G - H) / 2); - a.setFloat(idx1, (G + H + E - F) / 2); - a.setFloat(idx5, (C + D + A - B) / 2); - a.setFloat(idx2, (H + G + F - E) / 2); - a.setFloat(idx6, (D + C + B - A) / 2); - a.setFloat(idx8, (B + A + D - C) / 2); - a.setFloat(idx4, (F + E + H - G) / 2); - } - } - } - } - - private void yTransform(float[][][] a) { - float A, B, C, D, E, F, G, H; - int cC, rC, sC; - for (int s = 0; s <= slices / 2; s++) { - sC = (slices - s) % slices; - for (int r = 0; r <= rows / 2; r++) { - rC = (rows - r) % rows; - for (int c = 0; c <= columns / 2; c++) { - cC = (columns - c) % columns; - A = a[s][rC][c]; - B = a[s][r][cC]; - C = a[sC][r][c]; - D = a[sC][rC][cC]; - E = a[sC][rC][c]; - F = a[sC][r][cC]; - G = a[s][r][c]; - H = a[s][rC][cC]; - a[s][r][c] = (A + B + C - D) / 2; - a[sC][r][c] = (E + F + G - H) / 2; - a[s][rC][c] = (G + H + E - F) / 2; - a[sC][rC][c] = (C + D + A - B) / 2; - a[s][r][cC] = (H + G + F - E) / 2; - a[sC][r][cC] = (D + C + B - A) / 2; - a[s][rC][cC] = (B + A + D - C) / 2; - a[sC][rC][cC] = (F + E + H - G) / 2; - } - } - } - } - -} diff --git a/src/main/java/org/jtransforms/dht/package.html b/src/main/java/org/jtransforms/dht/package.html deleted file mode 100644 index 9ee9e8c..0000000 --- a/src/main/java/org/jtransforms/dht/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Discrete Hartley Transforms. - - diff --git a/src/main/java/org/jtransforms/dst/BenchmarkDoubleDST.java b/src/main/java/org/jtransforms/dst/BenchmarkDoubleDST.java deleted file mode 100644 index 92020fd..0000000 --- a/src/main/java/org/jtransforms/dst/BenchmarkDoubleDST.java +++ /dev/null @@ -1,326 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Benchmark of double precision DST's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkDoubleDST -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkDoubleDST() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDST_1D dst = new DoubleDST_1D(sizes1D[i]); - x = new double[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dst.forward(x, doScaling); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dst.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDST_1D dst = new DoubleDST_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes1D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dst.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDST_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDST_2D dst2 = new DoubleDST_2D(sizes2D[i], sizes2D[i]); - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDST_2D dst2 = new DoubleDST_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dst2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDST_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDST_2D dst2 = new DoubleDST_2D(sizes2D[i], sizes2D[i]); - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDST_2D dst2 = new DoubleDST_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dst2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDST_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDST_3D dst3 = new DoubleDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDST_3D dst3 = new DoubleDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dst3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDST_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleDST_3D dst3 = new DoubleDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - DoubleDST_3D dst3 = new DoubleDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dst3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleForwardDST_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dst/BenchmarkFloatDST.java b/src/main/java/org/jtransforms/dst/BenchmarkFloatDST.java deleted file mode 100644 index 875b6bf..0000000 --- a/src/main/java/org/jtransforms/dst/BenchmarkFloatDST.java +++ /dev/null @@ -1,326 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Benchmark of single precision DST's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkFloatDST -{ - - private static int nthread = 8; - - private static int niter = 200; - - private static int nsize = 16; - - private static int threadsBegin2D = 65636; - - private static int threadsBegin3D = 65636; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkFloatDST() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDST_1D dst = new FloatDST_1D(sizes1D[i]); - x = new float[(int) sizes1D[i]]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - dst.forward(x, doScaling); - IOUtils.fillMatrix_1D(sizes1D[i], x); - dst.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDST_1D dst = new FloatDST_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes1D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - dst.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDST_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDST_2D dst2 = new FloatDST_2D(sizes2D[i], sizes2D[i]); - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDST_2D dst2 = new FloatDST_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes2D[i] * sizes2D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dst2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDST_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDST_2D dst2 = new FloatDST_2D(sizes2D[i], sizes2D[i]); - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - dst2.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDST_2D dst2 = new FloatDST_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes2D[i]][(int) sizes2D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - dst2.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDST_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDST_3D dst3 = new FloatDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDST_3D dst3 = new FloatDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * sizes3D[i], false); - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dst3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDST_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Forward DST 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatDST_3D dst3 = new FloatDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - dst3.forward(x, doScaling); - } - long elapsedTime = System.nanoTime(); - FloatDST_3D dst3 = new FloatDST_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][(int) sizes3D[i]]; - double min_time = 0; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - dst3.forward(x, doScaling); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - dst3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatForwardDST_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkForward_1D(); - benchmarkForward_2D_input_1D(); - benchmarkForward_2D_input_2D(); - benchmarkForward_3D_input_1D(); - benchmarkForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/dst/DoubleDST_1D.java b/src/main/java/org/jtransforms/dst/DoubleDST_1D.java deleted file mode 100644 index ac980ad..0000000 --- a/src/main/java/org/jtransforms/dst/DoubleDST_1D.java +++ /dev/null @@ -1,345 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.dct.DoubleDCT_1D; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 1D Discrete Sine Transform (DST) of double precision data. The size - * of data can be an arbitrary number. It uses DCT algorithm. This is a parallel - * implementation optimized for SMP systems. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDST_1D { - - private final int n; - private final long nl; - private final DoubleDCT_1D dct; - private final boolean useLargeArrays; - - /** - * Creates new instance of DoubleDST_1D. - * - * @param n size of data - */ - public DoubleDST_1D(long n) { - this.n = (int) n; - this.nl = n; - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - dct = new DoubleDCT_1D(n); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(double[] a, boolean scale) { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(DoubleLargeArray a, boolean scale) { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final int offa, boolean scale) { - if (n == 1) { - return; - } - if (useLargeArrays) { - forward(new DoubleLargeArray(a), offa, scale); - } else { - double tmp; - int nd2 = n / 2; - int startIdx = 1 + offa; - int stopIdx = offa + n; - for (int i = startIdx; i < stopIdx; i += 2) { - a[i] = -a[i]; - } - dct.forward(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double tmp; - int idx0 = offa + n - 1; - int idx1; - int idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx0 = offa + n - 1; - int idx1; - int idx2; - for (int i = 0; i < nd2; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - } - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final long offa, boolean scale) { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - double tmp; - long nd2 = nl / 2; - long startIdx = 1 + offa; - long stopIdx = offa + nl; - for (long i = startIdx; i < stopIdx; i += 2) { - a.setDouble(i, -a.getDouble(i)); - } - dct.forward(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double tmp; - long idx0 = offa + nl - 1; - long idx1; - long idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a.getDouble(idx2); - idx1 = idx0 - i; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, tmp); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx0 = offa + nl - 1; - long idx1; - long idx2; - for (long i = 0; i < nd2; i++) { - idx2 = offa + i; - tmp = a.getDouble(idx2); - idx1 = idx0 - i; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, tmp); - } - } - } - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(double[] a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(DoubleLargeArray a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final int offa, boolean scale) { - if (n == 1) { - return; - } - if (useLargeArrays) { - inverse(new DoubleLargeArray(a), offa, scale); - } else { - double tmp; - int nd2 = n / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double tmp; - int idx0 = offa + n - 1; - int idx1, idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx0 = offa + n - 1; - for (int i = 0; i < nd2; i++) { - tmp = a[offa + i]; - a[offa + i] = a[idx0 - i]; - a[idx0 - i] = tmp; - } - } - dct.inverse(a, offa, scale); - int startidx = 1 + offa; - int stopidx = offa + n; - for (int i = startidx; i < stopidx; i += 2) { - a[i] = -a[i]; - } - } - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final long offa, boolean scale) { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - double tmp; - long nd2 = nl / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double tmp; - long idx0 = offa + nl - 1; - long idx1, idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a.getDouble(idx2); - idx1 = idx0 - i; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, tmp); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx0 = offa + nl - 1; - for (long i = 0; i < nd2; i++) { - tmp = a.getDouble(offa + i); - a.setDouble(offa + i, a.getDouble(idx0 - i)); - a.setDouble(idx0 - i, tmp); - } - } - dct.inverse(a, offa, scale); - long startidx = 1 + offa; - long stopidx = offa + nl; - for (long i = startidx; i < stopidx; i += 2) { - a.setDouble(i, -a.getDouble(i)); - } - } - } -} diff --git a/src/main/java/org/jtransforms/dst/DoubleDST_2D.java b/src/main/java/org/jtransforms/dst/DoubleDST_2D.java deleted file mode 100644 index 47241cd..0000000 --- a/src/main/java/org/jtransforms/dst/DoubleDST_2D.java +++ /dev/null @@ -1,1105 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 2D Discrete Sine Transform (DST) of double precision data. The sizes - * of both dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDST_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private DoubleDST_1D dstColumns, dstRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDST_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDST_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dstRows = new DoubleDST_1D(rows); - if (rows == columns) { - dstColumns = dstRows; - } else { - dstColumns = new DoubleDST_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.forward(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.forward(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.forward(a, i * columns, scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (long i = 0; i < rowsl; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - } - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.forward(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.forward(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.forward(a[i], scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a, i * columns, scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl + c)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setDouble(r * columnsl + c, temp.getDouble(r)); - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a[i], scale); - } - double[] temp = new double[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - private void ddxt2d_subth(final int isgn, final double[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final double[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - double[] t = new double[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.forward(a, r * columns, scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dstColumns.forward(a, r * columnsl, scale); - } - } else { - for (long r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final double[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.forward(a[r], scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, double[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, double[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - double[] t = new double[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } -} diff --git a/src/main/java/org/jtransforms/dst/DoubleDST_3D.java b/src/main/java/org/jtransforms/dst/DoubleDST_3D.java deleted file mode 100644 index 5caf44c..0000000 --- a/src/main/java/org/jtransforms/dst/DoubleDST_3D.java +++ /dev/null @@ -1,2101 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 3D Discrete Sine Transform (DST) of double precision data. The sizes - * of all three dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleDST_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private DoubleDST_1D dstSlices, dstRows, dstColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleDST_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public DoubleDST_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dstSlices = new DoubleDST_1D(slices); - if (slices == rows) { - dstRows = dstSlices; - } else { - dstRows = new DoubleDST_1D(rows); - } - if (slices == columns) { - dstColumns = dstSlices; - } else if (rows == columns) { - dstColumns = dstRows; - } else { - dstColumns = new DoubleDST_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dstSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dstSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - } - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final double[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final DoubleLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - DoubleLargeArray temp = new DoubleLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dstSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setDouble(r, a.getDouble(idx3)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setDouble(idx3, temp.getDouble(r)); - } - } - } - temp = new DoubleLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setDouble(s, a.getDouble(idx3)); - } - dstSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setDouble(idx3, temp.getDouble(s)); - } - } - } - } - } - - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final double[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - double[] temp = new double[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - } - double[] temp = new double[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new double[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - private void ddxt3da_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, DoubleLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - dstSlices.forward(t, 2 * slicesl, scale); - dstSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - dstSlices.inverse(t, 2 * slicesl, scale); - dstSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, double[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - double[] t = new double[nt]; - - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1l; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + rowsl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * rowsl, a.getDouble(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + rowsl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setDouble(r, a.getDouble(idx1)); - t.setDouble(rowsl + r, a.getDouble(idx1 + 1)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setDouble(idx1, t.getDouble(r)); - a.setDouble(idx1 + 1, t.getDouble(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final DoubleLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - dstSlices.forward(t, 2 * slicesl, scale); - dstSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(idx2, a.getDouble(idx1 + 1)); - t.setDouble(idx2 + slicesl, a.getDouble(idx1 + 2)); - t.setDouble(idx2 + 2 * slicesl, a.getDouble(idx1 + 3)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - dstSlices.inverse(t, 2 * slicesl, scale); - dstSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(idx2)); - a.setDouble(idx1 + 2, t.getDouble(idx2 + slicesl)); - a.setDouble(idx1 + 3, t.getDouble(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setDouble(s, a.getDouble(idx1)); - t.setDouble(slicesl + s, a.getDouble(idx1 + 1)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setDouble(idx1, t.getDouble(s)); - a.setDouble(idx1 + 1, t.getDouble(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final double[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } -} diff --git a/src/main/java/org/jtransforms/dst/FloatDST_1D.java b/src/main/java/org/jtransforms/dst/FloatDST_1D.java deleted file mode 100644 index e50cfcc..0000000 --- a/src/main/java/org/jtransforms/dst/FloatDST_1D.java +++ /dev/null @@ -1,345 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.dct.FloatDCT_1D; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 1D Discrete Sine Transform (DST) of float precision data. The size - * of data can be an arbitrary number. It uses DCT algorithm. This is a parallel - * implementation optimized for SMP systems. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDST_1D { - - private final int n; - private final long nl; - private final FloatDCT_1D dct; - private final boolean useLargeArrays; - - /** - * Creates new instance of FloatDST_1D. - * - * @param n size of data - */ - public FloatDST_1D(long n) { - this.n = (int) n; - this.nl = n; - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - dct = new FloatDCT_1D(n); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(float[] a, boolean scale) { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(FloatLargeArray a, boolean scale) { - forward(a, 0, scale); - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final float[] a, final int offa, boolean scale) { - if (n == 1) { - return; - } - if (useLargeArrays) { - forward(new FloatLargeArray(a), offa, scale); - } else { - float tmp; - int nd2 = n / 2; - int startIdx = 1 + offa; - int stopIdx = offa + n; - for (int i = startIdx; i < stopIdx; i += 2) { - a[i] = -a[i]; - } - dct.forward(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float tmp; - int idx0 = offa + n - 1; - int idx1; - int idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx0 = offa + n - 1; - int idx1; - int idx2; - for (int i = 0; i < nd2; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - } - } - - /** - * Computes 1D forward DST (DST-II) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final long offa, boolean scale) { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - forward(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - float tmp; - long nd2 = nl / 2; - long startIdx = 1 + offa; - long stopIdx = offa + nl; - for (long i = startIdx; i < stopIdx; i += 2) { - a.setFloat(i, -a.getFloat(i)); - } - dct.forward(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float tmp; - long idx0 = offa + nl - 1; - long idx1; - long idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a.getFloat(idx2); - idx1 = idx0 - i; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, tmp); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx0 = offa + nl - 1; - long idx1; - long idx2; - for (long i = 0; i < nd2; i++) { - idx2 = offa + i; - tmp = a.getFloat(idx2); - idx1 = idx0 - i; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, tmp); - } - } - } - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(float[] a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(FloatLargeArray a, boolean scale) { - inverse(a, 0, scale); - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final int offa, boolean scale) { - if (n == 1) { - return; - } - if (useLargeArrays) { - inverse(new FloatLargeArray(a), offa, scale); - } else { - float tmp; - int nd2 = n / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final int k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final int firstIdx = j * k; - final int lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float tmp; - int idx0 = offa + n - 1; - int idx1, idx2; - for (int i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a[idx2]; - idx1 = idx0 - i; - a[idx2] = a[idx1]; - a[idx1] = tmp; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx0 = offa + n - 1; - for (int i = 0; i < nd2; i++) { - tmp = a[offa + i]; - a[offa + i] = a[idx0 - i]; - a[idx0 - i] = tmp; - } - } - dct.inverse(a, offa, scale); - int startidx = 1 + offa; - int stopidx = offa + n; - for (int i = startidx; i < stopidx; i += 2) { - a[i] = -a[i]; - } - } - } - - /** - * Computes 1D inverse DST (DST-III) leaving the result in a. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final long offa, boolean scale) { - if (nl == 1) { - return; - } - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - inverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - float tmp; - long nd2 = nl / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nd2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - nthreads = 2; - final long k = nd2 / nthreads; - Future[] futures = new Future[nthreads]; - for (int j = 0; j < nthreads; j++) { - final long firstIdx = j * k; - final long lastIdx = (j == (nthreads - 1)) ? nd2 : firstIdx + k; - futures[j] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float tmp; - long idx0 = offa + nl - 1; - long idx1, idx2; - for (long i = firstIdx; i < lastIdx; i++) { - idx2 = offa + i; - tmp = a.getFloat(idx2); - idx1 = idx0 - i; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, tmp); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx0 = offa + nl - 1; - for (long i = 0; i < nd2; i++) { - tmp = a.getFloat(offa + i); - a.setFloat(offa + i, a.getFloat(idx0 - i)); - a.setFloat(idx0 - i, tmp); - } - } - dct.inverse(a, offa, scale); - long startidx = 1 + offa; - long stopidx = offa + nl; - for (long i = startidx; i < stopidx; i += 2) { - a.setFloat(i, -a.getFloat(i)); - } - } - } -} diff --git a/src/main/java/org/jtransforms/dst/FloatDST_2D.java b/src/main/java/org/jtransforms/dst/FloatDST_2D.java deleted file mode 100644 index f5c5733..0000000 --- a/src/main/java/org/jtransforms/dst/FloatDST_2D.java +++ /dev/null @@ -1,1105 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 2D Discrete Sine Transform (DST) of single precision data. The sizes - * of both dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDST_2D { - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private FloatDST_1D dstColumns, dstRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDST_2D. - * - * @param rows number of rows - * @param columns number of columns - */ - public FloatDST_2D(long rows, long columns) { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - dstRows = new FloatDST_1D(rows); - if (rows == columns) { - dstColumns = dstRows; - } else { - dstColumns = new FloatDST_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.forward(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.forward(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.forward(a, i * columns, scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (long i = 0; i < rowsl; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dstColumns.forward(a, i * columnsl, scale); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - } - } - - /** - * Computes 2D forward DST (DST-II) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(-1, a, scale); - ddxt2d0_subth(-1, a, scale); - } else { - ddxt2d_sub(-1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.forward(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.forward(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.forward(a[i], scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a, i * columns, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a, i * columns, scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r * columns + c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r * columns + c] = temp[r]; - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 1D array in row-major order. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (long i = 0; i < rowsl; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long i = 0; i < rowsl; i++) { - dstColumns.inverse(a, i * columnsl, scale); - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - temp.setFloat(r, a.getFloat(r * columnsl + c)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - a.setFloat(r * columnsl + c, temp.getFloat(r)); - } - } - } - } - } - - /** - * Computes 2D inverse DST (DST-III) leaving the result in a. - * The data is stored in 2D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt2d_subth(1, a, scale); - ddxt2d0_subth(1, a, scale); - } else { - ddxt2d_sub(1, a, scale); - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a[i], scale); - } - } - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstRow; i < lastRow; i++) { - dstColumns.inverse(a[i], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int c = firstColumn; c < lastColumn; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int i = 0; i < rows; i++) { - dstColumns.inverse(a[i], scale); - } - float[] temp = new float[rows]; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[r][c] = temp[r]; - } - } - } - } - } - - private void ddxt2d_subth(final int isgn, final float[] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - t[idx2] = a[idx1]; - t[idx2 + rows] = a[idx1 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - int nthread = (int) Math.min(columnsl, ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - final long ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 4 * n0; c < columnsl; c += 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - t.setFloat(idx2, a.getFloat(idx1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = r; - a.setFloat(idx1, t.getFloat(idx2)); - a.setFloat(idx1 + 1, t.getFloat(idx2 + rowsl)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_subth(final int isgn, final float[][] a, final boolean scale) { - int nthread = Math.min(columns, ConcurrencyUtils.getNumberOfThreads()); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - final int ntf = nt; - final int nthreads = nthread; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx2; - float[] t = new float[ntf]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 4 * n0; c < columns; c += 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = r; - t[idx2] = a[r][2 * n0]; - t[idx2 + rows] = a[r][2 * n0 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx2 = r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + rows]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.forward(a, r * columns, scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a, r * columns, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - dstColumns.forward(a, r * columnsl, scale); - } - } else { - for (long r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a, r * columnsl, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d0_subth(final int isgn, final float[][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.forward(a[r], scale); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - dstColumns.inverse(a[r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt2d_sub(int isgn, float[] a, boolean scale) { - int idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - - private void ddxt2d_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } else if (columnsl < 2) { - nt >>= 2; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (columnsl > 2) { - if (isgn == -1) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - } - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - - private void ddxt2d_sub(int isgn, float[][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } else if (columns < 2) { - nt >>= 2; - } - float[] t = new float[nt]; - if (columns > 2) { - if (isgn == -1) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[r][c]; - t[idx2] = a[r][c + 1]; - t[idx2 + rows] = a[r][c + 2]; - t[idx2 + 2 * rows] = a[r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[r][c] = t[r]; - a[r][c + 1] = t[idx2]; - a[r][c + 2] = t[idx2 + rows]; - a[r][c + 3] = t[idx2 + 2 * rows]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[r][0]; - t[rows + r] = a[r][1]; - } - if (isgn == -1) { - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - } else { - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - } - for (int r = 0; r < rows; r++) { - a[r][0] = t[r]; - a[r][1] = t[rows + r]; - } - } - } -} diff --git a/src/main/java/org/jtransforms/dst/FloatDST_3D.java b/src/main/java/org/jtransforms/dst/FloatDST_3D.java deleted file mode 100644 index 6625fc6..0000000 --- a/src/main/java/org/jtransforms/dst/FloatDST_3D.java +++ /dev/null @@ -1,2101 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Computes 3D Discrete Sine Transform (DST) of single precision data. The sizes - * of all three dimensions can be arbitrary numbers. This is a parallel - * implementation optimized for SMP systems.
- *
- * Part of code is derived from General Purpose FFT Package written by Takuya - * Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class FloatDST_3D { - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private FloatDST_1D dstSlices, dstRows, dstColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of FloatDST_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - */ - public FloatDST_3D(long slices, long rows, long columns) { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - dstSlices = new FloatDST_1D(slices); - if (slices == rows) { - dstRows = dstSlices; - } else { - dstRows = new FloatDST_1D(rows); - } - if (slices == columns) { - dstColumns = dstSlices; - } else if (rows == columns) { - dstColumns = dstRows; - } else { - dstColumns = new FloatDST_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx1 + r * rowStride, scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 1D array addressed in slice-major, then - * row-major, then column-major, in order of significance, i.e. the element - * (i,j,k) of 3D array x[slices][rows][columns] is stored in a[i*sliceStride - * + j*rowStride + k], where sliceStride = rows * columns and rowStride = - * columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dstSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx1 + r * rowStridel, scale); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dstRows.forward(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStridel + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dstSlices.forward(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - } - } - - /** - * Computes the 3D forward DST (DST-II) leaving the result in a - * . The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void forward(final float[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(-1, a, scale); - ddxt3db_subth(-1, a, scale); - } else { - ddxt3da_sub(-1, a, scale); - ddxt3db_sub(-1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.forward(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.forward(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - temp[r] = a[idx3]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * rowStride + c; - a[idx3] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - temp[s] = a[idx3]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + c; - a[idx3] = temp[s]; - } - } - } - } - } - - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. the - * element (i,j,k) of 3D array x[slices][rows][columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * columns - * and rowStride = columns. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final FloatLargeArray a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - FloatLargeArray temp = new FloatLargeArray(slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dstSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx1 + r * rowStride, scale); - } - } - FloatLargeArray temp = new FloatLargeArray(rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStride; - for (long c = 0; c < columnsl; c++) { - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - temp.setFloat(r, a.getFloat(idx3)); - } - dstRows.inverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * rowStride + c; - a.setFloat(idx3, temp.getFloat(r)); - } - } - } - temp = new FloatLargeArray(slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStride; - for (long c = 0; c < columnsl; c++) { - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - temp.setFloat(s, a.getFloat(idx3)); - } - dstSlices.inverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStride + idx1 + c; - a.setFloat(idx3, temp.getFloat(s)); - } - } - } - } - } - - } - - /** - * Computes the 3D inverse DST (DST-III) leaving the result in - * a. The data is stored in 3D array. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void inverse(final float[][][] a, final boolean scale) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - if ((nthreads > 1) && useThreads) { - ddxt3da_subth(1, a, scale); - ddxt3db_subth(1, a, scale); - } else { - ddxt3da_sub(1, a, scale); - ddxt3db_sub(1, a, scale); - } - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - float[] temp = new float[slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - } - float[] temp = new float[rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - for (int r = 0; r < rows; r++) { - temp[r] = a[s][r][c]; - } - dstRows.inverse(temp, scale); - for (int r = 0; r < rows; r++) { - a[s][r][c] = temp[r]; - } - } - } - temp = new float[slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - for (int s = 0; s < slices; s++) { - temp[s] = a[s][r][c]; - } - dstSlices.inverse(temp, scale); - for (int s = 0; s < slices; s++) { - a[s][r][c] = temp[s]; - } - } - } - } - } - } - - private void ddxt3da_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[r] = a[idx1]; - t[rows + r] = a[idx1 + 1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[r]; - a[idx1 + 1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3da_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - - private void ddxt3da_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[r] = a[s][r][0]; - t[rows + r] = a[s][r][1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[r]; - a[s][r][1] = t[rows + r]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[] a, boolean scale) { - int idx0, idx1, idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[s] = a[idx1]; - t[slices + s] = a[idx1 + 1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[s]; - a[idx1 + 1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3db_sub(int isgn, FloatLargeArray a, boolean scale) { - long idx0, idx1, idx2; - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - FloatLargeArray t = new FloatLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - dstSlices.forward(t, 2 * slicesl, scale); - dstSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - dstSlices.inverse(t, 2 * slicesl, scale); - dstSlices.inverse(t, 3 * slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - - private void ddxt3db_sub(int isgn, float[][][] a, boolean scale) { - int idx2; - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - float[] t = new float[nt]; - - if (isgn == -1) { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - t[s] = a[s][r][0]; - t[slices + s] = a[s][r][1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[s]; - a[s][r][1] = t[slices + s]; - } - } - } - } - } - - private void ddxt3da_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.forward(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a, idx0 + r * rowStride, scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - t[ r] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + rows] = a[idx1 + 2]; - t[idx2 + 2 * rows] = a[idx1 + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = rows + r; - a[idx1] = t[ r]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + rows]; - a[idx1 + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - t[ r] = a[idx1]; - t[ rows + r] = a[idx1 + 1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - a[idx1] = t[ r]; - a[idx1 + 1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > slicesl ? slicesl : ConcurrencyUtils.getNumberOfThreads()); - - long nt = 4 * rowsl; - if (columnsl == 2) { - nt >>= 1l; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.forward(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - dstRows.forward(t, 2 * rowsl, scale); - dstRows.forward(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - dstColumns.inverse(a, idx0 + r * rowStridel, scale); - } - if (columnsl > 2) { - for (long c = 0; c < columnsl; c += 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + rowsl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * rowsl, a.getFloat(idx1 + 3)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - dstRows.inverse(t, 2 * rowsl, scale); - dstRows.inverse(t, 3 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = rowsl + r; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + rowsl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * rowsl)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - t.setFloat(r, a.getFloat(idx1)); - t.setFloat(rowsl + r, a.getFloat(idx1 + 1)); - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - a.setFloat(idx1, t.getFloat(r)); - a.setFloat(idx1 + 1, t.getFloat(rowsl + r)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3da_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > slices ? slices : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * rows; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dstColumns.forward(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - dstRows.forward(t, 2 * rows, scale); - dstRows.forward(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dstRows.forward(t, 0, scale); - dstRows.forward(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } else { - for (int s = n0; s < slices; s += nthreads) { - for (int r = 0; r < rows; r++) { - dstColumns.inverse(a[s][r], scale); - } - if (columns > 2) { - for (int c = 0; c < columns; c += 4) { - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - t[ r] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + rows] = a[s][r][c + 2]; - t[idx2 + 2 * rows] = a[s][r][c + 3]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - dstRows.inverse(t, 2 * rows, scale); - dstRows.inverse(t, 3 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = rows + r; - a[s][r][c] = t[ r]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + rows]; - a[s][r][c + 3] = t[idx2 + 2 * rows]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - t[ r] = a[s][r][0]; - t[ rows + r] = a[s][r][1]; - } - dstRows.inverse(t, 0, scale); - dstRows.inverse(t, rows, scale); - for (int r = 0; r < rows; r++) { - a[s][r][0] = t[ r]; - a[s][r][1] = t[ rows + r]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx0, idx1, idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - t[ s] = a[idx1]; - t[idx2] = a[idx1 + 1]; - t[idx2 + slices] = a[idx1 + 2]; - t[idx2 + 2 * slices] = a[idx1 + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = slices + s; - a[idx1] = t[ s]; - a[idx1 + 1] = t[idx2]; - a[idx1 + 2] = t[idx2 + slices]; - a[idx1 + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - t[ s] = a[idx1]; - t[ slices + s] = a[idx1 + 1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - a[idx1] = t[ s]; - a[idx1 + 1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final FloatLargeArray a, final boolean scale) { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - long nt = 4 * slicesl; - if (columnsl == 2) { - nt >>= 1; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - long idx0, idx1, idx2; - FloatLargeArray t = new FloatLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - dstSlices.forward(t, 2 * slicesl, scale); - dstSlices.forward(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } else { - if (columnsl > 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 4) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(idx2, a.getFloat(idx1 + 1)); - t.setFloat(idx2 + slicesl, a.getFloat(idx1 + 2)); - t.setFloat(idx2 + 2 * slicesl, a.getFloat(idx1 + 3)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - dstSlices.inverse(t, 2 * slicesl, scale); - dstSlices.inverse(t, 3 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = slicesl + s; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(idx2)); - a.setFloat(idx1 + 2, t.getFloat(idx2 + slicesl)); - a.setFloat(idx1 + 3, t.getFloat(idx2 + 2 * slicesl)); - } - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - t.setFloat(s, a.getFloat(idx1)); - t.setFloat(slicesl + s, a.getFloat(idx1 + 1)); - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slicesl, scale); - - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - a.setFloat(idx1, t.getFloat(s)); - a.setFloat(idx1 + 1, t.getFloat(slicesl + s)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void ddxt3db_subth(final int isgn, final float[][][] a, final boolean scale) { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - int nt = 4 * slices; - if (columns == 2) { - nt >>= 1; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - - public void run() { - int idx2; - float[] t = new float[ntf]; - if (isgn == -1) { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - dstSlices.forward(t, 2 * slices, scale); - dstSlices.forward(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dstSlices.forward(t, 0, scale); - dstSlices.forward(t, slices, scale); - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } else { - if (columns > 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 4) { - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - t[ s] = a[s][r][c]; - t[idx2] = a[s][r][c + 1]; - t[idx2 + slices] = a[s][r][c + 2]; - t[idx2 + 2 * slices] = a[s][r][c + 3]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - dstSlices.inverse(t, 2 * slices, scale); - dstSlices.inverse(t, 3 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = slices + s; - a[s][r][c] = t[ s]; - a[s][r][c + 1] = t[idx2]; - a[s][r][c + 2] = t[idx2 + slices]; - a[s][r][c + 3] = t[idx2 + 2 * slices]; - } - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - t[ s] = a[s][r][0]; - t[ slices + s] = a[s][r][1]; - } - dstSlices.inverse(t, 0, scale); - dstSlices.inverse(t, slices, scale); - - for (int s = 0; s < slices; s++) { - a[s][r][0] = t[ s]; - a[s][r][1] = t[ slices + s]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } -} diff --git a/src/main/java/org/jtransforms/dst/package.html b/src/main/java/org/jtransforms/dst/package.html deleted file mode 100644 index 1e2097c..0000000 --- a/src/main/java/org/jtransforms/dst/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Discrete Sine Transforms. - - diff --git a/src/main/java/org/jtransforms/fft/BenchmarkDoubleFFT.java b/src/main/java/org/jtransforms/fft/BenchmarkDoubleFFT.java deleted file mode 100644 index 4d309ae..0000000 --- a/src/main/java/org/jtransforms/fft/BenchmarkDoubleFFT.java +++ /dev/null @@ -1,545 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Benchmark of single precision FFT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkDoubleFFT -{ - - private static int nthread = 16; - - private static int niter = 100; - - private static int nsize = 8; - - private static int threadsBegin2D = 65536; - - private static int threadsBegin3D = 65536; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkDoubleFFT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkComplexForward_1D() - { - double[] x; - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); - x = new double[(int) (2 * sizes1D[i])]; - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - fft.complexForward(x); - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - fft.complexForward(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) (2 * sizes1D[i])]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - elapsedTime = System.nanoTime(); - fft.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkRealForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); - x = new double[(int) (2 * sizes1D[i])]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - fft.realForwardFull(x); - IOUtils.fillMatrix_1D(sizes1D[i], x); - fft.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_1D fft = new DoubleFFT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) (2 * sizes1D[i])]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - fft.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkComplexForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - x = new DoubleLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - int niter_local = niter; - if (sizes2D[i] >= (1 << 13)) { - niter_local = Math.max(1, niter / 10); - } - for (int j = 0; j < niter_local; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - x = new double[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - x = new DoubleLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - x = new double[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_2D fft2 = new DoubleFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - int niter_local = niter; - if (sizes3D[i] >= (1 << 10)) { - niter_local = Math.max(1, niter / 10); - } - for (int j = 0; j < niter_local; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleComplexForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - DoubleLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new DoubleLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - double[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - DoubleFFT_3D fft3 = new DoubleFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new double[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkDoubleRealForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkComplexForward_1D(); - benchmarkRealForward_1D(); - - benchmarkComplexForward_2D_input_1D(); - benchmarkComplexForward_2D_input_2D(); - benchmarkRealForward_2D_input_1D(); - benchmarkRealForward_2D_input_2D(); - - benchmarkComplexForward_3D_input_1D(); - benchmarkComplexForward_3D_input_3D(); - benchmarkRealForward_3D_input_1D(); - benchmarkRealForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/fft/BenchmarkFloatFFT.java b/src/main/java/org/jtransforms/fft/BenchmarkFloatFFT.java deleted file mode 100644 index 088a619..0000000 --- a/src/main/java/org/jtransforms/fft/BenchmarkFloatFFT.java +++ /dev/null @@ -1,545 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.Arrays; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Benchmark of single precision FFT's - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class BenchmarkFloatFFT -{ - - private static int nthread = 16; - - private static int niter = 100; - - private static int nsize = 8; - - private static int threadsBegin2D = 65536; - - private static int threadsBegin3D = 65536; - - private static boolean doWarmup = true; - - private static long[] sizes1D = new long[]{262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 10368, 27000, 75600, 165375, 362880, 1562500, 3211264, 6250000}; - - private static long[] sizes2D = new long[]{256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 260, 520, 1050, 1458, 1960, 2916, 4116, 5832}; - - private static long[] sizes3D = new long[]{16, 32, 64, 128, 256, 512, 1024, 2048, 5, 17, 30, 95, 180, 270, 324, 420}; - - private static boolean doScaling = false; - - private BenchmarkFloatFFT() - { - - } - - public static void parseArguments(String[] args) - { - if (args.length > 0) { - nthread = Integer.parseInt(args[0]); - threadsBegin2D = Integer.parseInt(args[1]); - threadsBegin3D = Integer.parseInt(args[2]); - niter = Integer.parseInt(args[3]); - doWarmup = Boolean.parseBoolean(args[4]); - doScaling = Boolean.parseBoolean(args[5]); - nsize = Integer.parseInt(args[6]); - sizes1D = new long[nsize]; - sizes2D = new long[nsize]; - sizes3D = new long[nsize]; - for (int i = 0; i < nsize; i++) { - sizes1D[i] = Integer.parseInt(args[7 + i]); - } - for (int i = 0; i < nsize; i++) { - sizes2D[i] = Integer.parseInt(args[7 + nsize + i]); - } - for (int i = 0; i < nsize; i++) { - sizes3D[i] = Integer.parseInt(args[7 + nsize + nsize + i]); - } - } else { - System.out.println("Default settings are used."); - } - ConcurrencyUtils.setNumberOfThreads(nthread); - ConcurrencyUtils.setThreadsBeginN_2D(threadsBegin2D); - ConcurrencyUtils.setThreadsBeginN_3D(threadsBegin3D); - System.out.println("nthred = " + nthread); - System.out.println("threadsBegin2D = " + threadsBegin2D); - System.out.println("threadsBegin3D = " + threadsBegin3D); - System.out.println("niter = " + niter); - System.out.println("doWarmup = " + doWarmup); - System.out.println("doScaling = " + doScaling); - System.out.println("nsize = " + nsize); - System.out.println("sizes1D[] = " + Arrays.toString(sizes1D)); - System.out.println("sizes2D[] = " + Arrays.toString(sizes2D)); - System.out.println("sizes3D[] = " + Arrays.toString(sizes3D)); - } - - public static void benchmarkComplexForward_1D() - { - float[] x; - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_1D fft = new FloatFFT_1D(sizes1D[i]); - x = new float[(int) (2 * sizes1D[i])]; - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - fft.complexForward(x); - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - fft.complexForward(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_1D fft = new FloatFFT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) (2 * sizes1D[i])]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(2 * sizes1D[i], x); - elapsedTime = System.nanoTime(); - fft.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatComplexForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkRealForward_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 1D of size " + sizes1D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_1D fft = new FloatFFT_1D(sizes1D[i]); - x = new float[(int) (2 * sizes1D[i])]; - IOUtils.fillMatrix_1D(sizes1D[i], x); - fft.realForwardFull(x); - IOUtils.fillMatrix_1D(sizes1D[i], x); - fft.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_1D fft = new FloatFFT_1D(sizes1D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) (2 * sizes1D[i])]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_1D(sizes1D[i], x); - elapsedTime = System.nanoTime(); - fft.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatRealForwardFFT_1D.txt", nthread, niter, doWarmup, doScaling, sizes1D, times_without_constructor, times_with_constructor); - - } - - public static void benchmarkComplexForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - x = new FloatLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - int niter_local = niter; - if (sizes2D[i] >= (1 << 13)) { - niter_local = Math.max(1, niter / 10); - } - for (int j = 0; j < niter_local; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatComplexForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - x = new float[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - fft2.complexForward(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], 2 * sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatComplexForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_2D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 2D (input 1D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - x = new FloatLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes2D[i] * 2 * sizes2D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatRealForwardFFT_2D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_2D_input_2D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 2D (input 2D) of size " + sizes2D[i] + " x " + sizes2D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - x = new float[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - fft2.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_2D fft2 = new FloatFFT_2D(sizes2D[i], sizes2D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes2D[i]][2 * (int) sizes2D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_2D(sizes2D[i], sizes2D[i], x); - elapsedTime = System.nanoTime(); - fft2.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft2 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatRealForwardFFT_2D_input_2D.txt", nthread, niter, doWarmup, doScaling, sizes2D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - int niter_local = niter; - if (sizes3D[i] >= (1 << 10)) { - niter_local = Math.max(1, niter / 10); - } - for (int j = 0; j < niter_local; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatComplexForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkComplexForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Complex forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - fft3.complexForward(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], 2 * sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.complexForward(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatComplexForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_3D_input_1D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - FloatLargeArray x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 3D (input 1D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new FloatLargeArray(sizes3D[i] * sizes3D[i] * 2 * sizes3D[i], false); - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatRealForwardFFT_3D_input_1D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void benchmarkRealForward_3D_input_3D() - { - double[] times_without_constructor = new double[nsize]; - double[] times_with_constructor = new double[nsize]; - float[][][] x; - for (int i = 0; i < nsize; i++) { - System.out.println("Real forward FFT 3D (input 3D) of size " + sizes3D[i] + " x " + sizes3D[i] + " x " + sizes3D[i]); - if (doWarmup) { // call the transform twice to warm up - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - fft3.realForwardFull(x); - } - long elapsedTime = System.nanoTime(); - FloatFFT_3D fft3 = new FloatFFT_3D(sizes3D[i], sizes3D[i], sizes3D[i]); - times_with_constructor[i] = (System.nanoTime() - elapsedTime) / 1000000.0; - x = new float[(int) sizes3D[i]][(int) sizes3D[i]][2 * (int) sizes3D[i]]; - double min_time = Double.MAX_VALUE; - for (int j = 0; j < niter; j++) { - IOUtils.fillMatrix_3D(sizes3D[i], sizes3D[i], sizes3D[i], x); - elapsedTime = System.nanoTime(); - fft3.realForwardFull(x); - elapsedTime = System.nanoTime() - elapsedTime; - if (elapsedTime < min_time) { - min_time = elapsedTime; - } - } - times_without_constructor[i] = (double) min_time / 1000000.0; - times_with_constructor[i] += times_without_constructor[i]; - System.out.println("\tBest execution time without constructor: " + String.format("%.2f", times_without_constructor[i]) + " msec"); - System.out.println("\tBest execution time with constructor: " + String.format("%.2f", times_with_constructor[i]) + " msec"); - x = null; - fft3 = null; - System.gc(); - ConcurrencyUtils.sleep(5000); - } - IOUtils.writeFFTBenchmarkResultsToFile("benchmarkFloatRealForwardFFT_3D_input_3D.txt", nthread, niter, doWarmup, doScaling, sizes3D, times_without_constructor, times_with_constructor); - } - - public static void main(String[] args) - { - parseArguments(args); - benchmarkComplexForward_1D(); - benchmarkRealForward_1D(); - - benchmarkComplexForward_2D_input_1D(); - benchmarkComplexForward_2D_input_2D(); - benchmarkRealForward_2D_input_1D(); - benchmarkRealForward_2D_input_2D(); - - benchmarkComplexForward_3D_input_1D(); - benchmarkComplexForward_3D_input_3D(); - benchmarkRealForward_3D_input_1D(); - benchmarkRealForward_3D_input_3D(); - System.exit(0); - - } -} diff --git a/src/main/java/org/jtransforms/fft/DoubleFFT_1D.java b/src/main/java/org/jtransforms/fft/DoubleFFT_1D.java deleted file mode 100644 index 985e630..0000000 --- a/src/main/java/org/jtransforms/fft/DoubleFFT_1D.java +++ /dev/null @@ -1,7682 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.concurrent.Future; -import org.jtransforms.utils.CommonUtils; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.LongLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 1D Discrete Fourier Transform (DFT) of complex and real, double - * precision data. The size of the data can be an arbitrary number. This is a - * parallel implementation of split-radix and mixed-radix algorithms optimized - * for SMP systems.
- *
- * This code is derived from General Purpose FFT Package written by Takuya Ooura - * (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) and from JFFTPack written - * by Baoshe Zhang (http://jfftpack.sourceforge.net/) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public final class DoubleFFT_1D { - - private static enum Plans { - - SPLIT_RADIX, MIXED_RADIX, BLUESTEIN - } - - private int n; - - private long nl; - - private int nBluestein; - - private long nBluesteinl; - - private int[] ip; - - private LongLargeArray ipl; - - private double[] w; - - private DoubleLargeArray wl; - - private int nw; - - private long nwl; - - private int nc; - - private long ncl; - - private double[] wtable; - - private DoubleLargeArray wtablel; - - private double[] wtable_r; - - private DoubleLargeArray wtable_rl; - - private double[] bk1; - - private DoubleLargeArray bk1l; - - private double[] bk2; - - private DoubleLargeArray bk2l; - - private Plans plan; - - private boolean useLargeArrays; - - private static final int[] factors = {4, 2, 3, 5}; - - private static final double PI = 3.14159265358979311599796346854418516; - - private static final double TWO_PI = 6.28318530717958623199592693708837032; - - /** - * Creates new instance of DoubleFFT_1D. - * - * @param n size of data - */ - public DoubleFFT_1D(long n) { - if (n < 1) { - throw new IllegalArgumentException("n must be greater than 0"); - } - this.useLargeArrays = n >= ConcurrencyUtils.getLargeArraysBeginN(); - if(this.useLargeArrays == false) { - this.n = (int) n; - if (!ConcurrencyUtils.isPowerOf2(n)) { - if (CommonUtils.getReminder(n, factors) >= 211) { - plan = Plans.BLUESTEIN; - nBluestein = ConcurrencyUtils.nextPow2(this.n * 2 - 1); - bk1 = new double[2 * nBluestein]; - bk2 = new double[2 * nBluestein]; - this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(nBluestein + 0.5) / Math.log(2)) / 2))]; - this.w = new double[nBluestein]; - int twon = 2 * nBluestein; - nw = twon >> 2; - CommonUtils.makewt(nw, ip, w); - nc = nBluestein >> 2; - CommonUtils.makect(nc, w, nw, ip); - bluesteini(); - } else { - plan = Plans.MIXED_RADIX; - wtable = new double[4 * this.n + 15]; - wtable_r = new double[2 * this.n + 15]; - cffti(); - rffti(); - } - } else { - plan = Plans.SPLIT_RADIX; - this.ip = new int[2 + (int) Math.ceil(2 + (1 << (int) (Math.log(n + 0.5) / Math.log(2)) / 2))]; - this.w = new double[this.n]; - int twon = 2 * this.n; - nw = twon >> 2; - CommonUtils.makewt(nw, ip, w); - nc = this.n >> 2; - CommonUtils.makect(nc, w, nw, ip); - } - } else { - this.nl = n; - if (!ConcurrencyUtils.isPowerOf2(nl)) { - if (CommonUtils.getReminder(nl, factors) >= 211) { - plan = Plans.BLUESTEIN; - nBluesteinl = ConcurrencyUtils.nextPow2(nl * 2 - 1); - bk1l = new DoubleLargeArray(2l * nBluesteinl, false); - bk2l = new DoubleLargeArray(2l * nBluesteinl, false); - this.ipl = new LongLargeArray(2l + (long) Math.ceil(2l + (1l << (long) (Math.log(nBluesteinl + 0.5) / Math.log(2.)) / 2)), false); - this.wl = new DoubleLargeArray(nBluesteinl, false); - long twon = 2 * nBluesteinl; - nwl = twon >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - ncl = nBluesteinl >> 2l; - CommonUtils.makect(ncl, wl, nwl, ipl); - bluesteinil(); - } else { - plan = Plans.MIXED_RADIX; - wtablel = new DoubleLargeArray(4 * nl + 15, false); - wtable_rl = new DoubleLargeArray(2 * nl + 15, false); - cfftil(); - rfftil(); - } - } else { - plan = Plans.SPLIT_RADIX; - this.ipl = new LongLargeArray(2l + (long) Math.ceil(2 + (1l << (long) (Math.log(nl + 0.5) / Math.log(2)) / 2)), false); - this.wl = new DoubleLargeArray(nl, false); - long twon = 2 * nl; - nwl = twon >> 2l; - CommonUtils.makewt(nwl, ipl, wl); - ncl = nl >> 2l; - CommonUtils.makect(ncl, wl, nwl, ipl); - } - } - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - */ - public void complexForward(double[] a) { - complexForward(a, 0); - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - */ - public void complexForward(DoubleLargeArray a) { - complexForward(a, 0); - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void complexForward(double[] a, int offa) { - if (useLargeArrays) { - complexForward(new DoubleLargeArray(a), offa); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftbsub(2 * n, a, offa, ip, nw, w); - break; - case MIXED_RADIX: - cfftf(a, offa, -1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D forward DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void complexForward(DoubleLargeArray a, long offa) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - complexForward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftbsub(2 * nl, a, offa, ipl, nwl, wl); - break; - case MIXED_RADIX: - cfftf(a, offa, -1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(double[] a, boolean scale) { - complexInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[2*k] = Re[k], a[2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(DoubleLargeArray a, boolean scale) { - complexInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void complexInverse(double[] a, int offa, boolean scale) { - if (useLargeArrays) { - complexInverse(new DoubleLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftfsub(2 * n, a, offa, ip, nw, w); - break; - case MIXED_RADIX: - cfftf(a, offa, +1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, 1); - break; - } - if (scale) { - CommonUtils.scale(n, 1.0 / (double) n, a, offa, true); - } - } - } - - /** - * Computes 1D inverse DFT of complex data leaving the result in - * a. Complex number is stored as two double values in - * sequence: the real and imaginary part, i.e. the size of the input array - * must be greater or equal 2*n. The physical layout of the input data has - * to be as follows:
- * - * *
-     * a[offa+2*k] = Re[k], a[offa+2*k+1] = Im[k], 0<=k<n
-     * 
- * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void complexInverse(DoubleLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - complexInverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - CommonUtils.cftfsub(2 * nl, a, offa, ipl, nwl, wl); - break; - case MIXED_RADIX: - cfftf(a, offa, +1); - break; - case BLUESTEIN: - bluestein_complex(a, offa, 1); - break; - } - if (scale) { - CommonUtils.scale(nl, 1.0 / (double) nl, a, offa, true); - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(double[] a) { - realForward(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(DoubleLargeArray a) { - realForward(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForward(double[] a, int offa) { - if (useLargeArrays) { - realForward(new DoubleLargeArray(a), offa); - } else { - if (n == 1) { - return; - } - - switch (plan) { - case SPLIT_RADIX: - double xi; - - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - CommonUtils.rftfsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftx020(a, offa); - } - xi = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - a[offa + 1] = xi; - break; - case MIXED_RADIX: - rfftf(a, offa); - for (int k = n - 1; k >= 2; k--) { - int idx = offa + k; - double tmp = a[idx]; - a[idx] = a[idx - 1]; - a[idx - 1] = tmp; - } - break; - case BLUESTEIN: - bluestein_real_forward(a, offa); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . The physical layout of the output data is as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForward(DoubleLargeArray a, long offa) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realForward(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - - switch (plan) { - case SPLIT_RADIX: - double xi; - - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftx020(a, offa); - } - xi = a.getDouble(offa) - a.getDouble(offa + 1); - a.setDouble(offa, a.getDouble(offa) + a.getDouble(offa + 1)); - a.setDouble(offa + 1, xi); - break; - case MIXED_RADIX: - rfftf(a, offa); - for (long k = nl - 1; k >= 2; k--) { - long idx = offa + k; - double tmp = a.getDouble(idx); - a.setDouble(idx, a.getDouble(idx - 1)); - a.setDouble(idx - 1, tmp); - } - break; - case BLUESTEIN: - bluestein_real_forward(a, offa); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary parts equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(double[] a) { - realForwardFull(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary parts equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - */ - public void realForwardFull(DoubleLargeArray a) { - realForwardFull(a, 0); - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForwardFull(final double[] a, final int offa) { - - if (useLargeArrays) { - realForwardFull(new DoubleLargeArray(a), offa); - } else { - final int twon = 2 * n; - switch (plan) { - case SPLIT_RADIX: - realForward(a, offa); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - int k = n / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - for (int k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int k = 0; k < n / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - a[offa + n] = -a[offa + 1]; - a[offa + 1] = 0; - break; - case MIXED_RADIX: - rfftf(a, offa); - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - for (int k = 1; k < m; k++) { - int idx1 = offa + twon - 2 * k; - int idx2 = offa + 2 * k; - a[idx1 + 1] = -a[idx2]; - a[idx1] = a[idx2 - 1]; - } - for (int k = 1; k < n; k++) { - int idx = offa + n - k; - double tmp = a[idx + 1]; - a[idx + 1] = a[idx]; - a[idx] = tmp; - } - a[offa + 1] = 0; - break; - case BLUESTEIN: - bluestein_real_full(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D forward DFT of real data leaving the result in a - * . This method computes the full real forward transform, i.e. you will get - * the same result as from complexForward called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a data to transform - * @param offa index of the first element in array a - */ - public void realForwardFull(final DoubleLargeArray a, final long offa) { - - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realForwardFull(a.getData(), (int) offa); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - final long twon = 2 * nl; - switch (plan) { - case SPLIT_RADIX: - realForward(a, offa); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - long k = nl / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - for (long k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setDouble(idx2, a.getDouble(offa + idx1)); - a.setDouble(idx2 + 1, -a.getDouble(offa + idx1 + 1)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long k = 0; k < nl / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setDouble(idx2, a.getDouble(offa + idx1)); - a.setDouble(idx2 + 1, -a.getDouble(offa + idx1 + 1)); - } - } - a.setDouble(offa + nl, -a.getDouble(offa + 1)); - a.setDouble(offa + 1, 0); - break; - case MIXED_RADIX: - rfftf(a, offa); - long m; - if (nl % 2 == 0) { - m = nl / 2; - } else { - m = (nl + 1) / 2; - } - for (long k = 1; k < m; k++) { - long idx1 = offa + twon - 2 * k; - long idx2 = offa + 2 * k; - a.setDouble(idx1 + 1, -a.getDouble(idx2)); - a.setDouble(idx1, a.getDouble(idx2 - 1)); - } - for (long k = 1; k < nl; k++) { - long idx = offa + nl - k; - double tmp = a.getDouble(idx + 1); - a.setDouble(idx + 1, a.getDouble(idx)); - a.setDouble(idx, tmp); - } - a.setDouble(offa + 1, 0); - break; - case BLUESTEIN: - bluestein_real_full(a, offa, -1); - break; - } - } - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - * - */ - public void realInverse(double[] a, boolean scale) { - realInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[2*k] = Re[k], 0<=k<n/2 a[2*k+1] = Im[k], 0<k<n/2 a[1] =
-     * Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[2*k] = Re[k], 0<=k<(n+1)/2 a[2*k+1] = Im[k], 0<k<(n-1)/2
-     * a[1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - * - */ - public void realInverse(DoubleLargeArray a, boolean scale) { - realInverse(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - * - */ - public void realInverse(double[] a, int offa, boolean scale) { - if (useLargeArrays) { - realInverse(new DoubleLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - a[offa + 1] = 0.5 * (a[offa] - a[offa + 1]); - a[offa] -= a[offa + 1]; - if (n > 4) { - CommonUtils.rftfsub(n, a, offa, nc, w, nw); - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } else if (n == 4) { - CommonUtils.cftxc020(a, offa); - } - if (scale) { - CommonUtils.scale(n, 1.0 / (n / 2.0), a, offa, false); - } - break; - case MIXED_RADIX: - for (int k = 2; k < n; k++) { - int idx = offa + k; - double tmp = a[idx - 1]; - a[idx - 1] = a[idx]; - a[idx] = tmp; - } - rfftb(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - break; - case BLUESTEIN: - bluestein_real_inverse(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - break; - } - } - - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . The physical layout of the input data has to be as follows:
- * - * if n is even then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<n/2 a[offa+2*k+1] = Im[k], 0<k<n/2
-     * a[offa+1] = Re[n/2]
-     * 
- * - * if n is odd then - * - * *
-     * a[offa+2*k] = Re[k], 0<=k<(n+1)/2 a[offa+2*k+1] = Im[k],
-     * 0<k<(n-1)/2 a[offa+1] = Im[(n-1)/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - * - */ - public void realInverse(DoubleLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverse(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - a.setDouble(offa + 1, 0.5 * (a.getDouble(offa) - a.getDouble(offa + 1))); - a.setDouble(offa, a.getDouble(offa) - a.getDouble(offa + 1)); - if (nl > 4) { - CommonUtils.rftfsub(nl, a, offa, ncl, wl, nwl); - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } else if (nl == 4) { - CommonUtils.cftxc020(a, offa); - } - if (scale) { - CommonUtils.scale(nl, 1.0 / (nl / 2.0), a, offa, false); - } - break; - case MIXED_RADIX: - for (long k = 2; k < nl; k++) { - long idx = offa + k; - double tmp = a.getDouble(idx - 1); - a.setDouble(idx - 1, a.getDouble(idx)); - a.setDouble(idx, tmp); - } - rfftb(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - break; - case BLUESTEIN: - bluestein_real_inverse(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - break; - } - } - - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(double[] a, boolean scale) { - realInverseFull(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(DoubleLargeArray a, boolean scale) { - realInverseFull(a, 0, scale); - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void realInverseFull(final double[] a, final int offa, boolean scale) { - if (useLargeArrays) { - realInverseFull(new DoubleLargeArray(a), offa, scale); - } else { - final int twon = 2 * n; - switch (plan) { - case SPLIT_RADIX: - realInverse2(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (n / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - int k = n / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - int idx1, idx2; - for (int k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - int idx1, idx2; - for (int k = 0; k < n / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a[idx2] = a[offa + idx1]; - a[idx2 + 1] = -a[offa + idx1 + 1]; - } - } - a[offa + n] = -a[offa + 1]; - a[offa + 1] = 0; - break; - case MIXED_RADIX: - rfftf(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - for (int k = 1; k < m; k++) { - int idx1 = offa + 2 * k; - int idx2 = offa + twon - 2 * k; - a[idx1] = -a[idx1]; - a[idx2 + 1] = -a[idx1]; - a[idx2] = a[idx1 - 1]; - } - for (int k = 1; k < n; k++) { - int idx = offa + n - k; - double tmp = a[idx + 1]; - a[idx + 1] = a[idx]; - a[idx] = tmp; - } - a[offa + 1] = 0; - break; - case BLUESTEIN: - bluestein_real_full(a, offa, 1); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, true); - } - break; - } - } - } - - /** - * Computes 1D inverse DFT of real data leaving the result in a - * . This method computes the full real inverse transform, i.e. you will get - * the same result as from complexInverse called with all - * imaginary part equal 0. Because the result is stored in a, - * the size of the input array must greater or equal 2*n, with only the - * first n elements filled with real data. - * - * @param a data to transform - * @param offa index of the first element in array a - * @param scale if true then scaling is performed - */ - public void realInverseFull(final DoubleLargeArray a, final long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverseFull(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - final long twon = 2 * nl; - switch (plan) { - case SPLIT_RADIX: - realInverse2(a, offa, scale); - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && (nl / 2 > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - Future[] futures = new Future[nthreads]; - long k = nl / 2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl / 2 : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - long idx1, idx2; - for (long k = firstIdx; k < lastIdx; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setDouble(idx2, a.getDouble(offa + idx1)); - a.setDouble(idx2 + 1, -a.getDouble(offa + idx1 + 1)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - long idx1, idx2; - for (long k = 0; k < nl / 2; k++) { - idx1 = 2 * k; - idx2 = offa + ((twon - idx1) % twon); - a.setDouble(idx2, a.getDouble(offa + idx1)); - a.setDouble(idx2 + 1, -a.getDouble(offa + idx1 + 1)); - } - } - a.setDouble(offa + nl, -a.getDouble(offa + 1)); - a.setDouble(offa + 1, 0); - break; - case MIXED_RADIX: - rfftf(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - long m; - if (nl % 2 == 0) { - m = nl / 2; - } else { - m = (nl + 1) / 2; - } - for (long k = 1; k < m; k++) { - long idx1 = offa + 2 * k; - long idx2 = offa + twon - 2 * k; - a.setDouble(idx1, -a.getDouble(idx1)); - a.setDouble(idx2 + 1, -a.getDouble(idx1)); - a.setDouble(idx2, a.getDouble(idx1 - 1)); - } - for (long k = 1; k < nl; k++) { - long idx = offa + nl - k; - double tmp = a.getDouble(idx + 1); - a.setDouble(idx + 1, a.getDouble(idx)); - a.setDouble(idx, tmp); - } - a.setDouble(offa + 1, 0); - break; - case BLUESTEIN: - bluestein_real_full(a, offa, 1); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, true); - } - break; - } - } - } - - protected void realInverse2(double[] a, int offa, boolean scale) { - if (useLargeArrays) { - realInverse2(new DoubleLargeArray(a), offa, scale); - } else { - if (n == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - double xi; - - if (n > 4) { - CommonUtils.cftfsub(n, a, offa, ip, nw, w); - CommonUtils.rftbsub(n, a, offa, nc, w, nw); - } else if (n == 4) { - CommonUtils.cftbsub(n, a, offa, ip, nw, w); - } - xi = a[offa] - a[offa + 1]; - a[offa] += a[offa + 1]; - a[offa + 1] = xi; - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - break; - case MIXED_RADIX: - rfftf(a, offa); - for (int k = n - 1; k >= 2; k--) { - int idx = offa + k; - double tmp = a[idx]; - a[idx] = a[idx - 1]; - a[idx - 1] = tmp; - } - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - int m; - if (n % 2 == 0) { - m = n / 2; - for (int i = 1; i < m; i++) { - int idx = offa + 2 * i + 1; - a[idx] = -a[idx]; - } - } else { - m = (n - 1) / 2; - for (int i = 0; i < m; i++) { - int idx = offa + 2 * i + 1; - a[idx] = -a[idx]; - } - } - break; - case BLUESTEIN: - bluestein_real_inverse2(a, offa); - if (scale) { - CommonUtils.scale(n, 1.0 / n, a, offa, false); - } - break; - } - } - } - - protected void realInverse2(DoubleLargeArray a, long offa, boolean scale) { - if (!useLargeArrays) { - if (a.getData() != null && offa < Integer.MAX_VALUE) { - realInverse2(a.getData(), (int) offa, scale); - } else { - throw new IllegalArgumentException("The data array is too big."); - } - } else { - if (nl == 1) { - return; - } - switch (plan) { - case SPLIT_RADIX: - double xi; - - if (nl > 4) { - CommonUtils.cftfsub(nl, a, offa, ipl, nwl, wl); - CommonUtils.rftbsub(nl, a, offa, ncl, wl, nwl); - } else if (nl == 4) { - CommonUtils.cftbsub(nl, a, offa, ipl, nwl, wl); - } - xi = a.getDouble(offa) - a.getDouble(offa + 1); - a.setDouble(offa, a.getDouble(offa) + a.getDouble(offa + 1)); - a.setDouble(offa + 1, xi); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - break; - case MIXED_RADIX: - rfftf(a, offa); - for (long k = nl - 1; k >= 2; k--) { - long idx = offa + k; - double tmp = a.getDouble(idx); - a.setDouble(idx, a.getDouble(idx - 1)); - a.setDouble(idx - 1, tmp); - } - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - long m; - if (nl % 2 == 0) { - m = nl / 2; - for (long i = 1; i < m; i++) { - long idx = offa + 2 * i + 1; - a.setDouble(idx, -a.getDouble(idx)); - } - } else { - m = (nl - 1) / 2; - for (long i = 0; i < m; i++) { - long idx = offa + 2 * i + 1; - a.setDouble(idx, -a.getDouble(idx)); - } - } - break; - case BLUESTEIN: - bluestein_real_inverse2(a, offa); - if (scale) { - CommonUtils.scale(nl, 1.0 / nl, a, offa, false); - } - break; - } - } - } - - - /* -------- initializing routines -------- */ - - /*--------------------------------------------------------- - cffti: initialization of Complex FFT - --------------------------------------------------------*/ - void cffti(int n, int offw) { - if (n == 1) { - return; - } - - final int twon = 2 * n; - final int fourn = 4 * n; - double argh; - int idot, ntry = 0, i, j; - double argld; - int i1, k1, l1, l2, ib; - double fi; - int ld, ii, nf, ipll, nll, nq, nr; - double arg; - int ido, ipm; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtable[offw + nf + 1 + fourn] = ntry; - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + fourn; - wtable[offw + idx + 1] = wtable[offw + idx]; - } - wtable[offw + 2 + fourn] = 2; - } - } while (nll != 1); - break; - } - wtable[offw + fourn] = n; - wtable[offw + 1 + fourn] = nf; - argh = TWO_PI / (double) n; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable[offw + k1 + 1 + fourn]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtable[offw + i - 1 + twon] = 1; - wtable[offw + i + twon] = 0; - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + twon; - wtable[offw + idx - 1] = Math.cos(arg); - wtable[offw + idx] = Math.sin(arg); - } - if (ipll > 5) { - int idx1 = i1 + twon; - int idx2 = i + twon; - wtable[offw + idx1 - 1] = wtable[offw + idx2 - 1]; - wtable[offw + idx1] = wtable[offw + idx2]; - } - } - l1 = l2; - } - - } - - final void cffti() { - if (n == 1) { - return; - } - - final int twon = 2 * n; - final int fourn = 4 * n; - double argh; - int idot, ntry = 0, i, j; - double argld; - int i1, k1, l1, l2, ib; - double fi; - int ld, ii, nf, ipll, nll, nq, nr; - double arg; - int ido, ipm; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtable[nf + 1 + fourn] = ntry; - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + fourn; - wtable[idx + 1] = wtable[idx]; - } - wtable[2 + fourn] = 2; - } - } while (nll != 1); - break; - } - wtable[fourn] = n; - wtable[1 + fourn] = nf; - argh = TWO_PI / (double) n; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable[k1 + 1 + fourn]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtable[i - 1 + twon] = 1; - wtable[i + twon] = 0; - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + twon; - wtable[idx - 1] = Math.cos(arg); - wtable[idx] = Math.sin(arg); - } - if (ipll > 5) { - int idx1 = i1 + twon; - int idx2 = i + twon; - wtable[idx1 - 1] = wtable[idx2 - 1]; - wtable[idx1] = wtable[idx2]; - } - } - l1 = l2; - } - - } - - final void cfftil() { - if (nl == 1) { - return; - } - - final long twon = 2 * nl; - final long fourn = 4 * nl; - double argh; - long idot, ntry = 0, i, j; - double argld; - long i1, k1, l1, l2, ib; - double fi; - long ld, ii, nf, ipll, nl2, nq, nr; - double arg; - long ido, ipm; - - nl2 = nl; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - j++; - if (j <= 4) { - ntry = factors[(int) (j - 1)]; - } else { - ntry += 2; - } - do { - nq = nl2 / ntry; - nr = nl2 - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - nf++; - wtablel.setDouble(nf + 1 + fourn, ntry); - nl2 = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - long idx = ib + fourn; - wtablel.setDouble(idx + 1, wtablel.getDouble(idx)); - } - wtablel.setDouble(2 + fourn, 2); - } - } while (nl2 != 1); - break; - } - wtablel.setDouble(fourn, nl); - wtablel.setDouble(1 + fourn, nf); - argh = TWO_PI / (double) nl; - i = 1; - l1 = 1; - for (k1 = 1; k1 <= nf; k1++) { - ipll = (long) wtablel.getDouble(k1 + 1 + fourn); - ld = 0; - l2 = l1 * ipll; - ido = nl / l2; - idot = ido + ido + 2; - ipm = ipll - 1; - for (j = 1; j <= ipm; j++) { - i1 = i; - wtablel.setDouble(i - 1 + twon, 1); - wtablel.setDouble(i + twon, 0); - ld += l1; - fi = 0; - argld = ld * argh; - for (ii = 4; ii <= idot; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - long idx = i + twon; - wtablel.setDouble(idx - 1, Math.cos(arg)); - wtablel.setDouble(idx, Math.sin(arg)); - } - if (ipll > 5) { - long idx1 = i1 + twon; - long idx2 = i + twon; - wtablel.setDouble(idx1 - 1, wtablel.getDouble(idx2 - 1)); - wtablel.setDouble(idx1, wtablel.getDouble(idx2)); - } - } - l1 = l2; - } - - } - - void rffti() { - - if (n == 1) { - return; - } - final int twon = 2 * n; - double argh; - int ntry = 0, i, j; - double argld; - int k1, l1, l2, ib; - double fi; - int ld, ii, nf, ipll, nll, is, nq, nr; - double arg; - int ido, ipm; - int nfm1; - - nll = n; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - ++j; - if (j <= 4) { - ntry = factors[j - 1]; - } else { - ntry += 2; - } - do { - nq = nll / ntry; - nr = nll - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - ++nf; - wtable_r[nf + 1 + twon] = ntry; - - nll = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - int idx = ib + twon; - wtable_r[idx + 1] = wtable_r[idx]; - } - wtable_r[2 + twon] = 2; - } - } while (nll != 1); - break; - } - wtable_r[twon] = n; - wtable_r[1 + twon] = nf; - argh = TWO_PI / (double) (n); - is = 0; - nfm1 = nf - 1; - l1 = 1; - if (nfm1 == 0) { - return; - } - for (k1 = 1; k1 <= nfm1; k1++) { - ipll = (int) wtable_r[k1 + 1 + twon]; - ld = 0; - l2 = l1 * ipll; - ido = n / l2; - ipm = ipll - 1; - for (j = 1; j <= ipm; ++j) { - ld += l1; - i = is; - argld = (double) ld * argh; - - fi = 0; - for (ii = 3; ii <= ido; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - int idx = i + n; - wtable_r[idx - 2] = Math.cos(arg); - wtable_r[idx - 1] = Math.sin(arg); - } - is += ido; - } - l1 = l2; - } - } - - void rfftil() { - - if (nl == 1) { - return; - } - final long twon = 2 * nl; - double argh; - long ntry = 0, i, j; - double argld; - long k1, l1, l2, ib; - double fi; - long ld, ii, nf, ipll, nl2, is, nq, nr; - double arg; - long ido, ipm; - long nfm1; - - nl2 = nl; - nf = 0; - j = 0; - - factorize_loop: - while (true) { - ++j; - if (j <= 4) { - ntry = factors[(int) (j - 1)]; - } else { - ntry += 2; - } - do { - nq = nl2 / ntry; - nr = nl2 - ntry * nq; - if (nr != 0) { - continue factorize_loop; - } - ++nf; - wtable_rl.setDouble(nf + 1 + twon, ntry); - - nl2 = nq; - if (ntry == 2 && nf != 1) { - for (i = 2; i <= nf; i++) { - ib = nf - i + 2; - long idx = ib + twon; - wtable_rl.setDouble(idx + 1, wtable_rl.getDouble(idx)); - } - wtable_rl.setDouble(2 + twon, 2); - } - } while (nl2 != 1); - break; - } - wtable_rl.setDouble(twon, nl); - wtable_rl.setDouble(1 + twon, nf); - argh = TWO_PI / (double) (nl); - is = 0; - nfm1 = nf - 1; - l1 = 1; - if (nfm1 == 0) { - return; - } - for (k1 = 1; k1 <= nfm1; k1++) { - ipll = (long) wtable_rl.getDouble(k1 + 1 + twon); - ld = 0; - l2 = l1 * ipll; - ido = nl / l2; - ipm = ipll - 1; - for (j = 1; j <= ipm; ++j) { - ld += l1; - i = is; - argld = (double) ld * argh; - - fi = 0; - for (ii = 3; ii <= ido; ii += 2) { - i += 2; - fi += 1; - arg = fi * argld; - long idx = i + nl; - wtable_rl.setDouble(idx - 2, Math.cos(arg)); - wtable_rl.setDouble(idx - 1, Math.sin(arg)); - } - is += ido; - } - l1 = l2; - } - } - - private void bluesteini() { - int k = 0; - double arg; - double pi_n = PI / n; - bk1[0] = 1; - bk1[1] = 0; - for (int i = 1; i < n; i++) { - k += 2 * i - 1; - if (k >= 2 * n) { - k -= 2 * n; - } - arg = pi_n * k; - bk1[2 * i] = Math.cos(arg); - bk1[2 * i + 1] = Math.sin(arg); - } - double scale = 1.0 / nBluestein; - bk2[0] = bk1[0] * scale; - bk2[1] = bk1[1] * scale; - for (int i = 2; i < 2 * n; i += 2) { - bk2[i] = bk1[i] * scale; - bk2[i + 1] = bk1[i + 1] * scale; - bk2[2 * nBluestein - i] = bk2[i]; - bk2[2 * nBluestein - i + 1] = bk2[i + 1]; - } - CommonUtils.cftbsub(2 * nBluestein, bk2, 0, ip, nw, w); - } - - private void bluesteinil() { - long k = 0; - double arg; - double pi_n = PI / nl; - bk1l.setDouble(0, 1); - bk1l.setDouble(1, 0); - for (int i = 1; i < nl; i++) { - k += 2 * i - 1; - if (k >= 2 * nl) { - k -= 2 * nl; - } - arg = pi_n * k; - bk1l.setDouble(2 * i, Math.cos(arg)); - bk1l.setDouble(2 * i + 1, Math.sin(arg)); - } - double scale = 1.0 / nBluesteinl; - bk2l.setDouble(0, bk1l.getDouble(0) * scale); - bk2l.setDouble(1, bk1l.getDouble(1) * scale); - for (int i = 2; i < 2 * nl; i += 2) { - bk2l.setDouble(i, bk1l.getDouble(i) * scale); - bk2l.setDouble(i + 1, bk1l.getDouble(i + 1) * scale); - bk2l.setDouble(2 * nBluesteinl - i, bk2l.getDouble(i)); - bk2l.setDouble(2 * nBluesteinl - i + 1, bk2l.getDouble(i + 1)); - } - CommonUtils.cftbsub(2 * nBluesteinl, bk2l, 0, ipl, nwl, wl); - } - - private void bluestein_complex(final double[] a, final int offa, final int isign) { - final double[] ak = new double[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = -a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[idx4] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - a[idx3] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[idx4] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - } - - private void bluestein_complex(final DoubleLargeArray a, final long offa, final int isign) { - final DoubleLargeArray ak = new DoubleLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) - a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) + a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setDouble(idx3, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(idx4, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setDouble(idx3, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(idx4, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) - a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) + a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } else { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setDouble(idx3, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(idx4, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - a.setDouble(idx3, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(idx4, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } - } - } - - private void bluestein_real_full(final double[] a, final int offa, final int isign) { - final double[] ak = new double[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } else { - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (isign > 0) { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } - } - } - - private void bluestein_real_full(final DoubleLargeArray a, final long offa, final long isign) { - final DoubleLargeArray ak = new DoubleLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - if (isign > 0) { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } else { - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (isign > 0) { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } - } - } - - private void bluestein_real_forward(final double[] a, final int offa) { - final double[] ak = new double[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = -a[idx3] * bk1[idx2]; - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] - ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (n % 2 == 0) { - a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n] + bk1[n + 1] * ak[n + 1]; - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - a[offa] = bk1[0] * ak[0] + bk1[1] * ak[1]; - a[offa + 1] = -bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] + bk1[idx2] * ak[idx2]; - a[offa + idx2] = -bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - a[offa + n - 1] = bk1[n - 1] * ak[n - 1] + bk1[n] * ak[n]; - } - - } - - private void bluestein_real_forward(final DoubleLargeArray a, final long offa) { - final DoubleLargeArray ak = new DoubleLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, -a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) - ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (nl % 2 == 0) { - a.setDouble(offa, bk1l.getDouble(0) * ak.getDouble(0) + bk1l.getDouble(1) * ak.getDouble(1)); - a.setDouble(offa + 1, bk1l.getDouble(nl) * ak.getDouble(nl) + bk1l.getDouble(nl + 1) * ak.getDouble(nl + 1)); - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - a.setDouble(offa, bk1l.getDouble(0) * ak.getDouble(0) + bk1l.getDouble(1) * ak.getDouble(1)); - a.setDouble(offa + 1, -bk1l.getDouble(nl) * ak.getDouble(nl - 1) + bk1l.getDouble(nl - 1) * ak.getDouble(nl)); - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) + bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, -bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - a.setDouble(offa + nl - 1, bk1l.getDouble(nl - 1) * ak.getDouble(nl - 1) + bk1l.getDouble(nl) * ak.getDouble(nl)); - } - - } - - private void bluestein_real_inverse(final double[] a, final int offa) { - final double[] ak = new double[2 * nBluestein]; - if (n % 2 == 0) { - ak[0] = a[offa] * bk1[0]; - ak[1] = a[offa] * bk1[1]; - - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - - ak[n] = a[offa + 1] * bk1[n]; - ak[n + 1] = a[offa + 1] * bk1[n + 1]; - - for (int i = n / 2 + 1; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + 2 * n - idx1; - int idx4 = idx3 + 1; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; - } - - } else { - ak[0] = a[offa] * bk1[0]; - ak[1] = a[offa] * bk1[1]; - - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + idx1; - int idx4 = offa + idx2; - ak[idx1] = a[idx3] * bk1[idx1] - a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] + a[idx4] * bk1[idx1]; - } - - ak[n - 1] = a[offa + n - 1] * bk1[n - 1] - a[offa + 1] * bk1[n]; - ak[n] = a[offa + n - 1] * bk1[n] + a[offa + 1] * bk1[n - 1]; - - ak[n + 1] = a[offa + n - 1] * bk1[n + 1] + a[offa + 1] * bk1[n + 2]; - ak[n + 2] = a[offa + n - 1] * bk1[n + 2] - a[offa + 1] * bk1[n + 1]; - - for (int i = (n - 1) / 2 + 2; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + 2 * n - idx1; - int idx4 = idx3 + 1; - ak[idx1] = a[idx3] * bk1[idx1] + a[idx4] * bk1[idx2]; - ak[idx2] = a[idx3] * bk1[idx2] - a[idx4] * bk1[idx1]; - } - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + i] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - } - } - } - - private void bluestein_real_inverse(final DoubleLargeArray a, final long offa) { - final DoubleLargeArray ak = new DoubleLargeArray(2 * nBluesteinl, false); - if (nl % 2 == 0) { - ak.setDouble(0, a.getDouble(offa) * bk1l.getDouble(0)); - ak.setDouble(1, a.getDouble(offa) * bk1l.getDouble(1)); - - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) - a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - - ak.setDouble(nl, a.getDouble(offa + 1) * bk1l.getDouble(nl)); - ak.setDouble(nl + 1, a.getDouble(offa + 1) * bk1l.getDouble(nl + 1)); - - for (long i = nl / 2 + 1; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + 2 * nl - idx1; - long idx4 = idx3 + 1; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) + a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) - a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - - } else { - ak.setDouble(0, a.getDouble(offa) * bk1l.getDouble(0)); - ak.setDouble(1, a.getDouble(offa) * bk1l.getDouble(1)); - - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + idx1; - long idx4 = offa + idx2; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) - a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) + a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - - ak.setDouble(nl - 1, a.getDouble(offa + nl - 1) * bk1l.getDouble(nl - 1) - a.getDouble(offa + 1) * bk1l.getDouble(nl)); - ak.setDouble(nl, a.getDouble(offa + nl - 1) * bk1l.getDouble(nl) + a.getDouble(offa + 1) * bk1l.getDouble(nl - 1)); - - ak.setDouble(nl + 1, a.getDouble(offa + nl - 1) * bk1l.getDouble(nl + 1) + a.getDouble(offa + 1) * bk1l.getDouble(nl + 2)); - ak.setDouble(nl + 2, a.getDouble(offa + nl - 1) * bk1l.getDouble(nl + 2) - a.getDouble(offa + 1) * bk1l.getDouble(nl + 1)); - - for (long i = (nl - 1) / 2 + 2; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + 2 * nl - idx1; - long idx4 = idx3 + 1; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1) + a.getDouble(idx4) * bk1l.getDouble(idx2)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2) - a.getDouble(idx4) * bk1l.getDouble(idx1)); - } - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + i, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + i, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - } - } - } - - private void bluestein_real_inverse2(final double[] a, final int offa) { - final double[] ak = new double[2 * nBluestein]; - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (n >= ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - int k = n / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? n : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - k = nBluestein / nthreads; - for (int i = 0; i < nthreads; i++) { - final int firstIdx = i * k; - final int lastIdx = (i == (nthreads - 1)) ? nBluestein : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (int i = firstIdx; i < lastIdx; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int i = 0; i < n; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - int idx3 = offa + i; - ak[idx1] = a[idx3] * bk1[idx1]; - ak[idx2] = a[idx3] * bk1[idx2]; - } - - CommonUtils.cftbsub(2 * nBluestein, ak, 0, ip, nw, w); - - for (int i = 0; i < nBluestein; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - double im = -ak[idx1] * bk2[idx2] + ak[idx2] * bk2[idx1]; - ak[idx1] = ak[idx1] * bk2[idx1] + ak[idx2] * bk2[idx2]; - ak[idx2] = im; - } - } - - CommonUtils.cftfsub(2 * nBluestein, ak, 0, ip, nw, w); - - if (n % 2 == 0) { - a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n] - bk1[n + 1] * ak[n + 1]; - for (int i = 1; i < n / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - } else { - a[offa] = bk1[0] * ak[0] - bk1[1] * ak[1]; - a[offa + 1] = bk1[n] * ak[n - 1] + bk1[n - 1] * ak[n]; - for (int i = 1; i < (n - 1) / 2; i++) { - int idx1 = 2 * i; - int idx2 = idx1 + 1; - a[offa + idx1] = bk1[idx1] * ak[idx1] - bk1[idx2] * ak[idx2]; - a[offa + idx2] = bk1[idx2] * ak[idx1] + bk1[idx1] * ak[idx2]; - } - a[offa + n - 1] = bk1[n - 1] * ak[n - 1] - bk1[n] * ak[n]; - } - } - - private void bluestein_real_inverse2(final DoubleLargeArray a, final long offa) { - final DoubleLargeArray ak = new DoubleLargeArray(2 * nBluesteinl, false); - int threads = ConcurrencyUtils.getNumberOfThreads(); - if ((threads > 1) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_2Threads())) { - int nthreads = 2; - if ((threads >= 4) && (nl > ConcurrencyUtils.getThreadsBeginN_1D_FFT_4Threads())) { - nthreads = 4; - } - Future[] futures = new Future[nthreads]; - long k = nl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - k = nBluesteinl / nthreads; - for (int i = 0; i < nthreads; i++) { - final long firstIdx = i * k; - final long lastIdx = (i == (nthreads - 1)) ? nBluesteinl : firstIdx + k; - futures[i] = ConcurrencyUtils.submit(new Runnable() { - public void run() { - for (long i = firstIdx; i < lastIdx; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long i = 0; i < nl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - long idx3 = offa + i; - ak.setDouble(idx1, a.getDouble(idx3) * bk1l.getDouble(idx1)); - ak.setDouble(idx2, a.getDouble(idx3) * bk1l.getDouble(idx2)); - } - - CommonUtils.cftbsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - for (long i = 0; i < nBluesteinl; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - double im = -ak.getDouble(idx1) * bk2l.getDouble(idx2) + ak.getDouble(idx2) * bk2l.getDouble(idx1); - ak.setDouble(idx1, ak.getDouble(idx1) * bk2l.getDouble(idx1) + ak.getDouble(idx2) * bk2l.getDouble(idx2)); - ak.setDouble(idx2, im); - } - } - - CommonUtils.cftfsub(2 * nBluesteinl, ak, 0, ipl, nwl, wl); - - if (nl % 2 == 0) { - a.setDouble(offa, bk1l.getDouble(0) * ak.getDouble(0) - bk1l.getDouble(1) * ak.getDouble(1)); - a.setDouble(offa + 1, bk1l.getDouble(nl) * ak.getDouble(nl) - bk1l.getDouble(nl + 1) * ak.getDouble(nl + 1)); - for (long i = 1; i < nl / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - } else { - a.setDouble(offa, bk1l.getDouble(0) * ak.getDouble(0) - bk1l.getDouble(1) * ak.getDouble(1)); - a.setDouble(offa + 1, bk1l.getDouble(nl) * ak.getDouble(nl - 1) + bk1l.getDouble(nl - 1) * ak.getDouble(nl)); - for (long i = 1; i < (nl - 1) / 2; i++) { - long idx1 = 2 * i; - long idx2 = idx1 + 1; - a.setDouble(offa + idx1, bk1l.getDouble(idx1) * ak.getDouble(idx1) - bk1l.getDouble(idx2) * ak.getDouble(idx2)); - a.setDouble(offa + idx2, bk1l.getDouble(idx2) * ak.getDouble(idx1) + bk1l.getDouble(idx1) * ak.getDouble(idx2)); - } - a.setDouble(offa + nl - 1, bk1l.getDouble(nl - 1) * ak.getDouble(nl - 1) - bk1l.getDouble(nl) * ak.getDouble(nl)); - } - } - - /*--------------------------------------------------------- - rfftf1: further processing of Real forward FFT - --------------------------------------------------------*/ - void rfftf(final double a[], final int offa) { - if (n == 1) { - return; - } - int l1, l2, na, kh, nf, ipll, iw, ido, idl1; - - final double[] ch = new double[n]; - final int twon = 2 * n; - nf = (int) wtable_r[1 + twon]; - na = 1; - l2 = n; - iw = twon - 1; - for (int k1 = 1; k1 <= nf; ++k1) { - kh = nf - k1; - ipll = (int) wtable_r[kh + 2 + twon]; - l1 = l2 / ipll; - ido = n / l2; - idl1 = ido * l1; - iw -= (ipll - 1) * ido; - na = 1 - na; - switch (ipll) { - case 2: - if (na == 0) { - radf2(ido, l1, a, offa, ch, 0, iw); - } else { - radf2(ido, l1, ch, 0, a, offa, iw); - } - break; - case 3: - if (na == 0) { - radf3(ido, l1, a, offa, ch, 0, iw); - } else { - radf3(ido, l1, ch, 0, a, offa, iw); - } - break; - case 4: - if (na == 0) { - radf4(ido, l1, a, offa, ch, 0, iw); - } else { - radf4(ido, l1, ch, 0, a, offa, iw); - } - break; - case 5: - if (na == 0) { - radf5(ido, l1, a, offa, ch, 0, iw); - } else { - radf5(ido, l1, ch, 0, a, offa, iw); - } - break; - default: - if (ido == 1) { - na = 1 - na; - } - if (na == 0) { - radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - na = 1; - } else { - radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - na = 0; - } - break; - } - l2 = l1; - } - if (na == 1) { - return; - } - System.arraycopy(ch, 0, a, offa, n); - } - - /*--------------------------------------------------------- - rfftf1: further processing of Real forward FFT - --------------------------------------------------------*/ - void rfftf(final DoubleLargeArray a, final long offa) { - if (nl == 1) { - return; - } - long l1, l2, na, kh, nf, iw, ido, idl1; - int ipll; - - final DoubleLargeArray ch = new DoubleLargeArray(nl, false); - final long twon = 2 * nl; - nf = (long) wtable_rl.getDouble(1 + twon); - na = 1; - l2 = nl; - iw = twon - 1; - for (long k1 = 1; k1 <= nf; ++k1) { - kh = nf - k1; - ipll = (int) wtable_rl.getDouble(kh + 2 + twon); - l1 = l2 / ipll; - ido = nl / l2; - idl1 = ido * l1; - iw -= (ipll - 1) * ido; - na = 1 - na; - switch (ipll) { - case 2: - if (na == 0) { - radf2(ido, l1, a, offa, ch, 0, iw); - } else { - radf2(ido, l1, ch, 0, a, offa, iw); - } - break; - case 3: - if (na == 0) { - radf3(ido, l1, a, offa, ch, 0, iw); - } else { - radf3(ido, l1, ch, 0, a, offa, iw); - } - break; - case 4: - if (na == 0) { - radf4(ido, l1, a, offa, ch, 0, iw); - } else { - radf4(ido, l1, ch, 0, a, offa, iw); - } - break; - case 5: - if (na == 0) { - radf5(ido, l1, a, offa, ch, 0, iw); - } else { - radf5(ido, l1, ch, 0, a, offa, iw); - } - break; - default: - if (ido == 1) { - na = 1 - na; - } - if (na == 0) { - radfg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - na = 1; - } else { - radfg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - na = 0; - } - break; - } - l2 = l1; - } - if (na == 1) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, nl); - } - - /*--------------------------------------------------------- - rfftb1: further processing of Real backward FFT - --------------------------------------------------------*/ - void rfftb(final double a[], final int offa) { - if (n == 1) { - return; - } - int l1, l2, na, nf, ipll, iw, ido, idl1; - - double[] ch = new double[n]; - final int twon = 2 * n; - nf = (int) wtable_r[1 + twon]; - na = 0; - l1 = 1; - iw = n; - for (int k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable_r[k1 + 1 + twon]; - l2 = ipll * l1; - ido = n / l2; - idl1 = ido * l1; - switch (ipll) { - case 2: - if (na == 0) { - radb2(ido, l1, a, offa, ch, 0, iw); - } else { - radb2(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - radb3(ido, l1, a, offa, ch, 0, iw); - } else { - radb3(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 4: - if (na == 0) { - radb4(ido, l1, a, offa, ch, 0, iw); - } else { - radb4(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - radb5(ido, l1, a, offa, ch, 0, iw); - } else { - radb5(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - default: - if (na == 0) { - radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - } else { - radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - } - if (ido == 1) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * ido; - } - if (na == 0) { - return; - } - System.arraycopy(ch, 0, a, offa, n); - } - - /*--------------------------------------------------------- - rfftb1: further processing of Real backward FFT - --------------------------------------------------------*/ - void rfftb(final DoubleLargeArray a, final long offa) { - if (nl == 1) { - return; - } - long l1, l2, na, nf, iw, ido, idl1; - int ipll; - DoubleLargeArray ch = new DoubleLargeArray(nl, false); - final long twon = 2 * nl; - nf = (long) wtable_rl.getDouble(1 + twon); - na = 0; - l1 = 1; - iw = nl; - for (long k1 = 1; k1 <= nf; k1++) { - ipll = (int) wtable_rl.getDouble(k1 + 1 + twon); - l2 = ipll * l1; - ido = nl / l2; - idl1 = ido * l1; - switch (ipll) { - case 2: - if (na == 0) { - radb2(ido, l1, a, offa, ch, 0, iw); - } else { - radb2(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - radb3(ido, l1, a, offa, ch, 0, iw); - } else { - radb3(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 4: - if (na == 0) { - radb4(ido, l1, a, offa, ch, 0, iw); - } else { - radb4(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - radb5(ido, l1, a, offa, ch, 0, iw); - } else { - radb5(ido, l1, ch, 0, a, offa, iw); - } - na = 1 - na; - break; - default: - if (na == 0) { - radbg(ido, ipll, l1, idl1, a, offa, ch, 0, iw); - } else { - radbg(ido, ipll, l1, idl1, ch, 0, a, offa, iw); - } - if (ido == 1) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * ido; - } - if (na == 0) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, nl); - } - - /*------------------------------------------------- - radf2: Real FFT's forward processing of factor 2 - -------------------------------------------------*/ - void radf2(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - int i, ic, idx0, idx1, idx2, idx3, idx4; - double t1i, t1r, w1r, w1i; - int iw1; - iw1 = offset; - idx0 = l1 * ido; - idx1 = 2 * ido; - for (int k = 0; k < l1; k++) { - int oidx1 = out_off + k * idx1; - int oidx2 = oidx1 + idx1 - 1; - int iidx1 = in_off + k * ido; - int iidx2 = iidx1 + idx0; - - double i1r = in[iidx1]; - double i2r = in[iidx2]; - - out[oidx1] = i1r + i2r; - out[oidx2] = i1r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; k++) { - idx1 = k * ido; - idx2 = 2 * idx1; - idx3 = idx2 + ido; - idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int oidx1 = out_off + i + idx2; - int oidx2 = out_off + ic + idx3; - int iidx1 = in_off + i + idx1; - int iidx2 = in_off + i + idx4; - - double a1i = in[iidx1 - 1]; - double a1r = in[iidx1]; - double a2i = in[iidx2 - 1]; - double a2r = in[iidx2]; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - - t1r = w1r * a2i + w1i * a2r; - t1i = w1r * a2r - w1i * a2i; - - out[oidx1] = a1r + t1i; - out[oidx1 - 1] = a1i + t1r; - - out[oidx2] = t1i - a1r; - out[oidx2 - 1] = a1i - t1r; - } - } - if (ido % 2 == 1) { - return; - } - } - idx2 = 2 * idx1; - for (int k = 0; k < l1; k++) { - idx1 = k * ido; - int oidx1 = out_off + idx2 + ido; - int iidx1 = in_off + ido - 1 + idx1; - - out[oidx1] = -in[iidx1 + idx0]; - out[oidx1 - 1] = in[iidx1]; - } - } - - /*------------------------------------------------- - radf2: Real FFT's forward processing of factor 2 - -------------------------------------------------*/ - void radf2(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - long i, ic, idx0, idx1, idx2, idx3, idx4; - double t1i, t1r, w1r, w1i; - long iw1; - iw1 = offset; - idx0 = l1 * ido; - idx1 = 2 * ido; - for (long k = 0; k < l1; k++) { - long oidx1 = out_off + k * idx1; - long oidx2 = oidx1 + idx1 - 1; - long iidx1 = in_off + k * ido; - long iidx2 = iidx1 + idx0; - - double i1r = in.getDouble(iidx1); - double i2r = in.getDouble(iidx2); - - out.setDouble(oidx1, i1r + i2r); - out.setDouble(oidx2, i1r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; k++) { - idx1 = k * ido; - idx2 = 2 * idx1; - idx3 = idx2 + ido; - idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long oidx1 = out_off + i + idx2; - long oidx2 = out_off + ic + idx3; - long iidx1 = in_off + i + idx1; - long iidx2 = in_off + i + idx4; - - double a1i = in.getDouble(iidx1 - 1); - double a1r = in.getDouble(iidx1); - double a2i = in.getDouble(iidx2 - 1); - double a2r = in.getDouble(iidx2); - - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - - t1r = w1r * a2i + w1i * a2r; - t1i = w1r * a2r - w1i * a2i; - - out.setDouble(oidx1, a1r + t1i); - out.setDouble(oidx1 - 1, a1i + t1r); - - out.setDouble(oidx2, t1i - a1r); - out.setDouble(oidx2 - 1, a1i - t1r); - } - } - if (ido % 2 == 1) { - return; - } - } - idx2 = 2 * idx1; - for (long k = 0; k < l1; k++) { - idx1 = k * ido; - long oidx1 = out_off + idx2 + ido; - long iidx1 = in_off + ido - 1 + idx1; - - out.setDouble(oidx1, -in.getDouble(iidx1 + idx0)); - out.setDouble(oidx1 - 1, in.getDouble(iidx1)); - } - } - - /*------------------------------------------------- - radb2: Real FFT's backward processing of factor 2 - -------------------------------------------------*/ - void radb2(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - int i, ic; - double t1i, t1r, w1r, w1i; - int iw1 = offset; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int idx3 = idx2 + ido; - int oidx1 = out_off + idx1; - int iidx1 = in_off + idx2; - int iidx2 = in_off + ido - 1 + idx3; - double i1r = in[iidx1]; - double i2r = in[iidx2]; - out[oidx1] = i1r + i2r; - out[oidx1 + idx0] = i1r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int idx5 = i - 1 + iw1; - int idx6 = out_off + i; - int idx7 = in_off + i; - int idx8 = in_off + ic; - w1r = wtable_r[idx5 - 1]; - w1i = wtable_r[idx5]; - int iidx1 = idx7 + idx2; - int iidx2 = idx8 + idx3; - int oidx1 = idx6 + idx1; - int oidx2 = idx6 + idx4; - t1r = in[iidx1 - 1] - in[iidx2 - 1]; - t1i = in[iidx1] + in[iidx2]; - double i1i = in[iidx1]; - double i1r = in[iidx1 - 1]; - double i2i = in[iidx2]; - double i2r = in[iidx2 - 1]; - - out[oidx1 - 1] = i1r + i2r; - out[oidx1] = i1i - i2i; - out[oidx2 - 1] = w1r * t1r - w1i * t1i; - out[oidx2] = w1r * t1i + w1i * t1r; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 2 * idx1; - int oidx1 = out_off + ido - 1 + idx1; - int iidx1 = in_off + idx2 + ido; - out[oidx1] = 2 * in[iidx1 - 1]; - out[oidx1 + idx0] = -2 * in[iidx1]; - } - } - - /*------------------------------------------------- - radb2: Real FFT's backward processing of factor 2 - -------------------------------------------------*/ - void radb2(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - long i, ic; - double t1i, t1r, w1r, w1i; - long iw1 = offset; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long idx3 = idx2 + ido; - long oidx1 = out_off + idx1; - long iidx1 = in_off + idx2; - long iidx2 = in_off + ido - 1 + idx3; - double i1r = in.getDouble(iidx1); - double i2r = in.getDouble(iidx2); - out.setDouble(oidx1, i1r + i2r); - out.setDouble(oidx1 + idx0, i1r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx1 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long idx5 = i - 1 + iw1; - long idx6 = out_off + i; - long idx7 = in_off + i; - long idx8 = in_off + ic; - w1r = wtable_rl.getDouble(idx5 - 1); - w1i = wtable_rl.getDouble(idx5); - long iidx1 = idx7 + idx2; - long iidx2 = idx8 + idx3; - long oidx1 = idx6 + idx1; - long oidx2 = idx6 + idx4; - t1r = in.getDouble(iidx1 - 1) - in.getDouble(iidx2 - 1); - t1i = in.getDouble(iidx1) + in.getDouble(iidx2); - double i1i = in.getDouble(iidx1); - double i1r = in.getDouble(iidx1 - 1); - double i2i = in.getDouble(iidx2); - double i2r = in.getDouble(iidx2 - 1); - - out.setDouble(oidx1 - 1, i1r + i2r); - out.setDouble(oidx1, i1i - i2i); - out.setDouble(oidx2 - 1, w1r * t1r - w1i * t1i); - out.setDouble(oidx2, w1r * t1i + w1i * t1r); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 2 * idx1; - long oidx1 = out_off + ido - 1 + idx1; - long iidx1 = in_off + idx2 + ido; - out.setDouble(oidx1, 2 * in.getDouble(iidx1 - 1)); - out.setDouble(oidx1 + idx0, -2 * in.getDouble(iidx1)); - } - } - - /*------------------------------------------------- - radf3: Real FFT's forward processing of factor 3 - -------------------------------------------------*/ - void radf3(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - int i, ic; - double ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; - int iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx3 = 2 * idx0; - int idx4 = (3 * k + 1) * ido; - int iidx1 = in_off + idx1; - int iidx2 = iidx1 + idx0; - int iidx3 = iidx1 + idx3; - double i1r = in[iidx1]; - double i2r = in[iidx2]; - double i3r = in[iidx3]; - cr2 = i2r + i3r; - out[out_off + 3 * idx1] = i1r + cr2; - out[out_off + idx4 + ido] = taui * (i3r - i2r); - out[out_off + ido - 1 + idx4] = i1r + taur * cr2; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int idx4 = 3 * idx3; - int idx5 = idx3 + idx0; - int idx6 = idx5 + idx0; - int idx7 = idx4 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - - int idx9 = in_off + i; - int idx10 = out_off + i; - int idx11 = out_off + ic; - int iidx1 = idx9 + idx3; - int iidx2 = idx9 + idx5; - int iidx3 = idx9 + idx6; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - cr2 = dr2 + dr3; - ci2 = di2 + di3; - tr2 = i1i + taur * cr2; - ti2 = i1r + taur * ci2; - tr3 = taui * (di2 - di3); - ti3 = taui * (dr3 - dr2); - - int oidx1 = idx10 + idx4; - int oidx2 = idx11 + idx7; - int oidx3 = idx10 + idx8; - - out[oidx1 - 1] = i1i + cr2; - out[oidx1] = i1r + ci2; - out[oidx2 - 1] = tr2 - tr3; - out[oidx2] = ti3 - ti2; - out[oidx3 - 1] = tr2 + tr3; - out[oidx3] = ti2 + ti3; - } - } - } - - /*------------------------------------------------- - radf3: Real FFT's forward processing of factor 3 - -------------------------------------------------*/ - void radf3(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - long i, ic; - double ci2, di2, di3, cr2, dr2, dr3, ti2, ti3, tr2, tr3, w1r, w2r, w1i, w2i; - long iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx3 = 2 * idx0; - long idx4 = (3 * k + 1) * ido; - long iidx1 = in_off + idx1; - long iidx2 = iidx1 + idx0; - long iidx3 = iidx1 + idx3; - double i1r = in.getDouble(iidx1); - double i2r = in.getDouble(iidx2); - double i3r = in.getDouble(iidx3); - cr2 = i2r + i3r; - out.setDouble(out_off + 3 * idx1, i1r + cr2); - out.setDouble(out_off + idx4 + ido, taui * (i3r - i2r)); - out.setDouble(out_off + ido - 1 + idx4, i1r + taur * cr2); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long idx4 = 3 * idx3; - long idx5 = idx3 + idx0; - long idx6 = idx5 + idx0; - long idx7 = idx4 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - - long idx9 = in_off + i; - long idx10 = out_off + i; - long idx11 = out_off + ic; - long iidx1 = idx9 + idx3; - long iidx2 = idx9 + idx5; - long iidx3 = idx9 + idx6; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - cr2 = dr2 + dr3; - ci2 = di2 + di3; - tr2 = i1i + taur * cr2; - ti2 = i1r + taur * ci2; - tr3 = taui * (di2 - di3); - ti3 = taui * (dr3 - dr2); - - long oidx1 = idx10 + idx4; - long oidx2 = idx11 + idx7; - long oidx3 = idx10 + idx8; - - out.setDouble(oidx1 - 1, i1i + cr2); - out.setDouble(oidx1, i1r + ci2); - out.setDouble(oidx2 - 1, tr2 - tr3); - out.setDouble(oidx2, ti3 - ti2); - out.setDouble(oidx3 - 1, tr2 + tr3); - out.setDouble(oidx3, ti2 + ti3); - } - } - } - - /*------------------------------------------------- - radb3: Real FFT's backward processing of factor 3 - -------------------------------------------------*/ - void radb3(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - int i, ic; - double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; - int iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int iidx1 = in_off + 3 * idx1; - int iidx2 = iidx1 + 2 * ido; - double i1i = in[iidx1]; - - tr2 = 2 * in[iidx2 - 1]; - cr2 = i1i + taur * tr2; - ci3 = 2 * taui * in[iidx2]; - - out[out_off + idx1] = i1i + tr2; - out[out_off + (k + l1) * ido] = cr2 - ci3; - out[out_off + (k + 2 * l1) * ido] = cr2 + ci3; - } - if (ido == 1) { - return; - } - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 3 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx1 + idx0; - int idx6 = idx5 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = in_off + i; - int idx8 = in_off + ic; - int idx9 = out_off + i; - int iidx1 = idx7 + idx2; - int iidx2 = idx7 + idx4; - int iidx3 = idx8 + idx3; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - - tr2 = i2i + i3i; - cr2 = i1i + taur * tr2; - ti2 = i2r - i3r; - ci2 = i1r + taur * ti2; - cr3 = taui * (i2i - i3i); - ci3 = taui * (i2r + i3r); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - - int oidx1 = idx9 + idx1; - int oidx2 = idx9 + idx5; - int oidx3 = idx9 + idx6; - - out[oidx1 - 1] = i1i + tr2; - out[oidx1] = i1r + ti2; - out[oidx2 - 1] = w1r * dr2 - w1i * di2; - out[oidx2] = w1r * di2 + w1i * dr2; - out[oidx3 - 1] = w2r * dr3 - w2i * di3; - out[oidx3] = w2r * di3 + w2i * dr3; - } - } - } - - /*------------------------------------------------- - radb3: Real FFT's backward processing of factor 3 - -------------------------------------------------*/ - void radb3(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - long i, ic; - double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2, w1r, w2r, w1i, w2i; - long iw1, iw2; - iw1 = offset; - iw2 = iw1 + ido; - - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long iidx1 = in_off + 3 * idx1; - long iidx2 = iidx1 + 2 * ido; - double i1i = in.getDouble(iidx1); - - tr2 = 2 * in.getDouble(iidx2 - 1); - cr2 = i1i + taur * tr2; - ci3 = 2 * taui * in.getDouble(iidx2); - - out.setDouble(out_off + idx1, i1i + tr2); - out.setDouble(out_off + (k + l1) * ido, cr2 - ci3); - out.setDouble(out_off + (k + 2 * l1) * ido, cr2 + ci3); - } - if (ido == 1) { - return; - } - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 3 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx1 + idx0; - long idx6 = idx5 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = in_off + i; - long idx8 = in_off + ic; - long idx9 = out_off + i; - long iidx1 = idx7 + idx2; - long iidx2 = idx7 + idx4; - long iidx3 = idx8 + idx3; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - - tr2 = i2i + i3i; - cr2 = i1i + taur * tr2; - ti2 = i2r - i3r; - ci2 = i1r + taur * ti2; - cr3 = taui * (i2i - i3i); - ci3 = taui * (i2r + i3r); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - - long oidx1 = idx9 + idx1; - long oidx2 = idx9 + idx5; - long oidx3 = idx9 + idx6; - - out.setDouble(oidx1 - 1, i1i + tr2); - out.setDouble(oidx1, i1r + ti2); - out.setDouble(oidx2 - 1, w1r * dr2 - w1i * di2); - out.setDouble(oidx2, w1r * di2 + w1i * dr2); - out.setDouble(oidx3 - 1, w2r * dr3 - w2i * di3); - out.setDouble(oidx3, w2r * di3 + w2i * dr3); - } - } - } - - /*------------------------------------------------- - radf4: Real FFT's forward processing of factor 4 - -------------------------------------------------*/ - void radf4(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double hsqt2 = 0.707106781186547572737310929369414225; - int i, ic; - double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = offset + ido; - iw3 = iw2 + ido; - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - double i1r = in[in_off + idx1]; - double i2r = in[in_off + idx3]; - double i3r = in[in_off + idx4]; - double i4r = in[in_off + idx5]; - - tr1 = i2r + i4r; - tr2 = i1r + i3r; - - int oidx1 = out_off + idx2; - int oidx2 = out_off + idx6 + ido; - - out[oidx1] = tr1 + tr2; - out[oidx2 - 1 + ido + ido] = tr2 - tr1; - out[oidx2 - 1] = i1r - i3r; - out[oidx2] = i4r - i2r; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 + idx0; - int idx3 = idx2 + idx0; - int idx4 = idx3 + idx0; - int idx5 = 4 * idx1; - int idx6 = idx5 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - - int idx9 = in_off + i; - int idx10 = out_off + i; - int idx11 = out_off + ic; - int iidx1 = idx9 + idx1; - int iidx2 = idx9 + idx2; - int iidx3 = idx9 + idx3; - int iidx4 = idx9 + idx4; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - - cr2 = w1r * i2i + w1i * i2r; - ci2 = w1r * i2r - w1i * i2i; - cr3 = w2r * i3i + w2i * i3r; - ci3 = w2r * i3r - w2i * i3i; - cr4 = w3r * i4i + w3i * i4r; - ci4 = w3r * i4r - w3i * i4i; - tr1 = cr2 + cr4; - tr4 = cr4 - cr2; - ti1 = ci2 + ci4; - ti4 = ci2 - ci4; - ti2 = i1r + ci3; - ti3 = i1r - ci3; - tr2 = i1i + cr3; - tr3 = i1i - cr3; - - int oidx1 = idx10 + idx5; - int oidx2 = idx11 + idx6; - int oidx3 = idx10 + idx7; - int oidx4 = idx11 + idx8; - - out[oidx1 - 1] = tr1 + tr2; - out[oidx4 - 1] = tr2 - tr1; - out[oidx1] = ti1 + ti2; - out[oidx4] = ti1 - ti2; - out[oidx3 - 1] = ti4 + tr3; - out[oidx2 - 1] = tr3 - ti4; - out[oidx3] = tr4 + ti3; - out[oidx2] = tr4 - ti3; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - int idx9 = in_off + ido; - int idx10 = out_off + ido; - - double i1i = in[idx9 - 1 + idx1]; - double i2i = in[idx9 - 1 + idx3]; - double i3i = in[idx9 - 1 + idx4]; - double i4i = in[idx9 - 1 + idx5]; - - ti1 = -hsqt2 * (i2i + i4i); - tr1 = hsqt2 * (i2i - i4i); - - out[idx10 - 1 + idx2] = tr1 + i1i; - out[idx10 - 1 + idx7] = i1i - tr1; - out[out_off + idx6] = ti1 - i3i; - out[out_off + idx8] = ti1 + i3i; - } - } - - /*------------------------------------------------- - radf4: Real FFT's forward processing of factor 4 - -------------------------------------------------*/ - void radf4(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double hsqt2 = 0.707106781186547572737310929369414225; - long i, ic; - double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = offset + ido; - iw3 = iw2 + ido; - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - double i1r = in.getDouble(in_off + idx1); - double i2r = in.getDouble(in_off + idx3); - double i3r = in.getDouble(in_off + idx4); - double i4r = in.getDouble(in_off + idx5); - - tr1 = i2r + i4r; - tr2 = i1r + i3r; - - long oidx1 = out_off + idx2; - long oidx2 = out_off + idx6 + ido; - - out.setDouble(oidx1, tr1 + tr2); - out.setDouble(oidx2 - 1 + ido + ido, tr2 - tr1); - out.setDouble(oidx2 - 1, i1r - i3r); - out.setDouble(oidx2, i4r - i2r); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 + idx0; - long idx3 = idx2 + idx0; - long idx4 = idx3 + idx0; - long idx5 = 4 * idx1; - long idx6 = idx5 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - w3r = wtable_rl.getDouble(widx3 - 1); - w3i = wtable_rl.getDouble(widx3); - - long idx9 = in_off + i; - long idx10 = out_off + i; - long idx11 = out_off + ic; - long iidx1 = idx9 + idx1; - long iidx2 = idx9 + idx2; - long iidx3 = idx9 + idx3; - long iidx4 = idx9 + idx4; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - - cr2 = w1r * i2i + w1i * i2r; - ci2 = w1r * i2r - w1i * i2i; - cr3 = w2r * i3i + w2i * i3r; - ci3 = w2r * i3r - w2i * i3i; - cr4 = w3r * i4i + w3i * i4r; - ci4 = w3r * i4r - w3i * i4i; - tr1 = cr2 + cr4; - tr4 = cr4 - cr2; - ti1 = ci2 + ci4; - ti4 = ci2 - ci4; - ti2 = i1r + ci3; - ti3 = i1r - ci3; - tr2 = i1i + cr3; - tr3 = i1i - cr3; - - long oidx1 = idx10 + idx5; - long oidx2 = idx11 + idx6; - long oidx3 = idx10 + idx7; - long oidx4 = idx11 + idx8; - - out.setDouble(oidx1 - 1, tr1 + tr2); - out.setDouble(oidx4 - 1, tr2 - tr1); - out.setDouble(oidx1, ti1 + ti2); - out.setDouble(oidx4, ti1 - ti2); - out.setDouble(oidx3 - 1, ti4 + tr3); - out.setDouble(oidx2 - 1, tr3 - ti4); - out.setDouble(oidx3, tr4 + ti3); - out.setDouble(oidx2, tr4 - ti3); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - long idx9 = in_off + ido; - long idx10 = out_off + ido; - - double i1i = in.getDouble(idx9 - 1 + idx1); - double i2i = in.getDouble(idx9 - 1 + idx3); - double i3i = in.getDouble(idx9 - 1 + idx4); - double i4i = in.getDouble(idx9 - 1 + idx5); - - ti1 = -hsqt2 * (i2i + i4i); - tr1 = hsqt2 * (i2i - i4i); - - out.setDouble(idx10 - 1 + idx2, tr1 + i1i); - out.setDouble(idx10 - 1 + idx7, i1i - tr1); - out.setDouble(out_off + idx6, ti1 - i3i); - out.setDouble(out_off + idx8, ti1 + i3i); - } - } - - /*------------------------------------------------- - radb4: Real FFT's backward processing of factor 4 - -------------------------------------------------*/ - void radb4(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double sqrt2 = 1.41421356237309514547462185873882845; - int i, ic; - double ci2, ci3, ci4, cr2, cr3, cr4; - double ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - - double i1r = in[in_off + idx2]; - double i2r = in[in_off + idx7]; - double i3r = in[in_off + ido - 1 + idx8]; - double i4r = in[in_off + ido - 1 + idx6]; - - tr1 = i1r - i3r; - tr2 = i1r + i3r; - tr3 = i4r + i4r; - tr4 = i2r + i2r; - - out[out_off + idx1] = tr2 + tr3; - out[out_off + idx3] = tr1 - tr4; - out[out_off + idx4] = tr2 - tr3; - out[out_off + idx5] = tr1 + tr4; - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = idx1 + idx0; - int idx3 = idx2 + idx0; - int idx4 = idx3 + idx0; - int idx5 = 4 * idx1; - int idx6 = idx5 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - - int idx12 = in_off + i; - int idx13 = in_off + ic; - int idx14 = out_off + i; - - int iidx1 = idx12 + idx5; - int iidx2 = idx13 + idx6; - int iidx3 = idx12 + idx7; - int iidx4 = idx13 + idx8; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - - ti1 = i1r + i4r; - ti2 = i1r - i4r; - ti3 = i3r - i2r; - tr4 = i3r + i2r; - tr1 = i1i - i4i; - tr2 = i1i + i4i; - ti4 = i3i - i2i; - tr3 = i3i + i2i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 - tr4; - cr4 = tr1 + tr4; - ci2 = ti1 + ti4; - ci4 = ti1 - ti4; - - int oidx1 = idx14 + idx1; - int oidx2 = idx14 + idx2; - int oidx3 = idx14 + idx3; - int oidx4 = idx14 + idx4; - - out[oidx1 - 1] = tr2 + tr3; - out[oidx1] = ti2 + ti3; - out[oidx2 - 1] = w1r * cr2 - w1i * ci2; - out[oidx2] = w1r * ci2 + w1i * cr2; - out[oidx3 - 1] = w2r * cr3 - w2i * ci3; - out[oidx3] = w2r * ci3 + w2i * cr3; - out[oidx4 - 1] = w3r * cr4 - w3i * ci4; - out[oidx4] = w3r * ci4 + w3i * cr4; - } - } - if (ido % 2 == 1) { - return; - } - } - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 4 * idx1; - int idx3 = idx1 + idx0; - int idx4 = idx3 + idx0; - int idx5 = idx4 + idx0; - int idx6 = idx2 + ido; - int idx7 = idx6 + ido; - int idx8 = idx7 + ido; - int idx9 = in_off + ido; - int idx10 = out_off + ido; - - double i1r = in[idx9 - 1 + idx2]; - double i2r = in[idx9 - 1 + idx7]; - double i3r = in[in_off + idx6]; - double i4r = in[in_off + idx8]; - - ti1 = i3r + i4r; - ti2 = i4r - i3r; - tr1 = i1r - i2r; - tr2 = i1r + i2r; - - out[idx10 - 1 + idx1] = tr2 + tr2; - out[idx10 - 1 + idx3] = sqrt2 * (tr1 - ti1); - out[idx10 - 1 + idx4] = ti2 + ti2; - out[idx10 - 1 + idx5] = -sqrt2 * (tr1 + ti1); - } - } - - /*------------------------------------------------- - radb4: Real FFT's backward processing of factor 4 - -------------------------------------------------*/ - void radb4(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double sqrt2 = 1.41421356237309514547462185873882845; - long i, ic; - double ci2, ci3, ci4, cr2, cr3, cr4; - double ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4, w1r, w1i, w2r, w2i, w3r, w3i; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - - double i1r = in.getDouble(in_off + idx2); - double i2r = in.getDouble(in_off + idx7); - double i3r = in.getDouble(in_off + ido - 1 + idx8); - double i4r = in.getDouble(in_off + ido - 1 + idx6); - - tr1 = i1r - i3r; - tr2 = i1r + i3r; - tr3 = i4r + i4r; - tr4 = i2r + i2r; - - out.setDouble(out_off + idx1, tr2 + tr3); - out.setDouble(out_off + idx3, tr1 - tr4); - out.setDouble(out_off + idx4, tr2 - tr3); - out.setDouble(out_off + idx5, tr1 + tr4); - } - if (ido < 2) { - return; - } - if (ido != 2) { - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = idx1 + idx0; - long idx3 = idx2 + idx0; - long idx4 = idx3 + idx0; - long idx5 = 4 * idx1; - long idx6 = idx5 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - w3r = wtable_rl.getDouble(widx3 - 1); - w3i = wtable_rl.getDouble(widx3); - - long idx12 = in_off + i; - long idx13 = in_off + ic; - long idx14 = out_off + i; - - long iidx1 = idx12 + idx5; - long iidx2 = idx13 + idx6; - long iidx3 = idx12 + idx7; - long iidx4 = idx13 + idx8; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - - ti1 = i1r + i4r; - ti2 = i1r - i4r; - ti3 = i3r - i2r; - tr4 = i3r + i2r; - tr1 = i1i - i4i; - tr2 = i1i + i4i; - ti4 = i3i - i2i; - tr3 = i3i + i2i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 - tr4; - cr4 = tr1 + tr4; - ci2 = ti1 + ti4; - ci4 = ti1 - ti4; - - long oidx1 = idx14 + idx1; - long oidx2 = idx14 + idx2; - long oidx3 = idx14 + idx3; - long oidx4 = idx14 + idx4; - - out.setDouble(oidx1 - 1, tr2 + tr3); - out.setDouble(oidx1, ti2 + ti3); - out.setDouble(oidx2 - 1, w1r * cr2 - w1i * ci2); - out.setDouble(oidx2, w1r * ci2 + w1i * cr2); - out.setDouble(oidx3 - 1, w2r * cr3 - w2i * ci3); - out.setDouble(oidx3, w2r * ci3 + w2i * cr3); - out.setDouble(oidx4 - 1, w3r * cr4 - w3i * ci4); - out.setDouble(oidx4, w3r * ci4 + w3i * cr4); - } - } - if (ido % 2 == 1) { - return; - } - } - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 4 * idx1; - long idx3 = idx1 + idx0; - long idx4 = idx3 + idx0; - long idx5 = idx4 + idx0; - long idx6 = idx2 + ido; - long idx7 = idx6 + ido; - long idx8 = idx7 + ido; - long idx9 = in_off + ido; - long idx10 = out_off + ido; - - double i1r = in.getDouble(idx9 - 1 + idx2); - double i2r = in.getDouble(idx9 - 1 + idx7); - double i3r = in.getDouble(in_off + idx6); - double i4r = in.getDouble(in_off + idx8); - - ti1 = i3r + i4r; - ti2 = i4r - i3r; - tr1 = i1r - i2r; - tr2 = i1r + i2r; - - out.setDouble(idx10 - 1 + idx1, tr2 + tr2); - out.setDouble(idx10 - 1 + idx3, sqrt2 * (tr1 - ti1)); - out.setDouble(idx10 - 1 + idx4, ti2 + ti2); - out.setDouble(idx10 - 1 + idx5, -sqrt2 * (tr1 + ti1)); - } - } - - /*------------------------------------------------- - radf5: Real FFT's forward processing of factor 5 - -------------------------------------------------*/ - void radf5(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - int i, ic; - double ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - int iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - int idx11 = out_off + ido - 1; - - double i1r = in[in_off + idx1]; - double i2r = in[in_off + idx7]; - double i3r = in[in_off + idx8]; - double i4r = in[in_off + idx9]; - double i5r = in[in_off + idx10]; - - cr2 = i5r + i2r; - ci5 = i5r - i2r; - cr3 = i4r + i3r; - ci4 = i4r - i3r; - - out[out_off + idx2] = i1r + cr2 + cr3; - out[idx11 + idx3] = i1r + tr11 * cr2 + tr12 * cr3; - out[out_off + idx4] = ti11 * ci5 + ti12 * ci4; - out[idx11 + idx5] = i1r + tr12 * cr2 + tr11 * cr3; - out[out_off + idx6] = ti12 * ci5 - ti11 * ci4; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - int widx4 = i - 1 + iw4; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - w4r = wtable_r[widx4 - 1]; - w4i = wtable_r[widx4]; - - ic = ido - i; - int idx15 = in_off + i; - int idx16 = out_off + i; - int idx17 = out_off + ic; - - int iidx1 = idx15 + idx1; - int iidx2 = idx15 + idx7; - int iidx3 = idx15 + idx8; - int iidx4 = idx15 + idx9; - int iidx5 = idx15 + idx10; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - double i5i = in[iidx5 - 1]; - double i5r = in[iidx5]; - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - dr4 = w3r * i4i + w3i * i4r; - di4 = w3r * i4r - w3i * i4i; - dr5 = w4r * i5i + w4i * i5r; - di5 = w4r * i5r - w4i * i5i; - - cr2 = dr2 + dr5; - ci5 = dr5 - dr2; - cr5 = di2 - di5; - ci2 = di2 + di5; - cr3 = dr3 + dr4; - ci4 = dr4 - dr3; - cr4 = di3 - di4; - ci3 = di3 + di4; - - tr2 = i1i + tr11 * cr2 + tr12 * cr3; - ti2 = i1r + tr11 * ci2 + tr12 * ci3; - tr3 = i1i + tr12 * cr2 + tr11 * cr3; - ti3 = i1r + tr12 * ci2 + tr11 * ci3; - tr5 = ti11 * cr5 + ti12 * cr4; - ti5 = ti11 * ci5 + ti12 * ci4; - tr4 = ti12 * cr5 - ti11 * cr4; - ti4 = ti12 * ci5 - ti11 * ci4; - - int oidx1 = idx16 + idx2; - int oidx2 = idx17 + idx3; - int oidx3 = idx16 + idx4; - int oidx4 = idx17 + idx5; - int oidx5 = idx16 + idx6; - - out[oidx1 - 1] = i1i + cr2 + cr3; - out[oidx1] = i1r + ci2 + ci3; - out[oidx3 - 1] = tr2 + tr5; - out[oidx2 - 1] = tr2 - tr5; - out[oidx3] = ti2 + ti5; - out[oidx2] = ti5 - ti2; - out[oidx5 - 1] = tr3 + tr4; - out[oidx4 - 1] = tr3 - tr4; - out[oidx5] = ti3 + ti4; - out[oidx4] = ti4 - ti3; - } - } - } - - /*------------------------------------------------- - radf5: Real FFT's forward processing of factor 5 - -------------------------------------------------*/ - void radf5(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - long i, ic; - double ci2, di2, ci4, ci5, di3, di4, di5, ci3, cr2, cr3, dr2, dr3, dr4, dr5, cr5, cr4, ti2, ti3, ti5, ti4, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - long iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - long idx11 = out_off + ido - 1; - - double i1r = in.getDouble(in_off + idx1); - double i2r = in.getDouble(in_off + idx7); - double i3r = in.getDouble(in_off + idx8); - double i4r = in.getDouble(in_off + idx9); - double i5r = in.getDouble(in_off + idx10); - - cr2 = i5r + i2r; - ci5 = i5r - i2r; - cr3 = i4r + i3r; - ci4 = i4r - i3r; - - out.setDouble(out_off + idx2, i1r + cr2 + cr3); - out.setDouble(idx11 + idx3, i1r + tr11 * cr2 + tr12 * cr3); - out.setDouble(out_off + idx4, ti11 * ci5 + ti12 * ci4); - out.setDouble(idx11 + idx5, i1r + tr12 * cr2 + tr11 * cr3); - out.setDouble(out_off + idx6, ti12 * ci5 - ti11 * ci4); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - long widx4 = i - 1 + iw4; - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - w3r = wtable_rl.getDouble(widx3 - 1); - w3i = wtable_rl.getDouble(widx3); - w4r = wtable_rl.getDouble(widx4 - 1); - w4i = wtable_rl.getDouble(widx4); - - ic = ido - i; - long idx15 = in_off + i; - long idx16 = out_off + i; - long idx17 = out_off + ic; - - long iidx1 = idx15 + idx1; - long iidx2 = idx15 + idx7; - long iidx3 = idx15 + idx8; - long iidx4 = idx15 + idx9; - long iidx5 = idx15 + idx10; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - double i5i = in.getDouble(iidx5 - 1); - double i5r = in.getDouble(iidx5); - - dr2 = w1r * i2i + w1i * i2r; - di2 = w1r * i2r - w1i * i2i; - dr3 = w2r * i3i + w2i * i3r; - di3 = w2r * i3r - w2i * i3i; - dr4 = w3r * i4i + w3i * i4r; - di4 = w3r * i4r - w3i * i4i; - dr5 = w4r * i5i + w4i * i5r; - di5 = w4r * i5r - w4i * i5i; - - cr2 = dr2 + dr5; - ci5 = dr5 - dr2; - cr5 = di2 - di5; - ci2 = di2 + di5; - cr3 = dr3 + dr4; - ci4 = dr4 - dr3; - cr4 = di3 - di4; - ci3 = di3 + di4; - - tr2 = i1i + tr11 * cr2 + tr12 * cr3; - ti2 = i1r + tr11 * ci2 + tr12 * ci3; - tr3 = i1i + tr12 * cr2 + tr11 * cr3; - ti3 = i1r + tr12 * ci2 + tr11 * ci3; - tr5 = ti11 * cr5 + ti12 * cr4; - ti5 = ti11 * ci5 + ti12 * ci4; - tr4 = ti12 * cr5 - ti11 * cr4; - ti4 = ti12 * ci5 - ti11 * ci4; - - long oidx1 = idx16 + idx2; - long oidx2 = idx17 + idx3; - long oidx3 = idx16 + idx4; - long oidx4 = idx17 + idx5; - long oidx5 = idx16 + idx6; - - out.setDouble(oidx1 - 1, i1i + cr2 + cr3); - out.setDouble(oidx1, i1r + ci2 + ci3); - out.setDouble(oidx3 - 1, tr2 + tr5); - out.setDouble(oidx2 - 1, tr2 - tr5); - out.setDouble(oidx3, ti2 + ti5); - out.setDouble(oidx2, ti5 - ti2); - out.setDouble(oidx5 - 1, tr3 + tr4); - out.setDouble(oidx4 - 1, tr3 - tr4); - out.setDouble(oidx5, ti3 + ti4); - out.setDouble(oidx4, ti4 - ti3); - } - } - } - - /*------------------------------------------------- - radb5: Real FFT's backward processing of factor 5 - -------------------------------------------------*/ - void radb5(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - int i, ic; - double ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - int iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - int idx11 = in_off + ido - 1; - - double i1r = in[in_off + idx2]; - - ti5 = 2 * in[in_off + idx4]; - ti4 = 2 * in[in_off + idx6]; - tr2 = 2 * in[idx11 + idx3]; - tr3 = 2 * in[idx11 + idx5]; - cr2 = i1r + tr11 * tr2 + tr12 * tr3; - cr3 = i1r + tr12 * tr2 + tr11 * tr3; - ci5 = ti11 * ti5 + ti12 * ti4; - ci4 = ti12 * ti5 - ti11 * ti4; - - out[out_off + idx1] = i1r + tr2 + tr3; - out[out_off + idx7] = cr2 - ci5; - out[out_off + idx8] = cr3 - ci4; - out[out_off + idx9] = cr3 + ci4; - out[out_off + idx10] = cr2 + ci5; - } - if (ido == 1) { - return; - } - for (int k = 0; k < l1; ++k) { - int idx1 = k * ido; - int idx2 = 5 * idx1; - int idx3 = idx2 + ido; - int idx4 = idx3 + ido; - int idx5 = idx4 + ido; - int idx6 = idx5 + ido; - int idx7 = idx1 + idx0; - int idx8 = idx7 + idx0; - int idx9 = idx8 + idx0; - int idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - int widx1 = i - 1 + iw1; - int widx2 = i - 1 + iw2; - int widx3 = i - 1 + iw3; - int widx4 = i - 1 + iw4; - w1r = wtable_r[widx1 - 1]; - w1i = wtable_r[widx1]; - w2r = wtable_r[widx2 - 1]; - w2i = wtable_r[widx2]; - w3r = wtable_r[widx3 - 1]; - w3i = wtable_r[widx3]; - w4r = wtable_r[widx4 - 1]; - w4i = wtable_r[widx4]; - - int idx15 = in_off + i; - int idx16 = in_off + ic; - int idx17 = out_off + i; - - int iidx1 = idx15 + idx2; - int iidx2 = idx16 + idx3; - int iidx3 = idx15 + idx4; - int iidx4 = idx16 + idx5; - int iidx5 = idx15 + idx6; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - double i5i = in[iidx5 - 1]; - double i5r = in[iidx5]; - - ti5 = i3r + i2r; - ti2 = i3r - i2r; - ti4 = i5r + i4r; - ti3 = i5r - i4r; - tr5 = i3i - i2i; - tr2 = i3i + i2i; - tr4 = i5i - i4i; - tr3 = i5i + i4i; - - cr2 = i1i + tr11 * tr2 + tr12 * tr3; - ci2 = i1r + tr11 * ti2 + tr12 * ti3; - cr3 = i1i + tr12 * tr2 + tr11 * tr3; - ci3 = i1r + tr12 * ti2 + tr11 * ti3; - cr5 = ti11 * tr5 + ti12 * tr4; - ci5 = ti11 * ti5 + ti12 * ti4; - cr4 = ti12 * tr5 - ti11 * tr4; - ci4 = ti12 * ti5 - ti11 * ti4; - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - int oidx1 = idx17 + idx1; - int oidx2 = idx17 + idx7; - int oidx3 = idx17 + idx8; - int oidx4 = idx17 + idx9; - int oidx5 = idx17 + idx10; - - out[oidx1 - 1] = i1i + tr2 + tr3; - out[oidx1] = i1r + ti2 + ti3; - out[oidx2 - 1] = w1r * dr2 - w1i * di2; - out[oidx2] = w1r * di2 + w1i * dr2; - out[oidx3 - 1] = w2r * dr3 - w2i * di3; - out[oidx3] = w2r * di3 + w2i * dr3; - out[oidx4 - 1] = w3r * dr4 - w3i * di4; - out[oidx4] = w3r * di4 + w3i * dr4; - out[oidx5 - 1] = w4r * dr5 - w4i * di5; - out[oidx5] = w4r * di5 + w4i * dr5; - } - } - } - - /*------------------------------------------------- - radb5: Real FFT's backward processing of factor 5 - -------------------------------------------------*/ - void radb5(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - long i, ic; - double ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5, w1r, w1i, w2r, w2i, w3r, w3i, w4r, w4i; - long iw1, iw2, iw3, iw4; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - long idx11 = in_off + ido - 1; - - double i1r = in.getDouble(in_off + idx2); - - ti5 = 2 * in.getDouble(in_off + idx4); - ti4 = 2 * in.getDouble(in_off + idx6); - tr2 = 2 * in.getDouble(idx11 + idx3); - tr3 = 2 * in.getDouble(idx11 + idx5); - cr2 = i1r + tr11 * tr2 + tr12 * tr3; - cr3 = i1r + tr12 * tr2 + tr11 * tr3; - ci5 = ti11 * ti5 + ti12 * ti4; - ci4 = ti12 * ti5 - ti11 * ti4; - - out.setDouble(out_off + idx1, i1r + tr2 + tr3); - out.setDouble(out_off + idx7, cr2 - ci5); - out.setDouble(out_off + idx8, cr3 - ci4); - out.setDouble(out_off + idx9, cr3 + ci4); - out.setDouble(out_off + idx10, cr2 + ci5); - } - if (ido == 1) { - return; - } - for (long k = 0; k < l1; ++k) { - long idx1 = k * ido; - long idx2 = 5 * idx1; - long idx3 = idx2 + ido; - long idx4 = idx3 + ido; - long idx5 = idx4 + ido; - long idx6 = idx5 + ido; - long idx7 = idx1 + idx0; - long idx8 = idx7 + idx0; - long idx9 = idx8 + idx0; - long idx10 = idx9 + idx0; - for (i = 2; i < ido; i += 2) { - ic = ido - i; - long widx1 = i - 1 + iw1; - long widx2 = i - 1 + iw2; - long widx3 = i - 1 + iw3; - long widx4 = i - 1 + iw4; - w1r = wtable_rl.getDouble(widx1 - 1); - w1i = wtable_rl.getDouble(widx1); - w2r = wtable_rl.getDouble(widx2 - 1); - w2i = wtable_rl.getDouble(widx2); - w3r = wtable_rl.getDouble(widx3 - 1); - w3i = wtable_rl.getDouble(widx3); - w4r = wtable_rl.getDouble(widx4 - 1); - w4i = wtable_rl.getDouble(widx4); - - long idx15 = in_off + i; - long idx16 = in_off + ic; - long idx17 = out_off + i; - - long iidx1 = idx15 + idx2; - long iidx2 = idx16 + idx3; - long iidx3 = idx15 + idx4; - long iidx4 = idx16 + idx5; - long iidx5 = idx15 + idx6; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - double i5i = in.getDouble(iidx5 - 1); - double i5r = in.getDouble(iidx5); - - ti5 = i3r + i2r; - ti2 = i3r - i2r; - ti4 = i5r + i4r; - ti3 = i5r - i4r; - tr5 = i3i - i2i; - tr2 = i3i + i2i; - tr4 = i5i - i4i; - tr3 = i5i + i4i; - - cr2 = i1i + tr11 * tr2 + tr12 * tr3; - ci2 = i1r + tr11 * ti2 + tr12 * ti3; - cr3 = i1i + tr12 * tr2 + tr11 * tr3; - ci3 = i1r + tr12 * ti2 + tr11 * ti3; - cr5 = ti11 * tr5 + ti12 * tr4; - ci5 = ti11 * ti5 + ti12 * ti4; - cr4 = ti12 * tr5 - ti11 * tr4; - ci4 = ti12 * ti5 - ti11 * ti4; - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - long oidx1 = idx17 + idx1; - long oidx2 = idx17 + idx7; - long oidx3 = idx17 + idx8; - long oidx4 = idx17 + idx9; - long oidx5 = idx17 + idx10; - - out.setDouble(oidx1 - 1, i1i + tr2 + tr3); - out.setDouble(oidx1, i1r + ti2 + ti3); - out.setDouble(oidx2 - 1, w1r * dr2 - w1i * di2); - out.setDouble(oidx2, w1r * di2 + w1i * dr2); - out.setDouble(oidx3 - 1, w2r * dr3 - w2i * di3); - out.setDouble(oidx3, w2r * di3 + w2i * dr3); - out.setDouble(oidx4 - 1, w3r * dr4 - w3i * di4); - out.setDouble(oidx4, w3r * di4 + w3i * dr4); - out.setDouble(oidx5 - 1, w4r * dr5 - w4i * di5); - out.setDouble(oidx5, w4r * di5 + w4i * dr5); - } - } - } - - /*--------------------------------------------------------- - radfg: Real FFT's forward processing of general factor - --------------------------------------------------------*/ - void radfg(final int ido, final int ip, final int l1, final int idl1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - int idij, ipph, j2, ic, jc, lc, is, nbd; - double dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; - int iw1 = offset; - - arg = TWO_PI / (double) ip; - dcp = Math.cos(arg); - dsp = Math.sin(arg); - ipph = (ip + 1) / 2; - nbd = (ido - 1) / 2; - if (ido != 1) { - for (int ik = 0; ik < idl1; ik++) { - out[out_off + ik] = in[in_off + ik]; - } - for (int j = 1; j < ip; j++) { - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido + idx1; - out[out_off + idx2] = in[in_off + idx2]; - } - } - if (nbd <= l1) { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - int idx1 = j * l1 * ido; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - int idx4 = in_off + i; - int idx5 = out_off + i; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int oidx1 = idx5 + idx3; - int iidx1 = idx4 + idx3; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - - out[oidx1 - 1] = w1r * i1i + w1i * i1r; - out[oidx1] = w1r * i1r - w1i * i1i; - } - } - } - } else { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = is - 1; - int idx3 = k * ido + idx1; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int oidx1 = out_off + i + idx3; - int iidx1 = in_off + i + idx3; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - - out[oidx1 - 1] = w1r * i1i + w1i * i1r; - out[oidx1] = w1r * i1r - w1i * i1i; - } - } - } - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - for (int i = 2; i < ido; i += 2) { - int idx5 = in_off + i; - int idx6 = out_off + i; - int iidx1 = idx5 + idx3; - int iidx2 = idx5 + idx4; - int oidx1 = idx6 + idx3; - int oidx2 = idx6 + idx4; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - double o2i = out[oidx2 - 1]; - double o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx1] = o1r + o2r; - - in[iidx2 - 1] = o1r - o2r; - in[iidx2] = o2i - o1i; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int i = 2; i < ido; i += 2) { - int idx5 = in_off + i; - int idx6 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - int iidx1 = idx5 + idx3; - int iidx2 = idx5 + idx4; - int oidx1 = idx6 + idx3; - int oidx2 = idx6 + idx4; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - double o2i = out[oidx2 - 1]; - double o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx1] = o1r + o2r; - in[iidx2 - 1] = o1r - o2r; - in[iidx2] = o2i - o1i; - } - } - } - } - } else { - System.arraycopy(out, out_off, in, in_off, idl1); - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int idx4 = k * ido + idx2; - int oidx1 = out_off + idx3; - int oidx2 = out_off + idx4; - double o1r = out[oidx1]; - double o2r = out[oidx2]; - - in[in_off + idx3] = o1r + o2r; - in[in_off + idx4] = o2r - o1r; - } - } - - ar1 = 1; - ai1 = 0; - int idx0 = (ip - 1) * idl1; - for (int l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - int idx1 = l * idl1; - int idx2 = lc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx3 = out_off + ik; - int idx4 = in_off + ik; - out[idx3 + idx1] = in[idx4] + ar1 * in[idx4 + idl1]; - out[idx3 + idx2] = ai1 * in[idx4 + idx0]; - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - int idx3 = j * idl1; - int idx4 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx5 = out_off + ik; - int idx6 = in_off + ik; - out[idx5 + idx1] += ar2 * in[idx6 + idx3]; - out[idx5 + idx2] += ai2 * in[idx6 + idx4]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idx1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - out[out_off + ik] += in[in_off + ik + idx1]; - } - } - - if (ido >= l1) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 * ip; - for (int i = 0; i < ido; i++) { - in[in_off + i + idx2] = out[out_off + i + idx1]; - } - } - } else { - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - in[in_off + i + idx1 * ip] = out[out_off + i + idx1]; - } - } - } - int idx01 = ip * ido; - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido; - int idx5 = idx4 + idx1; - int idx6 = idx4 + idx2; - int idx7 = k * idx01; - in[in_off + ido - 1 + idx3 - ido + idx7] = out[out_off + idx5]; - in[in_off + idx3 + idx7] = out[out_off + idx6]; - } - } - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * idx01; - int idx5 = k * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx6 = in_off + i; - int idx7 = in_off + ic; - int idx8 = out_off + i; - int iidx1 = idx6 + idx3 + idx4; - int iidx2 = idx7 + idx3 - ido + idx4; - int oidx1 = idx8 + idx5 + idx1; - int oidx2 = idx8 + idx5 + idx2; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - double o2i = out[oidx2 - 1]; - double o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx2 - 1] = o1i - o2i; - in[iidx1] = o1r + o2r; - in[iidx2] = o2r - o1r; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx6 = in_off + i; - int idx7 = in_off + ic; - int idx8 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx4 = k * idx01; - int idx5 = k * ido; - int iidx1 = idx6 + idx3 + idx4; - int iidx2 = idx7 + idx3 - ido + idx4; - int oidx1 = idx8 + idx5 + idx1; - int oidx2 = idx8 + idx5 + idx2; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - double o2i = out[oidx2 - 1]; - double o2r = out[oidx2]; - - in[iidx1 - 1] = o1i + o2i; - in[iidx2 - 1] = o1i - o2i; - in[iidx1] = o1r + o2r; - in[iidx2] = o2r - o1r; - } - } - } - } - } - - /*--------------------------------------------------------- - radfg: Real FFT's forward processing of general factor - --------------------------------------------------------*/ - void radfg(final long ido, final long ip, final long l1, final long idl1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - long idij, ipph, j2, ic, jc, lc, is, nbd; - double dc2, ai1, ai2, ar1, ar2, ds2, dcp, arg, dsp, ar1h, ar2h, w1r, w1i; - long iw1 = offset; - - arg = TWO_PI / (double) ip; - dcp = Math.cos(arg); - dsp = Math.sin(arg); - ipph = (ip + 1) / 2; - nbd = (ido - 1) / 2; - if (ido != 1) { - for (long ik = 0; ik < idl1; ik++) { - out.setDouble(out_off + ik, in.getDouble(in_off + ik)); - } - for (long j = 1; j < ip; j++) { - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido + idx1; - out.setDouble(out_off + idx2, in.getDouble(in_off + idx2)); - } - } - if (nbd <= l1) { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - long idx1 = j * l1 * ido; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - long idx4 = in_off + i; - long idx5 = out_off + i; - w1r = wtable_rl.getDouble(idx2 - 1); - w1i = wtable_rl.getDouble(idx2); - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long oidx1 = idx5 + idx3; - long iidx1 = idx4 + idx3; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - - out.setDouble(oidx1 - 1, w1r * i1i + w1i * i1r); - out.setDouble(oidx1, w1r * i1r - w1i * i1i); - } - } - } - } else { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = is - 1; - long idx3 = k * ido + idx1; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getDouble(idx2 - 1); - w1i = wtable_rl.getDouble(idx2); - long oidx1 = out_off + i + idx3; - long iidx1 = in_off + i + idx3; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - - out.setDouble(oidx1 - 1, w1r * i1i + w1i * i1r); - out.setDouble(oidx1, w1r * i1r - w1i * i1i); - } - } - } - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - for (long i = 2; i < ido; i += 2) { - long idx5 = in_off + i; - long idx6 = out_off + i; - long iidx1 = idx5 + idx3; - long iidx2 = idx5 + idx4; - long oidx1 = idx6 + idx3; - long oidx2 = idx6 + idx4; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - double o2i = out.getDouble(oidx2 - 1); - double o2r = out.getDouble(oidx2); - - in.setDouble(iidx1 - 1, o1i + o2i); - in.setDouble(iidx1, o1r + o2r); - - in.setDouble(iidx2 - 1, o1r - o2r); - in.setDouble(iidx2, o2i - o1i); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long i = 2; i < ido; i += 2) { - long idx5 = in_off + i; - long idx6 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - long iidx1 = idx5 + idx3; - long iidx2 = idx5 + idx4; - long oidx1 = idx6 + idx3; - long oidx2 = idx6 + idx4; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - double o2i = out.getDouble(oidx2 - 1); - double o2r = out.getDouble(oidx2); - - in.setDouble(iidx1 - 1, o1i + o2i); - in.setDouble(iidx1, o1r + o2r); - in.setDouble(iidx2 - 1, o1r - o2r); - in.setDouble(iidx2, o2i - o1i); - } - } - } - } - } else { - Utilities.arraycopy(out, out_off, in, in_off, idl1); - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long idx4 = k * ido + idx2; - long oidx1 = out_off + idx3; - long oidx2 = out_off + idx4; - double o1r = out.getDouble(oidx1); - double o2r = out.getDouble(oidx2); - - in.setDouble(in_off + idx3, o1r + o2r); - in.setDouble(in_off + idx4, o2r - o1r); - } - } - - ar1 = 1; - ai1 = 0; - long idx0 = (ip - 1) * idl1; - for (long l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - long idx1 = l * idl1; - long idx2 = lc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx3 = out_off + ik; - long idx4 = in_off + ik; - out.setDouble(idx3 + idx1, in.getDouble(idx4) + ar1 * in.getDouble(idx4 + idl1)); - out.setDouble(idx3 + idx2, ai1 * in.getDouble(idx4 + idx0)); - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - long idx3 = j * idl1; - long idx4 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx5 = out_off + ik; - long idx6 = in_off + ik; - out.setDouble(idx5 + idx1, out.getDouble(idx5 + idx1) + ar2 * in.getDouble(idx6 + idx3)); - out.setDouble(idx5 + idx2, out.getDouble(idx5 + idx2) + ai2 * in.getDouble(idx6 + idx4)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idx1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - out.setDouble(out_off + ik, out.getDouble(out_off + ik) + in.getDouble(in_off + ik + idx1)); - } - } - - if (ido >= l1) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 * ip; - for (long i = 0; i < ido; i++) { - in.setDouble(in_off + i + idx2, out.getDouble(out_off + i + idx1)); - } - } - } else { - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - in.setDouble(in_off + i + idx1 * ip, out.getDouble(out_off + i + idx1)); - } - } - } - long idx01 = ip * ido; - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido; - long idx5 = idx4 + idx1; - long idx6 = idx4 + idx2; - long idx7 = k * idx01; - in.setDouble(in_off + ido - 1 + idx3 - ido + idx7, out.getDouble(out_off + idx5)); - in.setDouble(in_off + idx3 + idx7, out.getDouble(out_off + idx6)); - } - } - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * idx01; - long idx5 = k * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx6 = in_off + i; - long idx7 = in_off + ic; - long idx8 = out_off + i; - long iidx1 = idx6 + idx3 + idx4; - long iidx2 = idx7 + idx3 - ido + idx4; - long oidx1 = idx8 + idx5 + idx1; - long oidx2 = idx8 + idx5 + idx2; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - double o2i = out.getDouble(oidx2 - 1); - double o2r = out.getDouble(oidx2); - - in.setDouble(iidx1 - 1, o1i + o2i); - in.setDouble(iidx2 - 1, o1i - o2i); - in.setDouble(iidx1, o1r + o2r); - in.setDouble(iidx2, o2r - o1r); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx6 = in_off + i; - long idx7 = in_off + ic; - long idx8 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx4 = k * idx01; - long idx5 = k * ido; - long iidx1 = idx6 + idx3 + idx4; - long iidx2 = idx7 + idx3 - ido + idx4; - long oidx1 = idx8 + idx5 + idx1; - long oidx2 = idx8 + idx5 + idx2; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - double o2i = out.getDouble(oidx2 - 1); - double o2r = out.getDouble(oidx2); - - in.setDouble(iidx1 - 1, o1i + o2i); - in.setDouble(iidx2 - 1, o1i - o2i); - in.setDouble(iidx1, o1r + o2r); - in.setDouble(iidx2, o2r - o1r); - } - } - } - } - } - - /*--------------------------------------------------------- - radbg: Real FFT's backward processing of general factor - --------------------------------------------------------*/ - void radbg(final int ido, final int ip, final int l1, final int idl1, final double in[], final int in_off, final double out[], final int out_off, final int offset) { - int idij, ipph, j2, ic, jc, lc, is; - double dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; - int nbd; - double dcp, arg, dsp, ar1h, ar2h; - int iw1 = offset; - - arg = TWO_PI / (double) ip; - dcp = Math.cos(arg); - dsp = Math.sin(arg); - nbd = (ido - 1) / 2; - ipph = (ip + 1) / 2; - int idx0 = ip * ido; - if (ido >= l1) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = k * idx0; - for (int i = 0; i < ido; i++) { - out[out_off + i + idx1] = in[in_off + i + idx2]; - } - } - } else { - for (int i = 0; i < ido; i++) { - int idx1 = out_off + i; - int idx2 = in_off + i; - for (int k = 0; k < l1; k++) { - out[idx1 + k * ido] = in[idx2 + k * idx0]; - } - } - } - int iidx0 = in_off + ido - 1; - for (int j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = j2 * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido; - int idx5 = idx4 * ip; - int iidx1 = iidx0 + idx3 + idx5 - ido; - int iidx2 = in_off + idx3 + idx5; - double i1r = in[iidx1]; - double i2r = in[iidx2]; - - out[out_off + idx4 + idx1] = i1r + i1r; - out[out_off + idx4 + idx2] = i2r + i2r; - } - } - - if (ido != 1) { - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = 2 * j * ido; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido + idx1; - int idx5 = k * ido + idx2; - int idx6 = k * ip * ido + idx3; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = out_off + i; - int idx8 = in_off + ic; - int idx9 = in_off + i; - int oidx1 = idx7 + idx4; - int oidx2 = idx7 + idx5; - int iidx1 = idx9 + idx6; - int iidx2 = idx8 + idx6 - ido; - double a1i = in[iidx1 - 1]; - double a1r = in[iidx1]; - double a2i = in[iidx2 - 1]; - double a2r = in[iidx2]; - - out[oidx1 - 1] = a1i + a2i; - out[oidx2 - 1] = a1i - a2i; - out[oidx1] = a1r - a2r; - out[oidx2] = a1r + a2r; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - int idx3 = 2 * j * ido; - for (int i = 2; i < ido; i += 2) { - ic = ido - i; - int idx7 = out_off + i; - int idx8 = in_off + ic; - int idx9 = in_off + i; - for (int k = 0; k < l1; k++) { - int idx4 = k * ido + idx1; - int idx5 = k * ido + idx2; - int idx6 = k * ip * ido + idx3; - int oidx1 = idx7 + idx4; - int oidx2 = idx7 + idx5; - int iidx1 = idx9 + idx6; - int iidx2 = idx8 + idx6 - ido; - double a1i = in[iidx1 - 1]; - double a1r = in[iidx1]; - double a2i = in[iidx2 - 1]; - double a2r = in[iidx2]; - - out[oidx1 - 1] = a1i + a2i; - out[oidx2 - 1] = a1i - a2i; - out[oidx1] = a1r - a2r; - out[oidx2] = a1r + a2r; - } - } - } - } - } - - ar1 = 1; - ai1 = 0; - int idx01 = (ip - 1) * idl1; - for (int l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - int idx1 = l * idl1; - int idx2 = lc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx3 = in_off + ik; - int idx4 = out_off + ik; - in[idx3 + idx1] = out[idx4] + ar1 * out[idx4 + idl1]; - in[idx3 + idx2] = ai1 * out[idx4 + idx01]; - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - int idx5 = j * idl1; - int idx6 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx7 = in_off + ik; - int idx8 = out_off + ik; - in[idx7 + idx1] += ar2 * out[idx8 + idx5]; - in[idx7 + idx2] += ai2 * out[idx8 + idx6]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idx1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx2 = out_off + ik; - out[idx2] += out[idx2 + idx1]; - } - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int oidx1 = out_off + idx3; - int iidx1 = in_off + idx3 + idx1; - int iidx2 = in_off + idx3 + idx2; - double i1r = in[iidx1]; - double i2r = in[iidx2]; - - out[oidx1 + idx1] = i1r - i2r; - out[oidx1 + idx2] = i1r + i2r; - } - } - - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - for (int i = 2; i < ido; i += 2) { - int idx4 = out_off + i; - int idx5 = in_off + i; - int oidx1 = idx4 + idx3 + idx1; - int oidx2 = idx4 + idx3 + idx2; - int iidx1 = idx5 + idx3 + idx1; - int iidx2 = idx5 + idx3 + idx2; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * l1 * ido; - int idx2 = jc * l1 * ido; - for (int i = 2; i < ido; i += 2) { - int idx4 = out_off + i; - int idx5 = in_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int oidx1 = idx4 + idx3 + idx1; - int oidx2 = idx4 + idx3 + idx2; - int iidx1 = idx5 + idx3 + idx1; - int iidx2 = idx5 + idx3 + idx2; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - } - } - System.arraycopy(out, out_off, in, in_off, idl1); - for (int j = 1; j < ip; j++) { - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido + idx1; - in[in_off + idx2] = out[out_off + idx2]; - } - } - if (nbd <= l1) { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - int idx1 = j * l1 * ido; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int idx4 = in_off + i; - int idx5 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido + idx1; - int iidx1 = idx4 + idx3; - int oidx1 = idx5 + idx3; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } else { - is = -ido; - for (int j = 1; j < ip; j++) { - is += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = is - 1; - int idx3 = k * ido + idx1; - for (int i = 2; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1; - w1r = wtable_r[idx2 - 1]; - w1i = wtable_r[idx2]; - int idx4 = in_off + i; - int idx5 = out_off + i; - int iidx1 = idx4 + idx3; - int oidx1 = idx5 + idx3; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - - } - } - } - } - } - - /*--------------------------------------------------------- - radbg: Real FFT's backward processing of general factor - --------------------------------------------------------*/ - void radbg(final long ido, final long ip, final long l1, final long idl1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset) { - long idij, ipph, j2, ic, jc, lc, is; - double dc2, ai1, ai2, ar1, ar2, ds2, w1r, w1i; - long nbd; - double dcp, arg, dsp, ar1h, ar2h; - long iw1 = offset; - - arg = TWO_PI / (double) ip; - dcp = Math.cos(arg); - dsp = Math.sin(arg); - nbd = (ido - 1) / 2; - ipph = (ip + 1) / 2; - long idx0 = ip * ido; - if (ido >= l1) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = k * idx0; - for (long i = 0; i < ido; i++) { - out.setDouble(out_off + i + idx1, in.getDouble(in_off + i + idx2)); - } - } - } else { - for (long i = 0; i < ido; i++) { - long idx1 = out_off + i; - long idx2 = in_off + i; - for (long k = 0; k < l1; k++) { - out.setDouble(idx1 + k * ido, in.getDouble(idx2 + k * idx0)); - } - } - } - long iidx0 = in_off + ido - 1; - for (long j = 1; j < ipph; j++) { - jc = ip - j; - j2 = 2 * j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = j2 * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido; - long idx5 = idx4 * ip; - long iidx1 = iidx0 + idx3 + idx5 - ido; - long iidx2 = in_off + idx3 + idx5; - double i1r = in.getDouble(iidx1); - double i2r = in.getDouble(iidx2); - - out.setDouble(out_off + idx4 + idx1, i1r + i1r); - out.setDouble(out_off + idx4 + idx2, i2r + i2r); - } - } - - if (ido != 1) { - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = 2 * j * ido; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido + idx1; - long idx5 = k * ido + idx2; - long idx6 = k * ip * ido + idx3; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = out_off + i; - long idx8 = in_off + ic; - long idx9 = in_off + i; - long oidx1 = idx7 + idx4; - long oidx2 = idx7 + idx5; - long iidx1 = idx9 + idx6; - long iidx2 = idx8 + idx6 - ido; - double a1i = in.getDouble(iidx1 - 1); - double a1r = in.getDouble(iidx1); - double a2i = in.getDouble(iidx2 - 1); - double a2r = in.getDouble(iidx2); - - out.setDouble(oidx1 - 1, a1i + a2i); - out.setDouble(oidx2 - 1, a1i - a2i); - out.setDouble(oidx1, a1r - a2r); - out.setDouble(oidx2, a1r + a2r); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - long idx3 = 2 * j * ido; - for (long i = 2; i < ido; i += 2) { - ic = ido - i; - long idx7 = out_off + i; - long idx8 = in_off + ic; - long idx9 = in_off + i; - for (long k = 0; k < l1; k++) { - long idx4 = k * ido + idx1; - long idx5 = k * ido + idx2; - long idx6 = k * ip * ido + idx3; - long oidx1 = idx7 + idx4; - long oidx2 = idx7 + idx5; - long iidx1 = idx9 + idx6; - long iidx2 = idx8 + idx6 - ido; - double a1i = in.getDouble(iidx1 - 1); - double a1r = in.getDouble(iidx1); - double a2i = in.getDouble(iidx2 - 1); - double a2r = in.getDouble(iidx2); - - out.setDouble(oidx1 - 1, a1i + a2i); - out.setDouble(oidx2 - 1, a1i - a2i); - out.setDouble(oidx1, a1r - a2r); - out.setDouble(oidx2, a1r + a2r); - } - } - } - } - } - - ar1 = 1; - ai1 = 0; - long idx01 = (ip - 1) * idl1; - for (long l = 1; l < ipph; l++) { - lc = ip - l; - ar1h = dcp * ar1 - dsp * ai1; - ai1 = dcp * ai1 + dsp * ar1; - ar1 = ar1h; - long idx1 = l * idl1; - long idx2 = lc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx3 = in_off + ik; - long idx4 = out_off + ik; - in.setDouble(idx3 + idx1, out.getDouble(idx4) + ar1 * out.getDouble(idx4 + idl1)); - in.setDouble(idx3 + idx2, ai1 * out.getDouble(idx4 + idx01)); - } - dc2 = ar1; - ds2 = ai1; - ar2 = ar1; - ai2 = ai1; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - ar2h = dc2 * ar2 - ds2 * ai2; - ai2 = dc2 * ai2 + ds2 * ar2; - ar2 = ar2h; - long idx5 = j * idl1; - long idx6 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx7 = in_off + ik; - long idx8 = out_off + ik; - in.setDouble(idx7 + idx1, in.getDouble(idx7 + idx1) + ar2 * out.getDouble(idx8 + idx5)); - in.setDouble(idx7 + idx2, in.getDouble(idx7 + idx2) + ai2 * out.getDouble(idx8 + idx6)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idx1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx2 = out_off + ik; - out.setDouble(idx2, out.getDouble(idx2) + out.getDouble(idx2 + idx1)); - } - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long oidx1 = out_off + idx3; - long iidx1 = in_off + idx3 + idx1; - long iidx2 = in_off + idx3 + idx2; - double i1r = in.getDouble(iidx1); - double i2r = in.getDouble(iidx2); - - out.setDouble(oidx1 + idx1, i1r - i2r); - out.setDouble(oidx1 + idx2, i1r + i2r); - } - } - - if (ido == 1) { - return; - } - if (nbd >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - for (long i = 2; i < ido; i += 2) { - long idx4 = out_off + i; - long idx5 = in_off + i; - long oidx1 = idx4 + idx3 + idx1; - long oidx2 = idx4 + idx3 + idx2; - long iidx1 = idx5 + idx3 + idx1; - long iidx2 = idx5 + idx3 + idx2; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - - out.setDouble(oidx1 - 1, i1i - i2r); - out.setDouble(oidx2 - 1, i1i + i2r); - out.setDouble(oidx1, i1r + i2i); - out.setDouble(oidx2, i1r - i2i); - } - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * l1 * ido; - long idx2 = jc * l1 * ido; - for (long i = 2; i < ido; i += 2) { - long idx4 = out_off + i; - long idx5 = in_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long oidx1 = idx4 + idx3 + idx1; - long oidx2 = idx4 + idx3 + idx2; - long iidx1 = idx5 + idx3 + idx1; - long iidx2 = idx5 + idx3 + idx2; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - - out.setDouble(oidx1 - 1, i1i - i2r); - out.setDouble(oidx2 - 1, i1i + i2r); - out.setDouble(oidx1, i1r + i2i); - out.setDouble(oidx2, i1r - i2i); - } - } - } - } - Utilities.arraycopy(out, out_off, in, in_off, idl1); - for (long j = 1; j < ip; j++) { - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido + idx1; - in.setDouble(in_off + idx2, out.getDouble(out_off + idx2)); - } - } - if (nbd <= l1) { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - idij = is - 1; - long idx1 = j * l1 * ido; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getDouble(idx2 - 1); - w1i = wtable_rl.getDouble(idx2); - long idx4 = in_off + i; - long idx5 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido + idx1; - long iidx1 = idx4 + idx3; - long oidx1 = idx5 + idx3; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - - in.setDouble(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setDouble(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } else { - is = -ido; - for (long j = 1; j < ip; j++) { - is += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = is - 1; - long idx3 = k * ido + idx1; - for (long i = 2; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1; - w1r = wtable_rl.getDouble(idx2 - 1); - w1i = wtable_rl.getDouble(idx2); - long idx4 = in_off + i; - long idx5 = out_off + i; - long iidx1 = idx4 + idx3; - long oidx1 = idx5 + idx3; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - - in.setDouble(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setDouble(iidx1, w1r * o1r + w1i * o1i); - - } - } - } - } - } - - /*--------------------------------------------------------- - cfftf1: further processing of Complex forward FFT - --------------------------------------------------------*/ - void cfftf(double a[], int offa, int isign) { - int idot; - int l1, l2; - int na, nf, ipll, iw, ido, idl1; - int[] nac = new int[1]; - final int twon = 2 * n; - - int iw1, iw2; - double[] ch = new double[twon]; - - iw1 = twon; - iw2 = 4 * n; - nac[0] = 0; - nf = (int) wtable[1 + iw2]; - na = 0; - l1 = 1; - iw = iw1; - for (int k1 = 2; k1 <= nf + 1; k1++) { - ipll = (int) wtable[k1 + iw2]; - l2 = ipll * l1; - ido = n / l2; - idot = ido + ido; - idl1 = idot * l1; - switch (ipll) { - case 4: - if (na == 0) { - passf4(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf4(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 2: - if (na == 0) { - passf2(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf2(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - passf3(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf3(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - passf5(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf5(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - default: - if (na == 0) { - passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); - } else { - passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); - } - if (nac[0] != 0) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * idot; - } - if (na == 0) { - return; - } - System.arraycopy(ch, 0, a, offa, twon); - - } - - /*--------------------------------------------------------- - cfftf1: further processing of Complex forward FFT - --------------------------------------------------------*/ - void cfftf(DoubleLargeArray a, long offa, int isign) { - long idot; - long l1, l2; - long na, nf, iw, ido, idl1; - int[] nac = new int[1]; - final long twon = 2 * nl; - int ipll; - - long iw1, iw2; - DoubleLargeArray ch = new DoubleLargeArray(twon, false); - - iw1 = twon; - iw2 = 4 * nl; - nac[0] = 0; - nf = (long) wtablel.getDouble(1 + iw2); - na = 0; - l1 = 1; - iw = iw1; - for (long k1 = 2; k1 <= nf + 1; k1++) { - ipll = (int) wtablel.getDouble(k1 + iw2); - l2 = ipll * l1; - ido = nl / l2; - idot = ido + ido; - idl1 = idot * l1; - switch (ipll) { - case 4: - if (na == 0) { - passf4(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf4(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 2: - if (na == 0) { - passf2(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf2(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 3: - if (na == 0) { - passf3(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf3(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - case 5: - if (na == 0) { - passf5(idot, l1, a, offa, ch, 0, iw, isign); - } else { - passf5(idot, l1, ch, 0, a, offa, iw, isign); - } - na = 1 - na; - break; - default: - if (na == 0) { - passfg(nac, idot, ipll, l1, idl1, a, offa, ch, 0, iw, isign); - } else { - passfg(nac, idot, ipll, l1, idl1, ch, 0, a, offa, iw, isign); - } - if (nac[0] != 0) { - na = 1 - na; - } - break; - } - l1 = l2; - iw += (ipll - 1) * idot; - } - if (na == 0) { - return; - } - Utilities.arraycopy(ch, 0, a, offa, twon); - - } - - /*---------------------------------------------------------------------- - passf2: Complex FFT's forward/backward processing of factor 2; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf2(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset, final int isign) { - double t1i, t1r; - int iw1; - iw1 = offset; - int idx = ido * l1; - if (ido <= 2) { - for (int k = 0; k < l1; k++) { - int idx0 = k * ido; - int iidx1 = in_off + 2 * idx0; - int iidx2 = iidx1 + ido; - double a1r = in[iidx1]; - double a1i = in[iidx1 + 1]; - double a2r = in[iidx2]; - double a2i = in[iidx2 + 1]; - - int oidx1 = out_off + idx0; - int oidx2 = oidx1 + idx; - out[oidx1] = a1r + a2r; - out[oidx1 + 1] = a1i + a2i; - out[oidx2] = a1r - a2r; - out[oidx2 + 1] = a1i - a2i; - } - } else { - for (int k = 0; k < l1; k++) { - for (int i = 0; i < ido - 1; i += 2) { - int idx0 = k * ido; - int iidx1 = in_off + i + 2 * idx0; - int iidx2 = iidx1 + ido; - double i1r = in[iidx1]; - double i1i = in[iidx1 + 1]; - double i2r = in[iidx2]; - double i2i = in[iidx2 + 1]; - - int widx1 = i + iw1; - double w1r = wtable[widx1]; - double w1i = isign * wtable[widx1 + 1]; - - t1r = i1r - i2r; - t1i = i1i - i2i; - - int oidx1 = out_off + i + idx0; - int oidx2 = oidx1 + idx; - out[oidx1] = i1r + i2r; - out[oidx1 + 1] = i1i + i2i; - out[oidx2] = w1r * t1r - w1i * t1i; - out[oidx2 + 1] = w1r * t1i + w1i * t1r; - } - } - } - } - - /*---------------------------------------------------------------------- - passf2: Complex FFT's forward/backward processing of factor 2; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf2(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset, final long isign) { - double t1i, t1r; - long iw1; - iw1 = offset; - long idx = ido * l1; - if (ido <= 2) { - for (long k = 0; k < l1; k++) { - long idx0 = k * ido; - long iidx1 = in_off + 2 * idx0; - long iidx2 = iidx1 + ido; - double a1r = in.getDouble(iidx1); - double a1i = in.getDouble(iidx1 + 1); - double a2r = in.getDouble(iidx2); - double a2i = in.getDouble(iidx2 + 1); - - long oidx1 = out_off + idx0; - long oidx2 = oidx1 + idx; - out.setDouble(oidx1, a1r + a2r); - out.setDouble(oidx1 + 1, a1i + a2i); - out.setDouble(oidx2, a1r - a2r); - out.setDouble(oidx2 + 1, a1i - a2i); - } - } else { - for (long k = 0; k < l1; k++) { - for (long i = 0; i < ido - 1; i += 2) { - long idx0 = k * ido; - long iidx1 = in_off + i + 2 * idx0; - long iidx2 = iidx1 + ido; - double i1r = in.getDouble(iidx1); - double i1i = in.getDouble(iidx1 + 1); - double i2r = in.getDouble(iidx2); - double i2i = in.getDouble(iidx2 + 1); - - long widx1 = i + iw1; - double w1r = wtablel.getDouble(widx1); - double w1i = isign * wtablel.getDouble(widx1 + 1); - - t1r = i1r - i2r; - t1i = i1i - i2i; - - long oidx1 = out_off + i + idx0; - long oidx2 = oidx1 + idx; - out.setDouble(oidx1, i1r + i2r); - out.setDouble(oidx1 + 1, i1i + i2i); - out.setDouble(oidx2, w1r * t1r - w1i * t1i); - out.setDouble(oidx2 + 1, w1r * t1i + w1i * t1r); - } - } - } - } - - /*---------------------------------------------------------------------- - passf3: Complex FFT's forward/backward processing of factor 3; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf3(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset, final int isign) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; - int iw1, iw2; - - iw1 = offset; - iw2 = iw1 + ido; - - final int idxt = l1 * ido; - - if (ido == 2) { - for (int k = 1; k <= l1; k++) { - int iidx1 = in_off + (3 * k - 2) * ido; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - double i1r = in[iidx1]; - double i1i = in[iidx1 + 1]; - double i2r = in[iidx2]; - double i2i = in[iidx2 + 1]; - double i3r = in[iidx3]; - double i3i = in[iidx3 + 1]; - - tr2 = i1r + i2r; - cr2 = i3r + taur * tr2; - ti2 = i1i + i2i; - ci2 = i3i + taur * ti2; - cr3 = isign * taui * (i1r - i2r); - ci3 = isign * taui * (i1i - i2i); - - int oidx1 = out_off + (k - 1) * ido; - int oidx2 = oidx1 + idxt; - int oidx3 = oidx2 + idxt; - out[oidx1] = in[iidx3] + tr2; - out[oidx1 + 1] = i3i + ti2; - out[oidx2] = cr2 - ci3; - out[oidx2 + 1] = ci2 + cr3; - out[oidx3] = cr2 + ci3; - out[oidx3 + 1] = ci2 - cr3; - } - } else { - for (int k = 1; k <= l1; k++) { - int idx1 = in_off + (3 * k - 2) * ido; - int idx2 = out_off + (k - 1) * ido; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - double a1r = in[iidx1]; - double a1i = in[iidx1 + 1]; - double a2r = in[iidx2]; - double a2i = in[iidx2 + 1]; - double a3r = in[iidx3]; - double a3i = in[iidx3 + 1]; - - tr2 = a1r + a2r; - cr2 = a3r + taur * tr2; - ti2 = a1i + a2i; - ci2 = a3i + taur * ti2; - cr3 = isign * taui * (a1r - a2r); - ci3 = isign * taui * (a1i - a2i); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - int widx1 = i + iw1; - int widx2 = i + iw2; - double w1r = wtable[widx1]; - double w1i = isign * wtable[widx1 + 1]; - double w2r = wtable[widx2]; - double w2i = isign * wtable[widx2 + 1]; - - int oidx1 = i + idx2; - int oidx2 = oidx1 + idxt; - int oidx3 = oidx2 + idxt; - out[oidx1] = a3r + tr2; - out[oidx1 + 1] = a3i + ti2; - out[oidx2] = w1r * dr2 - w1i * di2; - out[oidx2 + 1] = w1r * di2 + w1i * dr2; - out[oidx3] = w2r * dr3 - w2i * di3; - out[oidx3 + 1] = w2r * di3 + w2i * dr3; - } - } - } - } - - /*---------------------------------------------------------------------- - passf3: Complex FFT's forward/backward processing of factor 3; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf3(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset, final long isign) { - final double taur = -0.5; - final double taui = 0.866025403784438707610604524234076962; - double ci2, ci3, di2, di3, cr2, cr3, dr2, dr3, ti2, tr2; - long iw1, iw2; - - iw1 = offset; - iw2 = iw1 + ido; - - final long idxt = l1 * ido; - - if (ido == 2) { - for (long k = 1; k <= l1; k++) { - long iidx1 = in_off + (3 * k - 2) * ido; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - double i1r = in.getDouble(iidx1); - double i1i = in.getDouble(iidx1 + 1); - double i2r = in.getDouble(iidx2); - double i2i = in.getDouble(iidx2 + 1); - double i3r = in.getDouble(iidx3); - double i3i = in.getDouble(iidx3 + 1); - - tr2 = i1r + i2r; - cr2 = i3r + taur * tr2; - ti2 = i1i + i2i; - ci2 = i3i + taur * ti2; - cr3 = isign * taui * (i1r - i2r); - ci3 = isign * taui * (i1i - i2i); - - long oidx1 = out_off + (k - 1) * ido; - long oidx2 = oidx1 + idxt; - long oidx3 = oidx2 + idxt; - out.setDouble(oidx1, in.getDouble(iidx3) + tr2); - out.setDouble(oidx1 + 1, i3i + ti2); - out.setDouble(oidx2, cr2 - ci3); - out.setDouble(oidx2 + 1, ci2 + cr3); - out.setDouble(oidx3, cr2 + ci3); - out.setDouble(oidx3 + 1, ci2 - cr3); - } - } else { - for (long k = 1; k <= l1; k++) { - long idx1 = in_off + (3 * k - 2) * ido; - long idx2 = out_off + (k - 1) * ido; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - double a1r = in.getDouble(iidx1); - double a1i = in.getDouble(iidx1 + 1); - double a2r = in.getDouble(iidx2); - double a2i = in.getDouble(iidx2 + 1); - double a3r = in.getDouble(iidx3); - double a3i = in.getDouble(iidx3 + 1); - - tr2 = a1r + a2r; - cr2 = a3r + taur * tr2; - ti2 = a1i + a2i; - ci2 = a3i + taur * ti2; - cr3 = isign * taui * (a1r - a2r); - ci3 = isign * taui * (a1i - a2i); - dr2 = cr2 - ci3; - dr3 = cr2 + ci3; - di2 = ci2 + cr3; - di3 = ci2 - cr3; - - long widx1 = i + iw1; - long widx2 = i + iw2; - double w1r = wtablel.getDouble(widx1); - double w1i = isign * wtablel.getDouble(widx1 + 1); - double w2r = wtablel.getDouble(widx2); - double w2i = isign * wtablel.getDouble(widx2 + 1); - - long oidx1 = i + idx2; - long oidx2 = oidx1 + idxt; - long oidx3 = oidx2 + idxt; - out.setDouble(oidx1, a3r + tr2); - out.setDouble(oidx1 + 1, a3i + ti2); - out.setDouble(oidx2, w1r * dr2 - w1i * di2); - out.setDouble(oidx2 + 1, w1r * di2 + w1i * dr2); - out.setDouble(oidx3, w2r * dr3 - w2i * di3); - out.setDouble(oidx3 + 1, w2r * di3 + w2i * dr3); - } - } - } - } - - /*---------------------------------------------------------------------- - passf4: Complex FFT's forward/backward processing of factor 4; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf4(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset, final int isign) { - double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; - int iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - int idx0 = l1 * ido; - if (ido == 2) { - for (int k = 0; k < l1; k++) { - int idxt1 = k * ido; - int iidx1 = in_off + 4 * idxt1 + 1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx2 + ido; - int iidx4 = iidx3 + ido; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - tr4 = i4r - i2r; - ti3 = i2r + i4r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - - int oidx1 = out_off + idxt1; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - out[oidx1] = tr2 + tr3; - out[oidx1 + 1] = ti2 + ti3; - out[oidx2] = tr1 + isign * tr4; - out[oidx2 + 1] = ti1 + isign * ti4; - out[oidx3] = tr2 - tr3; - out[oidx3 + 1] = ti2 - ti3; - out[oidx4] = tr1 - isign * tr4; - out[oidx4 + 1] = ti1 - isign * ti4; - } - } else { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = in_off + 1 + 4 * idx1; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx2; - int iidx2 = iidx1 + ido; - int iidx3 = iidx2 + ido; - int iidx4 = iidx3 + ido; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - ti3 = i2r + i4r; - tr4 = i4r - i2r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 + isign * tr4; - cr4 = tr1 - isign * tr4; - ci2 = ti1 + isign * ti4; - ci4 = ti1 - isign * ti4; - - int widx1 = i + iw1; - int widx2 = i + iw2; - int widx3 = i + iw3; - double w1r = wtable[widx1]; - double w1i = isign * wtable[widx1 + 1]; - double w2r = wtable[widx2]; - double w2i = isign * wtable[widx2 + 1]; - double w3r = wtable[widx3]; - double w3i = isign * wtable[widx3 + 1]; - - int oidx1 = out_off + i + idx1; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - out[oidx1] = tr2 + tr3; - out[oidx1 + 1] = ti2 + ti3; - out[oidx2] = w1r * cr2 - w1i * ci2; - out[oidx2 + 1] = w1r * ci2 + w1i * cr2; - out[oidx3] = w2r * cr3 - w2i * ci3; - out[oidx3 + 1] = w2r * ci3 + w2i * cr3; - out[oidx4] = w3r * cr4 - w3i * ci4; - out[oidx4 + 1] = w3r * ci4 + w3i * cr4; - } - } - } - } - - /*---------------------------------------------------------------------- - passf4: Complex FFT's forward/backward processing of factor 4; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf4(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset, final int isign) { - double ci2, ci3, ci4, cr2, cr3, cr4, ti1, ti2, ti3, ti4, tr1, tr2, tr3, tr4; - long iw1, iw2, iw3; - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - - long idx0 = l1 * ido; - if (ido == 2) { - for (long k = 0; k < l1; k++) { - long idxt1 = k * ido; - long iidx1 = in_off + 4 * idxt1 + 1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx2 + ido; - long iidx4 = iidx3 + ido; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - tr4 = i4r - i2r; - ti3 = i2r + i4r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - - long oidx1 = out_off + idxt1; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - out.setDouble(oidx1, tr2 + tr3); - out.setDouble(oidx1 + 1, ti2 + ti3); - out.setDouble(oidx2, tr1 + isign * tr4); - out.setDouble(oidx2 + 1, ti1 + isign * ti4); - out.setDouble(oidx3, tr2 - tr3); - out.setDouble(oidx3 + 1, ti2 - ti3); - out.setDouble(oidx4, tr1 - isign * tr4); - out.setDouble(oidx4 + 1, ti1 - isign * ti4); - } - } else { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = in_off + 1 + 4 * idx1; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx2; - long iidx2 = iidx1 + ido; - long iidx3 = iidx2 + ido; - long iidx4 = iidx3 + ido; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - - ti1 = i1r - i3r; - ti2 = i1r + i3r; - ti3 = i2r + i4r; - tr4 = i4r - i2r; - tr1 = i1i - i3i; - tr2 = i1i + i3i; - ti4 = i2i - i4i; - tr3 = i2i + i4i; - cr3 = tr2 - tr3; - ci3 = ti2 - ti3; - cr2 = tr1 + isign * tr4; - cr4 = tr1 - isign * tr4; - ci2 = ti1 + isign * ti4; - ci4 = ti1 - isign * ti4; - - long widx1 = i + iw1; - long widx2 = i + iw2; - long widx3 = i + iw3; - double w1r = wtablel.getDouble(widx1); - double w1i = isign * wtablel.getDouble(widx1 + 1); - double w2r = wtablel.getDouble(widx2); - double w2i = isign * wtablel.getDouble(widx2 + 1); - double w3r = wtablel.getDouble(widx3); - double w3i = isign * wtablel.getDouble(widx3 + 1); - - long oidx1 = out_off + i + idx1; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - out.setDouble(oidx1, tr2 + tr3); - out.setDouble(oidx1 + 1, ti2 + ti3); - out.setDouble(oidx2, w1r * cr2 - w1i * ci2); - out.setDouble(oidx2 + 1, w1r * ci2 + w1i * cr2); - out.setDouble(oidx3, w2r * cr3 - w2i * ci3); - out.setDouble(oidx3 + 1, w2r * ci3 + w2i * cr3); - out.setDouble(oidx4, w3r * cr4 - w3i * ci4); - out.setDouble(oidx4 + 1, w3r * ci4 + w3i * cr4); - } - } - } - } - - /*---------------------------------------------------------------------- - passf5: Complex FFT's forward/backward processing of factor 5; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf5(final int ido, final int l1, final double in[], final int in_off, final double out[], final int out_off, final int offset, final int isign) /* isign==-1 for forward transform and+1 for backward transform */ { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - double ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; - int iw1, iw2, iw3, iw4; - - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - int idx0 = l1 * ido; - - if (ido == 2) { - for (int k = 1; k <= l1; ++k) { - int iidx1 = in_off + (5 * k - 4) * ido + 1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - int iidx4 = iidx2 + ido; - int iidx5 = iidx4 + ido; - - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - double i5i = in[iidx5 - 1]; - double i5r = in[iidx5]; - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - - int oidx1 = out_off + (k - 1) * ido; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - int oidx5 = oidx4 + idx0; - out[oidx1] = i3i + tr2 + tr3; - out[oidx1 + 1] = i3r + ti2 + ti3; - out[oidx2] = cr2 - ci5; - out[oidx2 + 1] = ci2 + cr5; - out[oidx3] = cr3 - ci4; - out[oidx3 + 1] = ci3 + cr4; - out[oidx4] = cr3 + ci4; - out[oidx4 + 1] = ci3 - cr4; - out[oidx5] = cr2 + ci5; - out[oidx5 + 1] = ci2 - cr5; - } - } else { - for (int k = 1; k <= l1; k++) { - int idx1 = in_off + 1 + (k * 5 - 4) * ido; - int idx2 = out_off + (k - 1) * ido; - for (int i = 0; i < ido - 1; i += 2) { - int iidx1 = i + idx1; - int iidx2 = iidx1 + ido; - int iidx3 = iidx1 - ido; - int iidx4 = iidx2 + ido; - int iidx5 = iidx4 + ido; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - double i3i = in[iidx3 - 1]; - double i3r = in[iidx3]; - double i4i = in[iidx4 - 1]; - double i4r = in[iidx4]; - double i5i = in[iidx5 - 1]; - double i5r = in[iidx5]; - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - int widx1 = i + iw1; - int widx2 = i + iw2; - int widx3 = i + iw3; - int widx4 = i + iw4; - double w1r = wtable[widx1]; - double w1i = isign * wtable[widx1 + 1]; - double w2r = wtable[widx2]; - double w2i = isign * wtable[widx2 + 1]; - double w3r = wtable[widx3]; - double w3i = isign * wtable[widx3 + 1]; - double w4r = wtable[widx4]; - double w4i = isign * wtable[widx4 + 1]; - - int oidx1 = i + idx2; - int oidx2 = oidx1 + idx0; - int oidx3 = oidx2 + idx0; - int oidx4 = oidx3 + idx0; - int oidx5 = oidx4 + idx0; - out[oidx1] = i3i + tr2 + tr3; - out[oidx1 + 1] = i3r + ti2 + ti3; - out[oidx2] = w1r * dr2 - w1i * di2; - out[oidx2 + 1] = w1r * di2 + w1i * dr2; - out[oidx3] = w2r * dr3 - w2i * di3; - out[oidx3 + 1] = w2r * di3 + w2i * dr3; - out[oidx4] = w3r * dr4 - w3i * di4; - out[oidx4 + 1] = w3r * di4 + w3i * dr4; - out[oidx5] = w4r * dr5 - w4i * di5; - out[oidx5 + 1] = w4r * di5 + w4i * dr5; - } - } - } - } - - /*---------------------------------------------------------------------- - passf5: Complex FFT's forward/backward processing of factor 5; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passf5(final long ido, final long l1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset, final long isign) /* isign==-1 for forward transform and+1 for backward transform */ { - final double tr11 = 0.309016994374947451262869435595348477; - final double ti11 = 0.951056516295153531181938433292089030; - final double tr12 = -0.809016994374947340240566973079694435; - final double ti12 = 0.587785252292473248125759255344746634; - double ci2, ci3, ci4, ci5, di3, di4, di5, di2, cr2, cr3, cr5, cr4, ti2, ti3, ti4, ti5, dr3, dr4, dr5, dr2, tr2, tr3, tr4, tr5; - long iw1, iw2, iw3, iw4; - - iw1 = offset; - iw2 = iw1 + ido; - iw3 = iw2 + ido; - iw4 = iw3 + ido; - - long idx0 = l1 * ido; - - if (ido == 2) { - for (long k = 1; k <= l1; ++k) { - long iidx1 = in_off + (5 * k - 4) * ido + 1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - long iidx4 = iidx2 + ido; - long iidx5 = iidx4 + ido; - - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - double i5i = in.getDouble(iidx5 - 1); - double i5r = in.getDouble(iidx5); - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - - long oidx1 = out_off + (k - 1) * ido; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - long oidx5 = oidx4 + idx0; - out.setDouble(oidx1, i3i + tr2 + tr3); - out.setDouble(oidx1 + 1, i3r + ti2 + ti3); - out.setDouble(oidx2, cr2 - ci5); - out.setDouble(oidx2 + 1, ci2 + cr5); - out.setDouble(oidx3, cr3 - ci4); - out.setDouble(oidx3 + 1, ci3 + cr4); - out.setDouble(oidx4, cr3 + ci4); - out.setDouble(oidx4 + 1, ci3 - cr4); - out.setDouble(oidx5, cr2 + ci5); - out.setDouble(oidx5 + 1, ci2 - cr5); - } - } else { - for (long k = 1; k <= l1; k++) { - long idx1 = in_off + 1 + (k * 5 - 4) * ido; - long idx2 = out_off + (k - 1) * ido; - for (long i = 0; i < ido - 1; i += 2) { - long iidx1 = i + idx1; - long iidx2 = iidx1 + ido; - long iidx3 = iidx1 - ido; - long iidx4 = iidx2 + ido; - long iidx5 = iidx4 + ido; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - double i3i = in.getDouble(iidx3 - 1); - double i3r = in.getDouble(iidx3); - double i4i = in.getDouble(iidx4 - 1); - double i4r = in.getDouble(iidx4); - double i5i = in.getDouble(iidx5 - 1); - double i5r = in.getDouble(iidx5); - - ti5 = i1r - i5r; - ti2 = i1r + i5r; - ti4 = i2r - i4r; - ti3 = i2r + i4r; - tr5 = i1i - i5i; - tr2 = i1i + i5i; - tr4 = i2i - i4i; - tr3 = i2i + i4i; - cr2 = i3i + tr11 * tr2 + tr12 * tr3; - ci2 = i3r + tr11 * ti2 + tr12 * ti3; - cr3 = i3i + tr12 * tr2 + tr11 * tr3; - ci3 = i3r + tr12 * ti2 + tr11 * ti3; - cr5 = isign * (ti11 * tr5 + ti12 * tr4); - ci5 = isign * (ti11 * ti5 + ti12 * ti4); - cr4 = isign * (ti12 * tr5 - ti11 * tr4); - ci4 = isign * (ti12 * ti5 - ti11 * ti4); - dr3 = cr3 - ci4; - dr4 = cr3 + ci4; - di3 = ci3 + cr4; - di4 = ci3 - cr4; - dr5 = cr2 + ci5; - dr2 = cr2 - ci5; - di5 = ci2 - cr5; - di2 = ci2 + cr5; - - long widx1 = i + iw1; - long widx2 = i + iw2; - long widx3 = i + iw3; - long widx4 = i + iw4; - double w1r = wtablel.getDouble(widx1); - double w1i = isign * wtablel.getDouble(widx1 + 1); - double w2r = wtablel.getDouble(widx2); - double w2i = isign * wtablel.getDouble(widx2 + 1); - double w3r = wtablel.getDouble(widx3); - double w3i = isign * wtablel.getDouble(widx3 + 1); - double w4r = wtablel.getDouble(widx4); - double w4i = isign * wtablel.getDouble(widx4 + 1); - - long oidx1 = i + idx2; - long oidx2 = oidx1 + idx0; - long oidx3 = oidx2 + idx0; - long oidx4 = oidx3 + idx0; - long oidx5 = oidx4 + idx0; - out.setDouble(oidx1, i3i + tr2 + tr3); - out.setDouble(oidx1 + 1, i3r + ti2 + ti3); - out.setDouble(oidx2, w1r * dr2 - w1i * di2); - out.setDouble(oidx2 + 1, w1r * di2 + w1i * dr2); - out.setDouble(oidx3, w2r * dr3 - w2i * di3); - out.setDouble(oidx3 + 1, w2r * di3 + w2i * dr3); - out.setDouble(oidx4, w3r * dr4 - w3i * di4); - out.setDouble(oidx4 + 1, w3r * di4 + w3i * dr4); - out.setDouble(oidx5, w4r * dr5 - w4i * di5); - out.setDouble(oidx5 + 1, w4r * di5 + w4i * dr5); - } - } - } - } - - /*---------------------------------------------------------------------- - passfg: Complex FFT's forward/backward processing of general factor; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passfg(final int nac[], final int ido, final int ip, final int l1, final int idl1, final double in[], final int in_off, final double out[], final int out_off, final int offset, final int isign) { - int idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; - double w1r, w1i, w2i, w2r; - int iw1; - - iw1 = offset; - idot = ido / 2; - ipph = (ip + 1) / 2; - idp = ip * ido; - if (ido >= l1) { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * ido; - int idx2 = jc * ido; - for (int k = 0; k < l1; k++) { - int idx3 = k * ido; - int idx4 = idx3 + idx1 * l1; - int idx5 = idx3 + idx2 * l1; - int idx6 = idx3 * ip; - for (int i = 0; i < ido; i++) { - int oidx1 = out_off + i; - double i1r = in[in_off + i + idx1 + idx6]; - double i2r = in[in_off + i + idx2 + idx6]; - out[oidx1 + idx4] = i1r + i2r; - out[oidx1 + idx5] = i1r - i2r; - } - } - } - for (int k = 0; k < l1; k++) { - int idxt1 = k * ido; - int idxt2 = idxt1 * ip; - for (int i = 0; i < ido; i++) { - out[out_off + i + idxt1] = in[in_off + i + idxt2]; - } - } - } else { - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idxt1 = j * l1 * ido; - int idxt2 = jc * l1 * ido; - int idxt3 = j * ido; - int idxt4 = jc * ido; - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - int idx2 = idx1 * ip; - int idx3 = out_off + i; - int idx4 = in_off + i; - double i1r = in[idx4 + idxt3 + idx2]; - double i2r = in[idx4 + idxt4 + idx2]; - out[idx3 + idx1 + idxt1] = i1r + i2r; - out[idx3 + idx1 + idxt2] = i1r - i2r; - } - } - } - for (int i = 0; i < ido; i++) { - for (int k = 0; k < l1; k++) { - int idx1 = k * ido; - out[out_off + i + idx1] = in[in_off + i + idx1 * ip]; - } - } - } - - idl = 2 - ido; - inc = 0; - int idxt0 = (ip - 1) * idl1; - for (l = 1; l < ipph; l++) { - lc = ip - l; - idl += ido; - int idxt1 = l * idl1; - int idxt2 = lc * idl1; - int idxt3 = idl + iw1; - w1r = wtable[idxt3 - 2]; - w1i = isign * wtable[idxt3 - 1]; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = in_off + ik; - int idx2 = out_off + ik; - in[idx1 + idxt1] = out[idx2] + w1r * out[idx2 + idl1]; - in[idx1 + idxt2] = w1i * out[idx2 + idxt0]; - } - idlj = idl; - inc += ido; - for (int j = 2; j < ipph; j++) { - jc = ip - j; - idlj += inc; - if (idlj > idp) { - idlj -= idp; - } - int idxt4 = idlj + iw1; - w2r = wtable[idxt4 - 2]; - w2i = isign * wtable[idxt4 - 1]; - int idxt5 = j * idl1; - int idxt6 = jc * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = in_off + ik; - int idx2 = out_off + ik; - in[idx1 + idxt1] += w2r * out[idx2 + idxt5]; - in[idx1 + idxt2] += w2i * out[idx2 + idxt6]; - } - } - } - for (int j = 1; j < ipph; j++) { - int idxt1 = j * idl1; - for (int ik = 0; ik < idl1; ik++) { - int idx1 = out_off + ik; - out[idx1] += out[idx1 + idxt1]; - } - } - for (int j = 1; j < ipph; j++) { - jc = ip - j; - int idx1 = j * idl1; - int idx2 = jc * idl1; - for (int ik = 1; ik < idl1; ik += 2) { - int idx3 = out_off + ik; - int idx4 = in_off + ik; - int iidx1 = idx4 + idx1; - int iidx2 = idx4 + idx2; - double i1i = in[iidx1 - 1]; - double i1r = in[iidx1]; - double i2i = in[iidx2 - 1]; - double i2r = in[iidx2]; - - int oidx1 = idx3 + idx1; - int oidx2 = idx3 + idx2; - out[oidx1 - 1] = i1i - i2r; - out[oidx2 - 1] = i1i + i2r; - out[oidx1] = i1r + i2i; - out[oidx2] = i1r - i2i; - } - } - nac[0] = 1; - if (ido == 2) { - return; - } - nac[0] = 0; - System.arraycopy(out, out_off, in, in_off, idl1); - int idx0 = l1 * ido; - for (int j = 1; j < ip; j++) { - int idx1 = j * idx0; - for (int k = 0; k < l1; k++) { - int idx2 = k * ido; - int oidx1 = out_off + idx2 + idx1; - int iidx1 = in_off + idx2 + idx1; - in[iidx1] = out[oidx1]; - in[iidx1 + 1] = out[oidx1 + 1]; - } - } - if (idot <= l1) { - idij = 0; - for (int j = 1; j < ip; j++) { - idij += 2; - int idx1 = j * l1 * ido; - for (int i = 3; i < ido; i += 2) { - idij += 2; - int idx2 = idij + iw1 - 1; - w1r = wtable[idx2 - 1]; - w1i = isign * wtable[idx2]; - int idx3 = in_off + i; - int idx4 = out_off + i; - for (int k = 0; k < l1; k++) { - int idx5 = k * ido + idx1; - int iidx1 = idx3 + idx5; - int oidx1 = idx4 + idx5; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } else { - idj = 2 - ido; - for (int j = 1; j < ip; j++) { - idj += ido; - int idx1 = j * l1 * ido; - for (int k = 0; k < l1; k++) { - idij = idj; - int idx3 = k * ido + idx1; - for (int i = 3; i < ido; i += 2) { - idij += 2; - int idx2 = idij - 1 + iw1; - w1r = wtable[idx2 - 1]; - w1i = isign * wtable[idx2]; - int iidx1 = in_off + i + idx3; - int oidx1 = out_off + i + idx3; - double o1i = out[oidx1 - 1]; - double o1r = out[oidx1]; - in[iidx1 - 1] = w1r * o1i - w1i * o1r; - in[iidx1] = w1r * o1r + w1i * o1i; - } - } - } - } - } - - /*---------------------------------------------------------------------- - passfg: Complex FFT's forward/backward processing of general factor; - isign is +1 for backward and -1 for forward transforms - ----------------------------------------------------------------------*/ - void passfg(final int nac[], final long ido, final long ip, final long l1, final long idl1, final DoubleLargeArray in, final long in_off, final DoubleLargeArray out, final long out_off, final long offset, final long isign) { - long idij, idlj, idot, ipph, l, jc, lc, idj, idl, inc, idp; - double w1r, w1i, w2i, w2r; - long iw1; - - iw1 = offset; - idot = ido / 2; - ipph = (ip + 1) / 2; - idp = ip * ido; - if (ido >= l1) { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * ido; - long idx2 = jc * ido; - for (long k = 0; k < l1; k++) { - long idx3 = k * ido; - long idx4 = idx3 + idx1 * l1; - long idx5 = idx3 + idx2 * l1; - long idx6 = idx3 * ip; - for (long i = 0; i < ido; i++) { - long oidx1 = out_off + i; - double i1r = in.getDouble(in_off + i + idx1 + idx6); - double i2r = in.getDouble(in_off + i + idx2 + idx6); - out.setDouble(oidx1 + idx4, i1r + i2r); - out.setDouble(oidx1 + idx5, i1r - i2r); - } - } - } - for (long k = 0; k < l1; k++) { - long idxt1 = k * ido; - long idxt2 = idxt1 * ip; - for (long i = 0; i < ido; i++) { - out.setDouble(out_off + i + idxt1, in.getDouble(in_off + i + idxt2)); - } - } - } else { - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idxt1 = j * l1 * ido; - long idxt2 = jc * l1 * ido; - long idxt3 = j * ido; - long idxt4 = jc * ido; - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - long idx2 = idx1 * ip; - long idx3 = out_off + i; - long idx4 = in_off + i; - double i1r = in.getDouble(idx4 + idxt3 + idx2); - double i2r = in.getDouble(idx4 + idxt4 + idx2); - out.setDouble(idx3 + idx1 + idxt1, i1r + i2r); - out.setDouble(idx3 + idx1 + idxt2, i1r - i2r); - } - } - } - for (long i = 0; i < ido; i++) { - for (long k = 0; k < l1; k++) { - long idx1 = k * ido; - out.setDouble(out_off + i + idx1, in.getDouble(in_off + i + idx1 * ip)); - } - } - } - - idl = 2 - ido; - inc = 0; - long idxt0 = (ip - 1) * idl1; - for (l = 1; l < ipph; l++) { - lc = ip - l; - idl += ido; - long idxt1 = l * idl1; - long idxt2 = lc * idl1; - long idxt3 = idl + iw1; - w1r = wtablel.getDouble(idxt3 - 2); - w1i = isign * wtablel.getDouble(idxt3 - 1); - for (long ik = 0; ik < idl1; ik++) { - long idx1 = in_off + ik; - long idx2 = out_off + ik; - in.setDouble(idx1 + idxt1, out.getDouble(idx2) + w1r * out.getDouble(idx2 + idl1)); - in.setDouble(idx1 + idxt2, w1i * out.getDouble(idx2 + idxt0)); - } - idlj = idl; - inc += ido; - for (long j = 2; j < ipph; j++) { - jc = ip - j; - idlj += inc; - if (idlj > idp) { - idlj -= idp; - } - long idxt4 = idlj + iw1; - w2r = wtablel.getDouble(idxt4 - 2); - w2i = isign * wtablel.getDouble(idxt4 - 1); - long idxt5 = j * idl1; - long idxt6 = jc * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx1 = in_off + ik; - long idx2 = out_off + ik; - in.setDouble(idx1 + idxt1, in.getDouble(idx1 + idxt1) + w2r * out.getDouble(idx2 + idxt5)); - in.setDouble(idx1 + idxt2, in.getDouble(idx1 + idxt2) + w2i * out.getDouble(idx2 + idxt6)); - } - } - } - for (long j = 1; j < ipph; j++) { - long idxt1 = j * idl1; - for (long ik = 0; ik < idl1; ik++) { - long idx1 = out_off + ik; - out.setDouble(idx1, out.getDouble(idx1) + out.getDouble(idx1 + idxt1)); - } - } - for (long j = 1; j < ipph; j++) { - jc = ip - j; - long idx1 = j * idl1; - long idx2 = jc * idl1; - for (long ik = 1; ik < idl1; ik += 2) { - long idx3 = out_off + ik; - long idx4 = in_off + ik; - long iidx1 = idx4 + idx1; - long iidx2 = idx4 + idx2; - double i1i = in.getDouble(iidx1 - 1); - double i1r = in.getDouble(iidx1); - double i2i = in.getDouble(iidx2 - 1); - double i2r = in.getDouble(iidx2); - - long oidx1 = idx3 + idx1; - long oidx2 = idx3 + idx2; - out.setDouble(oidx1 - 1, i1i - i2r); - out.setDouble(oidx2 - 1, i1i + i2r); - out.setDouble(oidx1, i1r + i2i); - out.setDouble(oidx2, i1r - i2i); - } - } - nac[0] = 1; - if (ido == 2) { - return; - } - nac[0] = 0; - Utilities.arraycopy(out, out_off, in, in_off, idl1); - long idx0 = l1 * ido; - for (long j = 1; j < ip; j++) { - long idx1 = j * idx0; - for (long k = 0; k < l1; k++) { - long idx2 = k * ido; - long oidx1 = out_off + idx2 + idx1; - long iidx1 = in_off + idx2 + idx1; - in.setDouble(iidx1, out.getDouble(oidx1)); - in.setDouble(iidx1 + 1, out.getDouble(oidx1 + 1)); - } - } - if (idot <= l1) { - idij = 0; - for (long j = 1; j < ip; j++) { - idij += 2; - long idx1 = j * l1 * ido; - for (long i = 3; i < ido; i += 2) { - idij += 2; - long idx2 = idij + iw1 - 1; - w1r = wtablel.getDouble(idx2 - 1); - w1i = isign * wtablel.getDouble(idx2); - long idx3 = in_off + i; - long idx4 = out_off + i; - for (long k = 0; k < l1; k++) { - long idx5 = k * ido + idx1; - long iidx1 = idx3 + idx5; - long oidx1 = idx4 + idx5; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - in.setDouble(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setDouble(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } else { - idj = 2 - ido; - for (long j = 1; j < ip; j++) { - idj += ido; - long idx1 = j * l1 * ido; - for (long k = 0; k < l1; k++) { - idij = idj; - long idx3 = k * ido + idx1; - for (long i = 3; i < ido; i += 2) { - idij += 2; - long idx2 = idij - 1 + iw1; - w1r = wtablel.getDouble(idx2 - 1); - w1i = isign * wtablel.getDouble(idx2); - long iidx1 = in_off + i + idx3; - long oidx1 = out_off + i + idx3; - double o1i = out.getDouble(oidx1 - 1); - double o1r = out.getDouble(oidx1); - in.setDouble(iidx1 - 1, w1r * o1i - w1i * o1r); - in.setDouble(iidx1, w1r * o1r + w1i * o1i); - } - } - } - } - } -} diff --git a/src/main/java/org/jtransforms/fft/DoubleFFT_2D.java b/src/main/java/org/jtransforms/fft/DoubleFFT_2D.java deleted file mode 100644 index 866eb3b..0000000 --- a/src/main/java/org/jtransforms/fft/DoubleFFT_2D.java +++ /dev/null @@ -1,3940 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * Computes 2D Discrete Fourier Transform (DFT) of complex and real, double - * precision data. The sizes of both dimensions can be arbitrary numbers. This - * is a parallel implementation of split-radix and mixed-radix algorithms - * optimized for SMP systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by Takuya Ooura - * (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleFFT_2D -{ - - private int rows; - - private int columns; - - private long rowsl; - - private long columnsl; - - private DoubleFFT_1D fftColumns, fftRows; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleFFT_2D. - * - * @param rows - * number of rows - * @param columns - * number of columns - */ - public DoubleFFT_2D(long rows, long columns) - { - if (rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("rows and columns must be greater than 1"); - } - - this.rows = (int) rows; - this.columns = (int) columns; - this.rowsl = rows; - this.columnsl = columns; - if (rows * columns >= ConcurrencyUtils.getThreadsBeginN_2D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(rows, columns)); - } - fftRows = new DoubleFFT_1D(rows); - if (rows == columns) { - fftColumns = fftRows; - } - else { - fftColumns = new DoubleFFT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two double values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - */ - public void complexForward(final double[] a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - } - columns = columns / 2; - } else { - final int rowStride = 2 * columns; - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a, r * rowStride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - temp[idx1] = a[idx2]; - temp[idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[idx1]; - a[idx2 + 1] = temp[idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, r * rowStride); - } - double[] temp = new double[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - temp[idx1] = a[idx2]; - temp[idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[idx1]; - a[idx2 + 1] = temp[idx1 + 1]; - } - } - } - } - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two double values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - */ - public void complexForward(final DoubleLargeArray a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columnsl = 2 * columnsl; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - } - columnsl = columnsl / 2; - } else { - final long rowStride = 2 * columnsl; - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a, r * rowStride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - temp.setDouble(idx1, a.getDouble(idx2)); - temp.setDouble(idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(idx1)); - a.setDouble(idx2 + 1, temp.getDouble(idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, r * rowStride); - } - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long c = 0; c < columnsl; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - temp.setDouble(idx1, a.getDouble(idx2)); - temp.setDouble(idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(idx1)); - a.setDouble(idx2 + 1, temp.getDouble(idx1 + 1)); - } - } - } - } - } - - /** - * Computes 2D forward DFT of complex data leaving the result in - * a. The data is stored in 2D array. Complex data is - * represented by 2 double values in sequence: the real and imaginary part, - * i.e. the input array must be of size rows by 2*columns. The physical - * layout of the input data has to be as follows:
- * - *
-     * a[k1][2*k2] = Re[k1][k2],
-     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - */ - public void complexForward(final double[][] a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, -1, a, true); - cdft2d_subth(-1, a, true); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[r]); - } - cdft2d_sub(-1, a, true); - } - columns = columns / 2; - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexForward(a[r]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[r]); - } - double[] temp = new double[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two double values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - * - */ - public void complexInverse(final double[] a, final boolean scale) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, r * columns, scale); - } - cdft2d_sub(1, a, scale); - } - columns = columns / 2; - } else { - final int rowspan = 2 * columns; - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - temp[idx2] = a[idx3]; - temp[idx2 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - a[idx3] = temp[idx2]; - a[idx3 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - double[] temp = new double[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - temp[idx2] = a[idx3]; - temp[idx2 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - int idx3 = r * rowspan + idx1; - a[idx3] = temp[idx2]; - a[idx3 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 1D array in row-major order. - * Complex number is stored as two double values in sequence: the real and - * imaginary part, i.e. the input array must be of size rows*2*columns. The - * physical layout of the input data has to be as follows:
- * - *
-     * a[k1*2*columns+2*k2] = Re[k1][k2],
-     * a[k1*2*columns+2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - * - */ - public void complexInverse(final DoubleLargeArray a, final boolean scale) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columnsl = 2 * columnsl; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - cdft2d_sub(1, a, scale); - } - columnsl = columnsl / 2; - } else { - final long rowspan = 2 * columnsl; - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columnsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = l * p; - final long lastColumn = (l == (nthreads - 1)) ? columnsl : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long c = firstColumn; c < lastColumn; c++) { - long idx1 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - temp.setDouble(idx2, a.getDouble(idx3)); - temp.setDouble(idx2 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - a.setDouble(idx3, temp.getDouble(idx2)); - a.setDouble(idx3 + 1, temp.getDouble(idx2 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, r * rowspan, scale); - } - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - temp.setDouble(idx2, a.getDouble(idx3)); - temp.setDouble(idx2 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx2 = 2 * r; - long idx3 = r * rowspan + idx1; - a.setDouble(idx3, temp.getDouble(idx2)); - a.setDouble(idx3 + 1, temp.getDouble(idx2 + 1)); - } - } - } - } - } - - /** - * Computes 2D inverse DFT of complex data leaving the result in - * a. The data is stored in 2D array. Complex data is - * represented by 2 double values in sequence: the real and imaginary part, - * i.e. the input array must be of size rows by 2*columns. The physical - * layout of the input data has to be as follows:
- * - *
-     * a[k1][2*k2] = Re[k1][k2],
-     * a[k1][2*k2+1] = Im[k1][k2], 0<=k1<rows, 0<=k2<columns,
-     * 
- * - * @param a - * data to transform - * @param scale - * if true then scaling is performed - * - */ - public void complexInverse(final double[][] a, final boolean scale) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - columns = 2 * columns; - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(0, 1, a, scale); - cdft2d_subth(1, a, scale); - } else { - - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[r], scale); - } - cdft2d_sub(1, a, scale); - } - columns = columns / 2; - } else { - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - fftColumns.complexInverse(a[r], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = columns / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = l * p; - final int lastColumn = (l == (nthreads - 1)) ? columns : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int c = firstColumn; c < lastColumn; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[r], scale); - } - double[] temp = new double[2 * rows]; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - temp[idx2] = a[r][idx1]; - temp[idx2 + 1] = a[r][idx1 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx2 = 2 * r; - a[r][idx1] = temp[idx2]; - a[r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForward(double[] a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForward(DoubleLargeArray a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the output data is as - * follows: - * - *
-     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0][0] = Re[0][0],
-     * a[0][1] = Re[0][columns/2],
-     * a[rows/2][0] = Re[rows/2][0],
-     * a[rows/2][1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForward(double[][] a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. To get back the original data, use - * complexInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForwardFull(double[] a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. To get back the original data, use - * complexInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForwardFull(DoubleLargeArray a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows by 2*columns, with only the first rows by - * columns elements filled with real data. To get back the original data, - * use complexInverse on the output of this method. - * - * @param a - * data to transform - */ - public void realForwardFull(double[][] a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth1(1, 1, a, true); - cdft2d_subth(-1, a, true); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - cdft2d_sub(-1, a, true); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverse(double[] a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a, r * columns, scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - *
-     * a[k1*columns+2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1*columns+2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1*columns] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1*columns+1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[(rows-k1)*columns+1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[(rows-k1)*columns] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0] = Re[0][0],
-     * a[1] = Re[0][columns/2],
-     * a[(rows/2)*columns] = Re[rows/2][0],
-     * a[(rows/2)*columns+1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverse(DoubleLargeArray a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse(a, r * columnsl, scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of both dimensions are - * power-of-two numbers. The physical layout of the input data has to be as - * follows: - * - *
-     * a[k1][2*k2] = Re[k1][k2] = Re[rows-k1][columns-k2],
-     * a[k1][2*k2+1] = Im[k1][k2] = -Im[rows-k1][columns-k2],
-     *       0<k1<rows, 0<k2<columns/2,
-     * a[0][2*k2] = Re[0][k2] = Re[0][columns-k2],
-     * a[0][2*k2+1] = Im[0][k2] = -Im[0][columns-k2],
-     *       0<k2<columns/2,
-     * a[k1][0] = Re[k1][0] = Re[rows-k1][0],
-     * a[k1][1] = Im[k1][0] = -Im[rows-k1][0],
-     * a[rows-k1][1] = Re[k1][columns/2] = Re[rows-k1][columns/2],
-     * a[rows-k1][0] = -Im[k1][columns/2] = Im[rows-k1][columns/2],
-     *       0<k1<rows/2,
-     * a[0][0] = Re[0][0],
-     * a[0][1] = Re[0][columns/2],
-     * a[rows/2][0] = Re[rows/2][0],
-     * a[rows/2][1] = Re[rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverse(double[][] a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft2d_sub(-1, a); - cdft2d_subth(1, a, scale); - xdft2d0_subth1(1, -1, a, scale); - } else { - rdft2d_sub(-1, a); - cdft2d_sub(1, a, scale); - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a[r], scale); - } - } - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverseFull(double[] a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, r * columns, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows*2*columns, with only the first rows*columns - * elements filled with real data. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverseFull(DoubleLargeArray a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 2D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size rows by 2*columns, with only the first rows by - * columns elements filled with real data. - * - * @param a - * data to transform - * - * @param scale - * if true then scaling is performed - */ - public void realInverseFull(double[][] a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft2d0_subth2(1, -1, a, scale); - cdft2d_subth(1, a, scale); - rdft2d_sub(1, a); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[r], 0, scale); - } - cdft2d_sub(1, a, scale); - rdft2d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - private void mixedRadixRealForwardFull(final double[][] a) - { - final int n2d2 = columns / 2 + 1; - final double[][] temp = new double[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a[i]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int c = firstColumn; c < lastColumn; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[r]); - } - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - } - - private void mixedRadixRealForwardFull(final double[] a) - { - final int rowStride = 2 * columns; - final int n2d2 = columns / 2 + 1; - final double[][] temp = new double[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a, i * columns); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, r * columns); - } - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realForwardFull(temp[0]); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[c]); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realForwardFull(temp[n2d2 - 1]); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexForward(temp[n2d2 - 1]); - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - } - - private void mixedRadixRealForwardFull(final DoubleLargeArray a) - { - final long rowStride = 2 * columnsl; - final long n2d2 = columnsl / 2 + 1; - final DoubleLargeArray temp = new DoubleLargeArray(n2d2 * 2 * rowsl, false); - final long temp_stride = 2 * rowsl; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstRow; i < lastRow; i++) { - fftColumns.realForward(a, i * columnsl); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl)); //first column is always real - } - fftRows.realForwardFull(temp); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = 1 + l * p; - final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getDouble(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp, c * temp_stride); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getDouble(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getDouble(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); - } - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getDouble(c * temp_stride + idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstRow = 1 + l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getDouble(idx4)); - a.setDouble(idx3 + 1, -a.getDouble(idx4 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, r * columnsl); - } - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl)); //first column is always real - } - fftRows.realForwardFull(temp); - - for (long c = 1; c < n2d2 - 1; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getDouble(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp, c * temp_stride); - } - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getDouble(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realForwardFull(temp, (n2d2 - 1) * temp_stride); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getDouble(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexForward(temp, (n2d2 - 1) * temp_stride); - } - - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getDouble(c * temp_stride + idx1 + 1)); - } - } - - //fill symmetric - for (long r = 1; r < rowsl; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getDouble(idx4)); - a.setDouble(idx3 + 1, -a.getDouble(idx4 + 1)); - } - } - } - } - - private void mixedRadixRealInverseFull(final double[][] a, final boolean scale) - { - final int n2d2 = columns / 2 + 1; - final double[][] temp = new double[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a[i], 0, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int c = firstColumn; c < lastColumn; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[r], 0, scale); - } - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r][0]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - temp[c][idx1] = a[r][idx2]; - temp[c][idx1 + 1] = a[r][idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r][1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = n2d2 - 1; - temp[idx2][idx1] = a[r][2 * idx2]; - temp[idx2][idx1 + 1] = a[r][1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx2 = 2 * c; - a[r][idx2] = temp[c][idx1]; - a[r][idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx3 = rows - r; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[0][idx1] = a[0][idx2]; - a[0][idx1 + 1] = -a[0][idx2 + 1]; - a[r][idx1] = a[idx3][idx2]; - a[r][idx1 + 1] = -a[idx3][idx2 + 1]; - } - } - } - } - - private void mixedRadixRealInverseFull(final double[] a, final boolean scale) - { - final int rowStride = 2 * columns; - final int n2d2 = columns / 2 + 1; - final double[][] temp = new double[n2d2][2 * rows]; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rows >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a, i * columns, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstColumn = 1 + l * p; - final int lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int c = firstColumn; c < lastColumn; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - } - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstRow = 1 + l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int r = firstRow; r < lastRow; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, r * columns, scale); - } - for (int r = 0; r < rows; r++) { - temp[0][r] = a[r * columns]; //first column is always real - } - fftRows.realInverseFull(temp[0], scale); - - for (int c = 1; c < n2d2 - 1; c++) { - int idx0 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns + idx0; - temp[c][idx1] = a[idx2]; - temp[c][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[c], scale); - } - - if ((columns % 2) == 0) { - for (int r = 0; r < rows; r++) { - temp[n2d2 - 1][r] = a[r * columns + 1]; - //imaginary part = 0; - } - fftRows.realInverseFull(temp[n2d2 - 1], scale); - - } else { - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - int idx2 = r * columns; - int idx3 = n2d2 - 1; - temp[idx3][idx1] = a[idx2 + 2 * idx3]; - temp[idx3][idx1 + 1] = a[idx2 + 1]; - } - fftRows.complexInverse(temp[n2d2 - 1], scale); - } - - for (int r = 0; r < rows; r++) { - int idx1 = 2 * r; - for (int c = 0; c < n2d2; c++) { - int idx0 = 2 * c; - int idx2 = r * rowStride + idx0; - a[idx2] = temp[c][idx1]; - a[idx2 + 1] = temp[c][idx1 + 1]; - } - } - - //fill symmetric - for (int r = 1; r < rows; r++) { - int idx5 = r * rowStride; - int idx6 = (rows - r + 1) * rowStride; - for (int c = n2d2; c < columns; c++) { - int idx1 = 2 * c; - int idx2 = 2 * (columns - c); - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - int idx3 = idx5 + idx1; - int idx4 = idx6 - idx1; - a[idx3] = a[idx4]; - a[idx3 + 1] = -a[idx4 + 1]; - } - } - } - } - - private void mixedRadixRealInverseFull(final DoubleLargeArray a, final boolean scale) - { - final long rowStride = 2 * columnsl; - final long n2d2 = columnsl / 2 + 1; - final DoubleLargeArray temp = new DoubleLargeArray(n2d2 * 2 * rowsl, false); - final long temp_stride = 2 * rowsl; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (rowsl >= nthreads) && (n2d2 - 2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long i = firstRow; i < lastRow; i++) { - fftColumns.realInverse2(a, i * columnsl, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl)); //first column is always real - } - fftRows.realInverseFull(temp, scale); - - p = (n2d2 - 2) / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstColumn = 1 + l * p; - final long lastColumn = (l == (nthreads - 1)) ? n2d2 - 1 : firstColumn + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long c = firstColumn; c < lastColumn; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getDouble(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexInverse(temp, c * temp_stride, scale); - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getDouble(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getDouble(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); - } - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getDouble(c * temp_stride + idx1 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstRow = 1 + l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long r = firstRow; r < lastRow; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getDouble(idx4)); - a.setDouble(idx3 + 1, -a.getDouble(idx4 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - for (long r = 0; r < rowsl; r++) { - temp.setDouble(r, a.getDouble(r * columnsl)); //first column is always real - } - fftRows.realInverseFull(temp, scale); - - for (long c = 1; c < n2d2 - 1; c++) { - long idx0 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl + idx0; - temp.setDouble(c * temp_stride + idx1, a.getDouble(idx2)); - temp.setDouble(c * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexInverse(temp, c * temp_stride, scale); - } - - if ((columnsl % 2) == 0) { - for (long r = 0; r < rowsl; r++) { - temp.setDouble((n2d2 - 1) * temp_stride + r, a.getDouble(r * columnsl + 1)); - //imaginary part = 0; - } - fftRows.realInverseFull(temp, (n2d2 - 1) * temp_stride, scale); - - } else { - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - long idx2 = r * columnsl; - long idx3 = n2d2 - 1; - temp.setDouble(idx3 * temp_stride + idx1, a.getDouble(idx2 + 2 * idx3)); - temp.setDouble(idx3 * temp_stride + idx1 + 1, a.getDouble(idx2 + 1)); - } - fftRows.complexInverse(temp, (n2d2 - 1) * temp_stride, scale); - } - - for (long r = 0; r < rowsl; r++) { - long idx1 = 2 * r; - for (long c = 0; c < n2d2; c++) { - long idx0 = 2 * c; - long idx2 = r * rowStride + idx0; - a.setDouble(idx2, temp.getDouble(c * temp_stride + idx1)); - a.setDouble(idx2 + 1, temp.getDouble(c * temp_stride + idx1 + 1)); - } - } - - //fill symmetric - for (long r = 1; r < rowsl; r++) { - long idx5 = r * rowStride; - long idx6 = (rowsl - r + 1) * rowStride; - for (long c = n2d2; c < columnsl; c++) { - long idx1 = 2 * c; - long idx2 = 2 * (columnsl - c); - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - long idx3 = idx5 + idx1; - long idx4 = idx6 - idx1; - a.setDouble(idx3, a.getDouble(idx4)); - a.setDouble(idx3 + 1, -a.getDouble(idx4 + 1)); - } - } - } - } - - private void rdft2d_sub(int isgn, double[] a) - { - int n1h, j; - double xi; - int idx1, idx2; - - n1h = rows >> 1; - if (isgn < 0) { - for (int i = 1; i < n1h; i++) { - j = rows - i; - idx1 = i * columns; - idx2 = j * columns; - xi = a[idx1] - a[idx2]; - a[idx1] += a[idx2]; - a[idx2] = xi; - xi = a[idx2 + 1] - a[idx1 + 1]; - a[idx1 + 1] += a[idx2 + 1]; - a[idx2 + 1] = xi; - } - } else { - for (int i = 1; i < n1h; i++) { - j = rows - i; - idx1 = i * columns; - idx2 = j * columns; - a[idx2] = 0.5f * (a[idx1] - a[idx2]); - a[idx1] -= a[idx2]; - a[idx2 + 1] = 0.5f * (a[idx1 + 1] + a[idx2 + 1]); - a[idx1 + 1] -= a[idx2 + 1]; - } - } - } - - private void rdft2d_sub(int isgn, DoubleLargeArray a) - { - long n1h, j; - double xi; - long idx1, idx2; - - n1h = rowsl >> 1; - if (isgn < 0) { - for (long i = 1; i < n1h; i++) { - j = rowsl - i; - idx1 = i * columnsl; - idx2 = j * columnsl; - xi = a.getDouble(idx1) - a.getDouble(idx2); - a.setDouble(idx1, a.getDouble(idx1) + a.getDouble(idx2)); - a.setDouble(idx2, xi); - xi = a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, xi); - } - } else { - for (long i = 1; i < n1h; i++) { - j = rowsl - i; - idx1 = i * columnsl; - idx2 = j * columnsl; - a.setDouble(idx2, 0.5f * (a.getDouble(idx1) - a.getDouble(idx2))); - a.setDouble(idx1, a.getDouble(idx1) - a.getDouble(idx2)); - a.setDouble(idx2 + 1, 0.5f * (a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1))); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) - a.getDouble(idx2 + 1)); - } - } - } - - private void rdft2d_sub(int isgn, double[][] a) - { - int n1h, j; - double xi; - - n1h = rows >> 1; - if (isgn < 0) { - for (int i = 1; i < n1h; i++) { - j = rows - i; - xi = a[i][0] - a[j][0]; - a[i][0] += a[j][0]; - a[j][0] = xi; - xi = a[j][1] - a[i][1]; - a[i][1] += a[j][1]; - a[j][1] = xi; - } - } else { - for (int i = 1; i < n1h; i++) { - j = rows - i; - a[j][0] = 0.5f * (a[i][0] - a[j][0]); - a[i][0] -= a[j][0]; - a[j][1] = 0.5f * (a[i][1] + a[j][1]); - a[i][1] -= a[j][1]; - } - } - } - - private void cdft2d_sub(int isgn, double[] a, boolean scale) - { - int idx1, idx2, idx3, idx4, idx5; - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - - private void cdft2d_sub(int isgn, DoubleLargeArray a, boolean scale) - { - long idx1, idx2, idx3, idx4, idx5; - long nt = 8 * rowsl; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } else { - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - - private void cdft2d_sub(int isgn, double[][] a, boolean scale) - { - int idx2, idx3, idx4, idx5; - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - t[idx3] = a[r][2]; - t[idx3 + 1] = a[r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - a[r][2] = t[idx3]; - a[r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - t[idx3] = a[r][2]; - t[idx3 + 1] = a[r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - a[r][2] = t[idx3]; - a[r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][0]; - t[idx2 + 1] = a[r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][0] = t[idx2]; - a[r][1] = t[idx2 + 1]; - } - } - } - } - - private void xdft2d0_subth1(final int icr, final int isgn, final double[] a, final boolean scale) - { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a, r * columns, scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse(a, r * columns, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth1(final long icr, final int isgn, final DoubleLargeArray a, final boolean scale) - { - final int nthreads = (int) (ConcurrencyUtils.getNumberOfThreads() > rowsl ? rowsl : ConcurrencyUtils.getNumberOfThreads()); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - } - } else { - if (isgn == 1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realInverse(a, r * columnsl, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final int icr, final int isgn, final double[] a, final boolean scale) - { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a, r * columns, scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a, r * columns); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse2(a, r * columns, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final long icr, final int isgn, final DoubleLargeArray a, final boolean scale) - { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.complexInverse(a, r * columnsl, scale); - } - } - } else { - if (isgn == 1) { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realForward(a, r * columnsl); - } - } else { - for (long r = n0; r < rowsl; r += nthreads) { - fftColumns.realInverse2(a, r * columnsl, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth1(final int icr, final int isgn, final double[][] a, final boolean scale) - { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a[r], scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse(a[r], scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft2d0_subth2(final int icr, final int isgn, final double[][] a, final boolean scale) - { - final int nthreads = ConcurrencyUtils.getNumberOfThreads() > rows ? rows : ConcurrencyUtils.getNumberOfThreads(); - - Future[] futures = new Future[nthreads]; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - if (icr == 0) { - if (isgn == -1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.complexInverse(a[r], scale); - } - } - } else { - if (isgn == 1) { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realForward(a[r]); - } - } else { - for (int r = n0; r < rows; r += nthreads) { - fftColumns.realInverse2(a[r], 0, scale); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final double[] a, final boolean scale) - { - int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthread; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx1, idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = r * columns + 2 * n0; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final DoubleLargeArray a, final boolean scale) - { - int nthread = (int) Math.min(columnsl / 2, ConcurrencyUtils.getNumberOfThreads()); - long nt = 8 * rowsl; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - final long ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthread; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - long idx1, idx2, idx3, idx4, idx5; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 4 * nthreads) { - for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } else { - if (columnsl > 4 * nthreads) { - for (long c = 8 * n0; c < columnsl; c += 8 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 4 * n0; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2 * nthreads) { - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = r * columnsl + 2 * n0; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft2d_subth(final int isgn, final double[][] a, final boolean scale) - { - int nthread = Math.min(columns / 2, ConcurrencyUtils.getNumberOfThreads()); - int nt = 8 * rows; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthread]; - final int nthreads = nthread; - for (int i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][4 * n0]; - t[idx2 + 1] = a[r][4 * n0 + 1]; - t[idx3] = a[r][4 * n0 + 2]; - t[idx3 + 1] = a[r][4 * n0 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][4 * n0] = t[idx2]; - a[r][4 * n0 + 1] = t[idx2 + 1]; - a[r][4 * n0 + 2] = t[idx3]; - a[r][4 * n0 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][2 * n0]; - t[idx2 + 1] = a[r][2 * n0 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + 1]; - } - } - } else { - if (columns > 4 * nthreads) { - for (int c = 8 * n0; c < columns; c += 8 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[r][c]; - t[idx2 + 1] = a[r][c + 1]; - t[idx3] = a[r][c + 2]; - t[idx3 + 1] = a[r][c + 3]; - t[idx4] = a[r][c + 4]; - t[idx4 + 1] = a[r][c + 5]; - t[idx5] = a[r][c + 6]; - t[idx5 + 1] = a[r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[r][c] = t[idx2]; - a[r][c + 1] = t[idx2 + 1]; - a[r][c + 2] = t[idx3]; - a[r][c + 3] = t[idx3 + 1]; - a[r][c + 4] = t[idx4]; - a[r][c + 5] = t[idx4 + 1]; - a[r][c + 6] = t[idx5]; - a[r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[r][4 * n0]; - t[idx2 + 1] = a[r][4 * n0 + 1]; - t[idx3] = a[r][4 * n0 + 2]; - t[idx3 + 1] = a[r][4 * n0 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[r][4 * n0] = t[idx2]; - a[r][4 * n0 + 1] = t[idx2 + 1]; - a[r][4 * n0 + 2] = t[idx3]; - a[r][4 * n0 + 3] = t[idx3 + 1]; - } - } else if (columns == 2 * nthreads) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[r][2 * n0]; - t[idx2 + 1] = a[r][2 * n0 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[r][2 * n0] = t[idx2]; - a[r][2 * n0 + 1] = t[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void fillSymmetric(final double[] a) - { - final int twon2 = 2 * columns; - int idx1, idx2, idx3, idx4; - int n1d2 = rows / 2; - - for (int r = (rows - 1); r >= 1; r--) { - idx1 = r * columns; - idx2 = 2 * idx1; - for (int c = 0; c < columns; c += 2) { - a[idx2 + c] = a[idx1 + c]; - a[idx1 + c] = 0; - a[idx2 + c + 1] = a[idx1 + c + 1]; - a[idx1 + c + 1] = 0; - } - } - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int l1k = n1d2 / nthreads; - final int newn2 = 2 * columns; - for (int i = 0; i < nthreads; i++) { - final int l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) - l1offa = i * l1k + 1; - else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx1, idx2, idx3, idx4; - - for (int r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx2 = (rows - r) * newn2; - idx3 = idx1 + columns; - a[idx3] = a[idx2 + 1]; - a[idx3 + 1] = -a[idx2]; - } - for (int r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx3 = (rows - r + 1) * newn2; - for (int c = columns + 2; c < newn2; c += 2) { - idx2 = idx3 - c; - idx4 = idx1 + c; - a[idx4] = a[idx2]; - a[idx4 + 1] = -a[idx2 + 1]; - - } - } - for (int r = l2offa; r < l2stopa; r++) { - idx3 = ((rows - r) % rows) * newn2; - idx4 = r * newn2; - for (int c = 0; c < newn2; c += 2) { - idx1 = idx3 + (newn2 - c) % newn2; - idx2 = idx4 + c; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r) * twon2; - a[idx2 + columns] = a[idx3 + 1]; - a[idx2 + columns + 1] = -a[idx3]; - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r + 1) * twon2; - for (int c = columns + 2; c < twon2; c += 2) { - a[idx2 + c] = a[idx3 - c]; - a[idx2 + c + 1] = -a[idx3 - c + 1]; - - } - } - for (int r = 0; r <= rows / 2; r++) { - idx1 = r * twon2; - idx4 = ((rows - r) % rows) * twon2; - for (int c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a[idx3] = a[idx2]; - a[idx3 + 1] = -a[idx2 + 1]; - } - } - } - a[columns] = -a[1]; - a[1] = 0; - idx1 = n1d2 * twon2; - a[idx1 + columns] = -a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx1 + columns + 1] = 0; - } - - private void fillSymmetric(final DoubleLargeArray a) - { - final long twon2 = 2 * columnsl; - long idx1, idx2, idx3, idx4; - long n1d2 = rowsl / 2; - - for (long r = (rowsl - 1); r >= 1; r--) { - idx1 = r * columnsl; - idx2 = 2 * idx1; - for (long c = 0; c < columnsl; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx1 + c)); - a.setDouble(idx1 + c, 0); - a.setDouble(idx2 + c + 1, a.getDouble(idx1 + c + 1)); - a.setDouble(idx1 + c + 1, 0); - } - } - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long l1k = n1d2 / nthreads; - final long newn2 = 2 * columnsl; - for (int i = 0; i < nthreads; i++) { - final long l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) - l1offa = i * l1k + 1; - else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - long idx1, idx2, idx3, idx4; - - for (long r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx2 = (rowsl - r) * newn2; - idx3 = idx1 + columnsl; - a.setDouble(idx3, a.getDouble(idx2 + 1)); - a.setDouble(idx3 + 1, -a.getDouble(idx2)); - } - for (long r = l1offa; r < l1stopa; r++) { - idx1 = r * newn2; - idx3 = (rowsl - r + 1) * newn2; - for (long c = columnsl + 2; c < newn2; c += 2) { - idx2 = idx3 - c; - idx4 = idx1 + c; - a.setDouble(idx4, a.getDouble(idx2)); - a.setDouble(idx4 + 1, -a.getDouble(idx2 + 1)); - - } - } - for (long r = l2offa; r < l2stopa; r++) { - idx3 = ((rowsl - r) % rowsl) * newn2; - idx4 = r * newn2; - for (long c = 0; c < newn2; c += 2) { - idx1 = idx3 + (newn2 - c) % newn2; - idx2 = idx4 + c; - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r) * twon2; - a.setDouble(idx2 + columnsl, a.getDouble(idx3 + 1)); - a.setDouble(idx2 + columnsl + 1, -a.getDouble(idx3)); - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r + 1) * twon2; - for (long c = columnsl + 2; c < twon2; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx3 - c)); - a.setDouble(idx2 + c + 1, -a.getDouble(idx3 - c + 1)); - - } - } - for (long r = 0; r <= rowsl / 2; r++) { - idx1 = r * twon2; - idx4 = ((rowsl - r) % rowsl) * twon2; - for (long c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a.setDouble(idx3, a.getDouble(idx2)); - a.setDouble(idx3 + 1, -a.getDouble(idx2 + 1)); - } - } - } - a.setDouble(columnsl, -a.getDouble(1)); - a.setDouble(1, 0); - idx1 = n1d2 * twon2; - a.setDouble(idx1 + columnsl, -a.getDouble(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx1 + columnsl + 1, 0); - } - - private void fillSymmetric(final double[][] a) - { - final int newn2 = 2 * columns; - int n1d2 = rows / 2; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int l1k = n1d2 / nthreads; - for (int i = 0; i < nthreads; i++) { - final int l1offa, l1stopa, l2offa, l2stopa; - if (i == 0) - l1offa = i * l1k + 1; - else { - l1offa = i * l1k; - } - l1stopa = i * l1k + l1k; - l2offa = i * l1k; - if (i == nthreads - 1) { - l2stopa = i * l1k + l1k + 1; - } else { - l2stopa = i * l1k + l1k; - } - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx1, idx2; - for (int r = l1offa; r < l1stopa; r++) { - idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = l1offa; r < l1stopa; r++) { - idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - - } - } - for (int r = l2offa; r < l2stopa; r++) { - idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c = c + 2) { - idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - int idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - } - } - for (int r = 0; r <= rows / 2; r++) { - int idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c += 2) { - int idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - } - a[0][columns] = -a[0][1]; - a[0][1] = 0; - a[n1d2][columns] = -a[n1d2][1]; - a[n1d2][1] = 0; - a[n1d2][columns + 1] = 0; - } -} diff --git a/src/main/java/org/jtransforms/fft/DoubleFFT_3D.java b/src/main/java/org/jtransforms/fft/DoubleFFT_3D.java deleted file mode 100644 index fbc355c..0000000 --- a/src/main/java/org/jtransforms/fft/DoubleFFT_3D.java +++ /dev/null @@ -1,7448 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.concurrent.Future; -import org.jtransforms.utils.ConcurrencyUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.Utilities; - -/** - * Computes 3D Discrete Fourier Transform (DFT) of complex and real, double - * precision data. The sizes of all three dimensions can be arbitrary numbers. - * This is a parallel implementation of split-radix and mixed-radix algorithms - * optimized for SMP systems.
- *
- * Part of the code is derived from General Purpose FFT Package written by - * Takuya Ooura (http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html) - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class DoubleFFT_3D -{ - - private int slices; - - private long slicesl; - - private int rows; - - private long rowsl; - - private int columns; - - private long columnsl; - - private int sliceStride; - - private long sliceStridel; - - private int rowStride; - - private long rowStridel; - - private DoubleFFT_1D fftSlices, fftRows, fftColumns; - - private boolean isPowerOfTwo = false; - - private boolean useThreads = false; - - /** - * Creates new instance of DoubleFFT_3D. - * - * @param slices number of slices - * @param rows number of rows - * @param columns number of columns - * - */ - public DoubleFFT_3D(long slices, long rows, long columns) - { - if (slices <= 1 || rows <= 1 || columns <= 1) { - throw new IllegalArgumentException("slices, rows and columns must be greater than 1"); - } - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.sliceStride = (int) (rows * columns); - this.rowStride = (int) columns; - this.sliceStridel = rows * columns; - this.rowStridel = columns; - - if (slices * rows * columns >= ConcurrencyUtils.getThreadsBeginN_3D()) { - this.useThreads = true; - } - if (ConcurrencyUtils.isPowerOf2(slices) && ConcurrencyUtils.isPowerOf2(rows) && ConcurrencyUtils.isPowerOf2(columns)) { - isPowerOfTwo = true; - } - long largeArraysBenginN = ConcurrencyUtils.getLargeArraysBeginN(); - if (slices * rows * columns > (1 << 28)) { - ConcurrencyUtils.setLargeArraysBeginN(Math.min(Math.min(rows, columns), slices)); - } - fftSlices = new DoubleFFT_1D(slices); - if (slices == rows) { - fftRows = fftSlices; - } else { - fftRows = new DoubleFFT_1D(rows); - } - if (slices == columns) { - fftColumns = fftSlices; - } else if (rows == columns) { - fftColumns = fftRows; - } else { - fftColumns = new DoubleFFT_1D(columns); - } - ConcurrencyUtils.setLargeArraysBeginN(largeArraysBenginN); - } - - /** - * Computes 3D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. element - * (i,j,k) of 3D array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. Complex number is stored as two - * double values in sequence: the real and imaginary part, i.e. the input - * array must be of size slices*rows*2*columns. The physical layout of the - * input data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3],
-     * a[k1*sliceStride + k2*rowStride + 2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final double[] a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - int oldn3 = columns; - columns = 2 * columns; - sliceStride = rows * columns; - rowStride = columns; - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, -1, a, true); - cdft3db_subth(-1, a, true); - } else { - xdft3da_sub2(0, -1, a, true); - cdft3db_sub(-1, a, true); - } - columns = oldn3; - sliceStride = rows * columns; - rowStride = columns; - } else { - sliceStride = 2 * rows * columns; - rowStride = 2 * columns; - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx1 + r * rowStride); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx1 + r * rowStride); - } - } - - double[] temp = new double[2 * rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - sliceStride = rows * columns; - rowStride = columns; - } - } - - /** - * Computes 3D forward DFT of complex data leaving the result in - * a. The data is stored in 1D array addressed in slice-major, - * then row-major, then column-major, in order of significance, i.e. element - * (i,j,k) of 3D array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. Complex number is stored as two - * double values in sequence: the real and imaginary part, i.e. the input - * array must be of size slices*rows*2*columns. The physical layout of the - * input data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3],
-     * a[k1*sliceStride + k2*rowStride + 2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final DoubleLargeArray a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - long oldn3 = columnsl; - columnsl = 2 * columnsl; - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, -1, a, true); - cdft3db_subth(-1, a, true); - } else { - xdft3da_sub2(0, -1, a, true); - cdft3db_sub(-1, a, true); - } - columnsl = oldn3; - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - } else { - sliceStridel = 2 * rowsl * columnsl; - rowStridel = 2 * columnsl; - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx1 + r * rowStridel); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftSlices.complexForward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx1 + r * rowStridel); - } - } - - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - - temp = new DoubleLargeArray(2 * slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftSlices.complexForward(temp); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - } - } - - /** - * Computes 3D forward DFT of complex data leaving the result in - * a. The data is stored in 3D array. Complex data is - * represented by 2 double values in sequence: the real and imaginary part, - * i.e. the input array must be of size slices by rows by 2*columns. The - * physical layout of the input data is as follows: - * - * *
-     * a[k1][k2][2*k3] = Re[k1][k2][k3], a[k1][k2][2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - */ - public void complexForward(final double[][][] a) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - int oldn3 = columns; - columns = 2 * columns; - - sliceStride = rows * columns; - rowStride = columns; - - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, -1, a, true); - cdft3db_subth(-1, a, true); - } else { - xdft3da_sub2(0, -1, a, true); - cdft3db_sub(-1, a, true); - } - columns = oldn3; - sliceStride = rows * columns; - rowStride = columns; - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } - - double[] temp = new double[2 * rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - } - } - - /** - * Computes 3D inverse DFT of complex data leaving the result in - * a. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. Complex number is stored as two - * double values in sequence: the real and imaginary part, i.e. the input - * array must be of size slices*rows*2*columns. The physical layout of the - * input data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3],
-     * a[k1*sliceStride + k2*rowStride + 2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(final double[] a, final boolean scale) - { - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - - if (isPowerOfTwo) { - int oldn3 = columns; - columns = 2 * columns; - sliceStride = rows * columns; - rowStride = columns; - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, 1, a, scale); - cdft3db_subth(1, a, scale); - } else { - xdft3da_sub2(0, 1, a, scale); - cdft3db_sub(1, a, scale); - } - columns = oldn3; - sliceStride = rows * columns; - rowStride = columns; - } else { - sliceStride = 2 * rows * columns; - rowStride = 2 * columns; - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx1 + r * rowStride, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - for (int r = firstRow; r < lastRow; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx1 + r * rowStride, scale); - } - } - double[] temp = new double[2 * rows]; - for (int s = 0; s < slices; s++) { - int idx1 = s * sliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + idx2 + r * rowStride; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - temp = new double[2 * slices]; - for (int r = 0; r < rows; r++) { - int idx1 = r * rowStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx3 = s * sliceStride + idx1 + idx2; - int idx4 = 2 * s; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - sliceStride = rows * columns; - rowStride = columns; - } - } - - /** - * Computes 3D inverse DFT of complex data leaving the result in - * a. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. Complex number is stored as two - * double values in sequence: the real and imaginary part, i.e. the input - * array must be of size slices*rows*2*columns. The physical layout of the - * input data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3],
-     * a[k1*sliceStride + k2*rowStride + 2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(final DoubleLargeArray a, final boolean scale) - { - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - - if (isPowerOfTwo) { - long oldn3 = columnsl; - columnsl = 2 * columnsl; - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, 1, a, scale); - cdft3db_subth(1, a, scale); - } else { - xdft3da_sub2(0, 1, a, scale); - cdft3db_sub(1, a, scale); - } - columnsl = oldn3; - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - } else { - sliceStridel = 2 * rowsl * columnsl; - rowStridel = 2 * columnsl; - if ((nthreads > 1) && useThreads && (slicesl >= nthreads) && (rowsl >= nthreads) && (columnsl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx1 + r * rowStridel, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rowsl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? rowsl : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * slicesl, false); - for (long r = firstRow; r < lastRow; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftSlices.complexInverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx1 + r * rowStridel, scale); - } - } - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - for (long s = 0; s < slicesl; s++) { - long idx1 = s * sliceStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + idx2 + r * rowStridel; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - temp = new DoubleLargeArray(2 * slicesl, false); - for (long r = 0; r < rowsl; r++) { - long idx1 = r * rowStridel; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftSlices.complexInverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx3 = s * sliceStridel + idx1 + idx2; - long idx4 = 2 * s; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - sliceStridel = rowsl * columnsl; - rowStridel = columnsl; - } - } - - /** - * Computes 3D inverse DFT of complex data leaving the result in - * a. The data is stored in a 3D array. Complex data is - * represented by 2 double values in sequence: the real and imaginary part, - * i.e. the input array must be of size slices by rows by 2*columns. The - * physical layout of the input data is as follows: - * - * *
-     * a[k1][k2][2*k3] = Re[k1][k2][k3], a[k1][k2][2*k3+1] = Im[k1][k2][k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<=k3<columns,
-     * 
- * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void complexInverse(final double[][][] a, final boolean scale) - { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if (isPowerOfTwo) { - int oldn3 = columns; - columns = 2 * columns; - sliceStride = rows * columns; - rowStride = columns; - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(0, 1, a, scale); - cdft3db_subth(1, a, scale); - } else { - xdft3da_sub2(0, 1, a, scale); - cdft3db_sub(1, a, scale); - } - columns = oldn3; - sliceStride = rows * columns; - rowStride = columns; - } else { - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (rows >= nthreads) && (columns >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = rows / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? rows : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } - double[] temp = new double[2 * rows]; - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - temp = new double[2 * slices]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx4 = 2 * s; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. The physical layout of the output - * data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1*sliceStride +
-     * k2*rowStride + 2*k3+1] = Im[k1][k2][k3] =
-     * -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3], 0<=k1<slices,
-     * 0<=k2<rows, 0<k3<columns/2, a[k1*sliceStride + k2*rowStride]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1*sliceStride +
-     * k2*rowStride + 1] = Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0],
-     * a[k1*sliceStride + (rows-k2)*rowStride + 1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1*sliceStride + (rows-k2)*rowStride] =
-     * -Im[(slices-k1)%slices][k2][columns/2] = Im[k1][rows-k2][columns/2],
-     * 0<=k1<slices, 0<k2<rows/2, a[k1*sliceStride] = Re[k1][0][0] =
-     * Re[slices-k1][0][0], a[k1*sliceStride + 1] = Im[k1][0][0] =
-     * -Im[slices-k1][0][0], a[k1*sliceStride + (rows/2)*rowStride] =
-     * Re[k1][rows/2][0] = Re[slices-k1][rows/2][0], a[k1*sliceStride +
-     * (rows/2)*rowStride + 1] = Im[k1][rows/2][0] = -Im[slices-k1][rows/2][0],
-     * a[(slices-k1)*sliceStride + 1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[(slices-k1)*sliceStride] =
-     * -Im[k1][0][columns/2] = Im[slices-k1][0][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2) * rowStride] =
-     * -Im[k1][rows/2][columns/2] = Im[slices-k1][rows/2][columns/2],
-     * 0<k1<slices/2, a[0] = Re[0][0][0], a[1] = Re[0][0][columns/2],
-     * a[(rows/2)*rowStride] = Re[0][rows/2][0], a[(rows/2)*rowStride + 1] =
-     * Re[0][rows/2][columns/2], a[(slices/2)*sliceStride] = Re[slices/2][0][0],
-     * a[(slices/2)*sliceStride + 1] = Re[slices/2][0][columns/2],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride] = Re[slices/2][rows/2][0],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(double[] a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth1(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub1(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. The physical layout of the output - * data is as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1*sliceStride +
-     * k2*rowStride + 2*k3+1] = Im[k1][k2][k3] =
-     * -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3], 0<=k1<slices,
-     * 0<=k2<rows, 0<k3<columns/2, a[k1*sliceStride + k2*rowStride]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1*sliceStride +
-     * k2*rowStride + 1] = Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0],
-     * a[k1*sliceStride + (rows-k2)*rowStride + 1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1*sliceStride + (rows-k2)*rowStride] =
-     * -Im[(slices-k1)%slices][k2][columns/2] = Im[k1][rows-k2][columns/2],
-     * 0<=k1<slices, 0<k2<rows/2, a[k1*sliceStride] = Re[k1][0][0] =
-     * Re[slices-k1][0][0], a[k1*sliceStride + 1] = Im[k1][0][0] =
-     * -Im[slices-k1][0][0], a[k1*sliceStride + (rows/2)*rowStride] =
-     * Re[k1][rows/2][0] = Re[slices-k1][rows/2][0], a[k1*sliceStride +
-     * (rows/2)*rowStride + 1] = Im[k1][rows/2][0] = -Im[slices-k1][rows/2][0],
-     * a[(slices-k1)*sliceStride + 1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[(slices-k1)*sliceStride] =
-     * -Im[k1][0][columns/2] = Im[slices-k1][0][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2) * rowStride] =
-     * -Im[k1][rows/2][columns/2] = Im[slices-k1][rows/2][columns/2],
-     * 0<k1<slices/2, a[0] = Re[0][0][0], a[1] = Re[0][0][columns/2],
-     * a[(rows/2)*rowStride] = Re[0][rows/2][0], a[(rows/2)*rowStride + 1] =
-     * Re[0][rows/2][columns/2], a[(slices/2)*sliceStride] = Re[slices/2][0][0],
-     * a[(slices/2)*sliceStride + 1] = Re[slices/2][0][columns/2],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride] = Re[slices/2][rows/2][0],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(DoubleLargeArray a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth1(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub1(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 3D array. The physical - * layout of the output data is as follows: - * - * *
-     * a[k1][k2][2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1][k2][2*k3+1] =
-     * Im[k1][k2][k3] = -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<k3<columns/2, a[k1][k2][0]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1][k2][1] =
-     * Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0], a[k1][rows-k2][1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1][rows-k2][0] = -Im[(slices-k1)%slices][k2][columns/2] =
-     * Im[k1][rows-k2][columns/2], 0<=k1<slices, 0<k2<rows/2,
-     * a[k1][0][0] = Re[k1][0][0] = Re[slices-k1][0][0], a[k1][0][1] =
-     * Im[k1][0][0] = -Im[slices-k1][0][0], a[k1][rows/2][0] = Re[k1][rows/2][0]
-     * = Re[slices-k1][rows/2][0], a[k1][rows/2][1] = Im[k1][rows/2][0] =
-     * -Im[slices-k1][rows/2][0], a[slices-k1][0][1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[slices-k1][0][0] = -Im[k1][0][columns/2] =
-     * Im[slices-k1][0][columns/2], a[slices-k1][rows/2][1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[slices-k1][rows/2][0] = -Im[k1][rows/2][columns/2] =
-     * Im[slices-k1][rows/2][columns/2], 0<k1<slices/2, a[0][0][0] =
-     * Re[0][0][0], a[0][0][1] = Re[0][0][columns/2], a[0][rows/2][0] =
-     * Re[0][rows/2][0], a[0][rows/2][1] = Re[0][rows/2][columns/2],
-     * a[slices/2][0][0] = Re[slices/2][0][0], a[slices/2][0][1] =
-     * Re[slices/2][0][columns/2], a[slices/2][rows/2][0] =
-     * Re[slices/2][rows/2][0], a[slices/2][rows/2][1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * forward transform, use realForwardFull. To get back the - * original data, use realInverse on the output of this method. - * - * @param a data to transform - */ - public void realForward(double[][][] a) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth1(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub1(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices*rows*2*columns, with only the first - * slices*rows*columns elements filled with real data. To get back the - * original data, use complexInverse on the output of this - * method. - * - * @param a data to transform - */ - public void realForwardFull(double[] a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices*rows*2*columns, with only the first - * slices*rows*columns elements filled with real data. To get back the - * original data, use complexInverse on the output of this - * method. - * - * @param a data to transform - */ - public void realForwardFull(DoubleLargeArray a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 3D forward DFT of real data leaving the result in a - * . This method computes full real forward transform, i.e. you will get the - * same result as from complexForward called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices by rows by 2*columns, with only the first - * slices by rows by columns elements filled with real data. To get back the - * original data, use complexInverse on the output of this - * method. - * - * @param a data to transform - */ - public void realForwardFull(double[][][] a) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, -1, a, true); - cdft3db_subth(-1, a, true); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, -1, a, true); - cdft3db_sub(-1, a, true); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealForwardFull(a); - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. The physical layout of the input - * data has to be as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1*sliceStride +
-     * k2*rowStride + 2*k3+1] = Im[k1][k2][k3] =
-     * -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3], 0<=k1<slices,
-     * 0<=k2<rows, 0<k3<columns/2, a[k1*sliceStride + k2*rowStride]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1*sliceStride +
-     * k2*rowStride + 1] = Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0],
-     * a[k1*sliceStride + (rows-k2)*rowStride + 1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1*sliceStride + (rows-k2)*rowStride] =
-     * -Im[(slices-k1)%slices][k2][columns/2] = Im[k1][rows-k2][columns/2],
-     * 0<=k1<slices, 0<k2<rows/2, a[k1*sliceStride] = Re[k1][0][0] =
-     * Re[slices-k1][0][0], a[k1*sliceStride + 1] = Im[k1][0][0] =
-     * -Im[slices-k1][0][0], a[k1*sliceStride + (rows/2)*rowStride] =
-     * Re[k1][rows/2][0] = Re[slices-k1][rows/2][0], a[k1*sliceStride +
-     * (rows/2)*rowStride + 1] = Im[k1][rows/2][0] = -Im[slices-k1][rows/2][0],
-     * a[(slices-k1)*sliceStride + 1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[(slices-k1)*sliceStride] =
-     * -Im[k1][0][columns/2] = Im[slices-k1][0][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2) * rowStride] =
-     * -Im[k1][rows/2][columns/2] = Im[slices-k1][rows/2][columns/2],
-     * 0<k1<slices/2, a[0] = Re[0][0][0], a[1] = Re[0][0][columns/2],
-     * a[(rows/2)*rowStride] = Re[0][rows/2][0], a[(rows/2)*rowStride + 1] =
-     * Re[0][rows/2][columns/2], a[(slices/2)*sliceStride] = Re[slices/2][0][0],
-     * a[(slices/2)*sliceStride + 1] = Re[slices/2][0][columns/2],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride] = Re[slices/2][rows/2][0],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(double[] a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft3d_sub(-1, a); - cdft3db_subth(1, a, scale); - xdft3da_subth1(1, 1, a, scale); - } else { - rdft3d_sub(-1, a); - cdft3db_sub(1, a, scale); - xdft3da_sub1(1, 1, a, scale); - } - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 1D array addressed in - * slice-major, then row-major, then column-major, in order of significance, - * i.e. element (i,j,k) of 3-d array x[slices][rows][2*columns] is stored in - * a[i*sliceStride + j*rowStride + k], where sliceStride = rows * 2 * - * columns and rowStride = 2 * columns. The physical layout of the input - * data has to be as follows: - * - * *
-     * a[k1*sliceStride + k2*rowStride + 2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1*sliceStride +
-     * k2*rowStride + 2*k3+1] = Im[k1][k2][k3] =
-     * -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3], 0<=k1<slices,
-     * 0<=k2<rows, 0<k3<columns/2, a[k1*sliceStride + k2*rowStride]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1*sliceStride +
-     * k2*rowStride + 1] = Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0],
-     * a[k1*sliceStride + (rows-k2)*rowStride + 1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1*sliceStride + (rows-k2)*rowStride] =
-     * -Im[(slices-k1)%slices][k2][columns/2] = Im[k1][rows-k2][columns/2],
-     * 0<=k1<slices, 0<k2<rows/2, a[k1*sliceStride] = Re[k1][0][0] =
-     * Re[slices-k1][0][0], a[k1*sliceStride + 1] = Im[k1][0][0] =
-     * -Im[slices-k1][0][0], a[k1*sliceStride + (rows/2)*rowStride] =
-     * Re[k1][rows/2][0] = Re[slices-k1][rows/2][0], a[k1*sliceStride +
-     * (rows/2)*rowStride + 1] = Im[k1][rows/2][0] = -Im[slices-k1][rows/2][0],
-     * a[(slices-k1)*sliceStride + 1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[(slices-k1)*sliceStride] =
-     * -Im[k1][0][columns/2] = Im[slices-k1][0][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[(slices-k1)*sliceStride + (rows/2) * rowStride] =
-     * -Im[k1][rows/2][columns/2] = Im[slices-k1][rows/2][columns/2],
-     * 0<k1<slices/2, a[0] = Re[0][0][0], a[1] = Re[0][0][columns/2],
-     * a[(rows/2)*rowStride] = Re[0][rows/2][0], a[(rows/2)*rowStride + 1] =
-     * Re[0][rows/2][columns/2], a[(slices/2)*sliceStride] = Re[slices/2][0][0],
-     * a[(slices/2)*sliceStride + 1] = Re[slices/2][0][columns/2],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride] = Re[slices/2][rows/2][0],
-     * a[(slices/2)*sliceStride + (rows/2)*rowStride + 1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(DoubleLargeArray a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft3d_sub(-1, a); - cdft3db_subth(1, a, scale); - xdft3da_subth1(1, 1, a, scale); - } else { - rdft3d_sub(-1, a); - cdft3db_sub(1, a, scale); - xdft3da_sub1(1, 1, a, scale); - } - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method only works when the sizes of all three dimensions are - * power-of-two numbers. The data is stored in a 3D array. The physical - * layout of the input data has to be as follows: - * - * *
-     * a[k1][k2][2*k3] = Re[k1][k2][k3] =
-     * Re[(slices-k1)%slices][(rows-k2)%rows][columns-k3], a[k1][k2][2*k3+1] =
-     * Im[k1][k2][k3] = -Im[(slices-k1)%slices][(rows-k2)%rows][columns-k3],
-     * 0<=k1<slices, 0<=k2<rows, 0<k3<columns/2, a[k1][k2][0]
-     * = Re[k1][k2][0] = Re[(slices-k1)%slices][rows-k2][0], a[k1][k2][1] =
-     * Im[k1][k2][0] = -Im[(slices-k1)%slices][rows-k2][0], a[k1][rows-k2][1] =
-     * Re[(slices-k1)%slices][k2][columns/2] = Re[k1][rows-k2][columns/2],
-     * a[k1][rows-k2][0] = -Im[(slices-k1)%slices][k2][columns/2] =
-     * Im[k1][rows-k2][columns/2], 0<=k1<slices, 0<k2<rows/2,
-     * a[k1][0][0] = Re[k1][0][0] = Re[slices-k1][0][0], a[k1][0][1] =
-     * Im[k1][0][0] = -Im[slices-k1][0][0], a[k1][rows/2][0] = Re[k1][rows/2][0]
-     * = Re[slices-k1][rows/2][0], a[k1][rows/2][1] = Im[k1][rows/2][0] =
-     * -Im[slices-k1][rows/2][0], a[slices-k1][0][1] = Re[k1][0][columns/2] =
-     * Re[slices-k1][0][columns/2], a[slices-k1][0][0] = -Im[k1][0][columns/2] =
-     * Im[slices-k1][0][columns/2], a[slices-k1][rows/2][1] =
-     * Re[k1][rows/2][columns/2] = Re[slices-k1][rows/2][columns/2],
-     * a[slices-k1][rows/2][0] = -Im[k1][rows/2][columns/2] =
-     * Im[slices-k1][rows/2][columns/2], 0<k1<slices/2, a[0][0][0] =
-     * Re[0][0][0], a[0][0][1] = Re[0][0][columns/2], a[0][rows/2][0] =
-     * Re[0][rows/2][0], a[0][rows/2][1] = Re[0][rows/2][columns/2],
-     * a[slices/2][0][0] = Re[slices/2][0][0], a[slices/2][0][1] =
-     * Re[slices/2][0][columns/2], a[slices/2][rows/2][0] =
-     * Re[slices/2][rows/2][0], a[slices/2][rows/2][1] =
-     * Re[slices/2][rows/2][columns/2]
-     * 
- * - * This method computes only half of the elements of the real transform. The - * other half satisfies the symmetry condition. If you want the full real - * inverse transform, use realInverseFull. - * - * @param a data to transform - * - * @param scale if true then scaling is performed - */ - public void realInverse(double[][][] a, boolean scale) - { - if (isPowerOfTwo == false) { - throw new IllegalArgumentException("slices, rows and columns must be power of two numbers"); - } else { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - rdft3d_sub(-1, a); - cdft3db_subth(1, a, scale); - xdft3da_subth1(1, 1, a, scale); - } else { - rdft3d_sub(-1, a); - cdft3db_sub(1, a, scale); - xdft3da_sub1(1, 1, a, scale); - } - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices*rows*2*columns, with only the first - * slices*rows*columns elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(double[] a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, 1, a, scale); - cdft3db_subth(1, a, scale); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, 1, a, scale); - cdft3db_sub(1, a, scale); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices*rows*2*columns, with only the first - * slices*rows*columns elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(DoubleLargeArray a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, 1, a, scale); - cdft3db_subth(1, a, scale); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, 1, a, scale); - cdft3db_sub(1, a, scale); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /** - * Computes 3D inverse DFT of real data leaving the result in a - * . This method computes full real inverse transform, i.e. you will get the - * same result as from complexInverse called with all imaginary - * part equal 0. Because the result is stored in a, the input - * array must be of size slices by rows by 2*columns, with only the first - * slices by rows by columns elements filled with real data. - * - * @param a data to transform - * @param scale if true then scaling is performed - */ - public void realInverseFull(double[][][] a, boolean scale) - { - if (isPowerOfTwo) { - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads) { - xdft3da_subth2(1, 1, a, scale); - cdft3db_subth(1, a, scale); - rdft3d_sub(1, a); - } else { - xdft3da_sub2(1, 1, a, scale); - cdft3db_sub(1, a, scale); - rdft3d_sub(1, a); - } - fillSymmetric(a); - } else { - mixedRadixRealInverseFull(a, scale); - } - } - - /* -------- child routines -------- */ - private void mixedRadixRealForwardFull(final double[][][] a) - { - double[] temp = new double[2 * rows]; - int ldimn2 = rows / 2 + 1; - final int newn3 = 2 * columns; - final int n2d2; - if (rows % 2 == 0) { - n2d2 = rows / 2; - } else { - n2d2 = (rows + 1) / 2; - } - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (columns >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.realForwardFull(a[s][r]); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - temp[idx2] = a[s][r][idx1]; - temp[idx2 + 1] = a[s][r][idx1 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - a[s][r][idx1] = temp[idx2]; - a[s][r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (int s = firstSlice; s < lastSlice; s++) { - int idx2 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = newn3 - idx1; - a[idx2][idx4][idx3 % newn3] = a[s][r][idx1]; - a[idx2][idx4][(idx3 + 1) % newn3] = -a[s][r][idx1 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.realForwardFull(a[s][r]); - } - } - - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - - for (int r = 0; r < ldimn2; r++) { - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - temp[idx2] = a[s][r][idx1]; - temp[idx2 + 1] = a[s][r][idx1 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - a[s][r][idx1] = temp[idx2]; - a[s][r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - - for (int s = 0; s < slices; s++) { - int idx2 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = newn3 - idx1; - a[idx2][idx4][idx3 % newn3] = a[s][r][idx1]; - a[idx2][idx4][(idx3 + 1) % newn3] = -a[s][r][idx1 + 1]; - } - } - } - - } - } - - private void mixedRadixRealInverseFull(final double[][][] a, final boolean scale) - { - double[] temp = new double[2 * rows]; - int ldimn2 = rows / 2 + 1; - final int newn3 = 2 * columns; - final int n2d2; - if (rows % 2 == 0) { - n2d2 = rows / 2; - } else { - n2d2 = (rows + 1) / 2; - } - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (slices >= nthreads) && (columns >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverseFull(a[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - - for (int s = firstSlice; s < lastSlice; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - - for (int r = firstRow; r < lastRow; r++) { - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - temp[idx2] = a[s][r][idx1]; - temp[idx2 + 1] = a[s][r][idx1 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - a[s][r][idx1] = temp[idx2]; - a[s][r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (int s = firstSlice; s < lastSlice; s++) { - int idx2 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = newn3 - idx1; - a[idx2][idx4][idx3 % newn3] = a[s][r][idx1]; - a[idx2][idx4][(idx3 + 1) % newn3] = -a[s][r][idx1 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverseFull(a[s][r], scale); - } - } - - for (int s = 0; s < slices; s++) { - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - temp[idx4] = a[s][r][idx2]; - temp[idx4 + 1] = a[s][r][idx2 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - a[s][r][idx2] = temp[idx4]; - a[s][r][idx2 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - - for (int r = 0; r < ldimn2; r++) { - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - temp[idx2] = a[s][r][idx1]; - temp[idx2 + 1] = a[s][r][idx1 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - a[s][r][idx1] = temp[idx2]; - a[s][r][idx1 + 1] = temp[idx2 + 1]; - } - } - } - - for (int s = 0; s < slices; s++) { - int idx2 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = newn3 - idx1; - a[idx2][idx4][idx3 % newn3] = a[s][r][idx1]; - a[idx2][idx4][(idx3 + 1) % newn3] = -a[s][r][idx1 + 1]; - } - } - } - - } - } - - private void mixedRadixRealForwardFull(final double[] a) - { - final int twon3 = 2 * columns; - double[] temp = new double[twon3]; - int ldimn2 = rows / 2 + 1; - final int n2d2; - if (rows % 2 == 0) { - n2d2 = rows / 2; - } else { - n2d2 = (rows + 1) / 2; - } - - final int twoSliceStride = 2 * sliceStride; - final int twoRowStride = 2 * rowStride; - int n1d2 = slices / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads) && (columns >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = n1d2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = slices - 1 - l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice - p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[twon3]; - for (int s = firstSlice; s >= lastSlice; s--) { - int idx1 = s * sliceStride; - int idx2 = s * twoSliceStride; - for (int r = rows - 1; r >= 0; r--) { - System.arraycopy(a, idx1 + r * rowStride, temp, 0, columns); - fftColumns.realForwardFull(temp); - System.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - final double[][][] temp2 = new double[n1d2 + 1][rows][twon3]; - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - System.arraycopy(a, idx1 + r * rowStride, temp2[s][r], 0, columns); - fftColumns.realForwardFull(temp2[s][r]); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - System.arraycopy(temp2[s][r], 0, a, idx1 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * twoSliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * twoRowStride + idx2; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * twoRowStride + idx2; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - - for (int r = firstRow; r < lastRow; r++) { - int idx3 = r * twoRowStride; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - temp[idx2] = a[idx4]; - temp[idx2 + 1] = a[idx4 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - a[idx4] = temp[idx2]; - a[idx4 + 1] = temp[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (int s = firstSlice; s < lastSlice; s++) { - int idx2 = (slices - s) % slices; - int idx5 = idx2 * twoSliceStride; - int idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - int idx7 = idx4 * twoRowStride; - int idx8 = r * twoRowStride; - int idx9 = idx5 + idx7; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = twon3 - idx1; - int idx10 = idx6 + idx8 + idx1; - a[idx9 + idx3 % twon3] = a[idx10]; - a[idx9 + (idx3 + 1) % twon3] = -a[idx10 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int s = slices - 1; s >= 0; s--) { - int idx1 = s * sliceStride; - int idx2 = s * twoSliceStride; - for (int r = rows - 1; r >= 0; r--) { - System.arraycopy(a, idx1 + r * rowStride, temp, 0, columns); - fftColumns.realForwardFull(temp); - System.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - - temp = new double[2 * rows]; - - for (int s = 0; s < slices; s++) { - int idx1 = s * twoSliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - int idx3 = idx1 + r * twoRowStride + idx2; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexForward(temp); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - int idx3 = idx1 + r * twoRowStride + idx2; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - - for (int r = 0; r < ldimn2; r++) { - int idx3 = r * twoRowStride; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - temp[idx2] = a[idx4]; - temp[idx2 + 1] = a[idx4 + 1]; - } - fftSlices.complexForward(temp); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - a[idx4] = temp[idx2]; - a[idx4 + 1] = temp[idx2 + 1]; - } - } - } - - for (int s = 0; s < slices; s++) { - int idx2 = (slices - s) % slices; - int idx5 = idx2 * twoSliceStride; - int idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - int idx7 = idx4 * twoRowStride; - int idx8 = r * twoRowStride; - int idx9 = idx5 + idx7; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = twon3 - idx1; - int idx10 = idx6 + idx8 + idx1; - a[idx9 + idx3 % twon3] = a[idx10]; - a[idx9 + (idx3 + 1) % twon3] = -a[idx10 + 1]; - } - } - } - - } - } - - private void mixedRadixRealForwardFull(final DoubleLargeArray a) - { - final long twon3 = 2 * columnsl; - DoubleLargeArray temp = new DoubleLargeArray(twon3, false); - long ldimn2 = rowsl / 2 + 1; - final long n2d2; - if (rowsl % 2 == 0) { - n2d2 = rowsl / 2; - } else { - n2d2 = (rowsl + 1) / 2; - } - - final long twoSliceStride = 2 * sliceStridel; - final long twoRowStride = 2 * rowStridel; - long n1d2 = slicesl / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads) && (columnsl >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = n1d2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = slicesl - 1 - l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice - p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(twon3, false); - for (long s = firstSlice; s >= lastSlice; s--) { - long idx1 = s * sliceStridel; - long idx2 = s * twoSliceStride; - for (long r = rowsl - 1; r >= 0; r--) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp, 0, columnsl); - fftColumns.realForwardFull(temp); - Utilities.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - final DoubleLargeArray temp2 = new DoubleLargeArray((n1d2 + 1) * rowsl * twon3, false); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp2, s * rowsl * twon3 + r * twon3, columnsl); - fftColumns.realForwardFull(temp2, s * rowsl * twon3 + r * twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - Utilities.arraycopy(temp2, s * rowsl * twon3 + r * twon3, a, idx1 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * twoSliceStride; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * twoRowStride + idx2; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * twoRowStride + idx2; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * slicesl, false); - - for (long r = firstRow; r < lastRow; r++) { - long idx3 = r * twoRowStride; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - temp.setDouble(idx2, a.getDouble(idx4)); - temp.setDouble(idx2 + 1, a.getDouble(idx4 + 1)); - } - fftSlices.complexForward(temp); - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - a.setDouble(idx4, temp.getDouble(idx2)); - a.setDouble(idx4 + 1, temp.getDouble(idx2 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (long s = firstSlice; s < lastSlice; s++) { - long idx2 = (slicesl - s) % slicesl; - long idx5 = idx2 * twoSliceStride; - long idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx4 = rowsl - r; - long idx7 = idx4 * twoRowStride; - long idx8 = r * twoRowStride; - long idx9 = idx5 + idx7; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - long idx3 = twon3 - idx1; - long idx10 = idx6 + idx8 + idx1; - a.setDouble(idx9 + idx3 % twon3, a.getDouble(idx10)); - a.setDouble(idx9 + (idx3 + 1) % twon3, -a.getDouble(idx10 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (long s = slicesl - 1; s >= 0; s--) { - long idx1 = s * sliceStridel; - long idx2 = s * twoSliceStride; - for (long r = rowsl - 1; r >= 0; r--) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp, 0, columnsl); - fftColumns.realForwardFull(temp); - Utilities.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - - temp = new DoubleLargeArray(2 * rowsl, false); - - for (long s = 0; s < slicesl; s++) { - long idx1 = s * twoSliceStride; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx4 = 2 * r; - long idx3 = idx1 + r * twoRowStride + idx2; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexForward(temp); - for (long r = 0; r < rowsl; r++) { - long idx4 = 2 * r; - long idx3 = idx1 + r * twoRowStride + idx2; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - - temp = new DoubleLargeArray(2 * slicesl, false); - - for (long r = 0; r < ldimn2; r++) { - long idx3 = r * twoRowStride; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - temp.setDouble(idx2, a.getDouble(idx4)); - temp.setDouble(idx2 + 1, a.getDouble(idx4 + 1)); - } - fftSlices.complexForward(temp); - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - a.setDouble(idx4, temp.getDouble(idx2)); - a.setDouble(idx4 + 1, temp.getDouble(idx2 + 1)); - } - } - } - - for (long s = 0; s < slicesl; s++) { - long idx2 = (slicesl - s) % slicesl; - long idx5 = idx2 * twoSliceStride; - long idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx4 = rowsl - r; - long idx7 = idx4 * twoRowStride; - long idx8 = r * twoRowStride; - long idx9 = idx5 + idx7; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - long idx3 = twon3 - idx1; - long idx10 = idx6 + idx8 + idx1; - a.setDouble(idx9 + idx3 % twon3, a.getDouble(idx10)); - a.setDouble(idx9 + (idx3 + 1) % twon3, -a.getDouble(idx10 + 1)); - } - } - } - - } - } - - private void mixedRadixRealInverseFull(final double[] a, final boolean scale) - { - final int twon3 = 2 * columns; - double[] temp = new double[twon3]; - int ldimn2 = rows / 2 + 1; - final int n2d2; - if (rows % 2 == 0) { - n2d2 = rows / 2; - } else { - n2d2 = (rows + 1) / 2; - } - - final int twoSliceStride = 2 * sliceStride; - final int twoRowStride = 2 * rowStride; - int n1d2 = slices / 2; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads) && (columns >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = n1d2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = slices - 1 - l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice - p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[twon3]; - for (int s = firstSlice; s >= lastSlice; s--) { - int idx1 = s * sliceStride; - int idx2 = s * twoSliceStride; - for (int r = rows - 1; r >= 0; r--) { - System.arraycopy(a, idx1 + r * rowStride, temp, 0, columns); - fftColumns.realInverseFull(temp, scale); - System.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - final double[][][] temp2 = new double[n1d2 + 1][rows][twon3]; - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * sliceStride; - for (int r = 0; r < rows; r++) { - System.arraycopy(a, idx1 + r * rowStride, temp2[s][r], 0, columns); - fftColumns.realInverseFull(temp2[s][r], scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - System.arraycopy(temp2[s][r], 0, a, idx1 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * rows]; - - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = s * twoSliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * twoRowStride + idx2; - int idx4 = 2 * r; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx3 = idx1 + r * twoRowStride + idx2; - int idx4 = 2 * r; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstRow = l * p; - final int lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - double[] temp = new double[2 * slices]; - - for (int r = firstRow; r < lastRow; r++) { - int idx3 = r * twoRowStride; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - temp[idx2] = a[idx4]; - temp[idx2 + 1] = a[idx4 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - a[idx4] = temp[idx2]; - a[idx4 + 1] = temp[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (int s = firstSlice; s < lastSlice; s++) { - int idx2 = (slices - s) % slices; - int idx5 = idx2 * twoSliceStride; - int idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - int idx7 = idx4 * twoRowStride; - int idx8 = r * twoRowStride; - int idx9 = idx5 + idx7; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = twon3 - idx1; - int idx10 = idx6 + idx8 + idx1; - a[idx9 + idx3 % twon3] = a[idx10]; - a[idx9 + (idx3 + 1) % twon3] = -a[idx10 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (int s = slices - 1; s >= 0; s--) { - int idx1 = s * sliceStride; - int idx2 = s * twoSliceStride; - for (int r = rows - 1; r >= 0; r--) { - System.arraycopy(a, idx1 + r * rowStride, temp, 0, columns); - fftColumns.realInverseFull(temp, scale); - System.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - - temp = new double[2 * rows]; - - for (int s = 0; s < slices; s++) { - int idx1 = s * twoSliceStride; - for (int c = 0; c < columns; c++) { - int idx2 = 2 * c; - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - int idx3 = idx1 + r * twoRowStride + idx2; - temp[idx4] = a[idx3]; - temp[idx4 + 1] = a[idx3 + 1]; - } - fftRows.complexInverse(temp, scale); - for (int r = 0; r < rows; r++) { - int idx4 = 2 * r; - int idx3 = idx1 + r * twoRowStride + idx2; - a[idx3] = temp[idx4]; - a[idx3 + 1] = temp[idx4 + 1]; - } - } - } - - temp = new double[2 * slices]; - - for (int r = 0; r < ldimn2; r++) { - int idx3 = r * twoRowStride; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - temp[idx2] = a[idx4]; - temp[idx2 + 1] = a[idx4 + 1]; - } - fftSlices.complexInverse(temp, scale); - for (int s = 0; s < slices; s++) { - int idx2 = 2 * s; - int idx4 = s * twoSliceStride + idx3 + idx1; - a[idx4] = temp[idx2]; - a[idx4 + 1] = temp[idx2 + 1]; - } - } - } - - for (int s = 0; s < slices; s++) { - int idx2 = (slices - s) % slices; - int idx5 = idx2 * twoSliceStride; - int idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx4 = rows - r; - int idx7 = idx4 * twoRowStride; - int idx8 = r * twoRowStride; - int idx9 = idx5 + idx7; - for (int c = 0; c < columns; c++) { - int idx1 = 2 * c; - int idx3 = twon3 - idx1; - int idx10 = idx6 + idx8 + idx1; - a[idx9 + idx3 % twon3] = a[idx10]; - a[idx9 + (idx3 + 1) % twon3] = -a[idx10 + 1]; - } - } - } - - } - } - - private void mixedRadixRealInverseFull(final DoubleLargeArray a, final boolean scale) - { - final long twon3 = 2 * columnsl; - DoubleLargeArray temp = new DoubleLargeArray(twon3, false); - long ldimn2 = rowsl / 2 + 1; - final long n2d2; - if (rowsl % 2 == 0) { - n2d2 = rowsl / 2; - } else { - n2d2 = (rowsl + 1) / 2; - } - - final long twoSliceStride = 2 * sliceStridel; - final long twoRowStride = 2 * rowStridel; - long n1d2 = slicesl / 2; - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (n1d2 >= nthreads) && (columnsl >= nthreads) && (ldimn2 >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = n1d2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = slicesl - 1 - l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice - p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(twon3, false); - for (long s = firstSlice; s >= lastSlice; s--) { - long idx1 = s * sliceStridel; - long idx2 = s * twoSliceStride; - for (long r = rowsl - 1; r >= 0; r--) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp, 0, columnsl); - fftColumns.realInverseFull(temp, scale); - Utilities.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - final DoubleLargeArray temp2 = new DoubleLargeArray((n1d2 + 1) * rowsl * twon3, false); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * sliceStridel; - for (long r = 0; r < rowsl; r++) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp2, s * rowsl * twon3 + r * twon3, columnsl); - fftColumns.realInverseFull(temp2, s * rowsl * twon3 + r * twon3, scale); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? n1d2 + 1 : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - Utilities.arraycopy(temp2, s * rowsl * twon3 + r * twon3, a, idx1 + r * twoRowStride, twon3); - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * rowsl, false); - - for (long s = firstSlice; s < lastSlice; s++) { - long idx1 = s * twoSliceStride; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * twoRowStride + idx2; - long idx4 = 2 * r; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx3 = idx1 + r * twoRowStride + idx2; - long idx4 = 2 * r; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = ldimn2 / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstRow = l * p; - final long lastRow = (l == (nthreads - 1)) ? ldimn2 : firstRow + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - DoubleLargeArray temp = new DoubleLargeArray(2 * slicesl, false); - - for (long r = firstRow; r < lastRow; r++) { - long idx3 = r * twoRowStride; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - temp.setDouble(idx2, a.getDouble(idx4)); - temp.setDouble(idx2 + 1, a.getDouble(idx4 + 1)); - } - fftSlices.complexInverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - a.setDouble(idx4, temp.getDouble(idx2)); - a.setDouble(idx4 + 1, temp.getDouble(idx2 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - - for (long s = firstSlice; s < lastSlice; s++) { - long idx2 = (slicesl - s) % slicesl; - long idx5 = idx2 * twoSliceStride; - long idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx4 = rowsl - r; - long idx7 = idx4 * twoRowStride; - long idx8 = r * twoRowStride; - long idx9 = idx5 + idx7; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - long idx3 = twon3 - idx1; - long idx10 = idx6 + idx8 + idx1; - a.setDouble(idx9 + idx3 % twon3, a.getDouble(idx10)); - a.setDouble(idx9 + (idx3 + 1) % twon3, -a.getDouble(idx10 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - for (long s = slicesl - 1; s >= 0; s--) { - long idx1 = s * sliceStridel; - long idx2 = s * twoSliceStride; - for (long r = rowsl - 1; r >= 0; r--) { - Utilities.arraycopy(a, idx1 + r * rowStridel, temp, 0, columnsl); - fftColumns.realInverseFull(temp, scale); - Utilities.arraycopy(temp, 0, a, idx2 + r * twoRowStride, twon3); - } - } - - temp = new DoubleLargeArray(2 * rowsl, false); - - for (long s = 0; s < slicesl; s++) { - long idx1 = s * twoSliceStride; - for (long c = 0; c < columnsl; c++) { - long idx2 = 2 * c; - for (long r = 0; r < rowsl; r++) { - long idx4 = 2 * r; - long idx3 = idx1 + r * twoRowStride + idx2; - temp.setDouble(idx4, a.getDouble(idx3)); - temp.setDouble(idx4 + 1, a.getDouble(idx3 + 1)); - } - fftRows.complexInverse(temp, scale); - for (long r = 0; r < rowsl; r++) { - long idx4 = 2 * r; - long idx3 = idx1 + r * twoRowStride + idx2; - a.setDouble(idx3, temp.getDouble(idx4)); - a.setDouble(idx3 + 1, temp.getDouble(idx4 + 1)); - } - } - } - - temp = new DoubleLargeArray(2 * slicesl, false); - - for (long r = 0; r < ldimn2; r++) { - long idx3 = r * twoRowStride; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - temp.setDouble(idx2, a.getDouble(idx4)); - temp.setDouble(idx2 + 1, a.getDouble(idx4 + 1)); - } - fftSlices.complexInverse(temp, scale); - for (long s = 0; s < slicesl; s++) { - long idx2 = 2 * s; - long idx4 = s * twoSliceStride + idx3 + idx1; - a.setDouble(idx4, temp.getDouble(idx2)); - a.setDouble(idx4 + 1, temp.getDouble(idx2 + 1)); - } - } - } - - for (long s = 0; s < slicesl; s++) { - long idx2 = (slicesl - s) % slicesl; - long idx5 = idx2 * twoSliceStride; - long idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx4 = rowsl - r; - long idx7 = idx4 * twoRowStride; - long idx8 = r * twoRowStride; - long idx9 = idx5 + idx7; - for (long c = 0; c < columnsl; c++) { - long idx1 = 2 * c; - long idx3 = twon3 - idx1; - long idx10 = idx6 + idx8 + idx1; - a.setDouble(idx9 + idx3 % twon3, a.getDouble(idx10)); - a.setDouble(idx9 + (idx3 + 1) % twon3, -a.getDouble(idx10 + 1)); - } - } - } - - } - } - - private void xdft3da_sub1(int icr, int isgn, double[] a, boolean scale) - { - int idx0, idx1, idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx0 + r * rowStride); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, idx0 + r * rowStride); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStride, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - if (icr != 0) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a, idx0 + r * rowStride, scale); - } - } - } - } - } - - private void xdft3da_sub1(long icr, int isgn, DoubleLargeArray a, boolean scale) - { - long idx0, idx1, idx2, idx3, idx4, idx5; - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1l; - } else if (columnsl < 4) { - nt >>= 2l; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx0 + r * rowStridel); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, idx0 + r * rowStridel); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStridel, scale); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - if (icr != 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse(a, idx0 + r * rowStridel, scale); - } - } - } - } - } - - private void xdft3da_sub2(int icr, int isgn, double[] a, boolean scale) - { - int idx0, idx1, idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx0 + r * rowStride); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, idx0 + r * rowStride); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStride, scale); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, idx0 + r * rowStride, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - } - - private void xdft3da_sub2(long icr, int isgn, DoubleLargeArray a, boolean scale) - { - long idx0, idx1, idx2, idx3, idx4, idx5; - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx0 + r * rowStridel); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, idx0 + r * rowStridel); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } else { - for (long s = 0; s < slicesl; s++) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStridel, scale); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, idx0 + r * rowStridel, scale); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - } - - private void xdft3da_sub1(int icr, int isgn, double[][][] a, boolean scale) - { - int idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[s][r], 0); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - if (icr != 0) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a[s][r], scale); - } - } - } - } - } - - private void xdft3da_sub2(int icr, int isgn, double[][][] a, boolean scale) - { - int idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - for (int s = 0; s < slices; s++) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[s][r]); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } else { - for (int s = 0; s < slices; s++) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[s][r], 0, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } - } - - private void cdft3db_sub(int isgn, double[] a, boolean scale) - { - int idx0, idx1, idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - fftSlices.complexForward(t, 4 * slices); - fftSlices.complexForward(t, 6 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftSlices.complexForward(t, 0); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } else { - if (columns > 4) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - fftSlices.complexInverse(t, 4 * slices, scale); - fftSlices.complexInverse(t, 6 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftSlices.complexInverse(t, 0, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - } - - private void cdft3db_sub(int isgn, DoubleLargeArray a, boolean scale) - { - long idx0, idx1, idx2, idx3, idx4, idx5; - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - DoubleLargeArray t = new DoubleLargeArray(nt, false); - if (isgn == -1) { - if (columnsl > 4) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 8) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slicesl); - fftSlices.complexForward(t, 4 * slicesl); - fftSlices.complexForward(t, 6 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftSlices.complexForward(t, 0); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } else { - if (columnsl > 4) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 8) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slicesl, scale); - fftSlices.complexInverse(t, 4 * slicesl, scale); - fftSlices.complexInverse(t, 6 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftSlices.complexInverse(t, 0, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - } - - private void cdft3db_sub(int isgn, double[][][] a, boolean scale) - { - int idx2, idx3, idx4, idx5; - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - double[] t = new double[nt]; - if (isgn == -1) { - if (columns > 4) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - fftSlices.complexForward(t, 4 * slices); - fftSlices.complexForward(t, 6 * slices); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftSlices.complexForward(t, 0); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } else { - if (columns > 4) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - fftSlices.complexInverse(t, 4 * slices, scale); - fftSlices.complexInverse(t, 6 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftSlices.complexInverse(t, 0, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } - } - - private void xdft3da_subth1(final int icr, final int isgn, final double[] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), slices); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx0, idx1, idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx0 + r * rowStride); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, idx0 + r * rowStride); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStride, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - if (icr != 0) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a, idx0 + r * rowStride, scale); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft3da_subth1(final long icr, final int isgn, final DoubleLargeArray a, final boolean scale) - { - int i; - final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), slicesl); - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - long idx0, idx1, idx2, idx3, idx4, idx5; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx0 + r * rowStridel); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, idx0 + r * rowStridel); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStridel, scale); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - if (icr != 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse(a, idx0 + r * rowStridel, scale); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft3da_subth2(final int icr, final int isgn, final double[] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), slices); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx0, idx1, idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a, idx0 + r * rowStride); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a, idx0 + r * rowStride); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - - } - } else { - for (int s = n0; s < slices; s += nthreads) { - idx0 = s * sliceStride; - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStride, scale); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a, idx0 + r * rowStride, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride + c; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx1 = idx0 + r * rowStride; - idx2 = 2 * r; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft3da_subth2(final long icr, final int isgn, final DoubleLargeArray a, final boolean scale) - { - int i; - final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), slicesl); - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - long idx0, idx1, idx2, idx3, idx4, idx5; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexForward(a, idx0 + r * rowStridel); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realForward(a, idx0 + r * rowStridel); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - fftRows.complexForward(t, 4 * rowsl); - fftRows.complexForward(t, 6 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rowsl); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexForward(t, 0); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - - } - } else { - for (long s = n0; s < slicesl; s += nthreads) { - idx0 = s * sliceStridel; - if (icr == 0) { - for (long r = 0; r < rowsl; r++) { - fftColumns.complexInverse(a, idx0 + r * rowStridel, scale); - } - } else { - for (long r = 0; r < rowsl; r++) { - fftColumns.realInverse2(a, idx0 + r * rowStridel, scale); - } - } - if (columnsl > 4) { - for (long c = 0; c < columnsl; c += 8) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - fftRows.complexInverse(t, 4 * rowsl, scale); - fftRows.complexInverse(t, 6 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel + c; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - idx4 = idx3 + 2 * rowsl; - idx5 = idx4 + 2 * rowsl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } else if (columnsl == 4) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rowsl, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - idx3 = 2 * rowsl + 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } else if (columnsl == 2) { - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftRows.complexInverse(t, 0, scale); - for (long r = 0; r < rowsl; r++) { - idx1 = idx0 + r * rowStridel; - idx2 = 2 * r; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft3da_subth1(final int icr, final int isgn, final double[][][] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), slices); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[s][r], 0); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - - } - } else { - for (int s = n0; s < slices; s += nthreads) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - if (icr != 0) { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse(a[s][r], scale); - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void xdft3da_subth2(final int icr, final int isgn, final double[][][] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), slices); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - int idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - for (int s = n0; s < slices; s += nthreads) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexForward(a[s][r]); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realForward(a[s][r]); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - fftRows.complexForward(t, 4 * rows); - fftRows.complexForward(t, 6 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexForward(t, 0); - fftRows.complexForward(t, 2 * rows); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexForward(t, 0); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - - } - } else { - for (int s = n0; s < slices; s += nthreads) { - if (icr == 0) { - for (int r = 0; r < rows; r++) { - fftColumns.complexInverse(a[s][r], scale); - } - } else { - for (int r = 0; r < rows; r++) { - fftColumns.realInverse2(a[s][r], 0, scale); - } - } - if (columns > 4) { - for (int c = 0; c < columns; c += 8) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - fftRows.complexInverse(t, 4 * rows, scale); - fftRows.complexInverse(t, 6 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - idx4 = idx3 + 2 * rows; - idx5 = idx4 + 2 * rows; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } else if (columns == 4) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftRows.complexInverse(t, 0, scale); - fftRows.complexInverse(t, 2 * rows, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - idx3 = 2 * rows + 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } else if (columns == 2) { - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftRows.complexInverse(t, 0, scale); - for (int r = 0; r < rows; r++) { - idx2 = 2 * r; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft3db_subth(final int isgn, final double[] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), rows); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - - public void run() - { - int idx0, idx1, idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 4) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - fftSlices.complexForward(t, 4 * slices); - fftSlices.complexForward(t, 6 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftSlices.complexForward(t, 0); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } else { - if (columns > 4) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - t[idx4] = a[idx1 + 4]; - t[idx4 + 1] = a[idx1 + 5]; - t[idx5] = a[idx1 + 6]; - t[idx5 + 1] = a[idx1 + 7]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - fftSlices.complexInverse(t, 4 * slices, scale); - fftSlices.complexInverse(t, 6 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - a[idx1 + 4] = t[idx4]; - a[idx1 + 5] = t[idx4 + 1]; - a[idx1 + 6] = t[idx5]; - a[idx1 + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - t[idx3] = a[idx1 + 2]; - t[idx3 + 1] = a[idx1 + 3]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - a[idx1 + 2] = t[idx3]; - a[idx1 + 3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - idx0 = r * rowStride; - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - t[idx2] = a[idx1]; - t[idx2 + 1] = a[idx1 + 1]; - } - fftSlices.complexInverse(t, 0, scale); - for (int s = 0; s < slices; s++) { - idx1 = s * sliceStride + idx0; - idx2 = 2 * s; - a[idx1] = t[idx2]; - a[idx1 + 1] = t[idx2 + 1]; - } - } - } - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft3db_subth(final int isgn, final DoubleLargeArray a, final boolean scale) - { - int i; - final int nthreads = (int) Math.min(ConcurrencyUtils.getNumberOfThreads(), rowsl); - long nt = slicesl; - if (nt < rowsl) { - nt = rowsl; - } - nt *= 8; - if (columnsl == 4) { - nt >>= 1; - } else if (columnsl < 4) { - nt >>= 2; - } - final long ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final long n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - - public void run() - { - long idx0, idx1, idx2, idx3, idx4, idx5; - DoubleLargeArray t = new DoubleLargeArray(ntf, false); - if (isgn == -1) { - if (columnsl > 4) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 8) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slicesl); - fftSlices.complexForward(t, 4 * slicesl); - fftSlices.complexForward(t, 6 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } - } else if (columnsl == 4) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slicesl); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftSlices.complexForward(t, 0); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } else { - if (columnsl > 4) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long c = 0; c < columnsl; c += 8) { - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - t.setDouble(idx4, a.getDouble(idx1 + 4)); - t.setDouble(idx4 + 1, a.getDouble(idx1 + 5)); - t.setDouble(idx5, a.getDouble(idx1 + 6)); - t.setDouble(idx5 + 1, a.getDouble(idx1 + 7)); - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slicesl, scale); - fftSlices.complexInverse(t, 4 * slicesl, scale); - fftSlices.complexInverse(t, 6 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0 + c; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - idx4 = idx3 + 2 * slicesl; - idx5 = idx4 + 2 * slicesl; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - a.setDouble(idx1 + 4, t.getDouble(idx4)); - a.setDouble(idx1 + 5, t.getDouble(idx4 + 1)); - a.setDouble(idx1 + 6, t.getDouble(idx5)); - a.setDouble(idx1 + 7, t.getDouble(idx5 + 1)); - } - } - } - } else if (columnsl == 4) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - t.setDouble(idx3, a.getDouble(idx1 + 2)); - t.setDouble(idx3 + 1, a.getDouble(idx1 + 3)); - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slicesl, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - idx3 = 2 * slicesl + 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - a.setDouble(idx1 + 2, t.getDouble(idx3)); - a.setDouble(idx1 + 3, t.getDouble(idx3 + 1)); - } - } - } else if (columnsl == 2) { - for (long r = n0; r < rowsl; r += nthreads) { - idx0 = r * rowStridel; - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - t.setDouble(idx2, a.getDouble(idx1)); - t.setDouble(idx2 + 1, a.getDouble(idx1 + 1)); - } - fftSlices.complexInverse(t, 0, scale); - for (long s = 0; s < slicesl; s++) { - idx1 = s * sliceStridel + idx0; - idx2 = 2 * s; - a.setDouble(idx1, t.getDouble(idx2)); - a.setDouble(idx1 + 1, t.getDouble(idx2 + 1)); - } - } - } - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void cdft3db_subth(final int isgn, final double[][][] a, final boolean scale) - { - int i; - final int nthreads = Math.min(ConcurrencyUtils.getNumberOfThreads(), rows); - int nt = slices; - if (nt < rows) { - nt = rows; - } - nt *= 8; - if (columns == 4) { - nt >>= 1; - } else if (columns < 4) { - nt >>= 2; - } - final int ntf = nt; - Future[] futures = new Future[nthreads]; - for (i = 0; i < nthreads; i++) { - final int n0 = i; - futures[i] = ConcurrencyUtils.submit(new Runnable() - { - - public void run() - { - int idx2, idx3, idx4, idx5; - double[] t = new double[ntf]; - if (isgn == -1) { - if (columns > 4) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - fftSlices.complexForward(t, 4 * slices); - fftSlices.complexForward(t, 6 * slices); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftSlices.complexForward(t, 0); - fftSlices.complexForward(t, 2 * slices); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftSlices.complexForward(t, 0); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } else { - if (columns > 4) { - for (int r = n0; r < rows; r += nthreads) { - for (int c = 0; c < columns; c += 8) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - t[idx2] = a[s][r][c]; - t[idx2 + 1] = a[s][r][c + 1]; - t[idx3] = a[s][r][c + 2]; - t[idx3 + 1] = a[s][r][c + 3]; - t[idx4] = a[s][r][c + 4]; - t[idx4 + 1] = a[s][r][c + 5]; - t[idx5] = a[s][r][c + 6]; - t[idx5 + 1] = a[s][r][c + 7]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - fftSlices.complexInverse(t, 4 * slices, scale); - fftSlices.complexInverse(t, 6 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - idx4 = idx3 + 2 * slices; - idx5 = idx4 + 2 * slices; - a[s][r][c] = t[idx2]; - a[s][r][c + 1] = t[idx2 + 1]; - a[s][r][c + 2] = t[idx3]; - a[s][r][c + 3] = t[idx3 + 1]; - a[s][r][c + 4] = t[idx4]; - a[s][r][c + 5] = t[idx4 + 1]; - a[s][r][c + 6] = t[idx5]; - a[s][r][c + 7] = t[idx5 + 1]; - } - } - } - } else if (columns == 4) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - t[idx3] = a[s][r][2]; - t[idx3 + 1] = a[s][r][3]; - } - fftSlices.complexInverse(t, 0, scale); - fftSlices.complexInverse(t, 2 * slices, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - idx3 = 2 * slices + 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - a[s][r][2] = t[idx3]; - a[s][r][3] = t[idx3 + 1]; - } - } - } else if (columns == 2) { - for (int r = n0; r < rows; r += nthreads) { - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - t[idx2] = a[s][r][0]; - t[idx2 + 1] = a[s][r][1]; - } - fftSlices.complexInverse(t, 0, scale); - for (int s = 0; s < slices; s++) { - idx2 = 2 * s; - a[s][r][0] = t[idx2]; - a[s][r][1] = t[idx2 + 1]; - } - } - } - } - - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } - - private void rdft3d_sub(int isgn, double[] a) - { - int n1h, n2h, i, j, k, l, idx1, idx2, idx3, idx4; - double xi; - - n1h = slices >> 1; - n2h = rows >> 1; - if (isgn < 0) { - for (i = 1; i < n1h; i++) { - j = slices - i; - idx1 = i * sliceStride; - idx2 = j * sliceStride; - idx3 = i * sliceStride + n2h * rowStride; - idx4 = j * sliceStride + n2h * rowStride; - xi = a[idx1] - a[idx2]; - a[idx1] += a[idx2]; - a[idx2] = xi; - xi = a[idx2 + 1] - a[idx1 + 1]; - a[idx1 + 1] += a[idx2 + 1]; - a[idx2 + 1] = xi; - xi = a[idx3] - a[idx4]; - a[idx3] += a[idx4]; - a[idx4] = xi; - xi = a[idx4 + 1] - a[idx3 + 1]; - a[idx3 + 1] += a[idx4 + 1]; - a[idx4 + 1] = xi; - for (k = 1; k < n2h; k++) { - l = rows - k; - idx1 = i * sliceStride + k * rowStride; - idx2 = j * sliceStride + l * rowStride; - xi = a[idx1] - a[idx2]; - a[idx1] += a[idx2]; - a[idx2] = xi; - xi = a[idx2 + 1] - a[idx1 + 1]; - a[idx1 + 1] += a[idx2 + 1]; - a[idx2 + 1] = xi; - idx3 = j * sliceStride + k * rowStride; - idx4 = i * sliceStride + l * rowStride; - xi = a[idx3] - a[idx4]; - a[idx3] += a[idx4]; - a[idx4] = xi; - xi = a[idx4 + 1] - a[idx3 + 1]; - a[idx3 + 1] += a[idx4 + 1]; - a[idx4 + 1] = xi; - } - } - for (k = 1; k < n2h; k++) { - l = rows - k; - idx1 = k * rowStride; - idx2 = l * rowStride; - xi = a[idx1] - a[idx2]; - a[idx1] += a[idx2]; - a[idx2] = xi; - xi = a[idx2 + 1] - a[idx1 + 1]; - a[idx1 + 1] += a[idx2 + 1]; - a[idx2 + 1] = xi; - idx3 = n1h * sliceStride + k * rowStride; - idx4 = n1h * sliceStride + l * rowStride; - xi = a[idx3] - a[idx4]; - a[idx3] += a[idx4]; - a[idx4] = xi; - xi = a[idx4 + 1] - a[idx3 + 1]; - a[idx3 + 1] += a[idx4 + 1]; - a[idx4 + 1] = xi; - } - } else { - for (i = 1; i < n1h; i++) { - j = slices - i; - idx1 = j * sliceStride; - idx2 = i * sliceStride; - a[idx1] = 0.5f * (a[idx2] - a[idx1]); - a[idx2] -= a[idx1]; - a[idx1 + 1] = 0.5f * (a[idx2 + 1] + a[idx1 + 1]); - a[idx2 + 1] -= a[idx1 + 1]; - idx3 = j * sliceStride + n2h * rowStride; - idx4 = i * sliceStride + n2h * rowStride; - a[idx3] = 0.5f * (a[idx4] - a[idx3]); - a[idx4] -= a[idx3]; - a[idx3 + 1] = 0.5f * (a[idx4 + 1] + a[idx3 + 1]); - a[idx4 + 1] -= a[idx3 + 1]; - for (k = 1; k < n2h; k++) { - l = rows - k; - idx1 = j * sliceStride + l * rowStride; - idx2 = i * sliceStride + k * rowStride; - a[idx1] = 0.5f * (a[idx2] - a[idx1]); - a[idx2] -= a[idx1]; - a[idx1 + 1] = 0.5f * (a[idx2 + 1] + a[idx1 + 1]); - a[idx2 + 1] -= a[idx1 + 1]; - idx3 = i * sliceStride + l * rowStride; - idx4 = j * sliceStride + k * rowStride; - a[idx3] = 0.5f * (a[idx4] - a[idx3]); - a[idx4] -= a[idx3]; - a[idx3 + 1] = 0.5f * (a[idx4 + 1] + a[idx3 + 1]); - a[idx4 + 1] -= a[idx3 + 1]; - } - } - for (k = 1; k < n2h; k++) { - l = rows - k; - idx1 = l * rowStride; - idx2 = k * rowStride; - a[idx1] = 0.5f * (a[idx2] - a[idx1]); - a[idx2] -= a[idx1]; - a[idx1 + 1] = 0.5f * (a[idx2 + 1] + a[idx1 + 1]); - a[idx2 + 1] -= a[idx1 + 1]; - idx3 = n1h * sliceStride + l * rowStride; - idx4 = n1h * sliceStride + k * rowStride; - a[idx3] = 0.5f * (a[idx4] - a[idx3]); - a[idx4] -= a[idx3]; - a[idx3 + 1] = 0.5f * (a[idx4 + 1] + a[idx3 + 1]); - a[idx4 + 1] -= a[idx3 + 1]; - } - } - } - - private void rdft3d_sub(int isgn, DoubleLargeArray a) - { - long n1h, n2h, i, j, k, l, idx1, idx2, idx3, idx4; - double xi; - - n1h = slicesl >> 1l; - n2h = rowsl >> 1l; - if (isgn < 0) { - for (i = 1; i < n1h; i++) { - j = slicesl - i; - idx1 = i * sliceStridel; - idx2 = j * sliceStridel; - idx3 = i * sliceStridel + n2h * rowStridel; - idx4 = j * sliceStridel + n2h * rowStridel; - xi = a.getDouble(idx1) - a.getDouble(idx2); - a.setDouble(idx1, a.getDouble(idx1) + a.getDouble(idx2)); - a.setDouble(idx2, xi); - xi = a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, xi); - xi = a.getDouble(idx3) - a.getDouble(idx4); - a.setDouble(idx3, a.getDouble(idx3) + a.getDouble(idx4)); - a.setDouble(idx4, xi); - xi = a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1); - a.setDouble(idx3 + 1, a.getDouble(idx3 + 1) + a.getDouble(idx4 + 1)); - a.setDouble(idx4 + 1, xi); - for (k = 1; k < n2h; k++) { - l = rowsl - k; - idx1 = i * sliceStridel + k * rowStridel; - idx2 = j * sliceStridel + l * rowStridel; - xi = a.getDouble(idx1) - a.getDouble(idx2); - a.setDouble(idx1, a.getDouble(idx1) + a.getDouble(idx2)); - a.setDouble(idx2, xi); - xi = a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, xi); - idx3 = j * sliceStridel + k * rowStridel; - idx4 = i * sliceStridel + l * rowStridel; - xi = a.getDouble(idx3) - a.getDouble(idx4); - a.setDouble(idx3, a.getDouble(idx3) + a.getDouble(idx4)); - a.setDouble(idx4, xi); - xi = a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1); - a.setDouble(idx3 + 1, a.getDouble(idx3 + 1) + a.getDouble(idx4 + 1)); - a.setDouble(idx4 + 1, xi); - } - } - for (k = 1; k < n2h; k++) { - l = rowsl - k; - idx1 = k * rowStridel; - idx2 = l * rowStridel; - xi = a.getDouble(idx1) - a.getDouble(idx2); - a.setDouble(idx1, a.getDouble(idx1) + a.getDouble(idx2)); - a.setDouble(idx2, xi); - xi = a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1); - a.setDouble(idx1 + 1, a.getDouble(idx1 + 1) + a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, xi); - idx3 = n1h * sliceStridel + k * rowStridel; - idx4 = n1h * sliceStridel + l * rowStridel; - xi = a.getDouble(idx3) - a.getDouble(idx4); - a.setDouble(idx3, a.getDouble(idx3) + a.getDouble(idx4)); - a.setDouble(idx4, xi); - xi = a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1); - a.setDouble(idx3 + 1, a.getDouble(idx3 + 1) + a.getDouble(idx4 + 1)); - a.setDouble(idx4 + 1, xi); - } - } else { - for (i = 1; i < n1h; i++) { - j = slicesl - i; - idx1 = j * sliceStridel; - idx2 = i * sliceStridel; - a.setDouble(idx1, 0.5f * (a.getDouble(idx2) - a.getDouble(idx1))); - a.setDouble(idx2, a.getDouble(idx2) - a.getDouble(idx1)); - a.setDouble(idx1 + 1, 0.5f * (a.getDouble(idx2 + 1) + a.getDouble(idx1 + 1))); - a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1)); - idx3 = j * sliceStridel + n2h * rowStridel; - idx4 = i * sliceStridel + n2h * rowStridel; - a.setDouble(idx3, 0.5f * (a.getDouble(idx4) - a.getDouble(idx3))); - a.setDouble(idx4, a.getDouble(idx4) - a.getDouble(idx3)); - a.setDouble(idx3 + 1, 0.5f * (a.getDouble(idx4 + 1) + a.getDouble(idx3 + 1))); - a.setDouble(idx4 + 1, a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1)); - for (k = 1; k < n2h; k++) { - l = rowsl - k; - idx1 = j * sliceStridel + l * rowStridel; - idx2 = i * sliceStridel + k * rowStridel; - a.setDouble(idx1, 0.5f * (a.getDouble(idx2) - a.getDouble(idx1))); - a.setDouble(idx2, a.getDouble(idx2) - a.getDouble(idx1)); - a.setDouble(idx1 + 1, 0.5f * (a.getDouble(idx2 + 1) + a.getDouble(idx1 + 1))); - a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1)); - idx3 = i * sliceStridel + l * rowStridel; - idx4 = j * sliceStridel + k * rowStridel; - a.setDouble(idx3, 0.5f * (a.getDouble(idx4) - a.getDouble(idx3))); - a.setDouble(idx4, a.getDouble(idx4) - a.getDouble(idx3)); - a.setDouble(idx3 + 1, 0.5f * (a.getDouble(idx4 + 1) + a.getDouble(idx3 + 1))); - a.setDouble(idx4 + 1, a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1)); - } - } - for (k = 1; k < n2h; k++) { - l = rowsl - k; - idx1 = l * rowStridel; - idx2 = k * rowStridel; - a.setDouble(idx1, 0.5f * (a.getDouble(idx2) - a.getDouble(idx1))); - a.setDouble(idx2, a.getDouble(idx2) - a.getDouble(idx1)); - a.setDouble(idx1 + 1, 0.5f * (a.getDouble(idx2 + 1) + a.getDouble(idx1 + 1))); - a.setDouble(idx2 + 1, a.getDouble(idx2 + 1) - a.getDouble(idx1 + 1)); - idx3 = n1h * sliceStridel + l * rowStridel; - idx4 = n1h * sliceStridel + k * rowStridel; - a.setDouble(idx3, 0.5f * (a.getDouble(idx4) - a.getDouble(idx3))); - a.setDouble(idx4, a.getDouble(idx4) - a.getDouble(idx3)); - a.setDouble(idx3 + 1, 0.5f * (a.getDouble(idx4 + 1) + a.getDouble(idx3 + 1))); - a.setDouble(idx4 + 1, a.getDouble(idx4 + 1) - a.getDouble(idx3 + 1)); - } - } - } - - private void rdft3d_sub(int isgn, double[][][] a) - { - int n1h, n2h, i, j, k, l; - double xi; - - n1h = slices >> 1; - n2h = rows >> 1; - if (isgn < 0) { - for (i = 1; i < n1h; i++) { - j = slices - i; - xi = a[i][0][0] - a[j][0][0]; - a[i][0][0] += a[j][0][0]; - a[j][0][0] = xi; - xi = a[j][0][1] - a[i][0][1]; - a[i][0][1] += a[j][0][1]; - a[j][0][1] = xi; - xi = a[i][n2h][0] - a[j][n2h][0]; - a[i][n2h][0] += a[j][n2h][0]; - a[j][n2h][0] = xi; - xi = a[j][n2h][1] - a[i][n2h][1]; - a[i][n2h][1] += a[j][n2h][1]; - a[j][n2h][1] = xi; - for (k = 1; k < n2h; k++) { - l = rows - k; - xi = a[i][k][0] - a[j][l][0]; - a[i][k][0] += a[j][l][0]; - a[j][l][0] = xi; - xi = a[j][l][1] - a[i][k][1]; - a[i][k][1] += a[j][l][1]; - a[j][l][1] = xi; - xi = a[j][k][0] - a[i][l][0]; - a[j][k][0] += a[i][l][0]; - a[i][l][0] = xi; - xi = a[i][l][1] - a[j][k][1]; - a[j][k][1] += a[i][l][1]; - a[i][l][1] = xi; - } - } - for (k = 1; k < n2h; k++) { - l = rows - k; - xi = a[0][k][0] - a[0][l][0]; - a[0][k][0] += a[0][l][0]; - a[0][l][0] = xi; - xi = a[0][l][1] - a[0][k][1]; - a[0][k][1] += a[0][l][1]; - a[0][l][1] = xi; - xi = a[n1h][k][0] - a[n1h][l][0]; - a[n1h][k][0] += a[n1h][l][0]; - a[n1h][l][0] = xi; - xi = a[n1h][l][1] - a[n1h][k][1]; - a[n1h][k][1] += a[n1h][l][1]; - a[n1h][l][1] = xi; - } - } else { - for (i = 1; i < n1h; i++) { - j = slices - i; - a[j][0][0] = 0.5f * (a[i][0][0] - a[j][0][0]); - a[i][0][0] -= a[j][0][0]; - a[j][0][1] = 0.5f * (a[i][0][1] + a[j][0][1]); - a[i][0][1] -= a[j][0][1]; - a[j][n2h][0] = 0.5f * (a[i][n2h][0] - a[j][n2h][0]); - a[i][n2h][0] -= a[j][n2h][0]; - a[j][n2h][1] = 0.5f * (a[i][n2h][1] + a[j][n2h][1]); - a[i][n2h][1] -= a[j][n2h][1]; - for (k = 1; k < n2h; k++) { - l = rows - k; - a[j][l][0] = 0.5f * (a[i][k][0] - a[j][l][0]); - a[i][k][0] -= a[j][l][0]; - a[j][l][1] = 0.5f * (a[i][k][1] + a[j][l][1]); - a[i][k][1] -= a[j][l][1]; - a[i][l][0] = 0.5f * (a[j][k][0] - a[i][l][0]); - a[j][k][0] -= a[i][l][0]; - a[i][l][1] = 0.5f * (a[j][k][1] + a[i][l][1]); - a[j][k][1] -= a[i][l][1]; - } - } - for (k = 1; k < n2h; k++) { - l = rows - k; - a[0][l][0] = 0.5f * (a[0][k][0] - a[0][l][0]); - a[0][k][0] -= a[0][l][0]; - a[0][l][1] = 0.5f * (a[0][k][1] + a[0][l][1]); - a[0][k][1] -= a[0][l][1]; - a[n1h][l][0] = 0.5f * (a[n1h][k][0] - a[n1h][l][0]); - a[n1h][k][0] -= a[n1h][l][0]; - a[n1h][l][1] = 0.5f * (a[n1h][k][1] + a[n1h][l][1]); - a[n1h][k][1] -= a[n1h][l][1]; - } - } - } - - private void fillSymmetric(final double[][][] a) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (slices >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = (slices - s) % slices; - for (int r = 0; r < rows; r++) { - int idx2 = (rows - r) % rows; - for (int c = 1; c < columns; c += 2) { - int idx3 = twon3 - c; - a[idx1][idx2][idx3] = -a[s][r][c + 2]; - a[idx1][idx2][idx3 - 1] = a[s][r][c + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - // --------------------------------------------- - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][r][columns] = a[s][idx2][1]; - a[s][idx2][columns] = a[s][idx2][1]; - a[idx1][r][columns + 1] = -a[s][idx2][0]; - a[s][idx2][columns + 1] = a[s][idx2][0]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][idx2][0] = a[s][r][0]; - a[idx1][idx2][1] = -a[s][r][1]; - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - } else { - - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 0; r < rows; r++) { - int idx2 = (rows - r) % rows; - for (int c = 1; c < columns; c += 2) { - int idx3 = twon3 - c; - a[idx1][idx2][idx3] = -a[s][r][c + 2]; - a[idx1][idx2][idx3 - 1] = a[s][r][c + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][r][columns] = a[s][idx2][1]; - a[s][idx2][columns] = a[s][idx2][1]; - a[idx1][r][columns + 1] = -a[s][idx2][0]; - a[s][idx2][columns + 1] = a[s][idx2][0]; - } - } - - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][idx2][0] = a[s][r][0]; - a[idx1][idx2][1] = -a[s][r][1]; - } - } - } - - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - int idx1 = slices - s; - a[s][0][columns] = a[idx1][0][1]; - a[idx1][0][columns] = a[idx1][0][1]; - a[s][0][columns + 1] = -a[idx1][0][0]; - a[idx1][0][columns + 1] = a[idx1][0][0]; - a[s][n2d2][columns] = a[idx1][n2d2][1]; - a[idx1][n2d2][columns] = a[idx1][n2d2][1]; - a[s][n2d2][columns + 1] = -a[idx1][n2d2][0]; - a[idx1][n2d2][columns + 1] = a[idx1][n2d2][0]; - a[idx1][0][0] = a[s][0][0]; - a[idx1][0][1] = -a[s][0][1]; - a[idx1][n2d2][0] = a[s][n2d2][0]; - a[idx1][n2d2][1] = -a[s][n2d2][1]; - - } - // ---------------------------------------- - - a[0][0][columns] = a[0][0][1]; - a[0][0][1] = 0; - a[0][n2d2][columns] = a[0][n2d2][1]; - a[0][n2d2][1] = 0; - a[n1d2][0][columns] = a[n1d2][0][1]; - a[n1d2][0][1] = 0; - a[n1d2][n2d2][columns] = a[n1d2][n2d2][1]; - a[n1d2][n2d2][1] = 0; - a[n1d2][0][columns + 1] = 0; - a[n1d2][n2d2][columns + 1] = 0; - } - - private void fillSymmetric(final double[] a) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - - final int twoSliceStride = rows * twon3; - final int twoRowStride = twon3; - - int idx1, idx2, idx3, idx4, idx5, idx6; - - for (int s = (slices - 1); s >= 1; s--) { - idx3 = s * sliceStride; - idx4 = 2 * idx3; - for (int r = 0; r < rows; r++) { - idx5 = r * rowStride; - idx6 = 2 * idx5; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - } - - for (int r = 1; r < rows; r++) { - idx3 = (rows - r) * rowStride; - idx4 = (rows - r) * twoRowStride; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (slices >= nthreads)) { - Future[] futures = new Future[nthreads]; - int p = slices / nthreads; - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx3 = ((slices - s) % slices) * twoSliceStride; - int idx5 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - int idx4 = ((rows - r) % rows) * twoRowStride; - int idx6 = r * twoRowStride; - for (int c = 1; c < columns; c += 2) { - int idx1 = idx3 + idx4 + twon3 - c; - int idx2 = idx5 + idx6 + c; - a[idx1] = -a[idx2 + 2]; - a[idx1 - 1] = a[idx2 + 1]; - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - // --------------------------------------------- - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx5 = ((slices - s) % slices) * twoSliceStride; - int idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx4 = idx6 + (rows - r) * twoRowStride; - int idx1 = idx5 + r * twoRowStride + columns; - int idx2 = idx4 + columns; - int idx3 = idx4 + 1; - a[idx1] = a[idx3]; - a[idx2] = a[idx3]; - a[idx1 + 1] = -a[idx4]; - a[idx2 + 1] = a[idx4]; - - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - for (int l = 0; l < nthreads; l++) { - final int firstSlice = l * p; - final int lastSlice = (l == (nthreads - 1)) ? slices : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (int s = firstSlice; s < lastSlice; s++) { - int idx3 = ((slices - s) % slices) * twoSliceStride; - int idx4 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - int idx1 = idx3 + (rows - r) * twoRowStride; - int idx2 = idx4 + r * twoRowStride; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - // ----------------------------------------------- - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx5 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - idx4 = ((rows - r) % rows) * twoRowStride; - idx6 = r * twoRowStride; - for (int c = 1; c < columns; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a[idx1] = -a[idx2 + 2]; - a[idx1 - 1] = a[idx2 + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - idx5 = ((slices - s) % slices) * twoSliceStride; - idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx4 = idx6 + (rows - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columns; - idx2 = idx4 + columns; - idx3 = idx4 + 1; - a[idx1] = a[idx3]; - a[idx2] = a[idx3]; - a[idx1 + 1] = -a[idx4]; - a[idx2 + 1] = a[idx4]; - - } - } - - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx4 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx1 = idx3 + (rows - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - - } - } - } - - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slices - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a[idx1 + columns] = a[idx2 + 1]; - a[idx2 + columns] = a[idx2 + 1]; - a[idx1 + columns + 1] = -a[idx2]; - a[idx2 + columns + 1] = a[idx2]; - a[idx4 + columns] = a[idx5 + 1]; - a[idx5 + columns] = a[idx5 + 1]; - a[idx4 + columns + 1] = -a[idx5]; - a[idx5 + columns + 1] = a[idx5]; - a[idx2] = a[idx1]; - a[idx2 + 1] = -a[idx1 + 1]; - a[idx5] = a[idx4]; - a[idx5 + 1] = -a[idx4 + 1]; - - } - - // ---------------------------------------- - a[columns] = a[1]; - a[1] = 0; - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a[idx1 + columns] = a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx2 + columns] = a[idx2 + 1]; - a[idx2 + 1] = 0; - a[idx3 + columns] = a[idx3 + 1]; - a[idx3 + 1] = 0; - a[idx2 + columns + 1] = 0; - a[idx3 + columns + 1] = 0; - } - - private void fillSymmetric(final DoubleLargeArray a) - { - final long twon3 = 2 * columnsl; - final long n2d2 = rowsl / 2; - long n1d2 = slicesl / 2; - - final long twoSliceStride = rowsl * twon3; - final long twoRowStride = twon3; - - long idx1, idx2, idx3, idx4, idx5, idx6; - - for (long s = (slicesl - 1); s >= 1; s--) { - idx3 = s * sliceStridel; - idx4 = 2 * idx3; - for (long r = 0; r < rowsl; r++) { - idx5 = r * rowStridel; - idx6 = 2 * idx5; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - idx1++; - idx2++; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - } - } - } - - for (long r = 1; r < rowsl; r++) { - idx3 = (rowsl - r) * rowStridel; - idx4 = (rowsl - r) * twoRowStride; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - idx1++; - idx2++; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - } - } - - int nthreads = ConcurrencyUtils.getNumberOfThreads(); - if ((nthreads > 1) && useThreads && (slicesl >= nthreads)) { - Future[] futures = new Future[nthreads]; - long p = slicesl / nthreads; - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - long idx5 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - long idx4 = ((rowsl - r) % rowsl) * twoRowStride; - long idx6 = r * twoRowStride; - for (long c = 1; c < columnsl; c += 2) { - long idx1 = idx3 + idx4 + twon3 - c; - long idx2 = idx5 + idx6 + c; - a.setDouble(idx1, -a.getDouble(idx2 + 2)); - a.setDouble(idx1 - 1, a.getDouble(idx2 + 1)); - } - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - - // --------------------------------------------- - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx5 = ((slicesl - s) % slicesl) * twoSliceStride; - long idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx4 = idx6 + (rowsl - r) * twoRowStride; - long idx1 = idx5 + r * twoRowStride + columnsl; - long idx2 = idx4 + columnsl; - long idx3 = idx4 + 1; - a.setDouble(idx1, a.getDouble(idx3)); - a.setDouble(idx2, a.getDouble(idx3)); - a.setDouble(idx1 + 1, -a.getDouble(idx4)); - a.setDouble(idx2 + 1, a.getDouble(idx4)); - - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - for (int l = 0; l < nthreads; l++) { - final long firstSlice = l * p; - final long lastSlice = (l == (nthreads - 1)) ? slicesl : firstSlice + p; - futures[l] = ConcurrencyUtils.submit(new Runnable() - { - public void run() - { - for (long s = firstSlice; s < lastSlice; s++) { - long idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - long idx4 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - long idx1 = idx3 + (rowsl - r) * twoRowStride; - long idx2 = idx4 + r * twoRowStride; - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - - } - } - } - }); - } - ConcurrencyUtils.waitForCompletion(futures); - } else { - - // ----------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx5 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - idx4 = ((rowsl - r) % rowsl) * twoRowStride; - idx6 = r * twoRowStride; - for (long c = 1; c < columnsl; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a.setDouble(idx1, -a.getDouble(idx2 + 2)); - a.setDouble(idx1 - 1, a.getDouble(idx2 + 1)); - } - } - } - - // --------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx5 = ((slicesl - s) % slicesl) * twoSliceStride; - idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx4 = idx6 + (rowsl - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columnsl; - idx2 = idx4 + columnsl; - idx3 = idx4 + 1; - a.setDouble(idx1, a.getDouble(idx3)); - a.setDouble(idx2, a.getDouble(idx3)); - a.setDouble(idx1 + 1, -a.getDouble(idx4)); - a.setDouble(idx2 + 1, a.getDouble(idx4)); - - } - } - - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx4 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx1 = idx3 + (rowsl - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - - } - } - } - - // ---------------------------------------------------------- - for (long s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slicesl - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a.setDouble(idx1 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx2 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx1 + columnsl + 1, -a.getDouble(idx2)); - a.setDouble(idx2 + columnsl + 1, a.getDouble(idx2)); - a.setDouble(idx4 + columnsl, a.getDouble(idx5 + 1)); - a.setDouble(idx5 + columnsl, a.getDouble(idx5 + 1)); - a.setDouble(idx4 + columnsl + 1, -a.getDouble(idx5)); - a.setDouble(idx5 + columnsl + 1, a.getDouble(idx5)); - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx2 + 1, -a.getDouble(idx1 + 1)); - a.setDouble(idx5, a.getDouble(idx4)); - a.setDouble(idx5 + 1, -a.getDouble(idx4 + 1)); - - } - - // ---------------------------------------- - a.setDouble(columnsl, a.getDouble(1)); - a.setDouble(1, 0); - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a.setDouble(idx1 + columnsl, a.getDouble(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx2 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, 0); - a.setDouble(idx3 + columnsl, a.getDouble(idx3 + 1)); - a.setDouble(idx3 + 1, 0); - a.setDouble(idx2 + columnsl + 1, 0); - a.setDouble(idx3 + columnsl + 1, 0); - } -} diff --git a/src/main/java/org/jtransforms/fft/RealFFTUtils_2D.java b/src/main/java/org/jtransforms/fft/RealFFTUtils_2D.java deleted file mode 100644 index 61a5aa9..0000000 --- a/src/main/java/org/jtransforms/fft/RealFFTUtils_2D.java +++ /dev/null @@ -1,682 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -// @formatter:off -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * - * This is a set of utility methods for R/W access to data resulting from a call - * to the Fourier transform of real data. Memory optimized methods, - * namely - * - * are implemented to handle this case specifically. However, packing of the - * data in the data array is somewhat obscure. This class provides methods for - * direct access to the data, without the burden of all necessary tests. - *

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

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

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

- * - *
- * DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
- * double[][] data = new double[rows][2 * columns];
- * ...
- * fft.realForwardFull(data);
- * data[r1][c1] = val1;
- * val2 = data[r2][c2];
- * 
- * is equivalent to - *
- *   DoubleFFT_2D fft = new DoubleFFT_2D(rows, columns);
- *   RealFFTUtils_2D unpacker = new RealFFTUtils_2D(rows, columns);
- *   double[][] data = new double[rows][columns];
- *   ...
- *   fft.realForward(data);
- *   unpacker.pack(val1, r1, c1, data);
- *   val2 = unpacker.unpack(r2, c2, data, 0);
- * 
- * Even (resp. odd) values of c correspond to the real (resp. - * imaginary) part of the Fourier mode. - * - * @author Sébastien Brisard - */ -// @formatter:on -public class RealFFTUtils_2D -{ - - /** - * The constant int value of 1. - */ - private static final int ONE = 1; - - /** - * The constant int value of 2. - */ - private static final int TWO = 2; - - /** - * The constant int value of 0. - */ - private static final int ZERO = 0; - - /** - * The constant int value of 1. - */ - private static final long ONEL = 1; - - /** - * The constant int value of 2. - */ - private static final long TWOL = 2; - - /** - * The constant int value of 0. - */ - private static final long ZEROL = 0; - - /** - * The size of the data in the second direction. - */ - private final int columns; - - /** - * The size of the data in the first direction. - */ - private final int rows; - - /** - * The size of the data in the second direction. - */ - private final long columnsl; - - /** - * The size of the data in the first direction. - */ - private final long rowsl; - - /** - * Creates a new instance of this class. The size of the underlying - * {@link DoubleFFT_2D} or {@link FloatFFT_2D} must be specified. - * - * @param rows - * number of rows - * @param columns - * number of columns - */ - public RealFFTUtils_2D(final long rows, final long columns) - { - this.columns = (int) columns; - this.rows = (int) rows; - this.columnsl = columns; - this.rowsl = rows; - - } - - /** - * - * Returns the 1d index of the specified 2d Fourier mode. In other words, if - * packed contains the transformed data following a call to - * {@link DoubleFFT_2D#realForward(double[])} or - * {@link FloatFFT_2D#realForward(float[])}, then the returned value - * index gives access to the [r][c] Fourier mode - * - * - * @param r - * the row index - * @param c - * the column index - * - * @return the value of index - */ - public int getIndex(final int r, final int c) - { - final int cmod2 = c & ONE; - final int rmul2 = r << ONE; - if (r != ZERO) { - if (c <= ONE) { - if (rmul2 == rows) { - if (cmod2 == ONE) { - return Integer.MIN_VALUE; - } - return ((rows * columns) >> ONE); - } else if (rmul2 < rows) { - return columns * r + cmod2; - } else { - if (cmod2 == ZERO) { - return columns * (rows - r); - } else { - return -(columns * (rows - r) + ONE); - } - } - } else if ((c == columns) || (c == columns + ONE)) { - if (rmul2 == rows) { - if (cmod2 == ONE) { - return Integer.MIN_VALUE; - } - return ((rows * columns) >> ONE) + ONE; - } else if (rmul2 < rows) { - if (cmod2 == ZERO) { - return columns * (rows - r) + ONE; - } else { - return -(columns * (rows - r)); - } - } else { - return columns * r + ONE - cmod2; - } - } else if (c < columns) { - return columns * r + c; - } else { - if (cmod2 == ZERO) { - return columns * (rows + TWO - r) - c; - } else { - return -(columns * (rows + TWO - r) - c + TWO); - } - } - } else { - if ((c == ONE) || (c == columns + ONE)) { - return Integer.MIN_VALUE; - } else if (c == columns) { - return ONE; - } else if (c < columns) { - return c; - } else { - if (cmod2 == ZERO) { - return (columns << ONE) - c; - } else { - return -((columns << ONE) - c + TWO); - } - } - } - } - - /** - * - * Returns the 1d index of the specified 2d Fourier mode. In other words, if - * packed contains the transformed data following a call to - * {@link DoubleFFT_2D#realForward(DoubleLargeArray)} or - * {@link FloatFFT_2D#realForward(FloatLargeArray)}, then the returned value - * index gives access to the [r][c] Fourier mode - * - * - * @param r - * the row index - * @param c - * the column index - * - * @return the value of index - */ - public long getIndex(final long r, final long c) - { - final long cmod2 = c & ONEL; - final long rmul2 = r << ONEL; - if (r != ZERO) { - if (c <= ONEL) { - if (rmul2 == rowsl) { - if (cmod2 == ONEL) { - return Long.MIN_VALUE; - } - return ((rowsl * columnsl) >> ONEL); - } else if (rmul2 < rowsl) { - return columnsl * r + cmod2; - } else { - if (cmod2 == ZEROL) { - return columnsl * (rowsl - r); - } else { - return -(columnsl * (rowsl - r) + ONEL); - } - } - } else if ((c == columnsl) || (c == columnsl + ONEL)) { - if (rmul2 == rowsl) { - if (cmod2 == ONEL) { - return Long.MIN_VALUE; - } - return ((rowsl * columnsl) >> ONEL) + ONEL; - } else if (rmul2 < rowsl) { - if (cmod2 == ZEROL) { - return columnsl * (rowsl - r) + ONEL; - } else { - return -(columnsl * (rowsl - r)); - } - } else { - return columnsl * r + ONEL - cmod2; - } - } else if (c < columnsl) { - return columnsl * r + c; - } else { - if (cmod2 == ZEROL) { - return columnsl * (rowsl + TWOL - r) - c; - } else { - return -(columnsl * (rowsl + TWOL - r) - c + TWOL); - } - } - } else { - if ((c == ONEL) || (c == columnsl + ONEL)) { - return Long.MIN_VALUE; - } else if (c == columnsl) { - return ONEL; - } else if (c < columnsl) { - return c; - } else { - if (cmod2 == ZEROL) { - return (columnsl << ONEL) - c; - } else { - return -((columnsl << ONEL) - c + TWOL); - } - } - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_2D#realForward(double[])}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final double val, final int r, final int c, - final double[] packed, final int pos) - { - final int index = getIndex(r, c); - if (index >= 0) { - packed[pos + index] = val; - } else if (index > Integer.MIN_VALUE) { - packed[pos - index] = -val; - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_2D#realForward(DoubleLargeArray)}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final double val, final long r, final long c, - final DoubleLargeArray packed, final long pos) - { - final long index = getIndex(r, c); - if (index >= 0) { - packed.setDouble(pos + index, val); - } else if (index > Long.MIN_VALUE) { - packed.setDouble(pos - index, -val); - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_2D#realForward(double[][])}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - */ - public void pack(final double val, final int r, final int c, - final double[][] packed) - { - final int index = getIndex(r, c); - if (index >= 0) { - packed[index / columns][index % columns] = val; - } else if (index > Integer.MIN_VALUE) { - packed[(-index) / columns][(-index) % columns] = -val; - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_2D#realForward(float[])}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final float val, final int r, final int c, - final float[] packed, final int pos) - { - final int index = getIndex(r, c); - if (index >= 0) { - packed[pos + index] = val; - } else if (index > Integer.MIN_VALUE) { - packed[pos - index] = -val; - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_2D#realForward(FloatLargeArray)}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final float val, final long r, final long c, - final FloatLargeArray packed, final long pos) - { - final long index = getIndex(r, c); - if (index >= 0) { - packed.setFloat(pos + index, val); - } else if (index > Long.MIN_VALUE) { - packed.setFloat(pos - index, -val); - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_2D#realForward(float[][])}. - * - * @param val - * the new value of the [r][c] Fourier mode - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - */ - public void pack(final float val, final int r, final int c, - final float[][] packed) - { - final int index = getIndex(r, c); - if (index >= 0) { - packed[index / columns][index % columns] = val; - } else if (index > Integer.MIN_VALUE) { - packed[(-index) / columns][(-index) % columns] = -val; - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link DoubleFFT_2D#realForward(double[])}. - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [r][c] Fourier mode - */ - public double unpack(final int r, final int c, final double[] packed, - final int pos) - { - final int index = getIndex(r, c); - if (index >= 0) { - return packed[pos + index]; - } else if (index > Integer.MIN_VALUE) { - return -packed[pos - index]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link DoubleFFT_2D#realForward(DoubleLargeArray)}. - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [r][c] Fourier mode - */ - public double unpack(final long r, final long c, final DoubleLargeArray packed, - final long pos) - { - final long index = getIndex(r, c); - if (index >= 0) { - return packed.getDouble(pos + index); - } else if (index > Long.MIN_VALUE) { - return -packed.getDouble(pos - index); - } else { - return ZEROL; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link DoubleFFT_2D#realForward(double[][])} - * . - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * - * @return the value of the [r][c] Fourier mode - */ - public double unpack(final int r, final int c, final double[][] packed) - { - final int index = getIndex(r, c); - if (index >= 0) { - return packed[index / columns][index % columns]; - } else if (index > Integer.MIN_VALUE) { - return -packed[(-index) / columns][(-index) % columns]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_2D#realForward(float[])} - * . - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [r][c] Fourier mode - */ - public float unpack(final int r, final int c, final float[] packed, - final int pos) - { - final int index = getIndex(r, c); - if (index >= 0) { - return packed[pos + index]; - } else if (index > Integer.MIN_VALUE) { - return -packed[pos - index]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_2D#realForward(FloatLargeArray)} - * . - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [r][c] Fourier mode - */ - public float unpack(final long r, final long c, final FloatLargeArray packed, - final long pos) - { - final long index = getIndex(r, c); - if (index >= 0) { - return packed.getFloat(pos + index); - } else if (index > Long.MIN_VALUE) { - return -packed.getFloat(pos - index); - } else { - return ZEROL; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_2D#realForward(float[][])} . - * - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * - * @return the value of the [r][c] Fourier mode - */ - public float unpack(final int r, final int c, final float[][] packed) - { - final int index = getIndex(r, c); - if (index >= 0) { - return packed[index / columns][index % columns]; - } else if (index > Integer.MIN_VALUE) { - return -packed[(-index) / columns][(-index) % columns]; - } else { - return ZERO; - } - } -} diff --git a/src/main/java/org/jtransforms/fft/RealFFTUtils_3D.java b/src/main/java/org/jtransforms/fft/RealFFTUtils_3D.java deleted file mode 100644 index cd672dc..0000000 --- a/src/main/java/org/jtransforms/fft/RealFFTUtils_3D.java +++ /dev/null @@ -1,805 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -// @formatter:off -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * - * This is a set of utility methods for R/W access to data resulting from a call - * to the Fourier transform of real data. Memory optimized methods, - * namely - * - * are implemented to handle this case specifically. However, packing of the - * data in the data array is somewhat obscure. This class provides methods for - * direct access to the data, without the burden of all necessary tests. - *

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

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

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

- * - *
- * DoubleFFT_3D fft = new DoubleFFT_3D(slices, rows, columns);
- * double[][][] data = new double[slices][rows][2 * columns];
- * ...
- * fft.realForwardFull(data);
- * data[s1][r1][c1] = val1;
- * val2 = data[s2][r2][c2];
- * 
- * is equivalent to - *
- *   DoubleFFT_3D fft = new DoubleFFT_3D(slices, rows, columns);
- *   RealFFTUtils_3D unpacker = new RealFFTUtils_3D(slices, rows, columns);
- *   double[][][] data = new double[slices][rows][columns];
- *   ...
- *   fft.realForward(data);
- *   unpacker.pack(val1, s1, r1, c1, data);
- *   val2 = unpacker.unpack(s2, r2, c2, data, 0);
- * 
- * Even (resp. odd) values of c correspond to the real (resp. - * imaginary) part of the Fourier mode. - * - * @author Sébastien Brisard - */ -// @formatter:on -public class RealFFTUtils_3D -{ - - /** - * The constant int value of 1. - */ - private static final int ONE = 1; - - /** - * The constant int value of 2. - */ - private static final int TWO = 2; - - /** - * The constant int value of 0. - */ - private static final int ZERO = 0; - - /** - * The constant int value of 1. - */ - private static final long ONEL = 1; - - /** - * The constant int value of 2. - */ - private static final long TWOL = 2; - - /** - * The constant int value of 0. - */ - private static final long ZEROL = 0; - - /** - * The size of the data in the third direction. - */ - private final int columns; - - /** - * The size of the data in the third direction. - */ - private final long columnsl; - - /** - * The size of the data in the second direction. - */ - private final int rows; - - /** - * The size of the data in the second direction. - */ - private final long rowsl; - - /** - * The constant value of 2 * columns. - */ - private final int rowStride; - - /** - * The constant value of 2 * columns. - */ - private final long rowStridel; - - /** - * The size of the data in the first direction. - */ - private final int slices; - - /** - * The size of the data in the first direction. - */ - private final long slicesl; - - /** - * The constant value of 2 * rows * columns. - */ - private final int sliceStride; - - /** - * The constant value of 2 * rows * columns. - */ - private final long sliceStridel; - - /** - * Creates a new instance of this class. The size of the underlying - * {@link DoubleFFT_3D} or {@link FloatFFT_3D} must be specified. - * - * @param slices - * number of slices - * @param rows - * number of rows - * @param columns - * number of columns - */ - public RealFFTUtils_3D(final long slices, final long rows, final long columns) - { - this.slices = (int) slices; - this.rows = (int) rows; - this.columns = (int) columns; - this.rowStride = (int) columns; - this.sliceStride = (int) rows * (int) this.rowStride; - this.slicesl = slices; - this.rowsl = rows; - this.columnsl = columns; - this.rowStridel = columns; - this.sliceStridel = rows * this.rowStridel; - } - - /** - * - * Returns the 1d index of the specified 3d Fourier mode. In other words, if - * packed contains the transformed data following a call to - * {@link DoubleFFT_3D#realForwardFull(double[])} or - * {@link FloatFFT_3D#realForward(float[])}, then the returned value - * index gives access to the [s][r][c] Fourier - * mode - * - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * - * @return the value of index - */ - public int getIndex(final int s, final int r, final int c) - { - final int cmod2 = c & ONE; - final int rmul2 = r << ONE; - final int smul2 = s << ONE; - final int ss = s == ZERO ? ZERO : slices - s; - final int rr = r == ZERO ? ZERO : rows - r; - if (c <= ONE) { - if (r == ZERO) { - if (s == ZERO) { - return c == ZERO ? ZERO : Integer.MIN_VALUE; - } else if (smul2 < slices) { - return s * sliceStride + c; - } else if (smul2 > slices) { - final int index = ss * sliceStride; - return cmod2 == ZERO ? index : -(index + ONE); - } else { - return cmod2 == ZERO ? s * sliceStride : Integer.MIN_VALUE; - } - } else if (rmul2 < rows) { - return s * sliceStride + r * rowStride + c; - } else if (rmul2 > rows) { - final int index = ss * sliceStride + rr * rowStride; - return cmod2 == ZERO ? index : -(index + ONE); - } else { - if (s == ZERO) { - return cmod2 == ZERO ? r * rowStride : Integer.MIN_VALUE; - } else if (smul2 < slices) { - return s * sliceStride + r * rowStride + c; - } else if (smul2 > slices) { - final int index = ss * sliceStride + r * rowStride; - return cmod2 == ZERO ? index : -(index + ONE); - } else { - final int index = s * sliceStride + r * rowStride; - return cmod2 == ZERO ? index : Integer.MIN_VALUE; - } - } - } else if (c < columns) { - return s * sliceStride + r * rowStride + c; - } else if (c > columns + ONE) { - final int cc = (columns << ONE) - c; - final int index = ss * sliceStride + rr * rowStride + cc; - return cmod2 == ZERO ? index : -(index + TWO); - } else { - if (r == ZERO) { - if (s == ZERO) { - return cmod2 == ZERO ? ONE : Integer.MIN_VALUE; - } else if (smul2 < slices) { - final int index = ss * sliceStride; - return cmod2 == ZERO ? index + ONE : -index; - } else if (smul2 > slices) { - final int index = s * sliceStride; - return cmod2 == ZERO ? index + ONE : index; - } else { - final int index = s * sliceStride; - return cmod2 == ZERO ? index + ONE : Integer.MIN_VALUE; - } - } else if (rmul2 < rows) { - final int index = ss * sliceStride + rr * rowStride; - return cmod2 == ZERO ? index + ONE : -index; - } else if (rmul2 > rows) { - final int index = s * sliceStride + r * rowStride; - return cmod2 == ZERO ? index + ONE : index; - } else { - if (s == ZERO) { - final int index = r * rowStride + ONE; - return cmod2 == ZERO ? index : Integer.MIN_VALUE; - } else if (smul2 < slices) { - final int index = ss * sliceStride + r * rowStride; - return cmod2 == ZERO ? index + ONE : -index; - } else if (smul2 > slices) { - final int index = s * sliceStride + r * rowStride; - return cmod2 == ZERO ? index + ONE : index; - } else { - final int index = s * sliceStride + r * rowStride; - return cmod2 == ZERO ? index + ONE : Integer.MIN_VALUE; - } - } - } - } - - /** - * - * Returns the 1d index of the specified 3d Fourier mode. In other words, if - * packed contains the transformed data following a call to - * {@link DoubleFFT_3D#realForwardFull(double[])} or - * {@link FloatFFT_3D#realForward(float[])}, then the returned value - * index gives access to the [s][r][c] Fourier - * mode - * - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * - * @return the value of index - */ - public long getIndex(final long s, final long r, final long c) - { - final long cmod2 = c & ONEL; - final long rmul2 = r << ONEL; - final long smul2 = s << ONEL; - final long ss = s == ZEROL ? ZEROL : slicesl - s; - final long rr = r == ZEROL ? ZEROL : rowsl - r; - if (c <= ONEL) { - if (r == ZEROL) { - if (s == ZEROL) { - return c == ZEROL ? ZEROL : Long.MIN_VALUE; - } else if (smul2 < slicesl) { - return s * sliceStridel + c; - } else if (smul2 > slicesl) { - final long index = ss * sliceStridel; - return cmod2 == ZEROL ? index : -(index + ONEL); - } else { - return cmod2 == ZEROL ? s * sliceStridel : Long.MIN_VALUE; - } - } else if (rmul2 < rowsl) { - return s * sliceStridel + r * rowStridel + c; - } else if (rmul2 > rowsl) { - final long index = ss * sliceStridel + rr * rowStridel; - return cmod2 == ZEROL ? index : -(index + ONEL); - } else { - if (s == ZEROL) { - return cmod2 == ZEROL ? r * rowStridel : Long.MIN_VALUE; - } else if (smul2 < slicesl) { - return s * sliceStridel + r * rowStridel + c; - } else if (smul2 > slicesl) { - final long index = ss * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index : -(index + ONEL); - } else { - final long index = s * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index : Long.MIN_VALUE; - } - } - } else if (c < columnsl) { - return s * sliceStridel + r * rowStridel + c; - } else if (c > columnsl + ONEL) { - final long cc = (columnsl << ONEL) - c; - final long index = ss * sliceStridel + rr * rowStridel + cc; - return cmod2 == ZEROL ? index : -(index + TWO); - } else { - if (r == ZEROL) { - if (s == ZEROL) { - return cmod2 == ZEROL ? ONEL : Long.MIN_VALUE; - } else if (smul2 < slicesl) { - final long index = ss * sliceStridel; - return cmod2 == ZEROL ? index + ONEL : -index; - } else if (smul2 > slicesl) { - final long index = s * sliceStridel; - return cmod2 == ZEROL ? index + ONEL : index; - } else { - final long index = s * sliceStridel; - return cmod2 == ZEROL ? index + ONEL : Long.MIN_VALUE; - } - } else if (rmul2 < rowsl) { - final long index = ss * sliceStridel + rr * rowStridel; - return cmod2 == ZEROL ? index + ONEL : -index; - } else if (rmul2 > rowsl) { - final long index = s * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index + ONEL : index; - } else { - if (s == ZEROL) { - final long index = r * rowStridel + ONEL; - return cmod2 == ZEROL ? index : Long.MIN_VALUE; - } else if (smul2 < slicesl) { - final long index = ss * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index + ONEL : -index; - } else if (smul2 > slicesl) { - final long index = s * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index + ONEL : index; - } else { - final long index = s * sliceStridel + r * rowStridel; - return cmod2 == ZEROL ? index + ONEL : Long.MIN_VALUE; - } - } - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_3D#realForward(double[])}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final double val, final int s, final int r, final int c, - final double[] packed, final int pos) - { - final int i = getIndex(s, r, c); - if (i >= 0) { - packed[pos + i] = val; - } else if (i > Integer.MIN_VALUE) { - packed[pos - i] = -val; - } else { - throw new IllegalArgumentException(String.format( - "[%d][%d][%d] component cannot be modified (always zero)", - s, r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_3D#realForward(DoubleLargeArray)}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final double val, final long s, final long r, final long c, - final DoubleLargeArray packed, final long pos) - { - final long i = getIndex(s, r, c); - if (i >= 0) { - packed.setDouble(pos + i, val); - } else if (i > Long.MIN_VALUE) { - packed.setDouble(pos - i, -val); - } else { - throw new IllegalArgumentException(String.format( - "[%d][%d][%d] component cannot be modified (always zero)", - s, r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link DoubleFFT_3D#realForward(double[][][])}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - */ - public void pack(final double val, final int s, final int r, final int c, - final double[][][] packed) - { - final int i = getIndex(s, r, c); - final int ii = Math.abs(i); - final int ss = ii / sliceStride; - final int remainder = ii % sliceStride; - final int rr = remainder / rowStride; - final int cc = remainder % rowStride; - if (i >= 0) { - packed[ss][rr][cc] = val; - } else if (i > Integer.MIN_VALUE) { - packed[ss][rr][cc] = -val; - } else { - throw new IllegalArgumentException( - String.format( - "[%d][%d] component cannot be modified (always zero)", - r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_3D#realForward(float[])}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final float val, final int s, final int r, final int c, - final float[] packed, final int pos) - { - final int i = getIndex(s, r, c); - if (i >= 0) { - packed[pos + i] = val; - } else if (i > Integer.MIN_VALUE) { - packed[pos - i] = -val; - } else { - throw new IllegalArgumentException(String.format( - "[%d][%d][%d] component cannot be modified (always zero)", - s, r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_3D#realForward(FloatLargeArray)}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - */ - public void pack(final float val, final long s, final long r, final long c, - final FloatLargeArray packed, final long pos) - { - final long i = getIndex(s, r, c); - if (i >= 0) { - packed.setFloat(pos + i, val); - } else if (i > Long.MIN_VALUE) { - packed.setFloat(pos - i, -val); - } else { - throw new IllegalArgumentException(String.format( - "[%d][%d][%d] component cannot be modified (always zero)", - s, r, c)); - } - } - - /** - * Sets the specified Fourier mode of the transformed data. The data array - * results from a call to {@link FloatFFT_3D#realForward(float[][][])}. - * - * @param val - * the new value of the [s][r][c] Fourier mode - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - */ - public void pack(final float val, final int s, final int r, final int c, - final float[][][] packed) - { - final int i = getIndex(s, r, c); - final int ii = Math.abs(i); - final int ss = ii / sliceStride; - final int remainder = ii % sliceStride; - final int rr = remainder / rowStride; - final int cc = remainder % rowStride; - if (i >= 0) { - packed[ss][rr][cc] = val; - } else if (i > Integer.MIN_VALUE) { - packed[ss][rr][cc] = -val; - } else { - throw new IllegalArgumentException(String.format( - "[%d][%d][%d] component cannot be modified (always zero)", - s, r, c)); - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link DoubleFFT_3D#realForward(double[])}. - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [s][r][c] Fourier mode - */ - public double unpack(final int s, final int r, final int c, - final double[] packed, final int pos) - { - final int i = getIndex(s, r, c); - if (i >= 0) { - return packed[pos + i]; - } else if (i > Integer.MIN_VALUE) { - return -packed[pos - i]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link DoubleFFT_3D#realForward(DoubleLargeArray)}. - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [s][r][c] Fourier mode - */ - public double unpack(final long s, final long r, final long c, - final DoubleLargeArray packed, final long pos) - { - final long i = getIndex(s, r, c); - if (i >= 0) { - return packed.getDouble(pos + i); - } else if (i > Long.MIN_VALUE) { - return -packed.getDouble(pos - i); - } else { - return ZEROL; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to - * {@link DoubleFFT_3D#realForward(double[][][])} . - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * - * @return the value of the [s][r][c] Fourier mode - */ - public double unpack(final int s, final int r, final int c, - final double[][][] packed) - { - final int i = getIndex(s, r, c); - final int ii = Math.abs(i); - final int ss = ii / sliceStride; - final int remainder = ii % sliceStride; - final int rr = remainder / rowStride; - final int cc = remainder % rowStride; - if (i >= 0) { - return packed[ss][rr][cc]; - } else if (i > Integer.MIN_VALUE) { - return -packed[ss][rr][cc]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_3D#realForward(float[])} . - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [s][r][c] Fourier mode - */ - public float unpack(final int s, final int r, final int c, - final float[] packed, final int pos) - { - final int i = getIndex(s, r, c); - if (i >= 0) { - return packed[pos + i]; - } else if (i > Integer.MIN_VALUE) { - return -packed[pos - i]; - } else { - return ZERO; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_3D#realForward(FloatLargeArray)} . - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * @param pos - * index of the first element in array packed - * - * @return the value of the [s][r][c] Fourier mode - */ - public float unpack(final long s, final long r, final long c, - final FloatLargeArray packed, final long pos) - { - final long i = getIndex(s, r, c); - if (i >= 0) { - return packed.getFloat(pos + i); - } else if (i > Long.MIN_VALUE) { - return -packed.getFloat(pos - i); - } else { - return ZEROL; - } - } - - /** - * Returns the specified Fourier mode of the transformed data. The data - * array results from a call to {@link FloatFFT_3D#realForward(float[][][])} - * . - * - * @param s - * the slice index - * @param r - * the row index - * @param c - * the column index - * @param packed - * the transformed data - * - * @return the value of the [s][r][c] Fourier mode - */ - public float unpack(final int s, final int r, final int c, - final float[][][] packed) - { - final int i = getIndex(s, r, c); - final int ii = Math.abs(i); - final int ss = ii / sliceStride; - final int remainder = ii % sliceStride; - final int rr = remainder / rowStride; - final int cc = remainder % rowStride; - if (i >= 0) { - return packed[ss][rr][cc]; - } else if (i > Integer.MIN_VALUE) { - return -packed[ss][rr][cc]; - } else { - return ZERO; - } - } -} diff --git a/src/main/java/org/jtransforms/fft/package.html b/src/main/java/org/jtransforms/fft/package.html deleted file mode 100644 index a41a5ae..0000000 --- a/src/main/java/org/jtransforms/fft/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Discrete Fourier Transforms. - - diff --git a/src/main/java/org/jtransforms/utils/IOUtils.java b/src/main/java/org/jtransforms/utils/IOUtils.java deleted file mode 100644 index 4b15bda..0000000 --- a/src/main/java/org/jtransforms/utils/IOUtils.java +++ /dev/null @@ -1,1447 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.utils; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Date; -import java.util.Random; -import pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * I/O utilities. - * - * @author Piotr Wendykier (piotr.wendykier@gmail.com) - */ -public class IOUtils -{ - - private static final String FF = "%.4f"; - - private IOUtils() - { - - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(float a, float b) - { - double tmp = a - b; - double rms = tmp * tmp; - return Math.sqrt(rms); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(float[] a, float[] b) - { - if (a.length != b.length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int i = 0; i < a.length; i++) { - tmp = (a[i] - b[i]); - rms += tmp * tmp; - } - return Math.sqrt(rms / a.length); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(FloatLargeArray a, FloatLargeArray b) - { - if (a.length() != b.length()) { - throw new IllegalArgumentException("Arrays are not the same size."); - } - double rms = 0; - double tmp; - for (long i = 0; i < a.length(); i++) { - tmp = (a.getFloat(i) - b.getFloat(i)); - rms += tmp * tmp; - } - return Math.sqrt(rms / (double) a.length()); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(float[][] a, float[][] b) - { - if (a.length != b.length || a[0].length != b[0].length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int r = 0; r < a.length; r++) { - for (int c = 0; c < a[0].length; c++) { - tmp = (a[r][c] - b[r][c]); - rms += tmp * tmp; - } - } - return Math.sqrt(rms / (a.length * a[0].length)); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(float[][][] a, float[][][] b) - { - if (a.length != b.length || a[0].length != b[0].length || a[0][0].length != b[0][0].length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int s = 0; s < a.length; s++) { - for (int r = 0; r < a[0].length; r++) { - for (int c = 0; c < a[0][0].length; c++) { - tmp = (a[s][r][c] - b[s][r][c]); - rms += tmp * tmp; - } - } - } - return Math.sqrt(rms / (a.length * a[0].length * a[0][0].length)); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(double a, double b) - { - double tmp = a - b; - double rms = tmp * tmp; - return Math.sqrt(rms); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(double[] a, double[] b) - { - if (a.length != b.length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int i = 0; i < a.length; i++) { - tmp = (a[i] - b[i]); - rms += tmp * tmp; - } - return Math.sqrt(rms / a.length); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(DoubleLargeArray a, DoubleLargeArray b) - { - if (a.length() != b.length()) { - throw new IllegalArgumentException("Arrays are not the same size."); - } - double rms = 0; - double tmp; - for (long i = 0; i < a.length(); i++) { - tmp = (a.getDouble(i) - b.getDouble(i)); - rms += tmp * tmp; - } - return Math.sqrt(rms / (double) a.length()); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(double[][] a, double[][] b) - { - if (a.length != b.length || a[0].length != b[0].length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int r = 0; r < a.length; r++) { - for (int c = 0; c < a[0].length; c++) { - tmp = (a[r][c] - b[r][c]); - rms += tmp * tmp; - } - } - return Math.sqrt(rms / (a.length * a[0].length)); - } - - /** - * Computes root mean square error between a and b. - * - * @param a input parameter - * @param b input parameter - * - * @return root mean squared error between a and b - */ - public static double computeRMSE(double[][][] a, double[][][] b) - { - if (a.length != b.length || a[0].length != b[0].length || a[0][0].length != b[0][0].length) { - throw new IllegalArgumentException("Arrays are not the same size"); - } - double rms = 0; - double tmp; - for (int s = 0; s < a.length; s++) { - for (int r = 0; r < a[0].length; r++) { - for (int c = 0; c < a[0][0].length; c++) { - tmp = (a[s][r][c] - b[s][r][c]); - rms += tmp * tmp; - } - } - } - return Math.sqrt(rms / (a.length * a[0].length * a[0][0].length)); - } - - /** - * Fills 1D matrix with random numbers. - * - * @param N size - * @param m 1D matrix - */ - public static void fillMatrix_1D(long N, double[] m) - { - Random r = new Random(2); - for (int i = 0; i < N; i++) { - m[i] = r.nextDouble(); - } - } - - /** - * Fills 1D matrix with random numbers. - * - * @param N size - * @param m 1D matrix - */ - public static void fillMatrix_1D(long N, DoubleLargeArray m) - { - Random r = new Random(2); - for (long i = 0; i < N; i++) { - m.setDouble(i, r.nextDouble()); - } - } - - /** - * Fills 1D matrix with random numbers. - * - * @param N size - * @param m 1D matrix - */ - public static void fillMatrix_1D(long N, FloatLargeArray m) - { - Random r = new Random(2); - for (long i = 0; i < N; i++) { - m.setDouble(i, r.nextFloat()); - } - } - - /** - * Fills 1D matrix with random numbers. - * - * @param N size - * @param m 1D matrix - */ - public static void fillMatrix_1D(long N, float[] m) - { - Random r = new Random(2); - for (int i = 0; i < N; i++) { - m[i] = r.nextFloat(); - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, double[] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - m[(int) (i * n2 + j)] = r.nextDouble(); - } - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, FloatLargeArray m) - { - Random r = new Random(2); - for (long i = 0; i < n1; i++) { - for (long j = 0; j < n2; j++) { - m.setFloat(i * n2 + j, r.nextFloat()); - } - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, DoubleLargeArray m) - { - Random r = new Random(2); - for (long i = 0; i < n1; i++) { - for (long j = 0; j < n2; j++) { - m.setDouble(i * n2 + j, r.nextDouble()); - } - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, float[] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - m[(int) (i * n2 + j)] = r.nextFloat(); - } - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, double[][] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - m[i][j] = r.nextDouble(); - } - } - } - - /** - * Fills 2D matrix with random numbers. - * - * @param n1 rows - * @param n2 columns - * @param m 2D matrix - */ - public static void fillMatrix_2D(long n1, long n2, float[][] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - m[i][j] = r.nextFloat(); - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, double[] m) - { - Random r = new Random(2); - long sliceStride = n2 * n3; - long rowStride = n3; - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - for (int k = 0; k < n3; k++) { - m[(int) (i * sliceStride + j * rowStride + k)] = r.nextDouble(); - } - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, DoubleLargeArray m) - { - Random r = new Random(2); - long sliceStride = n2 * n3; - long rowStride = n3; - for (long i = 0; i < n1; i++) { - for (long j = 0; j < n2; j++) { - for (long k = 0; k < n3; k++) { - m.setDouble(i * sliceStride + j * rowStride + k, r.nextDouble()); - } - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, FloatLargeArray m) - { - Random r = new Random(2); - long sliceStride = n2 * n3; - long rowStride = n3; - for (long i = 0; i < n1; i++) { - for (long j = 0; j < n2; j++) { - for (long k = 0; k < n3; k++) { - m.setDouble(i * sliceStride + j * rowStride + k, r.nextFloat()); - } - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, float[] m) - { - Random r = new Random(2); - long sliceStride = n2 * n3; - long rowStride = n3; - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - for (int k = 0; k < n3; k++) { - m[(int) (i * sliceStride + j * rowStride + k)] = r.nextFloat(); - } - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, double[][][] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - for (int k = 0; k < n3; k++) { - m[i][j][k] = r.nextDouble(); - } - } - } - } - - /** - * Fills 3D matrix with random numbers. - * - * @param n1 slices - * @param n2 rows - * @param n3 columns - * @param m 3D matrix - */ - public static void fillMatrix_3D(long n1, long n2, long n3, float[][][] m) - { - Random r = new Random(2); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - for (int k = 0; k < n3; k++) { - m[i][j][k] = r.nextFloat(); - } - } - } - } - - /** - * Displays elements of x, assuming that it is 1D complex - * array. Complex data is represented by 2 double values in sequence: the - * real and imaginary parts. - * - * @param x input array - * @param title title of the array - */ - public static void showComplex_1D(double[] x, String title) - { - System.out.println(title); - System.out.println("-------------------"); - for (int i = 0; i < x.length; i = i + 2) { - if (x[i + 1] == 0) { - System.out.println(String.format(FF, x[i])); - continue; - } - if (x[i] == 0) { - System.out.println(String.format(FF, x[i + 1]) + "i"); - continue; - } - if (x[i + 1] < 0) { - System.out.println(String.format(FF, x[i]) + " - " + (String.format(FF, -x[i + 1])) + "i"); - continue; - } - System.out.println(String.format(FF, x[i]) + " + " + (String.format(FF, x[i + 1])) + "i"); - } - System.out.println(); - } - - /** - * Displays elements of x, assuming that it is 2D complex - * array. Complex data is represented by 2 double values in sequence: the - * real and imaginary parts. - * - * @param rows number of rows in the input array - * @param columns number of columns in the input array - * @param x input array - * @param title title of the array - */ - public static void showComplex_2D(int rows, int columns, double[] x, String title) - { - StringBuilder s = new StringBuilder(String.format(title + ": complex array 2D: %d rows, %d columns\n\n", rows, columns)); - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c = c + 2) { - if (x[r * 2 * columns + c + 1] == 0) { - s.append(String.format(FF + "\t", x[r * 2 * columns + c])); - continue; - } - if (x[r * 2 * columns + c] == 0) { - s.append(String.format(FF + "i\t", x[r * 2 * columns + c + 1])); - continue; - } - if (x[r * 2 * columns + c + 1] < 0) { - s.append(String.format(FF + " - " + FF + "i\t", x[r * 2 * columns + c], -x[r * 2 * columns + c + 1])); - continue; - } - s.append(String.format(FF + " + " + FF + "i\t", x[r * 2 * columns + c], x[r * 2 * columns + c + 1])); - } - s.append("\n"); - } - System.out.println(s.toString()); - } - - /** - * Displays elements of x, assuming that it is 2D complex - * array. Complex data is represented by 2 double values in sequence: the - * real and imaginary parts. - * - * @param x input array - * @param title title of the array - */ - public static void showComplex_2D(double[][] x, String title) - { - int rows = x.length; - int columns = x[0].length; - StringBuilder s = new StringBuilder(String.format(title + ": complex array 2D: %d rows, %d columns\n\n", rows, columns)); - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c = c + 2) { - if (x[r][c + 1] == 0) { - s.append(String.format(FF + "\t", x[r][c])); - continue; - } - if (x[r][c] == 0) { - s.append(String.format(FF + "i\t", x[r][c + 1])); - continue; - } - if (x[r][c + 1] < 0) { - s.append(String.format(FF + " - " + FF + "i\t", x[r][c], -x[r][c + 1])); - continue; - } - s.append(String.format(FF + " + " + FF + "i\t", x[r][c], x[r][c + 1])); - } - s.append("\n"); - } - System.out.println(s.toString()); - } - - /** - * Displays elements of x, assuming that it is 3D complex - * array. Complex data is represented by 2 double values in sequence: the - * real and imaginary parts. - * - * @param n1 first dimension - * @param n2 second dimension - * @param n3 third dimension - * @param x input array - * @param title title of the array - */ - public static void showComplex_3D(int n1, int n2, int n3, double[] x, String title) - { - int sliceStride = n2 * 2 * n3; - int rowStride = 2 * n3; - - System.out.println(title); - System.out.println("-------------------"); - - for (int k = 0; k < 2 * n3; k = k + 2) { - System.out.println("(:,:," + k / 2 + ")=\n"); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (x[i * sliceStride + j * rowStride + k + 1] == 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + "\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k] == 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k + 1] < 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " - " + String.format(FF, -x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " + " + String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - } - System.out.println(""); - } - } - System.out.println(""); - } - - /** - * Displays elements of x. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param x input array - * @param title title of the array - */ - public static void showComplex_3D(double[][][] x, String title) - { - System.out.println(title); - System.out.println("-------------------"); - int slices = x.length; - int rows = x[0].length; - int columns = x[0][0].length; - for (int k = 0; k < columns; k = k + 2) { - System.out.println("(:,:," + k / 2 + ")=\n"); - for (int i = 0; i < slices; i++) { - for (int j = 0; j < rows; j++) { - if (x[i][j][k + 1] == 0) { - System.out.print(String.format(FF, x[i][j][k]) + "\t"); - continue; - } - if (x[i][j][k] == 0) { - System.out.print(String.format(FF, x[i][j][k + 1]) + "i\t"); - continue; - } - if (x[i][j][k + 1] < 0) { - System.out.print(String.format(FF, x[i][j][k]) + " - " + String.format(FF, -x[i][j][k + 1]) + "i\t"); - continue; - } - System.out.print(String.format(FF, x[i][j][k]) + " + " + String.format(FF, x[i][j][k + 1]) + "i\t"); - } - System.out.println(""); - } - } - System.out.println(""); - } - - /** - * Displays elements of x, assuming that it is 3D complex - * array. Complex data is represented by 2 double values in sequence: the - * real and imaginary parts. - * - * @param n1 first dimension - * @param n2 second dimension - * @param n3 third dimension - * @param x input array - * @param title title of the array - */ - public static void showComplex_3D(int n1, int n2, int n3, float[] x, String title) - { - int sliceStride = n2 * 2 * n3; - int rowStride = 2 * n3; - - System.out.println(title); - System.out.println("-------------------"); - - for (int k = 0; k < 2 * n3; k = k + 2) { - System.out.println("(:,:," + k / 2 + ")=\n"); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (x[i * sliceStride + j * rowStride + k + 1] == 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + "\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k] == 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k + 1] < 0) { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " - " + String.format(FF, -x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " + " + String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - } - System.out.println(""); - } - } - System.out.println(""); - } - - /** - * Displays elements of x, assuming that it is 1D real array. - * - * @param x input array - * @param title title of the array - */ - public static void showReal_1D(double[] x, String title) - { - System.out.println(title); - System.out.println("-------------------"); - for (int j = 0; j < x.length; j++) { - System.out.println(String.format(FF, x[j])); - } - System.out.println(); - } - - /** - * Displays elements of x, assuming that it is 2D real array. - * - * @param n1 first dimension - * @param n2 second dimension - * @param x input array - * @param title title of the array - * - */ - public static void showReal_2D(int n1, int n2, double[] x, String title) - { - System.out.println(title); - System.out.println("-------------------"); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (Math.abs(x[i * n2 + j]) < 5e-5) { - System.out.print("0\t"); - } else { - System.out.print(String.format(FF, x[i * n2 + j]) + "\t"); - } - } - System.out.println(); - } - System.out.println(); - } - - /** - * Displays elements of x, assuming that it is 3D real array. - * - * - * @param n1 first dimension - * @param n2 second dimension - * @param n3 third dimension - * @param x input array - * @param title title of the array - */ - public static void showReal_3D(int n1, int n2, int n3, double[] x, String title) - { - int sliceStride = n2 * n3; - int rowStride = n3; - - System.out.println(title); - System.out.println("-------------------"); - - for (int k = 0; k < n3; k++) { - System.out.println(); - System.out.println("(:,:," + k + ")=\n"); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (Math.abs(x[i * sliceStride + j * rowStride + k]) <= 5e-5) { - System.out.print("0\t"); - } else { - System.out.print(String.format(FF, x[i * sliceStride + j * rowStride + k]) + "\t"); - } - } - System.out.println(); - } - } - System.out.println(); - } - - /** - * Displays elements of x. - * - * @param x input array - * @param title title of the array - */ - public static void showReal_3D(double[][][] x, String title) - { - - System.out.println(title); - System.out.println("-------------------"); - int slices = x.length; - int rows = x[0].length; - int columns = x[0][0].length; - for (int k = 0; k < columns; k++) { - System.out.println(); - System.out.println("(:,:," + k + ")=\n"); - for (int i = 0; i < slices; i++) { - for (int j = 0; j < rows; j++) { - if (Math.abs(x[i][j][k]) <= 5e-5) { - System.out.print("0\t"); - } else { - System.out.print(String.format(FF, x[i][j][k]) + "\t"); - } - } - System.out.println(); - } - } - System.out.println(); - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 1D complex array. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_1D(double[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < x.length; i = i + 2) { - if (x[i + 1] == 0) { - out.write(String.format(FF, x[i])); - out.newLine(); - continue; - } - if (x[i] == 0) { - out.write(String.format(FF, x[i + 1]) + "i"); - out.newLine(); - continue; - } - if (x[i + 1] < 0) { - out.write(String.format(FF, x[i]) + " - " + String.format(FF, -x[i + 1]) + "i"); - out.newLine(); - continue; - } - out.write(String.format(FF, x[i]) + " + " + String.format(FF, x[i + 1]) + "i"); - out.newLine(); - } - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 1D complex array. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_1D(float[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < x.length; i = i + 2) { - if (x[i + 1] == 0) { - out.write(String.format(FF, x[i])); - out.newLine(); - continue; - } - if (x[i] == 0) { - out.write(String.format(FF, x[i + 1]) + "i"); - out.newLine(); - continue; - } - if (x[i + 1] < 0) { - out.write(String.format(FF, x[i]) + " - " + String.format(FF, -x[i + 1]) + "i"); - out.newLine(); - continue; - } - out.write(String.format(FF, x[i]) + " + " + String.format(FF, x[i + 1]) + "i"); - out.newLine(); - } - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D complex array. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param n1 first dimension - * @param n2 second dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_2D(int n1, int n2, double[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < 2 * n2; j = j + 2) { - if ((Math.abs(x[i * 2 * n2 + j]) < 5e-5) && (Math.abs(x[i * 2 * n2 + j + 1]) < 5e-5)) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write("0 + 0i\t"); - } else { - out.write("0 - 0i\t"); - } - continue; - } - - if (Math.abs(x[i * 2 * n2 + j + 1]) < 5e-5) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " + 0i\t"); - } else { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " - 0i\t"); - } - continue; - } - if (Math.abs(x[i * 2 * n2 + j]) < 5e-5) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write("0 + " + String.format(FF, x[i * 2 * n2 + j + 1]) + "i\t"); - } else { - out.write("0 - " + String.format(FF, -x[i * 2 * n2 + j + 1]) + "i\t"); - } - continue; - } - if (x[i * 2 * n2 + j + 1] < 0) { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " - " + String.format(FF, -x[i * 2 * n2 + j + 1]) + "i\t"); - continue; - } - out.write(String.format(FF, x[i * 2 * n2 + j]) + " + " + String.format(FF, x[i * 2 * n2 + j + 1]) + "i\t"); - } - out.newLine(); - } - - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D complex array. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param n1 first dimension - * @param n2 second dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_2D(int n1, int n2, float[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < 2 * n2; j = j + 2) { - if ((Math.abs(x[i * 2 * n2 + j]) < 5e-5) && (Math.abs(x[i * 2 * n2 + j + 1]) < 5e-5)) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write("0 + 0i\t"); - } else { - out.write("0 - 0i\t"); - } - continue; - } - - if (Math.abs(x[i * 2 * n2 + j + 1]) < 5e-5) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " + 0i\t"); - } else { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " - 0i\t"); - } - continue; - } - if (Math.abs(x[i * 2 * n2 + j]) < 5e-5) { - if (x[i * 2 * n2 + j + 1] >= 0.0) { - out.write("0 + " + String.format(FF, x[i * 2 * n2 + j + 1]) + "i\t"); - } else { - out.write("0 - " + String.format(FF, -x[i * 2 * n2 + j + 1]) + "i\t"); - } - continue; - } - if (x[i * 2 * n2 + j + 1] < 0) { - out.write(String.format(FF, x[i * 2 * n2 + j]) + " - " + String.format(FF, -x[i * 2 * n2 + j + 1]) + "i\t"); - continue; - } - out.write(String.format(FF, x[i * 2 * n2 + j]) + " + " + String.format(FF, x[i * 2 * n2 + j + 1]) + "i\t"); - } - out.newLine(); - } - - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename. Complex - * data is represented by 2 double values in sequence: the real and - * imaginary parts. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_2D(double[][] x, String filename) - { - int n1 = x.length; - int n2 = x[0].length; - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < 2 * n2; j = j + 2) { - if ((Math.abs(x[i][j]) < 5e-5) && (Math.abs(x[i][j + 1]) < 5e-5)) { - if (x[i][j + 1] >= 0.0) { - out.write("0 + 0i\t"); - } else { - out.write("0 - 0i\t"); - } - continue; - } - - if (Math.abs(x[i][j + 1]) < 5e-5) { - if (x[i][j + 1] >= 0.0) { - out.write(String.format(FF, x[i][j]) + " + 0i\t"); - } else { - out.write(String.format(FF, x[i][j]) + " - 0i\t"); - } - continue; - } - if (Math.abs(x[i][j]) < 5e-5) { - if (x[i][j + 1] >= 0.0) { - out.write("0 + " + String.format(FF, x[i][j + 1]) + "i\t"); - } else { - out.write("0 - " + String.format(FF, -x[i][j + 1]) + "i\t"); - } - continue; - } - if (x[i][j + 1] < 0) { - out.write(String.format(FF, x[i][j]) + " - " + String.format(FF, -x[i][j + 1]) + "i\t"); - continue; - } - out.write(String.format(FF, x[i][j]) + " + " + String.format(FF, x[i][j + 1]) + "i\t"); - } - out.newLine(); - } - - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 3D complex array. Complex data is represented by 2 - * double values in sequence: the real and imaginary parts. - * - * @param n1 first dimension - * @param n2 second dimension - * @param n3 third dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_3D(int n1, int n2, int n3, double[] x, String filename) - { - int sliceStride = n2 * n3 * 2; - int rowStride = n3 * 2; - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int k = 0; k < 2 * n3; k = k + 2) { - out.newLine(); - out.write("(:,:," + k / 2 + ")="); - out.newLine(); - out.newLine(); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (x[i * sliceStride + j * rowStride + k + 1] == 0) { - out.write(String.format(FF, x[i * sliceStride + j * rowStride + k]) + "\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k] == 0) { - out.write(String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - if (x[i * sliceStride + j * rowStride + k + 1] < 0) { - out.write(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " - " + String.format(FF, -x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - continue; - } - out.write(String.format(FF, x[i * sliceStride + j * rowStride + k]) + " + " + String.format(FF, x[i * sliceStride + j * rowStride + k + 1]) + "i\t"); - } - out.newLine(); - } - } - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename. Complex - * data is represented by 2 double values in sequence: the real and - * imaginary parts. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileComplex_3D(double[][][] x, String filename) - { - int n1 = x.length; - int n2 = x[0].length; - int n3 = x[0][0].length; - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int k = 0; k < 2 * n3; k = k + 2) { - out.newLine(); - out.write("(:,:," + k / 2 + ")="); - out.newLine(); - out.newLine(); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (x[i][j][k + 1] == 0) { - out.write(String.format(FF, x[i][j][k]) + "\t"); - continue; - } - if (x[i][j][k] == 0) { - out.write(String.format(FF, x[i][j][k + 1]) + "i\t"); - continue; - } - if (x[i][j][k + 1] < 0) { - out.write(String.format(FF, x[i][j][k]) + " - " + String.format(FF, -x[i][j][k + 1]) + "i\t"); - continue; - } - out.write(String.format(FF, x[i][j][k]) + " + " + String.format(FF, x[i][j][k + 1]) + "i\t"); - } - out.newLine(); - } - } - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D real array. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileReal_1D(double[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int j = 0; j < x.length; j++) { - out.write(String.format(FF, x[j])); - out.newLine(); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D real array. - * - * @param x input array - * @param filename finename - */ - public static void writeToFileReal_1D(float[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int j = 0; j < x.length; j++) { - out.write(String.format(FF, x[j])); - out.newLine(); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D real array. - * - * @param n1 first dimension - * @param n2 second dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileReal_2D(int n1, int n2, double[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (Math.abs(x[i * n2 + j]) < 5e-5) { - out.write("0\t"); - } else { - out.write(String.format(FF, x[i * n2 + j]) + "\t"); - } - } - out.newLine(); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 2D real array. - * - * @param n1 first dimension - * @param n2 second dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileReal_2D(int n1, int n2, float[] x, String filename) - { - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - if (Math.abs(x[i * n2 + j]) < 5e-5) { - out.write("0\t"); - } else { - out.write(String.format(FF, x[i * n2 + j]) + "\t"); - } - } - out.newLine(); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves elements of x in a file filename, - * assuming that it is 3D real array. - * - * @param n1 first dimension - * @param n2 second dimension - * @param n3 third dimension - * @param x input array - * @param filename finename - */ - public static void writeToFileReal_3D(int n1, int n2, int n3, double[] x, String filename) - { - int sliceStride = n2 * n3; - int rowStride = n3; - - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename)); - for (int k = 0; k < n3; k++) { - out.newLine(); - out.write("(:,:," + k + ")="); - out.newLine(); - out.newLine(); - for (int i = 0; i < n1; i++) { - for (int j = 0; j < n2; j++) { - out.write(String.format(FF, x[i * sliceStride + j * rowStride + k]) + "\t"); - } - out.newLine(); - } - out.newLine(); - } - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Saves benchmark results in a file. - * - * @param filename filename - * @param nthread number of threads - * @param niter number of iterations - * @param doWarmup if warmup was performed - * @param doScaling if scaling was performed - * @param sizes benchmarked sizes - * @param times_without_constructor timings excluding constructor - * @param times_with_constructor timings including constructor - */ - public static void writeFFTBenchmarkResultsToFile(String filename, int nthread, int niter, boolean doWarmup, boolean doScaling, long[] sizes, double[] times_without_constructor, double[] times_with_constructor) - { - String[] properties = {"os.name", "os.version", "os.arch", "java.vendor", "java.version"}; - try { - BufferedWriter out = new BufferedWriter(new FileWriter(filename, false)); - out.write(new Date().toString()); - out.newLine(); - out.write("System properties:"); - out.newLine(); - out.write("\tos.name = " + System.getProperty(properties[0])); - out.newLine(); - out.write("\tos.version = " + System.getProperty(properties[1])); - out.newLine(); - out.write("\tos.arch = " + System.getProperty(properties[2])); - out.newLine(); - out.write("\tjava.vendor = " + System.getProperty(properties[3])); - out.newLine(); - out.write("\tjava.version = " + System.getProperty(properties[4])); - out.newLine(); - out.write("\tavailable processors = " + Runtime.getRuntime().availableProcessors()); - out.newLine(); - out.write("Settings:"); - out.newLine(); - out.write("\tused processors = " + nthread); - out.newLine(); - out.write("\tTHREADS_BEGIN_N_2D = " + ConcurrencyUtils.getThreadsBeginN_2D()); - out.newLine(); - out.write("\tTHREADS_BEGIN_N_3D = " + ConcurrencyUtils.getThreadsBeginN_3D()); - out.newLine(); - out.write("\tnumber of iterations = " + niter); - out.newLine(); - out.write("\twarm-up performed = " + doWarmup); - out.newLine(); - out.write("\tscaling performed = " + doScaling); - out.newLine(); - out.write("--------------------------------------------------------------------------------------------------"); - out.newLine(); - out.write("sizes=["); - for (int i = 0; i < sizes.length; i++) { - out.write(Long.toString(sizes[i])); - if (i < sizes.length - 1) { - out.write(", "); - } else { - out.write("]"); - } - } - out.newLine(); - out.write("times without constructor(in msec)=["); - for (int i = 0; i < times_without_constructor.length; i++) { - out.write(String.format("%.2f", times_without_constructor[i])); - if (i < times_without_constructor.length - 1) { - out.write(", "); - } else { - out.write("]"); - } - } - out.newLine(); - out.write("times with constructor(in msec)=["); - for (int i = 0; i < times_without_constructor.length; i++) { - out.write(String.format("%.2f", times_with_constructor[i])); - if (i < times_with_constructor.length - 1) { - out.write(", "); - } else { - out.write("]"); - } - } - out.newLine(); - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/org/jtransforms/utils/package.html b/src/main/java/org/jtransforms/utils/package.html deleted file mode 100644 index 4ee8eaa..0000000 --- a/src/main/java/org/jtransforms/utils/package.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Utility classes. - - diff --git a/src/test/java/org/jtransforms/dct/DoubleDCT_1DTest.java b/src/test/java/org/jtransforms/dct/DoubleDCT_1DTest.java deleted file mode 100644 index 786e9df..0000000 --- a/src/test/java/org/jtransforms/dct/DoubleDCT_1DTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDCT_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDCT_1DTest { - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final DoubleDCT_1D dct; - - /** - * The size of the DCT to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n the size of the DCT to be tested - * @param numThreads the number of threads - * @param seed the seed of the random generator - */ - public DoubleDCT_1DTest(final int n, final int numThreads, final long seed) { - this.n = n; - this.dct = new DoubleDCT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDCT_1D#forward(double[], boolean)}, and - * {@link DoubleDCT_1D#inverse(double[], boolean)} with the second parameter - * set to true. - */ - @Test - public void testScaled() { - final double[] actual = new double[n]; - final double[] expected = new double[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link DoubleDCT_1D#forward(DoubleLargeArray, boolean)}, and - * {@link DoubleDCT_1D#inverse(DoubleLargeArray, boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(n, false); - final DoubleLargeArray expected = new DoubleLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dct/DoubleDCT_2DTest.java b/src/test/java/org/jtransforms/dct/DoubleDCT_2DTest.java deleted file mode 100644 index bd94df2..0000000 --- a/src/test/java/org/jtransforms/dct/DoubleDCT_2DTest.java +++ /dev/null @@ -1,186 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDCT_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDCT_2DTest { - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final DoubleDCT_2D dct; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows number of rows - * @param numColumns number of columns - * @param numThreads the number of threads to be used - * @param seed the seed of the random generator - */ - public DoubleDCT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) { - this.numRows = numRows; - this.numCols = numColumns; - this.dct = new DoubleDCT_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDCT_2D#forward(double[], boolean)}, and - * {@link DoubleDCT_2D#inverse(double[], boolean)} with the second parameter - * set to true. - */ - @Test - public void testScaled() { - final double[] actual = new double[numRows * numCols]; - final double[] expected = new double[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link DoubleDCT_2D#forward(DoubleLargeArray, boolean)}, and - * {@link DoubleDCT_2D#inverse(DoubleLargeArray], boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaledLarge() { - final DoubleLargeArray actual = new DoubleLargeArray(numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(r * numCols + c, rnd); - expected.setDouble(r * numCols + c, rnd); - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDCT_2D#forward(double[][], boolean)}, and - * {@link DoubleDCT_2D#inverse(double[][], boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaled2D() { - final double[][] actual = new double[numRows][numCols]; - final double[][] expected = new double[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dct/DoubleDCT_3DTest.java b/src/test/java/org/jtransforms/dct/DoubleDCT_3DTest.java deleted file mode 100644 index 2c7c16a..0000000 --- a/src/test/java/org/jtransforms/dct/DoubleDCT_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDCT_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDCT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final DoubleDCT_3D dct; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleDCT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dct = new DoubleDCT_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDCT_3D#forward(double[], boolean)}, - * and {@link DoubleDCT_3D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[numSlices * numRows * numCols]; - final double[] expected = new double[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDCT_3D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDCT_3D#inverse(DoubleLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(numSlices * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(s * numRows * numCols + r * numCols + c, rnd); - expected.setDouble(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDCT_3D#forward(double[][][], boolean)}, - * and {@link DoubleDCT_3D#inverse(double[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final double[][][] actual = new double[numSlices][numRows][numCols]; - final double[][][] expected = new double[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dct/FloatDCT_1DTest.java b/src/test/java/org/jtransforms/dct/FloatDCT_1DTest.java deleted file mode 100644 index c78ec13..0000000 --- a/src/test/java/org/jtransforms/dct/FloatDCT_1DTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDCT_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDCT_1DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final FloatDCT_1D dct; - - /** - * The size of the DCT to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n - * the size of the DCT to be tested - * @param numThreads - * the number of threads - * @param seed - * the seed of the random generator - */ - public FloatDCT_1DTest(final int n, final int numThreads, final long seed) - { - this.n = n; - this.dct = new FloatDCT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDCT_1D#forward(float[], boolean)}, - * and {@link FloatDCT_1D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[n]; - final float[] expected = new float[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDCT_1D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDCT_1D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(n, false); - final FloatLargeArray expected = new FloatLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dct/FloatDCT_2DTest.java b/src/test/java/org/jtransforms/dct/FloatDCT_2DTest.java deleted file mode 100644 index bc96edd..0000000 --- a/src/test/java/org/jtransforms/dct/FloatDCT_2DTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDCT_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDCT_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final FloatDCT_2D dct; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDCT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.dct = new FloatDCT_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDCT_2D#forward(float[], boolean)}, - * and {@link FloatDCT_2D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numRows * numCols]; - final float[] expected = new float[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDCT_2D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDCT_2D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(r * numCols + c, rnd); - expected.setFloat(r * numCols + c, rnd); - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDCT_2D#forward(double[][], boolean)}, - * and {@link FloatDCT_2D#inverse(double[][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled2D() - { - final float[][] actual = new float[numRows][numCols]; - final float[][] expected = new float[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dct/FloatDCT_3DTest.java b/src/test/java/org/jtransforms/dct/FloatDCT_3DTest.java deleted file mode 100644 index 181ed2e..0000000 --- a/src/test/java/org/jtransforms/dct/FloatDCT_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dct; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDCT_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDCT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DCT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DCT to be tested. - */ - private final FloatDCT_3D dct; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDCT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dct = new FloatDCT_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDCT_3D#forward(float[], boolean)}, - * and {@link FloatDCT_3D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numSlices * numRows * numCols]; - final float[] expected = new float[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDCT_3D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDCT_3D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numSlices * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(s * numRows * numCols + r * numCols + c, rnd); - expected.setFloat(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDCT_3D#forward(float[][][], boolean)}, - * and {@link FloatDCT_3D#inverse(float[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final float[][][] actual = new float[numSlices][numRows][numCols]; - final float[][][] expected = new float[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dct.forward(actual, true); - dct.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/DoubleDHT_1DTest.java b/src/test/java/org/jtransforms/dht/DoubleDHT_1DTest.java deleted file mode 100644 index 2b0d29e..0000000 --- a/src/test/java/org/jtransforms/dht/DoubleDHT_1DTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDHT_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDHT_1DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final DoubleDHT_1D dht; - - /** - * The size of the DHT to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n - * the size of the DHT to be tested - * @param numThreads - * the number of threads - * @param seed - * the seed of the random generator - */ - public DoubleDHT_1DTest(final int n, final int numThreads, final long seed) - { - this.n = n; - this.dht = new DoubleDHT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDHT_1D#forward(double[], boolean)}, - * and {@link DoubleDHT_1D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[n]; - final double[] expected = new double[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDHT_1D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDHT_1D#inverse(DoubleLargeArray, boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(n, false); - final DoubleLargeArray expected = new DoubleLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/DoubleDHT_2DTest.java b/src/test/java/org/jtransforms/dht/DoubleDHT_2DTest.java deleted file mode 100644 index 21bf33a..0000000 --- a/src/test/java/org/jtransforms/dht/DoubleDHT_2DTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDHT_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDHT_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final DoubleDHT_2D dht; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleDHT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.dht = new DoubleDHT_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDHT_2D#forward(double[], boolean)}, - * and {@link DoubleDHT_2D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[numRows * numCols]; - final double[] expected = new double[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDHT_2D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDHT_2D#inverse(DoubleLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(r * numCols + c, rnd); - expected.setDouble(r * numCols + c, rnd); - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDHT_2D#forward(double[][], boolean)}, - * and {@link DoubleDHT_2D#inverse(double[][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled2D() - { - final double[][] actual = new double[numRows][numCols]; - final double[][] expected = new double[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/DoubleDHT_3DTest.java b/src/test/java/org/jtransforms/dht/DoubleDHT_3DTest.java deleted file mode 100644 index 0775b7b..0000000 --- a/src/test/java/org/jtransforms/dht/DoubleDHT_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDHT_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDHT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final DoubleDHT_3D dht; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleDHT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dht = new DoubleDHT_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDHT_3D#forward(double[], boolean)}, - * and {@link DoubleDHT_3D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[numSlices * numRows * numCols]; - final double[] expected = new double[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDHT_3D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDHT_3D#inverse(DoubleLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(numSlices * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(s * numRows * numCols + r * numCols + c, rnd); - expected.setDouble(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDHT_3D#forward(double[][][], boolean)}, - * and {@link DoubleDHT_3D#inverse(double[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final double[][][] actual = new double[numSlices][numRows][numCols]; - final double[][][] expected = new double[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/FloatDHT_1DTest.java b/src/test/java/org/jtransforms/dht/FloatDHT_1DTest.java deleted file mode 100644 index a47dc46..0000000 --- a/src/test/java/org/jtransforms/dht/FloatDHT_1DTest.java +++ /dev/null @@ -1,151 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDHT_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDHT_1DTest { - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final FloatDHT_1D dht; - - /** - * The size of the DHT to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n the size of the DHT to be tested - * @param numThreads the number of threads - * @param seed the seed of the random generator - */ - public FloatDHT_1DTest(final int n, final int numThreads, final long seed) { - this.n = n; - this.dht = new FloatDHT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDHT_1D#forward(float[], boolean)}, and - * {@link FloatDHT_1D#inverse(float[], boolean)} with the second parameter - * set to true. - */ - @Test - public void testScaled() { - final float[] actual = new float[n]; - final float[] expected = new float[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDHT_1D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDHT_1D#inverse(float[], boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(n, false); - final FloatLargeArray expected = new FloatLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/FloatDHT_2DTest.java b/src/test/java/org/jtransforms/dht/FloatDHT_2DTest.java deleted file mode 100644 index 179ddd6..0000000 --- a/src/test/java/org/jtransforms/dht/FloatDHT_2DTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDHT_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDHT_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final FloatDHT_2D dht; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDHT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.dht = new FloatDHT_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDHT_2D#forward(float[], boolean)}, - * and {@link FloatDHT_2D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numRows * numCols]; - final float[] expected = new float[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDHT_2D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDHT_2D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(r * numCols + c, rnd); - expected.setFloat(r * numCols + c, rnd); - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDHT_2D#forward(double[][], boolean)}, - * and {@link FloatDHT_2D#inverse(double[][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled2D() - { - final float[][] actual = new float[numRows][numCols]; - final float[][] expected = new float[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dht/FloatDHT_3DTest.java b/src/test/java/org/jtransforms/dht/FloatDHT_3DTest.java deleted file mode 100644 index f0d746a..0000000 --- a/src/test/java/org/jtransforms/dht/FloatDHT_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dht; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDHT_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDHT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DHT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DHT to be tested. - */ - private final FloatDHT_3D dht; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDHT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dht = new FloatDHT_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDHT_3D#forward(float[], boolean)}, - * and {@link FloatDHT_3D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numSlices * numRows * numCols]; - final float[] expected = new float[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDHT_3D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDHT_3D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numSlices * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(s * numRows * numCols + r * numCols + c, rnd); - expected.setFloat(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDHT_3D#forward(float[][][], boolean)}, - * and {@link FloatDHT_3D#inverse(float[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final float[][][] actual = new float[numSlices][numRows][numCols]; - final float[][][] expected = new float[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dht.forward(actual); - dht.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/DoubleDST_1DTest.java b/src/test/java/org/jtransforms/dst/DoubleDST_1DTest.java deleted file mode 100644 index fafef4d..0000000 --- a/src/test/java/org/jtransforms/dst/DoubleDST_1DTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDST_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDST_1DTest { - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final DoubleDST_1D dst; - - /** - * The size of the DST to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n the size of the DST to be tested - * @param numThreads the number of threads - * @param seed the seed of the random generator - */ - public DoubleDST_1DTest(final int n, final int numThreads, final long seed) { - this.n = n; - this.dst = new DoubleDST_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDST_1D#forward(double[], boolean)}, and - * {@link DoubleDST_1D#inverse(double[], boolean)} with the second parameter - * set to true. - */ - @Test - public void testScaled() { - final double[] actual = new double[n]; - final double[] expected = new double[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link DoubleDST_1D#forward(DoubleLargeArray, boolean)}, and - * {@link DoubleDST_1D#inverse(DoubleLargeArray, boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(n, false); - final DoubleLargeArray expected = new DoubleLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/DoubleDST_2DTest.java b/src/test/java/org/jtransforms/dst/DoubleDST_2DTest.java deleted file mode 100644 index 00c744b..0000000 --- a/src/test/java/org/jtransforms/dst/DoubleDST_2DTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDST_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDST_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final DoubleDST_2D dst; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleDST_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.dst = new DoubleDST_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDST_2D#forward(double[], boolean)}, - * and {@link DoubleDST_2D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[numRows * numCols]; - final double[] expected = new double[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDST_2D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDST_2D#inverse(DoubleLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(r * numCols + c, rnd); - expected.setDouble(r * numCols + c, rnd); - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDST_2D#forward(double[][], boolean)}, - * and {@link DoubleDST_2D#inverse(double[][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled2D() - { - final double[][] actual = new double[numRows][numCols]; - final double[][] expected = new double[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/DoubleDST_3DTest.java b/src/test/java/org/jtransforms/dst/DoubleDST_3DTest.java deleted file mode 100644 index 417d4e1..0000000 --- a/src/test/java/org/jtransforms/dst/DoubleDST_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleDST_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleDST_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final DoubleDST_3D dst; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleDST_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dst = new DoubleDST_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link DoubleDST_3D#forward(double[], boolean)}, - * and {@link DoubleDST_3D#inverse(double[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final double[] actual = new double[numSlices * numRows * numCols]; - final double[] expected = new double[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDST_3D#forward(DoubleLargeArray, boolean)}, - * and {@link DoubleDST_3D#inverse(DoubleLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(numSlices * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(s * numRows * numCols + r * numCols + c, rnd); - expected.setDouble(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleDST_3D#forward(double[][][], boolean)}, - * and {@link DoubleDST_3D#inverse(double[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final double[][][] actual = new double[numSlices][numRows][numCols]; - final double[][][] expected = new double[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/FloatDST_1DTest.java b/src/test/java/org/jtransforms/dst/FloatDST_1DTest.java deleted file mode 100644 index 6cbd278..0000000 --- a/src/test/java/org/jtransforms/dst/FloatDST_1DTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDST_1D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDST_1DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final FloatDST_1D dst; - - /** - * The size of the DST to be tested. - */ - private final int n; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this class. - * - * @param n - * the size of the DST to be tested - * @param numThreads - * the number of threads - * @param seed - * the seed of the random generator - */ - public FloatDST_1DTest(final int n, final int numThreads, final long seed) - { - this.n = n; - this.dst = new FloatDST_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(512); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(512); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDST_1D#forward(float[], boolean)}, - * and {@link FloatDST_1D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < 2 * n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatDST_1D#forward(FloatLargeArray, boolean)}, and - * {@link FloatDST_1D#inverse(FloatLargeArray, boolean)} with the second - * parameter set to true. - */ - @Test - public void testScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(n, false); - final FloatLargeArray expected = new FloatLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/FloatDST_2DTest.java b/src/test/java/org/jtransforms/dst/FloatDST_2DTest.java deleted file mode 100644 index e62d864..0000000 --- a/src/test/java/org/jtransforms/dst/FloatDST_2DTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDST_2D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDST_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final FloatDST_2D dst; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDST_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.dst = new FloatDST_2D(numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4096); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDST_2D#forward(float[], boolean)}, - * and {@link FloatDST_2D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numRows * numCols]; - final float[] expected = new float[numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r * numCols + c] = rnd; - expected[r * numCols + c] = rnd; - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDST_2D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDST_2D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(r * numCols + c, rnd); - expected.setFloat(r * numCols + c, rnd); - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDST_2D#forward(double[][], boolean)}, - * and {@link FloatDST_2D#inverse(double[][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled2D() - { - final float[][] actual = new float[numRows][numCols]; - final float[][] expected = new float[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/dst/FloatDST_3DTest.java b/src/test/java/org/jtransforms/dst/FloatDST_3DTest.java deleted file mode 100644 index dcb4267..0000000 --- a/src/test/java/org/jtransforms/dst/FloatDST_3DTest.java +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.dst; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatDST_3D}. - * - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatDST_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded DST of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -5); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The DST to be tested. - */ - private final FloatDST_3D dst; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatDST_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.dst = new FloatDST_3D(numSlices, numRows, numCols); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(1); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * This is a test of {@link FloatDST_3D#forward(float[], boolean)}, - * and {@link FloatDST_3D#inverse(float[], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled() - { - final float[] actual = new float[numSlices * numRows * numCols]; - final float[] expected = new float[numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s * numRows * numCols + r * numCols + c] = rnd; - expected[s * numRows * numCols + r * numCols + c] = rnd; - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDST_3D#forward(FloatLargeArray, boolean)}, - * and {@link FloatDST_3D#inverse(FloatLargeArray], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(numSlices * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setFloat(s * numRows * numCols + r * numCols + c, rnd); - expected.setFloat(s * numRows * numCols + r * numCols + c, rnd); - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatDST_3D#forward(float[][][], boolean)}, - * and {@link FloatDST_3D#inverse(float[][][], boolean)} - * with the second parameter set to true. - */ - @Test - public void testScaled3D() - { - final float[][][] actual = new float[numSlices][numRows][numCols]; - final float[][][] expected = new float[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - dst.forward(actual, true); - dst.inverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/DoubleFFT_1DTest.java b/src/test/java/org/jtransforms/fft/DoubleFFT_1DTest.java deleted file mode 100644 index cdee190..0000000 --- a/src/test/java/org/jtransforms/fft/DoubleFFT_1DTest.java +++ /dev/null @@ -1,629 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; - -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.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -import pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * This is a series of JUnit tests for the {@link DoubleFFT_1D}. First, - * {@link DoubleFFT_1D#complexForward(double[])} is tested by comparison with - * reference data (FFTW). Then the other methods of this class are tested using - * {@link DoubleFFT_1D#complexForward(double[])} as a reference. - * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleFFT_1DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %d: "; - - /** - * Name of binary files (input, untransformed data). - */ - private final static String FFTW_INPUT_PATTERN = "fftw%d.in"; - - /** - * Name of binary files (output, transformed data). - */ - private final static String FFTW_OUTPUT_PATTERN = "fftw%d.out"; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The FFT to be tested. - */ - private final DoubleFFT_1D fft; - - /** - * The size of the FFT to be tested. - */ - private final int n; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Creates a new instance of this class. - * - * @param n - * the size of the FFT to be tested - * @param numThreads - * the number of threads - * @param seed - * the seed of the random generator - */ - public DoubleFFT_1DTest(final int n, final int numThreads, final long seed) - { - this.n = n; - this.fft = new DoubleFFT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * Read the binary reference data files generated with FFTW. The structure - * of these files is very simple: double values are written linearly (little - * endian). - * - * @param name - * the file name - * @param data - * the array to be updated with the data read (the size of this - * array gives the number of double to be retrieved - */ - public void readData(final String name, final double[] data) - { - try { - final File f = new File(getClass().getClassLoader() - .getResource(name).getFile()); - final FileInputStream fin = new FileInputStream(f); - final FileChannel fc = fin.getChannel(); - final ByteBuffer buffer = ByteBuffer.allocate(8 * data.length); - buffer.order(ByteOrder.LITTLE_ENDIAN); - fc.read(buffer); - for (int i = 0; i < data.length; i++) { - data[i] = buffer.getDouble(8 * i); - } - } catch (IOException e) { - Assert.fail(e.getMessage()); - } - } - - /** - * Read the binary reference data files generated with FFTW. The structure - * of these files is very simple: double values are written linearly (little - * endian). - * - * @param name - * the file name - * @param data - * the array to be updated with the data read (the size of this - * array gives the number of double to be retrieved - */ - public void readData(final String name, final DoubleLargeArray data) - { - try { - final File f = new File(getClass().getClassLoader() - .getResource(name).getFile()); - final FileInputStream fin = new FileInputStream(f); - final FileChannel fc = fin.getChannel(); - final ByteBuffer buffer = ByteBuffer.allocate(8 * (int) data.length()); - buffer.order(ByteOrder.LITTLE_ENDIAN); - fc.read(buffer); - for (int i = 0; i < data.length(); i++) { - data.setDouble(i, buffer.getDouble(8 * i)); - } - } catch (IOException e) { - Assert.fail(e.getMessage()); - } - } - - /** - * This is a test of {@link DoubleFFT_1D#complexForward(double[])}. This - * method is tested by computation of the FFT of some pre-generated data, - * and comparison with results obtained with FFTW. - */ - @Test - public void testComplexForward() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - readData(String.format(FFTW_INPUT_PATTERN, n), actual); - readData(String.format(FFTW_OUTPUT_PATTERN, n), - expected); - fft.complexForward(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#complexForward(DoubleLargeArray)}. This - * method is tested by computation of the FFT of some pre-generated data, - * and comparison with results obtained with FFTW. - */ - @Test - public void testComplexForwardLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - readData(String.format(FFTW_INPUT_PATTERN, n), actual); - readData(String.format(FFTW_OUTPUT_PATTERN, n), expected); - fft.complexForward(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#complexInverse(double[], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testComplexInverseScaled() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < 2 * n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#complexInverse(DoubleLargeArray, boolean)}, - * with the second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < 2 * n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#complexInverse(double[], boolean)}, - * with the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < 2 * n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double s = 1. / (double) n; - for (int i = 0; i < actual.length; i++) { - actual[i] = s * actual[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#complexInverse(DoubleLargeArray, boolean)}, - * with the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < 2 * n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double s = 1. / (double) n; - for (int i = 0; i < actual.length(); i++) { - actual.setDouble(i, s * actual.getDouble(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realForward(double[])}. - */ - @Test - public void testRealForward() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.; - } - fft.complexForward(expected); - fft.realForward(actual); - if (!ConcurrencyUtils.isPowerOf2(n)) { - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - actual[n] = actual[1]; - actual[1] = 0; - for (int k = 1; k < m; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual[idx1] = actual[idx2]; - actual[idx1 + 1] = -actual[idx2 + 1]; - } - } else { - for (int k = 1; k < n / 2; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual[idx1] = actual[idx2]; - actual[idx1 + 1] = -actual[idx2 + 1]; - } - actual[n] = actual[1]; - actual[1] = 0; - } - - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realForward(DoubleLargeArray)}. - */ - @Test - public void testRealForwardLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(2 * i, actual.getDouble(i)); - expected.setDouble(2 * i + 1, 0.); - } - fft.complexForward(expected); - fft.realForward(actual); - if (!ConcurrencyUtils.isPowerOf2(n)) { - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - actual.setDouble(n, actual.getDouble(1)); - actual.setDouble(1, 0); - for (int k = 1; k < m; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual.setDouble(idx1, actual.getDouble(idx2)); - actual.setDouble(idx1 + 1, -actual.getDouble(idx2 + 1)); - } - } else { - for (int k = 1; k < n / 2; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual.setDouble(idx1, actual.getDouble(idx2)); - actual.setDouble(idx1 + 1, -actual.getDouble(idx2 + 1)); - } - actual.setDouble(n, actual.getDouble(1)); - actual.setDouble(1, 0); - } - - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realForward(double[])}. - */ - @Test - public void testRealForwardFull() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.; - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realForward(DoubleLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(2 * i, actual.getDouble(i)); - expected.setDouble(2 * i + 1, 0.); - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverseFull(double[], boolean)} - * , with the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.; - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverseFull(DoubleLargeArray, boolean)} - * , with the second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(2 * i, actual.getDouble(i)); - expected.setDouble(2 * i + 1, 0.); - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverseFull(double[], boolean)} - * , with the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled() - { - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.; - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverseFull(DoubleLargeArray, boolean)} - * , with the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(2 * i, actual.getDouble(i)); - expected.setDouble(2 * i + 1, 0.); - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverse(double[], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testRealInverseScaled() - { - final double[] actual = new double[n]; - final double[] expected = new double[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverse(DoubleLargeArray, boolean)}, - * with the second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(n, false); - final DoubleLargeArray expected = new DoubleLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverse(double[], boolean)}, - * with the second parameter set to false. - */ - @Test - public void testRealInverseUnscaled() - { - final double[] actual = new double[n]; - final double[] expected = new double[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2. * random.nextDouble() - 1.; - expected[i] = actual[i]; - } - fft.realForward(actual); - fft.realInverse(actual, false); - double s; - if (ConcurrencyUtils.isPowerOf2(n) && n > 1) { - s = 2. / (double) n; - } else { - s = 1. / (double) n; - } - for (int i = 0; i < actual.length; i++) { - actual[i] = s * actual[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link DoubleFFT_1D#realInverse(DoubleLargeArray, boolean)}, - * with the second parameter set to false. - */ - @Test - public void testRealInverseUnscaledLarge() - { - ConcurrencyUtils.setLargeArraysBeginN(n); - final DoubleLargeArray actual = new DoubleLargeArray(n, false); - final DoubleLargeArray expected = new DoubleLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setDouble(i, 2. * random.nextDouble() - 1.); - expected.setDouble(i, actual.getDouble(i)); - } - fft.realForward(actual); - fft.realInverse(actual, false); - - double s; - if (ConcurrencyUtils.isPowerOf2(n) && n > 1) { - s = 2. / (double) n; - } else { - s = 1. / (double) n; - } - for (int i = 0; i < actual.length(); i++) { - actual.setDouble(i, s * actual.getDouble(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/DoubleFFT_2DTest.java b/src/test/java/org/jtransforms/fft/DoubleFFT_2DTest.java deleted file mode 100644 index 75814c0..0000000 --- a/src/test/java/org/jtransforms/fft/DoubleFFT_2DTest.java +++ /dev/null @@ -1,911 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * - * This is a test of the class {@link DoubleFFT_2D}. In this test, a very crude - * 2d FFT method is implemented (see {@link #complexForward(double[][])}), - * assuming that {@link DoubleFFT_1D} has been fully tested and validated. This - * crude (unoptimized) method is then used to establish expected values - * of direct Fourier transforms. - *

- * - * For inverse Fourier transforms, the test assumes that the - * corresponding direct Fourier transform has been tested and - * validated. - *

- * - * In all cases, the test consists in creating a random array of data, and - * verifying that expected and actual values of its Fourier transform coincide - * (L2 norm is zero, within a specified accuracy). - *

- * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleFFT_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -12); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * Fourier transform of the columns. - */ - private final DoubleFFT_1D cfft; - - /** - * The object to be tested. - */ - private final DoubleFFT_2D fft; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Fourier transform of the rows. - */ - private final DoubleFFT_1D rfft; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleFFT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.rfft = new DoubleFFT_1D(numColumns); - this.cfft = new DoubleFFT_1D(numRows); - this.fft = new DoubleFFT_2D(numRows, numColumns); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * A crude implementation of 2d complex FFT. - * - * @param a - * the data to be transformed - */ - public void complexForward(final double[][] a) - { - for (int r = 0; r < numRows; r++) { - rfft.complexForward(a[r]); - } - final double[] buffer = new double[2 * numRows]; - for (int c = 0; c < numCols; c++) { - for (int r = 0; r < numRows; r++) { - buffer[2 * r] = a[r][2 * c]; - buffer[2 * r + 1] = a[r][2 * c + 1]; - } - cfft.complexForward(buffer); - for (int r = 0; r < numRows; r++) { - a[r][2 * c] = buffer[2 * r]; - a[r][2 * c + 1] = buffer[2 * r + 1]; - } - } - } - - /** - * A test of {@link DoubleFFT_2D#complexForward(double[])}. - */ - @Test - public void testComplexForward1dInput() - { - final double[] actual = new double[2 * numRows * numCols]; - final double[][] expected0 = new double[numRows][2 * numCols]; - final double[] expected = new double[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[2 * r * numCols + c] = rnd; - expected0[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[2 * r * numCols + c] = expected0[r][c]; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexForward(DoubleLargeArray)}. - */ - @Test - public void testComplexForwardLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - final double[][] expected0 = new double[numRows][2 * numCols]; - final DoubleLargeArray expected = new DoubleLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(2 * r * numCols + c, rnd); - expected0[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setDouble(2 * r * numCols + c, expected0[r][c]); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexForward(double[][])}. - */ - @Test - public void testComplexForward2dInput() - { - final double[][] actual = new double[numRows][2 * numCols]; - final double[][] expected = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(double[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled1dInput() - { - final double[] expected = new double[2 * numRows * numCols]; - final double[] actual = new double[2 * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(DoubleLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() - { - final DoubleLargeArray expected = new DoubleLargeArray(2 * numRows * numCols, false); - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(double[][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled2dInput() - { - final double[][] expected = new double[numRows][2 * numCols]; - final double[][] actual = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(double[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaled1dInput() - { - final double[] expected = new double[2 * numRows * numCols]; - final double[] actual = new double[2 * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double s = numRows * numCols; - for (int i = 0; i < actual.length; i++) { - actual[i] = actual[i] / s; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(DoubleLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaledLarge() - { - final DoubleLargeArray expected = new DoubleLargeArray(2 * numRows * numCols, false); - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double s = numRows * numCols; - for (int i = 0; i < actual.length(); i++) { - actual.setDouble(i, actual.getDouble(i) / s); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#complexInverse(double[][], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaled2dInput() - { - final double[][] expected = new double[numRows][2 * numCols]; - final double[][] actual = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - expected[r][c] = rnd; - actual[r][c] = rnd; - } - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double s = numRows * numCols; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - actual[r][c] = actual[r][c] / s; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private static void fillSymmetric(final double[] a, int rows, int columns) - { - final int twon2 = 2 * columns; - int idx1, idx2, idx3, idx4; - int n1d2 = rows / 2; - - for (int r = (rows - 1); r >= 1; r--) { - idx1 = r * columns; - idx2 = 2 * idx1; - for (int c = 0; c < columns; c += 2) { - a[idx2 + c] = a[idx1 + c]; - a[idx1 + c] = 0; - a[idx2 + c + 1] = a[idx1 + c + 1]; - a[idx1 + c + 1] = 0; - } - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r) * twon2; - a[idx2 + columns] = a[idx3 + 1]; - a[idx2 + columns + 1] = -a[idx3]; - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r + 1) * twon2; - for (int c = columns + 2; c < twon2; c += 2) { - a[idx2 + c] = a[idx3 - c]; - a[idx2 + c + 1] = -a[idx3 - c + 1]; - - } - } - for (int r = 0; r <= rows / 2; r++) { - idx1 = r * twon2; - idx4 = ((rows - r) % rows) * twon2; - for (int c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a[idx3] = a[idx2]; - a[idx3 + 1] = -a[idx2 + 1]; - } - } - a[columns] = -a[1]; - a[1] = 0; - idx1 = n1d2 * twon2; - a[idx1 + columns] = -a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx1 + columns + 1] = 0; - } - - /** - * A test of {@link DoubleFFT_2D#realForward(double[])}. - */ - @Test - public void testRealForward1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final double[] actual = new double[2 * numRows * numCols]; - final double[] expected = new double[numRows * 2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r * numCols + c] = rnd; - expected[r * 2 * numCols + 2 * c] = rnd; - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private static void fillSymmetric(final DoubleLargeArray a, int rowsl, int columnsl) - { - final long twon2 = 2 * columnsl; - long idx1, idx2, idx3, idx4; - long n1d2 = rowsl / 2; - - for (long r = (rowsl - 1); r >= 1; r--) { - idx1 = r * columnsl; - idx2 = 2 * idx1; - for (long c = 0; c < columnsl; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx1 + c)); - a.setDouble(idx1 + c, 0); - a.setDouble(idx2 + c + 1, a.getDouble(idx1 + c + 1)); - a.setDouble(idx1 + c + 1, 0); - } - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r) * twon2; - a.setDouble(idx2 + columnsl, a.getDouble(idx3 + 1)); - a.setDouble(idx2 + columnsl + 1, -a.getDouble(idx3)); - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r + 1) * twon2; - for (long c = columnsl + 2; c < twon2; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx3 - c)); - a.setDouble(idx2 + c + 1, -a.getDouble(idx3 - c + 1)); - - } - } - for (long r = 0; r <= rowsl / 2; r++) { - idx1 = r * twon2; - idx4 = ((rowsl - r) % rowsl) * twon2; - for (long c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a.setDouble(idx3, a.getDouble(idx2)); - a.setDouble(idx3 + 1, -a.getDouble(idx2 + 1)); - } - } - - a.setDouble(columnsl, -a.getDouble(1)); - a.setDouble(1, 0); - idx1 = n1d2 * twon2; - a.setDouble(idx1 + columnsl, -a.getDouble(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx1 + columnsl + 1, 0); - } - - /** - * A test of {@link DoubleFFT_2D#realForward(DoubleLargeArray)}. - */ - @Test - public void testRealForwardLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numRows * 2 * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(r * numCols + c, rnd); - expected.setDouble(r * 2 * numCols + 2 * c, rnd); - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final double[][] a, int rows, int columns) - { - final int newn2 = 2 * columns; - int n1d2 = rows / 2; - - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - int idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - } - } - for (int r = 0; r <= rows / 2; r++) { - int idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c += 2) { - int idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - a[0][columns] = -a[0][1]; - a[0][1] = 0; - a[n1d2][columns] = -a[n1d2][1]; - a[n1d2][1] = 0; - a[n1d2][columns + 1] = 0; - } - - /** - * A test of {@link DoubleFFT_2D#realForward(double[][])}. - */ - @Test - public void testRealForward2dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final double[][] actual = new double[numRows][2 * numCols]; - final double[][] expected = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - expected[r][2 * c + 1] = 0.0; - } - } - fft.realForward(actual); - complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - - } - - /** - * A test of {@link DoubleFFT_2D#realForwardFull(double[])}. - */ - @Test - public void testRealForwardFull1dInput() - { - final double[] actual = new double[2 * numRows * numCols]; - final double[][] expected0 = new double[numRows][2 * numCols]; - final double[] expected = new double[numRows * 2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r * numCols + c] = rnd; - expected0[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[2 * r * numCols + c] = expected0[r][c]; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link DoubleFFT_2D#realForwardFull(DoubleLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - final double[][] expected0 = new double[numRows][2 * numCols]; - final DoubleLargeArray expected = new DoubleLargeArray(numRows * 2 * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual.setDouble(r * numCols + c, rnd); - expected0[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setDouble(2 * r * numCols + c, expected0[r][c]); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link DoubleFFT_2D#realForwardFull(double[][])}. - */ - @Test - public void testRealForwardFull2dInput() - { - final double[][] actual = new double[numRows][2 * numCols]; - final double[][] expected = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(double[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled1dInput() - { - final double[] actual = new double[2 * numRows * numCols]; - final double[] expected = new double[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - final int index = r * numCols + c; - actual[index] = rnd; - expected[2 * index] = rnd; - } - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(DoubleLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - final int index = r * numCols + c; - actual.setDouble(index, rnd); - expected.setDouble(2 * index, rnd); - } - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(double[][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled2dInput() - { - final double[][] actual = new double[numRows][2 * numCols]; - final double[][] expected = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(double[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled1dInput() - { - final double[] actual = new double[2 * numRows * numCols]; - final double[] expected = new double[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - final int index = r * numCols + c; - actual[index] = rnd; - expected[2 * index] = rnd; - } - } - fft.complexInverse(expected, false); - fft.realInverseFull(actual, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(DoubleLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaledLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(2 * numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - final int index = r * numCols + c; - actual.set(index, rnd); - expected.setDouble(2 * index, rnd); - } - } - fft.complexInverse(expected, false); - fft.realInverseFull(actual, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link DoubleFFT_2D#realInverseFull(double[][], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled2dInput() - { - final double[][] actual = new double[numRows][2 * numCols]; - final double[][] expected = new double[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverse(double[], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final double[] actual = new double[numRows * numCols]; - final double[] expected = new double[actual.length]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link DoubleFFT_2D#realInverse(DoubleLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final DoubleLargeArray actual = new DoubleLargeArray(numRows * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(actual.length(), false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_2D#realInverse(double[][], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled2dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final double[][] actual = new double[numRows][numCols]; - final double[][] expected = new double[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/DoubleFFT_3DTest.java b/src/test/java/org/jtransforms/fft/DoubleFFT_3DTest.java deleted file mode 100644 index 120280b..0000000 --- a/src/test/java/org/jtransforms/fft/DoubleFFT_3DTest.java +++ /dev/null @@ -1,1078 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; - -/** - * - * This is a test of the class {@link DoubleFFT_3D}. In this test, a very crude - * 3d FFT method is implemented (see {@link #complexForward(double[][][])}), - * assuming that {@link DoubleFFT_1D} and {@link DoubleFFT_2D} have been fully - * tested and validated. This crude (unoptimized) method is then used to - * establish expected values of direct Fourier transforms. - *

- * - * For inverse Fourier transforms, the test assumes that the - * corresponding direct Fourier transform has been tested and - * validated. - *

- * - * In all cases, the test consists in creating a random array of data, and - * verifying that expected and actual values of its Fourier transform coincide - * within a specified accuracy. - *

- * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class DoubleFFT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110625; - - private static final double EPS = Math.pow(10, -9); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The object to be tested. - */ - private final DoubleFFT_3D fft; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Fourier transform of the slices. - */ - private final DoubleFFT_2D sfft; - - /** - * Fourier transform in the first direction (perpendicular to slices). - */ - private final DoubleFFT_1D xfft; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public DoubleFFT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.fft = new DoubleFFT_3D(numSlices, numRows, numColumns); - this.xfft = new DoubleFFT_1D(numSlices); - this.sfft = new DoubleFFT_2D(numRows, numColumns); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(4); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * A crude implementation of 3d complex FFT. - * - * @param a - * the data to be transformed - */ - public void complexForward(final double[][][] a) - { - for (int s = 0; s < numSlices; s++) { - sfft.complexForward(a[s]); - } - final double[] buffer = new double[2 * numSlices]; - for (int c = 0; c < numCols; c++) { - for (int r = 0; r < numRows; r++) { - for (int s = 0; s < numSlices; s++) { - buffer[2 * s] = a[s][r][2 * c]; - buffer[2 * s + 1] = a[s][r][2 * c + 1]; - } - xfft.complexForward(buffer); - for (int s = 0; s < numSlices; s++) { - a[s][r][2 * c] = buffer[2 * s]; - a[s][r][2 * c + 1] = buffer[2 * s + 1]; - } - } - } - } - - /** - * A test of {@link DoubleFFT_3D#complexForward(double[])}. - */ - @Test - public void testComplexForward1dInput() - { - final double[] actual = new double[2 * numSlices * numRows * numCols]; - final double[][][] expected0 = new double[numSlices][numRows][2 * numCols]; - final double[] expected = new double[2 * numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final int index = 2 * numCols * (r + numRows * s) + c; - final double rnd = random.nextDouble(); - actual[index] = rnd; - expected0[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[s * 2 * numRows * numCols + r * 2 * numCols + c] = expected0[s][r][c]; - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexForward(DoubleLargeArray)}. - */ - @Test - public void testComplexForwardLarge() - { - final DoubleLargeArray actual = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - final double[][][] expected0 = new double[numSlices][numRows][2 * numCols]; - final DoubleLargeArray expected = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final int index = 2 * numCols * (r + numRows * s) + c; - final double rnd = random.nextDouble(); - actual.setDouble(index, rnd); - expected0[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setDouble(s * 2 * numRows * numCols + r * 2 * numCols + c, expected0[s][r][c]); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexForward(double[][][])}. - */ - @Test - public void testComplexForward3dInput() - { - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(double[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled1dInput() - { - final double[] expected = new double[2 * numSlices * numRows * numCols]; - final double[] actual = new double[2 * numSlices * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(DoubleLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() - { - final DoubleLargeArray expected = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - final DoubleLargeArray actual = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(double[][][], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testComplexInverseScaled3dInput() - { - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(double[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled1dInput() - { - final double[] expected = new double[2 * numSlices * numRows * numCols]; - final double[] actual = new double[2 * numSlices * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double scaling = numSlices * numRows * numCols; - for (int i = 0; i < actual.length; i++) { - expected[i] = scaling * expected[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(DoubleLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaledLarge() - { - final DoubleLargeArray expected = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - final DoubleLargeArray actual = new DoubleLargeArray(2 * numSlices * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double scaling = numSlices * numRows * numCols; - for (int i = 0; i < actual.length(); i++) { - expected.setDouble(i, scaling * expected.getDouble(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#complexInverse(double[][][], boolean)}, - * with the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled3dInput() - { - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final double scaling = numSlices * numRows * numCols; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[s][r][c] = scaling * expected[s][r][c]; - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final double[] a, int slices, int rows, int columns) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - int sliceStride = rows * columns; - int rowStride = columns; - - final int twoSliceStride = rows * twon3; - final int twoRowStride = twon3; - - int idx1, idx2, idx3, idx4, idx5, idx6; - - for (int s = (slices - 1); s >= 1; s--) { - idx3 = s * sliceStride; - idx4 = 2 * idx3; - for (int r = 0; r < rows; r++) { - idx5 = r * rowStride; - idx6 = 2 * idx5; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - } - - for (int r = 1; r < rows; r++) { - idx3 = (rows - r) * rowStride; - idx4 = (rows - r) * twoRowStride; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - - // ----------------------------------------------- - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx5 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - idx4 = ((rows - r) % rows) * twoRowStride; - idx6 = r * twoRowStride; - for (int c = 1; c < columns; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a[idx1] = -a[idx2 + 2]; - a[idx1 - 1] = a[idx2 + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - idx5 = ((slices - s) % slices) * twoSliceStride; - idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx4 = idx6 + (rows - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columns; - idx2 = idx4 + columns; - idx3 = idx4 + 1; - a[idx1] = a[idx3]; - a[idx2] = a[idx3]; - a[idx1 + 1] = -a[idx4]; - a[idx2 + 1] = a[idx4]; - - } - } - - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx4 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx1 = idx3 + (rows - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - - } - } - - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slices - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a[idx1 + columns] = a[idx2 + 1]; - a[idx2 + columns] = a[idx2 + 1]; - a[idx1 + columns + 1] = -a[idx2]; - a[idx2 + columns + 1] = a[idx2]; - a[idx4 + columns] = a[idx5 + 1]; - a[idx5 + columns] = a[idx5 + 1]; - a[idx4 + columns + 1] = -a[idx5]; - a[idx5 + columns + 1] = a[idx5]; - a[idx2] = a[idx1]; - a[idx2 + 1] = -a[idx1 + 1]; - a[idx5] = a[idx4]; - a[idx5 + 1] = -a[idx4 + 1]; - - } - - // ---------------------------------------- - a[columns] = a[1]; - a[1] = 0; - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a[idx1 + columns] = a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx2 + columns] = a[idx2 + 1]; - a[idx2 + 1] = 0; - a[idx3 + columns] = a[idx3 + 1]; - a[idx3 + 1] = 0; - a[idx2 + columns + 1] = 0; - a[idx3 + columns + 1] = 0; - } - - /** - * A test of {@link DoubleFFT_3D#realForward(double[])}. - */ - @Test - public void testRealForward1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - int index; - final double[] actual = new double[numSlices * numRows * 2 * numCols]; - final double[] expected = new double[numSlices * numRows * 2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - index = c + numCols * (r + numRows * s); - final double rnd = random.nextDouble(); - actual[index] = rnd; - expected[s * 2 * numRows * numCols + r * 2 * numCols + 2 * c] = rnd; - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final DoubleLargeArray a, long slicesl, int rowsl, long columnsl) - { - final long twon3 = 2 * columnsl; - final long n2d2 = rowsl / 2; - long n1d2 = slicesl / 2; - - final long twoSliceStride = rowsl * twon3; - final long twoRowStride = twon3; - - long idx1, idx2, idx3, idx4, idx5, idx6; - - final long sliceStridel = rowsl * columnsl; - final long rowStridel = columnsl; - - for (long s = (slicesl - 1); s >= 1; s--) { - idx3 = s * sliceStridel; - idx4 = 2 * idx3; - for (long r = 0; r < rowsl; r++) { - idx5 = r * rowStridel; - idx6 = 2 * idx5; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - idx1++; - idx2++; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - } - } - } - - for (long r = 1; r < rowsl; r++) { - idx3 = (rowsl - r) * rowStridel; - idx4 = (rowsl - r) * twoRowStride; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - idx1++; - idx2++; - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx1, 0); - } - } - - // ----------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx5 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - idx4 = ((rowsl - r) % rowsl) * twoRowStride; - idx6 = r * twoRowStride; - for (long c = 1; c < columnsl; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a.setDouble(idx1, -a.getDouble(idx2 + 2)); - a.setDouble(idx1 - 1, a.getDouble(idx2 + 1)); - } - } - } - - // --------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx5 = ((slicesl - s) % slicesl) * twoSliceStride; - idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx4 = idx6 + (rowsl - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columnsl; - idx2 = idx4 + columnsl; - idx3 = idx4 + 1; - a.setDouble(idx1, a.getDouble(idx3)); - a.setDouble(idx2, a.getDouble(idx3)); - a.setDouble(idx1 + 1, -a.getDouble(idx4)); - a.setDouble(idx2 + 1, a.getDouble(idx4)); - - } - } - - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx4 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx1 = idx3 + (rowsl - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a.setDouble(idx1, a.getDouble(idx2)); - a.setDouble(idx1 + 1, -a.getDouble(idx2 + 1)); - - } - } - - // ---------------------------------------------------------- - for (long s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slicesl - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a.setDouble(idx1 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx2 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx1 + columnsl + 1, -a.getDouble(idx2)); - a.setDouble(idx2 + columnsl + 1, a.getDouble(idx2)); - a.setDouble(idx4 + columnsl, a.getDouble(idx5 + 1)); - a.setDouble(idx5 + columnsl, a.getDouble(idx5 + 1)); - a.setDouble(idx4 + columnsl + 1, -a.getDouble(idx5)); - a.setDouble(idx5 + columnsl + 1, a.getDouble(idx5)); - a.setDouble(idx2, a.getDouble(idx1)); - a.setDouble(idx2 + 1, -a.getDouble(idx1 + 1)); - a.setDouble(idx5, a.getDouble(idx4)); - a.setDouble(idx5 + 1, -a.getDouble(idx4 + 1)); - - } - - // ---------------------------------------- - a.setDouble(columnsl, a.getDouble(1)); - a.setDouble(1, 0); - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a.setDouble(idx1 + columnsl, a.getDouble(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx2 + columnsl, a.getDouble(idx2 + 1)); - a.setDouble(idx2 + 1, 0); - a.setDouble(idx3 + columnsl, a.getDouble(idx3 + 1)); - a.setDouble(idx3 + 1, 0); - a.setDouble(idx2 + columnsl + 1, 0); - a.setDouble(idx3 + columnsl + 1, 0); - } - - /** - * A test of {@link DoubleFFT_3D#realForward(DoubleLargeArray)}. - */ - @Test - public void testRealForwardLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - int index; - final DoubleLargeArray actual = new DoubleLargeArray(numSlices * numRows * 2 * numCols, false); - final DoubleLargeArray expected = new DoubleLargeArray(numSlices * numRows * 2 * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - index = c + numCols * (r + numRows * s); - final double rnd = random.nextDouble(); - actual.setDouble(index, rnd); - expected.setDouble(s * 2 * numRows * numCols + r * 2 * numCols + 2 * c, rnd); - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final double[][][] a, int slices, int rows, int columns) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 0; r < rows; r++) { - int idx2 = (rows - r) % rows; - for (int c = 1; c < columns; c += 2) { - int idx3 = twon3 - c; - a[idx1][idx2][idx3] = -a[s][r][c + 2]; - a[idx1][idx2][idx3 - 1] = a[s][r][c + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][r][columns] = a[s][idx2][1]; - a[s][idx2][columns] = a[s][idx2][1]; - a[idx1][r][columns + 1] = -a[s][idx2][0]; - a[s][idx2][columns + 1] = a[s][idx2][0]; - } - } - - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][idx2][0] = a[s][r][0]; - a[idx1][idx2][1] = -a[s][r][1]; - } - } - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - int idx1 = slices - s; - a[s][0][columns] = a[idx1][0][1]; - a[idx1][0][columns] = a[idx1][0][1]; - a[s][0][columns + 1] = -a[idx1][0][0]; - a[idx1][0][columns + 1] = a[idx1][0][0]; - a[s][n2d2][columns] = a[idx1][n2d2][1]; - a[idx1][n2d2][columns] = a[idx1][n2d2][1]; - a[s][n2d2][columns + 1] = -a[idx1][n2d2][0]; - a[idx1][n2d2][columns + 1] = a[idx1][n2d2][0]; - a[idx1][0][0] = a[s][0][0]; - a[idx1][0][1] = -a[s][0][1]; - a[idx1][n2d2][0] = a[s][n2d2][0]; - a[idx1][n2d2][1] = -a[s][n2d2][1]; - - } - // ---------------------------------------- - - a[0][0][columns] = a[0][0][1]; - a[0][0][1] = 0; - a[0][n2d2][columns] = a[0][n2d2][1]; - a[0][n2d2][1] = 0; - a[n1d2][0][columns] = a[n1d2][0][1]; - a[n1d2][0][1] = 0; - a[n1d2][n2d2][columns] = a[n1d2][n2d2][1]; - a[n1d2][n2d2][1] = 0; - a[n1d2][0][columns + 1] = 0; - a[n1d2][n2d2][columns + 1] = 0; - } - - /** - * A test of {@link DoubleFFT_3D#realForward(double[][][])}. - */ - @Test - public void testRealForward3dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverse(double[], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final double[] actual = new double[numRows * numCols * numSlices]; - final double[] expected = new double[actual.length]; - for (int i = 0; i < actual.length; i++) { - final double rnd = random.nextDouble(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverse(DoubleLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final DoubleLargeArray actual = new DoubleLargeArray(numRows * numCols * numSlices, false); - final DoubleLargeArray expected = new DoubleLargeArray(actual.length(), false); - for (int i = 0; i < actual.length(); i++) { - final double rnd = random.nextDouble(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverse(double[][][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseScaled3dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final double[][][] actual = new double[numSlices][numRows][numCols]; - final double[][][] expected = new double[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realForwardFull(double[])}. - */ - @Test - public void testRealForwardFull1dInput() - { - final int n = numSlices * numRows * numCols; - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int index = 0; index < n; index++) { - final double rnd = random.nextDouble(); - actual[index] = rnd; - expected[2 * index] = rnd; - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realForwardFull(DoubleLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() - { - final int n = numSlices * numRows * numCols; - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int index = 0; index < n; index++) { - final double rnd = random.nextDouble(); - actual.setDouble(index, rnd); - expected.setDouble(2 * index, rnd); - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realForwardFull(double[][][]). - */ - @Test - public void testRealForwardFull3dInput() - { - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverseFull(double[], boolean)} with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled1dInput() - { - final int n = numSlices * numRows * numCols; - final double[] actual = new double[2 * n]; - final double[] expected = new double[2 * n]; - for (int index = 0; index < n; index++) { - final double rnd = random.nextDouble(); - actual[index] = rnd; - expected[2 * index] = rnd; - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverseFull(DoubleLargeArray, boolean)} with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() - { - final int n = numSlices * numRows * numCols; - final DoubleLargeArray actual = new DoubleLargeArray(2 * n, false); - final DoubleLargeArray expected = new DoubleLargeArray(2 * n, false); - for (int index = 0; index < n; index++) { - final double rnd = random.nextDouble(); - actual.setDouble(index, rnd); - expected.setDouble(2 * index, rnd); - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link DoubleFFT_3D#realInverseFull(double[][][], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled3dInput() - { - final double[][][] actual = new double[numSlices][numRows][2 * numCols]; - final double[][][] expected = new double[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final double rnd = random.nextDouble(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/FloatFFT_1DTest.java b/src/test/java/org/jtransforms/fft/FloatFFT_1DTest.java deleted file mode 100644 index febdee1..0000000 --- a/src/test/java/org/jtransforms/fft/FloatFFT_1DTest.java +++ /dev/null @@ -1,616 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * This is a series of JUnit tests for the {@link FloatFFT_1D}. First, - * {@link FloatFFT_1D#complexForward(float[])} is tested by comparison with - * reference data (FFTW). Then the other methods of this class are tested using - * {@link FloatFFT_1D#complexForward(float[])} as a reference. - * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatFFT_1DTest { - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %d: "; - - /** - * Name of binary files (input, untransformed data). - */ - private final static String FFTW_INPUT_PATTERN = "fftw%d.in"; - - /** - * Name of binary files (output, transformed data). - */ - private final static String FFTW_OUTPUT_PATTERN = "fftw%d.out"; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -4); - - @Parameters - public static Collection getParameters() { - final int[] size = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 512, 1024, 1056, 2048, 8192, - 10158, 16384, 32768, 65530, 65536, 131072}; - - final ArrayList parameters = new ArrayList(); - for (int i = 0; i < size.length; i++) { - parameters.add(new Object[]{size[i], 1, SEED}); - parameters.add(new Object[]{size[i], 2, SEED}); - parameters.add(new Object[]{size[i], 4, SEED}); - } - return parameters; - } - - /** - * The FFT to be tested. - */ - private final FloatFFT_1D fft; - - /** - * The size of the FFT to be tested. - */ - private final int n; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Creates a new instance of this class. - * - * @param n the size of the FFT to be tested - * @param numThreads the number of threads - * @param seed the seed of the random generator - */ - public FloatFFT_1DTest(final int n, final int numThreads, final long seed) { - this.n = n; - this.fft = new FloatFFT_1D(n); - this.random = new Random(seed); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_2Threads(1024); - ConcurrencyUtils.setThreadsBeginN_1D_FFT_4Threads(1024); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * Read the binary reference data files generated with FFTW. The structure - * of these files is very simple: double values are written linearly (little - * endian). - * - * @param name the file name - * @param data the array to be updated with the data read (the size of this - * array gives the number of double to be retrieved - */ - public void readData(final String name, final double[] data) { - try { - final File f = new File(getClass().getClassLoader() - .getResource(name).getFile()); - final FileInputStream fin = new FileInputStream(f); - final FileChannel fc = fin.getChannel(); - final ByteBuffer buffer = ByteBuffer.allocate(8 * data.length); - buffer.order(ByteOrder.LITTLE_ENDIAN); - fc.read(buffer); - for (int i = 0; i < data.length; i++) { - data[i] = buffer.getDouble(8 * i); - } - } catch (IOException e) { - Assert.fail(e.getMessage()); - } - } - - /** - * Read the binary reference data files generated with FFTW. The structure - * of these files is very simple: double values are written linearly (little - * endian). - * - * @param name the file name - * @param data the array to be updated with the data read (the size of this - * array gives the number of double to be retrieved - */ - public void readData(final String name, final DoubleLargeArray data) { - try { - final File f = new File(getClass().getClassLoader() - .getResource(name).getFile()); - final FileInputStream fin = new FileInputStream(f); - final FileChannel fc = fin.getChannel(); - final ByteBuffer buffer = ByteBuffer.allocate(8 * (int) data.length()); - buffer.order(ByteOrder.LITTLE_ENDIAN); - fc.read(buffer); - for (int i = 0; i < data.length(); i++) { - data.setDouble(i, buffer.getDouble(8 * i)); - } - } catch (IOException e) { - Assert.fail(e.getMessage()); - } - } - - /** - * This is a test of {@link FloatFFT_1D#complexForward(float[])}. This - * method is tested by computation of the FFT of some pre-generated data, - * and comparison with results obtained with FFTW. - */ - @Test - public void testComplexForward() { - final float[] actual = new float[2 * n]; - final double[] expected0 = new double[2 * n]; - readData(String.format(FFTW_INPUT_PATTERN, n), expected0); - for (int index = 0; index < actual.length; index++) { - actual[index] = (float) expected0[index]; - } - readData(String.format(FFTW_OUTPUT_PATTERN, n), expected0); - final float[] expected = new float[2 * n]; - for (int index = 0; index < expected.length; index++) { - expected[index] = (float) expected0[index]; - } - fft.complexForward(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#complexForward(FloatLargeArray)}. - * This method is tested by computation of the FFT of some pre-generated - * data, and comparison with results obtained with FFTW. - */ - @Test - public void testComplexForwardLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final DoubleLargeArray expected0 = new DoubleLargeArray(2 * n, false); - readData(String.format(FFTW_INPUT_PATTERN, n), expected0); - for (int index = 0; index < actual.length(); index++) { - actual.setFloat(index, expected0.getFloat(index)); - } - readData(String.format(FFTW_OUTPUT_PATTERN, n), expected0); - final FloatLargeArray expected = new FloatLargeArray(2 * n); - for (int index = 0; index < expected.length(); index++) { - expected.setFloat(index, expected0.getFloat(index)); - } - fft.complexForward(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#complexInverse(float[], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testComplexInverseScaled() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < 2 * n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#complexInverse(FloatLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < 2 * n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#complexInverse(float[], boolean)}, - * with the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < 2 * n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float s = 1.f / (float) n; - for (int i = 0; i < actual.length; i++) { - actual[i] = s * actual[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#complexInverse(FloatLargeArray, boolean)}, with the - * second parameter set to false. - */ - @Test - public void testComplexInverseUnscaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < 2 * n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float s = 1.f / (float) n; - for (int i = 0; i < actual.length(); i++) { - actual.setFloat(i, s * actual.getFloat(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realForward(float[])}. - */ - @Test - public void testRealForward() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.f; - } - fft.complexForward(expected); - fft.realForward(actual); - if (!ConcurrencyUtils.isPowerOf2(n)) { - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - actual[n] = actual[1]; - actual[1] = 0; - for (int k = 1; k < m; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual[idx1] = actual[idx2]; - actual[idx1 + 1] = -actual[idx2 + 1]; - } - } else { - for (int k = 1; k < n / 2; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual[idx1] = actual[idx2]; - actual[idx1 + 1] = -actual[idx2 + 1]; - } - actual[n] = actual[1]; - actual[1] = 0; - } - - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realForward(FloatLargeArray)}. - */ - @Test - public void testRealForwardLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(2 * i, actual.getFloat(i)); - expected.setFloat(2 * i + 1, 0.0f); - } - fft.complexForward(expected); - fft.realForward(actual); - if (!ConcurrencyUtils.isPowerOf2(n)) { - int m; - if (n % 2 == 0) { - m = n / 2; - } else { - m = (n + 1) / 2; - } - actual.setFloat(n, actual.getFloat(1)); - actual.setFloat(1, 0); - for (int k = 1; k < m; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual.setFloat(idx1, actual.getFloat(idx2)); - actual.setFloat(idx1 + 1, -actual.getFloat(idx2 + 1)); - } - } else { - for (int k = 1; k < n / 2; k++) { - int idx1 = 2 * n - 2 * k; - int idx2 = 2 * k; - actual.setFloat(idx1, actual.getFloat(idx2)); - actual.setFloat(idx1 + 1, -actual.getFloat(idx2 + 1)); - } - actual.setFloat(n, actual.getFloat(1)); - actual.setFloat(1, 0); - } - - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realForward(float[])}. - */ - @Test - public void testRealForwardFull() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.f; - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realForward(FloatLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(2 * i, actual.getFloat(i)); - expected.setFloat(2 * i + 1, 0.0f); - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realInverseFull(float[], boolean)} , - * with the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.f; - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#realInverseFull(FloatLargeArray, boolean)} , with the - * second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(2 * i, actual.getFloat(i)); - expected.setFloat(2 * i + 1, 0.0f); - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realInverseFull(float[], boolean)} , - * with the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled() { - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[2 * i] = actual[i]; - expected[2 * i + 1] = 0.f; - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#realInverseFull(FloatLargeArray, boolean)} , with the - * second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(2 * i, actual.getFloat(i)); - expected.setFloat(2 * i + 1, 0.0f); - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realInverse(float[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseScaled() { - final float[] actual = new float[n]; - final float[] expected = new float[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#realInverse(FloatLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(n, false); - final FloatLargeArray expected = new FloatLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of {@link FloatFFT_1D#realInverse(float[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseUnscaled() { - final float[] actual = new float[n]; - final float[] expected = new float[n]; - for (int i = 0; i < n; i++) { - actual[i] = 2.f * random.nextFloat() - 1.f; - expected[i] = actual[i]; - } - fft.realForward(actual); - fft.realInverse(actual, false); - float s; - if (ConcurrencyUtils.isPowerOf2(n) && n > 1) { - s = 2.f / (float) n; - } else { - s = 1.f / (float) n; - } - for (int i = 0; i < actual.length; i++) { - actual[i] = s * actual[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * This is a test of - * {@link FloatFFT_1D#realInverse(FloatLargeArray, boolean)}, with the - * second parameter set to false. - */ - @Test - public void testRealInverseUnscaledLarge() { - ConcurrencyUtils.setLargeArraysBeginN(n); - final FloatLargeArray actual = new FloatLargeArray(n, false); - final FloatLargeArray expected = new FloatLargeArray(n, false); - for (int i = 0; i < n; i++) { - actual.setFloat(i, 2.f * random.nextFloat() - 1.f); - expected.setFloat(i, actual.getFloat(i)); - } - fft.realForward(actual); - fft.realInverse(actual, false); - float s; - if (ConcurrencyUtils.isPowerOf2(n) && n > 1) { - s = 2.f / (float) n; - } else { - s = 1.f / (float) n; - } - for (int i = 0; i < actual.length(); i++) { - actual.setFloat(i, s * actual.getFloat(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, n) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/FloatFFT_2DTest.java b/src/test/java/org/jtransforms/fft/FloatFFT_2DTest.java deleted file mode 100644 index d25cc93..0000000 --- a/src/test/java/org/jtransforms/fft/FloatFFT_2DTest.java +++ /dev/null @@ -1,918 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * - * This is a test of the class {@link FloatFFT_2D}. In this test, a very crude - * 2d FFT method is implemented (see {@link #complexForward(float[][])}), - * assuming that {@link FloatFFT_1D} has been fully tested and validated. This - * crude (unoptimized) method is then used to establish expected values - * of direct Fourier transforms. - *

- * - * For inverse Fourier transforms, the test assumes that the - * corresponding direct Fourier transform has been tested and - * validated. - *

- * - * In all cases, the test consists in creating a random array of data, and - * verifying that expected and actual values of its Fourier transform coincide - * (L2 norm is zero, within a specified accuracy). - *

- * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatFFT_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110602; - - private static final double EPS = Math.pow(10, -3); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 120, 128, 256, 310, 511, 512, 1024}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * Fourier transform of the columns. - */ - private final FloatFFT_1D cfft; - - /** - * The object to be tested. - */ - private final FloatFFT_2D fft; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Fourier transform of the rows. - */ - private final FloatFFT_1D rfft; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatFFT_2DTest(final int numRows, final int numColumns, - final int numThreads, final long seed) - { - this.numRows = numRows; - this.numCols = numColumns; - this.rfft = new FloatFFT_1D(numColumns); - this.cfft = new FloatFFT_1D(numRows); - this.fft = new FloatFFT_2D(numRows, numColumns); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_2D(4); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * A crude implementation of 2d complex FFT. - * - * @param a - * the data to be transformed - */ - public void complexForward(final float[][] a) - { - for (int r = 0; r < numRows; r++) { - rfft.complexForward(a[r]); - } - final float[] buffer = new float[2 * numRows]; - for (int c = 0; c < numCols; c++) { - for (int r = 0; r < numRows; r++) { - buffer[2 * r] = a[r][2 * c]; - buffer[2 * r + 1] = a[r][2 * c + 1]; - } - cfft.complexForward(buffer); - for (int r = 0; r < numRows; r++) { - a[r][2 * c] = buffer[2 * r]; - a[r][2 * c + 1] = buffer[2 * r + 1]; - } - } - } - - /** - * A test of {@link FloatFFT_2D#complexForward(float[])}. - */ - @Test - public void testComplexForward1dInput() - { - final float[] actual = new float[2 * numRows * numCols]; - final float[][] expected0 = new float[numRows][2 * numCols]; - final float[] expected = new float[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[2 * r * numCols + c] = rnd; - expected0[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[2 * r * numCols + c] = expected0[r][c]; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexForward(FloatLargeArray)}. - */ - @Test - public void testComplexForwardLarge() - { - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - final float[][] expected0 = new float[numRows][2 * numCols]; - final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual.setDouble(2 * r * numCols + c, rnd); - expected0[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setDouble(2 * r * numCols + c, expected0[r][c]); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexForward(float[][])}. - */ - @Test - public void testComplexForward2dInput() - { - final float[][] actual = new float[numRows][2 * numCols]; - final float[][] expected = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.complexForward(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(float[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled1dInput() - { - final float[] expected = new float[2 * numRows * numCols]; - final float[] actual = new float[2 * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(FloatLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() - { - final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false); - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(float[][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled2dInput() - { - final float[][] expected = new float[numRows][2 * numCols]; - final float[][] actual = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(float[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaled1dInput() - { - final float[] expected = new float[2 * numRows * numCols]; - final float[] actual = new float[2 * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float s = numRows * numCols; - for (int i = 0; i < actual.length; i++) { - actual[i] = actual[i] / s; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(FloatLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaledLarge() - { - final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false); - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float s = numRows * numCols; - for (int i = 0; i < actual.length(); i++) { - actual.setDouble(i, actual.getDouble(i) / s); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#complexInverse(float[][], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnScaled2dInput() - { - final float[][] expected = new float[numRows][2 * numCols]; - final float[][] actual = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - expected[r][c] = rnd; - actual[r][c] = rnd; - } - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float s = numRows * numCols; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - actual[r][c] = actual[r][c] / s; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private static void fillSymmetric(final float[] a, int rows, int columns) - { - final int twon2 = 2 * columns; - int idx1, idx2, idx3, idx4; - int n1d2 = rows / 2; - - for (int r = (rows - 1); r >= 1; r--) { - idx1 = r * columns; - idx2 = 2 * idx1; - for (int c = 0; c < columns; c += 2) { - a[idx2 + c] = a[idx1 + c]; - a[idx1 + c] = 0; - a[idx2 + c + 1] = a[idx1 + c + 1]; - a[idx1 + c + 1] = 0; - } - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r) * twon2; - a[idx2 + columns] = a[idx3 + 1]; - a[idx2 + columns + 1] = -a[idx3]; - } - - for (int r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rows - r + 1) * twon2; - for (int c = columns + 2; c < twon2; c += 2) { - a[idx2 + c] = a[idx3 - c]; - a[idx2 + c + 1] = -a[idx3 - c + 1]; - - } - } - for (int r = 0; r <= rows / 2; r++) { - idx1 = r * twon2; - idx4 = ((rows - r) % rows) * twon2; - for (int c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a[idx3] = a[idx2]; - a[idx3 + 1] = -a[idx2 + 1]; - } - } - a[columns] = -a[1]; - a[1] = 0; - idx1 = n1d2 * twon2; - a[idx1 + columns] = -a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx1 + columns + 1] = 0; - } - - /** - * A test of {@link FloatFFT_2D#realForward(float[])}. - */ - @Test - public void testRealForward1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final float[] actual = new float[2 * numRows * numCols]; - final float[] expected = new float[numRows * 2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r * numCols + c] = rnd; - expected[r * 2 * numCols + 2 * c] = rnd; - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private static void fillSymmetric(final FloatLargeArray a, int rowsl, int columnsl) - { - final long twon2 = 2 * columnsl; - long idx1, idx2, idx3, idx4; - long n1d2 = rowsl / 2; - - for (long r = (rowsl - 1); r >= 1; r--) { - idx1 = r * columnsl; - idx2 = 2 * idx1; - for (long c = 0; c < columnsl; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx1 + c)); - a.setDouble(idx1 + c, 0); - a.setDouble(idx2 + c + 1, a.getDouble(idx1 + c + 1)); - a.setDouble(idx1 + c + 1, 0); - } - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r) * twon2; - a.setDouble(idx2 + columnsl, a.getDouble(idx3 + 1)); - a.setDouble(idx2 + columnsl + 1, -a.getDouble(idx3)); - } - - for (long r = 1; r < n1d2; r++) { - idx2 = r * twon2; - idx3 = (rowsl - r + 1) * twon2; - for (long c = columnsl + 2; c < twon2; c += 2) { - a.setDouble(idx2 + c, a.getDouble(idx3 - c)); - a.setDouble(idx2 + c + 1, -a.getDouble(idx3 - c + 1)); - - } - } - for (long r = 0; r <= rowsl / 2; r++) { - idx1 = r * twon2; - idx4 = ((rowsl - r) % rowsl) * twon2; - for (long c = 0; c < twon2; c += 2) { - idx2 = idx1 + c; - idx3 = idx4 + (twon2 - c) % twon2; - a.setDouble(idx3, a.getDouble(idx2)); - a.setDouble(idx3 + 1, -a.getDouble(idx2 + 1)); - } - } - - a.setDouble(columnsl, -a.getDouble(1)); - a.setDouble(1, 0); - idx1 = n1d2 * twon2; - a.setDouble(idx1 + columnsl, -a.getDouble(idx1 + 1)); - a.setDouble(idx1 + 1, 0); - a.setDouble(idx1 + columnsl + 1, 0); - } - - /** - * A test of {@link FloatFFT_2D#realForward(FloatLargeArray)}. - */ - @Test - public void testRealForwardLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numRows * 2 * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setDouble(r * numCols + c, rnd); - expected.setDouble(r * 2 * numCols + 2 * c, rnd); - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final float[][] a, int rows, int columns) - { - final int newn2 = 2 * columns; - int n1d2 = rows / 2; - - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - a[r][columns] = a[idx1][1]; - a[r][columns + 1] = -a[idx1][0]; - } - for (int r = 1; r < n1d2; r++) { - int idx1 = rows - r; - for (int c = columns + 2; c < newn2; c += 2) { - int idx2 = newn2 - c; - a[r][c] = a[idx1][idx2]; - a[r][c + 1] = -a[idx1][idx2 + 1]; - } - } - for (int r = 0; r <= rows / 2; r++) { - int idx1 = (rows - r) % rows; - for (int c = 0; c < newn2; c += 2) { - int idx2 = (newn2 - c) % newn2; - a[idx1][idx2] = a[r][c]; - a[idx1][idx2 + 1] = -a[r][c + 1]; - } - } - a[0][columns] = -a[0][1]; - a[0][1] = 0; - a[n1d2][columns] = -a[n1d2][1]; - a[n1d2][1] = 0; - a[n1d2][columns + 1] = 0; - } - - /** - * A test of {@link FloatFFT_2D#realForward(float[][])}. - */ - @Test - public void testRealForward2dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final float[][] actual = new float[numRows][2 * numCols]; - final float[][] expected = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realForward(actual); - complexForward(expected); - fillSymmetric(actual, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - - } - - /** - * A test of {@link FloatFFT_2D#realForwardFull(float[])}. - */ - @Test - public void testRealForwardFull1dInput() - { - final float[] actual = new float[2 * numRows * numCols]; - final float[][] expected0 = new float[numRows][2 * numCols]; - final float[] expected = new float[numRows * 2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r * numCols + c] = rnd; - expected0[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[2 * r * numCols + c] = expected0[r][c]; - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link FloatFFT_2D#realForwardFull(FloatLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() - { - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - final float[][] expected0 = new float[numRows][2 * numCols]; - final FloatLargeArray expected = new FloatLargeArray(numRows * 2 * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual.setDouble(r * numCols + c, rnd); - expected0[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected0); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setDouble(2 * r * numCols + c, expected0[r][c]); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link FloatFFT_2D#realForwardFull(float[][])}. - */ - @Test - public void testRealForwardFull2dInput() - { - final float[][] actual = new float[numRows][2 * numCols]; - final float[][] expected = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realForwardFull(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverseFull(float[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled1dInput() - { - final float[] actual = new float[2 * numRows * numCols]; - final float[] expected = new float[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - final int index = r * numCols + c; - actual[index] = rnd; - expected[2 * index] = rnd; - } - } - // TODO If the two following lines are permuted, this causes an array - // index out of bounds exception. - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverseFull(FloatLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - final int index = r * numCols + c; - actual.setDouble(index, rnd); - expected.setDouble(2 * index, rnd); - } - } - // TODO If the two following lines are permuted, this causes an array - // index out of bounds exception. - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverseFull(float[][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled2dInput() - { - final float[][] actual = new float[numRows][2 * numCols]; - final float[][] expected = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realInverseFull(actual, true); - fft.complexInverse(expected, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverseFull(float[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled1dInput() - { - final float[] actual = new float[2 * numRows * numCols]; - final float[] expected = new float[2 * numRows * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - final int index = r * numCols + c; - actual[index] = rnd; - expected[2 * index] = rnd; - } - } - // TODO If the two following lines are permuted, this causes an array - // index out of bounds exception. - fft.complexInverse(expected, false); - fft.realInverseFull(actual, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverseFull(FloatLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaledLarge() - { - final FloatLargeArray actual = new FloatLargeArray(2 * numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(2 * numRows * numCols, false); - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - final int index = r * numCols + c; - actual.set(index, rnd); - expected.setDouble(2 * index, rnd); - } - } - // TODO If the two following lines are permuted, this causes an array - // index out of bounds exception. - fft.complexInverse(expected, false); - fft.realInverseFull(actual, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link FloatFFT_2D#realInverseFull(float[][], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testRealInverseFullUnscaled2dInput() - { - final float[][] actual = new float[numRows][2 * numCols]; - final float[][] expected = new float[numRows][2 * numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft.realInverseFull(actual, false); - fft.complexInverse(expected, false); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverse(float[], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final float[] actual = new float[numRows * numCols]; - final float[] expected = new float[actual.length]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - - /** - * A test of {@link FloatFFT_2D#realInverse(FloatLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final FloatLargeArray actual = new FloatLargeArray(numRows * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(actual.length(), false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setDouble(i, rnd); - expected.setDouble(i, rnd); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_2D#realInverse(float[][], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled2dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - final float[][] actual = new float[numRows][numCols]; - final float[][] expected = new float[numRows][numCols]; - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[r][c] = rnd; - expected[r][c] = rnd; - } - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/FloatFFT_3DTest.java b/src/test/java/org/jtransforms/fft/FloatFFT_3DTest.java deleted file mode 100644 index 46afdf9..0000000 --- a/src/test/java/org/jtransforms/fft/FloatFFT_3DTest.java +++ /dev/null @@ -1,1078 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * - * This is a test of the class {@link FloatFFT_3D}. In this test, a very crude - * 3d FFT method is implemented (see {@link #complexForward(float[][][])}), - * assuming that {@link FloatFFT_1D} and {@link FloatFFT_2D} have been fully - * tested and validated. This crude (unoptimized) method is then used to - * establish expected values of direct Fourier transforms. - *

- * - * For inverse Fourier transforms, the test assumes that the - * corresponding direct Fourier transform has been tested and - * validated. - *

- * - * In all cases, the test consists in creating a random array of data, and - * verifying that expected and actual values of its Fourier transform coincide - * within a specified accuracy. - *

- * - * @author Sébastien Brisard - * @author Piotr Wendykier - */ -@RunWith(value = Parameterized.class) -public class FloatFFT_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110625; - - private static final double EPS = Math.pow(10, -3); - - @Parameters - public static Collection getParameters() - { - final int[] size = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 32, - 64, 100, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * The object to be tested. - */ - private final FloatFFT_3D fft; - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int numCols; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int numRows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int numSlices; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Fourier transform of the slices. - */ - private final FloatFFT_2D sfft; - - /** - * Fourier transform in the first direction (perpendicular to slices). - */ - private final FloatFFT_1D xfft; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param numSlices - * number of slices - * @param numRows - * number of rows - * @param numColumns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public FloatFFT_3DTest(final int numSlices, final int numRows, - final int numColumns, final int numThreads, final long seed) - { - this.numSlices = numSlices; - this.numRows = numRows; - this.numCols = numColumns; - this.fft = new FloatFFT_3D(numSlices, numRows, numColumns); - this.xfft = new FloatFFT_1D(numSlices); - this.sfft = new FloatFFT_2D(numRows, numColumns); - this.random = new Random(seed); - ConcurrencyUtils.setNumberOfThreads(numThreads); - ConcurrencyUtils.setThreadsBeginN_3D(4); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - /** - * A crude implementation of 3d complex FFT. - * - * @param a - * the data to be transformed - */ - public void complexForward(final float[][][] a) - { - for (int s = 0; s < numSlices; s++) { - sfft.complexForward(a[s]); - } - final float[] buffer = new float[2 * numSlices]; - for (int c = 0; c < numCols; c++) { - for (int r = 0; r < numRows; r++) { - for (int s = 0; s < numSlices; s++) { - buffer[2 * s] = a[s][r][2 * c]; - buffer[2 * s + 1] = a[s][r][2 * c + 1]; - } - xfft.complexForward(buffer); - for (int s = 0; s < numSlices; s++) { - a[s][r][2 * c] = buffer[2 * s]; - a[s][r][2 * c + 1] = buffer[2 * s + 1]; - } - } - } - } - - /** - * A test of {@link FloatFFT_3D#complexForward(float[])}. - */ - @Test - public void testComplexForward1dInput() - { - final float[] actual = new float[2 * numSlices * numRows * numCols]; - final float[][][] expected0 = new float[numSlices][numRows][2 * numCols]; - final float[] expected = new float[2 * numSlices * numRows * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final int index = 2 * numCols * (r + numRows * s) + c; - final float rnd = random.nextFloat(); - actual[index] = rnd; - expected0[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[s * 2 * numRows * numCols + r * 2 * numCols + c] = expected0[s][r][c]; - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexForward(FloatLargeArray)}. - */ - @Test - public void testComplexForwardLarge() - { - final FloatLargeArray actual = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - final float[][][] expected0 = new float[numSlices][numRows][2 * numCols]; - final FloatLargeArray expected = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final int index = 2 * numCols * (r + numRows * s) + c; - final float rnd = random.nextFloat(); - actual.setFloat(index, rnd); - expected0[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected0); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected.setFloat(s * 2 * numRows * numCols + r * 2 * numCols + c, expected0[s][r][c]); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexForward(float[][][])}. - */ - @Test - public void testComplexForward3dInput() - { - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - complexForward(expected); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(float[], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaled1dInput() - { - final float[] expected = new float[2 * numSlices * numRows * numCols]; - final float[] actual = new float[2 * numSlices * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(FloatLargeArray, boolean)}, with - * the second parameter set to true. - */ - @Test - public void testComplexInverseScaledLarge() - { - final FloatLargeArray expected = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - final FloatLargeArray actual = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setFloat(i, rnd); - expected.setFloat(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(float[][][], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testComplexInverseScaled3dInput() - { - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - fft.complexInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(float[], boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled1dInput() - { - final float[] expected = new float[2 * numSlices * numRows * numCols]; - final float[] actual = new float[2 * numSlices * numRows * numCols]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float scaling = numSlices * numRows * numCols; - for (int i = 0; i < actual.length; i++) { - expected[i] = scaling * expected[i]; - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(FloatLargeArray, boolean)}, with - * the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaledLarge() - { - final FloatLargeArray expected = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - final FloatLargeArray actual = new FloatLargeArray(2 * numSlices * numRows * numCols, false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setFloat(i, rnd); - expected.setFloat(i, rnd); - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float scaling = numSlices * numRows * numCols; - for (int i = 0; i < actual.length(); i++) { - expected.setFloat(i, scaling * expected.getFloat(i)); - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#complexInverse(float[][][], boolean)}, - * with the second parameter set to false. - */ - @Test - public void testComplexInverseUnscaled3dInput() - { - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.complexForward(actual); - fft.complexInverse(actual, false); - final float scaling = numSlices * numRows * numCols; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < 2 * numCols; c++) { - expected[s][r][c] = scaling * expected[s][r][c]; - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final float[] a, int slices, int rows, int columns) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - int sliceStride = rows * columns; - int rowStride = columns; - - final int twoSliceStride = rows * twon3; - final int twoRowStride = twon3; - - int idx1, idx2, idx3, idx4, idx5, idx6; - - for (int s = (slices - 1); s >= 1; s--) { - idx3 = s * sliceStride; - idx4 = 2 * idx3; - for (int r = 0; r < rows; r++) { - idx5 = r * rowStride; - idx6 = 2 * idx5; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - } - - for (int r = 1; r < rows; r++) { - idx3 = (rows - r) * rowStride; - idx4 = (rows - r) * twoRowStride; - for (int c = 0; c < columns; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a[idx2] = a[idx1]; - a[idx1] = 0; - idx1++; - idx2++; - a[idx2] = a[idx1]; - a[idx1] = 0; - } - } - - // ----------------------------------------------- - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx5 = s * twoSliceStride; - for (int r = 0; r < rows; r++) { - idx4 = ((rows - r) % rows) * twoRowStride; - idx6 = r * twoRowStride; - for (int c = 1; c < columns; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a[idx1] = -a[idx2 + 2]; - a[idx1 - 1] = a[idx2 + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - idx5 = ((slices - s) % slices) * twoSliceStride; - idx6 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx4 = idx6 + (rows - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columns; - idx2 = idx4 + columns; - idx3 = idx4 + 1; - a[idx1] = a[idx3]; - a[idx2] = a[idx3]; - a[idx1 + 1] = -a[idx4]; - a[idx2 + 1] = a[idx4]; - - } - } - - for (int s = 0; s < slices; s++) { - idx3 = ((slices - s) % slices) * twoSliceStride; - idx4 = s * twoSliceStride; - for (int r = 1; r < n2d2; r++) { - idx1 = idx3 + (rows - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a[idx1] = a[idx2]; - a[idx1 + 1] = -a[idx2 + 1]; - - } - } - - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slices - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a[idx1 + columns] = a[idx2 + 1]; - a[idx2 + columns] = a[idx2 + 1]; - a[idx1 + columns + 1] = -a[idx2]; - a[idx2 + columns + 1] = a[idx2]; - a[idx4 + columns] = a[idx5 + 1]; - a[idx5 + columns] = a[idx5 + 1]; - a[idx4 + columns + 1] = -a[idx5]; - a[idx5 + columns + 1] = a[idx5]; - a[idx2] = a[idx1]; - a[idx2 + 1] = -a[idx1 + 1]; - a[idx5] = a[idx4]; - a[idx5 + 1] = -a[idx4 + 1]; - - } - - // ---------------------------------------- - a[columns] = a[1]; - a[1] = 0; - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a[idx1 + columns] = a[idx1 + 1]; - a[idx1 + 1] = 0; - a[idx2 + columns] = a[idx2 + 1]; - a[idx2 + 1] = 0; - a[idx3 + columns] = a[idx3 + 1]; - a[idx3 + 1] = 0; - a[idx2 + columns + 1] = 0; - a[idx3 + columns + 1] = 0; - } - - /** - * A test of {@link FloatFFT_3D#realForward(float[])}. - */ - @Test - public void testRealForward1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - int index; - final float[] actual = new float[numSlices * numRows * 2 * numCols]; - final float[] expected = new float[numSlices * numRows * 2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - index = c + numCols * (r + numRows * s); - final float rnd = random.nextFloat(); - actual[index] = rnd; - expected[s * 2 * numRows * numCols + r * 2 * numCols + 2 * c] = rnd; - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final FloatLargeArray a, long slicesl, int rowsl, long columnsl) - { - final long twon3 = 2 * columnsl; - final long n2d2 = rowsl / 2; - long n1d2 = slicesl / 2; - - final long twoSliceStride = rowsl * twon3; - final long twoRowStride = twon3; - - long idx1, idx2, idx3, idx4, idx5, idx6; - - final long sliceStridel = rowsl * columnsl; - final long rowStridel = columnsl; - - for (long s = (slicesl - 1); s >= 1; s--) { - idx3 = s * sliceStridel; - idx4 = 2 * idx3; - for (long r = 0; r < rowsl; r++) { - idx5 = r * rowStridel; - idx6 = 2 * idx5; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + idx5 + c; - idx2 = idx4 + idx6 + c; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, 0); - idx1++; - idx2++; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, 0); - } - } - } - - for (long r = 1; r < rowsl; r++) { - idx3 = (rowsl - r) * rowStridel; - idx4 = (rowsl - r) * twoRowStride; - for (long c = 0; c < columnsl; c += 2) { - idx1 = idx3 + c; - idx2 = idx4 + c; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, 0); - idx1++; - idx2++; - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx1, 0); - } - } - - // ----------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx5 = s * twoSliceStride; - for (long r = 0; r < rowsl; r++) { - idx4 = ((rowsl - r) % rowsl) * twoRowStride; - idx6 = r * twoRowStride; - for (long c = 1; c < columnsl; c += 2) { - idx1 = idx3 + idx4 + twon3 - c; - idx2 = idx5 + idx6 + c; - a.setFloat(idx1, -a.getFloat(idx2 + 2)); - a.setFloat(idx1 - 1, a.getFloat(idx2 + 1)); - } - } - } - - // --------------------------------------------- - for (long s = 0; s < slicesl; s++) { - idx5 = ((slicesl - s) % slicesl) * twoSliceStride; - idx6 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx4 = idx6 + (rowsl - r) * twoRowStride; - idx1 = idx5 + r * twoRowStride + columnsl; - idx2 = idx4 + columnsl; - idx3 = idx4 + 1; - a.setFloat(idx1, a.getFloat(idx3)); - a.setFloat(idx2, a.getFloat(idx3)); - a.setFloat(idx1 + 1, -a.getFloat(idx4)); - a.setFloat(idx2 + 1, a.getFloat(idx4)); - - } - } - - for (long s = 0; s < slicesl; s++) { - idx3 = ((slicesl - s) % slicesl) * twoSliceStride; - idx4 = s * twoSliceStride; - for (long r = 1; r < n2d2; r++) { - idx1 = idx3 + (rowsl - r) * twoRowStride; - idx2 = idx4 + r * twoRowStride; - a.setFloat(idx1, a.getFloat(idx2)); - a.setFloat(idx1 + 1, -a.getFloat(idx2 + 1)); - - } - } - - // ---------------------------------------------------------- - for (long s = 1; s < n1d2; s++) { - idx1 = s * twoSliceStride; - idx2 = (slicesl - s) * twoSliceStride; - idx3 = n2d2 * twoRowStride; - idx4 = idx1 + idx3; - idx5 = idx2 + idx3; - a.setFloat(idx1 + columnsl, a.getFloat(idx2 + 1)); - a.setFloat(idx2 + columnsl, a.getFloat(idx2 + 1)); - a.setFloat(idx1 + columnsl + 1, -a.getFloat(idx2)); - a.setFloat(idx2 + columnsl + 1, a.getFloat(idx2)); - a.setFloat(idx4 + columnsl, a.getFloat(idx5 + 1)); - a.setFloat(idx5 + columnsl, a.getFloat(idx5 + 1)); - a.setFloat(idx4 + columnsl + 1, -a.getFloat(idx5)); - a.setFloat(idx5 + columnsl + 1, a.getFloat(idx5)); - a.setFloat(idx2, a.getFloat(idx1)); - a.setFloat(idx2 + 1, -a.getFloat(idx1 + 1)); - a.setFloat(idx5, a.getFloat(idx4)); - a.setFloat(idx5 + 1, -a.getFloat(idx4 + 1)); - - } - - // ---------------------------------------- - a.setFloat(columnsl, a.getFloat(1)); - a.setFloat(1, 0); - idx1 = n2d2 * twoRowStride; - idx2 = n1d2 * twoSliceStride; - idx3 = idx1 + idx2; - a.setFloat(idx1 + columnsl, a.getFloat(idx1 + 1)); - a.setFloat(idx1 + 1, 0); - a.setFloat(idx2 + columnsl, a.getFloat(idx2 + 1)); - a.setFloat(idx2 + 1, 0); - a.setFloat(idx3 + columnsl, a.getFloat(idx3 + 1)); - a.setFloat(idx3 + 1, 0); - a.setFloat(idx2 + columnsl + 1, 0); - a.setFloat(idx3 + columnsl + 1, 0); - } - - /** - * A test of {@link FloatFFT_3D#realForward(FloatLargeArray)}. - */ - @Test - public void testRealForwardLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - int index; - final FloatLargeArray actual = new FloatLargeArray(numSlices * numRows * 2 * numCols, false); - final FloatLargeArray expected = new FloatLargeArray(numSlices * numRows * 2 * numCols, false); - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - index = c + numCols * (r + numRows * s); - final float rnd = random.nextFloat(); - actual.setFloat(index, rnd); - expected.setFloat(s * 2 * numRows * numCols + r * 2 * numCols + 2 * c, rnd); - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - private void fillSymmetric(final float[][][] a, int slices, int rows, int columns) - { - final int twon3 = 2 * columns; - final int n2d2 = rows / 2; - int n1d2 = slices / 2; - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 0; r < rows; r++) { - int idx2 = (rows - r) % rows; - for (int c = 1; c < columns; c += 2) { - int idx3 = twon3 - c; - a[idx1][idx2][idx3] = -a[s][r][c + 2]; - a[idx1][idx2][idx3 - 1] = a[s][r][c + 1]; - } - } - } - - // --------------------------------------------- - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][r][columns] = a[s][idx2][1]; - a[s][idx2][columns] = a[s][idx2][1]; - a[idx1][r][columns + 1] = -a[s][idx2][0]; - a[s][idx2][columns + 1] = a[s][idx2][0]; - } - } - - for (int s = 0; s < slices; s++) { - int idx1 = (slices - s) % slices; - for (int r = 1; r < n2d2; r++) { - int idx2 = rows - r; - a[idx1][idx2][0] = a[s][r][0]; - a[idx1][idx2][1] = -a[s][r][1]; - } - } - // ---------------------------------------------------------- - for (int s = 1; s < n1d2; s++) { - int idx1 = slices - s; - a[s][0][columns] = a[idx1][0][1]; - a[idx1][0][columns] = a[idx1][0][1]; - a[s][0][columns + 1] = -a[idx1][0][0]; - a[idx1][0][columns + 1] = a[idx1][0][0]; - a[s][n2d2][columns] = a[idx1][n2d2][1]; - a[idx1][n2d2][columns] = a[idx1][n2d2][1]; - a[s][n2d2][columns + 1] = -a[idx1][n2d2][0]; - a[idx1][n2d2][columns + 1] = a[idx1][n2d2][0]; - a[idx1][0][0] = a[s][0][0]; - a[idx1][0][1] = -a[s][0][1]; - a[idx1][n2d2][0] = a[s][n2d2][0]; - a[idx1][n2d2][1] = -a[s][n2d2][1]; - - } - // ---------------------------------------- - - a[0][0][columns] = a[0][0][1]; - a[0][0][1] = 0; - a[0][n2d2][columns] = a[0][n2d2][1]; - a[0][n2d2][1] = 0; - a[n1d2][0][columns] = a[n1d2][0][1]; - a[n1d2][0][1] = 0; - a[n1d2][n2d2][columns] = a[n1d2][n2d2][1]; - a[n1d2][n2d2][1] = 0; - a[n1d2][0][columns + 1] = 0; - a[n1d2][n2d2][columns + 1] = 0; - } - - /** - * A test of {@link FloatFFT_3D#realForward(float[][][])}. - */ - @Test - public void testRealForward3dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.realForward(actual); - fft.complexForward(expected); - fillSymmetric(actual, numSlices, numRows, numCols); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverse(float[], boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaled1dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final float[] actual = new float[numRows * numCols * numSlices]; - final float[] expected = new float[actual.length]; - for (int i = 0; i < actual.length; i++) { - final float rnd = random.nextFloat(); - actual[i] = rnd; - expected[i] = rnd; - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverse(FloatLargeArray, boolean)}, with the - * second parameter set to true. - */ - @Test - public void testRealInverseScaledLarge() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final FloatLargeArray actual = new FloatLargeArray(numRows * numCols * numSlices, false); - final FloatLargeArray expected = new FloatLargeArray(actual.length(), false); - for (int i = 0; i < actual.length(); i++) { - final float rnd = random.nextFloat(); - actual.setFloat(i, rnd); - expected.setFloat(i, rnd); - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverse(float[][][], boolean)}, with - * the second parameter set to true. - */ - @Test - public void testRealInverseScaled3dInput() - { - if (!ConcurrencyUtils.isPowerOf2(numRows)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numCols)) { - return; - } - if (!ConcurrencyUtils.isPowerOf2(numSlices)) { - return; - } - final float[][][] actual = new float[numSlices][numRows][numCols]; - final float[][][] expected = new float[numSlices][numRows][numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][c] = rnd; - } - } - } - fft.realForward(actual); - fft.realInverse(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realForwardFull(float[])}. - */ - @Test - public void testRealForwardFull1dInput() - { - final int n = numSlices * numRows * numCols; - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int index = 0; index < n; index++) { - final float rnd = random.nextFloat(); - actual[index] = rnd; - expected[2 * index] = rnd; - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realForwardFull(FloatLargeArray)}. - */ - @Test - public void testRealForwardFullLarge() - { - final int n = numSlices * numRows * numCols; - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int index = 0; index < n; index++) { - final float rnd = random.nextFloat(); - actual.setFloat(index, rnd); - expected.setFloat(2 * index, rnd); - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realForwardFull(float[][][]). - */ - @Test - public void testRealForwardFull3dInput() - { - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.complexForward(expected); - fft.realForwardFull(actual); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverseFull(float[], boolean)} with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled1dInput() - { - final int n = numSlices * numRows * numCols; - final float[] actual = new float[2 * n]; - final float[] expected = new float[2 * n]; - for (int index = 0; index < n; index++) { - final float rnd = random.nextFloat(); - actual[index] = rnd; - expected[2 * index] = rnd; - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverseFull(FloatLargeArray, boolean)} with - * the second parameter set to true. - */ - @Test - public void testRealInverseFullScaledLarge() - { - final int n = numSlices * numRows * numCols; - final FloatLargeArray actual = new FloatLargeArray(2 * n, false); - final FloatLargeArray expected = new FloatLargeArray(2 * n, false); - for (int index = 0; index < n; index++) { - final float rnd = random.nextFloat(); - actual.setFloat(index, rnd); - expected.setFloat(2 * index, rnd); - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } - - /** - * A test of {@link FloatFFT_3D#realInverseFull(float[][][], boolean)}, - * with the second parameter set to true. - */ - @Test - public void testRealInverseFullScaled3dInput() - { - final float[][][] actual = new float[numSlices][numRows][2 * numCols]; - final float[][][] expected = new float[numSlices][numRows][2 * numCols]; - for (int s = 0; s < numSlices; s++) { - for (int r = 0; r < numRows; r++) { - for (int c = 0; c < numCols; c++) { - final float rnd = random.nextFloat(); - actual[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft.complexInverse(expected, true); - fft.realInverseFull(actual, true); - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, numSlices, numRows, numCols) + ", rmse = " + rmse, 0.0, rmse, EPS); - } -} diff --git a/src/test/java/org/jtransforms/fft/RealFFTUtils_2DTest.java b/src/test/java/org/jtransforms/fft/RealFFTUtils_2DTest.java deleted file mode 100644 index 56727d7..0000000 --- a/src/test/java/org/jtransforms/fft/RealFFTUtils_2DTest.java +++ /dev/null @@ -1,412 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Test of the utility class {@link RealFFTUtils_2D}. - * - * @author Sébastien Brisard - */ -@RunWith(value = Parameterized.class) -public class RealFFTUtils_2DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110624; - - private static final double EPSD = Math.pow(10, -12); - - private static final double EPSF = Math.pow(10, -3); - - @Parameters - public static Collection getParameters() - { - final int[] size = {16, 32, 64, 128}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - parameters.add(new Object[]{size[i], size[j], 1, SEED}); - parameters.add(new Object[]{size[i], size[j], 8, SEED}); - } - } - return parameters; - } - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int columns; - - /** - * To perform FFTs on double precision data. - */ - private final DoubleFFT_2D fft2d; - - /** - * To perform FFTs on single precision data. - */ - private final FloatFFT_2D fft2f; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int rows; - - /** - * The object to be tested. - */ - private final RealFFTUtils_2D unpacker; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param rows - * number of rows - * @param columns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public RealFFTUtils_2DTest(final int rows, final int columns, - final int numThreads, final long seed) - { - this.rows = rows; - this.columns = columns; - this.fft2d = new DoubleFFT_2D(rows, columns); - this.fft2f = new FloatFFT_2D(rows, columns); - this.random = new Random(seed); - this.unpacker = new RealFFTUtils_2D(rows, columns); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - @Test - public void testUnpack1dInput() - { - - final double[] actual0 = new double[rows * columns]; - final double[][] actual = new double[rows][2 * columns]; - final double[][] expected = new double[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0[r * columns + c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft2d.complexForward(expected); - fft2d.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0, 0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack1dInputLarge() - { - - final DoubleLargeArray actual0 = new DoubleLargeArray(rows * columns, false); - final double[][] actual = new double[rows][2 * columns]; - final double[][] expected = new double[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0.setDouble(r * columns + c, rnd); - expected[r][2 * c] = rnd; - } - } - fft2d.complexForward(expected); - fft2d.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0, 0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack1fInput() - { - final float[] actual0 = new float[rows * columns]; - final float[][] actual = new float[rows][2 * columns]; - final float[][] expected = new float[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0[r * columns + c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft2f.complexForward(expected); - fft2f.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0, 0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testUnpack1fInputLarge() - { - final FloatLargeArray actual0 = new FloatLargeArray(rows * columns, false); - final float[][] actual = new float[rows][2 * columns]; - final float[][] expected = new float[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0.setFloat(r * columns + c, rnd); - expected[r][2 * c] = rnd; - } - } - fft2f.complexForward(expected); - fft2f.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0, 0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testUnpack2dInput() - { - final double[][] actual0 = new double[rows][columns]; - final double[][] actual = new double[rows][2 * columns]; - final double[][] expected = new double[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft2d.complexForward(expected); - fft2d.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack2fInput() - { - final float[][] actual0 = new float[rows][columns]; - final float[][] actual = new float[rows][2 * columns]; - final float[][] expected = new float[rows][2 * columns]; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0[r][c] = rnd; - expected[r][2 * c] = rnd; - } - } - fft2f.complexForward(expected); - fft2f.realForward(actual0); - - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[r][c] = unpacker.unpack(r, c, actual0); - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testPack1dInput() - { - final double[] data = new double[rows * columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, r, c, data, 0); - final double actual = unpacker.unpack(r, c, data, 0); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - - @Test - public void testPack1dInputLarge() - { - final DoubleLargeArray data = new DoubleLargeArray(rows * columns, false); - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, r, c, data, 0); - final double actual = unpacker.unpack(r, c, data, 0); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - - @Test - public void testPack1fInput() - { - final float[] data = new float[rows * columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, r, c, data, 0); - final float actual = unpacker.unpack(r, c, data, 0); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - - @Test - public void testPack1fInputLarge() - { - final FloatLargeArray data = new FloatLargeArray(rows * columns, false); - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, r, c, data, 0); - final float actual = unpacker.unpack(r, c, data, 0); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - - @Test - public void testPack2dInput() - { - final double[][] data = new double[rows][columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, r, c, data); - final double actual = unpacker.unpack(r, c, data); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - - @Test - public void testPack2fInput() - { - final float[][] data = new float[rows][columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, rows, columns) + "[%d][%d]"; - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, r, c, data); - final float actual = unpacker.unpack(r, c, data); - Assert.assertEquals(String.format(msg, r, c), expected, - actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } -} diff --git a/src/test/java/org/jtransforms/fft/RealFFTUtils_3DTest.java b/src/test/java/org/jtransforms/fft/RealFFTUtils_3DTest.java deleted file mode 100644 index 2d7a7e0..0000000 --- a/src/test/java/org/jtransforms/fft/RealFFTUtils_3DTest.java +++ /dev/null @@ -1,466 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * JTransforms - * Copyright (c) 2007 onward, Piotr Wendykier - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ -package org.jtransforms.fft; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Random; -import org.jtransforms.utils.ConcurrencyUtils; -import org.jtransforms.utils.IOUtils; -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 pl.edu.icm.jlargearrays.DoubleLargeArray; -import pl.edu.icm.jlargearrays.FloatLargeArray; - -/** - * Test of the utility class {@link RealFFTUtils_3D}. - * - * @author Sébastien Brisard - */ -@RunWith(value = Parameterized.class) -public class RealFFTUtils_3DTest -{ - - /** - * Base message of all exceptions. - */ - public static final String DEFAULT_MESSAGE = "%d-threaded FFT of size %dx%dx%d: "; - - /** - * The constant value of the seed of the random generator. - */ - public static final int SEED = 20110624; - - private static final double EPSD = Math.pow(10, -12); - - private static final double EPSF = Math.pow(10, -3); - - @Parameters - public static Collection getParameters() - { - final int[] size = {16, 32, 64}; - - final ArrayList parameters = new ArrayList(); - - for (int i = 0; i < size.length; i++) { - for (int j = 0; j < size.length; j++) { - for (int k = 0; k < size.length; k++) { - parameters.add(new Object[]{size[i], size[j], size[k], 1, - SEED}); - parameters.add(new Object[]{size[i], size[j], size[k], 8, - SEED}); - } - } - } - return parameters; - } - - /** - * Number of columns of the data arrays to be Fourier transformed. - */ - private final int columns; - - /** - * To perform FFTs on double precision data. - */ - private final DoubleFFT_3D fft3d; - - /** - * To perform FFTs on single precision data. - */ - private final FloatFFT_3D fft3f; - - /** - * For the generation of the data arrays. - */ - private final Random random; - - /** - * Number of rows of the data arrays to be Fourier transformed. - */ - private final int rows; - - /** - * Number of slices of the data arrays to be Fourier transformed. - */ - private final int slices; - - /** - * The object to be tested. - */ - private final RealFFTUtils_3D unpacker; - - /** - * The number of threads used. - */ - private final int numThreads; - - /** - * Creates a new instance of this test. - * - * @param slices - * number of slices - * @param rows - * number of rows - * @param columns - * number of columns - * @param numThreads - * the number of threads to be used - * @param seed - * the seed of the random generator - */ - public RealFFTUtils_3DTest(final int slices, final int rows, - final int columns, final int numThreads, final long seed) - { - this.slices = slices; - this.rows = rows; - this.columns = columns; - this.fft3d = new DoubleFFT_3D(slices, rows, columns); - this.fft3f = new FloatFFT_3D(slices, rows, columns); - this.random = new Random(seed); - this.unpacker = new RealFFTUtils_3D(slices, rows, columns); - ConcurrencyUtils.setNumberOfThreads(numThreads); - this.numThreads = ConcurrencyUtils.getNumberOfThreads(); - } - - @Test - public void testUnpack1dInput() - { - final double[] actual0 = new double[slices * rows * columns]; - final double[][][] actual = new double[slices][rows][2 * columns]; - final double[][][] expected = new double[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0[(s * rows + r) * columns + c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft3d.complexForward(expected); - fft3d.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0, 0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack1dInputLarge() - { - final DoubleLargeArray actual0 = new DoubleLargeArray(slices * rows * columns, false); - final double[][][] actual = new double[slices][rows][2 * columns]; - final double[][][] expected = new double[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0.setDouble((s * rows + r) * columns + c, rnd); - expected[s][r][2 * c] = rnd; - } - } - } - fft3d.complexForward(expected); - fft3d.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0, 0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack1fInput() - { - final float[] actual0 = new float[slices * rows * columns]; - final float[][][] expected = new float[slices][rows][2 * columns]; - final float[][][] actual = new float[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0[(s * rows + r) * columns + c] = rnd; - expected[s][r][2 * c] = rnd; - expected[s][r][2 * c + 1] = 0f; - } - } - } - fft3f.complexForward(expected); - fft3f.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0, 0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testUnpack1fInputLarge() - { - final FloatLargeArray actual0 = new FloatLargeArray(slices * rows * columns, false); - final float[][][] expected = new float[slices][rows][2 * columns]; - final float[][][] actual = new float[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0.setFloat((s * rows + r) * columns + c, rnd); - expected[s][r][2 * c] = rnd; - expected[s][r][2 * c + 1] = 0f; - } - } - } - fft3f.complexForward(expected); - fft3f.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0, 0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testUnpack3dInput() - { - final double[][][] actual0 = new double[slices][rows][columns]; - final double[][][] expected = new double[slices][rows][2 * columns]; - final double[][][] actual = new double[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final double rnd = random.nextDouble(); - actual0[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft3d.complexForward(expected); - fft3d.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSD); - } - - @Test - public void testUnpack3fInput() - { - final float[][][] actual0 = new float[slices][rows][columns]; - final float[][][] expected = new float[slices][rows][2 * columns]; - final float[][][] actual = new float[slices][rows][2 * columns]; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < columns; c++) { - final float rnd = random.nextFloat(); - actual0[s][r][c] = rnd; - expected[s][r][2 * c] = rnd; - } - } - } - fft3f.complexForward(expected); - fft3f.realForward(actual0); - - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - actual[s][r][c] = unpacker.unpack(s, r, c, actual0); - } - } - } - double rmse = IOUtils.computeRMSE(actual, expected); - Assert.assertEquals(String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + ", rmse = " + rmse, 0.0, rmse, EPSF); - } - - @Test - public void testPack1dInput() - { - final double[] data = new double[slices * rows * columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, s, r, c, data, 0); - final double actual = unpacker.unpack(s, r, c, data, 0); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } - - @Test - public void testPack1dInputLarge() - { - final DoubleLargeArray data = new DoubleLargeArray(slices * rows * columns, false); - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, s, r, c, data, 0); - final double actual = unpacker.unpack(s, r, c, data, 0); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } - - @Test - public void testPack3dInput() - { - final double[][][] data = new double[slices][rows][columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final double expected = random.nextDouble(); - try { - unpacker.pack(expected, s, r, c, data); - final double actual = unpacker.unpack(s, r, c, data); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } - - @Test - public void testPack1fInput() - { - final float[] data = new float[slices * rows * columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, s, r, c, data, 0); - final float actual = unpacker.unpack(s, r, c, data, 0); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } - - @Test - public void testPack1fInputLarge() - { - final FloatLargeArray data = new FloatLargeArray(slices * rows * columns, false); - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, s, r, c, data, 0); - final float actual = unpacker.unpack(s, r, c, data, 0); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } - - @Test - public void testPack3fInput() - { - final float[][][] data = new float[slices][rows][columns]; - String msg = String.format(DEFAULT_MESSAGE, numThreads, slices, rows, columns) + - "[%d][%d][%d]"; - for (int s = 0; s < slices; s++) { - for (int r = 0; r < rows; r++) { - for (int c = 0; c < 2 * columns; c++) { - final float expected = random.nextFloat(); - try { - unpacker.pack(expected, s, r, c, data); - final float actual = unpacker.unpack(s, r, c, data); - Assert.assertEquals(String.format(msg, s, r, c), - expected, actual, 0.); - } catch (IllegalArgumentException e) { - // Do nothing - } - } - } - } - } -} diff --git a/src/test/resources/Makefile b/src/test/resources/Makefile deleted file mode 100644 index 9196f90..0000000 --- a/src/test/resources/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -fftwdir = "E:\devel\fftw-3.2.2" - -CC = gcc -CFLAGS = -I$(fftwdir) -LDFLAGS = -L$(fftwdir) -lm -lfftw3-3 - -all: genref1d -genref1d.o: genref1d.c - gcc -c genref1d.c $(CFLAGS) -genref1d: genref1d.o - gcc -o genref1d genref1d.o $(LDFLAGS) \ No newline at end of file diff --git a/src/test/resources/fftw1.in b/src/test/resources/fftw1.in deleted file mode 100644 index 97f1e21..0000000 Binary files a/src/test/resources/fftw1.in and /dev/null differ diff --git a/src/test/resources/fftw1.out b/src/test/resources/fftw1.out deleted file mode 100644 index 97f1e21..0000000 Binary files a/src/test/resources/fftw1.out and /dev/null differ diff --git a/src/test/resources/fftw10.in b/src/test/resources/fftw10.in deleted file mode 100644 index 0a21149..0000000 Binary files a/src/test/resources/fftw10.in and /dev/null differ diff --git a/src/test/resources/fftw10.out b/src/test/resources/fftw10.out deleted file mode 100644 index 0fc6216..0000000 Binary files a/src/test/resources/fftw10.out and /dev/null differ diff --git a/src/test/resources/fftw100.in b/src/test/resources/fftw100.in deleted file mode 100644 index 19b6c56..0000000 Binary files a/src/test/resources/fftw100.in and /dev/null differ diff --git a/src/test/resources/fftw100.out b/src/test/resources/fftw100.out deleted file mode 100644 index 6a81fc9..0000000 Binary files a/src/test/resources/fftw100.out and /dev/null differ diff --git a/src/test/resources/fftw10158.in b/src/test/resources/fftw10158.in deleted file mode 100644 index 0fd39e1..0000000 Binary files a/src/test/resources/fftw10158.in and /dev/null differ diff --git a/src/test/resources/fftw10158.out b/src/test/resources/fftw10158.out deleted file mode 100644 index bbb372d..0000000 Binary files a/src/test/resources/fftw10158.out and /dev/null differ diff --git a/src/test/resources/fftw1024.in b/src/test/resources/fftw1024.in deleted file mode 100644 index 39dd8b7..0000000 Binary files a/src/test/resources/fftw1024.in and /dev/null differ diff --git a/src/test/resources/fftw1024.out b/src/test/resources/fftw1024.out deleted file mode 100644 index bcb7737..0000000 Binary files a/src/test/resources/fftw1024.out and /dev/null differ diff --git a/src/test/resources/fftw1056.in b/src/test/resources/fftw1056.in deleted file mode 100644 index 65674e8..0000000 Binary files a/src/test/resources/fftw1056.in and /dev/null differ diff --git a/src/test/resources/fftw1056.out b/src/test/resources/fftw1056.out deleted file mode 100644 index 09f8d20..0000000 Binary files a/src/test/resources/fftw1056.out and /dev/null differ diff --git a/src/test/resources/fftw11.in b/src/test/resources/fftw11.in deleted file mode 100644 index 3aad36b..0000000 Binary files a/src/test/resources/fftw11.in and /dev/null differ diff --git a/src/test/resources/fftw11.out b/src/test/resources/fftw11.out deleted file mode 100644 index 3722adb..0000000 Binary files a/src/test/resources/fftw11.out and /dev/null differ diff --git a/src/test/resources/fftw12.in b/src/test/resources/fftw12.in deleted file mode 100644 index 82bb930..0000000 Binary files a/src/test/resources/fftw12.in and /dev/null differ diff --git a/src/test/resources/fftw12.out b/src/test/resources/fftw12.out deleted file mode 100644 index cda9ed4..0000000 Binary files a/src/test/resources/fftw12.out and /dev/null differ diff --git a/src/test/resources/fftw120.in b/src/test/resources/fftw120.in deleted file mode 100644 index f1040a9..0000000 Binary files a/src/test/resources/fftw120.in and /dev/null differ diff --git a/src/test/resources/fftw120.out b/src/test/resources/fftw120.out deleted file mode 100644 index 6aefe98..0000000 Binary files a/src/test/resources/fftw120.out and /dev/null differ diff --git a/src/test/resources/fftw128.in b/src/test/resources/fftw128.in deleted file mode 100644 index 433d2c0..0000000 Binary files a/src/test/resources/fftw128.in and /dev/null differ diff --git a/src/test/resources/fftw128.out b/src/test/resources/fftw128.out deleted file mode 100644 index cbc3424..0000000 Binary files a/src/test/resources/fftw128.out and /dev/null differ diff --git a/src/test/resources/fftw13.in b/src/test/resources/fftw13.in deleted file mode 100644 index 5f06724..0000000 Binary files a/src/test/resources/fftw13.in and /dev/null differ diff --git a/src/test/resources/fftw13.out b/src/test/resources/fftw13.out deleted file mode 100644 index e22112c..0000000 Binary files a/src/test/resources/fftw13.out and /dev/null differ diff --git a/src/test/resources/fftw131072.in b/src/test/resources/fftw131072.in deleted file mode 100644 index 27e5659..0000000 Binary files a/src/test/resources/fftw131072.in and /dev/null differ diff --git a/src/test/resources/fftw131072.out b/src/test/resources/fftw131072.out deleted file mode 100644 index bc9fde3..0000000 Binary files a/src/test/resources/fftw131072.out and /dev/null differ diff --git a/src/test/resources/fftw16.in b/src/test/resources/fftw16.in deleted file mode 100644 index 586a2b5..0000000 Binary files a/src/test/resources/fftw16.in and /dev/null differ diff --git a/src/test/resources/fftw16.out b/src/test/resources/fftw16.out deleted file mode 100644 index d26b678..0000000 Binary files a/src/test/resources/fftw16.out and /dev/null differ diff --git a/src/test/resources/fftw16384.in b/src/test/resources/fftw16384.in deleted file mode 100644 index 35a155b..0000000 Binary files a/src/test/resources/fftw16384.in and /dev/null differ diff --git a/src/test/resources/fftw16384.out b/src/test/resources/fftw16384.out deleted file mode 100644 index 663e400..0000000 Binary files a/src/test/resources/fftw16384.out and /dev/null differ diff --git a/src/test/resources/fftw2.in b/src/test/resources/fftw2.in deleted file mode 100644 index 6200899..0000000 Binary files a/src/test/resources/fftw2.in and /dev/null differ diff --git a/src/test/resources/fftw2.out b/src/test/resources/fftw2.out deleted file mode 100644 index efd6372..0000000 Binary files a/src/test/resources/fftw2.out and /dev/null differ diff --git a/src/test/resources/fftw2048.in b/src/test/resources/fftw2048.in deleted file mode 100644 index 4b71f57..0000000 Binary files a/src/test/resources/fftw2048.in and /dev/null differ diff --git a/src/test/resources/fftw2048.out b/src/test/resources/fftw2048.out deleted file mode 100644 index 3b41a28..0000000 Binary files a/src/test/resources/fftw2048.out and /dev/null differ diff --git a/src/test/resources/fftw256.in b/src/test/resources/fftw256.in deleted file mode 100644 index e7be82f..0000000 Binary files a/src/test/resources/fftw256.in and /dev/null differ diff --git a/src/test/resources/fftw256.out b/src/test/resources/fftw256.out deleted file mode 100644 index 5afc2bf..0000000 Binary files a/src/test/resources/fftw256.out and /dev/null differ diff --git a/src/test/resources/fftw3.in b/src/test/resources/fftw3.in deleted file mode 100644 index f1230e0..0000000 Binary files a/src/test/resources/fftw3.in and /dev/null differ diff --git a/src/test/resources/fftw3.out b/src/test/resources/fftw3.out deleted file mode 100644 index cf65471..0000000 Binary files a/src/test/resources/fftw3.out and /dev/null differ diff --git a/src/test/resources/fftw310.in b/src/test/resources/fftw310.in deleted file mode 100644 index 3026249..0000000 Binary files a/src/test/resources/fftw310.in and /dev/null differ diff --git a/src/test/resources/fftw310.out b/src/test/resources/fftw310.out deleted file mode 100644 index 2823540..0000000 Binary files a/src/test/resources/fftw310.out and /dev/null differ diff --git a/src/test/resources/fftw32.in b/src/test/resources/fftw32.in deleted file mode 100644 index 92727cc..0000000 Binary files a/src/test/resources/fftw32.in and /dev/null differ diff --git a/src/test/resources/fftw32.out b/src/test/resources/fftw32.out deleted file mode 100644 index bf5d450..0000000 Binary files a/src/test/resources/fftw32.out and /dev/null differ diff --git a/src/test/resources/fftw32768.in b/src/test/resources/fftw32768.in deleted file mode 100644 index 1a5ad9d..0000000 Binary files a/src/test/resources/fftw32768.in and /dev/null differ diff --git a/src/test/resources/fftw32768.out b/src/test/resources/fftw32768.out deleted file mode 100644 index 78b633c..0000000 Binary files a/src/test/resources/fftw32768.out and /dev/null differ diff --git a/src/test/resources/fftw4.in b/src/test/resources/fftw4.in deleted file mode 100644 index e0e2486..0000000 Binary files a/src/test/resources/fftw4.in and /dev/null differ diff --git a/src/test/resources/fftw4.out b/src/test/resources/fftw4.out deleted file mode 100644 index 4ac5769..0000000 Binary files a/src/test/resources/fftw4.out and /dev/null differ diff --git a/src/test/resources/fftw5.in b/src/test/resources/fftw5.in deleted file mode 100644 index c261485..0000000 Binary files a/src/test/resources/fftw5.in and /dev/null differ diff --git a/src/test/resources/fftw5.out b/src/test/resources/fftw5.out deleted file mode 100644 index 9a82516..0000000 Binary files a/src/test/resources/fftw5.out and /dev/null differ diff --git a/src/test/resources/fftw512.in b/src/test/resources/fftw512.in deleted file mode 100644 index 3e0ab34..0000000 Binary files a/src/test/resources/fftw512.in and /dev/null differ diff --git a/src/test/resources/fftw512.out b/src/test/resources/fftw512.out deleted file mode 100644 index 7aff01d..0000000 Binary files a/src/test/resources/fftw512.out and /dev/null differ diff --git a/src/test/resources/fftw6.in b/src/test/resources/fftw6.in deleted file mode 100644 index 0c0f636..0000000 Binary files a/src/test/resources/fftw6.in and /dev/null differ diff --git a/src/test/resources/fftw6.out b/src/test/resources/fftw6.out deleted file mode 100644 index 996ef0c..0000000 Binary files a/src/test/resources/fftw6.out and /dev/null differ diff --git a/src/test/resources/fftw64.in b/src/test/resources/fftw64.in deleted file mode 100644 index d8f9311..0000000 Binary files a/src/test/resources/fftw64.in and /dev/null differ diff --git a/src/test/resources/fftw64.out b/src/test/resources/fftw64.out deleted file mode 100644 index b9d1101..0000000 Binary files a/src/test/resources/fftw64.out and /dev/null differ diff --git a/src/test/resources/fftw65530.in b/src/test/resources/fftw65530.in deleted file mode 100644 index 1430f09..0000000 Binary files a/src/test/resources/fftw65530.in and /dev/null differ diff --git a/src/test/resources/fftw65530.out b/src/test/resources/fftw65530.out deleted file mode 100644 index c26e309..0000000 Binary files a/src/test/resources/fftw65530.out and /dev/null differ diff --git a/src/test/resources/fftw65536.in b/src/test/resources/fftw65536.in deleted file mode 100644 index b3657ef..0000000 Binary files a/src/test/resources/fftw65536.in and /dev/null differ diff --git a/src/test/resources/fftw65536.out b/src/test/resources/fftw65536.out deleted file mode 100644 index 15375cc..0000000 Binary files a/src/test/resources/fftw65536.out and /dev/null differ diff --git a/src/test/resources/fftw7.in b/src/test/resources/fftw7.in deleted file mode 100644 index 3bb5f01..0000000 Binary files a/src/test/resources/fftw7.in and /dev/null differ diff --git a/src/test/resources/fftw7.out b/src/test/resources/fftw7.out deleted file mode 100644 index f7b2f40..0000000 Binary files a/src/test/resources/fftw7.out and /dev/null differ diff --git a/src/test/resources/fftw8.in b/src/test/resources/fftw8.in deleted file mode 100644 index 3f09be4..0000000 Binary files a/src/test/resources/fftw8.in and /dev/null differ diff --git a/src/test/resources/fftw8.out b/src/test/resources/fftw8.out deleted file mode 100644 index 0b86b68..0000000 Binary files a/src/test/resources/fftw8.out and /dev/null differ diff --git a/src/test/resources/fftw8192.in b/src/test/resources/fftw8192.in deleted file mode 100644 index 043eab5..0000000 Binary files a/src/test/resources/fftw8192.in and /dev/null differ diff --git a/src/test/resources/fftw8192.out b/src/test/resources/fftw8192.out deleted file mode 100644 index 2fd075a..0000000 Binary files a/src/test/resources/fftw8192.out and /dev/null differ diff --git a/src/test/resources/fftw9.in b/src/test/resources/fftw9.in deleted file mode 100644 index 556752e..0000000 Binary files a/src/test/resources/fftw9.in and /dev/null differ diff --git a/src/test/resources/fftw9.out b/src/test/resources/fftw9.out deleted file mode 100644 index 5f46db3..0000000 Binary files a/src/test/resources/fftw9.out and /dev/null differ diff --git a/src/test/resources/genref1d.c b/src/test/resources/genref1d.c deleted file mode 100644 index 79cb6e5..0000000 --- a/src/test/resources/genref1d.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include - -#define NUM_TESTS - -void generate_reference_data(int n, fftw_complex* in, fftw_complex* out){ - int i; - fftw_plan p; - - for (i = 0; i < n; i++){ - in[i][0] = 2 * rand() / ((double)RAND_MAX + 1) - 1; - in[i][1] = 2 * rand() / ((double)RAND_MAX + 1) - 1; - } - - p = fftw_plan_dft_1d(n, in, out, FFTW_FORWARD, FFTW_ESTIMATE); - fftw_execute(p); - fftw_destroy_plan(p); -} - -void save_reference_data(int n, fftw_complex* in, fftw_complex* out){ - char s[100]; - FILE* f; - - sprintf(s, "fftw%d.in", n); - f = fopen(s, "wb"); - fwrite(in, sizeof(fftw_complex), n, f); - fclose(f); - - sprintf(s, "fftw%d.out", n); - f = fopen(s, "wb"); - fwrite(out, sizeof(fftw_complex), n, f); - fclose(f); -} - -int main(int argc, char **argv){ - if (argc != 2){ - printf("Missing expected list of sizes"); - exit(0); - } - fftw_complex *in, *out; - fftw_plan p; - - int n; - - FILE* f; - f = fopen(argv[1], "r"); - while(!feof(f)){ - fscanf(f, "%i\n", &n); - printf("Generating reference data for n = %i\n", n); - in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * n); - out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * n); - generate_reference_data(n, in, out); - save_reference_data(n, in, out); - fftw_free(in); - fftw_free(out); - } - - - fclose(f); -} diff --git a/src/test/resources/genref1d.exe b/src/test/resources/genref1d.exe deleted file mode 100644 index fb3de21..0000000 Binary files a/src/test/resources/genref1d.exe and /dev/null differ diff --git a/src/test/resources/sizes.txt b/src/test/resources/sizes.txt deleted file mode 100644 index 844066e..0000000 --- a/src/test/resources/sizes.txt +++ /dev/null @@ -1,32 +0,0 @@ -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -16 -32 -64 -100 -120 -128 -256 -310 -512 -1024 -1056 -2048 -8192 -10158 -16384 -32768 -65530 -65536 -131072