/*
* The MIT License (MIT)
*
* Copyright (c) 2007-2014 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 net.algart.math.IRange;
/**
* <p>Implementation of
* {@link Matrices#copyRegion(ArrayContext, Matrix, Matrix, net.algart.arrays.Matrices.Region, long...)}
* method.</p>
*
* <p>This class is <b>thread-compatible</b> and recommended to be used in a single thread.</p>
*
* <p>AlgART Laboratory 2007–2014</p>
*
* @author Daniel Alievsky
* @version 1.2
* @since JDK 1.5
*/
abstract strictfp class ArraysMatrixRegionCopier {
private static final long OUTSIDE_SRC_INDEX = -1;
private final ArrayContext context;
private final Matrix<? extends UpdatableArray> dest;
private final Matrix<? extends Array> src;
private final UpdatableArray destArray;
private final Array srcArray;
private final Object destJArray;
private final Object srcJArray;
private final int destJArrayOffset;
private final int srcJArrayOffset;
private final long destDimX;
private final long srcDimX;
private final long[] shifts;
private final long[] srcCoordinates;
private final long[] destCoordinates;
private final Array outsideConst;
private long copiedElementsCount, lastCopiedElementsCount;
private long currentProgress, totalProgress; // can be Long.MAX_VALUE
private long lastProgressTime = Long.MIN_VALUE;
private ArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, Array outsideConst)
{
this.context = context;
this.dest = dest;
this.src = src;
this.destArray = dest.array();
this.srcArray = src.array();
this.destJArray = Arrays.javaArrayInternal(this.destArray);
this.srcJArray = Arrays.javaArrayInternal(this.srcArray);
this.destJArrayOffset = this.destJArray == null ? -1 : Arrays.javaArrayOffsetInternal(this.destArray);
this.srcJArrayOffset = this.srcJArray == null ? -1 : Arrays.javaArrayOffsetInternal(this.srcArray);
// checks above are necessary for a case of BitArray
this.destDimX = dest.dimX();
this.srcDimX = src.dimX();
this.shifts = shifts;
this.srcCoordinates = new long[maxNumberOfDimensions];
this.destCoordinates = new long[maxNumberOfDimensions];
this.outsideConst = outsideConst;
}
public static ArraysMatrixRegionCopier getInstance(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, Object outsideValue, boolean mustBeInside)
{
assert dest != null;
assert src != null;
assert maxNumberOfDimensions > 0;
outsideValue = Matrices.castOutsideValue(outsideValue, dest.array());
// - necessary even for null, to avoid NullPointerException below while autounboxing
Class<?> elementType = dest.elementType();
//[[Repeat() bit|boolean ==> char,,byte,,short,,int,,long,,float,,double;;
// Boolean ==> Character,,Byte,,Short,,Integer,,Long,,Float,,Double;;
// Bit ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double]]
if (elementType == boolean.class) {
return new BitArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Boolean)outsideValue, mustBeInside);
} else
//[[Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! ]]
if (elementType == char.class) {
return new CharArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Character)outsideValue, mustBeInside);
} else
if (elementType == byte.class) {
return new ByteArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Byte)outsideValue, mustBeInside);
} else
if (elementType == short.class) {
return new ShortArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Short)outsideValue, mustBeInside);
} else
if (elementType == int.class) {
return new IntArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Integer)outsideValue, mustBeInside);
} else
if (elementType == long.class) {
return new LongArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Long)outsideValue, mustBeInside);
} else
if (elementType == float.class) {
return new FloatArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Float)outsideValue, mustBeInside);
} else
if (elementType == double.class) {
return new DoubleArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
(Double)outsideValue, mustBeInside);
} else
//[[Repeat.AutoGeneratedEnd]]
return new ObjectArraysMatrixRegionCopier(context, maxNumberOfDimensions, dest, src, shifts,
outsideValue, mustBeInside);
}
public final void process(Matrices.Region destRegion) {
initializeProgress(destRegion);
boolean fullyInside = true;
for (int k = 0, n = destRegion.n(); k < n; k++) {
IRange destRange = destRegion.coordRange(k);
long destMin = destRange.min();
long destMax = destRange.max();
if (destMin < 0 || destMax >= dest.dim(k)) {
fullyInside = false;
break;
}
long srcMin = shifts.length > k ? destMin - shifts[k] : destMin;
long srcMax = shifts.length > k ? destMax - shifts[k] : destMax;
if (srcMin < 0 || srcMax >= src.dim(k)) {
fullyInside = false;
break;
}
}
JArrayPool bufferPool = this.destJArray != null || this.srcJArray != null ? null :
this.destArray instanceof CharArray ? ArraysFuncImpl.CHAR_BUFFERS :
this.destArray instanceof ByteArray ? ArraysFuncImpl.BYTE_BUFFERS :
this.destArray instanceof ShortArray ? ArraysFuncImpl.SHORT_BUFFERS :
this.destArray instanceof IntArray ? ArraysFuncImpl.INT_BUFFERS :
this.destArray instanceof LongArray ? ArraysFuncImpl.LONG_BUFFERS :
this.destArray instanceof FloatArray ? ArraysFuncImpl.FLOAT_BUFFERS :
this.destArray instanceof DoubleArray ? ArraysFuncImpl.DOUBLE_BUFFERS :
null;
Object buf = bufferPool == null ? null : bufferPool.requestArray();
try {
SegmentCopier segmentCopier = fullyInside ? new UncheckedSegmentCopier(buf) :
outsideConst == null ? new CheckedSegmentCopier(buf) :
new ContinuedSegmentCopier(buf);
processRecursively(destRegion, segmentCopier);
} finally {
if (bufferPool != null) {
bufferPool.releaseArray(buf);
}
}
}
/**
* Copies the element <tt>#srcIndex</tt> from the source array to the element <tt>#destIndex</tt>
* of the destination array or, if <tt>#srcIndex=={@link #OUTSIDE_SRC_INDEX}</tt>,
* fills the element <tt>#destIndex</tt> of the destination array by the outside value.
*
* @param destIndex the index in the destination array.
* @param srcIndex the index in the source array or {@link #OUTSIDE_SRC_INDEX}.
*/
abstract void copyElement(long destIndex, long srcIndex);
/**
* Fills <tt>count</tt> elements of this array, starting from <tt>position</tt> index,
* by the outside value.
*
* @param position start index (inclusive) to be filled.
* @param count number of filled elements.
* @throws IndexOutOfBoundsException for illegal <tt>position</tt> and <tt>count</tt>
* (<tt>position < 0 || count < 0 || position + count > length()</tt>).
* @see Arrays#zeroFill(UpdatableArray)
*/
abstract void fill(long position, long count);
private void processRecursively(Matrices.Region destRegion, SegmentCopier segmentCopier) {
final int n = destRegion.n();
// System.out.println("Copying " + destRegion + ", shifts=" + JArrays.toString(shifts, ",", 100));
if (n == 1) {
segmentCopier.copySegment(destRegion);
} else { // the recursion
final IRange destRange = destRegion.coordRange(n - 1);
final long destMin = destRange.min();
final long destMax = destRange.max();
Matrices.Region.MutableIRange mutableCoordRange = new Matrices.Region.MutableIRange();
for (long k = destMin; k <= destMax; k++) {
destCoordinates[n - 1] = k;
srcCoordinates[n - 1] = shifts.length >= n ? k - shifts[n - 1] : k;
if (destRegion.sectionIsUninterruptedSegment(k)) {
if (n != 2)
throw new AssertionError("Invalid implementation of " + destRegion.getClass()
+ ": sectionIsUninterruptedSegment must return true only for n=2, but n=" + n);
if (destRegion.segmentSectionAtLastCoordinate(mutableCoordRange, k)) {
segmentCopier.copyUninterruptedSegment(mutableCoordRange.min, mutableCoordRange.max);
}
} else {
for (Matrices.Region section : destRegion.sectionAtLastCoordinate(k)) {
if (section.n != n - 1)
throw new AssertionError("Invalid implementation of " + destRegion.getClass()
+ ": number of dimensions of its section is "
+ section.n + " instead of " + n + "-1");
processRecursively(section, segmentCopier);
}
}
}
}
}
private void initializeProgress(Matrices.Region destRegion) {
copiedElementsCount = 0;
lastCopiedElementsCount = 0;
currentProgress = 0;
totalProgress = 1;
for (int k = 0, n = destRegion.n(); k < n; k++) {
long size = destRegion.coordRange(k).size();
long product;
if ((product = Arrays.longMul(totalProgress, size)) == Long.MIN_VALUE) {
totalProgress = Long.MAX_VALUE;
break; // overflow
}
totalProgress = product;
}
}
private void updateProgressForSegment(IRange destRange) {
long size = destRange.size();
if (currentProgress + size < 0) { // overflow
currentProgress = Long.MAX_VALUE;
} else {
currentProgress += size;
}
if (context != null && copiedElementsCount - lastCopiedElementsCount > 4096) { // overflow is unimportant here
lastCopiedElementsCount = copiedElementsCount;
long t = System.currentTimeMillis();
if (lastProgressTime == Long.MIN_VALUE ||
t - lastProgressTime > Arrays.SystemSettings.RECOMMENDED_TIME_OF_NONINTERRUPTABLE_PROCESSING)
{
lastProgressTime = t;
context.checkInterruptionAndUpdateProgress(srcArray.elementType(), currentProgress, totalProgress);
}
}
}
abstract class SegmentCopier {
final Object workJArray;
final int workJArrayLength;
SegmentCopier(Object workJArray) {
this.workJArray = workJArray;
this.workJArrayLength = workJArray == null ? 0 : java.lang.reflect.Array.getLength(workJArray);
}
abstract void copyUninterruptedSegment(long destMin, long destMax);
abstract void copyInterruptedSegment(Matrices.Region destRegion, long destMin, long destMax);
final void copySegment(Matrices.Region destRegion) {
final IRange destRange = destRegion.coordRange(0);
if (destRegion.isRectangular()) {
copyUninterruptedSegment(destRange.min(), destRange.max());
} else {
// rare situation: only non-standard implementations of Matrices.Region
copyInterruptedSegment(destRegion, destRange.min(), destRange.max());
}
updateProgressForSegment(destRange);
}
final void copyRange(long destIndex, long srcIndex, long len) {
if (destJArray != null) {
srcArray.getData(srcIndex, destJArray, destJArrayOffset + (int)destIndex, (int)len);
} else if (srcJArray != null) {
destArray.setData(destIndex, srcJArray, srcJArrayOffset + (int)srcIndex, (int)len);
} else if (len < workJArrayLength) {
srcArray.getData(srcIndex, workJArray, 0, (int)len);
destArray.setData(destIndex, workJArray, 0, (int)len);
} else {
destArray.subArr(destIndex, len).copy(srcArray.subArr(srcIndex, len));
}
}
}
private class UncheckedSegmentCopier extends SegmentCopier {
UncheckedSegmentCopier(Object workJArray) {
super(workJArray);
}
@Override
void copyUninterruptedSegment(long destMin, long destMax) {
destCoordinates[0] = destMin;
long srcMin = shifts.length >= 1 ? destMin - shifts[0] : destMin;
long destIndex = dest.uncheckedIndex(destCoordinates);
assert destMax >= 0 && destMax < destDimX;
long len = destMax - destMin + 1;
copiedElementsCount += len;
srcCoordinates[0] = srcMin;
long srcIndex = src.uncheckedIndex(srcCoordinates);
copyRange(destIndex, srcIndex, len);
}
@Override
void copyInterruptedSegment(Matrices.Region destRegion, long destMin, long destMax) {
destCoordinates[0] = destMin;
long destIndex = dest.uncheckedIndex(destCoordinates);
long destX = destMin;
long srcX = shifts.length >= 1 ? destX - shifts[0] : destX;
srcCoordinates[0] = srcX;
long srcIndex = src.uncheckedIndex(srcCoordinates);
for (; destX <= destMax; destX++, srcX++, destIndex++, srcIndex++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
copyElement(destIndex, srcIndex);
copiedElementsCount++;
}
}
}
}
private class CheckedSegmentCopier extends SegmentCopier {
CheckedSegmentCopier(Object workJArray) {
super(workJArray);
}
@Override
void copyUninterruptedSegment(long destMin, long destMax) {
destCoordinates[0] = destMin;
long srcMin = shifts.length >= 1 ? destMin - shifts[0] : destMin;
long destIndex;
try {
destIndex = dest.index(destCoordinates);
} catch (IndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException("Destination region, " + e.getMessage());
}
assert destMax >= 0 : "destMin is correct " + destMin + ", but destMax is negative " + destMax;
if (destMax >= destDimX)
throw new IndexOutOfBoundsException("Destination region, index (" + destMax
+ ") >= dim(0) (" + destDimX + ")");
long len = destMax - destMin + 1;
long srcMax = srcMin + destMax - destMin;
copiedElementsCount += len;
srcCoordinates[0] = srcMin;
long srcIndex = src.index(srcCoordinates);
if (srcMax >= srcDimX)
throw new IndexOutOfBoundsException("Source region, index (" + srcMax
+ ") >= dim(0) (" + srcDimX + ")");
copyRange(destIndex, srcIndex, len);
}
@Override
void copyInterruptedSegment(Matrices.Region destRegion, long destMin, long destMax) {
long destX = destMin;
// find the 1st copied element before checking coordinates
for (; destX <= destMax; destX++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
break;
}
}
if (destX > destMax) {
return; // no integer points in the specified region
}
destCoordinates[0] = destX;
long destIndex;
try {
destIndex = dest.index(destCoordinates);
} catch (IndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException("Destination region, " + e.getMessage());
}
long srcX = shifts.length >= 1 ? destX - shifts[0] : destX;
srcCoordinates[0] = srcX;
long srcIndex = src.index(srcCoordinates);
for (; destX <= destMax; destX++, srcX++, destIndex++, srcIndex++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
if (destX >= destDimX)
throw new IndexOutOfBoundsException("Destination region, index (" + destX
+ (destX < 0 ? ") < 0" : ") >= dim(0) (" + destDimX + ")"));
if (srcX >= srcDimX)
throw new IndexOutOfBoundsException("Source region, index (" + srcX
+ (srcX < 0 ? ") < 0" : ") >= dim(0) (" + srcDimX + ")"));
copyElement(destIndex, srcIndex);
copiedElementsCount++;
}
}
}
}
private class ContinuedSegmentCopier extends SegmentCopier {
ContinuedSegmentCopier(Object workJArray) {
super(workJArray);
}
@Override
void copyUninterruptedSegment(long destMin, long destMax) {
destCoordinates[0] = 0;
if (!dest.inside(destCoordinates)) {
return; // the line is outside the destination matrix: nothing to do
}
if (destMin < 0) {
destMin = 0;
}
if (destMax > destDimX - 1) {
destMax = destDimX - 1;
}
if (destMin > destMax) {
return; // nothing to do
}
destCoordinates[0] = destMin;
long srcMin = shifts.length >= 1 ? destMin - shifts[0] : destMin;
long destIndex = dest.index(destCoordinates);
assert destMax >= 0 && destMax < destDimX : "destMin is " + destMin + ", but destMax is " + destMax;
long len = destMax - destMin + 1;
long srcMax = srcMin + destMax - destMin;
copiedElementsCount += len;
srcCoordinates[0] = 0;
if (srcMax < 0 || srcMin >= srcDimX || !src.inside(srcCoordinates)) {
// the line is outside the source matrix: filling from outsideConst
fill(destIndex, len);
return;
}
if (srcMin < 0) {
fill(destIndex, -srcMin);
destIndex -= srcMin; // increasing destIndex
len += srcMin; // decreasing len
srcMin = 0;
}
assert srcMin < srcDimX;
srcCoordinates[0] = srcMin;
long srcIndex = src.index(srcCoordinates);
long rear = 0;
if (srcMax >= srcDimX) {
rear = srcMax - srcDimX + 1;
len -= rear;
}
copyRange(destIndex, srcIndex, len);
if (rear > 0) {
fill(destIndex + len, rear);
}
}
@Override
void copyInterruptedSegment(Matrices.Region destRegion, long destMin, long destMax) {
destCoordinates[0] = 0;
if (!dest.inside(destCoordinates)) {
return; // the line is outside the destination matrix: nothing to do
}
if (destMin < 0) {
destMin = 0;
}
if (destMax > destDimX - 1) {
destMax = destDimX - 1;
}
if (destMin > destMax) {
return; // nothing to do
}
destCoordinates[0] = destMin;
long destIndex = dest.index(destCoordinates);
assert destMax >= 0 && destMax < destDimX : "destMin is " + destMin + ", but destMax is " + destMax;
long destX = destMin;
long srcX = shifts.length >= 1 ? destX - shifts[0] : destX;
srcCoordinates[0] = 0;
if (srcX >= srcDimX || !src.inside(srcCoordinates)) {
// the line is outside the source matrix: filling from outsideConst;
// the check of srcX is necessary to be sure that srcCoordinates will be correct for "index" call
for (; destX <= destMax; destX++, srcX++, destIndex++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
copyElement(destIndex, OUTSIDE_SRC_INDEX);
copiedElementsCount++;
}
}
return;
}
for (; srcX < 0 && destX <= destMax; destX++, srcX++, destIndex++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
copyElement(destIndex, OUTSIDE_SRC_INDEX);
copiedElementsCount++;
}
}
if (destX > destMax) {
return; // nothing to do more
}
assert srcX >= 0 && srcX < srcDimX;
srcCoordinates[0] = srcX;
long srcIndex = src.index(srcCoordinates);
for (; destX <= destMax; destX++, srcX++, destIndex++, srcIndex++) {
destCoordinates[0] = destX;
if (destRegion.contains(destCoordinates)) {
copyElement(destIndex, srcX >= srcDimX ? OUTSIDE_SRC_INDEX : srcIndex);
copiedElementsCount++;
}
}
}
}
/*Repeat() bit|boolean(?!\smustBeInside) ==> char,,byte,,short,,int,,long,,float,,double;;
Bit|Boolean ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double;;
(src(?:Byte|Short)Array\.get) ==> $1,,(byte)$1,,(short)$1,,$1,,...;;
(set|get)Object ==> $1Element,,...
*/
private static class BitArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableBitArray destBitArray;
private final BitArray srcBitArray;
private final boolean outsideValue;
private BitArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, boolean outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nBitCopies(Long.MAX_VALUE, outsideValue));
this.destBitArray = (UpdatableBitArray)dest.array();
this.srcBitArray = (BitArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destBitArray.setBit(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcBitArray.getBit(srcIndex));
}
void fill(long position, long count) {
destBitArray.fill(position, count, outsideValue);
}
}
/*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */
private static class CharArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableCharArray destCharArray;
private final CharArray srcCharArray;
private final char outsideValue;
private CharArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, char outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nCharCopies(Long.MAX_VALUE, outsideValue));
this.destCharArray = (UpdatableCharArray)dest.array();
this.srcCharArray = (CharArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destCharArray.setChar(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcCharArray.getChar(srcIndex));
}
void fill(long position, long count) {
destCharArray.fill(position, count, outsideValue);
}
}
private static class ByteArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableByteArray destByteArray;
private final ByteArray srcByteArray;
private final byte outsideValue;
private ByteArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, byte outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nByteCopies(Long.MAX_VALUE, outsideValue));
this.destByteArray = (UpdatableByteArray)dest.array();
this.srcByteArray = (ByteArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destByteArray.setByte(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : (byte)srcByteArray.getByte(srcIndex));
}
void fill(long position, long count) {
destByteArray.fill(position, count, outsideValue);
}
}
private static class ShortArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableShortArray destShortArray;
private final ShortArray srcShortArray;
private final short outsideValue;
private ShortArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, short outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nShortCopies(Long.MAX_VALUE, outsideValue));
this.destShortArray = (UpdatableShortArray)dest.array();
this.srcShortArray = (ShortArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destShortArray.setShort(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : (short)srcShortArray.getShort(srcIndex));
}
void fill(long position, long count) {
destShortArray.fill(position, count, outsideValue);
}
}
private static class IntArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableIntArray destIntArray;
private final IntArray srcIntArray;
private final int outsideValue;
private IntArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, int outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nIntCopies(Long.MAX_VALUE, outsideValue));
this.destIntArray = (UpdatableIntArray)dest.array();
this.srcIntArray = (IntArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destIntArray.setInt(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcIntArray.getInt(srcIndex));
}
void fill(long position, long count) {
destIntArray.fill(position, count, outsideValue);
}
}
private static class LongArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableLongArray destLongArray;
private final LongArray srcLongArray;
private final long outsideValue;
private LongArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, long outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nLongCopies(Long.MAX_VALUE, outsideValue));
this.destLongArray = (UpdatableLongArray)dest.array();
this.srcLongArray = (LongArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destLongArray.setLong(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcLongArray.getLong(srcIndex));
}
void fill(long position, long count) {
destLongArray.fill(position, count, outsideValue);
}
}
private static class FloatArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableFloatArray destFloatArray;
private final FloatArray srcFloatArray;
private final float outsideValue;
private FloatArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, float outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nFloatCopies(Long.MAX_VALUE, outsideValue));
this.destFloatArray = (UpdatableFloatArray)dest.array();
this.srcFloatArray = (FloatArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destFloatArray.setFloat(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcFloatArray.getFloat(srcIndex));
}
void fill(long position, long count) {
destFloatArray.fill(position, count, outsideValue);
}
}
private static class DoubleArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableDoubleArray destDoubleArray;
private final DoubleArray srcDoubleArray;
private final double outsideValue;
private DoubleArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, double outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : Arrays.nDoubleCopies(Long.MAX_VALUE, outsideValue));
this.destDoubleArray = (UpdatableDoubleArray)dest.array();
this.srcDoubleArray = (DoubleArray)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destDoubleArray.setDouble(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcDoubleArray.getDouble(srcIndex));
}
void fill(long position, long count) {
destDoubleArray.fill(position, count, outsideValue);
}
}
/*Repeat.AutoGeneratedEnd*/
private static class ObjectArraysMatrixRegionCopier extends ArraysMatrixRegionCopier {
private final UpdatableObjectArray<Object> destObjectArray;
private final ObjectArray<?> srcObjectArray;
private final Object outsideValue;
private ObjectArraysMatrixRegionCopier(ArrayContext context, int maxNumberOfDimensions,
Matrix<? extends UpdatableArray> dest, Matrix<? extends Array> src,
long[] shifts, Object outsideValue, boolean mustBeInside)
{
super(context, maxNumberOfDimensions, dest, src, shifts,
mustBeInside ? null : outsideValue == null ?
Arrays.nNullCopies(Long.MAX_VALUE, src.elementType()) :
Arrays.nObjectCopies(Long.MAX_VALUE, outsideValue));
this.destObjectArray = ((UpdatableObjectArray<?>)dest.array()).cast(Object.class);
this.srcObjectArray = (ObjectArray<?>)src.array();
this.outsideValue = outsideValue;
}
void copyElement(long destIndex, long srcIndex) {
destObjectArray.setElement(destIndex,
srcIndex == OUTSIDE_SRC_INDEX ? outsideValue : srcObjectArray.getElement(srcIndex));
}
void fill(long position, long count) {
destObjectArray.fill(position, count, outsideValue);
}
}
}