Package net.algart.arrays

Source Code of net.algart.arrays.ArraysMatrixRegionCopier$CheckedSegmentCopier

/*
* 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&ndash;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 &lt; 0 || count &lt; 0 || position + count &gt; 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);
        }
    }
}
TOP

Related Classes of net.algart.arrays.ArraysMatrixRegionCopier$CheckedSegmentCopier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.