org.apfloat.internal.AbstractConvolutionBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apfloat Show documentation
Show all versions of apfloat Show documentation
High performance arbitrary precision arithmetic library
package org.apfloat.internal;
import org.apfloat.ApfloatContext;
import org.apfloat.spi.ConvolutionBuilder;
import org.apfloat.spi.ConvolutionStrategy;
import org.apfloat.spi.NTTBuilder;
import org.apfloat.spi.NTTStrategy;
import org.apfloat.spi.Util;
/**
* Abstract base class for creating convolutions of suitable type for the specified length.
*
* Based on a work estimate, depending on the operand sizes and implementation-dependent
* factors, the O(n2) long multiplication, Karatsuba multiplication and
* the NTT algorithms are chosen e.g. as follows:
*
*
* size1 size2 Algorithm
* 16 16 Long
* 16 256 Long
* 32 32 Long
* 32 256 Long
* 64 64 Karatsuba
* 64 256 NTT
* 64 65536 Karatsuba
* 128 128 NTT
* 128 65536 NTT
* 128 4294967296 Karatsuba
* 256 256 NTT
* 256 4294967296 Karatsuba
* 512 512 NTT
* 512 4294967296 NTT
*
*
* @since 1.7.0
* @version 1.7.0
* @author Mikko Tommila
*/
public abstract class AbstractConvolutionBuilder
implements ConvolutionBuilder
{
/**
* Subclass constructor.
*/
protected AbstractConvolutionBuilder()
{
}
public ConvolutionStrategy createConvolution(int radix, long size1, long size2, long resultSize)
{
long minSize = Math.min(size1, size2),
maxSize = Math.max(size1, size2),
totalSize = size1 + size2;
if (minSize == 1)
{
return createShortConvolutionStrategy(radix);
}
else if (minSize <= getKaratsubaCutoffPoint())
{
return createMediumConvolutionStrategy(radix);
}
else
{
float mediumCost = (float) minSize * maxSize,
karatsubaCost = getKaratsubaCostFactor() * (float) Math.pow((double) minSize, LOG2_3) * maxSize / minSize,
nttCost = getNTTCostFactor() * totalSize * Util.log2down(totalSize);
if (mediumCost <= Math.min(karatsubaCost, nttCost))
{
return createMediumConvolutionStrategy(radix);
}
else if (karatsubaCost <= nttCost)
{
return createKaratsubaConvolutionStrategy(radix);
}
else
{
ApfloatContext ctx = ApfloatContext.getContext();
NTTBuilder nttBuilder = ctx.getBuilderFactory().getNTTBuilder();
NTTStrategy nttStrategy = nttBuilder.createNTT(totalSize);
return createThreeNTTConvolutionStrategy(radix, nttStrategy);
}
}
}
/**
* Get the Karatsuba convolution cutoff point.
* When either operand is shorter than this then the
* medium-length convolution strategy should be used instead.
*
* @return The Karatsuba convolution cutoff point.
*
* @since 1.7.0
*/
protected abstract int getKaratsubaCutoffPoint();
/**
* Get the Karatsuba convolution cost factor.
* It is used in determining the most efficient
* convolution strategy for the given data lengths.
*
* @return The Karatsuba convolution cost factor.
*
* @since 1.7.0
*/
protected abstract float getKaratsubaCostFactor();
/**
* Get the NTT convolution cost factor.
* It is used in determining the most efficient
* convolution strategy for the given data lengths.
*
* @return The NTT convolution cost factor.
*
* @since 1.7.0
*/
protected abstract float getNTTCostFactor();
/**
* Create a short-length convolution strategy where the size of either
* data set is one.
*
* @param radix The radix that will be used.
*
* @return A new short-length convolution strategy.
*
* @since 1.7.0
*/
protected abstract ConvolutionStrategy createShortConvolutionStrategy(int radix);
/**
* Create a medium-length convolution strategy where the size of one
* of the data sets is relatively small (but more than one).
*
* @param radix The radix that will be used.
*
* @return A new medium-length convolution strategy.
*
* @since 1.7.0
*/
protected abstract ConvolutionStrategy createMediumConvolutionStrategy(int radix);
/**
* Create a Karatsuba convolution strategy.
*
* @param radix The radix that will be used.
*
* @return A new Karatsuba convolution strategy.
*
* @since 1.7.0
*/
protected abstract ConvolutionStrategy createKaratsubaConvolutionStrategy(int radix);
/**
* Create a 3-NTT convolution strategy.
*
* @param radix The radix that will be used.
* @param nttStrategy The underlying NTT strategy.
*
* @return A new 3-NTT convolution strategy.
*
* @since 1.7.0
*/
protected abstract ConvolutionStrategy createThreeNTTConvolutionStrategy(int radix, NTTStrategy nttStrategy);
private static final double LOG2_3 = Math.log(3.0) / Math.log(2.0);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy