*
* This transform only works together with an {@link NTTStepStrategy} implementation
* that processes the data in columns instead of rows and a {@link MatrixStrategy}
* implementation that can transpose the data.
*
* The data size should be sufficiently large to meet the parallelization needs of the GPU.
* The GPU global size i.e. the number of columns in the data matrix should be at least 1024.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class ColumnSixStepFNTStrategy
extends SixStepFNTStrategy
{
/**
* Basic constructor.
*
* @param stepStrategy A step strategy that can process data in columns.
* @param matrixStrategy A matrix strategy that can process the data.
*/
public ColumnSixStepFNTStrategy(NTTStepStrategy stepStrategy, MatrixStrategy matrixStrategy)
{
super.stepStrategy = stepStrategy;
super.matrixStrategy = matrixStrategy;
}
@Override
protected void transposeInitial(ArrayAccess arrayAccess, int n1, int n2, boolean isInverse)
{
// Omitted as we want to process the columns, not rows
}
@Override
protected void transposeMiddle(ArrayAccess arrayAccess, int n1, int n2, boolean isInverse)
{
// Matrix is in transposed form compared to the normal six-step algorithm, so swap n1 and n2
super.transposeMiddle(arrayAccess, n2, n1, isInverse);
}
@Override
protected void multiplyElements(ArrayAccess arrayAccess, int rows, int columns, long length, long totalTransformLength, boolean isInverse, int modulus)
{
// Matrix is in transposed form compared to the normal six-step algorithm, so swap rows and columns
super.multiplyElements(arrayAccess, columns, rows, length, totalTransformLength, isInverse, modulus);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/ColumnTwoPassFNTStrategy.java 0000664 0000000 0000000 00000007106 14557414736 0032311 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.internal.TwoPassFNTStrategy;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.DataStorage;
import org.apfloat.spi.NTTStepStrategy;
/**
* Two-pass NTT implementation that processes the data in the columns of the matrix.
*
* This transform only works together with an {@link NTTStepStrategy} implementation
* that processes the data in columns instead of rows.
*
* Note that if the data size is too big compared to the maximum available memory then the
* data is read from disk in too thin slices and the level of parallelism may become too
* small for the GPU, ruining the performance. The GPU global size i.e. the number of columns
* read from the data matrix to memory at one time should be at least 1024.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class ColumnTwoPassFNTStrategy
extends TwoPassFNTStrategy
{
/**
* Basic constructor.
*
* @param stepStrategy A step strategy that can process data in columns.
*/
public ColumnTwoPassFNTStrategy(NTTStepStrategy stepStrategy)
{
// Note that there is no defaultStrategy here; if we get to the two-pass algorithm then we
// assume that the data size is always "big enough" for a sufficient level of parallelism on the GPU
super.stepStrategy = stepStrategy;
}
@Override
protected ArrayAccess getColumns(DataStorage dataStorage, int startColumn, int columns, int rows)
{
// Get columns un-transposed
return dataStorage.getArray(DataStorage.READ_WRITE, startColumn, columns, rows);
}
@Override
protected ArrayAccess getRows(DataStorage dataStorage, int startRow, int rows, int columns)
{
// Get rows transposed as we want to organize the data in columns
return dataStorage.subsequence(startRow * columns, rows * columns).getTransposedArray(DataStorage.READ_WRITE, 0, columns, rows);
}
@Override
protected void multiplyElements(ArrayAccess arrayAccess, int startRow, int startColumn, int rows, int columns, long length, long totalTransformLength, boolean isInverse, int modulus)
{
// Data is processed in transposed form compared to the normal two-pass algorithm, so swap rows and columns
super.multiplyElements(arrayAccess, startColumn, startRow, columns, rows, length, totalTransformLength, isInverse, modulus);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiBuilderFactory.java 0000664 0000000 0000000 00000003450 14557414736 0032325 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.NTTBuilder;
import org.apfloat.internal.IntBuilderFactory;
/**
* Builder factory for aparapi transform implementations for the int element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiBuilderFactory
extends IntBuilderFactory
{
/**
* Default constructor.
*/
public IntAparapiBuilderFactory()
{
}
@Override
public NTTBuilder getNTTBuilder()
{
return IntAparapiBuilderFactory.nttBuilder;
}
private static NTTBuilder nttBuilder = new IntAparapiNTTBuilder();
}
IntAparapiFactor3NTTStepStrategy.java 0000664 0000000 0000000 00000010354 14557414736 0033577 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.DataStorage;
import com.aparapi.Range;
import org.apfloat.internal.ApfloatInternalException;
import org.apfloat.internal.IntFactor3NTTStepStrategy;
import static org.apfloat.internal.IntModConstants.*;
/**
* Steps for the factor-3 NTT using the GPU, for the int element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiFactor3NTTStepStrategy
extends IntFactor3NTTStepStrategy
{
@Override
public void transformColumns(DataStorage dataStorage0, DataStorage dataStorage1, DataStorage dataStorage2, long startColumn, long columns, long power2length, long length, boolean isInverse, int modulus)
throws ApfloatRuntimeException
{
// Transform length is three times a power of two
assert (length == 3 * power2length);
// Check that the data storages use consecutive sections of the same memory array
if (!dataStorage0.isCached() || !dataStorage1.isCached() || !dataStorage2.isCached() ||
startColumn > Integer.MAX_VALUE || columns > Integer.MAX_VALUE)
{
throw new ApfloatInternalException("Data must be stored in memory");
}
ArrayAccess arrayAccess0 = dataStorage0.getArray(DataStorage.READ_WRITE, startColumn, (int) columns),
arrayAccess1 = dataStorage1.getArray(DataStorage.READ_WRITE, startColumn, (int) columns),
arrayAccess2 = dataStorage2.getArray(DataStorage.READ_WRITE, startColumn, (int) columns);
if (arrayAccess0.getIntData() != arrayAccess1.getIntData() || arrayAccess1.getIntData() != arrayAccess2.getIntData() ||
arrayAccess1.getOffset() != arrayAccess0.getOffset() + columns || arrayAccess2.getOffset() != arrayAccess1.getOffset() + columns)
{
throw new ApfloatInternalException("Data must be stored consecutively in memory");
}
setModulus(MODULUS[modulus]); // Modulus
int w = (isInverse ?
getInverseNthRoot(PRIMITIVE_ROOT[modulus], length) :
getForwardNthRoot(PRIMITIVE_ROOT[modulus], length)), // Forward/inverse n:th root
w3 = modPow(w, (int) power2length), // Forward/inverse 3rd root
ww = modMultiply(w, w),
w1 = negate(modDivide((int) 3, (int) 2)),
w2 = modAdd(w3, modDivide((int) 1, (int) 2));
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(isInverse ? IntKernel.INVERSE_TRANSFORM_COLUMNS : IntKernel.TRANSFORM_COLUMNS);
kernel.setArrayAccess(arrayAccess0);
kernel.setStartColumn((int) startColumn);
kernel.setColumns((int) columns);
kernel.setW(w);
kernel.setWw(ww);
kernel.setW1(w1);
kernel.setW2(w2);
kernel.setModulus(MODULUS[modulus]);
Range range = RangeHelper.create((int) columns);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiFactor3NTTStrategy.java 0000664 0000000 0000000 00000006552 14557414736 0033027 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.DataStorage;
import org.apfloat.internal.ApfloatInternalException;
import org.apfloat.internal.Factor3NTTStrategy;
/**
* Factor-3 NTT implementation for the int element type.
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
public class IntAparapiFactor3NTTStrategy
extends Factor3NTTStrategy
{
/**
* Default constructor.
*/
public IntAparapiFactor3NTTStrategy()
{
super(new ColumnSixStepFNTStrategy(new IntAparapiNTTStepStrategy(), new IntAparapiMatrixStrategy()));
super.stepStrategy = new IntAparapiFactor3NTTStepStrategy();
}
@Override
public void transform(DataStorage dataStorage, int modulus)
throws ApfloatRuntimeException
{
preTransform(dataStorage);
super.transform(dataStorage, modulus);
postTransform(dataStorage);
}
@Override
public void inverseTransform(DataStorage dataStorage, int modulus, long totalTransformLength)
throws ApfloatRuntimeException
{
preTransform(dataStorage);
super.inverseTransform(dataStorage, modulus, totalTransformLength);
postTransform(dataStorage);
}
private void preTransform(DataStorage dataStorage)
{
long length = dataStorage.getSize();
if (length > Integer.MAX_VALUE)
{
throw new ApfloatInternalException("Maximum array length exceeded: " + length);
}
ArrayAccess arrayAccess = dataStorage.getArray(DataStorage.READ_WRITE, 0, (int) length);
IntKernel kernel = IntKernel.getInstance();
kernel.setExplicit(true);
kernel.put(arrayAccess.getIntData());
}
private void postTransform(DataStorage dataStorage)
{
long length = dataStorage.getSize();
assert (length <= Integer.MAX_VALUE);
ArrayAccess arrayAccess = dataStorage.getArray(DataStorage.READ_WRITE, 0, (int) length);
IntKernel kernel = IntKernel.getInstance();
kernel.get(arrayAccess.getIntData());
kernel.cleanUpArrays();
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiMatrixStrategy.java 0000664 0000000 0000000 00000015414 14557414736 0032401 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.MatrixStrategy;
import org.apfloat.internal.ApfloatInternalException;
import com.aparapi.Range;
/**
* Matrix transposition in the GPU for the int type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiMatrixStrategy
implements MatrixStrategy
{
/**
* Default constructor.
*/
public IntAparapiMatrixStrategy()
{
}
@Override
public void transpose(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
if (n1 == n2)
{
// Simply transpose
transposeSquare(arrayAccess, n1, n1);
}
else if (n2 == 2 * n1)
{
// First transpose two n1 x n1 blocks
transposeSquare(arrayAccess, n1, n2);
transposeSquare(arrayAccess.subsequence(n1, arrayAccess.getLength() - n1), n1, n2);
// Then permute the rows to correct order
permuteToHalfWidth(arrayAccess, n1, n2);
}
else if (n1 == 2 * n2)
{
// First permute the rows to correct order
permuteToDoubleWidth(arrayAccess, n1, n2);
// Then transpose two n2 x n2 blocks
transposeSquare(arrayAccess, n2, n1);
transposeSquare(arrayAccess.subsequence(n2, arrayAccess.getLength() - n2), n2, n1);
}
else
{
throw new ApfloatInternalException("Must be n1 = n2, n1 = 2*n2 or n2 = 2*n1; matrix is " + n1 + " x " + n2);
}
}
@Override
public void transposeSquare(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(IntKernel.TRANSPOSE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2);
Range range = RangeHelper.create2D(n1, n1);
kernel.execute(range);
}
@Override
public void permuteToHalfWidth(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
// Permute the rows of matrix to correct order, to make the n1 x n2 matrix half as wide (2*n1 x n2/2)
if (n1 < 2)
{
return;
}
int twicen1 = 2 * n1;
boolean[] isRowDone = new boolean[twicen1];
int[] index = new int[twicen1 * 2]; // Overly big but twicen1 just isn't enough
int j = 1,
p = 0;
do
{
int m = j;
index[p++] = m;
isRowDone[m] = true;
m = (m < n1 ? 2 * m : 2 * (m - n1) + 1);
while (m != j)
{
isRowDone[m] = true;
index[p++] = m;
m = (m < n1 ? 2 * m : 2 * (m - n1) + 1);
}
index[p++] = 0;
while (isRowDone[j])
{
j++;
}
} while (j < twicen1 - 1);
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(IntKernel.PERMUTE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2 / 2);
kernel.setIndex(index);
kernel.setIndexCount(p);
kernel.put(index);
Range range = RangeHelper.create(n2 / 2);
kernel.execute(range);
}
@Override
public void permuteToDoubleWidth(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
if (n1 < 2)
{
throw new ApfloatInternalException("Matrix height must be at least 2.");
}
// Permute the rows of matrix to correct order, to make the n1 x n2 matrix twice as wide (n1/2 x 2*n2)
if (n1 < 4)
{
return;
}
int halfn1 = n1 / 2;
boolean[] isRowDone = new boolean[n1];
int[] index = new int[n1 * 2]; // Overly big but n1 just isn't enough
int j = 1,
p = 0;
do
{
int m = j;
index[p++] = m;
isRowDone[m] = true;
m = ((m & 1) != 0 ? m / 2 + halfn1 : m / 2);
while (m != j)
{
isRowDone[m] = true;
index[p++] = m;
m = ((m & 1) != 0 ? m / 2 + halfn1 : m / 2);
}
index[p++] = 0;
while (isRowDone[j])
{
j++;
}
} while (j < n1 - 1);
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(IntKernel.PERMUTE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2);
kernel.setIndex(index);
kernel.setIndexCount(p);
kernel.put(index);
Range range = RangeHelper.create(n2);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiNTTBuilder.java 0000664 0000000 0000000 00000005737 14557414736 0031375 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.BuilderFactory;
import org.apfloat.spi.NTTStrategy;
import org.apfloat.ApfloatContext;
import org.apfloat.internal.IntNTTBuilder;
/**
* NTT Builder for aparapi transform implementations for the int element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiNTTBuilder
extends IntNTTBuilder
{
private static final int MIN_GPU_LENGTH = 1048576;
/**
* Default constructor.
*/
public IntAparapiNTTBuilder()
{
}
@Override
protected NTTStrategy createSixStepFNTStrategy(long size)
{
long length = size;
if (length < MIN_GPU_LENGTH)
{
return super.createSixStepFNTStrategy(size);
}
return new IntAparapiSixStepFNTStrategy();
}
@Override
protected NTTStrategy createTwoPassFNTStrategy(long size)
{
long length = size;
if (length < MIN_GPU_LENGTH)
{
return super.createTwoPassFNTStrategy(size);
}
return new ColumnTwoPassFNTStrategy(new IntAparapiNTTStepStrategy());
}
@Override
protected NTTStrategy createFactor3NTTStrategy(long size, NTTStrategy nttStrategy)
{
if (nttStrategy instanceof IntAparapiSixStepFNTStrategy)
{
ApfloatContext ctx = ApfloatContext.getContext();
BuilderFactory builderFactory = ctx.getBuilderFactory();
long maxMemoryBlockSize = ctx.getMaxMemoryBlockSize() / builderFactory.getElementSize();
if (size <= maxMemoryBlockSize && size <= Integer.MAX_VALUE)
{
return new IntAparapiFactor3NTTStrategy();
}
}
return super.createFactor3NTTStrategy(size, nttStrategy);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiNTTStepStrategy.java 0000664 0000000 0000000 00000011201 14557414736 0032424 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import com.aparapi.Range;
import org.apfloat.internal.IntNTTStepStrategy;
import org.apfloat.internal.IntWTables;
import org.apfloat.internal.Scramble;
import static org.apfloat.internal.IntModConstants.*;
/**
* NTT steps for the int element type aparapi transforms.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiNTTStepStrategy
extends IntNTTStepStrategy
{
/**
* Default constructor.
*/
public IntAparapiNTTStepStrategy()
{
}
@Override
public void multiplyElements(ArrayAccess arrayAccess, int startRow, int startColumn, int rows, int columns, long length, long totalTransformLength, boolean isInverse, int modulus)
throws ApfloatRuntimeException
{
setModulus(MODULUS[modulus]);
int w = (isInverse ?
getInverseNthRoot(PRIMITIVE_ROOT[modulus], length) :
getForwardNthRoot(PRIMITIVE_ROOT[modulus], length));
int scaleFactor = (isInverse ?
modDivide((int) 1, (int) totalTransformLength) :
(int) 1);
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(IntKernel.MULTIPLY_ELEMENTS);
kernel.setArrayAccess(arrayAccess);
kernel.setStartRow(startRow);
kernel.setStartColumn(startColumn);
kernel.setRows(rows);
kernel.setColumns(columns);
kernel.setW(w);
kernel.setScaleFactor(scaleFactor);
kernel.setModulus(MODULUS[modulus]);
Range range = RangeHelper.create(columns);
kernel.execute(range);
}
/**
* Transform the columns of the data matrix. Note that this method expects the data
* to be organized in columns, not rows. The arguments length and
* count still mean the length of one transform and number of transforms
* to be done.
*
* @param arrayAccess The memory array to split to columns and to transform.
* @param length Length of one transform (one columns).
* @param count Number of columns.
* @param isInverse true if an inverse transform is performed, false if a forward transform is performed.
* @param permute If permutation should be done.
* @param modulus Index of the modulus.
*/
@Override
public void transformRows(ArrayAccess arrayAccess, int length, int count, boolean isInverse, boolean permute, int modulus)
throws ApfloatRuntimeException
{
int[] wTable = (isInverse ?
IntWTables.getInverseWTable(modulus, length) :
IntWTables.getWTable(modulus, length));
int[] permutationTable = (permute ? Scramble.createScrambleTable(length) : null);
IntKernel kernel = IntKernel.getInstance();
kernel.setOp(isInverse ? IntKernel.INVERSE_TRANSFORM_ROWS : IntKernel.TRANSFORM_ROWS);
kernel.setLength(length);
kernel.setArrayAccess(arrayAccess);
kernel.setWTable(wTable);
kernel.setPermutationTable(permutationTable);
kernel.setModulus(MODULUS[modulus]);
kernel.put(wTable);
if (permutationTable != null)
{
kernel.put(permutationTable);
}
Range range = RangeHelper.create(count);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntAparapiSixStepFNTStrategy.java 0000664 0000000 0000000 00000004225 14557414736 0033102 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.ArrayAccess;
/**
* Six-step NTT implementation for the int element type.
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
public class IntAparapiSixStepFNTStrategy
extends ColumnSixStepFNTStrategy
{
/**
* Default constructor.
*/
public IntAparapiSixStepFNTStrategy()
{
super(new IntAparapiNTTStepStrategy(), new IntAparapiMatrixStrategy());
}
@Override
protected void preTransform(ArrayAccess arrayAccess)
{
IntKernel kernel = IntKernel.getInstance();
kernel.setExplicit(true);
kernel.put(arrayAccess.getIntData());
super.preTransform(arrayAccess);
}
@Override
protected void postTransform(ArrayAccess arrayAccess)
{
super.postTransform(arrayAccess);
IntKernel kernel = IntKernel.getInstance();
kernel.get(arrayAccess.getIntData());
kernel.cleanUpArrays();
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/IntKernel.java 0000664 0000000 0000000 00000035256 14557414736 0027342 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import com.aparapi.Kernel;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
/**
* Kernel for the int element type. Contains everything needed for the NTT.
* The data is organized in columns, not rows, for efficient processing on the GPU.
*
* Due to the extreme parallelization requirements (global size should be at lest 1024)
* this algorithm works efficiently only with 4 million decimal digit calculations or bigger.
* However with 4 million digits, it's only approximately as fast as the pure-Java
* version (depending on the GPU and CPU hardware). On the other hand, the algorithm
* mathematically only works up to about 226 million digits. So the useful range is only
* somewhere around 10-200 million digits.
*
* Some notes about the aparapi specific requirements for code that must be converted to OpenCL:
*
*
assert() does not work
*
Can't check for null
*
Can't get array length
*
Arrays referenced by the kernel can't be null even if they are not accessed
*
Arrays referenced by the kernel can't be zero-length even if they are not accessed
*
Can't invoke methods in other classes e.g. enclosing class of an inner class
*
Early return statements do not work
*
Variables used inside loops must be initialized before the loop
*
Must compile the class with full debug information i.e. with -g
*
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
class IntKernel
extends Kernel
{
private IntKernel()
{
}
public static IntKernel getInstance()
{
return IntKernel.kernel.get();
}
private static ThreadLocal kernel = ThreadLocal.withInitial(IntKernel::new);
// Methods for calculating the column transforms in parallel
public static final int TRANSFORM_ROWS = 1;
public static final int INVERSE_TRANSFORM_ROWS = 2;
public void setLength(int length)
{
this.length = length; // Transform length
}
public void setArrayAccess(ArrayAccess arrayAccess)
throws ApfloatRuntimeException
{
this.data = arrayAccess.getIntData();
this.offset = arrayAccess.getOffset();
if (this.length != 0)
{
this.stride = arrayAccess.getLength() / this.length;
}
}
public void setWTable(int[] wTable)
{
this.wTable = wTable;
}
public void setPermutationTable(int[] permutationTable)
{
this.permutationTable = (permutationTable == null ? new int[1] : permutationTable); // Zero-length array or null won't work
this.permutationTableLength = (permutationTable == null ? 0 : permutationTable.length);
}
private void columnTableFNT()
{
int nn, istep = 0, mmax = 0, r = 0;
int[] data = this.data;
int offset = this.offset + getGlobalId();
int stride = this.stride;
nn = this.length;
if (nn >= 2)
{
r = 1;
mmax = nn >> 1;
while (mmax > 0)
{
istep = mmax << 1;
// Optimize first step when wr = 1
for (int i = offset; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
int a = data[i];
int 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 * stride; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
int a = data[i];
int b = data[j];
data[i] = modAdd(a, b);
data[j] = modMultiply(this.wTable[t], modSubtract(a, b));
}
t += r;
}
r <<= 1;
mmax >>= 1;
}
if (this.permutationTableLength > 0)
{
columnScramble(offset);
}
}
}
private void inverseColumnTableFNT()
{
int nn, istep = 0, mmax = 0, r = 0;
int[] data = this.data;
int offset = this.offset + getGlobalId();
int stride = this.stride;
nn = this.length;
if (nn >= 2)
{
if (this.permutationTableLength > 0)
{
columnScramble(offset);
}
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 * stride; i += istep * stride)
{
int j = i + mmax * stride;
int 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 * stride; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
int wTemp = modMultiply(this.wTable[t], data[j]);
data[j] = modSubtract(data[i], wTemp);
data[i] = modAdd(data[i], wTemp);
}
t += r;
}
mmax = istep;
}
}
}
private void columnScramble(int offset)
{
for (int k = 0; k < this.permutationTableLength; k += 2)
{
int i = offset + this.permutationTable[k] * this.stride,
j = offset + this.permutationTable[k + 1] * this.stride;
int tmp = this.data[i];
this.data[i] = this.data[j];
this.data[j] = tmp;
}
}
private int modMultiply(int a, int b)
{
long t = (long) a * (long) b;
//int r1 = a * b - (int) (this.inverseModulus * (double) a * (double) b) * this.modulus,
int r1 = (int) t - (int) ((t >>> 30) * this.inverseModulus >>> 33) * this.modulus,
r2 = r1 - this.modulus;
return (r2 < 0 ? r1 : r2);
}
private int modAdd(int a, int b)
{
int r1 = a + b,
r2 = r1 - this.modulus;
return (r2 < 0 ? r1 : r2);
}
private int modSubtract(int a, int b)
{
int r1 = a - b,
r2 = r1 + this.modulus;
return (r1 < 0 ? r2 : r1);
}
public void setModulus(int modulus)
{
//this.inverseModulus = 1.0 / (modulus + 0.5); // Round down
this.inverseModulus = (long) (9223372036854775808.0 / (double) modulus);
this.modulus = modulus;
}
public int getModulus()
{
return this.modulus;
}
private int stride;
private int length;
private int[] data;
private int offset;
private int[] wTable = { 0 };
private int[] permutationTable = { 0 };
private int permutationTableLength;
private int modulus;
//private double inverseModulus;
private long inverseModulus;
// Methods for transposing the matrix
public static final int TRANSPOSE = 3;
public static final int PERMUTE = 4;
public void setN2(int n2)
{
this.n2 = n2;
}
public void setIndex(int[] index)
{
this.index = index;
}
public void setIndexCount(int indexCount)
{
this.indexCount = indexCount;
}
private void transpose()
{
int i = getGlobalId(0),
j = getGlobalId(1);
if (i < j)
{
int position1 = this.offset + j * this.n2 + i,
position2 = this.offset + i * this.n2 + j;
int tmp = this.data[position1];
this.data[position1] = this.data[position2];
this.data[position2] = tmp;
}
}
private void permute()
{
int j = getGlobalId();
for (int i = 0; i < this.indexCount; i++)
{
int o = this.index[i];
int tmp = this.data[this.offset + this.n2 * o + j];
for (i++; this.index[i] != 0; i++)
{
int m = this.index[i];
this.data[this.offset + this.n2 * o + j] = this.data[this.offset + this.n2 * m + j];
o = m;
}
this.data[this.offset + this.n2 * o + j] = tmp;
}
}
private int n2;
private int[] index = { 0 };
private int indexCount;
// Methods for multiplying elements in the matrix
public static final int MULTIPLY_ELEMENTS = 5;
public void setStartRow(int startRow)
{
this.startRow = startRow;
}
public void setStartColumn(int startColumn)
{
this.startColumn = startColumn;
}
public void setRows(int rows)
{
this.rows = rows;
}
public void setColumns(int columns)
{
this.columns = columns;
}
public void setW(int w)
{
this.w = w;
}
public void setScaleFactor(int scaleFactor)
{
this.scaleFactor = scaleFactor;
}
private void multiplyElements()
{
int[] data = this.data;
int position = this.offset + getGlobalId();
int rowFactor = modPow(this.w, (int) this.startRow);
int columnFactor = modPow(this.w, (int) this.startColumn + getGlobalId());
int rowStartFactor = modMultiply(this.scaleFactor, modPow(rowFactor, (int) this.startColumn + getGlobalId()));
for (int i = 0; i < this.rows; i++)
{
data[position] = modMultiply(data[position], rowStartFactor);
position += this.columns;
rowStartFactor = modMultiply(rowStartFactor, columnFactor);
}
}
private int modPow(int a, int n)
{
if (n == 0)
{
return 1;
}
else if (n < 0)
{
n = getModulus() - 1 + n;
}
int exponent = (int) n;
while ((exponent & 1) == 0)
{
a = modMultiply(a, a);
exponent >>= 1;
}
int r = a;
for (exponent >>= 1; exponent > 0; exponent >>= 1)
{
a = modMultiply(a, a);
if ((exponent & 1) != 0)
{
r = modMultiply(r, a);
}
}
return r;
}
private int startRow;
private int startColumn;
private int rows;
private int columns;
private int w;
private int scaleFactor;
// Methods for factor-3 transform
public static final int TRANSFORM_COLUMNS = 6;
public static final int INVERSE_TRANSFORM_COLUMNS = 7;
public void setOp(int op)
{
this.op = op;
}
public void setWw(int ww)
{
this.ww = ww;
}
public void setW1(int w1)
{
this.w1 = w1;
}
public void setW2(int w2)
{
this.w2 = w2;
}
@Override
public void run()
{
if (this.op == TRANSFORM_ROWS)
{
columnTableFNT();
}
else if (this.op == INVERSE_TRANSFORM_ROWS)
{
inverseColumnTableFNT();
}
else if (this.op == TRANSPOSE)
{
transpose();
}
else if (this.op == PERMUTE)
{
permute();
}
else if (this.op == MULTIPLY_ELEMENTS)
{
multiplyElements();
}
else if (this.op == TRANSFORM_COLUMNS || this.op == INVERSE_TRANSFORM_COLUMNS)
{
transformColumns();
}
}
private void transformColumns()
{
int i = getGlobalId();
int tmp1 = modPow(this.w, (int) this.startColumn + i),
tmp2 = modPow(this.ww, (int) this.startColumn + i);
// 3-point WFTA on the corresponding array elements
int x0 = this.data[this.offset + i],
x1 = this.data[this.offset + this.columns + i],
x2 = this.data[this.offset + 2 * this.columns + i],
t;
if (this.op == INVERSE_TRANSFORM_COLUMNS)
{
// Multiply before transform
x1 = modMultiply(x1, tmp1);
x2 = modMultiply(x2, tmp2);
}
// Transform column
t = modAdd(x1, x2);
x2 = modSubtract(x1, x2);
x0 = modAdd(x0, t);
t = modMultiply(t, this.w1);
x2 = modMultiply(x2, this.w2);
t = modAdd(t, x0);
x1 = modAdd(t, x2);
x2 = modSubtract(t, x2);
if (this.op == TRANSFORM_COLUMNS)
{
// Multiply after transform
x1 = modMultiply(x1, tmp1);
x2 = modMultiply(x2, tmp2);
}
this.data[this.offset + i] = x0;
this.data[this.offset + this.columns + i] = x1;
this.data[this.offset + 2 * this.columns + i] = x2;
}
private int op;
private int ww;
private int w1;
private int w2;
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiBuilderFactory.java 0000664 0000000 0000000 00000003457 14557414736 0032501 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.NTTBuilder;
import org.apfloat.internal.LongBuilderFactory;
/**
* Builder factory for aparapi transform implementations for the long element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiBuilderFactory
extends LongBuilderFactory
{
/**
* Default constructor.
*/
public LongAparapiBuilderFactory()
{
}
@Override
public NTTBuilder getNTTBuilder()
{
return LongAparapiBuilderFactory.nttBuilder;
}
private static NTTBuilder nttBuilder = new LongAparapiNTTBuilder();
}
LongAparapiFactor3NTTStepStrategy.java 0000664 0000000 0000000 00000010405 14557414736 0033741 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.DataStorage;
import com.aparapi.Range;
import org.apfloat.internal.ApfloatInternalException;
import org.apfloat.internal.LongFactor3NTTStepStrategy;
import static org.apfloat.internal.LongModConstants.*;
/**
* Steps for the factor-3 NTT using the GPU, for the long element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiFactor3NTTStepStrategy
extends LongFactor3NTTStepStrategy
{
@Override
public void transformColumns(DataStorage dataStorage0, DataStorage dataStorage1, DataStorage dataStorage2, long startColumn, long columns, long power2length, long length, boolean isInverse, int modulus)
throws ApfloatRuntimeException
{
// Transform length is three times a power of two
assert (length == 3 * power2length);
// Check that the data storages use consecutive sections of the same memory array
if (!dataStorage0.isCached() || !dataStorage1.isCached() || !dataStorage2.isCached() ||
startColumn > Integer.MAX_VALUE || columns > Integer.MAX_VALUE)
{
throw new ApfloatInternalException("Data must be stored in memory");
}
ArrayAccess arrayAccess0 = dataStorage0.getArray(DataStorage.READ_WRITE, startColumn, (int) columns),
arrayAccess1 = dataStorage1.getArray(DataStorage.READ_WRITE, startColumn, (int) columns),
arrayAccess2 = dataStorage2.getArray(DataStorage.READ_WRITE, startColumn, (int) columns);
if (arrayAccess0.getLongData() != arrayAccess1.getLongData() || arrayAccess1.getLongData() != arrayAccess2.getLongData() ||
arrayAccess1.getOffset() != arrayAccess0.getOffset() + columns || arrayAccess2.getOffset() != arrayAccess1.getOffset() + columns)
{
throw new ApfloatInternalException("Data must be stored consecutively in memory");
}
setModulus(MODULUS[modulus]); // Modulus
long w = (isInverse ?
getInverseNthRoot(PRIMITIVE_ROOT[modulus], length) :
getForwardNthRoot(PRIMITIVE_ROOT[modulus], length)), // Forward/inverse n:th root
w3 = modPow(w, (long) power2length), // Forward/inverse 3rd root
ww = modMultiply(w, w),
w1 = negate(modDivide((long) 3, (long) 2)),
w2 = modAdd(w3, modDivide((long) 1, (long) 2));
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(isInverse ? LongKernel.INVERSE_TRANSFORM_COLUMNS : LongKernel.TRANSFORM_COLUMNS);
kernel.setArrayAccess(arrayAccess0);
kernel.setStartColumn((int) startColumn);
kernel.setColumns((int) columns);
kernel.setW(w);
kernel.setWw(ww);
kernel.setW1(w1);
kernel.setW2(w2);
kernel.setModulus(MODULUS[modulus]);
Range range = RangeHelper.create((int) columns);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiFactor3NTTStrategy.java 0000664 0000000 0000000 00000006566 14557414736 0033201 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.DataStorage;
import org.apfloat.internal.ApfloatInternalException;
import org.apfloat.internal.Factor3NTTStrategy;
/**
* Factor-3 NTT implementation for the long element type.
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
public class LongAparapiFactor3NTTStrategy
extends Factor3NTTStrategy
{
/**
* Default constructor.
*/
public LongAparapiFactor3NTTStrategy()
{
super(new ColumnSixStepFNTStrategy(new LongAparapiNTTStepStrategy(), new LongAparapiMatrixStrategy()));
super.stepStrategy = new LongAparapiFactor3NTTStepStrategy();
}
@Override
public void transform(DataStorage dataStorage, int modulus)
throws ApfloatRuntimeException
{
preTransform(dataStorage);
super.transform(dataStorage, modulus);
postTransform(dataStorage);
}
@Override
public void inverseTransform(DataStorage dataStorage, int modulus, long totalTransformLength)
throws ApfloatRuntimeException
{
preTransform(dataStorage);
super.inverseTransform(dataStorage, modulus, totalTransformLength);
postTransform(dataStorage);
}
private void preTransform(DataStorage dataStorage)
{
long length = dataStorage.getSize();
if (length > Integer.MAX_VALUE)
{
throw new ApfloatInternalException("Maximum array length exceeded: " + length);
}
ArrayAccess arrayAccess = dataStorage.getArray(DataStorage.READ_WRITE, 0, (int) length);
LongKernel kernel = LongKernel.getInstance();
kernel.setExplicit(true);
kernel.put(arrayAccess.getLongData());
}
private void postTransform(DataStorage dataStorage)
{
long length = dataStorage.getSize();
assert (length <= Integer.MAX_VALUE);
ArrayAccess arrayAccess = dataStorage.getArray(DataStorage.READ_WRITE, 0, (int) length);
LongKernel kernel = LongKernel.getInstance();
kernel.get(arrayAccess.getLongData());
kernel.cleanUpArrays();
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiMatrixStrategy.java 0000664 0000000 0000000 00000015430 14557414736 0032544 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import org.apfloat.spi.MatrixStrategy;
import org.apfloat.internal.ApfloatInternalException;
import com.aparapi.Range;
/**
* Matrix transposition in the GPU for the long type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiMatrixStrategy
implements MatrixStrategy
{
/**
* Default constructor.
*/
public LongAparapiMatrixStrategy()
{
}
@Override
public void transpose(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
if (n1 == n2)
{
// Simply transpose
transposeSquare(arrayAccess, n1, n1);
}
else if (n2 == 2 * n1)
{
// First transpose two n1 x n1 blocks
transposeSquare(arrayAccess, n1, n2);
transposeSquare(arrayAccess.subsequence(n1, arrayAccess.getLength() - n1), n1, n2);
// Then permute the rows to correct order
permuteToHalfWidth(arrayAccess, n1, n2);
}
else if (n1 == 2 * n2)
{
// First permute the rows to correct order
permuteToDoubleWidth(arrayAccess, n1, n2);
// Then transpose two n2 x n2 blocks
transposeSquare(arrayAccess, n2, n1);
transposeSquare(arrayAccess.subsequence(n2, arrayAccess.getLength() - n2), n2, n1);
}
else
{
throw new ApfloatInternalException("Must be n1 = n2, n1 = 2*n2 or n2 = 2*n1; matrix is " + n1 + " x " + n2);
}
}
@Override
public void transposeSquare(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(LongKernel.TRANSPOSE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2);
Range range = RangeHelper.create2D(n1, n1);
kernel.execute(range);
}
@Override
public void permuteToHalfWidth(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
// Permute the rows of matrix to correct order, to make the n1 x n2 matrix half as wide (2*n1 x n2/2)
if (n1 < 2)
{
return;
}
int twicen1 = 2 * n1;
boolean[] isRowDone = new boolean[twicen1];
int[] index = new int[twicen1 * 2]; // Overly big but twicen1 just isn't enough
int j = 1,
p = 0;
do
{
int m = j;
index[p++] = m;
isRowDone[m] = true;
m = (m < n1 ? 2 * m : 2 * (m - n1) + 1);
while (m != j)
{
isRowDone[m] = true;
index[p++] = m;
m = (m < n1 ? 2 * m : 2 * (m - n1) + 1);
}
index[p++] = 0;
while (isRowDone[j])
{
j++;
}
} while (j < twicen1 - 1);
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(LongKernel.PERMUTE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2 / 2);
kernel.setIndex(index);
kernel.setIndexCount(p);
kernel.put(index);
Range range = RangeHelper.create(n2 / 2);
kernel.execute(range);
}
@Override
public void permuteToDoubleWidth(ArrayAccess arrayAccess, int n1, int n2)
throws ApfloatRuntimeException
{
if (n1 != (n1 & -n1) ||
n2 != (n2 & -n2) ||
n1 <= 0 || n2 <= 0)
{
throw new ApfloatInternalException("Matrix size must be a power of two, not " + n1 + " x " + n2);
}
if (n1 < 2)
{
throw new ApfloatInternalException("Matrix height must be at least 2.");
}
// Permute the rows of matrix to correct order, to make the n1 x n2 matrix twice as wide (n1/2 x 2*n2)
if (n1 < 4)
{
return;
}
int halfn1 = n1 / 2;
boolean[] isRowDone = new boolean[n1];
int[] index = new int[n1 * 2]; // Overly big but n1 just isn't enough
int j = 1,
p = 0;
do
{
int m = j;
index[p++] = m;
isRowDone[m] = true;
m = ((m & 1) != 0 ? m / 2 + halfn1 : m / 2);
while (m != j)
{
isRowDone[m] = true;
index[p++] = m;
m = ((m & 1) != 0 ? m / 2 + halfn1 : m / 2);
}
index[p++] = 0;
while (isRowDone[j])
{
j++;
}
} while (j < n1 - 1);
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(LongKernel.PERMUTE);
kernel.setArrayAccess(arrayAccess);
kernel.setN2(n2);
kernel.setIndex(index);
kernel.setIndexCount(p);
kernel.put(index);
Range range = RangeHelper.create(n2);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiNTTBuilder.java 0000664 0000000 0000000 00000005750 14557414736 0031535 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.BuilderFactory;
import org.apfloat.spi.NTTStrategy;
import org.apfloat.ApfloatContext;
import org.apfloat.internal.LongNTTBuilder;
/**
* NTT Builder for aparapi transform implementations for the long element type.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiNTTBuilder
extends LongNTTBuilder
{
private static final int MIN_GPU_LENGTH = 1048576;
/**
* Default constructor.
*/
public LongAparapiNTTBuilder()
{
}
@Override
protected NTTStrategy createSixStepFNTStrategy(long size)
{
long length = size;
if (length < MIN_GPU_LENGTH)
{
return super.createSixStepFNTStrategy(size);
}
return new LongAparapiSixStepFNTStrategy();
}
@Override
protected NTTStrategy createTwoPassFNTStrategy(long size)
{
long length = size;
if (length < MIN_GPU_LENGTH)
{
return super.createTwoPassFNTStrategy(size);
}
return new ColumnTwoPassFNTStrategy(new LongAparapiNTTStepStrategy());
}
@Override
protected NTTStrategy createFactor3NTTStrategy(long size, NTTStrategy nttStrategy)
{
if (nttStrategy instanceof LongAparapiSixStepFNTStrategy)
{
ApfloatContext ctx = ApfloatContext.getContext();
BuilderFactory builderFactory = ctx.getBuilderFactory();
long maxMemoryBlockSize = ctx.getMaxMemoryBlockSize() / builderFactory.getElementSize();
if (size <= maxMemoryBlockSize && size <= Integer.MAX_VALUE)
{
return new LongAparapiFactor3NTTStrategy();
}
}
return super.createFactor3NTTStrategy(size, nttStrategy);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiNTTStepStrategy.java 0000664 0000000 0000000 00000011235 14557414736 0032600 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
import com.aparapi.Range;
import org.apfloat.internal.LongNTTStepStrategy;
import org.apfloat.internal.LongWTables;
import org.apfloat.internal.Scramble;
import static org.apfloat.internal.LongModConstants.*;
/**
* NTT steps for the long element type aparapi transforms.
*
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiNTTStepStrategy
extends LongNTTStepStrategy
{
/**
* Default constructor.
*/
public LongAparapiNTTStepStrategy()
{
}
@Override
public void multiplyElements(ArrayAccess arrayAccess, int startRow, int startColumn, int rows, int columns, long length, long totalTransformLength, boolean isInverse, int modulus)
throws ApfloatRuntimeException
{
setModulus(MODULUS[modulus]);
long w = (isInverse ?
getInverseNthRoot(PRIMITIVE_ROOT[modulus], length) :
getForwardNthRoot(PRIMITIVE_ROOT[modulus], length));
long scaleFactor = (isInverse ?
modDivide((long) 1, (long) totalTransformLength) :
(long) 1);
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(LongKernel.MULTIPLY_ELEMENTS);
kernel.setArrayAccess(arrayAccess);
kernel.setStartRow(startRow);
kernel.setStartColumn(startColumn);
kernel.setRows(rows);
kernel.setColumns(columns);
kernel.setW(w);
kernel.setScaleFactor(scaleFactor);
kernel.setModulus(MODULUS[modulus]);
Range range = RangeHelper.create(columns);
kernel.execute(range);
}
/**
* Transform the columns of the data matrix. Note that this method expects the data
* to be organized in columns, not rows. The arguments length and
* count still mean the length of one transform and number of transforms
* to be done.
*
* @param arrayAccess The memory array to split to columns and to transform.
* @param length Length of one transform (one columns).
* @param count Number of columns.
* @param isInverse true if an inverse transform is performed, false if a forward transform is performed.
* @param permute If permutation should be done.
* @param modulus Index of the modulus.
*/
@Override
public void transformRows(ArrayAccess arrayAccess, int length, int count, boolean isInverse, boolean permute, int modulus)
throws ApfloatRuntimeException
{
long[] wTable = (isInverse ?
LongWTables.getInverseWTable(modulus, length) :
LongWTables.getWTable(modulus, length));
int[] permutationTable = (permute ? Scramble.createScrambleTable(length) : null);
LongKernel kernel = LongKernel.getInstance();
kernel.setOp(isInverse ? LongKernel.INVERSE_TRANSFORM_ROWS : LongKernel.TRANSFORM_ROWS);
kernel.setLength(length);
kernel.setArrayAccess(arrayAccess);
kernel.setWTable(wTable);
kernel.setPermutationTable(permutationTable);
kernel.setModulus(MODULUS[modulus]);
kernel.put(wTable);
if (permutationTable != null)
{
kernel.put(permutationTable);
}
Range range = RangeHelper.create(count);
kernel.execute(range);
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongAparapiSixStepFNTStrategy.java 0000664 0000000 0000000 00000004240 14557414736 0033244 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.spi.ArrayAccess;
/**
* Six-step NTT implementation for the long element type.
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
public class LongAparapiSixStepFNTStrategy
extends ColumnSixStepFNTStrategy
{
/**
* Default constructor.
*/
public LongAparapiSixStepFNTStrategy()
{
super(new LongAparapiNTTStepStrategy(), new LongAparapiMatrixStrategy());
}
@Override
protected void preTransform(ArrayAccess arrayAccess)
{
LongKernel kernel = LongKernel.getInstance();
kernel.setExplicit(true);
kernel.put(arrayAccess.getLongData());
super.preTransform(arrayAccess);
}
@Override
protected void postTransform(ArrayAccess arrayAccess)
{
super.postTransform(arrayAccess);
LongKernel kernel = LongKernel.getInstance();
kernel.get(arrayAccess.getLongData());
kernel.cleanUpArrays();
}
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/LongKernel.java 0000664 0000000 0000000 00000035466 14557414736 0027512 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import com.aparapi.Kernel;
import org.apfloat.ApfloatRuntimeException;
import org.apfloat.spi.ArrayAccess;
/**
* Kernel for the long element type. Contains everything needed for the NTT.
* The data is organized in columns, not rows, for efficient processing on the GPU.
*
* Due to the extreme parallelization requirements (global size should be at lest 1024)
* this algorithm works efficiently only with 8 million decimal digit calculations or bigger.
* However with 8 million digits, it's only approximately as fast as the pure-Java
* version (depending on the GPU and CPU hardware). Depending on the total amount of memory
* available for the GPU this algorithm will fail (or revert to the very slow software emulation)
* e.g. at one-billion-digit calculations if your GPU has 1 GB of memory. The maximum power-of-two
* size for a Java array is one billion (230) so if your GPU has more than 8 GB of
* memory then the algorithm can never fail (as any Java long[] will always fit to the GPU memory).
*
* Some notes about the aparapi specific requirements for code that must be converted to OpenCL:
*
*
assert() does not work
*
Can't check for null
*
Can't get array length
*
Arrays referenced by the kernel can't be null even if they are not accessed
*
Arrays referenced by the kernel can't be zero-length even if they are not accessed
*
Can't invoke methods in other classes e.g. enclosing class of an inner class
*
Early return statements do not work
*
Variables used inside loops must be initialized before the loop
*
Must compile the class with full debug information i.e. with -g
*
*
* @since 1.8.3
* @version 1.9.0
* @author Mikko Tommila
*/
class LongKernel
extends Kernel
{
private LongKernel()
{
}
public static LongKernel getInstance()
{
return LongKernel.kernel.get();
}
private static ThreadLocal kernel = ThreadLocal.withInitial(LongKernel::new);
// Methods for calculating the column transforms in parallel
public static final int TRANSFORM_ROWS = 1;
public static final int INVERSE_TRANSFORM_ROWS = 2;
public void setLength(int length)
{
this.length = length; // Transform length
}
public void setArrayAccess(ArrayAccess arrayAccess)
throws ApfloatRuntimeException
{
this.data = arrayAccess.getLongData();
this.offset = arrayAccess.getOffset();
if (this.length != 0)
{
this.stride = arrayAccess.getLength() / this.length;
}
}
public void setWTable(long[] wTable)
{
this.wTable = wTable;
}
public void setPermutationTable(int[] permutationTable)
{
this.permutationTable = (permutationTable == null ? new int[1] : permutationTable); // Zero-length array or null won't work
this.permutationTableLength = (permutationTable == null ? 0 : permutationTable.length);
}
private void columnTableFNT()
{
int nn, istep = 0, mmax = 0, r = 0;
long[] data = this.data;
int offset = this.offset + getGlobalId();
int stride = this.stride;
nn = this.length;
if (nn >= 2)
{
r = 1;
mmax = nn >> 1;
while (mmax > 0)
{
istep = mmax << 1;
// Optimize first step when wr = 1
for (int i = offset; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
long a = data[i];
long 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 * stride; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
long a = data[i];
long b = data[j];
data[i] = modAdd(a, b);
data[j] = modMultiply(this.wTable[t], modSubtract(a, b));
}
t += r;
}
r <<= 1;
mmax >>= 1;
}
if (this.permutationTableLength > 0)
{
columnScramble(offset);
}
}
}
private void inverseColumnTableFNT()
{
int nn, istep = 0, mmax = 0, r = 0;
long[] data = this.data;
int offset = this.offset + getGlobalId();
int stride = this.stride;
nn = this.length;
if (nn >= 2)
{
if (this.permutationTableLength > 0)
{
columnScramble(offset);
}
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 * stride; i += istep * stride)
{
int j = i + mmax * stride;
long 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 * stride; i < offset + nn * stride; i += istep * stride)
{
int j = i + mmax * stride;
long wTemp = modMultiply(this.wTable[t], data[j]);
data[j] = modSubtract(data[i], wTemp);
data[i] = modAdd(data[i], wTemp);
}
t += r;
}
mmax = istep;
}
}
}
private void columnScramble(int offset)
{
for (int k = 0; k < this.permutationTableLength; k += 2)
{
int i = offset + this.permutationTable[k] * this.stride,
j = offset + this.permutationTable[k + 1] * this.stride;
long tmp = this.data[i];
this.data[i] = this.data[j];
this.data[j] = tmp;
}
}
private long modMultiply(long a, long b)
{
long r = a * b - this.modulus * (long) ((double) a * (double) b * this.inverseModulus);
r -= this.modulus * (int) ((double) r * this.inverseModulus);
r = (r >= this.modulus ? r - this.modulus : r);
r = (r < 0 ? r + this.modulus : r);
return r;
}
private long modAdd(long a, long b)
{
long r = a + b;
return (r >= this.modulus ? r - this.modulus : r);
}
private long modSubtract(long a, long b)
{
long r = a - b;
return (r < 0 ? r + this.modulus : r);
}
public void setModulus(long modulus)
{
this.inverseModulus = 1.0 / modulus;
this.modulus = modulus;
}
public long getModulus()
{
return this.modulus;
}
private int stride;
private int length;
private long[] data;
private int offset;
private long[] wTable = { 0 };
private int[] permutationTable = { 0 };
private int permutationTableLength;
private long modulus;
private double inverseModulus;
// Methods for transposing the matrix
public static final int TRANSPOSE = 3;
public static final int PERMUTE = 4;
public void setN2(int n2)
{
this.n2 = n2;
}
public void setIndex(int[] index)
{
this.index = index;
}
public void setIndexCount(int indexCount)
{
this.indexCount = indexCount;
}
private void transpose()
{
int i = getGlobalId(0),
j = getGlobalId(1);
if (i < j)
{
int position1 = this.offset + j * this.n2 + i,
position2 = this.offset + i * this.n2 + j;
long tmp = this.data[position1];
this.data[position1] = this.data[position2];
this.data[position2] = tmp;
}
}
private void permute()
{
int j = getGlobalId();
for (int i = 0; i < this.indexCount; i++)
{
int o = this.index[i];
long tmp = this.data[this.offset + this.n2 * o + j];
for (i++; this.index[i] != 0; i++)
{
int m = this.index[i];
this.data[this.offset + this.n2 * o + j] = this.data[this.offset + this.n2 * m + j];
o = m;
}
this.data[this.offset + this.n2 * o + j] = tmp;
}
}
private int n2;
private int[] index = { 0 };
private int indexCount;
// Methods for multiplying elements in the matrix
public static final int MULTIPLY_ELEMENTS = 5;
public void setStartRow(int startRow)
{
this.startRow = startRow;
}
public void setStartColumn(int startColumn)
{
this.startColumn = startColumn;
}
public void setRows(int rows)
{
this.rows = rows;
}
public void setColumns(int columns)
{
this.columns = columns;
}
public void setW(long w)
{
this.w = w;
}
public void setScaleFactor(long scaleFactor)
{
this.scaleFactor = scaleFactor;
}
private void multiplyElements()
{
long[] data = this.data;
int position = this.offset + getGlobalId();
long rowFactor = modPow(this.w, (long) this.startRow);
long columnFactor = modPow(this.w, (long) this.startColumn + getGlobalId());
long rowStartFactor = modMultiply(this.scaleFactor, modPow(rowFactor, (long) this.startColumn + getGlobalId()));
for (int i = 0; i < this.rows; i++)
{
data[position] = modMultiply(data[position], rowStartFactor);
position += this.columns;
rowStartFactor = modMultiply(rowStartFactor, columnFactor);
}
}
private long modPow(long a, long n)
{
if (n == 0)
{
return 1;
}
else if (n < 0)
{
n = getModulus() - 1 + n;
}
long exponent = (long) n;
while ((exponent & 1) == 0)
{
a = modMultiply(a, a);
exponent >>= 1;
}
long r = a;
for (exponent >>= 1; exponent > 0; exponent >>= 1)
{
a = modMultiply(a, a);
if ((exponent & 1) != 0)
{
r = modMultiply(r, a);
}
}
return r;
}
private int startRow;
private int startColumn;
private int rows;
private int columns;
private long w;
private long scaleFactor;
// Methods for factor-3 transform
public static final int TRANSFORM_COLUMNS = 6;
public static final int INVERSE_TRANSFORM_COLUMNS = 7;
public void setOp(int op)
{
this.op = op;
}
public void setWw(long ww)
{
this.ww = ww;
}
public void setW1(long w1)
{
this.w1 = w1;
}
public void setW2(long w2)
{
this.w2 = w2;
}
@Override
public void run()
{
if (this.op == TRANSFORM_ROWS)
{
columnTableFNT();
}
else if (this.op == INVERSE_TRANSFORM_ROWS)
{
inverseColumnTableFNT();
}
else if (this.op == TRANSPOSE)
{
transpose();
}
else if (this.op == PERMUTE)
{
permute();
}
else if (this.op == MULTIPLY_ELEMENTS)
{
multiplyElements();
}
else if (this.op == TRANSFORM_COLUMNS || this.op == INVERSE_TRANSFORM_COLUMNS)
{
transformColumns();
}
}
private void transformColumns()
{
int i = getGlobalId();
long tmp1 = modPow(this.w, (long) this.startColumn + i),
tmp2 = modPow(this.ww, (long) this.startColumn + i);
// 3-point WFTA on the corresponding array elements
long x0 = this.data[this.offset + i],
x1 = this.data[this.offset + this.columns + i],
x2 = this.data[this.offset + 2 * this.columns + i],
t;
if (this.op == INVERSE_TRANSFORM_COLUMNS)
{
// Multiply before transform
x1 = modMultiply(x1, tmp1);
x2 = modMultiply(x2, tmp2);
}
// Transform column
t = modAdd(x1, x2);
x2 = modSubtract(x1, x2);
x0 = modAdd(x0, t);
t = modMultiply(t, this.w1);
x2 = modMultiply(x2, this.w2);
t = modAdd(t, x0);
x1 = modAdd(t, x2);
x2 = modSubtract(t, x2);
if (this.op == TRANSFORM_COLUMNS)
{
// Multiply after transform
x1 = modMultiply(x1, tmp1);
x2 = modMultiply(x2, tmp2);
}
this.data[this.offset + i] = x0;
this.data[this.offset + this.columns + i] = x1;
this.data[this.offset + 2 * this.columns + i] = x2;
}
private int op;
private long ww;
private long w1;
private long w2;
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/RangeHelper.java 0000664 0000000 0000000 00000005201 14557414736 0027626 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import com.aparapi.Range;
/**
* Range helper methods.
*
* @since 1.11.0
*
* @author Mikko Tommila
*/
class RangeHelper
{
// Note: it seems that this class is just a workaround to aparapi issue #171 where the local size is sometimes not set correctly
// See: https://github.com/Syncleus/aparapi/issues/171
private RangeHelper()
{
}
/**
* Creates a one-dimensional range with the maximum local size.
*
* @param size The size.
*
* @return The range.
*/
public static Range create(int size)
{
assert (size == (size & -size)); // Must be a power of two
int localSize = Math.min(size, MAX_LOCAL_SIZE);
return Range.create(size, localSize);
}
/**
* Creates a two-dimensional range with the maximum local sizes.
*
* @param width Size of the first dimension.
* @param height Size of the second dimension.
*
* @return The range.
*/
public static Range create2D(int width, int height)
{
assert (width == (width & -width)); // Must be a power of two
assert (height == (height & -height)); // Must be a power of two
int localWidth = Math.min(width, MAX_LOCAL_SIZE),
localHeight = Math.min(height, MAX_LOCAL_SIZE / localWidth);
return Range.create2D(width, height, localWidth, localHeight);
}
private static final int MAX_LOCAL_SIZE = 256;
}
apfloat-1.13.0/apfloat-aparapi/src/main/java/org/apfloat/aparapi/package-info.java 0000664 0000000 0000000 00000003434 14557414736 0027764 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
Transforms for using a GPU via the aparapi library.
This package contains Number-Theoretic Transform implementations that can use
the GPU (Graphics Processing Unit) for executing the transforms. There is significant
overhead in invoking the GPU, e.g. in transferring the data between the main memory
and the GPU memory, so for small data sets there is usually no performance improvement,
and in many cases performance can be even significantly slower. However for very large
calculations, e.g. one billion digits, using the GPU can improve the performance noticeably,
depending on the hardware used.
*/
package org.apfloat.aparapi;
apfloat-1.13.0/apfloat-aparapi/src/main/resources/ 0000775 0000000 0000000 00000000000 14557414736 0022030 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/main/resources/META-INF/ 0000775 0000000 0000000 00000000000 14557414736 0023170 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/main/resources/META-INF/services/ 0000775 0000000 0000000 00000000000 14557414736 0025013 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/main/resources/META-INF/services/org.apfloat.spi.BuilderFactory 0000664 0000000 0000000 00000000135 14557414736 0032660 0 ustar 00root root 0000000 0000000 org.apfloat.aparapi.IntAparapiBuilderFactory
org.apfloat.aparapi.LongAparapiBuilderFactory
apfloat-1.13.0/apfloat-aparapi/src/test/ 0000775 0000000 0000000 00000000000 14557414736 0020051 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/ 0000775 0000000 0000000 00000000000 14557414736 0020772 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021561 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0023207 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi/ 0000775 0000000 0000000 00000000000 14557414736 0024624 5 ustar 00root root 0000000 0000000 IntAparapiFactor3NTTStrategyTest.java 0000664 0000000 0000000 00000014342 14557414736 0033637 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import java.util.Arrays;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.9.0
* @author Mikko Tommila
*/
public class IntAparapiFactor3NTTStrategyTest
extends IntNTTStrategyTestCase
{
public IntAparapiFactor3NTTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new IntAparapiFactor3NTTStrategyTest("testForward"));
suite.addTest(new IntAparapiFactor3NTTStrategyTest("testRoundTrip"));
suite.addTest(new IntAparapiFactor3NTTStrategyTest("testRoundTrip2"));
return suite;
}
public static void testForward()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMemoryThreshold(Long.MAX_VALUE);
for (int modulus = 0; modulus < 3; modulus++)
{
int size = 3 * 2048;
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
int[] data = getPlainArray(dataStorage),
expectedTransform = ntt(data, modulus);
Arrays.sort(expectedTransform);
NTTStrategy nttStrategy = new IntAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
int[] actualTransform = getPlainArray(dataStorage);
Arrays.sort(actualTransform);
assertEquals("expected length", size, expectedTransform.length);
assertEquals("actual length", size, actualTransform.length);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], [" + i + "]", (long) expectedTransform[i], (long) actualTransform[i]);
}
}
}
public static void testRoundTrip()
{
ApfloatContext ctx = ApfloatContext.getContext();
int numberOfProcessors = ctx.getNumberOfProcessors();
ctx.setNumberOfProcessors(1);
ctx.setMemoryThreshold(Long.MAX_VALUE);
runRoundTrip();
ctx.setNumberOfProcessors(numberOfProcessors);
}
private static void runRoundTrip()
{
int size = (int) Math.min(3 * 1048576, IntModConstants.MAX_TRANSFORM_LENGTH); // Will use six-step transform
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
for (int modulus = 0; modulus < 3; modulus++)
{
Factor3NTTStrategy nttStrategy = new IntAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
assertEquals("transformed size", size, dataStorage.getSize());
DataStorage.Iterator iterator = dataStorage.iterator(DataStorage.READ, 0, 1);
assertTrue("transformed [0]", 6 != (long) iterator.getInt());
iterator.close();
nttStrategy.inverseTransform(dataStorage, modulus, size);
assertEquals("inverse transformed size", size, dataStorage.getSize());
iterator = dataStorage.iterator(DataStorage.READ, 0, size);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], round-tripped [" + i + "]", i + 6, (long) iterator.getInt());
iterator.next();
}
}
}
public static void testRoundTrip2()
{
ApfloatContext ctx = ApfloatContext.getContext();
int numberOfProcessors = ctx.getNumberOfProcessors();
ctx.setNumberOfProcessors(1);
ctx.setMemoryThreshold(Long.MAX_VALUE);
runRoundTrip2();
ctx.setNumberOfProcessors(numberOfProcessors);
}
private static void runRoundTrip2()
{
int size = 2048; // Will fall back to the power-of-two length transform
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
for (int modulus = 0; modulus < 3; modulus++)
{
Factor3NTTStrategy nttStrategy = new IntAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
assertEquals("transformed size", size, dataStorage.getSize());
DataStorage.Iterator iterator = dataStorage.iterator(DataStorage.READ, 0, 1);
assertTrue("transformed [0]", 6 != (long) iterator.getInt());
iterator.close();
nttStrategy.inverseTransform(dataStorage, modulus, size);
assertEquals("inverse transformed size", size, dataStorage.getSize());
iterator = dataStorage.iterator(DataStorage.READ, 0, size);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], round-tripped [" + i + "]", i + 6, (long) iterator.getInt());
iterator.next();
}
}
}
}
apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi/IntAparapiMatrixStrategyTest.java 0000664 0000000 0000000 00000024645 14557414736 0033302 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiMatrixStrategyTest
extends IntTestCase
{
public IntAparapiMatrixStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new IntAparapiMatrixStrategyTest("testTransposeSquare"));
suite.addTest(new IntAparapiMatrixStrategyTest("testTransposeSquarePart"));
suite.addTest(new IntAparapiMatrixStrategyTest("testTransposeWide"));
suite.addTest(new IntAparapiMatrixStrategyTest("testTransposeTall"));
suite.addTest(new IntAparapiMatrixStrategyTest("testPermuteToDoubleWidth"));
suite.addTest(new IntAparapiMatrixStrategyTest("testPermuteToHalfWidth"));
return suite;
}
private static ArrayAccess getArray(int count)
{
int[] data = new int[count + 5];
ArrayAccess arrayAccess = new IntMemoryArrayAccess(data, 5, count);
for (int i = 0; i < count; i++)
{
data[i + 5] = (int) (i + 1);
}
return arrayAccess;
}
public static void testTransposeSquare()
{
ArrayAccess arrayAccess = getArray(16);
new IntAparapiMatrixStrategy().transpose(arrayAccess, 4, 4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("16 elem [" + i + "][" + j + "]", 4 * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 4 * i + j]);
}
}
arrayAccess = getArray(18).subsequence(1, 16);
new IntAparapiMatrixStrategy().transpose(arrayAccess, 4, 4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("16 elem sub [" + i + "][" + j + "]", 4 * j + i + 2, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 4 * i + j]);
}
}
ApfloatContext ctx = ApfloatContext.getContext();
int cacheBurstBlockSize = Util.round2down(ctx.getCacheBurst() / 4), // Cache burst in ints
cacheL1Size = Util.sqrt4down(ctx.getCacheL1Size() / 4), // To fit in processor L1 cache
cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 4), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
arrayAccess = getArray(cacheBurstBlockSize * cacheBurstBlockSize);
new IntAparapiMatrixStrategy().transpose(arrayAccess, cacheBurstBlockSize, cacheBurstBlockSize);
for (int i = 0; i < cacheBurstBlockSize; i++)
{
for (int j = 0; j < cacheBurstBlockSize; j++)
{
assertEquals("cacheBurstBlockSize [" + i + "][" + j + "]", cacheBurstBlockSize * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + cacheBurstBlockSize * i + j]);
}
}
arrayAccess = getArray(cacheL1Size * cacheL1Size);
new IntAparapiMatrixStrategy().transpose(arrayAccess, cacheL1Size, cacheL1Size);
for (int i = 0; i < cacheL1Size; i++)
{
for (int j = 0; j < cacheL1Size; j++)
{
assertEquals("cacheL1Size [" + i + "][" + j + "]", cacheL1Size * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + cacheL1Size * i + j]);
}
}
arrayAccess = getArray(cacheL2Size * cacheL2Size);
new IntAparapiMatrixStrategy().transpose(arrayAccess, cacheL2Size, cacheL2Size);
for (int i = 0; i < cacheL2Size; i++)
{
for (int j = 0; j < cacheL2Size; j++)
{
assertEquals("cacheL2Size [" + i + "][" + j + "]", cacheL2Size * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + cacheL2Size * i + j]);
}
}
arrayAccess = getArray(bigSize * bigSize);
new IntAparapiMatrixStrategy().transpose(arrayAccess, bigSize, bigSize);
for (int i = 0; i < bigSize; i++)
{
for (int j = 0; j < bigSize; j++)
{
assertEquals("bigSize [" + i + "][" + j + "]", bigSize * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + bigSize * i + j]);
}
}
}
public static void testTransposeSquarePart()
{
ArrayAccess arrayAccess = getArray(32);
new IntAparapiMatrixStrategy().transposeSquare(arrayAccess, 4, 8);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("1st transposed [" + i + "][" + j + "]", 8 * j + i + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 8 * i + j]);
}
for (int j = 4; j < 8; j++)
{
assertEquals("1st untransposed [" + i + "][" + j + "]", 8 * i + j + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 8 * i + j]);
}
}
arrayAccess = getArray(32);
new IntAparapiMatrixStrategy().transposeSquare(arrayAccess.subsequence(4, 28), 4, 8);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("2nd untransposed [" + i + "][" + j + "]", 8 * i + j + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 8 * i + j]);
}
for (int j = 4; j < 8; j++)
{
assertEquals("2nd transposed [" + i + "][" + j + "]", 8 * (j - 4) + (i + 4) + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 8 * i + j]);
}
}
}
public static void testTransposeWide()
{
ApfloatContext ctx = ApfloatContext.getContext();
int cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 4), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
ArrayAccess arrayAccess = getArray(2 * bigSize * bigSize + 5).subsequence(5, 2 * bigSize * bigSize);
new IntAparapiMatrixStrategy().transpose(arrayAccess, bigSize, 2 * bigSize);
for (int i = 0; i < 2 * bigSize; i++)
{
for (int j = 0; j < bigSize; j++)
{
assertEquals("transposed [" + i + "][" + j + "]", 2 * bigSize * j + i + 6, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + bigSize * i + j]);
}
}
}
public static void testTransposeTall()
{
ApfloatContext ctx = ApfloatContext.getContext();
int cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 4), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
ArrayAccess arrayAccess = getArray(2 * bigSize * bigSize + 5).subsequence(5, 2 * bigSize * bigSize);
new IntAparapiMatrixStrategy().transpose(arrayAccess, 2 * bigSize, bigSize);
for (int i = 0; i < bigSize; i++)
{
for (int j = 0; j < 2 * bigSize; j++)
{
assertEquals("transposed [" + i + "][" + j + "]", bigSize * j + i + 6, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 2 * bigSize * i + j]);
}
}
}
public static void testPermuteToDoubleWidth()
{
ArrayAccess arrayAccess = getArray(256);
new IntAparapiMatrixStrategy().permuteToDoubleWidth(arrayAccess, 8, 32);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to double width [" + i + "][" + j + "]", 32 * i + j + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 64 * i + j]);
}
for (int j = 32; j < 64; j++)
{
assertEquals("permuted to double width [" + i + "][" + j + "]", 32 * i + j - 32 + 128 + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 64 * i + j]);
}
}
}
public static void testPermuteToHalfWidth()
{
ArrayAccess arrayAccess = getArray(256);
new IntAparapiMatrixStrategy().permuteToHalfWidth(arrayAccess, 4, 64);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to half width [" + i + "][" + j + "]", 64 * i + j + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 32 * i + j]);
}
}
for (int i = 4; i < 8; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to half width [" + i + "][" + j + "]", 64 * (i - 4) + j + 32 + 1, (long) arrayAccess.getIntData()[arrayAccess.getOffset() + 32 * i + j]);
}
}
}
}
IntAparapiSixStepFNTStrategyTest.java 0000664 0000000 0000000 00000007556 14557414736 0033730 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import java.util.Arrays;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiSixStepFNTStrategyTest
extends IntNTTStrategyTestCase
{
public IntAparapiSixStepFNTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new IntAparapiSixStepFNTStrategyTest("testForward"));
suite.addTest(new IntAparapiSixStepFNTStrategyTest("testForwardBig"));
suite.addTest(new IntAparapiSixStepFNTStrategyTest("testRoundTrip"));
suite.addTest(new IntAparapiSixStepFNTStrategyTest("testRoundTripBig"));
return suite;
}
public static void testForward()
{
runTestForward(1024);
}
public static void testForwardBig()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMemoryThreshold(8192);
runTestForward(4096);
}
private static void runTestForward(int size)
{
for (int modulus = 0; modulus < 3; modulus++)
{
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
int[] data = getPlainArray(dataStorage),
expectedTransform = ntt(data, modulus);
IntScramble.scramble(expectedTransform, 0, Scramble.createScrambleTable(size));
Arrays.sort(expectedTransform);
AbstractStepFNTStrategy nttStrategy = new IntAparapiSixStepFNTStrategy();
nttStrategy.transform(dataStorage, modulus);
int[] actualTransform = getPlainArray(dataStorage);
Arrays.sort(actualTransform);
assertEquals("expected length", size, expectedTransform.length);
assertEquals("actual length", size, actualTransform.length);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], [" + i + "]", (long) expectedTransform[i], (long) actualTransform[i]);
}
}
}
public static void testRoundTrip()
{
runRoundTrip(1024);
}
public static void testRoundTripBig()
{
int size = (int) Math.min(1 << 21, IntModConstants.MAX_TRANSFORM_LENGTH & -IntModConstants.MAX_TRANSFORM_LENGTH);
runRoundTrip(size);
}
private static void runRoundTrip(int size)
{
runRoundTrip(new IntAparapiSixStepFNTStrategy(), size);
}
}
IntAparapiTwoPassFNTStrategyTest.java 0000664 0000000 0000000 00000005234 14557414736 0033720 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.8.3
* @author Mikko Tommila
*/
public class IntAparapiTwoPassFNTStrategyTest
extends IntNTTStrategyTestCase
{
public IntAparapiTwoPassFNTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new IntAparapiTwoPassFNTStrategyTest("testRoundTrip"));
suite.addTest(new IntAparapiTwoPassFNTStrategyTest("testRoundTripBig"));
return suite;
}
public static void testRoundTrip()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMaxMemoryBlockSize(65536);
ctx.setMemoryThreshold(1024);
ctx.setBlockSize(256);
runRoundTrip(131072);
}
public static void testRoundTripBig()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMaxMemoryBlockSize(65536);
ctx.setMemoryThreshold(1024);
ctx.setBlockSize(256);
runRoundTrip((int) Math.min(1 << 21, Util.round2down(IntModConstants.MAX_TRANSFORM_LENGTH)));
}
private static void runRoundTrip(int size)
{
runRoundTrip(new ColumnTwoPassFNTStrategy(new IntAparapiNTTStepStrategy()), size);
}
}
LongAparapiFactor3NTTStrategyTest.java 0000664 0000000 0000000 00000014362 14557414736 0034006 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import java.util.Arrays;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.9.0
* @author Mikko Tommila
*/
public class LongAparapiFactor3NTTStrategyTest
extends LongNTTStrategyTestCase
{
public LongAparapiFactor3NTTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new LongAparapiFactor3NTTStrategyTest("testForward"));
suite.addTest(new LongAparapiFactor3NTTStrategyTest("testRoundTrip"));
suite.addTest(new LongAparapiFactor3NTTStrategyTest("testRoundTrip2"));
return suite;
}
public static void testForward()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMemoryThreshold(Long.MAX_VALUE);
for (int modulus = 0; modulus < 3; modulus++)
{
int size = 3 * 2048;
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
long[] data = getPlainArray(dataStorage),
expectedTransform = ntt(data, modulus);
Arrays.sort(expectedTransform);
NTTStrategy nttStrategy = new LongAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
long[] actualTransform = getPlainArray(dataStorage);
Arrays.sort(actualTransform);
assertEquals("expected length", size, expectedTransform.length);
assertEquals("actual length", size, actualTransform.length);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], [" + i + "]", (long) expectedTransform[i], (long) actualTransform[i]);
}
}
}
public static void testRoundTrip()
{
ApfloatContext ctx = ApfloatContext.getContext();
int numberOfProcessors = ctx.getNumberOfProcessors();
ctx.setNumberOfProcessors(1);
ctx.setMemoryThreshold(Long.MAX_VALUE);
runRoundTrip();
ctx.setNumberOfProcessors(numberOfProcessors);
}
private static void runRoundTrip()
{
int size = (int) Math.min(3 * 1048576, LongModConstants.MAX_TRANSFORM_LENGTH); // Will use six-step transform
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
for (int modulus = 0; modulus < 3; modulus++)
{
Factor3NTTStrategy nttStrategy = new LongAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
assertEquals("transformed size", size, dataStorage.getSize());
DataStorage.Iterator iterator = dataStorage.iterator(DataStorage.READ, 0, 1);
assertTrue("transformed [0]", 6 != (long) iterator.getLong());
iterator.close();
nttStrategy.inverseTransform(dataStorage, modulus, size);
assertEquals("inverse transformed size", size, dataStorage.getSize());
iterator = dataStorage.iterator(DataStorage.READ, 0, size);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], round-tripped [" + i + "]", i + 6, (long) iterator.getLong());
iterator.next();
}
}
}
public static void testRoundTrip2()
{
ApfloatContext ctx = ApfloatContext.getContext();
int numberOfProcessors = ctx.getNumberOfProcessors();
ctx.setNumberOfProcessors(1);
ctx.setMemoryThreshold(Long.MAX_VALUE);
runRoundTrip2();
ctx.setNumberOfProcessors(numberOfProcessors);
}
private static void runRoundTrip2()
{
int size = 2048; // Will fall back to the power-of-two length transform
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
for (int modulus = 0; modulus < 3; modulus++)
{
Factor3NTTStrategy nttStrategy = new LongAparapiFactor3NTTStrategy();
nttStrategy.transform(dataStorage, modulus);
assertEquals("transformed size", size, dataStorage.getSize());
DataStorage.Iterator iterator = dataStorage.iterator(DataStorage.READ, 0, 1);
assertTrue("transformed [0]", 6 != (long) iterator.getLong());
iterator.close();
nttStrategy.inverseTransform(dataStorage, modulus, size);
assertEquals("inverse transformed size", size, dataStorage.getSize());
iterator = dataStorage.iterator(DataStorage.READ, 0, size);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], round-tripped [" + i + "]", i + 6, (long) iterator.getLong());
iterator.next();
}
}
}
}
apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi/LongAparapiMatrixStrategyTest.java 0000664 0000000 0000000 00000024717 14557414736 0033447 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @since 1.8.3
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiMatrixStrategyTest
extends LongTestCase
{
public LongAparapiMatrixStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new LongAparapiMatrixStrategyTest("testTransposeSquare"));
suite.addTest(new LongAparapiMatrixStrategyTest("testTransposeSquarePart"));
suite.addTest(new LongAparapiMatrixStrategyTest("testTransposeWide"));
suite.addTest(new LongAparapiMatrixStrategyTest("testTransposeTall"));
suite.addTest(new LongAparapiMatrixStrategyTest("testPermuteToDoubleWidth"));
suite.addTest(new LongAparapiMatrixStrategyTest("testPermuteToHalfWidth"));
return suite;
}
private static ArrayAccess getArray(int count)
{
long[] data = new long[count + 5];
ArrayAccess arrayAccess = new LongMemoryArrayAccess(data, 5, count);
for (int i = 0; i < count; i++)
{
data[i + 5] = (long) (i + 1);
}
return arrayAccess;
}
public static void testTransposeSquare()
{
ArrayAccess arrayAccess = getArray(16);
new LongAparapiMatrixStrategy().transpose(arrayAccess, 4, 4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("16 elem [" + i + "][" + j + "]", 4 * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 4 * i + j]);
}
}
arrayAccess = getArray(18).subsequence(1, 16);
new LongAparapiMatrixStrategy().transpose(arrayAccess, 4, 4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("16 elem sub [" + i + "][" + j + "]", 4 * j + i + 2, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 4 * i + j]);
}
}
ApfloatContext ctx = ApfloatContext.getContext();
int cacheBurstBlockSize = Util.round2down(ctx.getCacheBurst() / 8), // Cache burst in longs
cacheL1Size = Util.sqrt4down(ctx.getCacheL1Size() / 8), // To fit in processor L1 cache
cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 8), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
arrayAccess = getArray(cacheBurstBlockSize * cacheBurstBlockSize);
new LongAparapiMatrixStrategy().transpose(arrayAccess, cacheBurstBlockSize, cacheBurstBlockSize);
for (int i = 0; i < cacheBurstBlockSize; i++)
{
for (int j = 0; j < cacheBurstBlockSize; j++)
{
assertEquals("cacheBurstBlockSize [" + i + "][" + j + "]", cacheBurstBlockSize * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + cacheBurstBlockSize * i + j]);
}
}
arrayAccess = getArray(cacheL1Size * cacheL1Size);
new LongAparapiMatrixStrategy().transpose(arrayAccess, cacheL1Size, cacheL1Size);
for (int i = 0; i < cacheL1Size; i++)
{
for (int j = 0; j < cacheL1Size; j++)
{
assertEquals("cacheL1Size [" + i + "][" + j + "]", cacheL1Size * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + cacheL1Size * i + j]);
}
}
arrayAccess = getArray(cacheL2Size * cacheL2Size);
new LongAparapiMatrixStrategy().transpose(arrayAccess, cacheL2Size, cacheL2Size);
for (int i = 0; i < cacheL2Size; i++)
{
for (int j = 0; j < cacheL2Size; j++)
{
assertEquals("cacheL2Size [" + i + "][" + j + "]", cacheL2Size * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + cacheL2Size * i + j]);
}
}
arrayAccess = getArray(bigSize * bigSize);
new LongAparapiMatrixStrategy().transpose(arrayAccess, bigSize, bigSize);
for (int i = 0; i < bigSize; i++)
{
for (int j = 0; j < bigSize; j++)
{
assertEquals("bigSize [" + i + "][" + j + "]", bigSize * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + bigSize * i + j]);
}
}
}
public static void testTransposeSquarePart()
{
ArrayAccess arrayAccess = getArray(32);
new LongAparapiMatrixStrategy().transposeSquare(arrayAccess, 4, 8);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("1st transposed [" + i + "][" + j + "]", 8 * j + i + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 8 * i + j]);
}
for (int j = 4; j < 8; j++)
{
assertEquals("1st untransposed [" + i + "][" + j + "]", 8 * i + j + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 8 * i + j]);
}
}
arrayAccess = getArray(32);
new LongAparapiMatrixStrategy().transposeSquare(arrayAccess.subsequence(4, 28), 4, 8);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
assertEquals("2nd untransposed [" + i + "][" + j + "]", 8 * i + j + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 8 * i + j]);
}
for (int j = 4; j < 8; j++)
{
assertEquals("2nd transposed [" + i + "][" + j + "]", 8 * (j - 4) + (i + 4) + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 8 * i + j]);
}
}
}
public static void testTransposeWide()
{
ApfloatContext ctx = ApfloatContext.getContext();
int cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 8), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
ArrayAccess arrayAccess = getArray(2 * bigSize * bigSize + 5).subsequence(5, 2 * bigSize * bigSize);
new LongAparapiMatrixStrategy().transpose(arrayAccess, bigSize, 2 * bigSize);
for (int i = 0; i < 2 * bigSize; i++)
{
for (int j = 0; j < bigSize; j++)
{
assertEquals("transposed [" + i + "][" + j + "]", 2 * bigSize * j + i + 6, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + bigSize * i + j]);
}
}
}
public static void testTransposeTall()
{
ApfloatContext ctx = ApfloatContext.getContext();
int cacheL2Size = Util.sqrt4down(ctx.getCacheL2Size() / 8), // To fit in processor L2 cache
bigSize = cacheL2Size * 2; // To not fit in processor L2 cache
ArrayAccess arrayAccess = getArray(2 * bigSize * bigSize + 5).subsequence(5, 2 * bigSize * bigSize);
new LongAparapiMatrixStrategy().transpose(arrayAccess, 2 * bigSize, bigSize);
for (int i = 0; i < bigSize; i++)
{
for (int j = 0; j < 2 * bigSize; j++)
{
assertEquals("transposed [" + i + "][" + j + "]", bigSize * j + i + 6, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 2 * bigSize * i + j]);
}
}
}
public static void testPermuteToDoubleWidth()
{
ArrayAccess arrayAccess = getArray(256);
new LongAparapiMatrixStrategy().permuteToDoubleWidth(arrayAccess, 8, 32);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to double width [" + i + "][" + j + "]", 32 * i + j + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 64 * i + j]);
}
for (int j = 32; j < 64; j++)
{
assertEquals("permuted to double width [" + i + "][" + j + "]", 32 * i + j - 32 + 128 + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 64 * i + j]);
}
}
}
public static void testPermuteToHalfWidth()
{
ArrayAccess arrayAccess = getArray(256);
new LongAparapiMatrixStrategy().permuteToHalfWidth(arrayAccess, 4, 64);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to half width [" + i + "][" + j + "]", 64 * i + j + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 32 * i + j]);
}
}
for (int i = 4; i < 8; i++)
{
for (int j = 0; j < 32; j++)
{
assertEquals("permuted to half width [" + i + "][" + j + "]", 64 * (i - 4) + j + 32 + 1, (long) arrayAccess.getLongData()[arrayAccess.getOffset() + 32 * i + j]);
}
}
}
}
LongAparapiSixStepFNTStrategyTest.java 0000664 0000000 0000000 00000007574 14557414736 0034075 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import java.util.Arrays;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiSixStepFNTStrategyTest
extends LongNTTStrategyTestCase
{
public LongAparapiSixStepFNTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new LongAparapiSixStepFNTStrategyTest("testForward"));
suite.addTest(new LongAparapiSixStepFNTStrategyTest("testForwardBig"));
suite.addTest(new LongAparapiSixStepFNTStrategyTest("testRoundTrip"));
suite.addTest(new LongAparapiSixStepFNTStrategyTest("testRoundTripBig"));
return suite;
}
public static void testForward()
{
runTestForward(1024);
}
public static void testForwardBig()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMemoryThreshold(8192);
runTestForward(4096);
}
private static void runTestForward(int size)
{
for (int modulus = 0; modulus < 3; modulus++)
{
DataStorage dataStorage = createDataStorage(size + 5).subsequence(5, size);
long[] data = getPlainArray(dataStorage),
expectedTransform = ntt(data, modulus);
LongScramble.scramble(expectedTransform, 0, Scramble.createScrambleTable(size));
Arrays.sort(expectedTransform);
AbstractStepFNTStrategy nttStrategy = new LongAparapiSixStepFNTStrategy();
nttStrategy.transform(dataStorage, modulus);
long[] actualTransform = getPlainArray(dataStorage);
Arrays.sort(actualTransform);
assertEquals("expected length", size, expectedTransform.length);
assertEquals("actual length", size, actualTransform.length);
for (int i = 0; i < size; i++)
{
assertEquals("MODULUS[" + modulus + "], [" + i + "]", (long) expectedTransform[i], (long) actualTransform[i]);
}
}
}
public static void testRoundTrip()
{
runRoundTrip(1024);
}
public static void testRoundTripBig()
{
int size = (int) Math.min(1 << 21, LongModConstants.MAX_TRANSFORM_LENGTH & -LongModConstants.MAX_TRANSFORM_LENGTH);
runRoundTrip(size);
}
private static void runRoundTrip(int size)
{
runRoundTrip(new LongAparapiSixStepFNTStrategy(), size);
}
}
LongAparapiTwoPassFNTStrategyTest.java 0000664 0000000 0000000 00000005243 14557414736 0034065 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-aparapi/src/test/java/org/apfloat/aparapi /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.aparapi;
import org.apfloat.*;
import org.apfloat.spi.*;
import org.apfloat.internal.*;
import junit.framework.TestSuite;
/**
* @version 1.8.3
* @author Mikko Tommila
*/
public class LongAparapiTwoPassFNTStrategyTest
extends LongNTTStrategyTestCase
{
public LongAparapiTwoPassFNTStrategyTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new LongAparapiTwoPassFNTStrategyTest("testRoundTrip"));
suite.addTest(new LongAparapiTwoPassFNTStrategyTest("testRoundTripBig"));
return suite;
}
public static void testRoundTrip()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMaxMemoryBlockSize(65536);
ctx.setMemoryThreshold(1024);
ctx.setBlockSize(256);
runRoundTrip(131072);
}
public static void testRoundTripBig()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setMaxMemoryBlockSize(65536);
ctx.setMemoryThreshold(1024);
ctx.setBlockSize(256);
runRoundTrip((int) Math.min(1 << 21, Util.round2down(LongModConstants.MAX_TRANSFORM_LENGTH)));
}
private static void runRoundTrip(int size)
{
runRoundTrip(new ColumnTwoPassFNTStrategy(new LongAparapiNTTStepStrategy()), size);
}
}
apfloat-1.13.0/apfloat-applet/ 0000775 0000000 0000000 00000000000 14557414736 0016153 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-applet/pom.xml 0000664 0000000 0000000 00000003615 14557414736 0017475 0 ustar 00root root 0000000 0000000
4.0.0org.apfloatapfloat-parent1.13.0apfloat-appletapfloat-appletConfiguration for apfloat to not use disk files for data storagehttp://www.apfloat.orgorg.apfloatapfloatjunitjunittestorg.apache.maven.pluginsmaven-javadoc-pluginorg.apache.maven.pluginsmaven-shade-pluginshadeorg.apfloat:apfloat-applet${project.build.directory}/applet.jar
apfloat-1.13.0/apfloat-applet/src/ 0000775 0000000 0000000 00000000000 14557414736 0016742 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-applet/src/main/ 0000775 0000000 0000000 00000000000 14557414736 0017666 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-applet/src/main/java/ 0000775 0000000 0000000 00000000000 14557414736 0020607 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-applet/src/main/java/apfloat.java 0000664 0000000 0000000 00000007350 14557414736 0023105 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import java.util.ListResourceBundle;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import org.apfloat.ApfloatContext;
import org.apfloat.spi.Util;
/**
* Default initial settings for the global {@link ApfloatContext}.
* These settings are intended for applets that are not allowed to create
* disk files.
*
* @version 1.9.1
* @author Mikko Tommila
*/
public class apfloat
extends ListResourceBundle
{
@Override
public Object[][] getContents()
{
return CONTENTS;
}
private static final Object[][] CONTENTS;
static
{
// Try to use up to 80% of total memory and all processors
long totalMemory;
try
{
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage memoryUsage = memoryBean.getHeapMemoryUsage();
totalMemory = Math.max(memoryUsage.getCommitted(), memoryUsage.getMax());
}
catch (NoClassDefFoundError | NullPointerException e)
{
// The ManagementFactory class might be unavailable
totalMemory = Runtime.getRuntime().maxMemory();
}
long maxMemoryBlockSize = Util.round23down(totalMemory / 5 * 4);
int numberOfProcessors = Runtime.getRuntime().availableProcessors();
long memoryThreshold = Long.MAX_VALUE;
int blockSize = Util.round2down((int) Math.min(Math.max(maxMemoryBlockSize >> 10, 65536), Integer.MAX_VALUE));
Object[][] contents =
{
{ ApfloatContext.BUILDER_FACTORY, "org.apfloat.internal.LongBuilderFactory" },
{ ApfloatContext.DEFAULT_RADIX, "10" },
{ ApfloatContext.MAX_MEMORY_BLOCK_SIZE, String.valueOf(maxMemoryBlockSize) },
{ ApfloatContext.CACHE_L1_SIZE, "8192" },
{ ApfloatContext.CACHE_L2_SIZE, "262144" },
{ ApfloatContext.CACHE_BURST, "32" },
{ ApfloatContext.MEMORY_THRESHOLD, String.valueOf(memoryThreshold) },
{ ApfloatContext.SHARED_MEMORY_TRESHOLD, String.valueOf(maxMemoryBlockSize / numberOfProcessors / 32) },
{ ApfloatContext.BLOCK_SIZE, String.valueOf(blockSize) },
{ ApfloatContext.NUMBER_OF_PROCESSORS, String.valueOf(numberOfProcessors) },
{ ApfloatContext.FILE_PATH, "" },
{ ApfloatContext.FILE_INITIAL_VALUE, "0" },
{ ApfloatContext.FILE_SUFFIX, ".ap" },
{ ApfloatContext.CLEANUP_AT_EXIT, "false" }
};
CONTENTS = contents;
}
}
apfloat-1.13.0/apfloat-calc/ 0000775 0000000 0000000 00000000000 14557414736 0015570 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/pom.xml 0000664 0000000 0000000 00000006316 14557414736 0017113 0 ustar 00root root 0000000 0000000
4.0.0org.apfloatapfloat-parent1.13.0apfloat-calcapfloat-calcInteractive arbitrary precision calculator applicationhttp://www.apfloat.orgorg.apfloatapfloatjunitjunittestorg.codehaus.mojojavacc-maven-pluginjavaccjavaccsrc/main/javabiz.aQute.bndbnd-maven-plugingenerate-osgi-manifestbnd-processorg.apache.maven.pluginsmaven-jar-plugin${project.build.outputDirectory}/META-INF/MANIFEST.MForg.apache.maven.pluginsmaven-shade-pluginshadeorg.apfloat:apfloat-calc${project.build.directory}/calc.jarapfloat.jar
apfloat-1.13.0/apfloat-calc/src/ 0000775 0000000 0000000 00000000000 14557414736 0016357 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/ 0000775 0000000 0000000 00000000000 14557414736 0017303 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/java/ 0000775 0000000 0000000 00000000000 14557414736 0020224 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021013 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0022441 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/ 0000775 0000000 0000000 00000000000 14557414736 0023343 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/AbstractCalculatorImpl.java 0000664 0000000 0000000 00000010710 14557414736 0030604 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Basic calculator implementation.
* Provides a storage for variables, and maps
* the elementary operators to function calls.
*
* @version 1.9.1
* @author Mikko Tommila
*/
public abstract class AbstractCalculatorImpl
implements CalculatorImpl, Serializable
{
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
protected AbstractCalculatorImpl()
{
this.variables = new HashMap<>();
this.pretty = false;
}
@Override
public Number negate(Number x)
throws ParseException
{
return function("negate", toList(x));
}
@Override
public Number add(Number x, Number y)
throws ParseException
{
return function("add", toList(x, y));
}
@Override
public Number subtract(Number x, Number y)
throws ParseException
{
return function("subtract", toList(x, y));
}
@Override
public Number multiply(Number x, Number y)
throws ParseException
{
return function("multiply", toList(x, y));
}
@Override
public Number divide(Number x, Number y)
throws ParseException
{
return function("divide", toList(x, y));
}
@Override
public Number mod(Number x, Number y)
throws ParseException
{
return function("mod", toList(x, y));
}
@Override
public Number pow(Number x, Number y)
throws ParseException
{
return function("pow", toList(x, y));
}
@Override
public Number getVariable(String name)
throws ParseException
{
Number variable = this.variables.get(name);
if (variable == null)
{
throw new ParseException("Invalid variable: " + name);
}
return variable;
}
@Override
public void setVariable(String name, Number value)
{
this.variables.put(name, value);
}
@Override
public void setFormat(boolean pretty)
{
this.pretty = pretty;
}
@Override
public void setInputPrecision(Long inputPrecision)
{
this.inputPrecision = inputPrecision;
}
/**
* Get the formatting option.
*
* @return If a fixed-point or a floating-point notation should be used.
*/
protected boolean getFormat()
{
return this.pretty;
}
/**
* Get the input precision.
*
* @return The input precision if a fixed precision is used or null for arbitrary precision.
*/
protected Long getInputPrecision()
{
return this.inputPrecision;
}
private static List toList(Number x)
{
List list = new ArrayList<>();
list.add(x);
return list;
}
private static List toList(Number x, Number y)
{
List list = new ArrayList<>();
list.add(x);
list.add(y);
return list;
}
private Map variables;
private boolean pretty;
private Long inputPrecision;
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/ApfloatCalculatorImpl.java 0000664 0000000 0000000 00000111736 14557414736 0030441 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.math.RoundingMode;
import org.apfloat.Apcomplex;
import org.apfloat.ApcomplexMath;
import org.apfloat.Apfloat;
import org.apfloat.ApfloatMath;
import org.apfloat.Apint;
import org.apfloat.ApintMath;
import org.apfloat.Aprational;
import org.apfloat.AprationalMath;
import org.apfloat.FixedPrecisionApcomplexHelper;
import org.apfloat.spi.Util;
/**
* Arbitrary precision calculator implementation.
*
* @version 1.13.0
* @author Mikko Tommila
*/
public class ApfloatCalculatorImpl
extends FunctionCalculatorImpl
{
private static final long serialVersionUID = 1L;
private class ApcomplexFunctions
implements Functions
{
@Override
public Number negate(Number x)
{
return ((Apcomplex) x).negate();
}
@Override
public Number add(Number x, Number y)
{
return ((Apcomplex) x).add((Apcomplex) y);
}
@Override
public Number subtract(Number x, Number y)
{
return ((Apcomplex) x).subtract((Apcomplex) y);
}
@Override
public Number multiply(Number x, Number y)
{
return ((Apcomplex) x).multiply((Apcomplex) y);
}
@Override
public Number divide(Number x, Number y)
{
return ((Apcomplex) x).divide((Apcomplex) y);
}
@Override
public Number mod(Number x, Number y)
{
throw new IllegalArgumentException("Modulus can only be used with scalar values");
}
@Override
public Number pow(Number x, Number y)
{
if (isLong(y))
{
if (((Apcomplex) y).precision() < ((Apcomplex) x).precision())
{
x = ((Apcomplex) x).precision(((Apcomplex) y).precision());
}
return pow(x, y.longValue());
}
else
{
return ApcomplexMath.pow((Apcomplex) x, (Apcomplex) y);
}
}
protected Number pow(Number x, long y)
{
return ApcomplexMath.pow((Apcomplex) x, y);
}
@Override
public Number arg(Number x)
{
return ApcomplexMath.arg((Apcomplex) x);
}
@Override
public Number conj(Number x)
{
return ((Apcomplex) x).conj();
}
@Override
public Number imag(Number x)
{
return ((Apcomplex) x).imag();
}
@Override
public Number real(Number x)
{
return ((Apcomplex) x).real();
}
@Override
public Number abs(Number x)
{
return ApcomplexMath.abs((Apcomplex) x);
}
@Override
public Number acos(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::acos, ApcomplexMath::acos, x);
}
@Override
public Number acosh(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::acosh, ApcomplexMath::acosh, x);
}
@Override
public Number airyAi(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::airyAi, ApcomplexMath::airyAi, x);
}
@Override
public Number airyAiPrime(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::airyAiPrime, ApcomplexMath::airyAiPrime, x);
}
@Override
public Number airyBi(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::airyBi, ApcomplexMath::airyBi, x);
}
@Override
public Number airyBiPrime(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::airyBiPrime, ApcomplexMath::airyBiPrime, x);
}
@Override
public Number asin(Number x)
{
return ApcomplexMath.asin((Apcomplex) x);
}
@Override
public Number asinh(Number x)
{
return ApcomplexMath.asinh((Apcomplex) x);
}
@Override
public Number atan(Number x)
{
return ApcomplexMath.atan((Apcomplex) x);
}
@Override
public Number atanh(Number x)
{
return ApcomplexMath.atanh((Apcomplex) x);
}
@Override
public Number bernoulli(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Bernoulli can only be used with a valid integer argument");
}
long n = x.longValue();
return AprationalMath.bernoulli(n);
}
@Override
public Number besselI(Number x, Number y)
{
return ApcomplexMath.besselI((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number besselJ(Number x, Number y)
{
return ApcomplexMath.besselJ((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number besselK(Number x, Number y)
{
return ApcomplexMath.besselK((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number besselY(Number x, Number y)
{
return ApcomplexMath.besselY((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number beta(Number a, Number b)
{
return ApcomplexMath.beta((Apcomplex) a, (Apcomplex) b);
}
@Override
public Number beta(Number x, Number a, Number b)
{
return ApcomplexMath.beta((Apcomplex) x, (Apcomplex) a, (Apcomplex) b);
}
@Override
public Number beta(Number x1, Number x2, Number a, Number b)
{
return ApcomplexMath.beta((Apcomplex) x1, (Apcomplex) x2, (Apcomplex) a, (Apcomplex) b);
}
@Override
public Number binomial(Number x, Number y)
{
return ApcomplexMath.binomial((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number catalan(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Catalan can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.catalan(n);
}
@Override
public Number cbrt(Number x)
{
return root(x, 3);
}
@Override
public Number ceil(Number x)
{
throw new IllegalArgumentException("Ceiling can only be used with scalar values");
}
@Override
public Number cos(Number x)
{
return ApcomplexMath.cos((Apcomplex) x);
}
@Override
public Number cosIntegral(Number x)
{
return ApcomplexMath.cosIntegral((Apcomplex) x);
}
@Override
public Number cosh(Number x)
{
return ApcomplexMath.cosh((Apcomplex) x);
}
@Override
public Number coshIntegral(Number x)
{
return ApcomplexMath.coshIntegral((Apcomplex) x);
}
@Override
public Number digamma(Number x)
{
return ApcomplexMath.digamma((Apcomplex) x);
}
@Override
public Number e(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("E can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.e(n);
}
@Override
public Number ellipticE(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::ellipticE, ApcomplexMath::ellipticE, x);
}
@Override
public Number ellipticK(Number x)
{
return fixedOrArbitraryPrecision(fixedPrecisionApcomplexHelper::ellipticK, ApcomplexMath::ellipticK, x);
}
@Override
public Number erf(Number x)
{
return ApcomplexMath.erf((Apcomplex) x);
}
@Override
public Number erfc(Number x)
{
return ApcomplexMath.erfc((Apcomplex) x);
}
@Override
public Number erfi(Number x)
{
return ApcomplexMath.erfi((Apcomplex) x);
}
@Override
public Number euler(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Euler can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.euler(n);
}
@Override
public Number exp(Number x)
{
return ApcomplexMath.exp((Apcomplex) x);
}
@Override
public Number expIntegralE(Number x, Number y)
{
return ApcomplexMath.expIntegralE((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number expIntegralEi(Number x)
{
return ApcomplexMath.expIntegralEi((Apcomplex) x);
}
@Override
public Number factorial(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Factorial can only be used with a valid integer argument");
}
long n = x.longValue();
return ApintMath.factorial(n);
}
@Override
public Number floor(Number x)
{
throw new IllegalArgumentException("Floor can only be used with scalar values");
}
@Override
public Number frac(Number x)
{
throw new IllegalArgumentException("Frac can only be used with scalar values");
}
@Override
public Number fresnelC(Number x)
{
return ApcomplexMath.fresnelC((Apcomplex) x);
}
@Override
public Number fresnelS(Number x)
{
return ApcomplexMath.fresnelS((Apcomplex) x);
}
@Override
public Number glaisher(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Glaisher can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.glaisher(n);
}
@Override
public Number gamma(Number x)
{
return ApcomplexMath.gamma((Apcomplex) x);
}
@Override
public Number gamma(Number x, Number y)
{
return ApcomplexMath.gamma((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number gamma(Number x, Number y, Number z)
{
return ApcomplexMath.gamma((Apcomplex) x, (Apcomplex) y, (Apcomplex) z);
}
@Override
public Number hypergeometric0F1(Number a, Number z)
{
return ApcomplexMath.hypergeometric0F1((Apcomplex) a, (Apcomplex) z);
}
@Override
public Number hypergeometric0F1Regularized(Number a, Number z)
{
return ApcomplexMath.hypergeometric0F1Regularized((Apcomplex) a, (Apcomplex) z);
}
@Override
public Number hypergeometric1F1(Number a, Number b, Number z)
{
return ApcomplexMath.hypergeometric1F1((Apcomplex) a, (Apcomplex) b, (Apcomplex) z);
}
@Override
public Number hypergeometric1F1Regularized(Number a, Number b, Number z)
{
return ApcomplexMath.hypergeometric1F1Regularized((Apcomplex) a, (Apcomplex) b, (Apcomplex) z);
}
@Override
public Number hypergeometric2F1(Number a, Number b, Number c, Number z)
{
return ApcomplexMath.hypergeometric2F1((Apcomplex) a, (Apcomplex) b, (Apcomplex) c, (Apcomplex) z);
}
@Override
public Number hypergeometric2F1Regularized(Number a, Number b, Number c, Number z)
{
return ApcomplexMath.hypergeometric2F1Regularized((Apcomplex) a, (Apcomplex) b, (Apcomplex) c, (Apcomplex) z);
}
@Override
public Number hypergeometricU(Number a, Number b, Number z)
{
return ApcomplexMath.hypergeometricU((Apcomplex) a, (Apcomplex) b, (Apcomplex) z);
}
@Override
public Number inverseErf(Number x)
{
throw new IllegalArgumentException("Inverse erf can only be used with scalar values");
}
@Override
public Number inverseErfc(Number x)
{
throw new IllegalArgumentException("Inverse erfc can only be used with scalar values");
}
@Override
public Number khinchin(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Khinchin can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.khinchin(n);
}
@Override
public Number log(Number x)
{
return ApcomplexMath.log((Apcomplex) x);
}
@Override
public Number log(Number x, Number y)
{
return ApcomplexMath.log((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number logGamma(Number x)
{
return ApcomplexMath.logGamma((Apcomplex) x);
}
@Override
public Number logIntegral(Number x)
{
return ApcomplexMath.logIntegral((Apcomplex) x);
}
@Override
public Number max(Number x, Number y)
{
throw new IllegalArgumentException("Max can only be used with scalar values");
}
@Override
public Number min(Number x, Number y)
{
throw new IllegalArgumentException("Min can only be used with scalar values");
}
@Override
public Number nextAfter(Number x, Number y)
{
throw new IllegalArgumentException("Next after can only be used with scalar values");
}
@Override
public Number nextDown(Number x)
{
throw new IllegalArgumentException("Next down can only be used with scalar values");
}
@Override
public Number nextUp(Number x)
{
throw new IllegalArgumentException("Next up can only be used with scalar values");
}
@Override
public Number pi(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Pi can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.pi(n);
}
@Override
public Number pochhammer(Number x, Number y)
{
return ApcomplexMath.pochhammer((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number polygamma(Number x, Number y)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Polygamma can only be used with a valid integer first argument");
}
long n = x.longValue();
return ApcomplexMath.polygamma(n, (Apcomplex) y);
}
@Override
public Number random(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Random can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.random(n);
}
@Override
public Number randomGaussian(Number x)
{
if (!isLong(x))
{
throw new IllegalArgumentException("Random Gaussian can only be used with a valid integer argument");
}
long n = x.longValue();
return ApfloatMath.randomGaussian(n);
}
@Override
public Number round(Number x, Number y)
{
return roundToPrecision(x, y);
}
@Override
public Number roundToPrecision(Number x, Number y)
{
throw new IllegalArgumentException("Rounding can only be used with scalar values");
}
@Override
public Number roundToInteger(Number x)
{
throw new IllegalArgumentException("Rounding can only be used with scalar values");
}
@Override
public Number roundToPlaces(Number x, Number y)
{
throw new IllegalArgumentException("Rounding can only be used with scalar values");
}
@Override
public Number roundToMultiple(Number x, Number y)
{
throw new IllegalArgumentException("Rounding can only be used with scalar values");
}
@Override
public Number sin(Number x)
{
return ApcomplexMath.sin((Apcomplex) x);
}
@Override
public Number sinIntegral(Number x)
{
return ApcomplexMath.sinIntegral((Apcomplex) x);
}
@Override
public Number sinh(Number x)
{
return ApcomplexMath.sinh((Apcomplex) x);
}
@Override
public Number sinhIntegral(Number x)
{
return ApcomplexMath.sinhIntegral((Apcomplex) x);
}
@Override
public Number sqrt(Number x)
{
return root(x, 2);
}
@Override
public Number tan(Number x)
{
return ApcomplexMath.tan((Apcomplex) x);
}
@Override
public Number tanh(Number x)
{
return ApcomplexMath.tanh((Apcomplex) x);
}
@Override
public Number truncate(Number x)
{
throw new IllegalArgumentException("Truncate can only be used with scalar values");
}
@Override
public Number toDegrees(Number x)
{
throw new IllegalArgumentException("ToDegrees can only be used with scalar values");
}
@Override
public Number toRadians(Number x)
{
throw new IllegalArgumentException("ToRadians can only be used with scalar values");
}
@Override
public Number ulp(Number x)
{
return ApcomplexMath.ulp((Apcomplex) x);
}
@Override
public Number zeta(Number x)
{
return ApcomplexMath.zeta((Apcomplex) x);
}
@Override
public Number zeta(Number x, Number y)
{
return ApcomplexMath.zeta((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number agm(Number x, Number y)
{
return ApcomplexMath.agm((Apcomplex) x, (Apcomplex) y);
}
@Override
public Number w(Number x)
{
return ApcomplexMath.w((Apcomplex) x);
}
@Override
public Number w(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Lambert W can only be used with a valid integer argument");
}
return ApcomplexMath.w((Apcomplex) x, y.longValue());
}
@Override
public Number atan2(Number x, Number y)
{
throw new IllegalArgumentException("Atan2 can only be used with scalar values");
}
@Override
public Number copySign(Number x, Number y)
{
throw new IllegalArgumentException("CopySign can only be used with scalar values");
}
@Override
public Number fmod(Number x, Number y)
{
throw new IllegalArgumentException("Fmod can only be used with scalar values");
}
@Override
public Number gcd(Number x, Number y)
{
throw new IllegalArgumentException("Greatest Common Ddivisor can only be used with integer values");
}
@Override
public Number hypot(Number x, Number y)
{
throw new IllegalArgumentException("Hypot can only be used with scalar values");
}
@Override
public Number inverseRoot(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Inverse root can only be used with a valid integer argument");
}
return inverseRoot(x, y.longValue());
}
@Override
public Number inverseRoot(Number x, Number y, Number z)
{
if (!isLong(y) || !isLong(z))
{
throw new IllegalArgumentException("Inverse root can only be used with valid integer arguments");
}
return inverseRoot(x, y.longValue(), z.longValue());
}
protected Number inverseRoot(Number x, long y)
{
return ApcomplexMath.inverseRoot((Apcomplex) x, y);
}
protected Number inverseRoot(Number x, long y, long z)
{
return ApcomplexMath.inverseRoot((Apcomplex) x, y, z);
}
@Override
public Number lcm(Number x, Number y)
{
throw new IllegalArgumentException("Least Common Multiplier can only be used with integer values");
}
@Override
public Number root(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Root can only be used with a valid integer argument");
}
return root(x, y.longValue());
}
@Override
public Number root(Number x, Number y, Number z)
{
if (!isLong(y) || !isLong(z))
{
throw new IllegalArgumentException("Root can only be used with valid integer arguments");
}
return root(x, y.longValue(), z.longValue());
}
protected Number root(Number x, long y)
{
return ApcomplexMath.root((Apcomplex) x, y);
}
protected Number root(Number x, long y, long z)
{
return ApcomplexMath.root((Apcomplex) x, y, z);
}
@Override
public Number scale(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Scale can only be used with a valid integer argument");
}
return scale(x, y.longValue());
}
protected Number scale(Number x, long y)
{
return ApcomplexMath.scale((Apcomplex) x, y);
}
@Override
public Number precision(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Precision can only be used with a valid integer argument");
}
return precision(x, y.longValue());
}
protected Number precision(Number x, long precision)
{
return ((Apcomplex) x).precision(precision);
}
protected boolean isLong(Number value)
{
return value instanceof Long || value != null && new Apint(value.longValue()).equals(value);
}
}
private class ApfloatFunctions
extends ApcomplexFunctions
{
@Override
public Number mod(Number x, Number y)
{
return ((Apfloat) x).mod((Apfloat) y);
}
@Override
public Number ceil(Number x)
{
return ((Apfloat) x).ceil();
}
@Override
public Number floor(Number x)
{
return ((Apfloat) x).floor();
}
@Override
public Number frac(Number x)
{
return ((Apfloat) x).frac();
}
@Override
public Number inverseErf(Number x)
{
return ApfloatMath.inverseErf((Apfloat) x);
}
@Override
public Number inverseErfc(Number x)
{
return ApfloatMath.inverseErfc((Apfloat) x);
}
@Override
public Number max(Number x, Number y)
{
return ApfloatMath.max((Apfloat) x, (Apfloat) y);
}
@Override
public Number min(Number x, Number y)
{
return ApfloatMath.min((Apfloat) x, (Apfloat) y);
}
@Override
public Number nextAfter(Number x, Number y)
{
return ApfloatMath.nextAfter((Apfloat) x, (Apfloat) y);
}
@Override
public Number nextDown(Number x)
{
return ApfloatMath.nextDown((Apfloat) x);
}
@Override
public Number nextUp(Number x)
{
return ApfloatMath.nextUp((Apfloat) x);
}
@Override
public Number truncate(Number x)
{
return ((Apfloat) x).truncate();
}
@Override
public Number toDegrees(Number x)
{
return ApfloatMath.toDegrees((Apfloat) x);
}
@Override
public Number toRadians(Number x)
{
return ApfloatMath.toRadians((Apfloat) x);
}
@Override
public Number atan2(Number x, Number y)
{
return ApfloatMath.atan2((Apfloat) x, (Apfloat) y);
}
@Override
public Number copySign(Number x, Number y)
{
return ApfloatMath.copySign((Apfloat) x, (Apfloat) y);
}
@Override
public Number fmod(Number x, Number y)
{
return ApfloatMath.fmod((Apfloat) x, (Apfloat) y);
}
@Override
public Number hypot(Number x, Number y)
{
return ApcomplexMath.abs(new Apcomplex((Apfloat) x, (Apfloat) y));
}
@Override
public Number roundToPrecision(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Rounding can only be used with a valid integer argument");
}
return roundToPrecision(x, y.longValue());
}
protected Number roundToPrecision(Number x, long precision)
{
return ApfloatMath.roundToPrecision((Apfloat) x, precision, RoundingMode.HALF_UP);
}
@Override
public Number roundToInteger(Number x)
{
return ApfloatMath.roundToInteger((Apfloat) x, RoundingMode.HALF_UP);
}
@Override
public Number roundToPlaces(Number x, Number y)
{
if (!isLong(y))
{
throw new IllegalArgumentException("Rounding can only be used with a valid integer argument");
}
return roundToPlaces(x, y.longValue());
}
protected Number roundToPlaces(Number x, long precision)
{
return ApfloatMath.roundToPlaces((Apfloat) x, precision, RoundingMode.HALF_UP);
}
@Override
public Number roundToMultiple(Number x, Number y)
{
return ApfloatMath.roundToMultiple((Apfloat) x, (Apfloat) y, RoundingMode.HALF_UP);
}
}
private class AprationalFunctions
extends ApfloatFunctions
{
@Override
public Number add(Number x, Number y)
{
return ((Aprational) x).add((Aprational) y);
}
@Override
public Number subtract(Number x, Number y)
{
return ((Aprational) x).subtract((Aprational) y);
}
@Override
public Number multiply(Number x, Number y)
{
return ((Aprational) x).multiply((Aprational) y);
}
@Override
public Number divide(Number x, Number y)
{
return ((Aprational) x).divide((Aprational) y);
}
@Override
public Number mod(Number x, Number y)
{
return ((Aprational) x).mod((Aprational) y);
}
@Override
public Number pochhammer(Number x, Number y)
{
if (y instanceof Apint)
{
return AprationalMath.pochhammer((Aprational) x, (Apint) y);
}
return super.pochhammer(x, y);
}
@Override
protected Number pow(Number x, long y)
{
return AprationalMath.pow((Aprational) x, y);
}
@Override
public Number binomial(Number x, Number y)
{
return AprationalMath.binomial((Aprational) x, (Aprational) y);
}
@Override
public Number hypot(Number x, Number y)
{
return root(add(pow(x, 2), pow(y, 2)), 2);
}
@Override
protected Number root(Number x, long y)
{
return new Aprational(root(((Aprational) x).numerator(), y), root(((Aprational) x).denominator(), y));
}
private Apint root(Apint x, long y)
{
Apint[] root = ApintMath.root(x, y);
if (root[1].signum() != 0)
{
throw new IllegalArgumentException("Cannot calculate inexact root to infinite precision");
}
return root[0];
}
@Override
protected Number roundToPrecision(Number x, long precision)
{
return AprationalMath.roundToPrecision((Aprational) x, precision, RoundingMode.HALF_UP);
}
@Override
public Number roundToInteger(Number x)
{
return AprationalMath.roundToInteger((Aprational) x, RoundingMode.HALF_UP);
}
@Override
protected Number roundToPlaces(Number x, long places)
{
return AprationalMath.roundToPlaces((Aprational) x, places, RoundingMode.HALF_UP);
}
@Override
public Number roundToMultiple(Number x, Number y)
{
return AprationalMath.roundToMultiple((Aprational) x, (Aprational) y, RoundingMode.HALF_UP);
}
@Override
protected Number scale(Number x, long y)
{
return AprationalMath.scale((Aprational) x, y);
}
}
private class ApintFunctions
extends AprationalFunctions
{
@Override
public Number binomial(Number x, Number y)
{
if (isLong(x) && isLong(y))
{
return ApintMath.binomial(x.longValue(), y.longValue());
}
return ApintMath.binomial((Apint) x, (Apint) y);
}
@Override
public Number gcd(Number x, Number y)
{
return ApintMath.gcd((Apint) x, (Apint) y);
}
@Override
public Number lcm(Number x, Number y)
{
return ApintMath.lcm((Apint) x, (Apint) y);
}
@Override
protected Number scale(Number x, long y)
{
return (y >= 0 ? ApintMath.scale((Apint) x, y) : super.scale(x, y));
}
}
/**
* Default constructor.
*/
public ApfloatCalculatorImpl()
{
}
@Override
public Number parseInteger(String value)
{
Apcomplex x;
if (value.equalsIgnoreCase("i"))
{
x = Apcomplex.I;
}
else if (value.endsWith("i") || value.endsWith("I"))
{
x = new Apint(value.substring(0, value.length() - 1)).multiply(Apcomplex.I);
}
else
{
x = new Apint(value);
}
if (getInputPrecision() != null)
{
x = x.precision(getInputPrecision());
}
return x;
}
@Override
public Number parseDecimal(String value)
{
Apcomplex x;
if (value.endsWith("i") || value.endsWith("I"))
{
x = new Apfloat(value.substring(0, value.length() - 1)).multiply(Apcomplex.I);
}
else
{
x = new Apfloat(value);
}
if (getInputPrecision() != null)
{
x = x.precision(getInputPrecision());
}
return x;
}
@Override
public String format(Number x)
{
String text;
boolean pretty = getFormat();
if (x instanceof Aprational)
{
text = x.toString();
}
else if (x instanceof Apfloat)
{
Apfloat a = (Apfloat) x;
a = ApfloatMath.roundToPrecision(a.precision(Util.ifFinite(a.precision(), a.precision() + 1)), a.precision(), RoundingMode.HALF_UP);
text = a.toString(pretty);
}
else
{
Apcomplex z = (Apcomplex) x;
String imag = (z.imag().equals(Apfloat.ONE) ? "" : (z.imag().negate().equals(Apfloat.ONE) ? "-" : format(z.imag())));
if (z.real().signum() == 0)
{
text = imag + "i";
}
else
{
text = format(z.real()) + (z.imag().signum() < 0 ? "" : "+") + imag + "i";
}
}
return text;
}
@Override
protected Functions getFunctions(Number x)
{
Functions functions;
if (x instanceof Apint)
{
functions = new ApintFunctions();
}
else if (x instanceof Aprational)
{
functions = new AprationalFunctions();
}
else if (x instanceof Apfloat)
{
functions = new ApfloatFunctions();
}
else
{
functions = new ApcomplexFunctions();
}
return functions;
}
@Override
protected Number promote(Number x)
{
if (!(x instanceof Apfloat) && ((Apcomplex) x).imag().signum() == 0)
{
// Complex to float
x = ((Apcomplex) x).real();
}
if (x instanceof Apfloat && !(x instanceof Aprational) && ((Apfloat) x).precision() == Apfloat.INFINITE && ((Apfloat) x).isInteger())
{
// Float to integer
x = ((Apfloat) x).truncate();
}
if (x instanceof Aprational && !(x instanceof Apint) && ((Aprational) x).denominator().equals(Apint.ONE))
{
// Rational to integer
x = ((Aprational) x).numerator();
}
return x;
}
@Override
public void setInputPrecision(Long inputPrecision)
{
super.setInputPrecision(inputPrecision);
this.fixedPrecisionApcomplexHelper = new FixedPrecisionApcomplexHelper(inputPrecision == null ? Apfloat.INFINITE : inputPrecision);
}
private Number fixedOrArbitraryPrecision(java.util.function.Function fixedPrecisionFunction, java.util.function.Function arbitraryPrecisionFunction, Number x)
{
Apcomplex z = (Apcomplex) x;
return (getInputPrecision() != null && z.isZero() ? fixedPrecisionFunction.apply(z) : arbitraryPrecisionFunction.apply(z));
}
private FixedPrecisionApcomplexHelper fixedPrecisionApcomplexHelper = new FixedPrecisionApcomplexHelper(Apfloat.INFINITE);
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/Calculator.java 0000664 0000000 0000000 00000005511 14557414736 0026301 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
/**
* Command-line calculator.
*
* @version 1.11.0
* @author Mikko Tommila
*/
public class Calculator
{
private Calculator()
{
}
/**
* Command-line entry point.
*
* @param args Command-line parameters.
*
* @exception ParseException In case of invalid input
*/
public static void main(String args[])
throws ParseException
{
boolean pretty = false;
Long inputPrecision = null;
for (int i = 0; i < args.length; i++)
{
switch (args[i])
{
case "-p":
pretty = true;
break;
case "-i":
try
{
i++;
inputPrecision = Long.valueOf(args[i]);
break;
}
catch (NumberFormatException | ArrayIndexOutOfBoundsException e)
{
// Fall through to usage
}
default:
System.err.println("Usage: calculator [-p] [-i inputPrecision]");
System.exit(1);
}
}
CalculatorImpl calculatorImpl = new ApfloatCalculatorImpl();
calculatorImpl.setFormat(pretty);
calculatorImpl.setInputPrecision(inputPrecision);
CalculatorParser calculatorParser = new CalculatorParser(System.in, System.out, calculatorImpl);
while (calculatorParser.parseOneLine())
{
// Loop until input ends or exception is thrown
}
}
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/CalculatorAWT.java 0000664 0000000 0000000 00000022106 14557414736 0026654 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.Panel;
import java.awt.Label;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.TextField;
import java.awt.TextArea;
import java.awt.Button;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;
/**
* Graphical AWT elements for the calculator.
*
* @version 1.9.1
* @author Mikko Tommila
*/
public class CalculatorAWT
extends Panel
{
private static final long serialVersionUID = 1L;
/**
* Construct a panel with graphical elements.
*/
public CalculatorAWT()
{
this.calculatorImpl = new ApfloatCalculatorImpl();
this.history = new ArrayList<>();
this.historyPosition = 0;
initGUI();
this.out = new PrintWriter(new FlushStringWriter(this.outputArea), true);
}
// Initialize the container and add the graphical elements to it
private void initGUI()
{
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.insets = new Insets(5, 5, 5, 5);
constraints.weightx = 1;
constraints.weighty = 1;
// Initial focus will be on the first element, which is added here although it's located at the bottom
this.inputField = new TextField(null, 60);
constraints.gridy = 8;
add(this.inputField, constraints);
this.calculateButton = new Button("Calculate");
constraints.gridwidth = GridBagConstraints.REMAINDER;
add(this.calculateButton, constraints);
this.outputArea = new TextArea(null, 20, 60, TextArea.SCROLLBARS_VERTICAL_ONLY);
this.outputArea.setEditable(false);
constraints.gridy = 0;
constraints.gridwidth = 1;
constraints.gridheight = 8;
add(this.outputArea, constraints);
this.formatLabel = new Label("Format:");
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.gridheight = 1;
add(this.formatLabel, constraints);
this.formats = new CheckboxGroup();
this.floating = new Checkbox("Floating", true, this.formats);
constraints.gridy = 1;
add(this.floating, constraints);
this.fixed = new Checkbox("Fixed", false, this.formats);
constraints.gridy = 2;
add(this.fixed, constraints);
this.inputTypeLabel = new Label("Input precision:");
constraints.gridy = 3;
add(this.inputTypeLabel, constraints);
this.inputPrecisionTypes = new CheckboxGroup();
this.inputPrecisionArbitrary = new Checkbox("Arbitrary", true, this.inputPrecisionTypes);
constraints.gridy = 4;
add(this.inputPrecisionArbitrary, constraints);
this.inputPrecisionFixed = new Checkbox("Fixed", false, this.inputPrecisionTypes);
constraints.gridy = 5;
add(this.inputPrecisionFixed, constraints);
this.inputPrecisionField = new TextField(null, 10);
constraints.gridy = 6;
add(this.inputPrecisionField, constraints);
this.clearButton = new Button("Clear");
constraints.gridy = 7;
constraints.weighty = 1000;
add(this.clearButton, constraints);
// Clear output area and command history
this.clearButton.addActionListener((actionEvent) ->
{
CalculatorAWT.this.outputArea.setText(null);
CalculatorAWT.this.history.clear();
CalculatorAWT.this.historyPosition = 0;
});
// Calculate current input button
this.calculateButton.addActionListener((actionEvent) -> processInput());
// Calculate current input by hitting enter in the input field
this.inputField.addActionListener((actionEvent) -> processInput());
// Command history handler for up and down arrow keys
this.inputField.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent keyEvent)
{
switch(keyEvent.getKeyCode())
{
case KeyEvent.VK_UP:
if (CalculatorAWT.this.historyPosition > 0)
{
CalculatorAWT.this.inputField.setText(CalculatorAWT.this.history.get(--CalculatorAWT.this.historyPosition));
CalculatorAWT.this.inputField.setCaretPosition(Integer.MAX_VALUE);
}
break;
case KeyEvent.VK_DOWN:
if (CalculatorAWT.this.historyPosition < CalculatorAWT.this.history.size() - 1)
{
CalculatorAWT.this.inputField.setText(CalculatorAWT.this.history.get(++CalculatorAWT.this.historyPosition));
CalculatorAWT.this.inputField.setCaretPosition(Integer.MAX_VALUE);
}
break;
default:
}
}
});
}
private void processInput()
{
Long inputPrecision;
if (this.inputPrecisionArbitrary.getState())
{
inputPrecision = null;
}
else
{
try
{
inputPrecision = Long.parseLong(this.inputPrecisionField.getText());
}
catch (NumberFormatException nfe)
{
this.inputPrecisionField.requestFocus();
return;
}
}
String text = this.inputField.getText();
this.inputField.setText(null);
this.out.println(text);
// Parse the input line; the parser prints the output
try
{
this.calculatorImpl.setFormat(this.fixed.getState());
this.calculatorImpl.setInputPrecision(inputPrecision);
CalculatorParser calculatorParser = new CalculatorParser(new StringReader(text), this.out, this.calculatorImpl);
calculatorParser.parseOneLine();
}
catch (Exception e)
{
this.out.println(e.getMessage());
}
// Show the bottom part of the output area
this.outputArea.requestFocus();
this.outputArea.setCaretPosition(Integer.MAX_VALUE);
this.inputField.requestFocus();
// Add last command to history and reset history position
this.history.add(text);
this.historyPosition = this.history.size();
}
// Prints output to a text area
private static class FlushStringWriter
extends StringWriter
{
public FlushStringWriter(TextArea dst)
{
this.dst = dst;
}
@Override
public void flush()
{
super.flush();
StringBuffer buffer = getBuffer();
String text = buffer.toString();
this.dst.append(text);
buffer.setLength(0);
}
private TextArea dst;
}
private CalculatorImpl calculatorImpl;
private List history;
private int historyPosition;
private TextArea outputArea;
private Label formatLabel;
private CheckboxGroup formats;
private Checkbox floating;
private Checkbox fixed;
private Label inputTypeLabel;
private CheckboxGroup inputPrecisionTypes;
private Checkbox inputPrecisionArbitrary;
private Checkbox inputPrecisionFixed;
private TextField inputPrecisionField;
private Button clearButton;
private TextField inputField;
private Button calculateButton;
private PrintWriter out;
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/CalculatorApplet.java 0000664 0000000 0000000 00000006535 14557414736 0027456 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.applet.Applet;
import java.io.File;
import java.security.AccessControlException;
import org.apfloat.ApfloatContext;
import org.apfloat.spi.FilenameGenerator;
/**
* Calculator applet.
*
* @version 1.9.1
* @author Mikko Tommila
*/
public class CalculatorApplet
extends Applet
{
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public CalculatorApplet()
{
}
/**
* Initialize this applet.
*/
@Override
public void init()
{
add(new CalculatorAWT());
// Recreate the executor service in case the old thread group was destroyed by reloading the applet
ApfloatContext ctx = ApfloatContext.getContext();
ctx.setExecutorService(ApfloatContext.getDefaultExecutorService());
try
{
// The applet may not be able to write files to the current directory, but probably can write to the temp directory
String path = System.getProperty("java.io.tmpdir");
if (path != null && !path.endsWith(File.separator))
{
path = path + File.separator;
}
FilenameGenerator filenameGenerator = new FilenameGenerator(path, null, null);
ctx.setFilenameGenerator(filenameGenerator);
}
catch (AccessControlException ace)
{
// Ignore - reading the system property may not be allowed in unsigned applets
}
}
/**
* Called when this applet is destroyed.
*/
@Override
public void destroy()
{
removeAll();
}
/**
* Get information about this applet.
*
* @return Information about this applet.
*/
@Override
public String getAppletInfo()
{
String lineSeparator = System.lineSeparator();
return "Calculator applet" + lineSeparator +
"Written by Mikko Tommila 2011 - 2023" + lineSeparator +
"Java version: " + System.getProperty("java.version") + lineSeparator +
"Java Virtual Machine: " + System.getProperty("java.vm.name");
}
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/CalculatorGUI.java 0000664 0000000 0000000 00000004510 14557414736 0026644 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.awt.Frame;
import java.awt.BorderLayout;
import java.awt.Label;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
/**
* AWT client application for the calculator.
*
* @version 1.9.0
* @author Mikko Tommila
*/
public class CalculatorGUI
extends Frame
{
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
protected CalculatorGUI()
{
super("Calculator");
setSize(720, 540);
addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent windowEvent)
{
setVisible(false);
dispose();
System.exit(0);
}
});
setLayout(new BorderLayout());
add(new CalculatorAWT(), BorderLayout.NORTH);
add(new Label(), BorderLayout.SOUTH);
setVisible(true);
}
/**
* Command-line entry point.
*
* @param args Command-line parameters.
*/
public static void main(String[] args)
{
new CalculatorGUI();
}
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/CalculatorImpl.java 0000664 0000000 0000000 00000013262 14557414736 0027125 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.util.List;
/**
* Calculator implementation interface.
* The calculator parser uses this interface to perform the actual calculations.
*
* @version 1.9.1
* @author Mikko Tommila
*/
public interface CalculatorImpl
{
/**
* Negative value.
*
* @param x The argument.
*
* @return -x
*
* @exception ParseException In case of invalid argument.
*/
public Number negate(Number x)
throws ParseException;
/**
* Addition.
*
* @param x First argument.
* @param y Second argument.
*
* @return x + y
*
* @exception ParseException In case of invalid arguments.
*/
public Number add(Number x, Number y)
throws ParseException;
/**
* Subtraction.
*
* @param x First argument.
* @param y Second argument.
*
* @return x - y
*
* @exception ParseException In case of invalid arguments.
*/
public Number subtract(Number x, Number y)
throws ParseException;
/**
* Multiplication.
*
* @param x First argument.
* @param y Second argument.
*
* @return x * y
*
* @exception ParseException In case of invalid arguments.
*/
public Number multiply(Number x, Number y)
throws ParseException;
/**
* Division.
*
* @param x First argument.
* @param y Second argument.
*
* @return x / y
*
* @exception ParseException In case of invalid arguments.
*/
public Number divide(Number x, Number y)
throws ParseException;
/**
* Remainder.
*
* @param x First argument.
* @param y Second argument.
*
* @return x % y
*
* @exception ParseException In case of invalid arguments.
*/
public Number mod(Number x, Number y)
throws ParseException;
/**
* Power.
*
* @param x First argument.
* @param y Second argument.
*
* @return xy
*
* @exception ParseException In case of invalid arguments.
*/
public Number pow(Number x, Number y)
throws ParseException;
/**
* Arbitrary function.
*
* @param name Name of the function.
* @param arguments Function arguments.
*
* @return Function value.
*
* @exception ParseException In case of invalid arguments.
*/
public Number function(String name, List arguments)
throws ParseException;
/**
* Parse a string to an integer number.
*
* @param value The string to parse.
*
* @return The number.
*
* @exception ParseException In case of invalid number.
*/
public Number parseInteger(String value)
throws ParseException;
/**
* Parse a string to a floating-point number.
*
* @param value The string to parse.
*
* @return The number.
*
* @exception ParseException In case of invalid number.
*/
public Number parseDecimal(String value)
throws ParseException;
/**
* Get a variable.
*
* @param name Name of the variable.
*
* @return Value of the variable, or null if the variable is not defined.
*
* @exception ParseException In case of invalid argument.
*/
public Number getVariable(String name)
throws ParseException;
/**
* Set a variable.
*
* @param name Name of the variable.
* @param value Value of the variable.
*
* @exception ParseException In case of invalid arguments.
*/
public void setVariable(String name, Number value)
throws ParseException;
/**
* Set the formatting option.
*
* @param pretty If a fixed-point or a floating-point notation should be used.
*/
public void setFormat(boolean pretty);
/**
* Set a fixed input precision.
*
* @param inputPrecision The precision if a fixed precision is used or null for arbitrary precision.
*/
public void setInputPrecision(Long inputPrecision);
/**
* Convert a number to a String. The current formatting option is used.
*
* @param x The number.
*
* @return The String.
*/
public String format(Number x);
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/CalculatorParser.jj 0000664 0000000 0000000 00000014576 14557414736 0027153 0 ustar 00root root 0000000 0000000 options
{
LOOKAHEAD = 2;
STATIC = false;
UNICODE_INPUT = true;
ERROR_REPORTING = false;
}
PARSER_BEGIN(CalculatorParser)
package org.apfloat.calc;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.List;
import java.util.ArrayList;
public class CalculatorParser
{
public CalculatorParser(InputStream in, OutputStream out, CalculatorImpl calculatorImpl)
{
this(in);
this.out = new PrintWriter(new OutputStreamWriter(out), true);
this.calculatorImpl = calculatorImpl;
}
public CalculatorParser(Reader in, Writer out, CalculatorImpl calculatorImpl)
{
this(in);
this.out = new PrintWriter(out, true);
this.calculatorImpl = calculatorImpl;
}
public CalculatorParser(Reader in, PrintWriter out, CalculatorImpl calculatorImpl)
{
this(in);
this.out = out;
this.calculatorImpl = calculatorImpl;
}
private PrintWriter out;
private CalculatorImpl calculatorImpl;
}
PARSER_END(CalculatorParser)
SKIP:
{
" "
| "\t"
}
TOKEN:
{
< INTEGER: (()+ ()? | ()) >
| < DECIMAL: (()+ ("." ()*)? | "." ()+) (["e","E"] (["+","-"])? ()+)? ()? >
| < DIGIT: ["0"-"9"] >
| < IMAGINARY: ["i","I"] >
| < IDENTIFIER: () ( | )* >
| < LETTER: ["$","A"-"Z","_","a"-"z","\u00c0"-"\u00d6","\u00d8"-"\u00f6","\u00f8"-"\u00ff","\u0100"-"\u1fff","\u3040"-"\u318f","\u3300"-"\u337f","\u3400"-"\u3d2d","\u4e00"-"\u9fff","\uf900"-"\ufaff"] >
| < DELIMITER: (";")+ >
| < EOL: ("\n" | "\r\n" | "\r") >
}
boolean parseOneLine():
{
Number a;
}
{
(
a = expression() { this.out.println(this.calculatorImpl.format(a)); }
)?
(
a = expression() { this.out.println(this.calculatorImpl.format(a)); }
)*
(
)?
(
{ return true; }
| { return false; }
)
}
Number expression():
{
Number a;
}
{
(
a = assignmentExpression()
| a = additiveExpression()
)
{ return a; }
}
Number assignmentExpression():
{
String v;
Number a;
}
{
v = variable()
(
"=" a = additiveExpression() { this.calculatorImpl.setVariable(v, a); }
| "+=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.add(this.calculatorImpl.getVariable(v), a)); }
| "-=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.subtract(this.calculatorImpl.getVariable(v), a)); }
| "*=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.multiply(this.calculatorImpl.getVariable(v), a)); }
| "/=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.divide(this.calculatorImpl.getVariable(v), a)); }
| "%=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.mod(this.calculatorImpl.getVariable(v), a)); }
| "^=" a = additiveExpression() { this.calculatorImpl.setVariable(v, this.calculatorImpl.pow(this.calculatorImpl.getVariable(v), a)); }
)
{ return this.calculatorImpl.getVariable(v); }
}
Number additiveExpression():
{
Number a;
Number b;
}
{
a = multiplicativeExpression()
(
"+" b = multiplicativeExpression() { a = this.calculatorImpl.add(a, b); }
| "-" b = multiplicativeExpression() { a = this.calculatorImpl.subtract(a, b); }
)*
{ return a; }
}
Number multiplicativeExpression():
{
Number a;
Number b;
}
{
a = unaryExpression()
(
"*" b = unaryExpression() { a = this.calculatorImpl.multiply(a, b); }
| "/" b = unaryExpression() { a = this.calculatorImpl.divide(a, b); }
| "%" b = unaryExpression() { a = this.calculatorImpl.mod(a, b); }
)*
{ return a; }
}
Number unaryExpression():
{
Number a;
}
{
"-" a = unaryExpression() { return this.calculatorImpl.negate(a); }
| "+" a = unaryExpression() { return a; }
| a = powerExpression() { return a; }
}
Number powerExpression():
{
Number a;
Number b;
}
{
a = element()
(
"^" b = unaryExpression() { a = this.calculatorImpl.pow(a, b); }
)?
{ return a; }
}
Number element():
{
String v;
Number a;
}
{
a = constant() { return a; }
| a = function() { return a; }
| v = variable() { return this.calculatorImpl.getVariable(v); }
| "(" a = expression() ")" { return a; }
}
String variable():
{
String v;
}
{
v = identifier() { return v; }
}
Number function():
{
String v;
List l;
Number a;
}
{
v = identifier()
"(" l = argumentList() ")" { return this.calculatorImpl.function(v, l); }
}
List argumentList():
{
List list = new ArrayList();
Number a;
}
{
(
a = expression() { list.add(a); }
(
"," a = expression() { list.add(a); }
)*
)?
{ return list; }
}
String identifier():
{
Token t;
}
{
t = { return t.toString(); }
}
Number constant():
{
Token t;
}
{
t = { return this.calculatorImpl.parseInteger(t.toString()); }
| t = { return this.calculatorImpl.parseDecimal(t.toString()); }
}
TOKEN:
{
< INVALID_CHAR: ~[] >
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/FunctionCalculatorImpl.java 0000664 0000000 0000000 00000067032 14557414736 0030637 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Calculator implementation with function support.
* Provides a mapping mechanism for functions.
*
* @version 1.11.0
* @author Mikko Tommila
*/
public abstract class FunctionCalculatorImpl
extends AbstractCalculatorImpl
{
private static final long serialVersionUID = 1L;
/**
* Arbitrary function.
*/
@FunctionalInterface
protected static interface Function
extends Serializable
{
/**
* Call the function.
*
* @param arguments The function's arguments.
*
* @return The function's value.
*
* @exception ParseException In case the arguments are invalid.
*/
public Number call(List arguments)
throws ParseException;
}
/**
* Function taking a fixed number of arguments.
*/
protected class FixedFunction
implements Function
{
private static final long serialVersionUID = 1L;
/**
* Validate the number of arguments.
*
* @param arguments The function's arguments.
*
* @exception ParseException In case of incorrect number of arguments.
*/
protected void validate(List arguments)
throws ParseException
{
if (this.minArguments == this.maxArguments && arguments.size() != this.minArguments)
{
throw new ParseException("Function " + this.name + " takes " + this.minArguments + " argument" + (this.minArguments == 1 ? "" : "s") + ", not " + arguments.size());
}
if (arguments.size() < this.minArguments || arguments.size() > this.maxArguments)
{
throw new ParseException("Function " + this.name + " takes " + this.minArguments + " to " + this.maxArguments + " arguments, not " + arguments.size());
}
}
@Override
public final Number call(List arguments)
throws ParseException
{
validate(arguments);
return promote(handler.call(getFunctions(arguments), arguments));
}
private String name;
private int minArguments;
private int maxArguments;
private FixedFunctionHandler handler;
}
/**
* Handler for FixedFunction.
*/
@FunctionalInterface
protected static interface FixedFunctionHandler
extends Serializable
{
/**
* Call the function.
*
* @param functions The function implementations.
* @param arguments The function's argument(s).
*
* @return The function's value.
*/
public Number call(Functions functions, List arguments);
}
/**
* Function implementations.
*/
protected static interface Functions
{
public Number negate(Number x);
public Number add(Number x, Number y);
public Number subtract(Number x, Number y);
public Number multiply(Number x, Number y);
public Number divide(Number x, Number y);
public Number mod(Number x, Number y);
public Number pow(Number x, Number y);
public Number arg(Number x);
public Number conj(Number x);
public Number imag(Number x);
public Number real(Number x);
public Number abs(Number x);
public Number acos(Number x);
public Number acosh(Number x);
public Number airyAi(Number x);
public Number airyAiPrime(Number x);
public Number airyBi(Number x);
public Number airyBiPrime(Number x);
public Number asin(Number x);
public Number asinh(Number x);
public Number atan(Number x);
public Number atanh(Number x);
public Number bernoulli(Number x);
public Number besselI(Number x, Number y);
public Number besselJ(Number x, Number y);
public Number besselK(Number x, Number y);
public Number besselY(Number x, Number y);
public Number beta(Number a, Number b);
public Number beta(Number x, Number a, Number b);
public Number beta(Number x1, Number x2, Number a, Number b);
public Number binomial(Number x, Number y);
public Number catalan(Number x);
public Number cbrt(Number x);
public Number ceil(Number x);
public Number cos(Number x);
public Number cosIntegral(Number x);
public Number cosh(Number x);
public Number coshIntegral(Number x);
public Number digamma(Number x);
public Number e(Number x);
public Number ellipticE(Number x);
public Number ellipticK(Number x);
public Number erf(Number x);
public Number erfc(Number x);
public Number erfi(Number x);
public Number euler(Number x);
public Number exp(Number x);
public Number expIntegralE(Number x, Number y);
public Number expIntegralEi(Number x);
public Number factorial(Number x);
public Number floor(Number x);
public Number frac(Number x);
public Number fresnelC(Number x);
public Number fresnelS(Number x);
public Number gamma(Number x);
public Number gamma(Number x, Number y);
public Number gamma(Number x, Number y, Number z);
public Number hypergeometric0F1(Number a, Number z);
public Number hypergeometric0F1Regularized(Number a, Number z);
public Number hypergeometric1F1(Number a, Number b, Number z);
public Number hypergeometric1F1Regularized(Number a, Number b, Number z);
public Number hypergeometric2F1(Number a, Number b, Number c, Number z);
public Number hypergeometric2F1Regularized(Number a, Number b, Number c, Number z);
public Number hypergeometricU(Number a, Number b, Number z);
public Number inverseErf(Number x);
public Number inverseErfc(Number x);
public Number glaisher(Number x);
public Number khinchin(Number x);
public Number log(Number x);
public Number log(Number x, Number y);
public Number logGamma(Number x);
public Number logIntegral(Number x);
public Number max(Number x, Number y);
public Number min(Number x, Number y);
public Number nextAfter(Number x, Number y);
public Number nextDown(Number x);
public Number nextUp(Number x);
public Number pi(Number x);
public Number pochhammer(Number x, Number y);
public Number polygamma(Number x, Number y);
public Number random(Number x);
public Number randomGaussian(Number x);
@Deprecated
public Number round(Number x, Number y);
public Number roundToPrecision(Number x, Number y);
public Number roundToInteger(Number x);
public Number roundToPlaces(Number x, Number y);
public Number roundToMultiple(Number x, Number y);
public Number sin(Number x);
public Number sinIntegral(Number x);
public Number sinh(Number x);
public Number sinhIntegral(Number x);
public Number sqrt(Number x);
public Number tan(Number x);
public Number tanh(Number x);
public Number truncate(Number x);
public Number toDegrees(Number x);
public Number toRadians(Number x);
public Number ulp(Number x);
public Number zeta(Number x);
public Number zeta(Number x, Number y);
public Number agm(Number x, Number y);
public Number w(Number x);
public Number w(Number x, Number y);
public Number atan2(Number x, Number y);
public Number copySign(Number x, Number y);
public Number fmod(Number x, Number y);
public Number gcd(Number x, Number y);
public Number hypot(Number x, Number y);
public Number inverseRoot(Number x, Number y);
public Number inverseRoot(Number x, Number y, Number z);
public Number lcm(Number x, Number y);
public Number root(Number x, Number y);
public Number root(Number x, Number y, Number z);
public Number scale(Number x, Number y);
public Number precision(Number x, Number y);
}
/**
* Default constructor.
*/
protected FunctionCalculatorImpl()
{
this.functions = new HashMap<>();
setFunction("negate", fixedFunction("negate", 1, (functions, arguments) -> functions.negate(arguments.get(0))));
setFunction("add", fixedFunction("add", 2, (functions, arguments) -> functions.add(arguments.get(0), arguments.get(1))));
setFunction("subtract", fixedFunction("subtract", 2, (functions, arguments) -> functions.subtract(arguments.get(0), arguments.get(1))));
setFunction("multiply", fixedFunction("multiply", 2, (functions, arguments) -> functions.multiply(arguments.get(0), arguments.get(1))));
setFunction("divide", fixedFunction("divide", 2, (functions, arguments) -> functions.divide(arguments.get(0), arguments.get(1))));
setFunction("mod", fixedFunction("mod", 2, (functions, arguments) -> functions.mod(arguments.get(0), arguments.get(1))));
setFunction("pow", fixedFunction("pow", 2, (functions, arguments) -> functions.pow(arguments.get(0), arguments.get(1))));
setFunction("abs", fixedFunction("abs", 1, (functions, arguments) -> functions.abs(arguments.get(0))));
setFunction("acos", fixedFunction("acos", 1, (functions, arguments) -> functions.acos(arguments.get(0))));
setFunction("acosh", fixedFunction("acosh", 1, (functions, arguments) -> functions.acosh(arguments.get(0))));
setFunction("airyAi", fixedFunction("airyAi", 1, (functions, arguments) -> functions.airyAi(arguments.get(0))));
setFunction("airyAiPrime", fixedFunction("airyAiPrime", 1, (functions, arguments) -> functions.airyAiPrime(arguments.get(0))));
setFunction("airyBi", fixedFunction("airyBi", 1, (functions, arguments) -> functions.airyBi(arguments.get(0))));
setFunction("airyBiPrime", fixedFunction("airyBiPrime", 1, (functions, arguments) -> functions.airyBiPrime(arguments.get(0))));
setFunction("asin", fixedFunction("asin", 1, (functions, arguments) -> functions.asin(arguments.get(0))));
setFunction("asinh", fixedFunction("asinh", 1, (functions, arguments) -> functions.asinh(arguments.get(0))));
setFunction("atan", fixedFunction("atan", 1, (functions, arguments) -> functions.atan(arguments.get(0))));
setFunction("atanh", fixedFunction("atanh", 1, (functions, arguments) -> functions.atanh(arguments.get(0))));
setFunction("bernoulli", fixedFunction("bernoulli", 1, (functions, arguments) -> functions.bernoulli(arguments.get(0))));
setFunction("besselI", fixedFunction("besselI", 2, (functions, arguments) -> functions.besselI(arguments.get(0), arguments.get(1))));
setFunction("besselJ", fixedFunction("besselJ", 2, (functions, arguments) -> functions.besselJ(arguments.get(0), arguments.get(1))));
setFunction("besselK", fixedFunction("besselK", 2, (functions, arguments) -> functions.besselK(arguments.get(0), arguments.get(1))));
setFunction("besselY", fixedFunction("besselY", 2, (functions, arguments) -> functions.besselY(arguments.get(0), arguments.get(1))));
setFunction("beta", fixedFunction("beta", 2, 4, (functions, arguments) -> (arguments.size() == 2 ? functions.beta(arguments.get(0), arguments.get(1)) : arguments.size() == 3 ? functions.beta(arguments.get(0), arguments.get(1), arguments.get(2)): functions.beta(arguments.get(0), arguments.get(1), arguments.get(2), arguments.get(3)))));
setFunction("binomial", fixedFunction("binomial", 2, (functions, arguments) -> functions.binomial(arguments.get(0), arguments.get(1))));
setFunction("catalan", fixedFunction("catalan", 0, 1, (functions, arguments) -> functions.catalan(argumentOrInputPrecision(arguments))));
setFunction("cbrt", fixedFunction("cbrt", 1, (functions, arguments) -> functions.cbrt(arguments.get(0))));
setFunction("ceil", fixedFunction("ceil", 1, (functions, arguments) -> functions.ceil(arguments.get(0))));
setFunction("cos", fixedFunction("cos", 1, (functions, arguments) -> functions.cos(arguments.get(0))));
setFunction("cosIntegral", fixedFunction("cosIntegral", 1, (functions, arguments) -> functions.cosIntegral(arguments.get(0))));
setFunction("cosh", fixedFunction("cosh", 1, (functions, arguments) -> functions.cosh(arguments.get(0))));
setFunction("coshIntegral", fixedFunction("coshIntegral", 1, (functions, arguments) -> functions.coshIntegral(arguments.get(0))));
setFunction("digamma", fixedFunction("digamma", 1, (functions, arguments) -> functions.digamma(arguments.get(0))));
setFunction("e", fixedFunction("e", 0, 1, (functions, arguments) -> functions.e(argumentOrInputPrecision(arguments))));
setFunction("ellipticE", fixedFunction("ellipticE", 1, (functions, arguments) -> functions.ellipticE(arguments.get(0))));
setFunction("ellipticK", fixedFunction("ellipticK", 1, (functions, arguments) -> functions.ellipticK(arguments.get(0))));
setFunction("erf", fixedFunction("erf", 1, (functions, arguments) -> functions.erf(arguments.get(0))));
setFunction("erfc", fixedFunction("erfc", 1, (functions, arguments) -> functions.erfc(arguments.get(0))));
setFunction("erfi", fixedFunction("erfi", 1, (functions, arguments) -> functions.erfi(arguments.get(0))));
setFunction("euler", fixedFunction("euler", 0, 1, (functions, arguments) -> functions.euler(argumentOrInputPrecision(arguments))));
setFunction("exp", fixedFunction("exp", 1, (functions, arguments) -> functions.exp(arguments.get(0))));
setFunction("expIntegralE", fixedFunction("expIntegralE", 2, (functions, arguments) -> functions.expIntegralE(arguments.get(0), arguments.get(1))));
setFunction("expIntegralEi", fixedFunction("expIntegralEi", 1, (functions, arguments) -> functions.expIntegralEi(arguments.get(0))));
setFunction("factorial", fixedFunction("factorial", 1, (functions, arguments) -> functions.factorial(arguments.get(0))));
setFunction("floor", fixedFunction("floor", 1, (functions, arguments) -> functions.floor(arguments.get(0))));
setFunction("frac", fixedFunction("frac", 1, (functions, arguments) -> functions.frac(arguments.get(0))));
setFunction("fresnelC", fixedFunction("fresnelC", 1, (functions, arguments) -> functions.fresnelC(arguments.get(0))));
setFunction("fresnelS", fixedFunction("fresnelS", 1, (functions, arguments) -> functions.fresnelS(arguments.get(0))));
setFunction("gamma", fixedFunction("gamma", 1, 3, (functions, arguments) -> (arguments.size() == 1 ? functions.gamma(arguments.get(0)) : arguments.size() == 2 ? functions.gamma(arguments.get(0), arguments.get(1)): functions.gamma(arguments.get(0), arguments.get(1), arguments.get(2)))));
setFunction("glaisher", fixedFunction("glaisher", 0, 1, (functions, arguments) -> functions.glaisher(argumentOrInputPrecision(arguments))));
setFunction("hypergeometric0F1", fixedFunction("hypergeometric0F1", 2, (functions, arguments) -> functions.hypergeometric0F1(arguments.get(0), arguments.get(1))));
setFunction("hypergeometric0F1Regularized", fixedFunction("hypergeometric0F1Regularized", 2, (functions, arguments) -> functions.hypergeometric0F1Regularized(arguments.get(0), arguments.get(1))));
setFunction("hypergeometric1F1", fixedFunction("hypergeometric1F1", 3, (functions, arguments) -> functions.hypergeometric1F1(arguments.get(0), arguments.get(1), arguments.get(2))));
setFunction("hypergeometric1F1Regularized", fixedFunction("hypergeometric1F1Regularized", 3, (functions, arguments) -> functions.hypergeometric1F1Regularized(arguments.get(0), arguments.get(1), arguments.get(2))));
setFunction("hypergeometric2F1", fixedFunction("hypergeometric2F1", 4, (functions, arguments) -> functions.hypergeometric2F1(arguments.get(0), arguments.get(1), arguments.get(2), arguments.get(3))));
setFunction("hypergeometric2F1Regularized", fixedFunction("hypergeometric2F1Regularized", 4, (functions, arguments) -> functions.hypergeometric2F1Regularized(arguments.get(0), arguments.get(1), arguments.get(2), arguments.get(3))));
setFunction("hypergeometricU", fixedFunction("hypergeometricU", 3, (functions, arguments) -> functions.hypergeometricU(arguments.get(0), arguments.get(1), arguments.get(2))));
setFunction("inverseErf", fixedFunction("inverseErf", 1, (functions, arguments) -> functions.inverseErf(arguments.get(0))));
setFunction("inverseErfc", fixedFunction("inverseErfc", 1, (functions, arguments) -> functions.inverseErfc(arguments.get(0))));
setFunction("khinchin", fixedFunction("khinchin", 0, 1, (functions, arguments) -> functions.khinchin(argumentOrInputPrecision(arguments))));
setFunction("log", fixedFunction("log", 1, 2, (functions, arguments) -> (arguments.size() == 1 ? functions.log(arguments.get(0)) : functions.log(arguments.get(0), arguments.get(1)))));
setFunction("logGamma", fixedFunction("logGamma", 1, (functions, arguments) -> functions.logGamma(arguments.get(0))));
setFunction("logIntegral", fixedFunction("logIntegral", 1, (functions, arguments) -> functions.logIntegral(arguments.get(0))));
setFunction("max", fixedFunction("max", 2, (functions, arguments) -> functions.max(arguments.get(0), arguments.get(1))));
setFunction("min", fixedFunction("min", 2, (functions, arguments) -> functions.min(arguments.get(0), arguments.get(1))));
setFunction("nextAfter", fixedFunction("nextAfter", 2, (functions, arguments) -> functions.nextAfter(arguments.get(0), arguments.get(1))));
setFunction("nextDown", fixedFunction("nextDown", 1, (functions, arguments) -> functions.nextDown(arguments.get(0))));
setFunction("nextUp", fixedFunction("nextUp", 1, (functions, arguments) -> functions.nextUp(arguments.get(0))));
setFunction("pi", fixedFunction("pi", 0, 1, (functions, arguments) -> functions.pi(argumentOrInputPrecision(arguments))));
setFunction("pochhammer", fixedFunction("pochhammer", 2, (functions, arguments) -> functions.pochhammer(arguments.get(0), arguments.get(1))));
setFunction("polygamma", fixedFunction("polygamma", 2, (functions, arguments) -> functions.polygamma(arguments.get(0), arguments.get(1))));
setFunction("random", fixedFunction("random", 0, 1, (functions, arguments) -> functions.random(argumentOrInputPrecision(arguments))));
setFunction("randomGaussian", fixedFunction("randomGaussian", 0, 1, (functions, arguments) -> functions.randomGaussian(argumentOrInputPrecision(arguments))));
setFunction("round", fixedFunction("round", 2, (functions, arguments) -> functions.round(arguments.get(0), arguments.get(1))));
setFunction("roundToPrecision", fixedFunction("roundToPrecision", 2, (functions, arguments) -> functions.roundToPrecision(arguments.get(0), arguments.get(1))));
setFunction("roundToInteger", fixedFunction("roundToInteger", 1, (functions, arguments) -> functions.roundToInteger(arguments.get(0))));
setFunction("roundToPlaces", fixedFunction("roundToPlaces", 2, (functions, arguments) -> functions.roundToPlaces(arguments.get(0), arguments.get(1))));
setFunction("roundToMultiple", fixedFunction("roundToMultiple", 2, (functions, arguments) -> functions.roundToMultiple(arguments.get(0), arguments.get(1))));
setFunction("sin", fixedFunction("sin", 1, (functions, arguments) -> functions.sin(arguments.get(0))));
setFunction("sinIntegral", fixedFunction("sinIntegral", 1, (functions, arguments) -> functions.sinIntegral(arguments.get(0))));
setFunction("sinh", fixedFunction("sinh", 1, (functions, arguments) -> functions.sinh(arguments.get(0))));
setFunction("sinhIntegral", fixedFunction("sinhIntegral", 1, (functions, arguments) -> functions.sinhIntegral(arguments.get(0))));
setFunction("sqrt", fixedFunction("sqrt", 1, (functions, arguments) -> functions.sqrt(arguments.get(0))));
setFunction("tan", fixedFunction("tan", 1, (functions, arguments) -> functions.tan(arguments.get(0))));
setFunction("tanh", fixedFunction("tanh", 1, (functions, arguments) -> functions.tanh(arguments.get(0))));
setFunction("truncate", fixedFunction("truncate", 1, (functions, arguments) -> functions.truncate(arguments.get(0))));
setFunction("toDegrees", fixedFunction("toDegrees", 1, (functions, arguments) -> functions.toDegrees(arguments.get(0))));
setFunction("toRadians", fixedFunction("toRadians", 1, (functions, arguments) -> functions.toRadians(arguments.get(0))));
setFunction("ulp", fixedFunction("ulp", 1, (functions, arguments) -> functions.ulp(arguments.get(0))));
setFunction("zeta", fixedFunction("zeta", 1, 2, (functions, arguments) -> (arguments.size() == 1 ? functions.zeta(arguments.get(0)) : functions.zeta(arguments.get(0), arguments.get(1)))));
setFunction("arg", fixedFunction("arg", 1, (functions, arguments) -> functions.arg(arguments.get(0))));
setFunction("conj", fixedFunction("conj", 1, (functions, arguments) -> functions.conj(arguments.get(0))));
setFunction("imag", fixedFunction("imag", 1, (functions, arguments) -> functions.imag(arguments.get(0))));
setFunction("real", fixedFunction("real", 1, (functions, arguments) -> functions.real(arguments.get(0))));
setFunction("agm", fixedFunction("agm", 2, (functions, arguments) -> functions.agm(arguments.get(0), arguments.get(1))));
setFunction("w", fixedFunction("w", 1, 2, (functions, arguments) -> (arguments.size() == 1 ? functions.w(arguments.get(0)) : functions.w(arguments.get(0), arguments.get(1)))));
setFunction("atan2", fixedFunction("atan2", 2, (functions, arguments) -> functions.atan2(arguments.get(0), arguments.get(1))));
setFunction("copySign", fixedFunction("copySign", 2, (functions, arguments) -> functions.copySign(arguments.get(0), arguments.get(1))));
setFunction("fmod", fixedFunction("fmod", 2, (functions, arguments) -> functions.fmod(arguments.get(0), arguments.get(1))));
setFunction("gcd", fixedFunction("gcd", 2, (functions, arguments) -> functions.gcd(arguments.get(0), arguments.get(1))));
setFunction("hypot", fixedFunction("hypot", 2, (functions, arguments) -> functions.hypot(arguments.get(0), arguments.get(1))));
setFunction("inverseRoot", fixedFunction("inverseRoot", 2, 3, (functions, arguments) -> (arguments.size() == 2 ? functions.inverseRoot(arguments.get(0), arguments.get(1)) : functions.inverseRoot(arguments.get(0), arguments.get(1), arguments.get(2)))));
setFunction("lcm", fixedFunction("lcm", 2, (functions, arguments) -> functions.lcm(arguments.get(0), arguments.get(1))));
setFunction("root", fixedFunction("root", 2, 3, (functions, arguments) -> (arguments.size() == 2 ? functions.root(arguments.get(0), arguments.get(1)) : functions.root(arguments.get(0), arguments.get(1), arguments.get(2)))));
setFunction("scale", fixedFunction("scale", 2, (functions, arguments) -> functions.scale(arguments.get(0), arguments.get(1))));
setFunction("n", fixedFunction("precision", 2, (functions, arguments) -> functions.precision(arguments.get(0), arguments.get(1))));
}
@Override
public Number function(String name, List arguments)
throws ParseException
{
Function function = functions.get(name);
if (function == null)
{
throw new ParseException("Invalid function: " + name);
}
return function.call(arguments);
}
private Functions getFunctions(List arguments)
{
Functions functions = (arguments.isEmpty() ? getFunctions((Number) null) : null);
for (Number argument : arguments)
{
Functions functions2 = getFunctions(argument);
functions = (functions != null && functions.getClass().isAssignableFrom(functions2.getClass()) ? functions : functions2);
}
return functions;
}
private Number argumentOrInputPrecision(List arguments)
{
return arguments.size() == 0 ? getInputPrecision() : arguments.get(0);
}
/**
* Factory method.
*
* @param name The function's name.
* @param arguments The number of arguments that the function takes.
* @param handler The handler of the function.
*
* @return The function.
*/
protected FixedFunction fixedFunction(String name, int arguments, FixedFunctionHandler handler)
{
return fixedFunction(name, arguments, arguments, handler);
}
/**
* Factory method.
*
* @param name The function's name.
* @param minArguments The minimum number of arguments that the function takes.
* @param maxArguments The maximum number of arguments that the function takes.
* @param handler The handler of the function.
*
* @return The function.
*/
protected FixedFunction fixedFunction(String name, int minArguments, int maxArguments, FixedFunctionHandler handler)
{
FixedFunction fixedFunction = new FixedFunction();
fixedFunction.name = name;
fixedFunction.minArguments = minArguments;
fixedFunction.maxArguments = maxArguments;
fixedFunction.handler = handler;
return fixedFunction;
}
/**
* Define a function.
*
* @param name The function name.
* @param function The function.
*/
protected void setFunction(String name, Function function)
{
this.functions.put(name, function);
}
/**
* Get the function implementations.
*
* @param x The number to use as the function argument.
*
* @return The function implementations.
*/
protected abstract Functions getFunctions(Number x);
/**
* Promote a number to a more specific class.
*
* @param x The argument.
*
* @return The argument, possibly converted to a more specific subclass.
*/
protected abstract Number promote(Number x);
private Map functions;
}
apfloat-1.13.0/apfloat-calc/src/main/java/org/apfloat/calc/package-info.java 0000664 0000000 0000000 00000002355 14557414736 0026537 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
Arbitrary precision calculator interactive application.
*/
package org.apfloat.calc;
apfloat-1.13.0/apfloat-calc/src/test/ 0000775 0000000 0000000 00000000000 14557414736 0017336 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/test/java/ 0000775 0000000 0000000 00000000000 14557414736 0020257 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/test/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021046 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/test/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0022474 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/test/java/org/apfloat/calc/ 0000775 0000000 0000000 00000000000 14557414736 0023376 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-calc/src/test/java/org/apfloat/calc/CalculatorTest.java 0000664 0000000 0000000 00000106606 14557414736 0027203 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.calc;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* @version 1.11.0
* @author Mikko Tommila
*/
public class CalculatorTest
extends TestCase
{
public CalculatorTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new CalculatorTest("testOperators"));
suite.addTest(new CalculatorTest("testFunctions"));
suite.addTest(new CalculatorTest("testArguments"));
return suite;
}
private static void assertCalculation(String expected, String input, String... args)
throws ParseException
{
String actual = runCalculation(input, args);
assertEquals(input, expected + NEWLINE, actual);
}
private static void assertCalculationMatch(String expectedPattern, String input, String... args)
throws ParseException
{
String actual = runCalculation(input, args);
if (!actual.matches('(' + expectedPattern + ')' + NEWLINE))
{
assertEquals(input, expectedPattern + NEWLINE, actual);
}
}
private static String runCalculation(String input, String... args)
throws ParseException
{
InputStream oldIn = System.in;
PrintStream oldOut = System.out;
String actual;
try
{
InputStream in = new ByteArrayInputStream(input.getBytes());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
PrintStream out = new PrintStream(buffer, true);
System.setIn(in);
System.setOut(out);
Calculator.main(args);
actual = new String(buffer.toByteArray());
}
finally
{
System.setIn(oldIn);
System.setOut(oldOut);
}
return actual;
}
private static void assertCalculationFailure(String input, String... args)
{
try
{
runCalculation(input, args);
fail(input + " accepted");
}
catch (ParseException pe)
{
// OK: syntax error
}
catch (ArithmeticException ae)
{
// OK: result is not a number
}
catch (IllegalArgumentException iae)
{
// OK: invalid parameter
}
catch (org.apfloat.ApfloatRuntimeException are)
{
// OK: attempt invalid calculation
}
}
public static void testOperators()
throws ParseException
{
assertCalculation("163", "1+2*3^4");
assertCalculation("77", "99-22");
assertCalculation("7.7e1", "99.1-22.1");
assertCalculation("i", "2i-i");
assertCalculation("5" + NEWLINE + "11", "x = 5; x + 6");
assertCalculation("5" + NEWLINE + "11" + NEWLINE + "11", "x = 5; x += 6; x");
assertCalculation("5" + NEWLINE + "-1" + NEWLINE + "-1", "x = 5; x -= 6; x");
assertCalculation("5" + NEWLINE + "30" + NEWLINE + "30", "x = 5; x *= 6; x");
assertCalculation("30" + NEWLINE + "5" + NEWLINE + "5", "x = 30; x /= 6; x");
assertCalculation("31" + NEWLINE + "1" + NEWLINE + "1", "x = 31; x %= 6; x");
assertCalculation("5" + NEWLINE + "125" + NEWLINE + "125", "x = 5; x ^= 3; x");
assertCalculation("2", "5 % 3");
assertCalculation("2.1", "5.1 % 3");
assertCalculation("2", "5 + -3");
assertCalculation("7/6", "1/2 + 2/3");
assertCalculation("5e-1", "1./2");
assertCalculation("5e-1", ".5");
assertCalculation("5e-1", ".5e0");
assertCalculation("5e-1", "5e-1");
assertCalculation("5e-1", "5.e-1");
assertCalculation("5e1", "5e1");
assertCalculation("6.67", "20.0/3.00");
assertCalculation("-1", "I*I");
assertCalculation("3+2i", "2I+3");
assertCalculation("3-2i", "i*-2+3");
assertCalculation("35", "((5))*(3+4)");
assertCalculation("7", "+++++++++++++7");
assertCalculation("8", "--8");
assertCalculation("-9", "-----9");
assertCalculation("1", " ;;; \t 1 ;;;;;;;;; ");
assertCalculation("1.41421", "2.0000^0.50000");
assertCalculation("8.8080652584e646456992", "2^2147483647.0");
assertCalculation("-1", "i^2");
assertCalculation("1", "1^2i");
assertCalculationFailure("6%i");
assertCalculationFailure("5e");
assertCalculationFailure("2^^2");
assertCalculationFailure("2a2");
assertCalculationFailure("x=");
assertCalculationFailure("x+=");
assertCalculationFailure("x-=");
assertCalculationFailure("x*=");
assertCalculationFailure("x/=");
assertCalculationFailure("x%=");
assertCalculationFailure("x^=");
assertCalculationFailure("*5");
assertCalculationFailure("/");
assertCalculationFailure("6%");
assertCalculationFailure("2-");
assertCalculationFailure("bogus^5");
}
public static void testFunctions()
throws ParseException
{
assertCalculation("3", "abs(-3)");
assertCalculation("3", "abs(-3i)");
assertCalculation("5", "abs(3.00 + 4.00I)");
assertCalculation("3.03703e-1", "airyAi(0.200000)");
assertCalculation("-2.52405e-1", "airyAiPrime(0.200000)");
assertCalculation("7.05464e-1", "airyBi(0.200000)");
assertCalculation("4.61789e-1", "airyBiPrime(0.200000)");
assertCalculation("7/6", "bernoulli(14)");
assertCalculation("1.72763", "besselI(0.700000,1.90000)");
assertCalculation("5.84978e-1", "besselJ(0.700000,1.90000)");
assertCalculation("2.06052", "besselK(0.700000,0.300000)");
assertCalculation("-1.6523", "besselY(0.700000,0.300000)");
assertCalculation("3.55114", "beta(0.200000,4.00000)");
assertCalculation("3.00545", "beta(0.100000,0.200000,4.00000)");
assertCalculation("-1.02994", "beta(0.100000,2.90000,0.200000,4.00000)");
assertCalculation("1.5057e2", "binomial(9.2000,4.6000)");
assertCalculation("2.3282", "binomial(4,3.5000)");
assertCalculation("6.5625", "binomial(4.5000,3)");
assertCalculation("45", "binomial(10,2)");
assertCalculation("366166666666666666665821666666666666666667100000000000000000000", "binomial(1300000000000000000000,3)");
assertCalculation("0", "binomial(3,1300000000000000000000)");
assertCalculation("1", "binomial(1300000000000000000000,1300000000000000000000)");
assertCalculation("1040/81", "binomial(16/3,7/3)");
assertCalculation("-455/81", "binomial(-7/3,-16/3)");
assertCalculation("-1", "binomial(-1,1)");
assertCalculation("0", "binomial(1,-1)");
assertCalculation("0", "binomial(3.5,4.5)");
assertCalculation("-3.109-1.604i", "binomial(3.000+4.000i,5.000+6.000i)");
assertCalculation("9.1596559e-1", "catalan(8)");
assertCalculation("2", "cbrt(8)");
assertCalculation("2/3", "cbrt(8/27)");
assertCalculation("7.07e-1+7.07e-1i", "cbrt(-0.707+0.707i)");
assertCalculation("1.2599", "cbrt(2.0000)");
assertCalculation("2", "ceil(1.1)");
assertCalculation("2", "ceil(3/2)");
assertCalculation("-2", "copySign(2, -3)");
assertCalculation("-1.04221", "cosIntegral(0.200000)");
assertCalculation("-1.02221", "coshIntegral(0.200000)");
assertCalculation("1.7061", "digamma(6.0000)");
assertCalculation("1.48904", "ellipticE(0.200000)");
assertCalculation("1.65962", "ellipticK(0.200000)");
assertCalculation("2.22703e-1", "erf(0.200000)");
assertCalculation("7.77297e-1", "erfc(0.200000)");
assertCalculation("2.41591", "erfi(1.20000)");
assertCalculation("1.172", "expIntegralE(0.70000,0.30000)");
assertCalculation("2.44209", "expIntegralEi(1.20000)");
assertCalculation("5040", "factorial(7)");
assertCalculation("2", "floor(2.9)");
assertCalculation("2", "floor(29/10)");
assertCalculation("9e-1", "frac(2.9)");
assertCalculation("9/10", "frac(29/10)");
assertCalculation("7.15438e-1", "fresnelC(1.20000)");
assertCalculation("6.23401e-1", "fresnelS(1.20000)");
assertCalculation("6", "gamma(4)");
assertCalculation("5.8861", "gamma(4.0000, 1.0000)");
assertCalculation("5.0928", "gamma(4.0000, 0, 6.0000)");
assertCalculation("4.74294943677064514689542753377e1-3.27488916473624576880974867017e1i", "gamma(100.000000000000000000000000000+374.000000000000000000000000000i)");
assertCalculation("1.282427", "glaisher(7)");
assertCalculation("1.453+1.237i", "hypergeometric0F1(3.456+2.890i,0.1234+4.678i)");
assertCalculation("2.6328", "hypergeometric0F1Regularized(-3.00000,2.50000)");
assertCalculation("-7.477+3.738i", "hypergeometric1F1(3.456+2.890i,3.456+2.890i,2.1234+2.678i)");
assertCalculation("1.2856", "hypergeometric1F1Regularized(0.200000,-3,1.50000)");
assertCalculation("-1.478-2.074i", "hypergeometric2F1(9.456+4.890i,3.456+2.890i,1.256+1.390i,0.11234+0.1678i)");
assertCalculation("4.8317", "hypergeometric2F1Regularized(0.100000,0.200000,-3,0.800000)");
assertCalculation("4.99704", "hypergeometricU(1.20000,2,0.200000)");
assertCalculation("2", "fmod(5, 3)");
assertCalculation("5", "hypot(3, 4)");
assertCalculation("5e-1", "hypot(0.3, 0.4)");
assertCalculation("1.16309", "inverseErf(0.900000)");
assertCalculation("1.0179", "inverseErfc(0.150000)");
assertCalculation("5e-1", "inverseRoot(2.0, 1)");
assertCalculation("5e-1", "inverseRoot(4.0, 2)");
assertCalculation("7.07e-1-7.07e-1i", "inverseRoot(-0.707+0.707i, 3)");
assertCalculation("-5e-1", "inverseRoot(4.0, 2, 1)");
assertCalculation("2.685452", "khinchin(7)");
assertCalculation("-4.371-3.651i", "logGamma(-1.234+2.345i)");
assertCalculation("1.04516", "logIntegral(2.0000)");
assertCalculation("1.23", "n(1.23456, 3)");
assertCalculation("1.04748", "pochhammer(1.20000,0.700000)");
assertCalculation("280/81", "pochhammer(1/3,4)");
assertCalculation("-3.2018", "polygamma(2,0.900000)");
assertCalculation("2", "root(8, 3)");
assertCalculation("2/3", "root(16/81, 4)");
assertCalculation("7.07e-1+7.07e-1i", "root(-0.707+0.707i, 3)");
assertCalculation("1.2599", "root(2.0000, 3)");
assertCalculation("-4", "root(16.0, 2, 1)");
assertCalculation("3", "round(2.9, 1)");
assertCalculation("3", "round(29/10, 1)");
assertCalculation("3", "round(2.5, 1)");
assertCalculation("4", "round(3.5, 1)");
assertCalculation("-3", "round(-2.5, 1)");
assertCalculation("-4", "round(-3.5, 1)");
assertCalculation("3", "roundToPrecision(2.9, 1)");
assertCalculation("3", "roundToPrecision(29/10, 1)");
assertCalculation("3", "roundToPrecision(2.5, 1)");
assertCalculation("4", "roundToPrecision(3.5, 1)");
assertCalculation("-3", "roundToPrecision(-2.5, 1)");
assertCalculation("-4", "roundToPrecision(-3.5, 1)");
assertCalculation("3", "roundToInteger(2.9)");
assertCalculation("3", "roundToInteger(29/10)");
assertCalculation("3", "roundToInteger(2.5)");
assertCalculation("-3", "roundToInteger(-2.5)");
assertCalculation("-4", "roundToInteger(-3.5)");
assertCalculation("2.9", "roundToPlaces(2.94, 1)");
assertCalculation("3e-1", "roundToPlaces(29/100, 1)");
assertCalculation("30", "roundToPlaces(25, -1)");
assertCalculation("4", "roundToPlaces(3.5, 0)");
assertCalculation("-2.35", "roundToPlaces(-2.345, 2)");
assertCalculation("-3.36", "roundToPlaces(-3.355, 2)");
assertCalculation("2.4", "roundToMultiple(2.9, 1.2)");
assertCalculation("20/7", "roundToMultiple(29/10, 1/7)");
assertCalculation("3", "roundToMultiple(2.5, 1.0)");
assertCalculation("4", "roundToMultiple(3.5, 1.0)");
assertCalculation("-2.5", "roundToMultiple(-2.5, 1.25)");
assertCalculation("-3", "roundToMultiple(-3., 0.3)");
assertCalculation("20000000000", "scale(2, 10)");
assertCalculation("1/5", "scale(2, -1)");
assertCalculation("2.1e10", "scale(2.1, 10)");
assertCalculation("2.5e10+1.5e10i", "scale(2.5+1.5i, 10)");
assertCalculation("200000/3", "scale(2/3, 5)");
assertCalculation("1.60541", "sinIntegral(2.00000)");
assertCalculation("2.50157", "sinhIntegral(2.00000)");
assertCalculation("3", "sqrt(9)");
assertCalculation("2/3", "sqrt(4/9)");
assertCalculation("7.07+7.07i", "sqrt(100.i)");
assertCalculation("1.4142", "sqrt(2.0000)");
assertCalculation("2", "truncate(2.5)");
assertCalculation("2", "truncate(5/2)");
assertCalculation("1.79e2", "toDegrees(3.14)");
assertCalculation("1.57", "toRadians(90.0)");
assertCalculation("1.644", "zeta(2.000)");
assertCalculation("1.181e-1", "zeta(3.000,-1.500)");
assertCalculation("3.14", "acos(-1.00)");
assertCalculation("1.01", "acosh(1.55)");
assertCalculation("1.57", "asin(1.00)");
assertCalculation("0", "asinh(0)");
assertCalculation("7.85e-1", "atan(1.00)");
assertCalculation("0", "atanh(0)");
assertCalculation("1.57", "atan2(1.00, 0)");
assertCalculation("1", "cos(0)");
assertCalculation("1.54", "cosh(1.00)");
assertCalculation("8.414709848e-1", "sin(1.000000000)");
assertCalculation("1.18", "sinh(1.00)");
assertCalculation("1.56", "tan(1.00)");
assertCalculation("9.64e-1", "tanh(2.00)");
assertCalculation("2.7182818284590452353602874713526624977572470937", "e(47)");
assertCalculation("5.772e-1", "euler(4)");
assertCalculation("2.718", "exp(1.000)");
assertCalculation("1.79+3.14i", "log(-6.00)");
assertCalculation("1.58", "log(3.00, 2.00)");
assertCalculation("1.585", "log(3.000, 2)");
assertCalculation("1.585", "log(3, 2.0000)");
assertCalculation("1.2", "max(1.1, 1.2)");
assertCalculation("1/3", "max(1/3, 1/4)");
assertCalculation("2", "max(1, 2)");
assertCalculation("1.1", "min(1.1, 1.2)");
assertCalculation("1/4", "min(1/3, 1/4)");
assertCalculation("1", "min(1, 2)");
assertCalculation("2", "nextAfter(1., 2)");
assertCalculation("2", "nextUp(1.)");
assertCalculation("1", "nextDown(2.)");
assertCalculation("2/3", "nextDown(2/3)");
assertCalculation("1", "ulp(2.)");
assertCalculation("0", "ulp(2/3)");
assertCalculation("0", "ulp(1+i)");
assertCalculation("1e-1", "ulp(-10.00-2.0i)");
assertCalculation("1.57", "arg(1.00i)");
assertCalculation("2-i", "conj(2+i)");
assertCalculation("1", "imag(2+i)");
assertCalculation("2", "real(2+i)");
assertCalculation("2.47468", "agm(2.000000, 3.000000)");
assertCalculation("5.672e-1", "w(1.000)");
assertCalculation("-3.181e-1+1.3372i", "w(-1.0000)");
assertCalculation("-1.34285+5.24725i", "w(1.00000+i, 1)");
assertCalculation("3", "gcd(15, 12)");
assertCalculation("60", "lcm(15, 12)");
assertCalculation("3.14159", "pi(6)");
assertCalculationMatch("0|[1-9]e-1", "random(1)");
assertCalculationMatch("0|-?([1-5]|[1-9]e-1)", "randomGaussian(1)");
assertCalculation("5", "add(2, 3)");
assertCalculation("-1", "subtract(2, 3)");
assertCalculation("6", "multiply(2, 3)");
assertCalculation("2/3", "divide(2, 3)");
assertCalculation("-2", "negate(2)");
assertCalculation("2", "mod(5, 3)");
assertCalculation("8", "pow(2, 3)");
assertCalculationFailure("airyAi()");
assertCalculationFailure("airyAi(0,0)");
assertCalculationFailure("airyAiPrime()");
assertCalculationFailure("airyAiPrime(0,0)");
assertCalculationFailure("airyBi()");
assertCalculationFailure("airyBi(0,0)");
assertCalculationFailure("airyBiPrime()");
assertCalculationFailure("airyBiPrime(0,0)");
assertCalculationFailure("bernoulli(-1)");
assertCalculationFailure("bernoulli(i)");
assertCalculationFailure("bernoulli()");
assertCalculationFailure("bernoulli(1,1)");
assertCalculationFailure("besselI(1.0)");
assertCalculationFailure("besselI(1.0,1.0,1.0)");
assertCalculationFailure("besselJ(1.0)");
assertCalculationFailure("besselJ(1.0,1.0,1.0)");
assertCalculationFailure("besselK(1.0)");
assertCalculationFailure("besselK(1.0,1.0,1.0)");
assertCalculationFailure("besselY(1.0)");
assertCalculationFailure("besselY(1.0,1.0,1.0)");
assertCalculationFailure("beta(1.0)");
assertCalculationFailure("beta(1.0,1.0,1.0,1.0,1.0)");
assertCalculationFailure("binomial(-3,5i)");
assertCalculationFailure("binomial(-3i,5)");
assertCalculationFailure("binomial(-3i,5i)");
assertCalculationFailure("binomial(-3,3.5)");
assertCalculationFailure("binomial(4/3,3/2)");
assertCalculationFailure("binomial()");
assertCalculationFailure("binomial(2)");
assertCalculationFailure("binomial(2,2,2)");
assertCalculationFailure("catalan()");
assertCalculationFailure("catalan(5, 5)");
assertCalculationFailure("catalan(0)");
assertCalculationFailure("catalan(-1)");
assertCalculationFailure("catalan(0.5)");
assertCalculationFailure("catalan(i)");
assertCalculationFailure("cbrt(2)");
assertCalculationFailure("cbrt()");
assertCalculationFailure("cbrt(8, 2)");
assertCalculationFailure("ceil(i)");
assertCalculationFailure("ceil()");
assertCalculationFailure("ceil(2, 2)");
assertCalculationFailure("copySign(2i, -3)");
assertCalculationFailure("copySign(2)");
assertCalculationFailure("copySign(2, 2, 2)");
assertCalculationFailure("cosIntegral()");
assertCalculationFailure("cosIntegral(1.0,1.0)");
assertCalculationFailure("coshIntegral()");
assertCalculationFailure("coshIntegral(1.0,1.0)");
assertCalculationFailure("digamma(0)");
assertCalculationFailure("digamma()");
assertCalculationFailure("digamma(2,2)");
assertCalculationFailure("ellipticE()");
assertCalculationFailure("ellipticE(0.5,0.5)");
assertCalculationFailure("ellipticK()");
assertCalculationFailure("ellipticK(0.5,0.5)");
assertCalculationFailure("erf()");
assertCalculationFailure("erf(0.5,0.5)");
assertCalculationFailure("erfc()");
assertCalculationFailure("erfc(0.5,0.5)");
assertCalculationFailure("erfi()");
assertCalculationFailure("erfi(0.5,0.5)");
assertCalculationFailure("expIntegralE(0.5)");
assertCalculationFailure("expIntegralE(0.5,0.5,0.5)");
assertCalculationFailure("expIntegralEi()");
assertCalculationFailure("expIntegralEi(0.5,0.5)");
assertCalculationFailure("factorial(0.5)");
assertCalculationFailure("factorial(2i)");
assertCalculationFailure("factorial(2/3)");
assertCalculationFailure("factorial()");
assertCalculationFailure("factorial(2, 2)");
assertCalculationFailure("floor(i)");
assertCalculationFailure("floor()");
assertCalculationFailure("floor(2, 2)");
assertCalculationFailure("frac(i)");
assertCalculationFailure("frac()");
assertCalculationFailure("frac(2, 2)");
assertCalculationFailure("fresnelC()");
assertCalculationFailure("fresnelC(1.0,1.0)");
assertCalculationFailure("fresnelS()");
assertCalculationFailure("fresnelS(1.0,1.0)");
assertCalculationFailure("gamma(0)");
assertCalculationFailure("gamma()");
assertCalculationFailure("gamma(2, 2, 2, 2)");
assertCalculationFailure("glaisher()");
assertCalculationFailure("glaisher(5, 5)");
assertCalculationFailure("glaisher(0)");
assertCalculationFailure("glaisher(-1)");
assertCalculationFailure("glaisher(0.5)");
assertCalculationFailure("glaisher(i)");
assertCalculationFailure("hypergeometric0F1(0)");
assertCalculationFailure("hypergeometric0F1(0,0)");
assertCalculationFailure("hypergeometric0F1(0,0,0)");
assertCalculationFailure("hypergeometric0F1Regularized(0)");
assertCalculationFailure("hypergeometric0F1Regularized(0,0,0)");
assertCalculationFailure("hypergeometric1F1(0,0)");
assertCalculationFailure("hypergeometric1F1(1,0,0)");
assertCalculationFailure("hypergeometric1F1(0,0,0,0)");
assertCalculationFailure("hypergeometric1F1Regularized(0,0)");
assertCalculationFailure("hypergeometric1F1Regularized(0,0,0,0)");
assertCalculationFailure("hypergeometric2F1(0,0,0)");
assertCalculationFailure("hypergeometric2F1(1,2,0,0)");
assertCalculationFailure("hypergeometric2F1(0,0,0,0,0)");
assertCalculationFailure("hypergeometric2F1Regularized(0,0,0)");
assertCalculationFailure("hypergeometric2F1Regularized(0,0,0,0,0)");
assertCalculationFailure("hypergeometricU(0,0)");
assertCalculationFailure("hypergeometricU(0,0,0,0)");
assertCalculationFailure("fmod(2, i)");
assertCalculationFailure("fmod(2)");
assertCalculationFailure("fmod(2, 2, 2)");
assertCalculationFailure("hypot(2, i)");
assertCalculationFailure("hypot(2)");
assertCalculationFailure("hypot(2, 2, 2)");
assertCalculationFailure("inverseErf()");
assertCalculationFailure("inverseErf(-1.0)");
assertCalculationFailure("inverseErf(1.0)");
assertCalculationFailure("inverseErf(2.0)");
assertCalculationFailure("inverseErf(0.5i)");
assertCalculationFailure("inverseErf(0.5,0.5)");
assertCalculationFailure("inverseErfc()");
assertCalculationFailure("inverseErfc(0)");
assertCalculationFailure("inverseErfc(2.0)");
assertCalculationFailure("inverseErfc(3.0)");
assertCalculationFailure("inverseErfc(0.5i)");
assertCalculationFailure("inverseErfc(0.5,0.5)");
assertCalculationFailure("inverseRoot(2.0, i)");
assertCalculationFailure("inverseRoot(2.0, 1/2)");
assertCalculationFailure("inverseRoot(2, 2)");
assertCalculationFailure("inverseRoot(2)");
assertCalculationFailure("inverseRoot(2.0, 1, i)");
assertCalculationFailure("inverseRoot(2.0, i, 1)");
assertCalculationFailure("inverseRoot(2.0, i, i)");
assertCalculationFailure("inverseRoot(2.0, 2, 2, 2)");
assertCalculationFailure("khinchin()");
assertCalculationFailure("khinchin(5, 5)");
assertCalculationFailure("khinchin(0)");
assertCalculationFailure("khinchin(-1)");
assertCalculationFailure("khinchin(0.5)");
assertCalculationFailure("khinchin(i)");
assertCalculationFailure("logGamma(0)");
assertCalculationFailure("logGamma(-1)");
assertCalculationFailure("logGamma()");
assertCalculationFailure("logGamma(2,2)");
assertCalculationFailure("logIntegral()");
assertCalculationFailure("logIntegral(1.0,1.0)");
assertCalculationFailure("n(1.23456, i)");
assertCalculationFailure("n(1.23456, 0.5)");
assertCalculationFailure("n(1.23456)");
assertCalculationFailure("n(1.23456, 2, 2)");
assertCalculationFailure("pochhammer(1.0)");
assertCalculationFailure("pochhammer(1.0,1.0,1.0)");
assertCalculationFailure("pochhammer(1/3,1/4)");
assertCalculationFailure("polygamma(1)");
assertCalculationFailure("polygamma(-1,1.0)");
assertCalculationFailure("polygamma(1,1.0,1.0)");
assertCalculationFailure("root(2, 2)");
assertCalculationFailure("root(2)");
assertCalculationFailure("root(2, i)");
assertCalculationFailure("root(2, 1, i)");
assertCalculationFailure("root(2, i, 1)");
assertCalculationFailure("root(2, i, i)");
assertCalculationFailure("root(4.0, 2, 2, 2)");
assertCalculationFailure("round(2)");
assertCalculationFailure("round(2, 0)");
assertCalculationFailure("round(2, 0.5)");
assertCalculationFailure("round(2, i)");
assertCalculationFailure("round(i, 2)");
assertCalculationFailure("round(2, 2, 2)");
assertCalculationFailure("roundToPrecision(2)");
assertCalculationFailure("roundToPrecision(2, 0)");
assertCalculationFailure("roundToPrecision(2, 0.5)");
assertCalculationFailure("roundToPrecision(2, i)");
assertCalculationFailure("roundToPrecision(i, 2)");
assertCalculationFailure("roundToPrecision(2, 2, 2)");
assertCalculationFailure("roundToInteger()");
assertCalculationFailure("roundToInteger(i)");
assertCalculationFailure("roundToInteger(2, 0)");
assertCalculationFailure("roundToPlaces(2)");
assertCalculationFailure("roundToPlaces(2, 0.5)");
assertCalculationFailure("roundToPlaces(2, i)");
assertCalculationFailure("roundToPlaces(i, 2)");
assertCalculationFailure("roundToPlaces(2, 2, 2)");
assertCalculationFailure("roundToMultiple(2)");
assertCalculationFailure("roundToMultiple(2, 0)");
assertCalculationFailure("roundToMultiple(2, i)");
assertCalculationFailure("roundToMultiple(i, 2)");
assertCalculationFailure("roundToMultiple(2, 2, 2)");
assertCalculationFailure("scale(1.23456, i)");
assertCalculationFailure("scale(1.23456, 0.5)");
assertCalculationFailure("scale(1.23456)");
assertCalculationFailure("scale(1.23456, 2, 2)");
assertCalculationFailure("sinIntegral()");
assertCalculationFailure("sinIntegral(1.0,1.0)");
assertCalculationFailure("sinhIntegral()");
assertCalculationFailure("sinhIntegral(1.0,1.0)");
assertCalculationFailure("sqrt(2)");
assertCalculationFailure("sqrt()");
assertCalculationFailure("sqrt(4, 2)");
assertCalculationFailure("truncate(i)");
assertCalculationFailure("truncate()");
assertCalculationFailure("truncate(2, 2)");
assertCalculationFailure("toDegrees(2)");
assertCalculationFailure("toDegrees(i)");
assertCalculationFailure("toDegrees()");
assertCalculationFailure("toDegrees(2, 2)");
assertCalculationFailure("toRadians(2)");
assertCalculationFailure("toRadians(i)");
assertCalculationFailure("toRadians()");
assertCalculationFailure("toRadians(2, 2)");
assertCalculationFailure("zeta(1)");
assertCalculationFailure("zeta(2,0)");
assertCalculationFailure("zeta(2,-1)");
assertCalculationFailure("zeta()");
assertCalculationFailure("zeta(2,3,4)");
assertCalculationFailure("acos()");
assertCalculationFailure("acos(1, 1)");
assertCalculationFailure("acosh()");
assertCalculationFailure("acosh(1, 1)");
assertCalculationFailure("asin()");
assertCalculationFailure("asin(1, 1)");
assertCalculationFailure("asinh()");
assertCalculationFailure("asinh(1, 1)");
assertCalculationFailure("atan()");
assertCalculationFailure("atan(1, 1)");
assertCalculationFailure("atanh()");
assertCalculationFailure("atanh(1, 1)");
assertCalculationFailure("atan2(1)");
assertCalculationFailure("atan2(i, i)");
assertCalculationFailure("atan2(1, 1, 1)");
assertCalculationFailure("cos()");
assertCalculationFailure("cos(1, 1)");
assertCalculationFailure("cosh()");
assertCalculationFailure("cosh(1, 1)");
assertCalculationFailure("sin()");
assertCalculationFailure("sin(1, 1)");
assertCalculationFailure("sinh()");
assertCalculationFailure("sinh(1, 1)");
assertCalculationFailure("tan()");
assertCalculationFailure("tan(1, 1)");
assertCalculationFailure("tanh()");
assertCalculationFailure("tanh(1, 1)");
assertCalculationFailure("e()");
assertCalculationFailure("e(0)");
assertCalculationFailure("e(-1)");
assertCalculationFailure("e(0.5)");
assertCalculationFailure("e(i)");
assertCalculationFailure("e(1, 1)");
assertCalculationFailure("euler()");
assertCalculationFailure("euler(0)");
assertCalculationFailure("euler(-1)");
assertCalculationFailure("euler(0.5)");
assertCalculationFailure("euler(i)");
assertCalculationFailure("euler(1, 1)");
assertCalculationFailure("exp()");
assertCalculationFailure("exp(1, 1)");
assertCalculationFailure("log()");
assertCalculationFailure("log(1, 1, 1)");
assertCalculationFailure("max()");
assertCalculationFailure("max(1)");
assertCalculationFailure("max(1, 1, 1)");
assertCalculationFailure("max(i, i)");
assertCalculationFailure("min()");
assertCalculationFailure("min(1)");
assertCalculationFailure("min(1, 1, 1)");
assertCalculationFailure("min(i, i)");
assertCalculationFailure("nextAfter(1)");
assertCalculationFailure("nextAfter(1, 2, 3)");
assertCalculationFailure("nextAfter(1, i)");
assertCalculationFailure("nextUp()");
assertCalculationFailure("nextUp(1, 1)");
assertCalculationFailure("nextUp(i)");
assertCalculationFailure("nextDown()");
assertCalculationFailure("nextDown(2, 2)");
assertCalculationFailure("nextDown(i)");
assertCalculationFailure("ulp()");
assertCalculationFailure("ulp(2, 2)");
assertCalculationFailure("arg()");
assertCalculationFailure("arg(1, 1)");
assertCalculationFailure("conj()");
assertCalculationFailure("conj(1, 1)");
assertCalculationFailure("imag()");
assertCalculationFailure("imag(1, 1)");
assertCalculationFailure("real()");
assertCalculationFailure("real(1, 1)");
assertCalculationFailure("agm(1)");
assertCalculationFailure("agm(1, 1, 1)");
assertCalculationFailure("w(1, 1, 1)");
assertCalculationFailure("w(1, i)");
assertCalculationFailure("w(1, 1.5)");
assertCalculationFailure("w(1, 2/3)");
assertCalculationFailure("gcd(2, i)");
assertCalculationFailure("gcd(2, 2/3)");
assertCalculationFailure("gcd(1)");
assertCalculationFailure("gcd(1, 1, 1)");
assertCalculationFailure("lcm(2, i)");
assertCalculationFailure("lcm(2, 2/3)");
assertCalculationFailure("lcm(1)");
assertCalculationFailure("lcm(1, 1, 1)");
assertCalculationFailure("pi(i)");
assertCalculationFailure("pi(0.5)");
assertCalculationFailure("pi()");
assertCalculationFailure("pi(1, 1)");
assertCalculationFailure("random(i)");
assertCalculationFailure("random(0.5)");
assertCalculationFailure("random()");
assertCalculationFailure("random(1, 1)");
assertCalculationFailure("randomGaussian(i)");
assertCalculationFailure("randomGaussian(0.5)");
assertCalculationFailure("randomGaussian()");
assertCalculationFailure("randomGaussian(1, 1)");
assertCalculationFailure("add(2)");
assertCalculationFailure("add(2, 2, 2)");
assertCalculationFailure("subtract(2)");
assertCalculationFailure("subtract(2, 2, 2)");
assertCalculationFailure("multiply(2)");
assertCalculationFailure("multiply(2, 2, 2)");
assertCalculationFailure("divide(2)");
assertCalculationFailure("divide(2, 2, 2)");
assertCalculationFailure("negate()");
assertCalculationFailure("negate(2, 2)");
assertCalculationFailure("mod(2, i)");
assertCalculationFailure("mod(2)");
assertCalculationFailure("mod(2, 2, 2)");
assertCalculationFailure("pow(2)");
assertCalculationFailure("pow(2, 2, 2)");
assertCalculationFailure("bogusfunc(5)");
}
public static void testArguments()
throws ParseException
{
assertCalculation("1.4142", "sqrt(2.)", "-i", "5");
assertCalculation("0.5", "1/2", "-p", "-i", "1");
assertCalculation("0.5", "1.0/2.0", "-p");
assertCalculation("0.915966", "catalan()", "-p", "-i", "6");
assertCalculation("2.71828", "e()", "-i", "6");
assertCalculation("0.577216", "euler()", "-p", "-i", "6");
assertCalculation("1.28243", "glaisher()", "-i", "6");
assertCalculation("2.68545", "khinchin()", "-p", "-i", "6");
assertCalculation("3.14159", "pi()", "-i", "6");
assertCalculationMatch("0|[1-9]e-1", "random()", "-i", "1");
assertCalculationMatch("0|-?([1-5]|[1-9]e-1)", "randomGaussian()", "-i", "1");
assertCalculation("1.5708", "acos(0)", "-p", "-i", "6");
assertCalculation("1.5708i", "acosh(0)", "-p", "-i", "6");
assertCalculation("0.355028", "airyAi(0)", "-p", "-i", "6");
assertCalculation("-0.258819", "airyAiPrime(0)", "-p", "-i", "6");
assertCalculation("0.614927", "airyBi(0)", "-p", "-i", "6");
assertCalculation("0.448288", "airyBiPrime(0)", "-p", "-i", "6");
assertCalculation("1.5708", "ellipticE(0)", "-p", "-i", "6");
assertCalculation("1.5708", "ellipticK(0)", "-p", "-i", "6");
}
private static final String NEWLINE = System.lineSeparator();
}
apfloat-1.13.0/apfloat-jscience/ 0000775 0000000 0000000 00000000000 14557414736 0016451 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/pom.xml 0000664 0000000 0000000 00000005041 14557414736 0017766 0 ustar 00root root 0000000 0000000
4.0.0org.apfloatapfloat-parent1.13.0apfloat-jscienceapfloat-jscienceJScience wrapper for apfloathttp://www.apfloat.orgorg.apfloatapfloatorg.jsciencejsciencejunitjunittestorg.apfloatapfloattest-jartestbiz.aQute.bndbnd-maven-plugingenerate-osgi-manifestbnd-processorg.apache.maven.pluginsmaven-jar-plugin${project.build.outputDirectory}/META-INF/MANIFEST.MForg.apache.maven.pluginsmaven-shade-pluginshadeorg.apfloat:apfloat-jscience${project.build.directory}/apfloat-jscience.jar
apfloat-1.13.0/apfloat-jscience/src/ 0000775 0000000 0000000 00000000000 14557414736 0017240 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/ 0000775 0000000 0000000 00000000000 14557414736 0020164 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/java/ 0000775 0000000 0000000 00000000000 14557414736 0021105 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021674 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0023322 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/ 0000775 0000000 0000000 00000000000 14557414736 0025105 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/AbstractField.java 0000664 0000000 0000000 00000012763 14557414736 0030470 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import javolution.text.Text;
import org.apfloat.Apcomplex;
import org.apfloat.ApcomplexMath;
import org.jscience.mathematics.number.Number;
import org.jscience.mathematics.structure.Field;
/**
* This class represents an arbitrary precision field object.
*
* @param The type of the field.
* @param The type of the underlying value.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public abstract class AbstractField, V extends Apcomplex>
extends Number
implements Field
{
/**
* Constructs a new field object with the specified value.
*
* @param value The value.
*/
protected AbstractField(V value)
{
if (value == null)
{
throw new NullPointerException("Value can't be null");
}
this.value = value;
}
/**
* Returns the sum of this object with the one specified.
*
* @param that The addend.
*
* @return this + that
*/
@Override
public abstract T plus(T that);
/**
* Returns the additive inverse of this object.
*
* @return -this
*/
@Override
public abstract T opposite();
/**
* Returns the product of this object with the one specified.
*
* @param that The multiplicand.
*
* @return this * that
*/
@Override
public abstract T times(T that);
/**
* Returns the multiplicative inverse of this object.
*
* @return 1 / this
*
* @exception ArithmeticException If the divisor is zero.
*/
@Override
public abstract T inverse()
throws ArithmeticException;
/**
* Returns a copy of this object.
*
* @return A copy of this object.
*/
@Override
public abstract T copy();
/**
* Compares the absolute value of this number
* with the absolute value of the number specified.
*
* @param that The number to be compared with.
*
* @return |this| > |that|
*/
@Override
public boolean isLargerThan(T that)
{
return ApcomplexMath.abs(value()).compareTo(ApcomplexMath.abs(that.value())) > 0;
}
/**
* Returns the value of this number as the underlying type.
*
* @return The value.
*/
public V value()
{
return this.value;
}
/**
* Returns the value of this number as a double.
*
* @return The value.
*/
@Override
public double doubleValue()
{
return value().doubleValue();
}
/**
* Returns the value of this number as a long.
*
* @return The value.
*/
@Override
public long longValue()
{
return value().longValue();
}
/**
* Returns the text representation of this number.
*
* @return The string representation of this number as a Text.
*/
@Override
public Text toText()
{
return Text.valueOf(value().toString());
}
/**
* Compares this number to another number.
*
* @param that The number to be compared with.
*
* @return -1, 0, or 1 depending on the ordering.
*/
@Override
public int compareTo(T that)
{
int result = value().real().compareTo(that.value().real());
if (result == 0)
{
result = value().imag().compareTo(that.value().imag());
}
return result;
}
/**
* Returns the hash code for this number.
*
* @return The hash code value.
*/
@Override
public int hashCode()
{
return value().hashCode();
}
/**
* Compares for equality.
*
* @return If the objects are equal.
*/
@Override
public boolean equals(Object obj)
{
if (obj instanceof AbstractField)
{
AbstractField, ?> that = (AbstractField, ?>) obj;
return value().equals(that.value());
}
return false;
}
private static final long serialVersionUID = -7725271295007354895L;
private V value;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/ApcomplexField.java 0000664 0000000 0000000 00000005417 14557414736 0030653 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import org.apfloat.Apcomplex;
import org.apfloat.ApcomplexMath;
/**
* This class represents an arbitrary precision complex number.
*
* The precision of each calculation is determined separately, which means
* that loss of precision can easily accumulate in complicated calculations
* (e.g. matrix inversion). If this should be avoided, and a fixed precision is
* required, then it may be better to use {@link FixedPrecisionApcomplexField}
* instead.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class ApcomplexField
extends AbstractField
{
/**
* Constructs a new complex field object with the specified value.
*
* @param value The value.
*/
public ApcomplexField(Apcomplex value)
{
super(value);
}
@Override
public ApcomplexField plus(ApcomplexField that)
{
return new ApcomplexField(value().add(that.value()));
}
@Override
public ApcomplexField opposite()
{
return new ApcomplexField(value().negate());
}
@Override
public ApcomplexField times(ApcomplexField that)
{
return new ApcomplexField(value().multiply(that.value()));
}
@Override
public ApcomplexField inverse()
throws ArithmeticException
{
return new ApcomplexField(ApcomplexMath.inverseRoot(value(), 1));
}
@Override
public ApcomplexField copy()
{
return new ApcomplexField(value());
}
private static final long serialVersionUID = -6242843580910131563L;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/ApfloatField.java 0000664 0000000 0000000 00000005362 14557414736 0030310 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import org.apfloat.Apfloat;
import org.apfloat.ApfloatMath;
/**
* This class represents an arbitrary precision floating-point number.
*
* The precision of each calculation is determined separately, which means
* that loss of precision can easily accumulate in complicated calculations
* (e.g. matrix inversion). If this should be avoided, and a fixed precision is
* required, then it may be better to use {@link FixedPrecisionApfloatField}
* instead.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class ApfloatField
extends AbstractField
{
/**
* Constructs a new floating-point field object with the specified value.
*
* @param value The value.
*/
public ApfloatField(Apfloat value)
{
super(value);
}
@Override
public ApfloatField plus(ApfloatField that)
{
return new ApfloatField(value().add(that.value()));
}
@Override
public ApfloatField opposite()
{
return new ApfloatField(value().negate());
}
@Override
public ApfloatField times(ApfloatField that)
{
return new ApfloatField(value().multiply(that.value()));
}
@Override
public ApfloatField inverse()
throws ArithmeticException
{
return new ApfloatField(ApfloatMath.inverseRoot(value(), 1));
}
@Override
public ApfloatField copy()
{
return new ApfloatField(value());
}
private static final long serialVersionUID = -901594332306254700L;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/AprationalField.java 0000664 0000000 0000000 00000005100 14557414736 0031002 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import org.apfloat.Aprational;
/**
* This class represents an arbitrary precision rational number.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class AprationalField
extends AbstractField
{
/**
* Constructs a new rational field object with the specified value.
*
* @param value The value.
*/
public AprationalField(Aprational value)
{
super(value);
}
@Override
public AprationalField plus(AprationalField that)
{
return new AprationalField(value().add(that.value()));
}
@Override
public AprationalField opposite()
{
return new AprationalField(value().negate());
}
@Override
public AprationalField times(AprationalField that)
{
return new AprationalField(value().multiply(that.value()));
}
@Override
public AprationalField inverse()
throws ArithmeticException
{
if (value().signum() == 0)
{
throw new ArithmeticException("Inverse of zero");
}
return new AprationalField(new Aprational(value().denominator(), value().numerator()));
}
@Override
public AprationalField copy()
{
return new AprationalField(value());
}
private static final long serialVersionUID = -4642791345140583865L;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/FixedPrecisionApcomplexField.java0000664 0000000 0000000 00000006730 14557414736 0033506 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import org.apfloat.Apcomplex;
import org.apfloat.FixedPrecisionApcomplexHelper;
/**
* This class represents a fixed-precision complex number. The precision
* is reset after each computation using the provided FixedPrecisionApcomplexHelper.
* This can help avoid accumulating round-off errors and loss of precision
* in complicated computations such as matrix inversion.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class FixedPrecisionApcomplexField
extends AbstractField
{
/**
* Constructs a new complex field object with the specified value and precision helper.
*
* @param value The value.
* @param helper The precision helper.
*/
public FixedPrecisionApcomplexField(Apcomplex value, FixedPrecisionApcomplexHelper helper)
{
super(value);
if (helper == null)
{
throw new NullPointerException("Helper can't be null");
}
this.helper = helper;
}
@Override
public FixedPrecisionApcomplexField plus(FixedPrecisionApcomplexField that)
{
return new FixedPrecisionApcomplexField(helper().add(value(), that.value()), helper());
}
@Override
public FixedPrecisionApcomplexField opposite()
{
return new FixedPrecisionApcomplexField(helper().negate(value()), helper());
}
@Override
public FixedPrecisionApcomplexField times(FixedPrecisionApcomplexField that)
{
return new FixedPrecisionApcomplexField(helper().multiply(value(), that.value()), helper());
}
@Override
public FixedPrecisionApcomplexField inverse()
throws ArithmeticException
{
return new FixedPrecisionApcomplexField(helper().inverseRoot(value(), 1), helper());
}
@Override
public FixedPrecisionApcomplexField copy()
{
return new FixedPrecisionApcomplexField(value(), helper());
}
/**
* Return the precision helper.
*
* @return The precision helper.
*/
public FixedPrecisionApcomplexHelper helper()
{
return this.helper;
}
private static final long serialVersionUID = -2069599698604093434L;
private FixedPrecisionApcomplexHelper helper;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/FixedPrecisionApfloatField.java 0000664 0000000 0000000 00000006643 14557414736 0033147 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import org.apfloat.Apfloat;
import org.apfloat.FixedPrecisionApfloatHelper;
/**
* This class represents a fixed-precision floating-point number. The precision
* is reset after each computation using the provided FixedPrecisionApfloatHelper.
* This can help avoid accumulating round-off errors and loss of precision
* in complicated computations such as matrix inversion.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class FixedPrecisionApfloatField
extends AbstractField
{
/**
* Constructs a new floating-point field object with the specified value.
*
* @param value The value.
* @param helper The precision helper.
*/
public FixedPrecisionApfloatField(Apfloat value, FixedPrecisionApfloatHelper helper)
{
super(value);
if (helper == null)
{
throw new NullPointerException("Helper can't be null");
}
this.helper = helper;
}
@Override
public FixedPrecisionApfloatField plus(FixedPrecisionApfloatField that)
{
return new FixedPrecisionApfloatField(helper().add(value(), that.value()), helper());
}
@Override
public FixedPrecisionApfloatField opposite()
{
return new FixedPrecisionApfloatField(helper().negate(value()), helper());
}
@Override
public FixedPrecisionApfloatField times(FixedPrecisionApfloatField that)
{
return new FixedPrecisionApfloatField(helper().multiply(value(), that.value()), helper());
}
@Override
public FixedPrecisionApfloatField inverse()
throws ArithmeticException
{
return new FixedPrecisionApfloatField(helper().inverseRoot(value(), 1), helper());
}
@Override
public FixedPrecisionApfloatField copy()
{
return new FixedPrecisionApfloatField(value(), helper());
}
/**
* Return the precision helper.
*
* @return The precision helper.
*/
public FixedPrecisionApfloatHelper helper()
{
return this.helper;
}
private static final long serialVersionUID = -8969242537753892317L;
private FixedPrecisionApfloatHelper helper;
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/ModuloApintField.java 0000664 0000000 0000000 00000010705 14557414736 0031152 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import javolution.context.LocalContext;
import org.apfloat.Apint;
import org.apfloat.ApintMath;
/**
* This class represents an arbitrary precision modulo integer.
* The modulus must be set with {@link #setModulus(Apint)}; otherwise
* the modulo reduction is not done.
*
* @since 1.8.0
* @version 1.8.0
* @author Mikko Tommila
*/
public class ModuloApintField
extends AbstractField
{
/**
* Constructs a new integer field object with the specified value.
*
* @param value The value.
*/
public ModuloApintField(Apint value)
{
super(reduce(value));
}
/**
* Returns the modulus or null if modulo reduction is not done.
* The modulus can be set in a thread-specific way using
* {@link javolution.context.LocalContext}.
*
* @return The local modulus or null if modulo reduction is not done.
*
* @see #setModulus
*/
public static Apint getModulus()
{
return MODULUS.get();
}
/**
* Sets the modulus.
* The modulus can be set in a thread-specific way using
* {@link javolution.context.LocalContext}.
*
* @param modulus The modulus or null if modulo reduction is not done.
*
* @throws IllegalArgumentException If modulus is not positive.
*/
public static void setModulus(Apint modulus)
{
if (modulus != null && modulus.signum() <= 0)
{
throw new IllegalArgumentException("Modulus has to be greater than zero");
}
MODULUS.set(modulus);
}
/**
* Reduce the value with the current modulus.
*
* @param value The value.
*
* @return The value mod the current modulus.
*/
public static Apint reduce(Apint value)
{
Apint modulus = MODULUS.get();
if (modulus != null)
{
value = value.mod(modulus);
if (value.signum() < 0) // The modulus is always positive, so reduce values to positive
{
value = value.add(modulus);
}
}
return value;
}
@Override
public ModuloApintField plus(ModuloApintField that)
{
return new ModuloApintField(value().add(that.value()));
}
@Override
public ModuloApintField opposite()
{
return new ModuloApintField(value().negate());
}
@Override
public ModuloApintField times(ModuloApintField that)
{
return new ModuloApintField(value().multiply(that.value()));
}
@Override
public ModuloApintField inverse()
throws ArithmeticException
{
Apint modulus = MODULUS.get();
if (modulus == null)
{
throw new ArithmeticException("Modulus is not set");
}
return new ModuloApintField(ApintMath.modPow(value(), new Apint(-1), modulus));
}
@Override
public ModuloApintField copy()
{
return new ModuloApintField(value());
}
private static final long serialVersionUID = 5308452222350777004L;
private static final LocalContext.Reference MODULUS = new LocalContext.Reference();
}
apfloat-1.13.0/apfloat-jscience/src/main/java/org/apfloat/jscience/package-info.java 0000664 0000000 0000000 00000002640 14557414736 0030276 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
JScience wrapper for apfloat.
This package contains classes that allow using the apfloat library
classes with the JScience library. For example, it's possible
to perform arbitrary-precision matrix or polynomial operations.
*/
package org.apfloat.jscience;
apfloat-1.13.0/apfloat-jscience/src/test/ 0000775 0000000 0000000 00000000000 14557414736 0020217 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/ 0000775 0000000 0000000 00000000000 14557414736 0021140 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021727 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0023355 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience/ 0000775 0000000 0000000 00000000000 14557414736 0025140 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience/ApcomplexFieldTest.java 0000664 0000000 0000000 00000012540 14557414736 0031541 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class ApcomplexFieldTest
extends ApfloatTestCase
{
public ApcomplexFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new ApcomplexFieldTest("testBasic"));
suite.addTest(new ApcomplexFieldTest("testMatrixInverse"));
suite.addTest(new ApcomplexFieldTest("testRationalFunction"));
return suite;
}
public static void testBasic()
{
ApcomplexField a = valueOf("(0,100)");
ApcomplexField b = valueOf("(0,200)");
ApcomplexField c = valueOf("(0,200)");
ApcomplexField zero = valueOf("0");
assertEquals("100 + 200", valueOf("(0,300)"), a.plus(b));
assertEquals("-100", valueOf("(0,-100)"), a.opposite());
assertEquals("100 - 200", valueOf("(0,-100)"), a.minus(b));
assertEquals("100 * 200", valueOf("-20000"), a.times(b));
assertEquals("1 / 100", valueOf("(0,-0.01)"), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 0.0, a.doubleValue());
assertEquals("longValue", 0L, a.longValue());
assertEquals("String", "(0, 1e2)", a.toString());
assertEquals("Text", new Text("(0, 1e2)"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new ApcomplexField(null);
fail("null accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testMatrixInverse()
{
ApcomplexField[][] elements = { { valueOf("1"), valueOf("(0,2)"), valueOf("3") },
{ valueOf("4"), valueOf("5"), valueOf("(0,6)") },
{ valueOf("(0,7)"), valueOf("8"), valueOf("9") } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
Apfloat sum = Apfloat.ZERO;
for (int i = 0; i < vectorization.getDimension(); i++)
{
sum = sum.add(ApcomplexMath.abs(vectorization.get(i).value()));
}
assertEquals("Double inverse error", Apfloat.ZERO, sum, new Apfloat(5e-27));
}
public static void testRationalFunction()
{
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf("(1,2)"), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf("(3,4)"), x));
Polynomial divisor = Polynomial.valueOf(valueOf("(5,6)"), x).plus(valueOf("(7,8)"));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", new Apcomplex("(0.570962479608482871125611745514,0.983686786296900489396411092985)"), function.evaluate(valueOf("(2,3)")).value(), new Apfloat("5e-30"));
assertEquals("Function plus inverse, value", new Apcomplex("(1.01232439638023570845221956392,0.22328325540156631537371248012)"), function.plus(function.inverse()).evaluate(valueOf("(2,3)")).value(), new Apfloat("5e-29"));
}
private static ApcomplexField valueOf(String value)
{
return new ApcomplexField(new Apcomplex(value).precision(30));
}
}
apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience/ApfloatFieldTest.java 0000664 0000000 0000000 00000012214 14557414736 0031175 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class ApfloatFieldTest
extends ApfloatTestCase
{
public ApfloatFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new ApfloatFieldTest("testMatrixInverse"));
suite.addTest(new ApfloatFieldTest("testRationalFunction"));
suite.addTest(new ApfloatFieldTest("testBasic"));
return suite;
}
public static void testBasic()
{
ApfloatField a = valueOf("100");
ApfloatField b = valueOf("200");
ApfloatField c = valueOf("200");
ApfloatField zero = valueOf("0");
assertEquals("100 + 200", valueOf("300"), a.plus(b));
assertEquals("-100", valueOf("-100"), a.opposite());
assertEquals("100 - 200", valueOf("-100"), a.minus(b));
assertEquals("100 * 200", valueOf("20000"), a.times(b));
assertEquals("1 / 100", valueOf("0.01"), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 100.0, a.doubleValue(), 0.00000000000005);
assertEquals("longValue", 100L, a.longValue());
assertEquals("String", "1e2", a.toString());
assertEquals("Text", new Text("1e2"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new ApfloatField(null);
fail("null accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testMatrixInverse()
{
ApfloatField[][] elements = { { valueOf("1"), valueOf("2"), valueOf("3") },
{ valueOf("4"), valueOf("5"), valueOf("6") },
{ valueOf("7"), valueOf("8"), valueOf("10") } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
Apfloat sum = Apfloat.ZERO;
for (int i = 0; i < vectorization.getDimension(); i++)
{
sum = sum.add(ApfloatMath.abs(vectorization.get(i).value()));
}
assertEquals("Double inverse error", Apfloat.ZERO, sum, new Apfloat(5e-25));
}
public static void testRationalFunction()
{
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf("2"), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf("3"), x));
Polynomial divisor = Polynomial.valueOf(valueOf("5"), x).plus(valueOf("6"));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", new Apfloat("0.875"), function.evaluate(valueOf("2")).value(), new Apfloat("5e-30"));
assertEquals("Function plus inverse, value", new Apfloat("2.017857142857142857142857142857"), function.plus(function.inverse()).evaluate(valueOf("2")).value(), new Apfloat("5e-29"));
}
private static ApfloatField valueOf(String value)
{
return new ApfloatField(new Apfloat(value, 30));
}
}
apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience/AprationalFieldTest.java 0000664 0000000 0000000 00000012564 14557414736 0031711 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class AprationalFieldTest
extends ApfloatTestCase
{
public AprationalFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new AprationalFieldTest("testMatrixInverse"));
suite.addTest(new AprationalFieldTest("testRationalFunction"));
suite.addTest(new AprationalFieldTest("testBasic"));
return suite;
}
public static void testBasic()
{
AprationalField a = valueOf("100");
AprationalField b = valueOf("200");
AprationalField c = valueOf("200");
AprationalField zero = valueOf("0");
assertEquals("100 + 200", valueOf("300"), a.plus(b));
assertEquals("-100", valueOf("-100"), a.opposite());
assertEquals("100 - 200", valueOf("-100"), a.minus(b));
assertEquals("100 * 200", valueOf("20000"), a.times(b));
assertEquals("1 / 100", valueOf("1/100"), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 100.0, a.doubleValue(), 0.00000000000005);
assertEquals("longValue", 100L, a.longValue());
assertEquals("String", "100", a.toString());
assertEquals("Text", new Text("100"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new AprationalField(null);
fail("null accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testMatrixInverse()
{
AprationalField[][] elements = { { valueOf("1"), valueOf("1/2"), valueOf("1/3"), valueOf("1/4"), valueOf("1/5") },
{ valueOf("1/2"), valueOf("1/3"), valueOf("1/4"), valueOf("1/5"), valueOf("1/6") },
{ valueOf("1/3"), valueOf("1/4"), valueOf("1/5"), valueOf("1/6"), valueOf("1/7") },
{ valueOf("1/4"), valueOf("1/5"), valueOf("1/6"), valueOf("1/7"), valueOf("1/8") },
{ valueOf("1/5"), valueOf("1/6"), valueOf("1/7"), valueOf("1/8"), valueOf("1/9") } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
for (int i = 0; i < vectorization.getDimension(); i++)
{
assertEquals("Element " + i, 0, vectorization.get(i).value().signum());
}
}
public static void testRationalFunction()
{
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf("1/2"), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf("2/3"), x));
Polynomial divisor = Polynomial.valueOf(valueOf("3/4"), x).plus(valueOf("5/6"));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", valueOf("10/7"), function.evaluate(valueOf("2")));
assertEquals("Function plus inverse, value", valueOf("149/70"), function.plus(function.inverse()).evaluate(valueOf("2")));
}
private static AprationalField valueOf(String value)
{
return new AprationalField(new Aprational(value));
}
}
FixedPrecisionApcomplexFieldTest.java 0000664 0000000 0000000 00000014005 14557414736 0034314 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class FixedPrecisionApcomplexFieldTest
extends ApfloatTestCase
{
public FixedPrecisionApcomplexFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new FixedPrecisionApcomplexFieldTest("testBasic"));
suite.addTest(new FixedPrecisionApcomplexFieldTest("testMatrixInverse"));
suite.addTest(new FixedPrecisionApcomplexFieldTest("testRationalFunction"));
return suite;
}
public static void testBasic()
{
FixedPrecisionApcomplexField a = valueOf("(0,100)");
FixedPrecisionApcomplexField b = valueOf("(0,200)");
FixedPrecisionApcomplexField c = valueOf("(0,200)");
FixedPrecisionApcomplexField zero = valueOf("0");
assertEquals("100 + 200", valueOf("(0,300)"), a.plus(b));
assertEquals("-100", valueOf("(0,-100)"), a.opposite());
assertEquals("100 - 200", valueOf("(0,-100)"), a.minus(b));
assertEquals("100 * 200", valueOf("-20000"), a.times(b));
assertEquals("1 / 100", valueOf("(0,-0.01)"), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 0.0, a.doubleValue());
assertEquals("longValue", 0L, a.longValue());
assertEquals("String", "(0, 1e2)", a.toString());
assertEquals("Text", new Text("(0, 1e2)"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new FixedPrecisionApcomplexField(null, HELPER);
fail("null value accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
try
{
new FixedPrecisionApcomplexField(Apcomplex.ZERO, null);
fail("null helper accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testMatrixInverse()
{
FixedPrecisionApcomplexField[][] elements = { { valueOf("1"), valueOf("(0,2)"), valueOf("3") },
{ valueOf("4"), valueOf("5"), valueOf("(0,6)") },
{ valueOf("(0,7)"), valueOf("8"), valueOf("9") } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
Apfloat sum = Apfloat.ZERO;
for (int i = 0; i < vectorization.getDimension(); i++)
{
sum = sum.add(ApcomplexMath.abs(vectorization.get(i).value()));
}
assertEquals("Double inverse error", Apfloat.ZERO, sum, new Apfloat(5e-28));
}
public static void testRationalFunction()
{
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf("(1,2)"), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf("(3,4)"), x));
Polynomial divisor = Polynomial.valueOf(valueOf("(5,6)"), x).plus(valueOf("(7,8)"));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", new Apcomplex("(0.570962479608482871125611745514,0.983686786296900489396411092985)"), function.evaluate(valueOf("(2,3)")).value(), new Apfloat("5e-30"));
assertEquals("Function plus inverse, value", new Apcomplex("(1.01232439638023570845221956392,0.22328325540156631537371248012)"), function.plus(function.inverse()).evaluate(valueOf("(2,3)")).value(), new Apfloat("5e-29"));
}
private static FixedPrecisionApcomplexField valueOf(String value)
{
return new FixedPrecisionApcomplexField(new Apcomplex(value), HELPER);
}
private static final FixedPrecisionApcomplexHelper HELPER = new FixedPrecisionApcomplexHelper(30);
}
FixedPrecisionApfloatFieldTest.java 0000664 0000000 0000000 00000013465 14557414736 0033763 0 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class FixedPrecisionApfloatFieldTest
extends ApfloatTestCase
{
public FixedPrecisionApfloatFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new FixedPrecisionApfloatFieldTest("testBasic"));
suite.addTest(new FixedPrecisionApfloatFieldTest("testMatrixInverse"));
suite.addTest(new FixedPrecisionApfloatFieldTest("testRationalFunction"));
return suite;
}
public static void testBasic()
{
FixedPrecisionApfloatField a = valueOf("100");
FixedPrecisionApfloatField b = valueOf("200");
FixedPrecisionApfloatField c = valueOf("200");
FixedPrecisionApfloatField zero = valueOf("0");
assertEquals("100 + 200", valueOf("300"), a.plus(b));
assertEquals("-100", valueOf("-100"), a.opposite());
assertEquals("100 - 200", valueOf("-100"), a.minus(b));
assertEquals("100 * 200", valueOf("20000"), a.times(b));
assertEquals("1 / 100", valueOf("0.01"), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 100.0, a.doubleValue(), 0.00000000000005);
assertEquals("longValue", 100L, a.longValue());
assertEquals("String", "1e2", a.toString());
assertEquals("Text", new Text("1e2"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new FixedPrecisionApfloatField(null, HELPER);
fail("null value accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
try
{
new FixedPrecisionApfloatField(Apcomplex.ZERO, null);
fail("null helper accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testMatrixInverse()
{
FixedPrecisionApfloatField[][] elements = { { valueOf("1"), valueOf("2"), valueOf("3") },
{ valueOf("4"), valueOf("5"), valueOf("6") },
{ valueOf("7"), valueOf("8"), valueOf("10") } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
Apfloat sum = Apfloat.ZERO;
for (int i = 0; i < vectorization.getDimension(); i++)
{
sum = sum.add(ApfloatMath.abs(vectorization.get(i).value()));
}
assertEquals("Double inverse error", Apfloat.ZERO, sum, new Apfloat(5e-28));
}
public static void testRationalFunction()
{
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf("2"), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf("3"), x));
Polynomial divisor = Polynomial.valueOf(valueOf("5"), x).plus(valueOf("6"));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", new Apfloat("0.875"), function.evaluate(valueOf("2")).value(), new Apfloat("5e-30"));
assertEquals("Function plus inverse, value", new Apfloat("2.017857142857142857142857142857"), function.plus(function.inverse()).evaluate(valueOf("2")).value(), new Apfloat("5e-29"));
}
private static FixedPrecisionApfloatField valueOf(String value)
{
return new FixedPrecisionApfloatField(new Apfloat(value), HELPER);
}
private static final FixedPrecisionApfloatHelper HELPER = new FixedPrecisionApfloatHelper(30);
}
apfloat-1.13.0/apfloat-jscience/src/test/java/org/apfloat/jscience/ModuloApintFieldTest.java 0000664 0000000 0000000 00000013616 14557414736 0032051 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.jscience;
import java.util.HashSet;
import org.apfloat.*;
import org.jscience.mathematics.function.*;
import org.jscience.mathematics.vector.*;
import javolution.text.*;
import junit.framework.TestSuite;
/**
* @since 1.8.0
* @version 1.9.0
* @author Mikko Tommila
*/
public class ModuloApintFieldTest
extends ApfloatTestCase
{
public ModuloApintFieldTest(String methodName)
{
super(methodName);
}
public static void main(String[] args)
{
junit.textui.TestRunner.run(suite());
}
public static TestSuite suite()
{
TestSuite suite = new TestSuite();
suite.addTest(new ModuloApintFieldTest("testBasic"));
suite.addTest(new ModuloApintFieldTest("testNoModulus"));
suite.addTest(new ModuloApintFieldTest("testMatrixInverse"));
suite.addTest(new ModuloApintFieldTest("testRationalFunction"));
return suite;
}
public static void testBasic()
{
ModuloApintField.setModulus(new Apint(65537));
ModuloApintField a = valueOf(100);
ModuloApintField b = valueOf(200);
ModuloApintField c = valueOf(200);
ModuloApintField zero = valueOf(0);
assertEquals("100 + 200", valueOf(300), a.plus(b));
assertEquals("-100", valueOf(65537 - 100), a.opposite());
assertEquals("100 - 200", valueOf(65537 - 100), a.minus(b));
assertEquals("100 * 200", valueOf(20000), a.times(b));
assertEquals("1 / 100", valueOf(17695), a.inverse());
assertEquals("copy", a, a.copy());
assertEquals("doubleValue", 100.0, a.doubleValue(), 0.00000000000005);
assertEquals("longValue", 100L, a.longValue());
assertEquals("String", "100", a.toString());
assertEquals("Text", new Text("100"), a.toText());
assertTrue("isLargerThan", b.isLargerThan(a));
assertEquals("compareTo", -1, a.compareTo(b));
HashSet set = new HashSet<>();
set.add(b);
set.add(c);
assertEquals("hashCode", 1, set.size());
try
{
zero.inverse();
fail("Zero divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
try
{
new ModuloApintField(null);
fail("null accepted");
}
catch (NullPointerException npe)
{
// OK, illegal
}
}
public static void testNoModulus()
{
ModuloApintField.setModulus(null);
ModuloApintField a = valueOf(100),
b = valueOf(200);
assertEquals("100 + 200", valueOf(300), a.plus(b));
assertEquals("-100", valueOf(-100), a.opposite());
assertEquals("100 - 200", valueOf(-100), a.minus(b));
assertEquals("100 * 200", valueOf(20000), a.times(b));
assertEquals("copy", a, a.copy());
try
{
a.inverse();
fail("No divisor accepted");
}
catch (ArithmeticException ae)
{
// OK, modulus is not set
}
}
public static void testMatrixInverse()
{
ModuloApintField.setModulus(new Apint(43));
ModuloApintField[][] elements = { { valueOf(1), valueOf(2), valueOf(3) },
{ valueOf(4), valueOf(5), valueOf(6) },
{ valueOf(7), valueOf(8), valueOf(10) } };
Matrix m = DenseMatrix.valueOf(elements);
Vector vectorization = m.minus(m.inverse().inverse()).vectorization();
for (int i = 0; i < vectorization.getDimension(); i++)
{
assertEquals("Element " + i, 0, vectorization.get(i).value().signum());
}
}
public static void testRationalFunction()
{
ModuloApintField.setModulus(new Apint(43));
Variable.Local x = new Variable.Local("x");
Polynomial dividend = Polynomial.valueOf(valueOf(17), Term.valueOf(x, 2)).plus(Polynomial.valueOf(valueOf(23), x));
Polynomial divisor = Polynomial.valueOf(valueOf(37), x).plus(valueOf(26));
RationalFunction function = RationalFunction.valueOf(dividend, divisor);
assertEquals("Function value", new Apint(2), function.evaluate(valueOf(2)).value());
assertEquals("Function plus inverse, value", new Apint(24), function.plus(function.inverse()).evaluate(valueOf(2)).value());
}
private static ModuloApintField valueOf(int value)
{
return new ModuloApintField(new Apint(value));
}
}
apfloat-1.13.0/apfloat-samples/ 0000775 0000000 0000000 00000000000 14557414736 0016332 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/pom.xml 0000664 0000000 0000000 00000010612 14557414736 0017647 0 ustar 00root root 0000000 0000000
4.0.0org.apfloatapfloat-parent1.13.0apfloat-samplesapfloat-samplesSample programs for apfloat for calculating pihttp://www.apfloat.orgorg.apfloatapfloatorg.apfloatapfloat-aparapitrueorg.apfloatapfloat-calctruejunitjunittestorg.apache.maven.pluginsmaven-compiler-plugin*org.apache.maven.pluginsmaven-jar-plugintrueorg.apfloat.samples.PiParallelGUIorg.apfloat.samplesorg.apache.maven.pluginsmaven-shade-plugincustom-jarshadeorg.apfloat:apfloat-samples${project.build.directory}/samples.jarapfloat.jarsigned-appletshadeorg.apfloat:apfloatorg.apfloat:apfloat-calcorg.apfloat:apfloat-samples${project.build.directory}/signedapplet.jarorg.apache.maven.pluginsmaven-jarsigner-pluginsign${project.build.directory}/signedapplet.jarmykeypasswordsrc/main/resourcescluster.properties
apfloat-1.13.0/apfloat-samples/src/ 0000775 0000000 0000000 00000000000 14557414736 0017121 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/ 0000775 0000000 0000000 00000000000 14557414736 0020045 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/java/ 0000775 0000000 0000000 00000000000 14557414736 0020766 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/java/org/ 0000775 0000000 0000000 00000000000 14557414736 0021555 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/ 0000775 0000000 0000000 00000000000 14557414736 0023203 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/ 0000775 0000000 0000000 00000000000 14557414736 0024647 5 ustar 00root root 0000000 0000000 apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/ApfloatHolder.java 0000664 0000000 0000000 00000004542 14557414736 0030243 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
import java.io.Serializable;
import org.apfloat.Apfloat;
/**
* Simple JavaBean to hold one {@link org.apfloat.Apfloat}.
* This class can also be thought of as a pointer to an {@link Apfloat}.
*
* @version 1.9.0
* @author Mikko Tommila
*/
public class ApfloatHolder
implements Serializable
{
/**
* Construct an ApfloatHolder containing null.
*/
public ApfloatHolder()
{
this(null);
}
/**
* Construct an ApfloatHolder containing the specified apfloat.
*
* @param apfloat The number to hold.
*/
public ApfloatHolder(Apfloat apfloat)
{
this.apfloat = apfloat;
}
/**
* Return the apfloat contained in this bean.
*
* @return The apfloat contained in this bean.
*/
public Apfloat getApfloat()
{
return this.apfloat;
}
/**
* Set the apfloat contained in this bean.
*
* @param apfloat The apfloat.
*/
public void setApfloat(Apfloat apfloat)
{
this.apfloat = apfloat;
}
private static final long serialVersionUID = 1L;
private Apfloat apfloat;
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/BackgroundOperation.java 0000664 0000000 0000000 00000006113 14557414736 0031453 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;
import org.apfloat.ApfloatContext;
/**
* Class for running an {@link Operation} in the background in a separate thread.
* The operation is executed using the ExecutorService retrieved from
* {@link ApfloatContext#getExecutorService()}.
*
* @version 1.9.0
* @author Mikko Tommila
*/
public class BackgroundOperation
{
/**
* Runs an operation in the background in a separate thread.
* The execution is started immediately.
*
* @param operation The operation to execute.
*/
public BackgroundOperation(Operation operation)
{
ApfloatContext ctx = ApfloatContext.getContext();
ExecutorService executorService = ctx.getExecutorService();
Callable callable = () -> operation.execute();
this.future = executorService.submit(callable);
}
/**
* Check if the operation has been completed.
*
* @return true if the execution of the operation has been completed, otherwise false.
*/
public boolean isFinished()
{
return this.future.isDone();
}
/**
* Get the result of the operation.
* This method blocks until the operation has been completed.
*
* @return Result of the operation.
*
* @exception RuntimeException If an exception was thrown by the executed operation.
*/
public T getResult()
{
ApfloatContext ctx = ApfloatContext.getContext();
ctx.wait(this.future);
try
{
return this.future.get();
}
catch (InterruptedException | ExecutionException e)
{
throw new RuntimeException(e);
}
}
private Future future;
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/LocalOperationExecutor.java 0000664 0000000 0000000 00000004643 14557414736 0032153 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
/**
* Class to execute {@link Operation}s locally.
* The execution is done in the current JVM.
*
* @version 1.9.0
* @author Mikko Tommila
*/
public class LocalOperationExecutor
implements OperationExecutor
{
/**
* Default constructor.
*/
public LocalOperationExecutor()
{
}
/**
* Execute an operation immediately.
* This method will block until the operation is complete.
*
* @param operation The operation to execute.
*
* @return The result of the operation.
*/
@Override
public T execute(Operation operation)
{
return operation.execute();
}
/**
* Execute an operation in the background.
* This method starts a new thread executing the operation and returns immediately.
*
* @param operation The operation to execute in the background.
*
* @return A {@link BackgroundOperation} for retrieving the result of the operation later.
*/
@Override
public BackgroundOperation executeBackground(Operation operation)
{
return new BackgroundOperation<>(operation);
}
@Override
public int getWeight()
{
return 1;
}
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/Operation.java 0000664 0000000 0000000 00000003065 14557414736 0027456 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
import java.io.Serializable;
/**
* Interface for implementing arbitrary operations to be executed.
*
* @version 1.9.0
* @author Mikko Tommila
*/
@FunctionalInterface
public interface Operation
extends Serializable
{
/**
* Executes some code, returning a value.
*
* @return Return value of the operation.
*/
public T execute();
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/OperationExecutor.java 0000664 0000000 0000000 00000004510 14557414736 0031171 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
/**
* Interface for implementing objects that can execute {@link Operation}s.
* An operation can e.g. be executed locally or remotely.
*
* @version 1.1
* @author Mikko Tommila
*/
public interface OperationExecutor
{
/**
* Executes some code, returning a value.
*
* @param Return value type of the operation.
* @param operation The operation to execute.
*
* @return Return value of the operation.
*/
public T execute(Operation operation);
/**
* Starts executing some code in the background.
*
* @param Return value type of the operation.
* @param operation The operation to execute in the background.
*
* @return An object for retrieving the result of the operation later.
*/
public BackgroundOperation executeBackground(Operation operation);
/**
* Returns the relative weight of this executor.
* The weights of different operation executors can be used
* to distribute work more equally.
*
* @return The relative weight of this operation executor.
*/
public int getWeight();
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/OperationServer.java 0000664 0000000 0000000 00000020605 14557414736 0030644 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
import java.nio.channels.Channels;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.ServerSocketChannel;
import java.net.InetSocketAddress;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* Server for executing {@link Operation}s from remote calls. The client
* should simply send a class implementing the {@link Operation}
* interface serialized through a socket connection. Obviously, the
* class must exist also in the server's classpath. The server will then
* simply call {@link Operation#execute()} on the operation, and send
* the resulting object back in the socket, serialized. If an exception
* occurs during the operation execution, nothing is returned and
* the socket connection is closed.
*
* @version 1.9.0
* @author Mikko Tommila
*/
public class OperationServer
{
private static class Request
implements Runnable
{
public Request(SocketChannel channel)
{
this.channel = channel;
}
@Override
public void run()
{
try (SocketChannel channel = this.channel)
{
info("Request processing started");
ObjectInputStream in = new ObjectInputStream(Channels.newInputStream(this.channel));
info("Ready to receive input data");
Operation> operation = (Operation>) in.readObject();
info("Executing operation");
Object result = operation.execute();
ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(Channels.newOutputStream(this.channel), BUFFER_SIZE));
info("Ready to write output data");
out.writeObject(result);
out.flush();
info("Request processing complete");
}
catch (Exception e)
{
// Avoid exiting the thread
warning("Request processing failed", e);
}
}
private SocketChannel channel;
}
private OperationServer()
{
}
/**
* Command-line entry point.
*
* @param args Command-line parameters.
*
* @exception IOException In case of unexpected network error.
*/
public static void main(String[] args)
throws IOException
{
int port,
workerThreads = 1;
if (args.length < 1)
{
System.err.println("USAGE: OperationServer port [workerThreads] [messageLevel]");
return;
}
try
{
port = Integer.parseInt(args[0]);
}
catch (NumberFormatException nfe)
{
System.err.println("Invalid port: " + args[0]);
return;
}
try
{
if (args.length > 1)
{
workerThreads = Integer.parseInt(args[1]);
if (workerThreads <= 0)
{
throw new NumberFormatException();
}
}
}
catch (NumberFormatException nfe)
{
System.err.println("Invalid number of workerThreads: " + args[0]);
return;
}
try
{
if (args.length > 2)
{
messageLevel = Integer.parseInt(args[2]);
}
}
catch (NumberFormatException nfe)
{
System.err.println("Invalid messageLevel: " + args[0]);
return;
}
// Create a selector object to monitor all open client connections.
Selector selector = Selector.open();
// Create a new non-blocking ServerSocketChannel, bind it to a port, and register it with the Selector
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // Open channel
serverSocketChannel.configureBlocking(false); // Set non-blocking mode
serverSocketChannel.socket().bind(new InetSocketAddress(port)); // Bind to port
SelectionKey serverKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
// Create a pool of worker threads that will run independently
Executor executor = Executors.newFixedThreadPool(workerThreads);
info("Waiting for connections to port " + port);
while (true) // The main server loop. The server runs forever.
{
// This call blocks until there is activity on one of the registered channels
selector.select();
// Get a java.util.Set containing the SelectionKey objects for all channels that are ready for I/O
Set keys = selector.selectedKeys();
// Use a java.util.Iterator to loop through the selected keys
for (Iterator i = keys.iterator(); i.hasNext(); )
{
SelectionKey key = i.next();
i.remove(); // Remove the key from the set of selected keys
// Check whether this key is the SelectionKey we got when we registered the ServerSocketChannel
if (key == serverKey)
{
// Activity on the ServerSocketChannel means a client is trying to connect to the server
if (key.isAcceptable())
{
// Accept the client connection
// Note that the client channel is in blocking mode; a separate thread will use it
SocketChannel clientSocketChannel = serverSocketChannel.accept();
info("New connection accepted");
// Put a new request to the queue so a worker thread can pick it up from there
executor.execute(new Request(clientSocketChannel));
}
}
}
}
}
private static void warning(String message, Exception e)
{
if (messageLevel >= WARNING)
{
System.err.println("WARNING: " + Thread.currentThread().getName() + ": " + message);
e.printStackTrace(System.err);
}
}
private static void info(String message)
{
if (messageLevel >= INFO)
{
System.err.println("INFO: " + Thread.currentThread().getName() + ": " + message);
}
}
private static void debug(String message)
{
if (messageLevel >= DEBUG)
{
System.err.println("DEBUG: " + Thread.currentThread().getName() + ": " + message);
}
}
private static final int BUFFER_SIZE = 8192;
private static final int ERROR = 0;
private static final int WARNING = 1;
private static final int INFO = 2;
private static final int DEBUG = 3;
private static int messageLevel = WARNING;
}
apfloat-1.13.0/apfloat-samples/src/main/java/org/apfloat/samples/Pi.java 0000664 0000000 0000000 00000102505 14557414736 0026065 0 ustar 00root root 0000000 0000000 /*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat.samples;
import java.io.Serializable;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import org.apfloat.Apfloat;
import org.apfloat.ApfloatContext;
import org.apfloat.ApfloatMath;
import org.apfloat.ApfloatRuntimeException;
/**
* Calculates pi using four different algorithms.
*
* @version 1.8.2
* @author Mikko Tommila
*/
public class Pi
{
// Implementation note: we use printf() for printing, because it flushes the output (print() does not)
/**
* Terms for the binary splitting series.
*/
protected static interface BinarySplittingSeries
extends Serializable
{
/**
* Binary splitting term.
*
* @param n The term.
*
* @return The value.
*/
public Apfloat a(long n)
throws ApfloatRuntimeException;
/**
* Binary splitting term.
*
* @param n The term.
*
* @return The value.
*/
public Apfloat p(long n)
throws ApfloatRuntimeException;
/**
* Binary splitting term.
*
* @param n The term.
*
* @return The value.
*/
public Apfloat q(long n)
throws ApfloatRuntimeException;
}
/**
* Abstract base class for the binary splitting series.
*/
protected static abstract class AbstractBinarySplittingSeries
implements BinarySplittingSeries
{
/**
* Construct a binary splitting series with the specified precision and radix.
*
* @param precision The target precision.
* @param radix The radix to be used.
*/
protected AbstractBinarySplittingSeries(long precision, int radix)
{
this.precision = precision;
this.radix = radix;
}
/**
* Target precision.
*/
protected long precision;
/**
* Radix to be used.
*/
protected int radix;
private static final long serialVersionUID = 1L;
}
/**
* Chudnovskys' algorithm terms for the binary splitting series.
*/
protected static class ChudnovskyBinarySplittingSeries
extends AbstractBinarySplittingSeries
{
/**
* Basic constructor.
*
* @param precision The precision.
* @param radix The radix.
*/
public ChudnovskyBinarySplittingSeries(long precision, int radix)
{
super(precision, radix);
this.A = new Apfloat(13591409, precision, radix);
this.B = new Apfloat(545140134, precision, radix);
this.J = new Apfloat(10939058860032000L, precision, radix);
this.ONE = new Apfloat(1, precision, radix);
this.TWO = new Apfloat(2, precision, radix);
this.FIVE = new Apfloat(5, precision, radix);
this.SIX = new Apfloat(6, precision, radix);
}
@Override
public Apfloat a(long n)
throws ApfloatRuntimeException
{
Apfloat s = new Apfloat(n, Apfloat.INFINITE, this.radix),
v = this.A.add(this.B.multiply(s));
v = ((n & 1) == 0 ? v : v.negate());
return v;
}
@Override
public Apfloat p(long n)
throws ApfloatRuntimeException
{
Apfloat v;
if (n == 0)
{
v = this.ONE;
}
else
{
Apfloat f = new Apfloat(n, Apfloat.INFINITE, this.radix),
sixf = this.SIX.multiply(f);
v = sixf.subtract(this.ONE).multiply(this.TWO.multiply(f).subtract(this.ONE)).multiply(sixf.subtract(this.FIVE));
}
return v;
}
@Override
public Apfloat q(long n)
throws ApfloatRuntimeException
{
Apfloat v;
if (n == 0)
{
v = this.ONE;
}
else
{
Apfloat f = new Apfloat(n, Apfloat.INFINITE, this.radix);
v = this.J.multiply(f.multiply(f).multiply(f));
}
return v;
}
private static final long serialVersionUID = 1L;
private final Apfloat A;
private final Apfloat B;
private final Apfloat J;
private final Apfloat ONE;
private final Apfloat TWO;
private final Apfloat FIVE;
private final Apfloat SIX;
}
/**
* Ramanujan's algorithm terms for the binary splitting series.
*/
protected static class RamanujanBinarySplittingSeries
extends AbstractBinarySplittingSeries
{
/**
* Basic constructor.
*
* @param precision The precision.
* @param radix The radix.
*/
public RamanujanBinarySplittingSeries(long precision, int radix)
{
super(precision, radix);
this.A = new Apfloat(1103, precision, radix);
this.B = new Apfloat(26390, precision, radix);
this.J = new Apfloat(3073907232L, precision, radix);
this.ONE = new Apfloat(1, precision, radix);
this.TWO = new Apfloat(2, precision, radix);
this.THREE = new Apfloat(3, precision, radix);
this.FOUR = new Apfloat(4, precision, radix);
}
@Override
public Apfloat a(long n)
throws ApfloatRuntimeException
{
Apfloat s = new Apfloat(n, Apfloat.INFINITE, this.radix),
v = this.A.add(this.B.multiply(s));
return v;
}
@Override
public Apfloat p(long n)
throws ApfloatRuntimeException
{
Apfloat v;
if (n == 0)
{
v = this.ONE;
}
else
{
Apfloat f = new Apfloat(n, Apfloat.INFINITE, this.radix),
fourf = this.FOUR.multiply(f);
v = fourf.subtract(this.ONE).multiply(this.TWO.multiply(f).subtract(this.ONE)).multiply(fourf.subtract(this.THREE));
}
return v;
}
@Override
public Apfloat q(long n)
throws ApfloatRuntimeException
{
Apfloat v;
if (n == 0)
{
v = this.ONE;
}
else
{
Apfloat f = new Apfloat(n, Apfloat.INFINITE, this.radix);
v = this.J.multiply(f.multiply(f).multiply(f));
}
return v;
}
private static final long serialVersionUID = 1L;
private final Apfloat A;
private final Apfloat B;
private final Apfloat J;
private final Apfloat ONE;
private final Apfloat TWO;
private final Apfloat THREE;
private final Apfloat FOUR;
}
/**
* Class for implementing the binary splitting algorithm.
*/
protected static class BinarySplittingPiCalculator
implements Serializable
{
/**
* Construct a pi calculator with the specified precision and radix.
*
* @param series The binary splitting series to be used.
*/
public BinarySplittingPiCalculator(BinarySplittingSeries series)
{
this.series = series;
}
/**
* Entry point for the binary splitting algorithm.
*
* @param n1 Start term.
* @param n2 End term.
* @param T Algorithm parameter.
* @param Q Algorithm parameter.
* @param P Algorithm parameter.
* @param progressIndicator Class to print out the progress of the calculation.
*/
public void r(long n1, long n2, ApfloatHolder T, ApfloatHolder Q, ApfloatHolder P, BinarySplittingProgressIndicator progressIndicator)
throws ApfloatRuntimeException
{
checkAlive();
assert (n1 != n2);
long length = n2 - n1;
if (length == 1)
{
Apfloat p0 = p(n1);
T.setApfloat(a(n1).multiply(p0));
Q.setApfloat(q(n1));
if (P != null) P.setApfloat(p0);
}
else
{
long nMiddle = n1 + n2 >> 1;
ApfloatHolder LT = new ApfloatHolder(),
LQ = new ApfloatHolder(),
LP = new ApfloatHolder();
r(n1, nMiddle, LT, LQ, LP, progressIndicator);
r(nMiddle, n2, T, Q, P, progressIndicator);
T.setApfloat(Q.getApfloat().multiply(LT.getApfloat()).add(LP.getApfloat().multiply(T.getApfloat())));
Q.setApfloat(LQ.getApfloat().multiply(Q.getApfloat()));
if (P != null) P.setApfloat(LP.getApfloat().multiply(P.getApfloat()));
}
if (progressIndicator != null)
{
progressIndicator.progress(n1, n2);
}
}
private Apfloat a(long n)
throws ApfloatRuntimeException
{
return this.series.a(n);
}
private Apfloat p(long n)
throws ApfloatRuntimeException
{
return this.series.p(n);
}
private Apfloat q(long n)
throws ApfloatRuntimeException
{
return this.series.q(n);
}
private static final long serialVersionUID = 1L;
private BinarySplittingSeries series;
}
/**
* Basic class for calculating pi using the Chudnovskys' binary splitting algorithm.
*/
public static class ChudnovskyPiCalculator
implements Operation
{
/**
* Construct a pi calculator with the specified precision and radix.
*
* @param precision The target precision.
* @param radix The radix to be used.
*/
public ChudnovskyPiCalculator(long precision, int radix)
throws ApfloatRuntimeException
{
this(new BinarySplittingPiCalculator(new ChudnovskyBinarySplittingSeries(precision, radix)), precision, radix);
}
/**
* Construct a pi calculator with the specified binary splitting algorithm.
*
* @param calculator The binary splitting algorithm to be used.
* @param precision The target precision.
* @param radix The radix to be used.
*/
protected ChudnovskyPiCalculator(BinarySplittingPiCalculator calculator, long precision, int radix)
throws ApfloatRuntimeException
{
this.calculator = calculator;
this.precision = precision;
this.radix = radix;
}
/**
* Calculate pi using the Chudnovskys' binary splitting algorithm.
*/
@Override
public Apfloat execute()
{
Pi.err.println("Using the Chudnovsky brothers' binary splitting algorithm");
ApfloatHolder T = new ApfloatHolder(),
Q = new ApfloatHolder();
// Perform the calculation of T, Q and P to requested precision only, to improve performance
long terms = (long) ((double) this.precision * Math.log((double) this.radix) / 32.654450041768516);
long time = System.currentTimeMillis();
this.calculator.r(0, terms + 1, T, Q, null, new BinarySplittingProgressIndicator(terms));
time = System.currentTimeMillis() - time;
Pi.err.println("100% complete, elapsed time " + time / 1000.0 + " seconds");
Pi.err.printf("Final value ");
time = System.currentTimeMillis();
Apfloat t = T.getApfloat(),
q = Q.getApfloat();
checkAlive();
Apfloat factor = ApfloatMath.inverseRoot(new Apfloat(1823176476672000L, this.precision, this.radix), 2);
checkAlive();
Apfloat pi = ApfloatMath.inverseRoot(factor.multiply(t), 1).multiply(q);
time = System.currentTimeMillis() - time;
Pi.err.println("took " + time / 1000.0 + " seconds");
return pi;
}
private static final long serialVersionUID = 1L;
private BinarySplittingPiCalculator calculator;
private long precision;
private int radix;
}
/**
* Basic class for calculating pi using the Ramanujan binary splitting algorithm.
*/
public static class RamanujanPiCalculator
implements Operation
{
/**
* Construct a pi calculator with the specified precision and radix.
*
* @param precision The target precision.
* @param radix The radix to be used.
*/
public RamanujanPiCalculator(long precision, int radix)
throws ApfloatRuntimeException
{
this(new BinarySplittingPiCalculator(new RamanujanBinarySplittingSeries(precision, radix)), precision, radix);
}
/**
* Construct a pi calculator with the specified binary splitting algorithm.
*
* @param calculator The binary splitting algorithm to be used.
* @param precision The target precision.
* @param radix The radix to be used.
*/
protected RamanujanPiCalculator(BinarySplittingPiCalculator calculator, long precision, int radix)
throws ApfloatRuntimeException
{
this.calculator = calculator;
this.precision = precision;
this.radix = radix;
}
/**
* Calculate pi using the Ramanujan binary splitting algorithm.
*/
@Override
public Apfloat execute()
{
Pi.err.println("Using the Ramanujan binary splitting algorithm");
ApfloatHolder T = new ApfloatHolder(),
Q = new ApfloatHolder();
// Perform the calculation of T, Q and P to requested precision only, to improve performance
long terms = (long) ((double) this.precision * Math.log((double) this.radix) / 18.38047940053836);
long time = System.currentTimeMillis();
this.calculator.r(0, terms + 1, T, Q, null, new BinarySplittingProgressIndicator(terms));
time = System.currentTimeMillis() - time;
Pi.err.println("100% complete, elapsed time " + time / 1000.0 + " seconds");
Pi.err.printf("Final value ");
time = System.currentTimeMillis();
Apfloat t = T.getApfloat(),
q = Q.getApfloat();
checkAlive();
Apfloat factor = ApfloatMath.inverseRoot(new Apfloat(8, this.precision, this.radix), 2);
checkAlive();
Apfloat pi = ApfloatMath.inverseRoot(t, 1).multiply(factor).multiply(new Apfloat(9801, Apfloat.INFINITE, this.radix)).multiply(q);
time = System.currentTimeMillis() - time;
Pi.err.println("took " + time / 1000.0 + " seconds");
return pi;
}
private static final long serialVersionUID = 1L;
private BinarySplittingPiCalculator calculator;
private long precision;
private int radix;
}
/**
* Indicates progress of the pi calculation using
* the binary splitting algorithm.