All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apfloat.internal.DoubleNTTConvolutionStepStrategy Maven / Gradle / Ivy

There is a newer version: 1.14.0
Show newest version
package org.apfloat.internal;

import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.NTTConvolutionStepStrategy;
import org.apfloat.spi.DataStorage;
import static org.apfloat.internal.DoubleModConstants.*;

/**
 * Steps of a three-NTT convolution for the double type.
 * This class implements the details of the element-by-element multiplication
 * and element-by-element squaring of the transformed elements.

* * The in-place multiplication and squaring of the data elements is done * using a parallel algorithm, if the data fits in memory.

* * All access to this class must be externally synchronized. * * @since 1.7.0 * @version 1.8.0 * @author Mikko Tommila */ public class DoubleNTTConvolutionStepStrategy extends DoubleModMath implements NTTConvolutionStepStrategy, Parallelizable { // Runnable for multiplying elements in place private class MultiplyInPlaceRunnable implements Runnable { public MultiplyInPlaceRunnable(DataStorage sourceAndDestination, DataStorage source, long offset, long length) { this.sourceAndDestination = sourceAndDestination; this.source = source; this.offset = offset; this.length = length; } public void run() { DataStorage.Iterator dest = this.sourceAndDestination.iterator(DataStorage.READ_WRITE, this.offset, this.offset + this.length), src = this.source.iterator(DataStorage.READ, this.offset, this.offset + this.length); while (this.length > 0) { dest.setDouble(modMultiply(dest.getDouble(), src.getDouble())); dest.next(); src.next(); this.length--; } } private DataStorage sourceAndDestination, source; private long offset, length; } // Runnable for squaring elements in place private class SquareInPlaceRunnable implements Runnable { public SquareInPlaceRunnable(DataStorage sourceAndDestination, long offset, long length) { this.sourceAndDestination = sourceAndDestination; this.offset = offset; this.length = length; } public void run() { DataStorage.Iterator iterator = this.sourceAndDestination.iterator(DataStorage.READ_WRITE, this.offset, this.offset + this.length); while (this.length > 0) { double value = iterator.getDouble(); iterator.setDouble(modMultiply(value, value)); iterator.next(); this.length--; } } private DataStorage sourceAndDestination; private long offset, length; } /** * Default constructor. */ public DoubleNTTConvolutionStepStrategy() { } public void multiplyInPlace(DataStorage sourceAndDestination, DataStorage source, int modulus) throws ApfloatRuntimeException { assert (sourceAndDestination != source); long size = sourceAndDestination.getSize(); ParallelRunnable parallelRunnable = createMultiplyInPlaceParallelRunnable(sourceAndDestination, source, modulus); if (size <= Integer.MAX_VALUE && // Only if the size fits in an integer, but with memory arrays it should sourceAndDestination.isCached() && source.isCached()) // Only if the data storage supports efficient parallel random access { ParallelRunner.runParallel(parallelRunnable); } else { parallelRunnable.run(); // Just run in current thread without parallelization } } public void squareInPlace(DataStorage sourceAndDestination, int modulus) throws ApfloatRuntimeException { long size = sourceAndDestination.getSize(); ParallelRunnable parallelRunnable = createSquareInPlaceParallelRunnable(sourceAndDestination, modulus); if (size <= Integer.MAX_VALUE && // Only if the size fits in an integer, but with memory arrays it should sourceAndDestination.isCached()) // Only if the data storage supports efficient parallel random access { ParallelRunner.runParallel(parallelRunnable); } else { parallelRunnable.run(); // Just run in current thread without parallelization } } /** * Create a ParallelRunnable for multiplying the elements in-place. * * @param sourceAndDestination The first source data storage, which is also the destination. * @param source The second source data storage. * @param modulus Which modulus to use (0, 1, 2) * * @return An object suitable for multiplying the elements in parallel. */ protected ParallelRunnable createMultiplyInPlaceParallelRunnable(final DataStorage sourceAndDestination, final DataStorage source, int modulus) { final long size = sourceAndDestination.getSize(); setModulus(MODULUS[modulus]); ParallelRunnable parallelRunnable = new ParallelRunnable(size) { public Runnable getRunnable(long offset, long length) { return new MultiplyInPlaceRunnable(sourceAndDestination, source, offset, length); } }; return parallelRunnable; } /** * Create a ParallelRunnable for squaring the elements in-place. * * @param sourceAndDestination The source data storage, which is also the destination. * @param modulus Which modulus to use (0, 1, 2) * * @return An object suitable for squaring the elements in parallel. */ protected ParallelRunnable createSquareInPlaceParallelRunnable(final DataStorage sourceAndDestination, int modulus) { final long size = sourceAndDestination.getSize(); setModulus(MODULUS[modulus]); ParallelRunnable parallelRunnable = new ParallelRunnable(size) { public Runnable getRunnable(long offset, long length) { return new SquareInPlaceRunnable(sourceAndDestination, offset, length); } }; return parallelRunnable; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy