net.algart.arrays.AbstractMemoryModel Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of algart Show documentation
Show all versions of algart Show documentation
Open-source Java libraries, supporting generalized smart arrays and matrices with elements
of any types, including a wide set of 2D-, 3D- and multidimensional image processing
and other algorithms, working with arrays and matrices.
/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
*
* 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 net.algart.arrays;
import java.util.Objects;
/**
* A skeletal implementation of the {@link MemoryModel} interface to minimize
* the effort required to implement this interface.
*
* This class implements all concrete newEmptyXxxArray
,
* newXxxArray
and newUnresizableXxxArray
* methods, and also all valueOf
methods
* via trivial calls of corresponding newEmptyArray
and newArray
methods.
* This class implements all concrete newXxxMatrix
* via trivial calls of newMatrix
method.
* It also offers a simple implementation of some other methods: see comments to them.
*
* @author Daniel Alievsky
*/
public abstract class AbstractMemoryModel implements MemoryModel {
public abstract MutableArray newEmptyArray(Class> elementType);
public abstract MutableArray newEmptyArray(Class> elementType, long initialCapacity);
public abstract MutableArray newArray(Class> elementType, long initialLength);
public abstract UpdatableArray newUnresizableArray(Class> elementType, long length);
public MutableArray newArray(Array array) {
Objects.requireNonNull(array, "Null array argument");
return newArray(array.elementType(), array.length());
}
public UpdatableArray newUnresizableArray(Array array) {
Objects.requireNonNull(array, "Null array argument");
return newUnresizableArray(array.elementType(), array.length());
}
/*Repeat() boolean(.class) ==> char$1,,byte$1,,short$1,,int$1,,long$1,,float$1,,double$1;;
Bit ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double
*/
public MutableBitArray newEmptyBitArray() {
return (MutableBitArray) newEmptyArray(boolean.class);
}
public MutableBitArray newEmptyBitArray(long initialCapacity) {
return (MutableBitArray) newEmptyArray(boolean.class, initialCapacity);
}
public MutableBitArray newBitArray(long initialLength) {
return (MutableBitArray) newArray(boolean.class, initialLength);
}
public UpdatableBitArray newUnresizableBitArray(long initialLength) {
return (UpdatableBitArray) newUnresizableArray(boolean.class, initialLength);
}
/*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */
public MutableCharArray newEmptyCharArray() {
return (MutableCharArray) newEmptyArray(char.class);
}
public MutableCharArray newEmptyCharArray(long initialCapacity) {
return (MutableCharArray) newEmptyArray(char.class, initialCapacity);
}
public MutableCharArray newCharArray(long initialLength) {
return (MutableCharArray) newArray(char.class, initialLength);
}
public UpdatableCharArray newUnresizableCharArray(long initialLength) {
return (UpdatableCharArray) newUnresizableArray(char.class, initialLength);
}
public MutableByteArray newEmptyByteArray() {
return (MutableByteArray) newEmptyArray(byte.class);
}
public MutableByteArray newEmptyByteArray(long initialCapacity) {
return (MutableByteArray) newEmptyArray(byte.class, initialCapacity);
}
public MutableByteArray newByteArray(long initialLength) {
return (MutableByteArray) newArray(byte.class, initialLength);
}
public UpdatableByteArray newUnresizableByteArray(long initialLength) {
return (UpdatableByteArray) newUnresizableArray(byte.class, initialLength);
}
public MutableShortArray newEmptyShortArray() {
return (MutableShortArray) newEmptyArray(short.class);
}
public MutableShortArray newEmptyShortArray(long initialCapacity) {
return (MutableShortArray) newEmptyArray(short.class, initialCapacity);
}
public MutableShortArray newShortArray(long initialLength) {
return (MutableShortArray) newArray(short.class, initialLength);
}
public UpdatableShortArray newUnresizableShortArray(long initialLength) {
return (UpdatableShortArray) newUnresizableArray(short.class, initialLength);
}
public MutableIntArray newEmptyIntArray() {
return (MutableIntArray) newEmptyArray(int.class);
}
public MutableIntArray newEmptyIntArray(long initialCapacity) {
return (MutableIntArray) newEmptyArray(int.class, initialCapacity);
}
public MutableIntArray newIntArray(long initialLength) {
return (MutableIntArray) newArray(int.class, initialLength);
}
public UpdatableIntArray newUnresizableIntArray(long initialLength) {
return (UpdatableIntArray) newUnresizableArray(int.class, initialLength);
}
public MutableLongArray newEmptyLongArray() {
return (MutableLongArray) newEmptyArray(long.class);
}
public MutableLongArray newEmptyLongArray(long initialCapacity) {
return (MutableLongArray) newEmptyArray(long.class, initialCapacity);
}
public MutableLongArray newLongArray(long initialLength) {
return (MutableLongArray) newArray(long.class, initialLength);
}
public UpdatableLongArray newUnresizableLongArray(long initialLength) {
return (UpdatableLongArray) newUnresizableArray(long.class, initialLength);
}
public MutableFloatArray newEmptyFloatArray() {
return (MutableFloatArray) newEmptyArray(float.class);
}
public MutableFloatArray newEmptyFloatArray(long initialCapacity) {
return (MutableFloatArray) newEmptyArray(float.class, initialCapacity);
}
public MutableFloatArray newFloatArray(long initialLength) {
return (MutableFloatArray) newArray(float.class, initialLength);
}
public UpdatableFloatArray newUnresizableFloatArray(long initialLength) {
return (UpdatableFloatArray) newUnresizableArray(float.class, initialLength);
}
public MutableDoubleArray newEmptyDoubleArray() {
return (MutableDoubleArray) newEmptyArray(double.class);
}
public MutableDoubleArray newEmptyDoubleArray(long initialCapacity) {
return (MutableDoubleArray) newEmptyArray(double.class, initialCapacity);
}
public MutableDoubleArray newDoubleArray(long initialLength) {
return (MutableDoubleArray) newArray(double.class, initialLength);
}
public UpdatableDoubleArray newUnresizableDoubleArray(long initialLength) {
return (UpdatableDoubleArray) newUnresizableArray(double.class, initialLength);
}
/*Repeat.AutoGeneratedEnd*/
public MutableObjectArray newEmptyObjectArray(Class elementType) {
return InternalUtils.cast(newEmptyArray(elementType));
}
public MutableObjectArray newEmptyObjectArray(Class elementType, long initialCapacity) {
return InternalUtils.cast(newEmptyArray(elementType, initialCapacity));
}
public MutableObjectArray newObjectArray(Class elementType, long initialLength) {
return InternalUtils.cast(newArray(elementType, initialLength));
}
public UpdatableObjectArray newUnresizableObjectArray(Class elementType, long initialLength) {
return InternalUtils.cast(newUnresizableArray(elementType, initialLength));
}
/**
* This implementation returns usual actual copy of the array.
* More precisely, it is equivalent to the following operator:
*
*
* thisMemoryModel.{@link #newArray(Class, long)
* newArray}(array.{@link Array#elementType() elementType()}, array.{@link Array#length()
* length()}).{@link UpdatableArray#copy(Array) copy}(array);
*
*
* @param array the source array.
* @return the usual identical copy of the source array.
* @throws NullPointerException if the argument is {@code null}.
* @throws UnsupportedElementTypeException if the element type of the passed array
* is not supported by this memory model.
* @throws TooLargeArrayException if the length of the passed array is too large for this memory model.
*/
public MutableArray newLazyCopy(Array array) {
// OBSOLETE INCORRECT IMPLEMENTATION: attempt to copy another data into such "lazy copy" via standard
// tools like Arrays.copy (based on subarrays) failed due to copy-on-write nature of the array!
// if (isCreatedBy(array) && array instanceof MutableArray) {
// return ((MutableArray)array).asCopyOnNextWrite();
// } else {
// return newArray(array.elementType(), array.length()).copy(array);
// }
return newArray(array.elementType(), array.length()).copy(array);
}
/**
* This implementation returns usual actual copy of the array.
* More precisely, it is equivalent to the following operator:
*
*
* thisMemoryModel.{@link #newUnresizableArray(Class, long)
* newUnresizableArray}(array.{@link Array#elementType() elementType()}, array.{@link Array#length()
* length()}).{@link UpdatableArray#copy(Array) copy}(array);
*
*
* @param array the source array.
* @return the usual identical unresizable copy of the source array.
* @throws NullPointerException if the argument is {@code null}.
* @throws UnsupportedElementTypeException if the element type of the passed array
* is not supported by this memory model.
* @throws TooLargeArrayException if the length of the passed array is too large for this memory model.
*/
public UpdatableArray newUnresizableLazyCopy(Array array) {
// OBSOLETE INCORRECT IMPLEMENTATION: attempt to copy another data into such "lazy copy" via standard
// tools like Arrays.copy (based on subarrays) failed due to copy-on-write nature of the array!
// if (isCreatedBy(array) && array instanceof UpdatableArray) {
// return ((UpdatableArray)array).asCopyOnNextWrite();
// } else {
// return newUnresizableArray(array.elementType(), array.length()).copy(array);
// }
return newUnresizableArray(array.elementType(), array.length()).copy(array);
}
/**
* This method is fully implemented in this class.
*
* @param arraySupertype the desired type of the underlying array (the generic argument of the matrix type).
* @param elementType the type of matrix elements.
* @param dim the dimensions of the matrix.
* @return created matrix.
* @throws NullPointerException if elementType
or dim
is {@code null}.
* @throws IllegalArgumentException if elementType
is void.class
,
* or if arraySupertype
is {@link MutableArray} or its subtype,
* or if the specified dimensions are incorrect:
* dim.length == 0
,
* dim[n] < 0
for some n
,
* or the product of all specified dimensions
* is greater than Long.MAX_VALUE
.
* @throws ClassCastException if arraySupertype
and
* elementType
do not match.
* @throws UnsupportedElementTypeException if elementType
is not supported by this memory model.
* @throws TooLargeArrayException if the product of all specified dimensions is too large
* for this memory model.
*/
public Matrix newMatrix(Class arraySupertype, Class> elementType, long... dim) {
Objects.requireNonNull(arraySupertype, "Null arraySupertype argument");
Arrays.checkElementTypeForNullAndVoid(elementType);
if (MutableArray.class.isAssignableFrom(arraySupertype)) {
throw new IllegalArgumentException("Illegal arraySupertype = " + arraySupertype
+ ": it is MutableArray or its subtype, but a matrix cannot be based on a resizable array");
}
Class type = Arrays.type(UpdatableArray.class, elementType);
if (!arraySupertype.isAssignableFrom(type)) {
throw new ClassCastException("The passed array supertype " + arraySupertype.getName()
+ " is not a supertype for " + type.getName()
+ " and, so, cannot contain required " + elementType.getCanonicalName() + " elements");
}
long len = AbstractMatrix.checkDimensions(dim);
// this check before cloning dim array is not absolutely safe,
// but it will be repeated inside MatrixImpl constructor
T array = arraySupertype.cast(newUnresizableArray(elementType, len));
return new MatrixImpl(array, dim);
}
/**
* This method is fully implemented in this class.
*
* @param maxSizeAllocatedInJavaMemory the maximal amount of required memory, for which this method
* just redirects to the same method of
* {@link SimpleMemoryModel#getInstance()}
* @param arraySupertype the desired type of the underlying array (the generic argument
* of the matrix type).
* @param elementType the type of matrix elements.
* @param dim the dimensions of the matrix.
* @return created matrix.
* @throws NullPointerException if elementType
or dim
is {@code null}.
* @throws IllegalArgumentException if elementType
is void.class
,
* or if arraySupertype
is {@link MutableArray} or its subtype,
* or if the specified dimensions are incorrect: dim.length == 0
,
* dim[n] < 0
for some n
,
* or the product of all specified dimensions
* is greater than Long.MAX_VALUE
.
* @throws ClassCastException if arraySupertype
and elementType
do not match.
* @throws UnsupportedElementTypeException if elementType
is not supported by this memory model
* or, for a matrix smaller than maxSizeAllocatedInJavaMemory
,
* by {@link SimpleMemoryModel}.
* @throws TooLargeArrayException if the product of all specified dimensions is too large
* for this memory model or,
* for a matrix smaller than maxSizeAllocatedInJavaMemory
,
* by {@link SimpleMemoryModel}.
*/
public Matrix newMatrix(
long maxSizeAllocatedInJavaMemory,
Class arraySupertype, Class> elementType, long... dim) {
long arrayLength = Arrays.longMul(dim);
return (arrayLength != Long.MIN_VALUE // prefer throwing an exception by this class, not by SimpleMemoryModel
&& Arrays.sizeOf(elementType, arrayLength) <= maxSizeAllocatedInJavaMemory ?
Arrays.SMM :
this)
.newMatrix(arraySupertype, elementType, dim);
}
public Matrix newMatrix(Class arraySupertype, Matrix> matrix) {
Objects.requireNonNull(matrix, "Null matrix argument");
return newMatrix(arraySupertype, matrix.elementType(), matrix.dimensions());
}
public Matrix newStructuredMatrix(Class arraySupertype, Matrix> matrix) {
return newMatrix(arraySupertype, matrix).structureLike(matrix);
}
/*Repeat() boolean ==> char,,byte,,short,,int,,long,,float,,double;;
Bit ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double;;
bit ==> char,,byte,,short,,int,,long,,float,,double */
public Matrix newBitMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableBitArray array = newUnresizableBitArray(len);
return new MatrixImpl(array, dim);
}
/*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */
public Matrix newCharMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableCharArray array = newUnresizableCharArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newByteMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableByteArray array = newUnresizableByteArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newShortMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableShortArray array = newUnresizableShortArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newIntMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableIntArray array = newUnresizableIntArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newLongMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableLongArray array = newUnresizableLongArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newFloatMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableFloatArray array = newUnresizableFloatArray(len);
return new MatrixImpl(array, dim);
}
public Matrix newDoubleMatrix(long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableDoubleArray array = newUnresizableDoubleArray(len);
return new MatrixImpl(array, dim);
}
/*Repeat.AutoGeneratedEnd*/
public Matrix> newObjectMatrix(Class elementType, long... dim) {
long len = AbstractMatrix.checkDimensions(dim);
UpdatableObjectArray array = newUnresizableObjectArray(elementType, len);
return new MatrixImpl>(array, dim);
}
public Matrix newLazyCopy(Class arraySupertype, Matrix> matrix) {
return matrix.matrix(newUnresizableLazyCopy(matrix.array())).cast(arraySupertype);
}
public UpdatableArray valueOf(Object array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
Class> elementType = array.getClass().getComponentType();
if (elementType == null) {
throw new IllegalArgumentException("The argument is not a Java array: " + array.getClass());
}
return newUnresizableArray(elementType, count).setData(0, array, offset, count);
}
public UpdatableArray valueOf(Object array) {
Objects.requireNonNull(array, "Null array argument");
Class> elementType = array.getClass().getComponentType();
if (elementType == null) {
throw new IllegalArgumentException("The argument is not a Java array: " + array.getClass());
}
return newUnresizableArray(elementType, java.lang.reflect.Array.getLength(array)).setData(0, array);
}
/*Repeat() boolean ==> char,,byte,,short,,int,,long,,float,,double;;
Bit ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double */
public UpdatableBitArray valueOf(boolean[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableBitArray) newUnresizableBitArray(count).setData(0, array, offset, count);
}
public UpdatableBitArray valueOf(boolean[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableBitArray) newUnresizableBitArray(array.length).setData(0, array);
}
/*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */
public UpdatableCharArray valueOf(char[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableCharArray) newUnresizableCharArray(count).setData(0, array, offset, count);
}
public UpdatableCharArray valueOf(char[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableCharArray) newUnresizableCharArray(array.length).setData(0, array);
}
public UpdatableByteArray valueOf(byte[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableByteArray) newUnresizableByteArray(count).setData(0, array, offset, count);
}
public UpdatableByteArray valueOf(byte[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableByteArray) newUnresizableByteArray(array.length).setData(0, array);
}
public UpdatableShortArray valueOf(short[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableShortArray) newUnresizableShortArray(count).setData(0, array, offset, count);
}
public UpdatableShortArray valueOf(short[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableShortArray) newUnresizableShortArray(array.length).setData(0, array);
}
public UpdatableIntArray valueOf(int[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableIntArray) newUnresizableIntArray(count).setData(0, array, offset, count);
}
public UpdatableIntArray valueOf(int[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableIntArray) newUnresizableIntArray(array.length).setData(0, array);
}
public UpdatableLongArray valueOf(long[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableLongArray) newUnresizableLongArray(count).setData(0, array, offset, count);
}
public UpdatableLongArray valueOf(long[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableLongArray) newUnresizableLongArray(array.length).setData(0, array);
}
public UpdatableFloatArray valueOf(float[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableFloatArray) newUnresizableFloatArray(count).setData(0, array, offset, count);
}
public UpdatableFloatArray valueOf(float[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableFloatArray) newUnresizableFloatArray(array.length).setData(0, array);
}
public UpdatableDoubleArray valueOf(double[] array, int offset, int count) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableDoubleArray) newUnresizableDoubleArray(count).setData(0, array, offset, count);
}
public UpdatableDoubleArray valueOf(double[] array) {
Objects.requireNonNull(array, "Null array argument");
return (UpdatableDoubleArray) newUnresizableDoubleArray(array.length).setData(0, array);
}
/*Repeat.AutoGeneratedEnd*/
public UpdatableObjectArray valueOf(E[] array, int offset, int count) {
return InternalUtils.cast(valueOf((Object) array, offset, count));
}
public UpdatableObjectArray valueOf(E[] array) {
return InternalUtils.cast(valueOf((Object) array));
}
public abstract boolean isElementTypeSupported(Class> elementType);
public abstract boolean areAllPrimitiveElementTypesSupported();
public abstract boolean areAllElementTypesSupported();
public abstract long maxSupportedLength(Class> elementType);
public abstract boolean isCreatedBy(Array array);
}