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

net.algart.arrays.PackedBitArraysPer8 Maven / Gradle / Ivy

Go to download

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.

There is a newer version: 1.4.23
Show newest version
/*
 * 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.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;

/**
 * 

Operations with bit arrays packed into byte[] Java arrays.

* *

This is an analog of {@link PackedBitArrays} class, using byte values * for packing bits instead of long values. * AlgART bit arrays do not use this class, but it can be useful while using external modules, * where bits are packed into bytes. * Also this class contains some features for processing bits, packed into bytes in the reverse order: * highest bit first, lowest bit last.

* *

Note that you * should prefer {@link PackedBitArrays} class for processing packed bit arrays * when possible: that class works significantly faster for the same number of packed bits. * *

The maximal length of bit arrays supported by this class is 234-8. * All indexes and lengths passed to methods of this class must not exceed this value. * *

In some methods of this class, it's supposed that the bit #k in a packed byte[] array * is the bit #(k%8) in the byte element array[k/8]. In other words, the bit #k * (false or true value) can be extracted by the following operator:

* *
 * (array[k >>> 3] & (1 << (k & 7))) != 0
 * 
* *

and can be set or cleared by the following operators:

* *
 * if (newValue) // we need to set bit #k to 1
 *     array[k >>> 3] |= 1 << (k & 7);
 * else          // we need to clear bit #k to 0
 *     array[k >>> 3] &= ~(1 << (k & 7));
 * 
* *

You may use {@link #getBit(byte[], long)} and {@link #setBit(byte[], long, boolean)}, implementing * the equivalent code.

* *

The order of bits within a byte, that corresponds to the above specification, is what we call * the normal order.

* *

Other methods of this class support the reverse bit order: * see comments to {@link #getBitInReverseOrder(byte[], long)} and {@link #setBitInReverseOrder(byte[], long, boolean)} * methods. Such methods contain the word "reverse" inside their names.

* *

If any method of this class modifies some portion of an element of a packed byte[] Java array, * i.e. modifies less than all 8 its bits, then all accesses to this byte element are performed * inside a single synchronized block, using the following instruction:

* *
 * synchronized (array) {
 *     // accessing to some element array[k]
 * }
 * 
* *

unless otherwise specified in the method comments. (See an example in comments to {@link #setBit} method.) * If all 8 bits of the element are written, or if the bits are read only, then no synchronization is performed. * Such behavior allows to simultaneously work with non-overlapping fragments of a packed bit array * from several threads (different fragments for different threads), as if it would be a usual Java array. * However, some methods of this class do not perform such synchronization; the names of all such methods has * ...NoSync postfix.

* *

This class cannot be instantiated.

* * @author Daniel Alievsky * @see PackedBitArrays */ public class PackedBitArraysPer8 { private PackedBitArraysPer8() { } private static final byte[] REVERSE = {0x00, -0x80, 0x40, -0x40, 0x20, -0x60, 0x60, -0x20, 0x10, -0x70, 0x50, -0x30, 0x30, -0x50, 0x70, -0x10, 0x08, -0x78, 0x48, -0x38, 0x28, -0x58, 0x68, -0x18, 0x18, -0x68, 0x58, -0x28, 0x38, -0x48, 0x78, -0x08, 0x04, -0x7c, 0x44, -0x3c, 0x24, -0x5c, 0x64, -0x1c, 0x14, -0x6c, 0x54, -0x2c, 0x34, -0x4c, 0x74, -0x0c, 0x0c, -0x74, 0x4c, -0x34, 0x2c, -0x54, 0x6c, -0x14, 0x1c, -0x64, 0x5c, -0x24, 0x3c, -0x44, 0x7c, -0x04, 0x02, -0x7e, 0x42, -0x3e, 0x22, -0x5e, 0x62, -0x1e, 0x12, -0x6e, 0x52, -0x2e, 0x32, -0x4e, 0x72, -0x0e, 0x0a, -0x76, 0x4a, -0x36, 0x2a, -0x56, 0x6a, -0x16, 0x1a, -0x66, 0x5a, -0x26, 0x3a, -0x46, 0x7a, -0x06, 0x06, -0x7a, 0x46, -0x3a, 0x26, -0x5a, 0x66, -0x1a, 0x16, -0x6a, 0x56, -0x2a, 0x36, -0x4a, 0x76, -0x0a, 0x0e, -0x72, 0x4e, -0x32, 0x2e, -0x52, 0x6e, -0x12, 0x1e, -0x62, 0x5e, -0x22, 0x3e, -0x42, 0x7e, -0x02, 0x01, -0x7f, 0x41, -0x3f, 0x21, -0x5f, 0x61, -0x1f, 0x11, -0x6f, 0x51, -0x2f, 0x31, -0x4f, 0x71, -0x0f, 0x09, -0x77, 0x49, -0x37, 0x29, -0x57, 0x69, -0x17, 0x19, -0x67, 0x59, -0x27, 0x39, -0x47, 0x79, -0x07, 0x05, -0x7b, 0x45, -0x3b, 0x25, -0x5b, 0x65, -0x1b, 0x15, -0x6b, 0x55, -0x2b, 0x35, -0x4b, 0x75, -0x0b, 0x0d, -0x73, 0x4d, -0x33, 0x2d, -0x53, 0x6d, -0x13, 0x1d, -0x63, 0x5d, -0x23, 0x3d, -0x43, 0x7d, -0x03, 0x03, -0x7d, 0x43, -0x3d, 0x23, -0x5d, 0x63, -0x1d, 0x13, -0x6d, 0x53, -0x2d, 0x33, -0x4d, 0x73, -0x0d, 0x0b, -0x75, 0x4b, -0x35, 0x2b, -0x55, 0x6b, -0x15, 0x1b, -0x65, 0x5b, -0x25, 0x3b, -0x45, 0x7b, -0x05, 0x07, -0x79, 0x47, -0x39, 0x27, -0x59, 0x67, -0x19, 0x17, -0x69, 0x57, -0x29, 0x37, -0x49, 0x77, -0x09, 0x0f, -0x71, 0x4f, -0x31, 0x2f, -0x51, 0x6f, -0x11, 0x1f, -0x61, 0x5f, -0x21, 0x3f, -0x41, 0x7f, -0x01}; /** * Equivalent to {@link #toLongArray(long[], byte[], long) * toLongArray(null, byteArray, 8L * byteArray.length)}. * * @param byteArray byte array, supposedly storing packed bits according the rules of this class. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if the argument is {@code null}. */ public static long[] toLongArray(byte[] byteArray) { Objects.requireNonNull(byteArray, "Null byte[] array"); return toLongArray(null, byteArray, 8L * (long) byteArray.length); } /** * Equivalent to {@link #toLongArray(long[], byte[], long) * toLongArray(null, byteArray, numberOfBits)}. * * @param byteArray byte array, supposedly storing packed bits according the rules of this class. * @param numberOfBits the number of packed bits. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if the argument is {@code null}. * @throws IllegalArgumentException if numberOfBits is negative or too large: * greater than byteArray.length*8. */ public static long[] toLongArray(byte[] byteArray, long numberOfBits) { return toLongArray(null, byteArray, numberOfBits); } /** * Packs byte[] array byteArray to the result long[] array, * so that the bits, stored in the result array according the rules * of {@link PackedBitArrays} class, will be identical to bits stored in the source byteArray * according the rules of this class. * *

The length of the result array must be not less than * n = {@link PackedBitArrays#packedLength PackedBitArrays.packedLength}(numberOfBits). * The result array may be null, than it will be created automatically as * new long[n]. * The bytes of the result long values are just the bytes of the source array, * packed in little-endian order. * If numberOfBits is not divisible by 64, the unused high bits of the last long * element will be set to zero (even the corresponding unused bits in the last byte of the source * byteArray were non-zero). * The result array (the result argument or a newly created long[] array) * is returned in the result of this method. * * @param result the result array; can be null, then it will be created automatically. * @param byteArray byte array, supposedly storing packed bits according the rules of this class. * @param numberOfBits the number of packed bits. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if byteArray argument is {@code null}. * @throws IllegalArgumentException if numberOfBits is negative or too large: * greater than byteArray.length*8, * or greater than result.length*64 * (when result!=null). */ public static long[] toLongArray(long[] result, byte[] byteArray, long numberOfBits) { Objects.requireNonNull(byteArray, "Null byte[] array"); if (numberOfBits < 0) { throw new IllegalArgumentException("Negative numberOfBits = " + numberOfBits); } final long numberOfBytes = packedLength(numberOfBits); if (numberOfBytes > byteArray.length) { throw new IllegalArgumentException("Too short byte[" + byteArray.length + "] array (packed bits): it must contain at least " + numberOfBytes + " byte elements to contain " + numberOfBits + " bits"); } final int numberOfLongs = (int) PackedBitArrays.packedLength(numberOfBits); if (result == null) { result = new long[numberOfLongs]; } else if (numberOfLongs > result.length) { throw new IllegalArgumentException("Too short result array long[" + result.length + "]: it must contain at least " + numberOfLongs + " elements to store " + numberOfBits + " bits"); } final int numberOfWholeLongs = (int) (numberOfBytes >>> 3); final int alignedLength = numberOfWholeLongs << 3; final ByteBuffer bb = ByteBuffer.wrap(byteArray); bb.order(ByteOrder.LITTLE_ENDIAN); bb.limit(alignedLength); bb.asLongBuffer().get(result, 0, numberOfWholeLongs); if (numberOfBytes > alignedLength) { assert numberOfLongs == numberOfWholeLongs + 1; long v = 0; for (int k = alignedLength, shift = 0; k < numberOfBytes; k++, shift += 8) { v |= ((long) byteArray[k] & 0xFF) << shift; } result[numberOfWholeLongs] = v; } final int cntFinish = (int) (numberOfBits & 63); if (cntFinish > 0) { result[numberOfLongs - 1] &= (1L << cntFinish) - 1; // cntFinish times 1 (from the left) } return result; } /** * Equivalent to {@link #toLongArray(long[], ByteBuffer, long) * toLongArray(null, byteBuffer, 8L * byteBuffer.limit())}. * * @param byteBuffer bytes, supposedly storing packed bits according the rules of this class. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if the argument is {@code null}. */ public static long[] toLongArray(ByteBuffer byteBuffer) { Objects.requireNonNull(byteBuffer, "Null ByteBuffer"); return toLongArray(null, byteBuffer, 8L * (long) byteBuffer.limit()); } /** * Equivalent to {@link #toLongArray(long[], ByteBuffer, long) * toLongArray(null, byteBuffer, numberOfBits)}. * * @param byteBuffer bytes, supposedly storing packed bits according the rules of this class. * @param numberOfBits the number of packed bits. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if the argument is {@code null}. * @throws IllegalArgumentException if numberOfBits is negative or too large: * greater than byteBuffer.limit()*8. */ public static long[] toLongArray(ByteBuffer byteBuffer, long numberOfBits) { return toLongArray(null, byteBuffer, numberOfBits); } /** * Exact analog of {@link #toLongArray(long[], byte[], long)} method, but the original bytes are stored in * ByteBuffer * instead of byte[] array. If b is some byte[] array, * then the following calls are equivalent: *

     *     {@link #toLongArray(long[], ByteBuffer, long) toLongArray}(result, ByteBuffer.wrap(b), numberOfBits)
     *     {@link #toLongArray(long[], byte[], long) toLongArray}(result, b, numberOfBits)
     * 
* *

This method works with a duplicate of the specified ByteBuffer and, so, does not modify * its settings like position and limit. Note that the byte order in the passes ByteBuffer is ignored: * the bytes are always packed into long values in little-endian order.

* * @param result the result array; can be null, then it will be created automatically. * @param byteBuffer bytes, supposedly storing packed bits according the rules of this class. * @param numberOfBits the number of packed bits. * @return long[] array, storing the same packed bits according the rules of {@link PackedBitArrays}. * @throws NullPointerException if byteBuffer argument is {@code null}. * @throws IllegalArgumentException if numberOfBits is negative or too large: * greater than byteBuffer.limit()*8, * or greater than result.length*64 * (when result!=null). */ public static long[] toLongArray(long[] result, ByteBuffer byteBuffer, long numberOfBits) { Objects.requireNonNull(byteBuffer, "Null ByteBuffer"); if (numberOfBits < 0) { throw new IllegalArgumentException("Negative numberOfBits = " + numberOfBits); } ByteBuffer bb = byteBuffer.duplicate(); final long numberOfBytes = packedLength(numberOfBits); if (numberOfBytes > bb.limit()) { throw new IllegalArgumentException("Too short ByteBuffer, " + bb.limit() + " bytes (packed bits): it must contain at least " + numberOfBytes + " byte elements to contain " + numberOfBits + " bits"); } final int numberOfLongs = (int) PackedBitArrays.packedLength(numberOfBits); if (result == null) { result = new long[numberOfLongs]; } else if (numberOfLongs > result.length) { throw new IllegalArgumentException("Too short result array long[" + result.length + "]: it must contain at least " + numberOfLongs + " elements to store " + numberOfBits + " bits"); } final int numberOfWholeLongs = (int) (numberOfBytes >>> 3); final int alignedLength = numberOfWholeLongs << 3; bb.order(ByteOrder.LITTLE_ENDIAN); bb.rewind(); bb.limit(alignedLength); bb.asLongBuffer().get(result, 0, numberOfWholeLongs); bb.limit((int) numberOfBytes); if (numberOfBytes > alignedLength) { assert numberOfLongs == numberOfWholeLongs + 1; long v = 0; for (int k = alignedLength, shift = 0; k < numberOfBytes; k++, shift += 8) { v |= ((long) (bb.get(k) & 0xFF)) << shift; } result[numberOfWholeLongs] = v; } final int cntFinish = (int) (numberOfBits & 63); if (cntFinish > 0) { result[numberOfLongs - 1] &= (1L << cntFinish) - 1; // cntFinish times 1 (from the left) } return result; } /** * Equivalent to {@link #toByteArray(byte[], long[], long) * toByteArray(null, longArray, numberOfBits)}. * * @param longArray long array, supposedly storing packed bits according the rules * of {@link PackedBitArrays} class. * @param numberOfBits the number of packed bits. * @return byte[] array, storing the same packed bits according the rules of this class. * @throws IllegalArgumentException if numberOfBits is negative or * greater than longArray.length*64. * @throws TooLargeArrayException if numberOfBits is greater than 2^34−1 * (then the required length of the returned array * exceeds Java limit 2^31). */ public static byte[] toByteArray(long[] longArray, long numberOfBits) { return toByteArray(null, longArray, numberOfBits); } /** * Unpacks long[] array longArray to the result byte[] array, * so that the bits, stored in the result array according * the rules of this class, will be identical to bits stored in the source longArray * according the rules of {@link PackedBitArrays}. The actual length of the passed bit array should be specified * in numberOfBits argument. * *

The length of the result array must be not less than * n = {@link #packedLength PackedBitArraysPer8.packedLength}(numberOfBits). * The result array may be null, than it will be created automatically as * new byte[n]. * The bytes of the result array * are just the bytes of the source long values, packed in little-endian order. * If numberOfBits is not divisible by 8, the unused high bits of the last byte * element will be set to zero (even the corresponding unused bits in the last long element * of the source longArray were non-zero). * The result array (the result argument or a newly created byte[] array) * is returned in the result of this method. * * @param result the result array; can be null, then it will be created automatically. * @param longArray long array, supposedly storing packed bits according the rules * of {@link PackedBitArrays} class. * @param numberOfBits the number of packed bits. * @return byte[] array, storing the same packed bits according the rules of this class. * @throws IllegalArgumentException if numberOfBits is negative or too large: * greater than longArray.length*64 * or greater than result.length*8 * (when result!=null). * @throws TooLargeArrayException if numberOfBits is greater than 2^34−1 * (then the required length of the returned array * exceeds Java limit 2^31). */ public static byte[] toByteArray(byte[] result, long[] longArray, long numberOfBits) { Objects.requireNonNull(longArray, "Null long[] array (packed bits)"); if (numberOfBits < 0) { throw new IllegalArgumentException("Negative numberOfBits = " + numberOfBits); } final long numberOfLongs = PackedBitArrays.packedLength(numberOfBits); if (numberOfLongs > longArray.length) { throw new IllegalArgumentException("Too short long[" + longArray.length + "] array (packed bits): it must contain at least " + numberOfLongs + " long elements to contain " + numberOfBits + " bits"); } final long numberOfBytes = packedLength(numberOfBits); if (numberOfBytes > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large number of bits " + numberOfBits + " > 2^34-1: cannot pack such a large bit array into byte[] array"); } if (result == null) { result = new byte[(int) numberOfBytes]; } else if (numberOfBytes > result.length) { throw new IllegalArgumentException("Too short result array byte[" + result.length + "]: it must contain at least " + numberOfBytes + " elements to store " + numberOfBits + " bits"); } final int numberOfWholeLongs = (int) (numberOfBytes >>> 3); final int alignedLength = numberOfWholeLongs << 3; final ByteBuffer bb = ByteBuffer.wrap(result); bb.order(ByteOrder.LITTLE_ENDIAN); bb.asLongBuffer().put(longArray, 0, numberOfWholeLongs); if (numberOfBytes > alignedLength) { assert numberOfLongs == numberOfWholeLongs + 1; long v = longArray[numberOfWholeLongs]; for (int k = alignedLength, shift = 0; k < numberOfBytes; k++, shift += 8) { result[k] = (byte) (v >>> shift); } } final int cntFinish = (int) (numberOfBits & 7); if (cntFinish > 0) { result[(int) numberOfBytes - 1] &= (byte) ((1 << cntFinish) - 1); // cntFinish times 1 (from the left) } return result; } /** * Returns numberOfBytes << 3: the maximal number of bits that * can be stored in the specified number of bytes. * * @param numberOfBytes number of packed bytes. * @return 8 * numberOfBytes * @throws TooLargeArrayException if the argument is too large: ≥ 260. * @throws IllegalArgumentException if the argument is negative. */ public static long unpackedLength(long numberOfBytes) { if (numberOfBytes < 0) { throw new IllegalArgumentException("Negative packed length"); } if (numberOfBytes >= 1L << 60) { throw new TooLargeArrayException("Too large packed length: number of unpacked bits >= 2^60"); } return numberOfBytes << 3; } /** * Returns ((long) array.length) << 3: the maximal number of bits that * can be stored in the specified array. * * @param array byte[] array. * @return 8 * (long) array.length * @throws NullPointerException if the argument is {@code null}. */ public static long unpackedLength(byte[] array) { return ((long) array.length) << 3; } /** * Returns (numberOfBits + 7) >>> 3: the minimal number of byte values * allowing to store the specified number of bits. * * @param numberOfBits the number of bits (the length of bit array). * @return (numberOfBits + 7) >>> 3 (the length of corresponding byte[] array). * @throws IllegalArgumentException if the argument is negative. */ public static long packedLength(long numberOfBits) { if (numberOfBits < 0) { throw new IllegalArgumentException("Negative unpacked length"); } return (numberOfBits + 7) >>> 3; // here >>> must be used instead of >>, because numberOfBits+7 can be >Long.MAX_VALUE } /** * Returns the same result as {@link #packedLength(long) packedLength(numberOfBits)} as * a 32-bit int value, or throws {@link TooLargeArrayException} if * that result is greater than Integer.MAX_VALUE. * * @param numberOfBits the number of bits (the length of bit array). * @return (numberOfBits + 7) >>> 3 * (the length of corresponding byte[] array). * @throws IllegalArgumentException if the argument is negative. * @throws TooLargeArrayException if numberOfBits ≥ 234. */ public static int packedLength32(long numberOfBits) { if (numberOfBits < 0) { throw new IllegalArgumentException("Negative unpacked length"); } long result = (numberOfBits + 7) >>> 3; // here >>> must be used instead of >>, because numberOfBits+63 can be >Long.MAX_VALUE if (result > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large number of bits " + numberOfBits + ": number of packed longs " + result + " >= 2^31"); } return (int) result; } /** * Equivalent of {@link #packedLength32(long)} for int argument. * * @param numberOfBits the number of bits (the length of bit array). * @return (numberOfBits + 7) >>> 3 * (the length of corresponding byte[] array). * @throws IllegalArgumentException if the argument is negative. */ public static int packedLength32(int numberOfBits) { if (numberOfBits < 0) { throw new IllegalArgumentException("Negative unpacked length"); } return (numberOfBits + 7) >>> 3; // here >>> must be used instead of >>, because numberOfBits+63 may be >Integer.MAX_VALUE } /** * Returns the bit #index in the packed src bit array. * Equivalent to the following expression:

     * (src[(int)(index >>> 3)] & (1 << (index & 7))) != 0;
     * 
* * @param src the source array (bits are packed in byte values). * @param index index of the returned bit. * @return the bit at the specified index. * @throws NullPointerException if src is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. */ public static boolean getBit(byte[] src, long index) { return (src[(int) (index >>> 3)] & (1 << ((int) index & 7))) != 0; } /** * Sets the bit #index in the packed dest bit array. * Equivalent to the following operators:
     * synchronized (dest) {
     *     if (value)
     *         dest[(int)(index >>> 3)] |= 1 << (index & 7);
     *     else
     *         dest[(int)(index >>> 3)] &= ~(1 << (index & 7));
     * }
     * 
* * @param dest the destination array (bits are packed in byte values). * @param index index of the written bit. * @param value new bit value. * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void setBit(byte[] dest, long index, boolean value) { synchronized (dest) { if (value) dest[(int) (index >>> 3)] |= (byte) (1 << ((int) index & 7)); else dest[(int) (index >>> 3)] &= (byte) ~(1 << ((int) index & 7)); } } /** * Sets the bit #index in the packed dest bit array without synchronization. * May be used instead of {@link #setBit(byte[], long, boolean)}, if you are not planning to call * this method from different threads for the same dest array. * Equivalent to the following operators:
     *     if (value)
     *         dest[(int)(index >>> 3)] |= 1 << (index & 7);
     *     else
     *         dest[(int)(index >>> 3)] &= ~(1 << (index & 7));
     * }
     * 
* * @param dest the destination array (bits are packed in byte values). * @param index index of the written bit. * @param value new bit value. * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. */ public static void setBitNoSync(byte[] dest, long index, boolean value) { if (value) dest[(int) (index >>> 3)] |= (byte) (1 << ((int) index & 7)); else dest[(int) (index >>> 3)] &= (byte) ~(1 << ((int) index & 7)); } /** * Returns the sequence of count bits (maximum 64 bits), starting from the bit #srcPos, * in the packed src bit array. * *

More precisely, the bit #(srcPos+k) will be returned in the bit #k of the returned * long value R: the first bit #srcPos will be equal to * R&1, * the following bit #(srcPos+1) will be equal to (R>>1)&1, etc. * If count=0, the result is 0.

* *

The same result can be calculated using the following loop * (for correct count in the range 0..64):

* *
     *      long result = 0;
     *      for (int k = 0; k < count; k++) {
     *          final long bit = {@link #getBit(byte[], long) PackedBitArraysPer8.getBit}(src, srcPos + k) ? 1L : 0L;
     *          result |= bit << k;
     *      }
* *

But this function works significantly faster, if count is greater than 1.

* *

Note: unlike the loop listed above, this function does not throw exception for too large indexes of bits * after the end of the array (≥8*src.length); * instead, all bits outside the array are considered zero. * (But negative indexes are not allowed.)

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be unpacked (must be in range 0..64). * @return the sequence of count bits. * @throws NullPointerException if src argument is {@code null}. * @throws IndexOutOfBoundsException if srcPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. * @see JArrays#getBytes8(byte[], int, int) */ public static long getBits64(byte[] src, long srcPos, int count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IndexOutOfBoundsException("Negative srcPos argument: " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot get > 64 bits in getBits64 method"); } final long srcPosDiv8 = srcPos >>> 3; if (count == 0 || srcPosDiv8 >= src.length) { return 0; } long result = 0; int sPosRem = (int) (srcPos & 7); int sPos = (int) srcPosDiv8; int shift = 0; for (; ; ) { final int bitsLeft = 8 - sPosRem; if (count > bitsLeft) { final long actualBits = (src[sPos] & 0xFFL) >>> sPosRem; // sPosRem=5, bitsLeft=3: // (01234567) // abcdefgh // fgh00000 result |= actualBits << shift; count -= bitsLeft; shift += bitsLeft; sPos++; if (sPos >= src.length) { break; } sPosRem = 0; } else { final long actualBits = (src[sPos] & (0xFFL >>> (bitsLeft - count))) >>> sPosRem; // sPosRem=5, bitsLeft=3, count=2: // (01234567) // abcdefgh // 11111110 0xFFL >>> (bitsLeft - count) // abcdefg0 // fg000000 result |= actualBits << shift; break; } } return result; } /** * Sets the sequence of count bits (maximum 64 bits), starting from the bit #destPos, * in the packed dest bit array. This is the reverse operation of * {@link #getBits64(byte[], long, int)}. * *

This function is equivalent to the following loop * (for correct count in the range 0..64):

* *
     *      for (int k = 0; k < count; k++) {
     *          final long bit = (bits >>> k) & 1L;
     *          {@link #setBit(byte[], long, boolean) PackedBitArraysPer8.setBit}(dest, destPos + k, bit != 0);
     *      }
* *

But this function works significantly faster, if count is greater than 1.

* *

Note: unlike the loop listed above, this function does not throw exception for too large indexes of bits * after the end of the array (≥8*dest.length); * instead, extra bits outside the array are just ignored. * (But negative indexes are not allowed.)

* * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param bits sequence of new bits to be copied into the destination array. * @param count the number of bits to be written (must be in range 0..64). * @throws NullPointerException if dest argument is {@code null}. * @throws IndexOutOfBoundsException if destPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. * @see JArrays#setBytes8(byte[], int, long, int) */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void setBits64(byte[] dest, long destPos, long bits, int count) { Objects.requireNonNull(dest, "Null dest"); if (destPos < 0) { throw new IndexOutOfBoundsException("Negative destPos argument: " + destPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot set > 64 bits in setBits64 method"); } final long destPosDiv8 = destPos >>> 3; if (count == 0 || destPosDiv8 >= dest.length) { return; } int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = count; maskStart &= (1 << (dPosRem + count)) - 1; // &= dPosRem+cntStart times 1 (from the left) } int dPos = (int) destPosDiv8; synchronized (dest) { if (cntStart > 0) { dest[dPos] = (byte) (((bits << dPosRem) & maskStart) | (dest[dPos] & ~maskStart)); dPos++; count -= cntStart; bits >>>= cntStart; } while (count >= 8) { if (dPos >= dest.length) { return; } dest[dPos++] = (byte) bits; count -= 8; bits >>>= 8; } if (count > 0 && dPos < dest.length) { int maskFinish = (1 << count) - 1; // count times 1 (from the left) dest[dPos] = (byte) ((bits & maskFinish) | (dest[dPos] & ~maskFinish)); } } } /** * Sets the sequence of count bits (maximum 64 bits), starting from the bit #destPos, * in the packed dest bit array, without synchronization. * May be used instead of {@link #setBits64(byte[], long, long, int)}, if you are not planning to call * this method from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param bits sequence of new bits to be copied into the destination array. * @param count the number of bits to be written (must be in range 0..64). * @throws NullPointerException if dest argument is {@code null}. * @throws IndexOutOfBoundsException if destPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. */ public static void setBits64NoSync(byte[] dest, long destPos, long bits, int count) { Objects.requireNonNull(dest, "Null dest"); if (destPos < 0) { throw new IndexOutOfBoundsException("Negative destPos argument: " + destPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot set > 64 bits in setBits64NoSync method"); } final long destPosDiv8 = destPos >>> 3; if (count == 0 || destPosDiv8 >= dest.length) { return; } int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = count; maskStart &= (1 << (dPosRem + count)) - 1; // &= dPosRem+cntStart times 1 (from the left) } int dPos = (int) destPosDiv8; if (cntStart > 0) { dest[dPos] = (byte) (((bits << dPosRem) & maskStart) | (dest[dPos] & ~maskStart)); dPos++; count -= cntStart; bits >>>= cntStart; } while (count >= 8) { if (dPos >= dest.length) { return; } dest[dPos++] = (byte) bits; count -= 8; bits >>>= 8; } if (count > 0 && dPos < dest.length) { int maskFinish = (1 << count) - 1; // count times 1 (from the left) dest[dPos] = (byte) ((bits & maskFinish) | (dest[dPos] & ~maskFinish)); } } /** * Returns the bit #index in the packed src bit array * for a case, when the bits are packed in each byte in the reverse order: * highest bit first, lowest bit last. * Equivalent to the following expression:
     * (src[(int)(index >>> 3)] & (1 << (7 - (index & 7)))) != 0;
     * 
* *

This bit order is used, for example, in TIFF format when storing binary images or * image with less than 8 bits per channel.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param index index of the returned bit. * @return the bit at the specified index. * @throws NullPointerException if src is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. * @see #reverseBitOrder(byte[], int, byte[], int, int) */ public static boolean getBitInReverseOrder(byte[] src, long index) { return (src[(int) (index >>> 3)] & (1 << (7 - ((int) index & 7)))) != 0; } /** * Sets the bit #index in the packed dest bit array * for a case, when the bits are packed in each byte in the reverse order: * highest bit first, lowest bit last. * Equivalent to the following operators:
     * synchronized (dest) {
     *     final int bitIndex = 7 - ((int) index & 7);
     *     if (value)
     *         dest[(int)(index >>> 3)] |= (1 << bitIndex);
     *     else
     *         dest[(int)(index >>> 3)] &= ~(1 << bitIndex);
     * }
     * 
* * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param index index of the written bit. * @param value new bit value. * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. * @see #reverseBitOrder(byte[], int, int) */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void setBitInReverseOrder(byte[] dest, long index, boolean value) { synchronized (dest) { final int bitIndex = 7 - ((int) index & 7); if (value) dest[(int) (index >>> 3)] |= (byte) (1 << bitIndex); else dest[(int) (index >>> 3)] &= (byte) ~(1 << bitIndex); } } /** * Sets the bit #index in the packed dest bit array * for a case, when the bits are packed in each byte in the reverse order, * without synchronization. * May be used instead of {@link #setBitInReverseOrder(byte[], long, boolean)}, if you are not planning to call * this method from different threads for the same dest array. * Equivalent to the following operators:
     *     final int bitIndex = 7 - ((int) index & 7);
     *     if (value)
     *         dest[(int)(index >>> 3)] |= (1 << bitIndex);
     *     else
     *         dest[(int)(index >>> 3)] &= ~(1 << bitIndex);
     * }
     * 
* * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param index index of the written bit. * @param value new bit value. * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if this method cause access of data outside array bounds. */ public static void setBitInReverseOrderNoSync(byte[] dest, long index, boolean value) { final int bitIndex = 7 - ((int) index & 7); if (value) dest[(int) (index >>> 3)] |= (byte) (1 << bitIndex); else dest[(int) (index >>> 3)] &= (byte) ~(1 << bitIndex); } /** * Returns the sequence of count bits (maximum 64 bits), starting from the bit #srcPos, * in the packed src bit array for a case, when the bits are packed in each byte in the reverse order: * highest bit first, lowest bit last. * *

More precisely, the bit #(srcPos+k), that can be read by the call * {@link #getBitInReverseOrder(byte[] src, long index) * getBitInReverseOrder}(src, srcPos+k), * will be returned in the bit #(count-1-k) (in direct order) of the returned * long value R, i.e. it is equal to (R>>(count-1-k))&1. * If count=30, the result is 0.

* *

The same result can be calculated using the following loop:

* *
     *      long result = 0;
     *      for (int k = 0; k < count; k++) {
     *          final long bit = {@link #getBitInReverseOrder(byte[], long)
     *              PackedBitArraysPer8.getBitInReverseOrder}(src, srcPos + k) ? 1L : 0L;
     *          result |= bit << (count - 1 - k);
     *      }
* *

But this function works significantly faster, if count is greater than 1.

* *

Note: unlike the loop listed above, this function does not throw exception for too large indexes of bits * after the end of the array (≥8*src.length); instead, all bits outside the array are considered * zero. * (But negative indexes are not allowed.)

* *

This bit order is used, for example, in TIFF format when storing binary images or * image with less than 8 bits per channel.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be unpacked (must be in range 0..64). * @return the sequence of count bits. * @throws NullPointerException if src argument is {@code null}. * @throws IndexOutOfBoundsException if srcPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. * @see JArrays#getBytes8InBigEndianOrder(byte[], int, int) */ public static long getBits64InReverseOrder(byte[] src, long srcPos, int count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IndexOutOfBoundsException("Negative srcPos argument: " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot get > 64 bits in getBits64 method"); } final long srcPosDiv8 = srcPos >>> 3; if (count == 0 || srcPosDiv8 >= src.length) { return 0; } long result = 0; int sPosRem = (int) (srcPos & 7); int sPos = (int) srcPosDiv8; for (; ; ) { final int bitsLeft = 8 - sPosRem; if (count > bitsLeft) { final long actualBits = (long) src[sPos] & (0xFFL >>> sPosRem); // sPosRem=5, bitsLeft=3: // (76543210) // abcdefgh // 00000fgh result = (result << bitsLeft) | actualBits; count -= bitsLeft; sPos++; sPosRem = 0; } else { final long actualBits = (long) src[sPos] & ~(0xFF00 >>> sPosRem) & 0xFF; // sPosRem=5, bitsLeft=3, count=2: // (76543210) // abcdefgh // 11111000 0xFF00 >>> sPosRem // 00000111 ~(0xFF00 >>> sPosRem) // 00000fgh result = (result << count) | (actualBits >> (bitsLeft - count)); // 000000fg break; } if (sPos >= src.length) { return result << count; } } return result; } /** * Sets the sequence of count bits (maximum 64 bits), starting from the bit #destPos, * in the packed dest bit array * for a case, when the bits are packed in each byte in the reverse order. * This is the reverse operation of {@link #getBits64InReverseOrder(byte[], long, int)}. * *

This function is equivalent to the following loop:

* *
     *      for (int k = 0; k < count; k++) {
     *          final long bit = (bits >>> (count - 1 - k)) & 1L;
     *          {@link #setBitInReverseOrder(byte[], long, boolean)
     *          PackedBitArraysPer8.setBitInReverseOrder}(dest, destPos + k, bit != 0);
     *      }
* *

But this function works significantly faster, if count is greater than 1.

* *

Note: unlike the loop listed above, this function does not throw exception for too large indexes of bits * after the end of the array (≥8*dest.length); * instead, extra bits outside the array are just ignored. * (But negative indexes are not allowed.)

* * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param bits sequence of new bits (in reverse order) to be copied into the destination array. * @param count the number of bits to be written (must be in range 0..64). * @throws NullPointerException if dest argument is {@code null}. * @throws IndexOutOfBoundsException if destPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. * @see JArrays#setBytes8InBigEndianOrder(byte[], int, long, int) */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void setBits64InReverseOrder(byte[] dest, long destPos, long bits, int count) { Objects.requireNonNull(dest, "Null dest"); if (destPos < 0) { throw new IndexOutOfBoundsException("Negative destPos argument: " + destPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot set > 64 bits in setBits64InReverseOrder method"); } final long destPosDiv8 = destPos >>> 3; if (count == 0 || destPosDiv8 >= dest.length) { return; } int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } int dPos = (int) destPosDiv8; synchronized (dest) { if (cntStart > 0) { // bits #count-cntStart...#count-1 of "bits" argument should be copied to // bits #8-dPosRem-cntStart..#8-dPosRem-1 (where 8-dPosRem = original cntStart) // This means shifting >>> (count-1)-(8-dPosRem-1) int shift = count - (8 - dPosRem); long v = shift >= 0 ? bits >>> shift : bits << -shift; dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); dPos++; count -= cntStart; } while (count >= 8) { if (dPos >= dest.length) { return; } count -= 8; dest[dPos++] = (byte) (bits >>> count); } if (count > 0 && dPos < dest.length) { int maskFinish = 0xFF00 >>> count; // count times 1 (from the highest bit) // We still did not use only the count lowest bits // #0...#count-3; they should be copied to // #7...#(8-count) bits ot dest[dPos] dest[dPos] = (byte) (((bits << (8 - count)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } /** * Sets the sequence of count bits (maximum 64 bits), starting from the bit #destPos, * in the packed dest bit array * for a case, when the bits are packed in each byte in the reverse order, * without synchronization. * May be used instead of {@link #setBits64InReverseOrder(byte[], long, long, int)}, * if you are not planning to call * this method from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param bits sequence of new bits (in reverse order) to be copied into the destination array. * @param count the number of bits to be written (must be in range 0..64). * @throws NullPointerException if dest argument is {@code null}. * @throws IndexOutOfBoundsException if destPos < 0. * @throws IllegalArgumentException if count < 0 or count > 64. */ public static void setBits64InReverseOrderNoSync(byte[] dest, long destPos, long bits, int count) { Objects.requireNonNull(dest, "Null dest"); if (destPos < 0) { throw new IndexOutOfBoundsException("Negative destPos argument: " + destPos); } if (count < 0) { throw new IllegalArgumentException("Negative count argument: " + count); } if (count > 64) { throw new IllegalArgumentException("Too large count argument: " + count + "; we cannot set > 64 bits in setBits64InReverseOrderNoSync method"); } final long destPosDiv8 = destPos >>> 3; if (count == 0 || destPosDiv8 >= dest.length) { return; } int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = count; maskStart &= (0xFF00 >>> (dPosRem + cntStart)); // &= dPosRem+cntStart times 1 (from the highest bit) } int dPos = (int) destPosDiv8; if (cntStart > 0) { // bits #count-cntStart...#count-1 of "bits" argument should be copied to // bits #8-dPosRem-cntStart..#8-dPosRem-1 (where 8-dPosRem = original cntStart) // This means shifting >>> (count-1)-(8-dPosRem-1) int shift = count - (8 - dPosRem); long v = shift >= 0 ? bits >>> shift : bits << -shift; dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); dPos++; count -= cntStart; } while (count >= 8) { if (dPos >= dest.length) { return; } count -= 8; dest[dPos++] = (byte) (bits >>> count); } if (count > 0 && dPos < dest.length) { int maskFinish = 0xFF00 >>> count; // count times 1 (from the highest bit) // We still did not use only the count lowest bits // #0...#count-3; they should be copied to // #7...#(8-count) bits ot dest[dPos] dest[dPos] = (byte) (((bits << (8 - count)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } /** * Copies count bits, packed in src array, starting from the bit #srcPos, * to packed dest array, starting from the bit #destPos. * *

This method works correctly even if src == dest * and the copied areas overlap, * i.e. if Math.abs(destPos - srcPos) < count. * More precisely, in this case the copying is performed as if the * bits at positions srcPos..srcPos+count-1 * were first unpacked to a temporary boolean[] array with count elements * and then the contents of the temporary array were packed into positions * destPos..destPos+count-1. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void copyBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } //Start_reverseOrder !! this comment is necessary for preprocessing by Repeater !! if (src == dest && srcPos <= destPos && srcPos + count > destPos) //End_reverseOrder !! this comment is necessary for preprocessing by Repeater !! { // overlap possible if (sPosRem == dPosRem) { //Start_nothingToDo !! this comment is necessary for preprocessing by Repeater !! if (sPos == dPos) { return; // nothing to do } //End_nothingToDo !! this comment is necessary for preprocessing by Repeater !! final int sPosStart = sPos; final int dPosStart = dPos; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos + cnt] = (byte) ((src[sPos + cnt] & maskFinish) | (dest[dPos + cnt] & ~maskFinish)); } } System.arraycopy(src, sPos, dest, dPos, cnt); if (cntStart > 0) { synchronized (dest) { dest[dPosStart] = (byte) ((src[sPosStart] & maskStart) | (dest[dPosStart] & ~maskStart)); } } } else { final int shift = dPosRem - sPosRem; final int sPosStart = sPos; final int dPosStart = dPos; final int sPosRemStart = sPosRem; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element sPosRem += cntStart; } else { sPos++; sPosRem = (sPosRem + cntStart) & 7; } // we suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more count -= cntStart; dPos++; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] int cnt = (int) (count >>> 3); final long dPosMin = dPos; sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); final int sPosRem8 = 8 - sPosRem; int sPrev; if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = (sPrev = (src[sPos] & 0xFF)) >>> sPosRem; } else { v = ((sPrev = (src[sPos] & 0xFF)) >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } else { //Start_sPrev !! this comment is necessary for preprocessing by Repeater !! sPrev = (src[sPos] & 0xFF); // IndexOutOfBoundException is impossible here, because there is one of the following situations: // 1) cnt > 0, then src[sPos] is really necessary in the following loop; // 2) cnt == 0 and cntStart > 0, then src[sPos] will be necessary for making dest[dPosStart]. // All other situations are impossible here: // 3) cntFinish > 0: it was processed above in "if (cntFinish > 0)..." branch; // 4) cntStart == 0, cntFinish == 0 and cnt == 0, i.e. count == 0: it's impossible // in this branch of all algorithm (overlap is impossible when count == 0). //End_sPrev !! this comment is necessary for preprocessing by Repeater !! } while (dPos > dPosMin) { // cnt times --sPos; --dPos; dest[dPos] = (byte) ((sPrev << sPosRem8) | ((sPrev = (src[sPos] & 0xFF)) >>> sPosRem)); } if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end int v; if (sPosRemStart + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (src[sPosStart] & 0xFF) << shift; else v = (src[sPosStart] & 0xFF) >>> -shift; } else { v = ((src[sPosStart] & 0xFF) >>> -shift) | ((src[sPosStart + 1] & 0xFF) << (8 + shift)); } synchronized (dest) { dest[dPosStart] = (byte) ((v & maskStart) | (dest[dPosStart] & ~maskStart)); } } } } else { // usual case if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((src[sPos] & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); System.arraycopy(src, sPos, dest, dPos, cnt); sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) ((src[sPos] & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } } /** * Equivalent to {@link #copyBits(byte[], long, byte[], long, long)} method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #copyBits}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void copyBitsNoSync(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } //Start_reverseOrder !! this comment is necessary for preprocessing by Repeater !! if (src == dest && srcPos <= destPos && srcPos + count > destPos) //End_reverseOrder !! this comment is necessary for preprocessing by Repeater !! { // overlap possible if (sPosRem == dPosRem) { //Start_nothingToDo !! this comment is necessary for preprocessing by Repeater !! if (sPos == dPos) { return; // nothing to do } //End_nothingToDo !! this comment is necessary for preprocessing by Repeater !! final int sPosStart = sPos; final int dPosStart = dPos; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) dest[dPos + cnt] = (byte) ((src[sPos + cnt] & maskFinish) | (dest[dPos + cnt] & ~maskFinish)); } System.arraycopy(src, sPos, dest, dPos, cnt); if (cntStart > 0) { dest[dPosStart] = (byte) ((src[sPosStart] & maskStart) | (dest[dPosStart] & ~maskStart)); } } else { final int shift = dPosRem - sPosRem; final int sPosStart = sPos; final int dPosStart = dPos; final int sPosRemStart = sPosRem; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element sPosRem += cntStart; } else { sPos++; sPosRem = (sPosRem + cntStart) & 7; } // we suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more count -= cntStart; dPos++; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] int cnt = (int) (count >>> 3); final long dPosMin = dPos; sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); final int sPosRem8 = 8 - sPosRem; int sPrev; if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = (sPrev = (src[sPos] & 0xFF)) >>> sPosRem; } else { v = ((sPrev = (src[sPos] & 0xFF)) >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } else { //Start_sPrev !! this comment is necessary for preprocessing by Repeater !! sPrev = (src[sPos] & 0xFF); // IndexOutOfBoundException is impossible here, because there is one of the following situations: // 1) cnt > 0, then src[sPos] is really necessary in the following loop; // 2) cnt == 0 and cntStart > 0, then src[sPos] will be necessary for making dest[dPosStart]. // All other situations are impossible here: // 3) cntFinish > 0: it was processed above in "if (cntFinish > 0)..." branch; // 4) cntStart == 0, cntFinish == 0 and cnt == 0, i.e. count == 0: it's impossible // in this branch of all algorithm (overlap is impossible when count == 0). //End_sPrev !! this comment is necessary for preprocessing by Repeater !! } while (dPos > dPosMin) { // cnt times --sPos; --dPos; dest[dPos] = (byte) ((sPrev << sPosRem8) | ((sPrev = (src[sPos] & 0xFF)) >>> sPosRem)); } if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end int v; if (sPosRemStart + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (src[sPosStart] & 0xFF) << shift; else v = (src[sPosStart] & 0xFF) >>> -shift; } else { v = ((src[sPosStart] & 0xFF) >>> -shift) | ((src[sPosStart + 1] & 0xFF) << (8 + shift)); } dest[dPosStart] = (byte) ((v & maskStart) | (dest[dPosStart] & ~maskStart)); } } } else { // usual case if (sPosRem == dPosRem) { if (cntStart > 0) { dest[dPos] = (byte) (((src[sPos] & 0xFF) & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); System.arraycopy(src, sPos, dest, dPos, cnt); sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) dest[dPos] = (byte) (((src[sPos] & 0xFF) & maskFinish) | (dest[dPos] & ~maskFinish)); } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Copies count bits, packed in src array, starting from the bit #srcPos, * to packed dest array, starting from the bit #destPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and the copied areas overlap, * i.e. if Math.abs(destPos - srcPos) < count. * More precisely, in this case the copying is performed as if the * bits at positions srcPos..srcPos+count-1 * were first unpacked to a temporary boolean[] array with count elements * and then the contents of the temporary array were packed into positions * destPos..destPos+count-1 (in both cases in the reverse order). * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void copyBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + cntStart)); // &= dPosRem+cntStart times 1 (from the highest bit) } //Start_reverseOrder !! this comment is necessary for preprocessing by Repeater !! if (src == dest && srcPos <= destPos && srcPos + count > destPos) //End_reverseOrder !! this comment is necessary for preprocessing by Repeater !! { // overlap possible if (sPosRem == dPosRem) { //Start_nothingToDo !! this comment is necessary for preprocessing by Repeater !! if (sPos == dPos) { return; // nothing to do } //End_nothingToDo !! this comment is necessary for preprocessing by Repeater !! final int sPosStart = sPos; final int dPosStart = dPos; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos + cnt] = (byte) ((src[sPos + cnt] & maskFinish) | (dest[dPos + cnt] & ~maskFinish)); } } System.arraycopy(src, sPos, dest, dPos, cnt); if (cntStart > 0) { synchronized (dest) { dest[dPosStart] = (byte) ((src[sPosStart] & maskStart) | (dest[dPosStart] & ~maskStart)); } } } else { final int shift = dPosRem - sPosRem; final int sPosStart = sPos; final int dPosStart = dPos; final int sPosRemStart = sPosRem; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element sPosRem += cntStart; } else { sPos++; sPosRem = (sPosRem + cntStart) & 7; } // we suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more count -= cntStart; dPos++; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] int cnt = (int) (count >>> 3); final long dPosMin = dPos; sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); final int sPosRem8 = 8 - sPosRem; int sPrev; if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = (sPrev = (src[sPos] & 0xFF)) << sPosRem; } else { v = ((sPrev = (src[sPos] & 0xFF)) << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } else { sPrev = (src[sPos] & 0xFF); // IndexOutOfBoundException is impossible here, because there is one of the following situations: // 1) cnt > 0, then src[sPos] is really necessary in the following loop; // 2) cnt == 0 and cntStart > 0, then src[sPos] will be necessary for making dest[dPosStart]. // All other situations are impossible here: // 3) cntFinish > 0: it was processed above in "if (cntFinish > 0)..." branch; // 4) cntStart == 0, cntFinish == 0 and cnt == 0, i.e. count == 0: it's impossible // in this branch of all algorithm (overlap is impossible when count == 0). } while (dPos > dPosMin) { // cnt times --sPos; --dPos; dest[dPos] = (byte) ((sPrev >>> sPosRem8) | ((sPrev = (src[sPos] & 0xFF)) << sPosRem)); } if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end int v; if (sPosRemStart + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (src[sPosStart] & 0xFF) >>> shift; else v = (src[sPosStart] & 0xFF) << -shift; } else { v = ((src[sPosStart] & 0xFF) << -shift) | ((src[sPosStart + 1] & 0xFF) >>> (8 + shift)); } synchronized (dest) { dest[dPosStart] = (byte) ((v & maskStart) | (dest[dPosStart] & ~maskStart)); } } } } else { // usual case if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((src[sPos] & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); System.arraycopy(src, sPos, dest, dPos, cnt); sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) ((src[sPos] & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } } /** * Equivalent to {@link #copyBitsInReverseOrder(byte[], long, byte[], long, long)} method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #copyBitsInReverseOrder}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void copyBitsInReverseOrderNoSync(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + cntStart)); // &= dPosRem+cntStart times 1 (from the highest bit) } //Start_reverseOrder !! this comment is necessary for preprocessing by Repeater !! if (src == dest && srcPos <= destPos && srcPos + count > destPos) //End_reverseOrder !! this comment is necessary for preprocessing by Repeater !! { // overlap possible if (sPosRem == dPosRem) { //Start_nothingToDo !! this comment is necessary for preprocessing by Repeater !! if (sPos == dPos) { return; // nothing to do } //End_nothingToDo !! this comment is necessary for preprocessing by Repeater !! final int sPosStart = sPos; final int dPosStart = dPos; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) dest[dPos + cnt] = (byte) ((src[sPos + cnt] & maskFinish) | (dest[dPos + cnt] & ~maskFinish)); } System.arraycopy(src, sPos, dest, dPos, cnt); if (cntStart > 0) { dest[dPosStart] = (byte) ((src[sPosStart] & maskStart) | (dest[dPosStart] & ~maskStart)); } } else { final int shift = dPosRem - sPosRem; final int sPosStart = sPos; final int dPosStart = dPos; final int sPosRemStart = sPosRem; if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element sPosRem += cntStart; } else { sPos++; sPosRem = (sPosRem + cntStart) & 7; } // we suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more count -= cntStart; dPos++; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] int cnt = (int) (count >>> 3); final long dPosMin = dPos; sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); final int sPosRem8 = 8 - sPosRem; int sPrev; if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = (sPrev = (src[sPos] & 0xFF)) << sPosRem; } else { v = ((sPrev = (src[sPos] & 0xFF)) << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } else { sPrev = (src[sPos] & 0xFF); // IndexOutOfBoundException is impossible here, because there is one of the following situations: // 1) cnt > 0, then src[sPos] is really necessary in the following loop; // 2) cnt == 0 and cntStart > 0, then src[sPos] will be necessary for making dest[dPosStart]. // All other situations are impossible here: // 3) cntFinish > 0: it was processed above in "if (cntFinish > 0)..." branch; // 4) cntStart == 0, cntFinish == 0 and cnt == 0, i.e. count == 0: it's impossible // in this branch of all algorithm (overlap is impossible when count == 0). } while (dPos > dPosMin) { // cnt times --sPos; --dPos; dest[dPos] = (byte) ((sPrev >>> sPosRem8) | ((sPrev = (src[sPos] & 0xFF)) << sPosRem)); } if (cntStart > 0) { // here we correct indexes only: we delay actual access until the end int v; if (sPosRemStart + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (src[sPosStart] & 0xFF) >>> shift; else v = (src[sPosStart] & 0xFF) << -shift; } else { v = ((src[sPosStart] & 0xFF) << -shift) | ((src[sPosStart + 1] & 0xFF) >>> (8 + shift)); } dest[dPosStart] = (byte) ((v & maskStart) | (dest[dPosStart] & ~maskStart)); } } } else { // usual case if (sPosRem == dPosRem) { if (cntStart > 0) { dest[dPos] = (byte) ((src[sPos] & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; dPos++; sPos++; } int cnt = (int) (count >>> 3); System.arraycopy(src, sPos, dest, dPos, cnt); sPos += cnt; dPos += cnt; int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) dest[dPos] = (byte) ((src[sPos] & maskFinish) | (dest[dPos] & ~maskFinish)); } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Copies count bits, packed in src array in the reverse order, * starting from the bit #srcPos, to packed dest array, stored in the normal order, * starting from the bit #destPos. * *

The same action may be performed by the following operators:

*
     *     byte[] copy = {@link #reverseBitOrder(byte[]) PackedBitArraysPer8.reverseBitOrder}(src);
     *     {@link #copyBits PackedBitArraysPer8.copyBits}(dest, destPos, copy, srcPos, count);
     * 
*

but without necessity to copy src bytes into a new array. * *

Warning: unlike {@link #copyBits(byte[], long, byte[], long, long)}, * this method does not provide correct processing the situation when src == dest * and the copied areas overlap. However, this method still does work correctly if * src == dest and destPos ≤ srcPos. In particular, * this method allows you to invert the bit order in place: the following call

*
     *      PackedBitArraysPer8.copyBitsFromReverseToNormalOrder(dest, 0, dest, 0, dest.length * 8);
     * 
*

is equivalent to {@link #reverseBitOrderInPlace(byte[]) * PackedBitArraysPer8.reverseBitOrderInPlace}(dest).

* * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. * @see #copyBits(byte[], long, byte[], long, long) * @see #copyBitsFromNormalToReverseOrder(byte[], long, byte[], long, long) */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void copyBitsFromReverseToNormalOrder( byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } // Note: overlapping IS NOT supported! if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskStart) | (dest[dPos] & ~maskStart)); } // - only 8 low bits are stored count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = REVERSE[src[sPos] & 0xFF]; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskFinish) | (dest[dPos] & ~maskFinish)); } // - only 8 low bits are stored } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << shift; else v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((REVERSE[src[sPos] & 0xFF] & 0xFF) >>> -shift) | ((sNext = (REVERSE[src[sPos + 1] & 0xFF] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = REVERSE[src[sPos] & 0xFF] & 0xFF; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext >>> sPosRem) | ((sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((REVERSE[src[sPos + 1] & 0xFF] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Equivalent to {@link #copyBitsFromReverseToNormalOrder(byte[], long, byte[], long, long)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #copyBitsFromReverseToNormalOrder}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void copyBitsFromReverseToNormalOrderNoSync( byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } // Note: overlapping IS NOT supported! if (sPosRem == dPosRem) { if (cntStart > 0) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskStart) | (dest[dPos] & ~maskStart)); // - only 8 low bits are stored count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = REVERSE[src[sPos] & 0xFF]; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskFinish) | (dest[dPos] & ~maskFinish)); // - only 8 low bits are stored } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << shift; else v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((REVERSE[src[sPos] & 0xFF] & 0xFF) >>> -shift) | ((sNext = (REVERSE[src[sPos + 1] & 0xFF] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = REVERSE[src[sPos] & 0xFF] & 0xFF; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext >>> sPosRem) | ((sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((REVERSE[src[sPos + 1] & 0xFF] & 0xFF) << sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } /** * Copies count bits, packed in src array in the normal order, * starting from the bit #srcPos, to packed dest array, stored in the reverse order, * starting from the bit #destPos. * *

The same action may be performed by the following simple loop:

*
     *      byte[] copy = pSrc.clone();
     *      for (int k = 0; k < count; k++) {
     *          final boolean bit = {@link #getBit
     *              PackedBitArraysPer8.getBit}(copy, srcPos + k);
     *          {@link #setBitInReverseOrder
     *              PackedBitArraysPer8.setBitInReverseOrder}(dest, destPos + k, bit);
     *      }
     * 
*

but this method works much faster. * *

Warning: unlike {@link #copyBits(byte[], long, byte[], long, long)}, * this method does not provide correct processing the situation when src == dest * and the copied areas overlap. However, this method still does work correctly if * src == dest and destPos ≤ srcPos. In particular, * this method allows you to invert the bit order in place: the following call

*
     *      PackedBitArraysPer8.copyBitsFromNormalToReverseOrder(dest, 0, dest, 0, dest.length * 8);
     * 
*

(like the similar call of {@link #copyBitsFromReverseToNormalOrder}) * is equivalent to {@link #reverseBitOrderInPlace(byte[]) * PackedBitArraysPer8.reverseBitOrderInPlace}(dest).

* * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. * @see #copyBits(byte[], long, byte[], long, long) * @see #copyBitsFromReverseToNormalOrder(byte[], long, byte[], long, long) */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void copyBitsFromNormalToReverseOrder( byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + cntStart)); // &= dPosRem+cntStart times 1 (from the highest bit) } // Note: overlapping IS NOT supported! if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskStart) | (dest[dPos] & ~maskStart)); // - only 8 low bits are stored } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = REVERSE[src[sPos] & 0xFF]; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskFinish) | (dest[dPos] & ~maskFinish)); // - only 8 low bits are stored } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> shift; else v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((REVERSE[src[sPos] & 0xFF] & 0xFF) << -shift) | ((sNext = (REVERSE[src[sPos + 1] & 0xFF] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = REVERSE[src[sPos] & 0xFF] & 0xFF; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext << sPosRem) | ((sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((REVERSE[src[sPos + 1] & 0xFF] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Equivalent to {@link #copyBitsFromNormalToReverseOrder(byte[], long, byte[], long, long)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #copyBitsFromNormalToReverseOrder}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be copied (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void copyBitsFromNormalToReverseOrderNoSync( byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + cntStart)); // &= dPosRem+cntStart times 1 (from the highest bit) } // Note: overlapping IS NOT supported! if (sPosRem == dPosRem) { if (cntStart > 0) { dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskStart) | (dest[dPos] & ~maskStart)); // - only 8 low bits are stored count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = REVERSE[src[sPos] & 0xFF]; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) dest[dPos] = (byte) ((REVERSE[src[sPos] & 0xFF] & maskFinish) | (dest[dPos] & ~maskFinish)); // - only 8 low bits are stored } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> shift; else v = (sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((REVERSE[src[sPos] & 0xFF] & 0xFF) << -shift) | ((sNext = (REVERSE[src[sPos + 1] & 0xFF] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more dest[dPos] = (byte) ((v & maskStart) | (dest[dPos] & ~maskStart)); count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing src[sPos] } sNext = REVERSE[src[sPos] & 0xFF] & 0xFF; } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of src[sPos] final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) ((sNext << sPosRem) | ((sNext = (REVERSE[src[sPos] & 0xFF] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((REVERSE[src[sPos + 1] & 0xFF] & 0xFF) >>> sPosRem8); } dest[dPos] = (byte) ((v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } /** * Packs count bits from the src array, starting from the element #srcPos, * into a newly created packed bit array byte[{@link #packedLength(long) packedLength}(count)] * returned as a result, starting from the bit #0. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #packBits(byte[], long, boolean[], int, int)} * method.

* *

Note: srcPos and count arguments are declared as long, * but actually they must be in 0..Integer.MAX_VALUE range; in other case, * this method throws IllegalArgumentException. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array * (must be in 0..Integer.MAX_VALUE range). * @param count the number of bits to be packed * (must be in 0..Integer.MAX_VALUE range). * @return the result bit array, where bits are packed in byte. * @throws NullPointerException if src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. */ public static byte[] packBits(boolean[] src, long srcPos, long count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (srcPos > src.length) { throw new IllegalArgumentException("The source position " + srcPos + " is out of the array boolean[" + src.length + "]"); } if (count > src.length - srcPos) { throw new IllegalArgumentException("Too short source array boolean[" + src.length + "]: it does not contain " + count + " bits since position " + srcPos); } assert count == (int) count; final byte[] dest = new byte[(int) packedLength(count)]; int sPos = (int) srcPos; final int cnt = (int) (count >>> 3); for (int k = 0; k < cnt; k++) { dest[k] = (byte) ((src[sPos] ? 1 : 0) | (src[sPos + 1] ? 1 << 1 : 0) | (src[sPos + 2] ? 1 << 2 : 0) | (src[sPos + 3] ? 1 << 3 : 0) | (src[sPos + 4] ? 1 << 4 : 0) | (src[sPos + 5] ? 1 << 5 : 0) | (src[sPos + 6] ? 1 << 6 : 0) | (src[sPos + 7] ? 1 << 7 : 0) ); sPos += 8; } int countFinish = (int) count & 7; for (int k = 0; k < countFinish; sPos++, k++) { if (src[sPos]) { dest[cnt] |= (byte) (1 << k); } else { dest[cnt] &= (byte) ~(1 << k); } } return dest; } /** * Packs count bits from src array, starting from the element #srcPos, * to packed dest array, starting from the bit #destPos. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be packed (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void packBits(byte[] dest, long destPos, boolean[] src, int srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (destPos & 7) == 0 ? 0 : 8 - (int) (destPos & 7); if (countStart > count) { countStart = count; } if (countStart > 0) { synchronized (dest) { for (int srcPosMax = srcPos + countStart; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (destPos & 7)); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (destPos & 7))); } } } count -= countStart; int cnt = count >>> 3; for (int k = (int) (destPos >>> 3), kMax = k + cnt; k < kMax; k++) { dest[k] = (byte) ((src[srcPos] ? 1 : 0) //[[Repeat() \([^\)]*\) ==> (src[srcPos + $INDEX(start=2)] ? 1 << $INDEX(start=2) : 0) ,, ...(6)]] | (src[srcPos + 1] ? 1 << 1 : 0) //[[Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! ]] | (src[srcPos + 2] ? 1 << 2 : 0) | (src[srcPos + 3] ? 1 << 3 : 0) | (src[srcPos + 4] ? 1 << 4 : 0) | (src[srcPos + 5] ? 1 << 5 : 0) | (src[srcPos + 6] ? 1 << 6 : 0) | (src[srcPos + 7] ? 1 << 7 : 0) //[[Repeat.AutoGeneratedEnd]] ); srcPos += 8; destPos += 8; } int countFinish = count & 7; if (countFinish > 0) { synchronized (dest) { for (int srcPosMax = srcPos + countFinish; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (destPos & 7)); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (destPos & 7))); } } } } /** * Equivalent to {@link #packBits(byte[], long, boolean[], int, int)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #packBits(byte[], long, boolean[], int, int)}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be packed (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void packBitsNoSync(byte[] dest, long destPos, boolean[] src, int srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (destPos & 7) == 0 ? 0 : 8 - (int) (destPos & 7); if (countStart > count) { countStart = count; } if (countStart > 0) { for (int srcPosMax = srcPos + countStart; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (destPos & 7)); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (destPos & 7))); } } count -= countStart; int cnt = count >>> 3; for (int k = (int) (destPos >>> 3), kMax = k + cnt; k < kMax; k++) { dest[k] = (byte) ((src[srcPos] ? 1 : 0) //[[Repeat() \([^\)]*\) ==> (src[srcPos + $INDEX(start=2)] ? 1 << $INDEX(start=2) : 0) ,, ...(6)]] | (src[srcPos + 1] ? 1 << 1 : 0) //[[Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! ]] | (src[srcPos + 2] ? 1 << 2 : 0) | (src[srcPos + 3] ? 1 << 3 : 0) | (src[srcPos + 4] ? 1 << 4 : 0) | (src[srcPos + 5] ? 1 << 5 : 0) | (src[srcPos + 6] ? 1 << 6 : 0) | (src[srcPos + 7] ? 1 << 7 : 0) //[[Repeat.AutoGeneratedEnd]] ); srcPos += 8; destPos += 8; } int countFinish = count & 7; if (countFinish > 0) { for (int srcPosMax = srcPos + countFinish; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (destPos & 7)); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (destPos & 7))); } } } /** * Packs count bits from the src array, starting from the element #srcPos, * into a newly created packed bit array byte[{@link #packedLength(long) packedLength}(count)] * returned as a result, starting from the bit #0, * for a case, when the bits are packed in each byte in the reverse order. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #packBitsInReverseOrder(byte[], long, boolean[], int, int)} * method.

* *

Note: srcPos and count arguments are declared as long, * but actually they must be in 0..Integer.MAX_VALUE range; in other case, * this method throws IllegalArgumentException. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array * (must be in 0..Integer.MAX_VALUE range). * @param count the number of bits to be packed * (must be in 0..Integer.MAX_VALUE range). * @return the result bit array, where bits are packed in byte values in reverse order 76543210. * @throws NullPointerException if src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. */ public static byte[] packBitsInReverseOrder(boolean[] src, long srcPos, long count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (srcPos > src.length) { throw new IllegalArgumentException("The source position " + srcPos + " is out of the array boolean[" + src.length + "]"); } if (count > src.length - srcPos) { throw new IllegalArgumentException("Too short source array boolean[" + src.length + "]: it does not contain " + count + " bits since position " + srcPos); } assert count == (int) count; final byte[] dest = new byte[(int) packedLength(count)]; int sPos = (int) srcPos; final int cnt = (int) (count >>> 3); for (int k = 0; k < cnt; k++) { dest[k] = (byte) ((src[sPos] ? 1 << 7 : 0) | (src[sPos + 1] ? 1 << 6 : 0) | (src[sPos + 2] ? 1 << 5 : 0) | (src[sPos + 3] ? 1 << 4 : 0) | (src[sPos + 4] ? 1 << 3 : 0) | (src[sPos + 5] ? 1 << 2 : 0) | (src[sPos + 6] ? 1 << 1 : 0) | (src[sPos + 7] ? 1 : 0) ); sPos += 8; } int countFinish = (int) count & 7; for (int k = 0; k < countFinish; sPos++, k++) { if (src[sPos]) { dest[cnt] |= (byte) (1 << (7 - k)); } else { dest[cnt] &= (byte) ~(1 << (7 - k)); } } return dest; } /** * Packs count bits from src array, starting from the element #srcPos, * to packed dest array, starting from the bit #destPos, * for a case, when the bits are packed in each byte in the reverse order. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be packed (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void packBitsInReverseOrder(byte[] dest, long destPos, boolean[] src, int srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (destPos & 7) == 0 ? 0 : 8 - (int) (destPos & 7); if (countStart > count) { countStart = count; } if (countStart > 0) { synchronized (dest) { for (int srcPosMax = srcPos + countStart; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (7 - (destPos & 7))); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (7 - (destPos & 7)))); } } } count -= countStart; int cnt = count >>> 3; for (int k = (int) (destPos >>> 3), kMax = k + cnt; k < kMax; k++) { dest[k] = (byte) ((src[srcPos] ? 1 << 7 : 0) | (src[srcPos + 1] ? 1 << 6 : 0) | (src[srcPos + 2] ? 1 << 5 : 0) | (src[srcPos + 3] ? 1 << 4 : 0) | (src[srcPos + 4] ? 1 << 3 : 0) | (src[srcPos + 5] ? 1 << 2 : 0) | (src[srcPos + 6] ? 1 << 1 : 0) | (src[srcPos + 7] ? 1 : 0) ); srcPos += 8; destPos += 8; } int countFinish = count & 7; if (countFinish > 0) { synchronized (dest) { for (int srcPosMax = srcPos + countFinish; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (7 - (destPos & 7))); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (7 - (destPos & 7)))); } } } } /** * Equivalent to {@link #packBitsInReverseOrder(byte[], long, boolean[], int, int)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #packBitsInReverseOrder(byte[], long, boolean[], int, int)}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (unpacked boolean values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be packed (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void packBitsInReverseOrderNoSync(byte[] dest, long destPos, boolean[] src, int srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (destPos & 7) == 0 ? 0 : 8 - (int) (destPos & 7); if (countStart > count) { countStart = count; } if (countStart > 0) { for (int srcPosMax = srcPos + countStart; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (7 - (destPos & 7))); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (7 - (destPos & 7)))); } } count -= countStart; int cnt = count >>> 3; for (int k = (int) (destPos >>> 3), kMax = k + cnt; k < kMax; k++) { dest[k] = (byte) ((src[srcPos] ? 1 << 7 : 0) | (src[srcPos + 1] ? 1 << 6 : 0) | (src[srcPos + 2] ? 1 << 5 : 0) | (src[srcPos + 3] ? 1 << 4 : 0) | (src[srcPos + 4] ? 1 << 3 : 0) | (src[srcPos + 5] ? 1 << 2 : 0) | (src[srcPos + 6] ? 1 << 1 : 0) | (src[srcPos + 7] ? 1 : 0) ); srcPos += 8; destPos += 8; } int countFinish = count & 7; if (countFinish > 0) { for (int srcPosMax = srcPos + countFinish; srcPos < srcPosMax; srcPos++, destPos++) { if (src[srcPos]) dest[(int) (destPos >>> 3)] |= (byte) (1 << (7 - (destPos & 7))); else dest[(int) (destPos >>> 3)] &= (byte) (~(1 << (7 - (destPos & 7)))); } } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array boolean[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k). * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(boolean[], int, byte[], long, int)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @return the unpacked boolean array. * @throws NullPointerException if src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static boolean[] unpackBits(byte[] src, long srcPos, long count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final boolean[] result = new boolean[(int) count]; unpackBits(result, 0, src, srcPos, result.length); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest boolean array, starting from the element #destPos. * * @param dest the destination array (unpacked boolean values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be unpacked (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits(boolean[] dest, int destPos, byte[] src, long srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; //[[Repeat() dest\[.*?0; ==> // dest[destPos + $INDEX(start=1)] = (v & (1 << $INDEX(start=1))) != 0; ,, ...(7)]] dest[destPos] = (v & 1) != 0; //[[Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! ]] dest[destPos + 1] = (v & (1 << 1)) != 0; dest[destPos + 2] = (v & (1 << 2)) != 0; dest[destPos + 3] = (v & (1 << 3)) != 0; dest[destPos + 4] = (v & (1 << 4)) != 0; dest[destPos + 5] = (v & (1 << 5)) != 0; dest[destPos + 6] = (v & (1 << 6)) != 0; dest[destPos + 7] = (v & (1 << 7)) != 0; //[[Repeat.AutoGeneratedEnd]] destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array boolean[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k). * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBitsInReverseOrder(boolean[], int, byte[], long, int)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @return the unpacked boolean array. * @throws NullPointerException if src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static boolean[] unpackBitsInReverseOrder(byte[] src, long srcPos, long count) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final boolean[] result = new boolean[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest boolean array, starting from the element #destPos. * * @param dest the destination array (unpacked boolean values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be unpacked (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder(boolean[] dest, int destPos, byte[] src, long srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0; dest[destPos + 1] = (v & (1 << 6)) != 0; dest[destPos + 2] = (v & (1 << 5)) != 0; dest[destPos + 3] = (v & (1 << 4)) != 0; dest[destPos + 4] = (v & (1 << 3)) != 0; dest[destPos + 5] = (v & (1 << 2)) != 0; dest[destPos + 6] = (v & (1 << 1)) != 0; dest[destPos + 7] = (v & 1) != 0; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0; } } /*Repeat() (boolean\[\] unpackBits(?:InReverseOrder)?) ==> $1ToChars,,$1ToBytes,,$1ToShorts,,$1ToInts,,$1ToLongs,,$1ToFloats,,$1ToDoubles;; boolean ==> char,,byte,,short,,int,,long,,float,,double;; Booleans ==> Chars,,Bytes,,Shorts,,Ints,,Longs,,Floats,,Doubles */ /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array boolean[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(boolean[], int, byte[], long, int, boolean, boolean)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked boolean array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static boolean[] unpackBits( byte[] src, long srcPos, long count, boolean bit0Value, boolean bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final boolean[] result = new boolean[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest boolean array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked boolean values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( boolean[] dest, int destPos, byte[] src, long srcPos, int count, boolean bit0Value, boolean bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; //[[Repeat() dest\[.*?0\s*\? ==> // dest[destPos + $INDEX(start=1)] = (v & (1 << $INDEX(start=1))) != 0 ?,, ...(7)]] dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; //[[Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! ]] dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; //[[Repeat.AutoGeneratedEnd]] destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array boolean[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(boolean[], int, byte[], long, int, boolean, boolean)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked boolean array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static boolean[] unpackBitsInReverseOrder( byte[] src, long srcPos, long count, boolean bit0Value, boolean bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final boolean[] result = new boolean[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest boolean array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked boolean values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( boolean[] dest, int destPos, byte[] src, long srcPos, int count, boolean bit0Value, boolean bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */ /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array char[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(char[], int, byte[], long, int, char, char)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked char array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static char[] unpackBitsToChars( byte[] src, long srcPos, long count, char bit0Value, char bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final char[] result = new char[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest char array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked char values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( char[] dest, int destPos, byte[] src, long srcPos, int count, char bit0Value, char bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array char[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(char[], int, byte[], long, int, char, char)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked char array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static char[] unpackBitsInReverseOrderToChars( byte[] src, long srcPos, long count, char bit0Value, char bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final char[] result = new char[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest char array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked char values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( char[] dest, int destPos, byte[] src, long srcPos, int count, char bit0Value, char bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array byte[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(byte[], int, byte[], long, int, byte, byte)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked byte array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static byte[] unpackBitsToBytes( byte[] src, long srcPos, long count, byte bit0Value, byte bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final byte[] result = new byte[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest byte array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked byte values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( byte[] dest, int destPos, byte[] src, long srcPos, int count, byte bit0Value, byte bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array byte[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(byte[], int, byte[], long, int, byte, byte)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked byte array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static byte[] unpackBitsInReverseOrderToBytes( byte[] src, long srcPos, long count, byte bit0Value, byte bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final byte[] result = new byte[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest byte array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked byte values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( byte[] dest, int destPos, byte[] src, long srcPos, int count, byte bit0Value, byte bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array short[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(short[], int, byte[], long, int, short, short)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked short array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static short[] unpackBitsToShorts( byte[] src, long srcPos, long count, short bit0Value, short bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final short[] result = new short[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest short array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked short values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( short[] dest, int destPos, byte[] src, long srcPos, int count, short bit0Value, short bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array short[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(short[], int, byte[], long, int, short, short)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked short array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static short[] unpackBitsInReverseOrderToShorts( byte[] src, long srcPos, long count, short bit0Value, short bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final short[] result = new short[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest short array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked short values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( short[] dest, int destPos, byte[] src, long srcPos, int count, short bit0Value, short bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array int[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(int[], int, byte[], long, int, int, int)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked int array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static int[] unpackBitsToInts( byte[] src, long srcPos, long count, int bit0Value, int bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final int[] result = new int[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest int array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked int values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( int[] dest, int destPos, byte[] src, long srcPos, int count, int bit0Value, int bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array int[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(int[], int, byte[], long, int, int, int)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked int array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static int[] unpackBitsInReverseOrderToInts( byte[] src, long srcPos, long count, int bit0Value, int bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final int[] result = new int[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest int array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked int values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( int[] dest, int destPos, byte[] src, long srcPos, int count, int bit0Value, int bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array long[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(long[], int, byte[], long, int, long, long)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked long array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static long[] unpackBitsToLongs( byte[] src, long srcPos, long count, long bit0Value, long bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final long[] result = new long[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest long array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked long values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( long[] dest, int destPos, byte[] src, long srcPos, int count, long bit0Value, long bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array long[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(long[], int, byte[], long, int, long, long)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked long array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static long[] unpackBitsInReverseOrderToLongs( byte[] src, long srcPos, long count, long bit0Value, long bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final long[] result = new long[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest long array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked long values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( long[] dest, int destPos, byte[] src, long srcPos, int count, long bit0Value, long bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array float[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(float[], int, byte[], long, int, float, float)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked float array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static float[] unpackBitsToFloats( byte[] src, long srcPos, long count, float bit0Value, float bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final float[] result = new float[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest float array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked float values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( float[] dest, int destPos, byte[] src, long srcPos, int count, float bit0Value, float bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array float[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(float[], int, byte[], long, int, float, float)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked float array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static float[] unpackBitsInReverseOrderToFloats( byte[] src, long srcPos, long count, float bit0Value, float bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final float[] result = new float[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest float array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked float values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( float[] dest, int destPos, byte[] src, long srcPos, int count, float bit0Value, float bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to newly created array double[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than {@link #unpackBits(double[], int, byte[], long, int, double, double)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked double array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static double[] unpackBitsToDoubles( byte[] src, long srcPos, long count, double bit0Value, double bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final double[] result = new double[(int) count]; unpackBits(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array, starting from the bit #srcPos, * to dest double array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBit getBit}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked double values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBits( double[] dest, int destPos, byte[] src, long srcPos, int count, double bit0Value, double bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & 1) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (srcPos & 7))) != 0 ? bit1Value : bit0Value; } } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to newly created array double[count] array returned as a result. * Every element result[k] of the result array is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * *

Note that this method provides more user-friendly exception messages in a case * of incorrect arguments, than * {@link #unpackBitsInReverseOrder(double[], int, byte[], long, int, double, double)} * method.

* *

Note: count argument is declared as long, * but actually it must be in 0..Integer.MAX_VALUE range; in other case, * this method throws an exception. Using long * type instead of int may make this method more convenient to use in some situations.

* * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked * (must be in 0..Integer.MAX_VALUE range). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @return the unpacked double array. * @throws NullPointerException if either src is {@code null}. * @throws IllegalArgumentException if srcPos or count is negative, or * if copying would cause access of data outside the source array bounds. * @throws TooLargeArrayException if count > Integer.MAX_VALUE (cannot create the result array). */ public static double[] unpackBitsInReverseOrderToDoubles( byte[] src, long srcPos, long count, double bit0Value, double bit1Value) { Objects.requireNonNull(src, "Null src"); if (srcPos < 0) { throw new IllegalArgumentException("Negative srcPos = " + srcPos); } if (count < 0) { throw new IllegalArgumentException("Negative count = " + count); } if (count > unpackedLength(src) - srcPos) { throw new IllegalArgumentException("Too short source array byte[" + src.length + "]: it cannot contain " + count + " bits since position " + srcPos); } if (count > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large bit array for unpacking to Java array: " + count + " >= 2^31 bits"); } final double[] result = new double[(int) count]; unpackBitsInReverseOrder(result, 0, src, srcPos, result.length, bit0Value, bit1Value); return result; } /** * Unpacks count bits, packed in src array in the reverse order, * starting from the bit #srcPos, * to dest double array, starting from the element #destPos. * It means that every element dest[destPos+k] is assigned to * {@link #getBitInReverseOrder getBitInReverseOrder}(srcPos+k)?bit1Value:bit0Value. * * @param dest the destination array (unpacked double values). * @param destPos position of the first written element in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of elements to be unpacked (must be >=0). * @param bit0Value the value of elements in the destination array to which the bit 0 is translated. * @param bit1Value the value of elements in the destination array to which the bit 1 is translated. * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. */ public static void unpackBitsInReverseOrder( double[] dest, int destPos, byte[] src, long srcPos, int count, double bit0Value, double bit1Value) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int countStart = (srcPos & 7) == 0 ? 0 : 8 - (int) (srcPos & 7); if (countStart > count) { countStart = count; } for (int destPosMax = destPos + countStart; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } count -= countStart; int cnt = count >>> 3; for (int k = (int) (srcPos >>> 3), kMax = k + cnt; k < kMax; k++) { int v = src[k]; srcPos += 8; dest[destPos] = (v & (1 << 7)) != 0 ? bit1Value : bit0Value; dest[destPos + 1] = (v & (1 << 6)) != 0 ? bit1Value : bit0Value; dest[destPos + 2] = (v & (1 << 5)) != 0 ? bit1Value : bit0Value; dest[destPos + 3] = (v & (1 << 4)) != 0 ? bit1Value : bit0Value; dest[destPos + 4] = (v & (1 << 3)) != 0 ? bit1Value : bit0Value; dest[destPos + 5] = (v & (1 << 2)) != 0 ? bit1Value : bit0Value; dest[destPos + 6] = (v & (1 << 1)) != 0 ? bit1Value : bit0Value; dest[destPos + 7] = (v & 1) != 0 ? bit1Value : bit0Value; destPos += 8; } int countFinish = count & 7; for (int destPosMax = destPos + countFinish; destPos < destPosMax; srcPos++, destPos++) { dest[destPos] = (src[(int) (srcPos >>> 3)] & (1 << (7 - (srcPos & 7)))) != 0 ? bit1Value : bit0Value; } } /*Repeat.AutoGeneratedEnd*/ /** * Equivalent to {@link #notBits(byte[], long, byte[], long, long) * notBits}(dest, destPos, dest, destPos, count). * * @param dest the source/destination array (bits are packed in byte values). * @param destPos position of the first bit written in the source/destination array. * @param count the number of bits to be inverted (must be >=0). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ public static void notBits(byte[] dest, long destPos, long count) { notBits(dest, destPos, dest, destPos, count); } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical NOT of corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it just inverts the specified bits. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void notBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((~(src[sPos] & 0xFF) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) ((~(src[sPos] & 0xFF) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((~v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) (~((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((~v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Equivalent to {@link #notBitsInReverseOrder(byte[], long, byte[], long, long) * notBitsInReverseOrder}(dest, destPos, dest, destPos, count). * * @param dest the source/destination array (bits are packed in byte values * in reverse order 76543210). * @param destPos position of the first bit written in the source/destination array. * @param count the number of bits to be inverted (must be >=0). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ public static void notBitsInReverseOrder(byte[] dest, long destPos, long count) { notBitsInReverseOrder(dest, destPos, dest, destPos, count); } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical NOT of corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it just inverts the specified bits. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void notBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) ((~(src[sPos] & 0xFF) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] = (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) ((~(src[sPos] & 0xFF) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) ((~v & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] = (byte) (~((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) ((~v & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /*Repeat() andBits ==> orBits;; AND ==> OR;; \&=(\s*\(byte\)) ==> |=$1;; \|\s*\~mask ==> & mask */ /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical AND of them and corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it does nothing (so there are no reasons for this call). * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void andBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] &= (byte) ((src[sPos] & 0xFF) | ~maskStart); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] &= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] &= (byte) ((src[sPos] & 0xFF) | ~maskFinish); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] &= (byte) (v | ~maskStart); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] &= (byte) ((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] &= (byte) (v | ~maskFinish); } } } } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical AND of them and corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it does nothing (so there are no reasons for this call). * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void andBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] &= (byte) ((src[sPos] & 0xFF) | ~maskStart); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] &= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] &= (byte) ((src[sPos] & 0xFF) | ~maskFinish); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] &= (byte) (v | ~maskStart); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] &= (byte) ((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] &= (byte) (v | ~maskFinish); } } } } /*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */ /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical OR of them and corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it does nothing (so there are no reasons for this call). * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void orBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] |= (byte) ((src[sPos] & 0xFF) & maskStart); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] |= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] |= (byte) ((src[sPos] & 0xFF) & maskFinish); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] |= (byte) (v & maskStart); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] |= (byte) ((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] |= (byte) (v & maskFinish); } } } } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical OR of them and corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it does nothing (so there are no reasons for this call). * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void orBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] |= (byte) ((src[sPos] & 0xFF) & maskStart); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] |= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] |= (byte) ((src[sPos] & 0xFF) & maskFinish); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] |= (byte) (v & maskStart); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] |= (byte) ((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] |= (byte) (v & maskFinish); } } } } /*Repeat.AutoGeneratedEnd*/ /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical XOR of them and corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it clears all specified bits. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void xorBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ (src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] ^= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ (src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] ^= (byte) ((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical XOR of them and corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it clears all specified bits. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void xorBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ (src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] ^= (byte) ((src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ (src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] ^= (byte) ((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8)); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] ^ v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /*Repeat() andNotBits ==> orNotBits;; AND ==> OR;; it clears all specified bits ==> it sets all specified bits to 1;; \&=(\s*\(byte\)) ==> |=$1;; \&\s+\~(?!mask) ==> | ~ */ /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical AND of them and inverted corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it clears all specified bits. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void andNotBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~(src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] &= (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~(src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] &= (byte) (~((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical AND of them and inverted corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it clears all specified bits. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void andNotBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~(src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] &= (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~(src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] &= (byte) (~((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] & ~v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */ /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical OR of them and inverted corresponding count bits, * packed in src array, starting from the bit #srcPos. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it sets all specified bits to 1. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void orNotBits(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~(src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] |= (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~(src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) << shift; else v = (sNext = (src[sPos] & 0xFF)) >>> -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) >>> -shift) | ((sNext = (src[sPos + 1] & 0xFF)) << (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] |= (byte) (~((sNext >>> sPosRem) | ((sNext = (src[sPos] & 0xFF)) << sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext >>> sPosRem; } else { v = (sNext >>> sPosRem) | ((src[sPos + 1] & 0xFF) << sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /** * Replaces count bits, * packed in dest array, starting from the bit #destPos, * with the logical OR of them and inverted corresponding count bits, * packed in src array, starting from the bit #srcPos, * for a case, when the bits are packed in both arrays in the reverse order. * *

This method works correctly even if src == dest * and srcPos == destPos: * in this case it sets all specified bits to 1. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param src the source array (bits are packed in byte values in reverse order 76543210). * @param srcPos position of the first bit read in the source array. * @param count the number of bits to be replaced (must be >=0). * @throws NullPointerException if either src or dest is {@code null}. * @throws IndexOutOfBoundsException if accessing bits would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void orNotBitsInReverseOrder(byte[] dest, long destPos, byte[] src, long srcPos, long count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); int sPos = (int) (srcPos >>> 3); int dPos = (int) (destPos >>> 3); int sPosRem = (int) (srcPos & 7); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (sPosRem == dPosRem) { if (cntStart > 0) { synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~(src[sPos] & 0xFF)) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; dPos++; sPos++; } for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++, sPos++) { dest[dPos] |= (byte) (~(src[sPos] & 0xFF)); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~(src[sPos] & 0xFF)) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } else { final int shift = dPosRem - sPosRem; int sNext; if (cntStart > 0) { int v; if (sPosRem + cntStart <= 8) { // cntStart bits are in a single src element if (shift > 0) v = (sNext = (src[sPos] & 0xFF)) >>> shift; else v = (sNext = (src[sPos] & 0xFF)) << -shift; sPosRem += cntStart; } else { v = ((src[sPos] & 0xFF) << -shift) | ((sNext = (src[sPos + 1] & 0xFF)) >>> (8 + shift)); sPos++; sPosRem = (sPosRem + cntStart) & 7; } // let's suppose dPosRem = 0 now; don't perform it, because we'll not use dPosRem more synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~v) & maskStart) | (dest[dPos] & ~maskStart)); } count -= cntStart; if (count == 0) { return; // little optimization } dPos++; } else { if (count == 0) { return; // necessary check to avoid IndexOutOfBoundException while accessing (src[sPos] & 0xFF) } sNext = (src[sPos] & 0xFF); } // Now the bit #0 of dest[dPos] corresponds to the bit #sPosRem of (src[sPos] & 0xFF) final int sPosRem8 = 8 - sPosRem; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; ) { sPos++; dest[dPos] |= (byte) (~((sNext << sPosRem) | ((sNext = (src[sPos] & 0xFF)) >>> sPosRem8))); dPos++; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) int v; if (sPosRem + cntFinish <= 8) { // cntFinish bits are in a single src element v = sNext << sPosRem; } else { v = (sNext << sPosRem) | ((src[sPos + 1] & 0xFF) >>> sPosRem8); } synchronized (dest) { dest[dPos] = (byte) (((dest[dPos] | ~v) & maskFinish) | (dest[dPos] & ~maskFinish)); } } } } /*Repeat.AutoGeneratedEnd*/ /*Repeat(INCLUDE_FROM_FILE, PackedBitArrays.java, fillBits) long\[\] ==> byte[] ;; long<\/code> ==> byte ;; >>>\s*6 ==> >>> 3 ;; 63 ==> 7 ;; 64 ==> 8 ;; (dest\[\w+\]\s*(?:\&=|\|=|\^=|=)\s*)([^;]+); ==> $1(byte) ($2); ;; long longValue = value \? -1 \: 0 ==> byte byteValue = value ? (byte) -1 : (byte) 0 ;; \(byte\) \(longValue\) ==> byteValue ;; src\[(sPos|sPos \+ 1)\] ==> (src[$1] & 0xFF) ;; long\s+(v\b|sNext\b|mask) ==> int $1 ;; 1L\s+<< ==> 1 << !! Auto-generated: NOT EDIT !! */ /** * Fills count bits in the packed dest array, starting * from the bit #destPos, * by the specified value. Be careful: the second int argument in this method * is the number of filled element, but not the end filled index * as in java.util.Arrays.fill methods. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param count the number of bits to be filled (must be >=0). * @param value new value of all filled bits (false means the bit 0, * true means the bit 1). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if filling would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void fillBits(byte[] dest, long destPos, long count, boolean value) { Objects.requireNonNull(dest, "Null dest"); int dPos = (int) (destPos >>> 3); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (cntStart > 0) { synchronized (dest) { if (value) dest[dPos] |= (byte) (maskStart); else dest[dPos] &= (byte) (~maskStart); } count -= cntStart; dPos++; } byte byteValue = value ? (byte) -1 : (byte) 0; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++) { dest[dPos] = byteValue; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) synchronized (dest) { if (value) dest[dPos] |= (byte) (maskFinish); else dest[dPos] &= (byte) (~maskFinish); } } } /** * Equivalent to {@link #fillBits(byte[], long, long, boolean)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #fillBits}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values). * @param destPos position of the first bit written in the destination array. * @param count the number of bits to be filled (must be >=0). * @param value new value of all filled bits (false means the bit 0, * true means the bit 1). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if filling would cause access of data outside array bounds. */ public static void fillBitsNoSync(byte[] dest, long destPos, long count, boolean value) { Objects.requireNonNull(dest, "Null dest"); int dPos = (int) (destPos >>> 3); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = -1 << dPosRem; // dPosRem times 0, then 1 (from the left) if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (dPosRem + cntStart)) - 1; // &= dPosRem+cntStart times 1 (from the left) } if (cntStart > 0) { if (value) dest[dPos] |= (byte) (maskStart); else dest[dPos] &= (byte) (~maskStart); count -= cntStart; dPos++; } byte byteValue = value ? (byte) -1 : (byte) 0; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++) { dest[dPos] = byteValue; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = (1 << cntFinish) - 1; // cntFinish times 1 (from the left) if (value) dest[dPos] |= (byte) (maskFinish); else dest[dPos] &= (byte) (~maskFinish); } } /*Repeat.IncludeEnd*/ /** * Fills count bits in the packed dest array, starting from the bit * #destPos, for a case, when the bits are packed in each byte in the reverse order. * Be careful: the second int argument in this method * is the number of filled element, but not the end filled index * as in java.util.Arrays.fill methods. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param count the number of bits to be filled (must be >=0). * @param value new value of all filled bits (false means the bit 0, * true means the bit 1). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if filling would cause access of data outside array bounds. */ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") public static void fillBitsInReverseOrder(byte[] dest, long destPos, long count, boolean value) { Objects.requireNonNull(dest, "Null dest"); int dPos = (int) (destPos >>> 3); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (cntStart > 0) { synchronized (dest) { if (value) dest[dPos] |= (byte) (maskStart); else dest[dPos] &= (byte) (~maskStart); } count -= cntStart; dPos++; } byte byteValue = value ? (byte) -1 : (byte) 0; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++) { dest[dPos] = byteValue; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) synchronized (dest) { if (value) dest[dPos] |= (byte) (maskFinish); else dest[dPos] &= (byte) (~maskFinish); } } } /** * Equivalent to {@link #fillBitsInReverseOrder(byte[], long, long, boolean)} * method with the only exception, * that this method does not perform synchronization on dest array. * You may use this method instead of {@link #fillBitsInReverseOrder}, * if you are not planning to call it from different threads for the same dest array. * * @param dest the destination array (bits are packed in byte values in reverse order 76543210). * @param destPos position of the first bit written in the destination array. * @param count the number of bits to be filled (must be >=0). * @param value new value of all filled bits (false means the bit 0, * true means the bit 1). * @throws NullPointerException if dest is {@code null}. * @throws IndexOutOfBoundsException if filling would cause access of data outside array bounds. */ public static void fillBitsInReverseOrderNoSync(byte[] dest, long destPos, long count, boolean value) { Objects.requireNonNull(dest, "Null dest"); int dPos = (int) (destPos >>> 3); int dPosRem = (int) (destPos & 7); int cntStart = (-dPosRem) & 7; int maskStart = 0xFF >>> dPosRem; // dPosRem times 0, then 1 (from the highest bit) if (cntStart > count) { cntStart = (int) count; maskStart &= (0xFF00 >>> (dPosRem + count)); // &= dPosRem+cntStart times 1 (from the highest bit) } if (cntStart > 0) { if (value) dest[dPos] |= (byte) (maskStart); else dest[dPos] &= (byte) (~maskStart); count -= cntStart; dPos++; } byte byteValue = value ? (byte) -1 : (byte) 0; for (int dPosMax = dPos + (int) (count >>> 3); dPos < dPosMax; dPos++) { dest[dPos] = byteValue; } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = 0xFF00 >>> cntFinish; // cntFinish times 1 (from the highest bit) if (value) dest[dPos] |= (byte) (maskFinish); else dest[dPos] &= (byte) (~maskFinish); } } /** * Returns the number of high bits (1) in the given fragment of the given packed bit array. * * @param src the source packed bit array. * @param fromIndex the initial checked bit index in array, inclusive. * @param toIndex the end checked bit index in array, exclusive. * @return the number of high bits (1) in the given fragment of the given packed bit array. * @throws NullPointerException if the src argument is {@code null}. * @throws IndexOutOfBoundsException if fromIndex or toIndex are negative, * if toIndex is greater than src.length*8, * or if fromIndex is greater than startIndex */ public static long cardinality(byte[] src, final long fromIndex, final long toIndex) { Objects.requireNonNull(src, "Null src argument in cardinality method"); if (fromIndex < 0) throw new ArrayIndexOutOfBoundsException("Bit array index out of range: initial index = " + fromIndex); if (toIndex > ((long) src.length) << 3) throw new ArrayIndexOutOfBoundsException("Bit array index out of range: end index = " + toIndex); if (fromIndex > toIndex) throw new ArrayIndexOutOfBoundsException("Bit array index out of range: initial index = " + fromIndex + " > end index = " + toIndex); long count = toIndex - fromIndex; int sPos = (int) (fromIndex >>> 3); int sPosRem = (int) (fromIndex & 7); int cntStart = (-sPosRem) & 7; int maskStart = (-1 << sPosRem) & 0xFF; // sPosRem times 0, then 1 (from the left) // - 0xFF is important here for correct usage of bitCount if (cntStart > count) { cntStart = (int) count; maskStart &= (1 << (sPosRem + cntStart)) - 1; // &= sPosRem+cntStart times 1 (from the left) } long result = 0; if (cntStart > 0) { result += PackedBitArrays.bitCount(src[sPos] & maskStart); count -= cntStart; sPos++; } for (int sPosMax = sPos + (int) (count >>> 3); sPos < sPosMax; sPos++) { result += PackedBitArrays.bitCount(src[sPos] & 0xFF); } int cntFinish = (int) (count & 7); if (cntFinish > 0) { int maskFinish = ((1 << cntFinish) - 1) & 0xFF; // cntFinish times 1 (from the left) result += PackedBitArrays.bitCount(src[sPos] & maskFinish); } return result; } /** * Equivalent to {@link #reverseBitOrder(byte[], int, byte[], int, int) * reverseBitOrder}(bytes, 0, bytes, 0, bytes.length). * * @param bytes array to process and to save results. * @throws NullPointerException if src is {@code null}. */ public static void reverseBitOrderInPlace(byte[] bytes) { Objects.requireNonNull(bytes, "Null bytes"); for (int i = 0; i < bytes.length; i++) { bytes[i] = REVERSE[bytes[i] & 0xFF]; } } /** * Equivalent to {@link #reverseBitOrder(byte[], int, int) * reverseBitOrder}(src, 0, src.length). * * @param src source array to be processed. * @return result array with reversed bit order in bytes. * @throws NullPointerException if src is {@code null}. */ public static byte[] reverseBitOrder(byte[] src) { return reverseBitOrder(src, 0, src.length); } /** * Reverses the bit order in count bytes of src array, * starting from the byte #srcPos, * and returns the reversed bytes in the newly created array. * *

The same result can be achieved with the following code:

* *
     *      byte[] result = new byte[count];
     *      {@link #reverseBitOrder(byte[], int, byte[], int, int)
     *      PackedBitArraysPer8.reverseBitOrder}(result, 0, src, srcPos, count);
* * @param src the source array. * @param srcPos position of the first read element in the source array. * @param count the number of bytes to be processed. * @return result array with reversed bit order in bytes. * @throws NullPointerException if src is {@code null}. * @throws IllegalArgumentException if count is negative. * @throws IndexOutOfBoundsException if processing would cause access of data outside array bounds. */ public static byte[] reverseBitOrder(byte[] src, int srcPos, int count) { Objects.requireNonNull(src, "Null src"); JArrays.rangeCheck(src.length, srcPos, count); byte[] result = new byte[count]; for (int i = srcPos, j = 0; j < count; i++, j++) { result[j] = REVERSE[src[i] & 0xFF]; } return result; } /** * Reverses the bit order in count bytes of src array, * starting from the byte #srcPos, * and returns the reversed bytes in dest array, * starting from the byte #destPos. * You can pass the same array in both arguments to perform the reversion in place. * *

Equivalent to the following loop:

*
     *     for (int i = 0; i < count; i++) {
     *         dest[destPos + i] = {@link #reverseBitOrder(byte)
     *         PackedBitArraysPer8.reverseBitOrder}(src[srcPos + i]);
     *     }
     * 
* *

This method can be useful if you have an array of bits, packed into src in reverse order: * (b>>7)&1, * (b>>6)&1, * (b>>5)&1, * (b>>4)&1, * (b>>3)&1, * (b>>2)&1, * (b>>1)&1, * b&1 * (highest bits first) for each byte b.

* * @param dest array to store results. * @param destPos position of the first stored element in the destination array. * @param src the source array. * @param srcPos position of the first read element in the source array. * @param count the number of bytes to be processed. * @throws NullPointerException if either src or dest is {@code null}. * @throws IllegalArgumentException if count is negative. * @throws IndexOutOfBoundsException if processing would cause access of data outside array bounds. */ public static void reverseBitOrder(byte[] dest, int destPos, byte[] src, int srcPos, int count) { Objects.requireNonNull(dest, "Null dest"); Objects.requireNonNull(src, "Null src"); JArrays.rangeCheck(src.length, srcPos, dest.length, destPos, count); for (int i = srcPos, j = destPos, toIndex = srcPos + count; i < toIndex; i++, j++) { dest[j] = REVERSE[src[i] & 0xFF]; } } /** * Reverses the bit order of a byte and returns the result. * Equivalent to (byte) ({@link Integer#reverse(int) Integer.reverse(value)} >>> 24). * * @param value byte value * @return the byte with bit order reversed. */ public static byte reverseBitOrder(byte value) { return REVERSE[value & 0xFF]; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy