org.apfloat.internal.DoubleTableFNT Maven / Gradle / Ivy
Show all versions of apfloat Show documentation
package org.apfloat.internal;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
/**
* Fast Number Theoretic Transform that uses lookup tables
* for powers of n:th root of unity and permutation indexes.
*
* All access to this class must be externally synchronized.
*
* @since 1.7.0
* @version 1.7.0
* @author Mikko Tommila
*/
public class DoubleTableFNT
extends DoubleModMath
{
/**
* Default constructor.
*/
public DoubleTableFNT()
{
}
/**
* Forward (Sande-Tukey) fast Number Theoretic Transform.
* Data length must be a power of two.
*
* @param arrayAccess The data array to transform.
* @param wTable Table of powers of n:th root of unity w
modulo the current modulus.
* @param permutationTable Table of permutation indexes, or null
if the data should not be permuted.
*/
public void tableFNT(ArrayAccess arrayAccess, double[] wTable, int[] permutationTable)
throws ApfloatRuntimeException
{
int nn, offset, istep, mmax, r;
double[] data;
data = arrayAccess.getDoubleData();
offset = arrayAccess.getOffset();
nn = arrayAccess.getLength();
assert (nn == (nn & -nn));
if (nn < 2)
{
return;
}
r = 1;
mmax = nn >> 1;
while (mmax > 0)
{
istep = mmax << 1;
// Optimize first step when wr = 1
for (int i = offset; i < offset + nn; i += istep)
{
int j = i + mmax;
double a = data[i];
double b = data[j];
data[i] = modAdd(a, b);
data[j] = modSubtract(a, b);
}
int t = r;
for (int m = 1; m < mmax; m++)
{
for (int i = offset + m; i < offset + nn; i += istep)
{
int j = i + mmax;
double a = data[i];
double b = data[j];
data[i] = modAdd(a, b);
data[j] = modMultiply(wTable[t], modSubtract(a, b));
}
t += r;
}
r <<= 1;
mmax >>= 1;
}
if (permutationTable != null)
{
DoubleScramble.scramble(data, offset, permutationTable);
}
}
/**
* Inverse (Cooley-Tukey) fast Number Theoretic Transform.
* Data length must be a power of two.
*
* @param arrayAccess The data array to transform.
* @param wTable Table of powers of n:th root of unity w
modulo the current modulus.
* @param permutationTable Table of permutation indexes, or null
if the data should not be permuted.
*/
public void inverseTableFNT(ArrayAccess arrayAccess, double[] wTable, int[] permutationTable)
throws ApfloatRuntimeException
{
int nn, offset, istep, mmax, r;
double[] data;
data = arrayAccess.getDoubleData();
offset = arrayAccess.getOffset();
nn = arrayAccess.getLength();
assert (nn == (nn & -nn));
if (nn < 2)
{
return;
}
if (permutationTable != null)
{
DoubleScramble.scramble(data, offset, permutationTable);
}
r = nn;
mmax = 1;
while (nn > mmax)
{
istep = mmax << 1;
r >>= 1;
// Optimize first step when w = 1
for (int i = offset; i < offset + nn; i += istep)
{
int j = i + mmax;
double wTemp = data[j];
data[j] = modSubtract(data[i], wTemp);
data[i] = modAdd(data[i], wTemp);
}
int t = r;
for (int m = 1; m < mmax; m++)
{
for (int i = offset + m; i < offset + nn; i += istep)
{
int j = i + mmax;
double wTemp = modMultiply(wTable[t], data[j]);
data[j] = modSubtract(data[i], wTemp);
data[i] = modAdd(data[i], wTemp);
}
t += r;
}
mmax = istep;
}
}
}