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

tfw.immutable.ila.bitila.BitIlaReverse Maven / Gradle / Ivy

Go to download

The FrameWork for building highly scalable and maintainable applications

The newest version!
package tfw.immutable.ila.bitila;

import java.io.IOException;
import tfw.check.Argument;

public final class BitIlaReverse {
    private static final long REVERSE_MASK_32 = 0x00000000FFFFFFFFL;
    private static final long REVERSE_MASK_16 = 0x0000FFFF0000FFFFL;
    private static final long REVERSE_MASK_8 = 0x00FF00FF00FF00FFL;
    private static final long REVERSE_MASK_4 = 0x0F0F0F0F0F0F0F0FL;
    private static final long REVERSE_MASK_2 = 0x3333333333333333L;
    private static final long REVERSE_MASK_1 = 0x5555555555555555L;
    private static final long NOT_REVERSE_MASK_32 = ~REVERSE_MASK_32;
    private static final long NOT_REVERSE_MASK_16 = ~REVERSE_MASK_16;
    private static final long NOT_REVERSE_MASK_8 = ~REVERSE_MASK_8;
    private static final long NOT_REVERSE_MASK_4 = ~REVERSE_MASK_4;
    private static final long NOT_REVERSE_MASK_2 = ~REVERSE_MASK_2;
    private static final long NOT_REVERSE_MASK_1 = ~REVERSE_MASK_1;

    private BitIlaReverse() {}

    public static void reverse(final long[] array, final long offset, final long length) {
        Argument.assertNotNull(array, "array");
        Argument.assertNotLessThan(offset, 0, "offset");
        Argument.assertNotLessThan(length, 0, "length");

        long leadPartial = 0;
        long leadPartialSize = 0;
        long offsetMod64 = offset % Long.SIZE;

        if (offsetMod64 != 0) {
            leadPartialSize = Long.SIZE - offsetMod64;

            if (leadPartialSize > length) {
                leadPartialSize = length;
            }

            leadPartial = BitIlaUtil.getPartialLong(array, offset, leadPartialSize);
        }

        long revLeadPartial = reverseLong(leadPartial);
        int longsOffset = (int) ((offset + leadPartialSize) / Long.SIZE);
        int numLongs = (int) ((length - leadPartialSize) / Long.SIZE);

        if (numLongs > 0) {
            reverseLongs(array, longsOffset, numLongs);
        }

        long trailPartialSize = (length - leadPartialSize) % Long.SIZE;
        long trailOffset = offset + leadPartialSize + numLongs * (long) Long.SIZE;
        long trailPartial = BitIlaUtil.getPartialLong(array, trailOffset, trailPartialSize);
        long revTrailFrag = reverseLong(trailPartial);

        if (numLongs > 0 && leadPartialSize != trailPartialSize) {
            BitIlaUtil.copy(
                    array,
                    longsOffset * (long) Long.SIZE + trailPartialSize - leadPartialSize,
                    array,
                    longsOffset * (long) Long.SIZE,
                    numLongs * (long) Long.SIZE);
        }

        BitIlaUtil.setLeftJustifiedPartialLong(array, offset, revTrailFrag, trailPartialSize);
        BitIlaUtil.setLeftJustifiedPartialLong(
                array, offset + length - leadPartialSize, revLeadPartial, leadPartialSize);
    }

    private static void reverseLongs(final long[] longs, int longsOffset, int numLongs) {
        int leftIndex = longsOffset;
        int rightIndex = longsOffset + numLongs - 1;

        while (leftIndex < rightIndex) {
            final long leftLongRev = reverseLong(longs[leftIndex]);
            final long rightLongRev = reverseLong(longs[rightIndex]);

            longs[leftIndex] = rightLongRev;
            longs[rightIndex] = leftLongRev;

            leftIndex++;
            rightIndex--;
        }

        if (leftIndex == rightIndex) {
            longs[leftIndex] = reverseLong(longs[leftIndex]);
        }
    }

    private static long reverseLong(final long value) {
        long reverseValue = (value & REVERSE_MASK_32) << 32 | (value & NOT_REVERSE_MASK_32) >>> 32;

        reverseValue = (reverseValue & REVERSE_MASK_16) << 16 | (reverseValue & NOT_REVERSE_MASK_16) >>> 16;
        reverseValue = (reverseValue & REVERSE_MASK_8) << 8 | (reverseValue & NOT_REVERSE_MASK_8) >>> 8;
        reverseValue = (reverseValue & REVERSE_MASK_4) << 4 | (reverseValue & NOT_REVERSE_MASK_4) >>> 4;
        reverseValue = (reverseValue & REVERSE_MASK_2) << 2 | (reverseValue & NOT_REVERSE_MASK_2) >>> 2;
        reverseValue = (reverseValue & REVERSE_MASK_1) << 1 | (reverseValue & NOT_REVERSE_MASK_1) >>> 1;

        return reverseValue;
    }

    public static BitIla create(final BitIla bitIla) {
        return new BitIlaImpl(bitIla);
    }

    private static class BitIlaImpl extends AbstractBitIla {
        private final BitIla bitIla;

        private BitIlaImpl(final BitIla bitIla) {
            Argument.assertNotNull(bitIla, "bitIla");

            this.bitIla = bitIla;
        }

        @Override
        protected void getImpl(long[] array, long arrayOffsetInBits, long ilaStartInBits, long lengthInBits)
                throws IOException {
            bitIla.get(array, arrayOffsetInBits, bitIla.lengthInBits() - ilaStartInBits - lengthInBits, lengthInBits);

            reverse(array, arrayOffsetInBits, lengthInBits);
        }

        @Override
        protected long lengthInBitsImpl() throws IOException {
            return bitIla.lengthInBits();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy