You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by le...@apache.org on 2025/05/23 23:04:47 UTC
(datasketches-java) branch thetaRework updated: Theta rework, phase 1, no testing yet!
This is an automated email from the ASF dual-hosted git repository.
leerho pushed a commit to branch thetaRework
in repository https://gitbox.apache.org/repos/asf/datasketches-java.git
The following commit(s) were added to refs/heads/thetaRework by this push:
new 6008cb35 Theta rework, phase 1, no testing yet!
6008cb35 is described below
commit 6008cb35f7dc075d24d0a47af687f15b36a79eee
Author: Lee Rhodes <le...@gmail.com>
AuthorDate: Fri May 23 16:04:37 2025 -0700
Theta rework, phase 1, no testing yet!
---
.../java/org/apache/datasketches/common/Util.java | 112 +-
.../java/org/apache/datasketches/theta2/AnotB.java | 205 +
.../org/apache/datasketches/theta2/AnotBimpl.java | 241 +
.../org/apache/datasketches/theta2/BitPacking.java | 6292 ++++++++++++++++++++
.../theta2/BytesCompactCompressedHashIterator.java | 93 +
.../theta2/BytesCompactHashIterator.java | 53 +
.../datasketches/theta2/CompactOperations.java | 388 ++
.../apache/datasketches/theta2/CompactSketch.java | 478 ++
.../ConcurrentBackgroundThetaPropagation.java | 110 +
.../theta2/ConcurrentDirectQuickSelectSketch.java | 270 +
.../theta2/ConcurrentHeapQuickSelectSketch.java | 266 +
.../theta2/ConcurrentHeapThetaBuffer.java | 223 +
.../theta2/ConcurrentPropagationService.java | 72 +
.../theta2/ConcurrentSharedThetaSketch.java | 187 +
.../theta2/DirectCompactCompressedSketch.java | 142 +
.../datasketches/theta2/DirectCompactSketch.java | 174 +
.../theta2/DirectQuickSelectSketch.java | 339 ++
.../theta2/DirectQuickSelectSketchR.java | 284 +
.../datasketches/theta2/EmptyCompactSketch.java | 147 +
.../datasketches/theta2/ForwardCompatibility.java | 164 +
.../apache/datasketches/theta2/HashIterator.java | 40 +
.../datasketches/theta2/HeapAlphaSketch.java | 601 ++
.../theta2/HeapCompactHashIterator.java | 41 +
.../datasketches/theta2/HeapCompactSketch.java | 158 +
.../datasketches/theta2/HeapHashIterator.java | 54 +
.../datasketches/theta2/HeapQuickSelectSketch.java | 326 +
.../datasketches/theta2/HeapUpdateSketch.java | 139 +
.../apache/datasketches/theta2/Intersection.java | 218 +
.../datasketches/theta2/IntersectionImpl.java | 561 ++
.../MemoryCompactCompressedHashIterator.java | 108 +
.../datasketches/theta2/MemoryHashIterator.java | 62 +
.../apache/datasketches/theta2/PreambleUtil.java | 533 ++
.../org/apache/datasketches/theta2/Rebuilder.java | 175 +
.../apache/datasketches/theta2/SetOperation.java | 259 +
.../datasketches/theta2/SetOperationBuilder.java | 275 +
.../datasketches/theta2/SingleItemSketch.java | 413 ++
.../org/apache/datasketches/theta2/Sketch.java | 695 +++
.../java/org/apache/datasketches/theta2/Union.java | 231 +
.../org/apache/datasketches/theta2/UnionImpl.java | 365 ++
.../datasketches/theta2/UpdateReturnState.java | 79 +
.../apache/datasketches/theta2/UpdateSketch.java | 469 ++
.../datasketches/theta2/UpdateSketchBuilder.java | 493 ++
.../theta2/WrappedCompactCompressedSketch.java | 111 +
.../datasketches/theta2/WrappedCompactSketch.java | 159 +
.../apache/datasketches/theta2/package-info.java | 27 +
.../datasketches/thetacommon/HashOperations.java | 104 +
46 files changed, 16934 insertions(+), 2 deletions(-)
diff --git a/src/main/java/org/apache/datasketches/common/Util.java b/src/main/java/org/apache/datasketches/common/Util.java
index 19a8ee61..969cdc38 100644
--- a/src/main/java/org/apache/datasketches/common/Util.java
+++ b/src/main/java/org/apache/datasketches/common/Util.java
@@ -24,9 +24,11 @@ import static java.lang.Math.floor;
import static java.lang.Math.log;
import static java.lang.Math.pow;
import static java.lang.Math.round;
-import static java.util.Arrays.fill;
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import java.lang.foreign.MemorySegment;
import java.util.Comparator;
+import java.util.Objects;
/**
* Common utility functions.
@@ -257,7 +259,7 @@ public final class Util {
final int sLen = s.length();
if (sLen < fieldLength) {
final char[] cArr = new char[fieldLength - sLen];
- fill(cArr, padChar);
+ java.util.Arrays.fill(cArr, padChar);
final String addstr = String.valueOf(cArr);
return (postpend) ? s.concat(addstr) : addstr.concat(s);
}
@@ -798,4 +800,110 @@ public final class Util {
return c.compare((T)item1, (T)item2) <= 0;
}
+ //MemorySegment related
+
+ /**
+ * Returns true if the two given MemorySegments refer to the same backing resource,
+ * which is either an off-heap memory location and size, or the same on-heap array object.
+ *
+ * <p>If both segment are off-heap, they both must have the same starting address and the same size.</p>
+ *
+ * <p>For on-heap segments, both segments must be based on or derived from the same array object and neither segment
+ * can be read-only.</p>
+ *
+ * @param seg1 The first given MemorySegment
+ * @param seg2 The second given MemorySegment
+ * @return true if both MemorySegments are determined to be the same backing memory.
+ */
+ public static boolean isSameResource(final MemorySegment seg1, final MemorySegment seg2) {
+ Objects.requireNonNull(seg1, "seg1 must not be null.");
+ Objects.requireNonNull(seg2, "seg2 must not be null.");
+ if (!seg1.scope().isAlive() || !seg2.scope().isAlive()) {
+ throw new IllegalArgumentException("Both arguments must be alive.");
+ }
+ final boolean seg1Native = seg1.isNative();
+ final boolean seg2Native = seg2.isNative();
+ if (seg1Native ^ seg2Native) { return false; }
+ if (seg1Native && seg2Native) { //both off heap
+ return (seg1.address() == seg2.address()) && (seg1.byteSize() == seg2.byteSize());
+ }
+ //both on heap
+ if (seg1.isReadOnly() || seg2.isReadOnly()) {
+ throw new IllegalArgumentException("Cannot determine 'isSameBackingMemory(..)' on heap if either MemorySegment is Read-only.");
+ }
+ return (seg1.heapBase().orElse(null) == seg2.heapBase().orElse(null));
+ }
+
+ /**
+ * Request a new heap MemorySegment with the given capacityBytes.
+ *
+ * <p>The returned MemorySegment will be constructed from a <i>long[]</i> array.
+ * As a result, it will be on-heap and have a memory alignment of 8.
+ * If the requested capacity is not divisible by eight, the returned size
+ * will be rolled up to the next multiple of eight.</p>
+ *
+ * @param capacityBytes The new capacity being requested.
+ * @return a new MemorySegment with the requested capacity.
+ */
+ public static MemorySegment newHeapSegment(final int capacityBytes) {
+ if (capacityBytes < 0) {
+ throw new IllegalArgumentException("Requested capacity must be positive.");
+ }
+ final long[] array = ((capacityBytes * 0x7) == 0) ? new long[capacityBytes >>> 3] : new long[(capacityBytes >>> 3) + 1];
+ return MemorySegment.ofArray(array);
+ }
+
+ /**
+ * Clears all bytes of this MemorySegment to zero.
+ * @param seg the given MemorySegment
+ */
+ public static void clear(final MemorySegment seg) {
+ seg.fill((byte)0);
+ }
+
+ /**
+ * Clears a portion of this MemorySegment to zero.
+ * @param seg the given MemorySegment
+ * @param offsetBytes offset bytes relative to this MemorySegment start
+ * @param lengthBytes the length in bytes
+ */
+ public static void clear(final MemorySegment seg, final long offsetBytes, final long lengthBytes) {
+ final MemorySegment slice = seg.asSlice(offsetBytes, lengthBytes);
+ slice.fill((byte)0);
+ }
+
+ /**
+ * Fills a portion of this Memory region to the given byte value.
+ * @param seg the given MemorySegment
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param lengthBytes the length in bytes
+ * @param value the given byte value
+ */
+ public static void fill(final MemorySegment seg, final long offsetBytes, final long lengthBytes, final byte value) {
+ final MemorySegment slice = seg.asSlice(offsetBytes, lengthBytes);
+ slice.fill(value);
+ }
+
+ /**
+ * Clears the bits defined by the bitMask
+ * @param seg the given MemorySegment
+ * @param offsetBytes offset bytes relative to this Memory start.
+ * @param bitMask the bits set to one will be cleared
+ */
+ public static void clearBits(final MemorySegment seg, final long offsetBytes, final byte bitMask) {
+ final byte b = seg.get(JAVA_BYTE, offsetBytes);
+ seg.set(JAVA_BYTE, offsetBytes, (byte)(b & ~bitMask));
+ }
+
+ /**
+ * Sets the bits defined by the bitMask
+ * @param seg the given MemorySegment
+ * @param offsetBytes offset bytes relative to this Memory start
+ * @param bitMask the bits set to one will be set
+ */
+ public static void setBits(final MemorySegment seg, final long offsetBytes, final byte bitMask) {
+ final byte b = seg.get(JAVA_BYTE, offsetBytes);
+ seg.set(JAVA_BYTE, offsetBytes, (byte)(b | bitMask));
+ }
+
}
diff --git a/src/main/java/org/apache/datasketches/theta2/AnotB.java b/src/main/java/org/apache/datasketches/theta2/AnotB.java
new file mode 100644
index 00000000..72f7e89b
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/AnotB.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.common.Family;
+
+/**
+ * Computes a set difference, A-AND-NOT-B, of two theta sketches.
+ * This class includes both stateful and stateless operations.
+ *
+ * <p>The stateful operation is as follows:</p>
+ * <pre><code>
+ * AnotB anotb = SetOperationBuilder.buildAnotB();
+ *
+ * anotb.setA(Sketch skA); //The first argument.
+ * anotb.notB(Sketch skB); //The second (subtraction) argument.
+ * anotb.notB(Sketch skC); // ...any number of additional subtractions...
+ * anotb.getResult(false); //Get an interim result.
+ * anotb.notB(Sketch skD); //Additional subtractions.
+ * anotb.getResult(true); //Final result and resets the AnotB operator.
+ * </code></pre>
+ *
+ * <p>The stateless operation is as follows:</p>
+ * <pre><code>
+ * AnotB anotb = SetOperationBuilder.buildAnotB();
+ *
+ * CompactSketch csk = anotb.aNotB(Sketch skA, Sketch skB);
+ * </code></pre>
+ *
+ * <p>Calling the <i>setA</i> operation a second time essentially clears the internal state and loads
+ * the new sketch.</p>
+ *
+ * <p>The stateless and stateful operations are independent of each other with the exception of
+ * sharing the same update hash seed loaded as the default seed or specified by the user as an
+ * argument to the builder.</p>
+ *
+ * @author Lee Rhodes
+ */
+public abstract class AnotB extends SetOperation {
+
+ /**
+ * Constructor
+ */
+ AnotB() {}
+
+ @Override
+ public Family getFamily() {
+ return Family.A_NOT_B;
+ }
+
+ /**
+ * This is part of a multistep, stateful AnotB operation and sets the given Theta sketch as the
+ * first argument <i>A</i> of <i>A-AND-NOT-B</i>. This overwrites the internal state of this
+ * AnotB operator with the contents of the given sketch.
+ * This sets the stage for multiple following <i>notB</i> steps.
+ *
+ * <p>An input argument of null will throw an exception.</p>
+ *
+ * <p>Rationale: In mathematics a "null set" is a set with no members, which we call an empty set.
+ * That is distinctly different from the java <i>null</i>, which represents a nonexistent object.
+ * In most cases it is a programming error due to some object that was not properly initialized.
+ * With a null as the first argument, we cannot know what the user's intent is.
+ * Since it is very likely that a <i>null</i> is a programming error, we throw a an exception.</p>
+ *
+ * <p>An empty input argument will set the internal state to empty.</p>
+ *
+ * <p>Rationale: An empty set is a mathematically legal concept. Although it makes any subsequent,
+ * valid argument for B irrelevant, we must allow this and assume the user knows what they are
+ * doing.</p>
+ *
+ * <p>Performing {@link #getResult(boolean)} just after this step will return a compact form of
+ * the given argument.</p>
+ *
+ * @param skA The incoming sketch for the first argument, <i>A</i>.
+ */
+ public abstract void setA(Sketch skA);
+
+ /**
+ * This is part of a multistep, stateful AnotB operation and sets the given Theta sketch as the
+ * second (or <i>n+1</i>th) argument <i>B</i> of <i>A-AND-NOT-B</i>.
+ * Performs an <i>AND NOT</i> operation with the existing internal state of this AnotB operator.
+ *
+ * <p>An input argument of null or empty is ignored.</p>
+ *
+ * <p>Rationale: A <i>null</i> for the second or following arguments is more tolerable because
+ * <i>A NOT null</i> is still <i>A</i> even if we don't know exactly what the null represents. It
+ * clearly does not have any content that overlaps with <i>A</i>. Also, because this can be part of
+ * a multistep operation with multiple <i>notB</i> steps. Other following steps can still produce
+ * a valid result.</p>
+ *
+ * <p>Use {@link #getResult(boolean)} to obtain the result.</p>
+ *
+ * @param skB The incoming Theta sketch for the second (or following) argument <i>B</i>.
+ */
+ public abstract void notB(Sketch skB);
+
+ /**
+ * Gets the result of the multistep, stateful operation AnotB that have been executed with calls
+ * to {@link #setA(Sketch)} and ({@link #notB(Sketch)} or
+ * {@link #notB(org.apache.datasketches.theta2.Sketch)}).
+ *
+ * @param reset If <i>true</i>, clears this operator to the empty state after this result is
+ * returned. Set this to <i>false</i> if you wish to obtain an intermediate result.
+ *
+ * @return the result of this operation as an ordered, on-heap {@link CompactSketch}.
+ */
+ public abstract CompactSketch getResult(boolean reset);
+
+ /**
+ * Gets the result of the multistep, stateful operation AnotB that have been executed with calls
+ * to {@link #setA(Sketch)} and ({@link #notB(Sketch)} or
+ * {@link #notB(org.apache.datasketches.theta2.Sketch)}).
+ *
+ * @param dstOrdered If <i>true</i>, the result will be an ordered {@link CompactSketch}.
+ * <a href="{@docRoot}/resources/dictionary.html#dstOrdered">See Destination Ordered</a>.
+ *
+ * @param dstSeg if not <i>null</i> the given MemorySegment will be the target location of the result.
+ * <a href="{@docRoot}/resources/dictionary.html#dstMem">See Destination MemorySegment</a>.
+ *
+ * @param reset If <i>true</i>, clears this operator to the empty state after this result is
+ * returned. Set this to <i>false</i> if you wish to obtain an intermediate result.
+ *
+ * @return the result of this operation as a {@link CompactSketch} in the given dstMem.
+ */
+ public abstract CompactSketch getResult(boolean dstOrdered, MemorySegment dstSeg, boolean reset);
+
+ /**
+ * Perform A-and-not-B set operation on the two given sketches and return the result as an
+ * ordered CompactSketch on the heap.
+ *
+ * <p>This a stateless operation and has no impact on the internal state of this operator.
+ * Thus, this is not an accumulating update and does not interact with the {@link #setA(Sketch)},
+ * {@link #notB(Sketch)}, {@link #getResult(boolean)}, or
+ * {@link #getResult(boolean, MemorySegment, boolean)} methods.</p>
+ *
+ * <p>If either argument is null an exception is thrown.</p>
+ *
+ * <p>Rationale: In mathematics a "null set" is a set with no members, which we call an empty set.
+ * That is distinctly different from the java <i>null</i>, which represents a nonexistent object.
+ * In most cases <i>null</i> is a programming error due to a non-initialized object. </p>
+ *
+ * <p>With a null as the first argument we cannot know what the user's intent is and throw an
+ * exception. With a null as the second argument for this method we must return a result and
+ * there is no following possible viable arguments for the second argument so we thrown an
+ * exception.</p>
+ *
+ * @param skA The incoming sketch for the first argument. It must not be null.
+ * @param skB The incoming sketch for the second argument. It must not be null.
+ * @return an ordered CompactSketch on the heap
+ */
+ public CompactSketch aNotB(final Sketch skA, final Sketch skB) {
+ return aNotB(skA, skB, true, null);
+ }
+
+ /**
+ * Perform A-and-not-B set operation on the two given sketches and return the result as a
+ * CompactSketch.
+ *
+ * <p>This a stateless operation and has no impact on the internal state of this operator.
+ * Thus, this is not an accumulating update and does not interact with the {@link #setA(Sketch)},
+ * {@link #notB(Sketch)}, {@link #getResult(boolean)}, or
+ * {@link #getResult(boolean, MemorySegment, boolean)} methods.</p>
+ *
+ * <p>If either argument is null an exception is thrown.</p>
+ *
+ * <p>Rationale: In mathematics a "null set" is a set with no members, which we call an empty set.
+ * That is distinctly different from the java <i>null</i>, which represents a nonexistent object.
+ * In most cases <i>null</i> is a programming error due to a non-initialized object. </p>
+ *
+ * <p>With a null as the first argument we cannot know what the user's intent is and throw an
+ * exception. With a null as the second argument for this method we must return a result and
+ * there is no following possible viable arguments for the second argument so we thrown an
+ * exception.</p>
+ *
+ * @param skA The incoming sketch for the first argument. It must not be null.
+ * @param skB The incoming sketch for the second argument. It must not be null.
+ * @param dstOrdered
+ * <a href="{@docRoot}/resources/dictionary.html#dstOrdered">See Destination Ordered</a>.
+ * @param dstSeg
+ * <a href="{@docRoot}/resources/dictionary.html#dstMem">See Destination MemorySegment</a>.
+ * @return the result as a CompactSketch.
+ */
+ public abstract CompactSketch aNotB(Sketch skA, Sketch skB, boolean dstOrdered,
+ MemorySegment dstSeg);
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/AnotBimpl.java b/src/main/java/org/apache/datasketches/theta2/AnotBimpl.java
new file mode 100644
index 00000000..4931bb68
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/AnotBimpl.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static org.apache.datasketches.common.Util.exactLog2OfLong;
+import static org.apache.datasketches.thetacommon.HashOperations.checkThetaCorruption;
+import static org.apache.datasketches.thetacommon.HashOperations.continueCondition;
+import static org.apache.datasketches.thetacommon.HashOperations.hashSearch;
+import static org.apache.datasketches.thetacommon.HashOperations.hashSearchOrInsert;
+import static org.apache.datasketches.thetacommon.HashOperations.minLgHashTableSize;
+
+import java.lang.foreign.MemorySegment;
+import java.util.Arrays;
+
+import org.apache.datasketches.common.SketchesArgumentException;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * Implements the A-and-not-B operations.
+ * @author Lee Rhodes
+ * @author Kevin Lang
+ */
+final class AnotBimpl extends AnotB {
+ private final short seedHash_;
+ private boolean empty_;
+ private long thetaLong_;
+ private long[] hashArr_ = new long[0]; //compact array w curCount_ entries
+ private int curCount_;
+
+ /**
+ * Construct a new AnotB SetOperation on the java heap. Called by SetOperation.Builder.
+ *
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See seed</a>
+ */
+ AnotBimpl(final long seed) {
+ this(ThetaUtil.computeSeedHash(seed));
+ }
+
+ /**
+ * Construct a new AnotB SetOperation on the java heap.
+ *
+ * @param seedHash 16 bit hash of the chosen update seed.
+ */
+ private AnotBimpl(final short seedHash) {
+ seedHash_ = seedHash;
+ reset();
+ }
+
+ @Override
+ public void setA(final Sketch skA) {
+ if (skA == null) {
+ reset();
+ throw new SketchesArgumentException("The input argument <i>A</i> must not be null");
+ }
+ if (skA.isEmpty()) {
+ reset();
+ return;
+ }
+ //skA is not empty
+ ThetaUtil.checkSeedHashes(seedHash_, skA.getSeedHash());
+
+ //process A
+ hashArr_ = getHashArrA(skA);
+ empty_ = false;
+ thetaLong_ = skA.getThetaLong();
+ curCount_ = hashArr_.length;
+ }
+
+ @Override
+ public void notB(final Sketch skB) {
+ if (empty_ || skB == null || skB.isEmpty()) { return; }
+ //local and skB is not empty
+ ThetaUtil.checkSeedHashes(seedHash_, skB.getSeedHash());
+
+ thetaLong_ = Math.min(thetaLong_, skB.getThetaLong());
+
+ //process B
+ hashArr_ = getResultHashArr(thetaLong_, curCount_, hashArr_, skB);
+ curCount_ = hashArr_.length;
+ empty_ = curCount_ == 0 && thetaLong_ == Long.MAX_VALUE;
+ }
+
+ @Override
+ public CompactSketch getResult(final boolean reset) {
+ return getResult(true, null, reset);
+ }
+
+ @Override
+ public CompactSketch getResult(final boolean dstOrdered, final MemorySegment dstSeg,
+ final boolean reset) {
+ final CompactSketch result = CompactOperations.componentsToCompact(
+ thetaLong_, curCount_, seedHash_, empty_, true, false, dstOrdered, dstSeg, hashArr_.clone());
+ if (reset) { reset(); }
+ return result;
+ }
+
+ @Override
+ public CompactSketch aNotB(final Sketch skA, final Sketch skB, final boolean dstOrdered,
+ final MemorySegment dstSeg) {
+ if (skA == null || skB == null) {
+ throw new SketchesArgumentException("Neither argument may be null");
+ }
+ //Both skA & skB are not null
+
+ final long minThetaLong = Math.min(skA.getThetaLong(), skB.getThetaLong());
+
+ if (skA.isEmpty()) { return skA.compact(dstOrdered, dstSeg); }
+ //A is not Empty
+ ThetaUtil.checkSeedHashes(skA.getSeedHash(), seedHash_);
+
+ if (skB.isEmpty()) {
+ return skA.compact(dstOrdered, dstSeg);
+ }
+ ThetaUtil.checkSeedHashes(skB.getSeedHash(), seedHash_);
+ //Both skA & skB are not empty
+
+ //process A
+ final long[] hashArrA = getHashArrA(skA);
+ final int countA = hashArrA.length;
+
+ //process B
+ final long[] hashArrOut = getResultHashArr(minThetaLong, countA, hashArrA, skB); //out is clone
+ final int countOut = hashArrOut.length;
+ final boolean empty = countOut == 0 && minThetaLong == Long.MAX_VALUE;
+
+ final CompactSketch result = CompactOperations.componentsToCompact(
+ minThetaLong, countOut, seedHash_, empty, true, false, dstOrdered, dstSeg, hashArrOut);
+ return result;
+ }
+
+ @Override
+ int getRetainedEntries() {
+ return curCount_;
+ }
+
+ //restricted
+
+ private static long[] getHashArrA(final Sketch skA) { //returns a new array
+ //Get skA cache as array
+ final CompactSketch cskA = skA.compact(false, null); //sorting not required
+ final long[] hashArrA = cskA.getCache().clone();
+ return hashArrA;
+ }
+
+ private static long[] getResultHashArr( //returns a new array
+ final long minThetaLong,
+ final int countA,
+ final long[] hashArrA,
+ final Sketch skB) {
+
+ // Rebuild or get hashtable of skB
+ final long[] hashTableB; //read only
+ if (skB instanceof CompactSketch) {
+ hashTableB = convertToHashTable(skB, minThetaLong, ThetaUtil.REBUILD_THRESHOLD);
+ } else {
+ hashTableB = skB.getCache();
+ }
+
+ //build temporary result arrays of skA
+ final long[] tmpHashArrA = new long[countA];
+
+ //search for non matches and build temp arrays
+ final int lgHTBLen = exactLog2OfLong(hashTableB.length);
+ int nonMatches = 0;
+ for (int i = 0; i < countA; i++) {
+ final long hash = hashArrA[i];
+ if (hash != 0 && hash < minThetaLong) { //only allows hashes of A < minTheta
+ final int index = hashSearch(hashTableB, lgHTBLen, hash);
+ if (index == -1) {
+ tmpHashArrA[nonMatches] = hash;
+ nonMatches++;
+ }
+ }
+ }
+ return Arrays.copyOfRange(tmpHashArrA, 0, nonMatches);
+ }
+
+ private static long[] convertToHashTable(
+ final Sketch sketch,
+ final long thetaLong,
+ final double rebuildThreshold) {
+ final int lgArrLongs = minLgHashTableSize(sketch.getRetainedEntries(true), rebuildThreshold);
+ final int arrLongs = 1 << lgArrLongs;
+ final long[] hashTable = new long[arrLongs];
+ checkThetaCorruption(thetaLong);
+ final HashIterator it = sketch.iterator();
+ while (it.next()) {
+ final long hash = it.get();
+ if (continueCondition(thetaLong, hash) ) {
+ continue;
+ }
+ hashSearchOrInsert(hashTable, lgArrLongs, hash);
+ }
+ return hashTable;
+ }
+
+ private void reset() {
+ thetaLong_ = Long.MAX_VALUE;
+ empty_ = true;
+ hashArr_ = new long[0];
+ curCount_ = 0;
+ }
+
+ @Override
+ long[] getCache() {
+ return hashArr_.clone();
+ }
+
+ @Override
+ short getSeedHash() {
+ return seedHash_;
+ }
+
+ @Override
+ long getThetaLong() {
+ return thetaLong_;
+ }
+
+ @Override
+ boolean isEmpty() {
+ return empty_;
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/BitPacking.java b/src/main/java/org/apache/datasketches/theta2/BitPacking.java
new file mode 100644
index 00000000..e2b6be2f
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/BitPacking.java
@@ -0,0 +1,6292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import org.apache.datasketches.common.SketchesArgumentException;
+
+/**
+ * Used as part of Theta compression.
+ */
+public class BitPacking {
+
+ /**
+ * The bit packing operation
+ * @param value the value to pack
+ * @param bits number of bits to pack
+ * @param buffer the output byte array buffer
+ * @param bufOffset the byte offset in the buffer
+ * @param bitOffset the bit offset
+ */
+ public static void packBits(final long value, int bits, final byte[] buffer, int bufOffset, final int bitOffset) {
+ if (bitOffset > 0) {
+ final int chunkBits = 8 - bitOffset;
+ final int mask = (1 << chunkBits) - 1;
+ if (bits < chunkBits) {
+ buffer[bufOffset] |= (value << (chunkBits - bits)) & mask;
+ return;
+ }
+ buffer[bufOffset++] |= (value >>> (bits - chunkBits)) & mask;
+ bits -= chunkBits;
+ }
+ while (bits >= 8) {
+ buffer[bufOffset++] = (byte)(value >>> (bits - 8));
+ bits -= 8;
+ }
+ if (bits > 0) {
+ buffer[bufOffset] = (byte)(value << (8 - bits));
+ }
+ }
+
+ /**
+ * The unpacking operation
+ * @param value the output array
+ * @param index index of the value array
+ * @param bits the number of bits to unpack
+ * @param buffer the input packed buffer
+ * @param bufOffset the buffer offset
+ * @param bitOffset the bit offset
+ */
+ public static void unpackBits(final long[] value, final int index, int bits, final byte[] buffer,
+ int bufOffset,final int bitOffset) {
+ final int availBits = 8 - bitOffset;
+ final int chunkBits = availBits <= bits ? availBits : bits;
+ final int mask = (1 << chunkBits) - 1;
+ value[index] = (buffer[bufOffset] >>> (availBits - chunkBits)) & mask;
+ bufOffset += availBits == chunkBits ? 1 : 0;
+ bits -= chunkBits;
+ while (bits >= 8) {
+ value[index] <<= 8;
+ value[index] |= (Byte.toUnsignedLong(buffer[bufOffset++]));
+ bits -= 8;
+ }
+ if (bits > 0) {
+ value[index] <<= bits;
+ value[index] |= Byte.toUnsignedLong(buffer[bufOffset]) >>> (8 - bits);
+ }
+ }
+
+ // pack given number of bits from a block of 8 64-bit values into bytes
+ // we don't need 0 and 64 bits
+ // we assume that higher bits (which we are not packing) are zeros
+ // this assumption allows to avoid masking operations
+
+ static void packBitsBlock8(final long[] values, final int i, final byte[] buf, final int off, final int bits) {
+ switch (bits) {
+ case 1: packBits1(values, i, buf, off); break;
+ case 2: packBits2(values, i, buf, off); break;
+ case 3: packBits3(values, i, buf, off); break;
+ case 4: packBits4(values, i, buf, off); break;
+ case 5: packBits5(values, i, buf, off); break;
+ case 6: packBits6(values, i, buf, off); break;
+ case 7: packBits7(values, i, buf, off); break;
+ case 8: packBits8(values, i, buf, off); break;
+ case 9: packBits9(values, i, buf, off); break;
+ case 10: packBits10(values, i, buf, off); break;
+ case 11: packBits11(values, i, buf, off); break;
+ case 12: packBits12(values, i, buf, off); break;
+ case 13: packBits13(values, i, buf, off); break;
+ case 14: packBits14(values, i, buf, off); break;
+ case 15: packBits15(values, i, buf, off); break;
+ case 16: packBits16(values, i, buf, off); break;
+ case 17: packBits17(values, i, buf, off); break;
+ case 18: packBits18(values, i, buf, off); break;
+ case 19: packBits19(values, i, buf, off); break;
+ case 20: packBits20(values, i, buf, off); break;
+ case 21: packBits21(values, i, buf, off); break;
+ case 22: packBits22(values, i, buf, off); break;
+ case 23: packBits23(values, i, buf, off); break;
+ case 24: packBits24(values, i, buf, off); break;
+ case 25: packBits25(values, i, buf, off); break;
+ case 26: packBits26(values, i, buf, off); break;
+ case 27: packBits27(values, i, buf, off); break;
+ case 28: packBits28(values, i, buf, off); break;
+ case 29: packBits29(values, i, buf, off); break;
+ case 30: packBits30(values, i, buf, off); break;
+ case 31: packBits31(values, i, buf, off); break;
+ case 32: packBits32(values, i, buf, off); break;
+ case 33: packBits33(values, i, buf, off); break;
+ case 34: packBits34(values, i, buf, off); break;
+ case 35: packBits35(values, i, buf, off); break;
+ case 36: packBits36(values, i, buf, off); break;
+ case 37: packBits37(values, i, buf, off); break;
+ case 38: packBits38(values, i, buf, off); break;
+ case 39: packBits39(values, i, buf, off); break;
+ case 40: packBits40(values, i, buf, off); break;
+ case 41: packBits41(values, i, buf, off); break;
+ case 42: packBits42(values, i, buf, off); break;
+ case 43: packBits43(values, i, buf, off); break;
+ case 44: packBits44(values, i, buf, off); break;
+ case 45: packBits45(values, i, buf, off); break;
+ case 46: packBits46(values, i, buf, off); break;
+ case 47: packBits47(values, i, buf, off); break;
+ case 48: packBits48(values, i, buf, off); break;
+ case 49: packBits49(values, i, buf, off); break;
+ case 50: packBits50(values, i, buf, off); break;
+ case 51: packBits51(values, i, buf, off); break;
+ case 52: packBits52(values, i, buf, off); break;
+ case 53: packBits53(values, i, buf, off); break;
+ case 54: packBits54(values, i, buf, off); break;
+ case 55: packBits55(values, i, buf, off); break;
+ case 56: packBits56(values, i, buf, off); break;
+ case 57: packBits57(values, i, buf, off); break;
+ case 58: packBits58(values, i, buf, off); break;
+ case 59: packBits59(values, i, buf, off); break;
+ case 60: packBits60(values, i, buf, off); break;
+ case 61: packBits61(values, i, buf, off); break;
+ case 62: packBits62(values, i, buf, off); break;
+ case 63: packBits63(values, i, buf, off); break;
+ default: throw new SketchesArgumentException("wrong number of bits in packBitsBlock8: " + bits);
+ }
+ }
+
+ static void unpackBitsBlock8(final long[] values, final int i, final byte[] buf, final int off, final int bits) {
+ switch (bits) {
+ case 1: unpackBits1(values, i, buf, off); break;
+ case 2: unpackBits2(values, i, buf, off); break;
+ case 3: unpackBits3(values, i, buf, off); break;
+ case 4: unpackBits4(values, i, buf, off); break;
+ case 5: unpackBits5(values, i, buf, off); break;
+ case 6: unpackBits6(values, i, buf, off); break;
+ case 7: unpackBits7(values, i, buf, off); break;
+ case 8: unpackBits8(values, i, buf, off); break;
+ case 9: unpackBits9(values, i, buf, off); break;
+ case 10: unpackBits10(values, i, buf, off); break;
+ case 11: unpackBits11(values, i, buf, off); break;
+ case 12: unpackBits12(values, i, buf, off); break;
+ case 13: unpackBits13(values, i, buf, off); break;
+ case 14: unpackBits14(values, i, buf, off); break;
+ case 15: unpackBits15(values, i, buf, off); break;
+ case 16: unpackBits16(values, i, buf, off); break;
+ case 17: unpackBits17(values, i, buf, off); break;
+ case 18: unpackBits18(values, i, buf, off); break;
+ case 19: unpackBits19(values, i, buf, off); break;
+ case 20: unpackBits20(values, i, buf, off); break;
+ case 21: unpackBits21(values, i, buf, off); break;
+ case 22: unpackBits22(values, i, buf, off); break;
+ case 23: unpackBits23(values, i, buf, off); break;
+ case 24: unpackBits24(values, i, buf, off); break;
+ case 25: unpackBits25(values, i, buf, off); break;
+ case 26: unpackBits26(values, i, buf, off); break;
+ case 27: unpackBits27(values, i, buf, off); break;
+ case 28: unpackBits28(values, i, buf, off); break;
+ case 29: unpackBits29(values, i, buf, off); break;
+ case 30: unpackBits30(values, i, buf, off); break;
+ case 31: unpackBits31(values, i, buf, off); break;
+ case 32: unpackBits32(values, i, buf, off); break;
+ case 33: unpackBits33(values, i, buf, off); break;
+ case 34: unpackBits34(values, i, buf, off); break;
+ case 35: unpackBits35(values, i, buf, off); break;
+ case 36: unpackBits36(values, i, buf, off); break;
+ case 37: unpackBits37(values, i, buf, off); break;
+ case 38: unpackBits38(values, i, buf, off); break;
+ case 39: unpackBits39(values, i, buf, off); break;
+ case 40: unpackBits40(values, i, buf, off); break;
+ case 41: unpackBits41(values, i, buf, off); break;
+ case 42: unpackBits42(values, i, buf, off); break;
+ case 43: unpackBits43(values, i, buf, off); break;
+ case 44: unpackBits44(values, i, buf, off); break;
+ case 45: unpackBits45(values, i, buf, off); break;
+ case 46: unpackBits46(values, i, buf, off); break;
+ case 47: unpackBits47(values, i, buf, off); break;
+ case 48: unpackBits48(values, i, buf, off); break;
+ case 49: unpackBits49(values, i, buf, off); break;
+ case 50: unpackBits50(values, i, buf, off); break;
+ case 51: unpackBits51(values, i, buf, off); break;
+ case 52: unpackBits52(values, i, buf, off); break;
+ case 53: unpackBits53(values, i, buf, off); break;
+ case 54: unpackBits54(values, i, buf, off); break;
+ case 55: unpackBits55(values, i, buf, off); break;
+ case 56: unpackBits56(values, i, buf, off); break;
+ case 57: unpackBits57(values, i, buf, off); break;
+ case 58: unpackBits58(values, i, buf, off); break;
+ case 59: unpackBits59(values, i, buf, off); break;
+ case 60: unpackBits60(values, i, buf, off); break;
+ case 61: unpackBits61(values, i, buf, off); break;
+ case 62: unpackBits62(values, i, buf, off); break;
+ case 63: unpackBits63(values, i, buf, off); break;
+ default: throw new SketchesArgumentException("wrong number of bits unpackBitsBlock8: " + bits);
+ }
+ }
+
+ static void packBits1(final long[] values, final int i, final byte[] buf, final int off) {
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off] |= values[i + 1] << 6;
+ buf[off] |= values[i + 2] << 5;
+ buf[off] |= values[i + 3] << 4;
+ buf[off] |= values[i + 4] << 3;
+ buf[off] |= values[i + 5] << 2;
+ buf[off] |= values[i + 6] << 1;
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits2(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off] |= values[i + 1] << 4;
+ buf[off] |= values[i + 2] << 2;
+ buf[off++] |= values[i + 3];
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off] |= values[i + 5] << 4;
+ buf[off] |= values[i + 6] << 2;
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits3(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off] |= values[i + 1] << 2;
+ buf[off++] |= values[i + 2] >>> 1;
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off] |= values[i + 3] << 4;
+ buf[off] |= values[i + 4] << 1;
+ buf[off++] |= values[i + 5] >>> 2;
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off] |= values[i + 6] << 3;
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits4(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1];
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3];
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5];
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits5(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 2;
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off] |= values[i + 2] << 1;
+ buf[off++] |= values[i + 3] >>> 4;
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 1;
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off] |= values[i + 5] << 2;
+ buf[off++] |= values[i + 6] >>> 3;
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits6(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 4;
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 2;
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3];
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 4;
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 2;
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits7(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 6;
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 5;
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 4;
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 3;
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 2;
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 1;
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off] |= values[i + 7];
+ }
+
+ static void packBits8(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0]);
+ buf[off++] = (byte) (values[i + 1]);
+ buf[off++] = (byte) (values[i + 2]);
+ buf[off++] = (byte) (values[i + 3]);
+ buf[off++] = (byte) (values[i + 4]);
+ buf[off++] = (byte) (values[i + 5]);
+ buf[off++] = (byte) (values[i + 6]);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits9(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 2;
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 3;
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 4;
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 5;
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 6;
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 7;
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits10(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 4;
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 6;
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 8;
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 4;
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 6;
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits11(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 6;
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 9;
+
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 4;
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 7;
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 10;
+
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 5;
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits12(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 8;
+
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 8;
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 8;
+
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits13(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 10;
+
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 7;
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 12;
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 9;
+
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 6;
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 11;
+
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits14(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 12;
+
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 10;
+
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 8;
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 12;
+
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 10;
+
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits15(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 14;
+
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 13;
+
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 12;
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 11;
+
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 10;
+
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 9;
+
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 8;
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits16(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits17(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 10;
+
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 11;
+
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 12;
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 13;
+
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 14;
+
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 15;
+
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits18(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 12;
+
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 14;
+
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 16;
+
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 12;
+
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 14;
+
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits19(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 14;
+
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 17;
+
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 12;
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 15;
+
+ buf[off++] |= values[i + 4] >>> 7;
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 18;
+
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 13;
+
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits20(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 16;
+
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 16;
+
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 16;
+
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits21(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 18;
+
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 15;
+
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 20;
+
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 17;
+
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 14;
+
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 19;
+
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits22(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 20;
+
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 18;
+
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 16;
+
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 20;
+
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 18;
+
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits23(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 22;
+
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 21;
+
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 20;
+
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 19;
+
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 18;
+
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 17;
+
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 16;
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits24(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 16);
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 16);
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 16);
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 16);
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits25(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 17);
+
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 18;
+
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 19;
+
+ buf[off++] = (byte) (values[i + 2] >>> 11);
+
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 20;
+
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 21;
+
+ buf[off++] = (byte) (values[i + 4] >>> 13);
+
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 22;
+
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 23;
+
+ buf[off++] = (byte) (values[i + 6] >>> 15);
+
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 24;
+
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits26(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 18);
+
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 20;
+
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 22;
+
+ buf[off++] = (byte) (values[i + 2] >>> 14);
+
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 24;
+
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 18);
+
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 20;
+
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 22;
+
+ buf[off++] = (byte) (values[i + 6] >>> 14);
+
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 24;
+
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits27(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 19);
+
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 22;
+
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 25;
+
+ buf[off++] = (byte) (values[i + 2] >>> 17);
+
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 20;
+
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 23;
+
+ buf[off++] = (byte) (values[i + 4] >>> 15);
+
+ buf[off++] = (byte) (values[i + 4] >>> 7);
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 26;
+
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 21;
+
+ buf[off++] = (byte) (values[i + 6] >>> 13);
+
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 24;
+
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits28(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 20);
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 24;
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+ buf[off++] = (byte) (values[i + 2] >>> 20);
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 24;
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+ buf[off++] = (byte) (values[i + 4] >>> 20);
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 24;
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+ buf[off++] = (byte) (values[i + 6] >>> 20);
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 24;
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits29(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 21);
+
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 26;
+
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 23;
+
+ buf[off++] = (byte) (values[i + 2] >>> 15);
+
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 28;
+
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 25;
+
+ buf[off++] = (byte) (values[i + 4] >>> 17);
+
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 22;
+
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 27;
+
+ buf[off++] = (byte) (values[i + 6] >>> 19);
+
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 24;
+
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits30(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 22);
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 28;
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 26;
+ buf[off++] = (byte) (values[i + 2] >>> 18);
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 24;
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 22);
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 28;
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 26;
+ buf[off++] = (byte) (values[i + 6] >>> 18);
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 24;
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits31(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 23);
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 30;
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 29;
+ buf[off++] = (byte) (values[i + 2] >>> 21);
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 28;
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 27;
+ buf[off++] = (byte) (values[i + 4] >>> 19);
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 26;
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 25;
+ buf[off++] = (byte) (values[i + 6] >>> 17);
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 24;
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits32(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 24);
+ buf[off++] = (byte) (values[i + 0] >>> 16);
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 24);
+ buf[off++] = (byte) (values[i + 2] >>> 16);
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 24);
+ buf[off++] = (byte) (values[i + 4] >>> 16);
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 24);
+ buf[off++] = (byte) (values[i + 6] >>> 16);
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits33(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 25);
+ buf[off++] = (byte) (values[i + 0] >>> 17);
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 26;
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 27;
+ buf[off++] = (byte) (values[i + 2] >>> 19);
+ buf[off++] = (byte) (values[i + 2] >>> 11);
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 28;
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 29;
+ buf[off++] = (byte) (values[i + 4] >>> 21);
+ buf[off++] = (byte) (values[i + 4] >>> 13);
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 30;
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 31;
+ buf[off++] = (byte) (values[i + 6] >>> 23);
+ buf[off++] = (byte) (values[i + 6] >>> 15);
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits34(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 26);
+ buf[off++] = (byte) (values[i + 0] >>> 18);
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 28;
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 30;
+ buf[off++] = (byte) (values[i + 2] >>> 22);
+ buf[off++] = (byte) (values[i + 2] >>> 14);
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 32;
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 26);
+ buf[off++] = (byte) (values[i + 4] >>> 18);
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 28;
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 30;
+ buf[off++] = (byte) (values[i + 6] >>> 22);
+ buf[off++] = (byte) (values[i + 6] >>> 14);
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits35(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 27);
+ buf[off++] = (byte) (values[i + 0] >>> 19);
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 30;
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 33;
+ buf[off++] = (byte) (values[i + 2] >>> 25);
+ buf[off++] = (byte) (values[i + 2] >>> 17);
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 28;
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 31;
+ buf[off++] = (byte) (values[i + 4] >>> 23);
+ buf[off++] = (byte) (values[i + 4] >>> 15);
+ buf[off++] = (byte) (values[i + 4] >>> 7);
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 34;
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 29;
+ buf[off++] = (byte) (values[i + 6] >>> 21);
+ buf[off++] = (byte) (values[i + 6] >>> 13);
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits36(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 28);
+ buf[off++] = (byte) (values[i + 0] >>> 20);
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 32;
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 28);
+ buf[off++] = (byte) (values[i + 2] >>> 20);
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 32;
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 28);
+ buf[off++] = (byte) (values[i + 4] >>> 20);
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 32;
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 28);
+ buf[off++] = (byte) (values[i + 6] >>> 20);
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits37(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 29);
+ buf[off++] = (byte) (values[i + 0] >>> 21);
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 34;
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 31;
+ buf[off++] = (byte) (values[i + 2] >>> 23);
+ buf[off++] = (byte) (values[i + 2] >>> 15);
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 36;
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 33;
+ buf[off++] = (byte) (values[i + 4] >>> 25);
+ buf[off++] = (byte) (values[i + 4] >>> 17);
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 30;
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 35;
+ buf[off++] = (byte) (values[i + 6] >>> 27);
+ buf[off++] = (byte) (values[i + 6] >>> 19);
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits38(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 30);
+ buf[off++] = (byte) (values[i + 0] >>> 22);
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 36;
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 34;
+ buf[off++] = (byte) (values[i + 2] >>> 26);
+ buf[off++] = (byte) (values[i + 2] >>> 18);
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 32;
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 30);
+ buf[off++] = (byte) (values[i + 4] >>> 22);
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 36;
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 34;
+ buf[off++] = (byte) (values[i + 6] >>> 26);
+ buf[off++] = (byte) (values[i + 6] >>> 18);
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits39(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 31);
+ buf[off++] = (byte) (values[i + 0] >>> 23);
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 38;
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 37;
+ buf[off++] = (byte) (values[i + 2] >>> 29);
+ buf[off++] = (byte) (values[i + 2] >>> 21);
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 36;
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 35;
+ buf[off++] = (byte) (values[i + 4] >>> 27);
+ buf[off++] = (byte) (values[i + 4] >>> 19);
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 34;
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 33;
+ buf[off++] = (byte) (values[i + 6] >>> 25);
+ buf[off++] = (byte) (values[i + 6] >>> 17);
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 32;
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits40(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 32);
+ buf[off++] = (byte) (values[i + 0] >>> 24);
+ buf[off++] = (byte) (values[i + 0] >>> 16);
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 32);
+ buf[off++] = (byte) (values[i + 2] >>> 24);
+ buf[off++] = (byte) (values[i + 2] >>> 16);
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 32);
+ buf[off++] = (byte) (values[i + 4] >>> 24);
+ buf[off++] = (byte) (values[i + 4] >>> 16);
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 32);
+ buf[off++] = (byte) (values[i + 6] >>> 24);
+ buf[off++] = (byte) (values[i + 6] >>> 16);
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits41(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 33);
+ buf[off++] = (byte) (values[i + 0] >>> 25);
+ buf[off++] = (byte) (values[i + 0] >>> 17);
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 34;
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 35;
+ buf[off++] = (byte) (values[i + 2] >>> 27);
+ buf[off++] = (byte) (values[i + 2] >>> 19);
+ buf[off++] = (byte) (values[i + 2] >>> 11);
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 36;
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 37;
+ buf[off++] = (byte) (values[i + 4] >>> 29);
+ buf[off++] = (byte) (values[i + 4] >>> 21);
+ buf[off++] = (byte) (values[i + 4] >>> 13);
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 38;
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 39;
+ buf[off++] = (byte) (values[i + 6] >>> 31);
+ buf[off++] = (byte) (values[i + 6] >>> 23);
+ buf[off++] = (byte) (values[i + 6] >>> 15);
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits42(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 34);
+ buf[off++] = (byte) (values[i + 0] >>> 26);
+ buf[off++] = (byte) (values[i + 0] >>> 18);
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 36;
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 38;
+ buf[off++] = (byte) (values[i + 2] >>> 30);
+ buf[off++] = (byte) (values[i + 2] >>> 22);
+ buf[off++] = (byte) (values[i + 2] >>> 14);
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 40;
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 34);
+ buf[off++] = (byte) (values[i + 4] >>> 26);
+ buf[off++] = (byte) (values[i + 4] >>> 18);
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 36;
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 38;
+ buf[off++] = (byte) (values[i + 6] >>> 30);
+ buf[off++] = (byte) (values[i + 6] >>> 22);
+ buf[off++] = (byte) (values[i + 6] >>> 14);
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits43(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 35);
+ buf[off++] = (byte) (values[i + 0] >>> 27);
+ buf[off++] = (byte) (values[i + 0] >>> 19);
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 38;
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 41;
+ buf[off++] = (byte) (values[i + 2] >>> 33);
+ buf[off++] = (byte) (values[i + 2] >>> 25);
+ buf[off++] = (byte) (values[i + 2] >>> 17);
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 36;
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 39;
+ buf[off++] = (byte) (values[i + 4] >>> 31);
+ buf[off++] = (byte) (values[i + 4] >>> 23);
+ buf[off++] = (byte) (values[i + 4] >>> 15);
+ buf[off++] = (byte) (values[i + 4] >>> 7);
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 42;
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 37;
+ buf[off++] = (byte) (values[i + 6] >>> 29);
+ buf[off++] = (byte) (values[i + 6] >>> 21);
+ buf[off++] = (byte) (values[i + 6] >>> 13);
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits44(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 36);
+ buf[off++] = (byte) (values[i + 0] >>> 28);
+ buf[off++] = (byte) (values[i + 0] >>> 20);
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 40;
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 36);
+ buf[off++] = (byte) (values[i + 2] >>> 28);
+ buf[off++] = (byte) (values[i + 2] >>> 20);
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 40;
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 36);
+ buf[off++] = (byte) (values[i + 4] >>> 28);
+ buf[off++] = (byte) (values[i + 4] >>> 20);
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 40;
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 36);
+ buf[off++] = (byte) (values[i + 6] >>> 28);
+ buf[off++] = (byte) (values[i + 6] >>> 20);
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits45(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 37);
+ buf[off++] = (byte) (values[i + 0] >>> 29);
+ buf[off++] = (byte) (values[i + 0] >>> 21);
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 42;
+ buf[off++] = (byte) (values[i + 1] >>> 34);
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 39;
+ buf[off++] = (byte) (values[i + 2] >>> 31);
+ buf[off++] = (byte) (values[i + 2] >>> 23);
+ buf[off++] = (byte) (values[i + 2] >>> 15);
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 44;
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 41;
+ buf[off++] = (byte) (values[i + 4] >>> 33);
+ buf[off++] = (byte) (values[i + 4] >>> 25);
+ buf[off++] = (byte) (values[i + 4] >>> 17);
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 38;
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 43;
+ buf[off++] = (byte) (values[i + 6] >>> 35);
+ buf[off++] = (byte) (values[i + 6] >>> 27);
+ buf[off++] = (byte) (values[i + 6] >>> 19);
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits46(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 38);
+ buf[off++] = (byte) (values[i + 0] >>> 30);
+ buf[off++] = (byte) (values[i + 0] >>> 22);
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 44;
+ buf[off++] = (byte) (values[i + 1] >>> 36);
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 42;
+ buf[off++] = (byte) (values[i + 2] >>> 34);
+ buf[off++] = (byte) (values[i + 2] >>> 26);
+ buf[off++] = (byte) (values[i + 2] >>> 18);
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 40;
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 38);
+ buf[off++] = (byte) (values[i + 4] >>> 30);
+ buf[off++] = (byte) (values[i + 4] >>> 22);
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 44;
+ buf[off++] = (byte) (values[i + 5] >>> 36);
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 42;
+ buf[off++] = (byte) (values[i + 6] >>> 34);
+ buf[off++] = (byte) (values[i + 6] >>> 26);
+ buf[off++] = (byte) (values[i + 6] >>> 18);
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits47(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 39);
+ buf[off++] = (byte) (values[i + 0] >>> 31);
+ buf[off++] = (byte) (values[i + 0] >>> 23);
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 46;
+ buf[off++] = (byte) (values[i + 1] >>> 38);
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 45;
+ buf[off++] = (byte) (values[i + 2] >>> 37);
+ buf[off++] = (byte) (values[i + 2] >>> 29);
+ buf[off++] = (byte) (values[i + 2] >>> 21);
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 44;
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 43;
+ buf[off++] = (byte) (values[i + 4] >>> 35);
+ buf[off++] = (byte) (values[i + 4] >>> 27);
+ buf[off++] = (byte) (values[i + 4] >>> 19);
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 42;
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 41;
+ buf[off++] = (byte) (values[i + 6] >>> 33);
+ buf[off++] = (byte) (values[i + 6] >>> 25);
+ buf[off++] = (byte) (values[i + 6] >>> 17);
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 40;
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits48(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 40);
+ buf[off++] = (byte) (values[i + 0] >>> 32);
+ buf[off++] = (byte) (values[i + 0] >>> 24);
+ buf[off++] = (byte) (values[i + 0] >>> 16);
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 40);
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 40);
+ buf[off++] = (byte) (values[i + 2] >>> 32);
+ buf[off++] = (byte) (values[i + 2] >>> 24);
+ buf[off++] = (byte) (values[i + 2] >>> 16);
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 40);
+ buf[off++] = (byte) (values[i + 4] >>> 32);
+ buf[off++] = (byte) (values[i + 4] >>> 24);
+ buf[off++] = (byte) (values[i + 4] >>> 16);
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 40);
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 40);
+ buf[off++] = (byte) (values[i + 6] >>> 32);
+ buf[off++] = (byte) (values[i + 6] >>> 24);
+ buf[off++] = (byte) (values[i + 6] >>> 16);
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits49(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 41);
+ buf[off++] = (byte) (values[i + 0] >>> 33);
+ buf[off++] = (byte) (values[i + 0] >>> 25);
+ buf[off++] = (byte) (values[i + 0] >>> 17);
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 42;
+ buf[off++] = (byte) (values[i + 1] >>> 34);
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 43;
+ buf[off++] = (byte) (values[i + 2] >>> 35);
+ buf[off++] = (byte) (values[i + 2] >>> 27);
+ buf[off++] = (byte) (values[i + 2] >>> 19);
+ buf[off++] = (byte) (values[i + 2] >>> 11);
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 44;
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 45;
+ buf[off++] = (byte) (values[i + 4] >>> 37);
+ buf[off++] = (byte) (values[i + 4] >>> 29);
+ buf[off++] = (byte) (values[i + 4] >>> 21);
+ buf[off++] = (byte) (values[i + 4] >>> 13);
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 46;
+ buf[off++] = (byte) (values[i + 5] >>> 38);
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 47;
+ buf[off++] = (byte) (values[i + 6] >>> 39);
+ buf[off++] = (byte) (values[i + 6] >>> 31);
+ buf[off++] = (byte) (values[i + 6] >>> 23);
+ buf[off++] = (byte) (values[i + 6] >>> 15);
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits50(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 42);
+ buf[off++] = (byte) (values[i + 0] >>> 34);
+ buf[off++] = (byte) (values[i + 0] >>> 26);
+ buf[off++] = (byte) (values[i + 0] >>> 18);
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 44;
+ buf[off++] = (byte) (values[i + 1] >>> 36);
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 46;
+ buf[off++] = (byte) (values[i + 2] >>> 38);
+ buf[off++] = (byte) (values[i + 2] >>> 30);
+ buf[off++] = (byte) (values[i + 2] >>> 22);
+ buf[off++] = (byte) (values[i + 2] >>> 14);
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 48;
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 42);
+ buf[off++] = (byte) (values[i + 4] >>> 34);
+ buf[off++] = (byte) (values[i + 4] >>> 26);
+ buf[off++] = (byte) (values[i + 4] >>> 18);
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 44;
+ buf[off++] = (byte) (values[i + 5] >>> 36);
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 46;
+ buf[off++] = (byte) (values[i + 6] >>> 38);
+ buf[off++] = (byte) (values[i + 6] >>> 30);
+ buf[off++] = (byte) (values[i + 6] >>> 22);
+ buf[off++] = (byte) (values[i + 6] >>> 14);
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits51(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 43);
+ buf[off++] = (byte) (values[i + 0] >>> 35);
+ buf[off++] = (byte) (values[i + 0] >>> 27);
+ buf[off++] = (byte) (values[i + 0] >>> 19);
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 46;
+ buf[off++] = (byte) (values[i + 1] >>> 38);
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 49;
+ buf[off++] = (byte) (values[i + 2] >>> 41);
+ buf[off++] = (byte) (values[i + 2] >>> 33);
+ buf[off++] = (byte) (values[i + 2] >>> 25);
+ buf[off++] = (byte) (values[i + 2] >>> 17);
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 44;
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 47;
+ buf[off++] = (byte) (values[i + 4] >>> 39);
+ buf[off++] = (byte) (values[i + 4] >>> 31);
+ buf[off++] = (byte) (values[i + 4] >>> 23);
+ buf[off++] = (byte) (values[i + 4] >>> 15);
+ buf[off++] = (byte) (values[i + 4] >>> 7);
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 50;
+ buf[off++] = (byte) (values[i + 5] >>> 42);
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 45;
+ buf[off++] = (byte) (values[i + 6] >>> 37);
+ buf[off++] = (byte) (values[i + 6] >>> 29);
+ buf[off++] = (byte) (values[i + 6] >>> 21);
+ buf[off++] = (byte) (values[i + 6] >>> 13);
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits52(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 44);
+ buf[off++] = (byte) (values[i + 0] >>> 36);
+ buf[off++] = (byte) (values[i + 0] >>> 28);
+ buf[off++] = (byte) (values[i + 0] >>> 20);
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 48;
+ buf[off++] = (byte) (values[i + 1] >>> 40);
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 44);
+ buf[off++] = (byte) (values[i + 2] >>> 36);
+ buf[off++] = (byte) (values[i + 2] >>> 28);
+ buf[off++] = (byte) (values[i + 2] >>> 20);
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 48;
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 44);
+ buf[off++] = (byte) (values[i + 4] >>> 36);
+ buf[off++] = (byte) (values[i + 4] >>> 28);
+ buf[off++] = (byte) (values[i + 4] >>> 20);
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 48;
+ buf[off++] = (byte) (values[i + 5] >>> 40);
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 44);
+ buf[off++] = (byte) (values[i + 6] >>> 36);
+ buf[off++] = (byte) (values[i + 6] >>> 28);
+ buf[off++] = (byte) (values[i + 6] >>> 20);
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits53(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 45);
+ buf[off++] = (byte) (values[i + 0] >>> 37);
+ buf[off++] = (byte) (values[i + 0] >>> 29);
+ buf[off++] = (byte) (values[i + 0] >>> 21);
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 50;
+ buf[off++] = (byte) (values[i + 1] >>> 42);
+ buf[off++] = (byte) (values[i + 1] >>> 34);
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 47;
+ buf[off++] = (byte) (values[i + 2] >>> 39);
+ buf[off++] = (byte) (values[i + 2] >>> 31);
+ buf[off++] = (byte) (values[i + 2] >>> 23);
+ buf[off++] = (byte) (values[i + 2] >>> 15);
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 52;
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 49;
+ buf[off++] = (byte) (values[i + 4] >>> 41);
+ buf[off++] = (byte) (values[i + 4] >>> 33);
+ buf[off++] = (byte) (values[i + 4] >>> 25);
+ buf[off++] = (byte) (values[i + 4] >>> 17);
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 46;
+ buf[off++] = (byte) (values[i + 5] >>> 38);
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 51;
+ buf[off++] = (byte) (values[i + 6] >>> 43);
+ buf[off++] = (byte) (values[i + 6] >>> 35);
+ buf[off++] = (byte) (values[i + 6] >>> 27);
+ buf[off++] = (byte) (values[i + 6] >>> 19);
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits54(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 46);
+ buf[off++] = (byte) (values[i + 0] >>> 38);
+ buf[off++] = (byte) (values[i + 0] >>> 30);
+ buf[off++] = (byte) (values[i + 0] >>> 22);
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 52;
+ buf[off++] = (byte) (values[i + 1] >>> 44);
+ buf[off++] = (byte) (values[i + 1] >>> 36);
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 50;
+ buf[off++] = (byte) (values[i + 2] >>> 42);
+ buf[off++] = (byte) (values[i + 2] >>> 34);
+ buf[off++] = (byte) (values[i + 2] >>> 26);
+ buf[off++] = (byte) (values[i + 2] >>> 18);
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 48;
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 46);
+ buf[off++] = (byte) (values[i + 4] >>> 38);
+ buf[off++] = (byte) (values[i + 4] >>> 30);
+ buf[off++] = (byte) (values[i + 4] >>> 22);
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 52;
+ buf[off++] = (byte) (values[i + 5] >>> 44);
+ buf[off++] = (byte) (values[i + 5] >>> 36);
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 50;
+ buf[off++] = (byte) (values[i + 6] >>> 42);
+ buf[off++] = (byte) (values[i + 6] >>> 34);
+ buf[off++] = (byte) (values[i + 6] >>> 26);
+ buf[off++] = (byte) (values[i + 6] >>> 18);
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits55(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 47);
+ buf[off++] = (byte) (values[i + 0] >>> 39);
+ buf[off++] = (byte) (values[i + 0] >>> 31);
+ buf[off++] = (byte) (values[i + 0] >>> 23);
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 54;
+ buf[off++] = (byte) (values[i + 1] >>> 46);
+ buf[off++] = (byte) (values[i + 1] >>> 38);
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 53;
+ buf[off++] = (byte) (values[i + 2] >>> 45);
+ buf[off++] = (byte) (values[i + 2] >>> 37);
+ buf[off++] = (byte) (values[i + 2] >>> 29);
+ buf[off++] = (byte) (values[i + 2] >>> 21);
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 52;
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 51;
+ buf[off++] = (byte) (values[i + 4] >>> 43);
+ buf[off++] = (byte) (values[i + 4] >>> 35);
+ buf[off++] = (byte) (values[i + 4] >>> 27);
+ buf[off++] = (byte) (values[i + 4] >>> 19);
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 50;
+ buf[off++] = (byte) (values[i + 5] >>> 42);
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 49;
+ buf[off++] = (byte) (values[i + 6] >>> 41);
+ buf[off++] = (byte) (values[i + 6] >>> 33);
+ buf[off++] = (byte) (values[i + 6] >>> 25);
+ buf[off++] = (byte) (values[i + 6] >>> 17);
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 48;
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits56(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 48);
+ buf[off++] = (byte) (values[i + 0] >>> 40);
+ buf[off++] = (byte) (values[i + 0] >>> 32);
+ buf[off++] = (byte) (values[i + 0] >>> 24);
+ buf[off++] = (byte) (values[i + 0] >>> 16);
+ buf[off++] = (byte) (values[i + 0] >>> 8);
+ buf[off++] = (byte) (values[i + 0]);
+
+ buf[off++] = (byte) (values[i + 1] >>> 48);
+ buf[off++] = (byte) (values[i + 1] >>> 40);
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 48);
+ buf[off++] = (byte) (values[i + 2] >>> 40);
+ buf[off++] = (byte) (values[i + 2] >>> 32);
+ buf[off++] = (byte) (values[i + 2] >>> 24);
+ buf[off++] = (byte) (values[i + 2] >>> 16);
+ buf[off++] = (byte) (values[i + 2] >>> 8);
+ buf[off++] = (byte) (values[i + 2]);
+
+ buf[off++] = (byte) (values[i + 3] >>> 48);
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 48);
+ buf[off++] = (byte) (values[i + 4] >>> 40);
+ buf[off++] = (byte) (values[i + 4] >>> 32);
+ buf[off++] = (byte) (values[i + 4] >>> 24);
+ buf[off++] = (byte) (values[i + 4] >>> 16);
+ buf[off++] = (byte) (values[i + 4] >>> 8);
+ buf[off++] = (byte) (values[i + 4]);
+
+ buf[off++] = (byte) (values[i + 5] >>> 48);
+ buf[off++] = (byte) (values[i + 5] >>> 40);
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 48);
+ buf[off++] = (byte) (values[i + 6] >>> 40);
+ buf[off++] = (byte) (values[i + 6] >>> 32);
+ buf[off++] = (byte) (values[i + 6] >>> 24);
+ buf[off++] = (byte) (values[i + 6] >>> 16);
+ buf[off++] = (byte) (values[i + 6] >>> 8);
+ buf[off++] = (byte) (values[i + 6]);
+
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits57(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 49);
+ buf[off++] = (byte) (values[i + 0] >>> 41);
+ buf[off++] = (byte) (values[i + 0] >>> 33);
+ buf[off++] = (byte) (values[i + 0] >>> 25);
+ buf[off++] = (byte) (values[i + 0] >>> 17);
+ buf[off++] = (byte) (values[i + 0] >>> 9);
+ buf[off++] = (byte) (values[i + 0] >>> 1);
+
+ buf[off] = (byte) (values[i + 0] << 7);
+ buf[off++] |= values[i + 1] >>> 50;
+ buf[off++] = (byte) (values[i + 1] >>> 42);
+ buf[off++] = (byte) (values[i + 1] >>> 34);
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 51;
+ buf[off++] = (byte) (values[i + 2] >>> 43);
+ buf[off++] = (byte) (values[i + 2] >>> 35);
+ buf[off++] = (byte) (values[i + 2] >>> 27);
+ buf[off++] = (byte) (values[i + 2] >>> 19);
+ buf[off++] = (byte) (values[i + 2] >>> 11);
+ buf[off++] = (byte) (values[i + 2] >>> 3);
+
+ buf[off] = (byte) (values[i + 2] << 5);
+ buf[off++] |= values[i + 3] >>> 52;
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 53;
+ buf[off++] = (byte) (values[i + 4] >>> 45);
+ buf[off++] = (byte) (values[i + 4] >>> 37);
+ buf[off++] = (byte) (values[i + 4] >>> 29);
+ buf[off++] = (byte) (values[i + 4] >>> 21);
+ buf[off++] = (byte) (values[i + 4] >>> 13);
+ buf[off++] = (byte) (values[i + 4] >>> 5);
+
+ buf[off] = (byte) (values[i + 4] << 3);
+ buf[off++] |= values[i + 5] >>> 54;
+ buf[off++] = (byte) (values[i + 5] >>> 46);
+ buf[off++] = (byte) (values[i + 5] >>> 38);
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 55;
+ buf[off++] = (byte) (values[i + 6] >>> 47);
+ buf[off++] = (byte) (values[i + 6] >>> 39);
+ buf[off++] = (byte) (values[i + 6] >>> 31);
+ buf[off++] = (byte) (values[i + 6] >>> 23);
+ buf[off++] = (byte) (values[i + 6] >>> 15);
+ buf[off++] = (byte) (values[i + 6] >>> 7);
+
+ buf[off] = (byte) (values[i + 6] << 1);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits58(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 50);
+ buf[off++] = (byte) (values[i + 0] >>> 42);
+ buf[off++] = (byte) (values[i + 0] >>> 34);
+ buf[off++] = (byte) (values[i + 0] >>> 26);
+ buf[off++] = (byte) (values[i + 0] >>> 18);
+ buf[off++] = (byte) (values[i + 0] >>> 10);
+ buf[off++] = (byte) (values[i + 0] >>> 2);
+
+ buf[off] = (byte) (values[i + 0] << 6);
+ buf[off++] |= values[i + 1] >>> 52;
+ buf[off++] = (byte) (values[i + 1] >>> 44);
+ buf[off++] = (byte) (values[i + 1] >>> 36);
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 54;
+ buf[off++] = (byte) (values[i + 2] >>> 46);
+ buf[off++] = (byte) (values[i + 2] >>> 38);
+ buf[off++] = (byte) (values[i + 2] >>> 30);
+ buf[off++] = (byte) (values[i + 2] >>> 22);
+ buf[off++] = (byte) (values[i + 2] >>> 14);
+ buf[off++] = (byte) (values[i + 2] >>> 6);
+
+ buf[off] = (byte) (values[i + 2] << 2);
+ buf[off++] |= values[i + 3] >>> 56;
+ buf[off++] = (byte) (values[i + 3] >>> 48);
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 50);
+ buf[off++] = (byte) (values[i + 4] >>> 42);
+ buf[off++] = (byte) (values[i + 4] >>> 34);
+ buf[off++] = (byte) (values[i + 4] >>> 26);
+ buf[off++] = (byte) (values[i + 4] >>> 18);
+ buf[off++] = (byte) (values[i + 4] >>> 10);
+ buf[off++] = (byte) (values[i + 4] >>> 2);
+
+ buf[off] = (byte) (values[i + 4] << 6);
+ buf[off++] |= values[i + 5] >>> 52;
+ buf[off++] = (byte) (values[i + 5] >>> 44);
+ buf[off++] = (byte) (values[i + 5] >>> 36);
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 54;
+ buf[off++] = (byte) (values[i + 6] >>> 46);
+ buf[off++] = (byte) (values[i + 6] >>> 38);
+ buf[off++] = (byte) (values[i + 6] >>> 30);
+ buf[off++] = (byte) (values[i + 6] >>> 22);
+ buf[off++] = (byte) (values[i + 6] >>> 14);
+ buf[off++] = (byte) (values[i + 6] >>> 6);
+
+ buf[off] = (byte) (values[i + 6] << 2);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits59(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 51);
+ buf[off++] = (byte) (values[i + 0] >>> 43);
+ buf[off++] = (byte) (values[i + 0] >>> 35);
+ buf[off++] = (byte) (values[i + 0] >>> 27);
+ buf[off++] = (byte) (values[i + 0] >>> 19);
+ buf[off++] = (byte) (values[i + 0] >>> 11);
+ buf[off++] = (byte) (values[i + 0] >>> 3);
+
+ buf[off] = (byte) (values[i + 0] << 5);
+ buf[off++] |= values[i + 1] >>> 54;
+ buf[off++] = (byte) (values[i + 1] >>> 46);
+ buf[off++] = (byte) (values[i + 1] >>> 38);
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 57;
+ buf[off++] = (byte) (values[i + 2] >>> 49);
+ buf[off++] = (byte) (values[i + 2] >>> 41);
+ buf[off++] = (byte) (values[i + 2] >>> 33);
+ buf[off++] = (byte) (values[i + 2] >>> 25);
+ buf[off++] = (byte) (values[i + 2] >>> 17);
+ buf[off++] = (byte) (values[i + 2] >>> 9);
+ buf[off++] = (byte) (values[i + 2] >>> 1);
+
+ buf[off] = (byte) (values[i + 2] << 7);
+ buf[off++] |= values[i + 3] >>> 52;
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 55;
+ buf[off++] = (byte) (values[i + 4] >>> 47);
+ buf[off++] = (byte) (values[i + 4] >>> 39);
+ buf[off++] = (byte) (values[i + 4] >>> 31);
+ buf[off++] = (byte) (values[i + 4] >>> 23);
+ buf[off++] = (byte) (values[i + 4] >>> 15);
+ buf[off++] = (byte) (values[i + 4] >>> 7);
+
+ buf[off] = (byte) (values[i + 4] << 1);
+ buf[off++] |= values[i + 5] >>> 58;
+ buf[off++] = (byte) (values[i + 5] >>> 50);
+ buf[off++] = (byte) (values[i + 5] >>> 42);
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 53;
+ buf[off++] = (byte) (values[i + 6] >>> 45);
+ buf[off++] = (byte) (values[i + 6] >>> 37);
+ buf[off++] = (byte) (values[i + 6] >>> 29);
+ buf[off++] = (byte) (values[i + 6] >>> 21);
+ buf[off++] = (byte) (values[i + 6] >>> 13);
+ buf[off++] = (byte) (values[i + 6] >>> 5);
+
+ buf[off] = (byte) (values[i + 6] << 3);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits60(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 52);
+ buf[off++] = (byte) (values[i + 0] >>> 44);
+ buf[off++] = (byte) (values[i + 0] >>> 36);
+ buf[off++] = (byte) (values[i + 0] >>> 28);
+ buf[off++] = (byte) (values[i + 0] >>> 20);
+ buf[off++] = (byte) (values[i + 0] >>> 12);
+ buf[off++] = (byte) (values[i + 0] >>> 4);
+
+ buf[off] = (byte) (values[i + 0] << 4);
+ buf[off++] |= values[i + 1] >>> 56;
+ buf[off++] = (byte) (values[i + 1] >>> 48);
+ buf[off++] = (byte) (values[i + 1] >>> 40);
+ buf[off++] = (byte) (values[i + 1] >>> 32);
+ buf[off++] = (byte) (values[i + 1] >>> 24);
+ buf[off++] = (byte) (values[i + 1] >>> 16);
+ buf[off++] = (byte) (values[i + 1] >>> 8);
+ buf[off++] = (byte) (values[i + 1]);
+
+ buf[off++] = (byte) (values[i + 2] >>> 52);
+ buf[off++] = (byte) (values[i + 2] >>> 44);
+ buf[off++] = (byte) (values[i + 2] >>> 36);
+ buf[off++] = (byte) (values[i + 2] >>> 28);
+ buf[off++] = (byte) (values[i + 2] >>> 20);
+ buf[off++] = (byte) (values[i + 2] >>> 12);
+ buf[off++] = (byte) (values[i + 2] >>> 4);
+
+ buf[off] = (byte) (values[i + 2] << 4);
+ buf[off++] |= values[i + 3] >>> 56;
+ buf[off++] = (byte) (values[i + 3] >>> 48);
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 52);
+ buf[off++] = (byte) (values[i + 4] >>> 44);
+ buf[off++] = (byte) (values[i + 4] >>> 36);
+ buf[off++] = (byte) (values[i + 4] >>> 28);
+ buf[off++] = (byte) (values[i + 4] >>> 20);
+ buf[off++] = (byte) (values[i + 4] >>> 12);
+ buf[off++] = (byte) (values[i + 4] >>> 4);
+
+ buf[off] = (byte) (values[i + 4] << 4);
+ buf[off++] |= values[i + 5] >>> 56;
+ buf[off++] = (byte) (values[i + 5] >>> 48);
+ buf[off++] = (byte) (values[i + 5] >>> 40);
+ buf[off++] = (byte) (values[i + 5] >>> 32);
+ buf[off++] = (byte) (values[i + 5] >>> 24);
+ buf[off++] = (byte) (values[i + 5] >>> 16);
+ buf[off++] = (byte) (values[i + 5] >>> 8);
+ buf[off++] = (byte) (values[i + 5]);
+
+ buf[off++] = (byte) (values[i + 6] >>> 52);
+ buf[off++] = (byte) (values[i + 6] >>> 44);
+ buf[off++] = (byte) (values[i + 6] >>> 36);
+ buf[off++] = (byte) (values[i + 6] >>> 28);
+ buf[off++] = (byte) (values[i + 6] >>> 20);
+ buf[off++] = (byte) (values[i + 6] >>> 12);
+ buf[off++] = (byte) (values[i + 6] >>> 4);
+
+ buf[off] = (byte) (values[i + 6] << 4);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits61(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 53);
+ buf[off++] = (byte) (values[i + 0] >>> 45);
+ buf[off++] = (byte) (values[i + 0] >>> 37);
+ buf[off++] = (byte) (values[i + 0] >>> 29);
+ buf[off++] = (byte) (values[i + 0] >>> 21);
+ buf[off++] = (byte) (values[i + 0] >>> 13);
+ buf[off++] = (byte) (values[i + 0] >>> 5);
+
+ buf[off] = (byte) (values[i + 0] << 3);
+ buf[off++] |= values[i + 1] >>> 58;
+ buf[off++] = (byte) (values[i + 1] >>> 50);
+ buf[off++] = (byte) (values[i + 1] >>> 42);
+ buf[off++] = (byte) (values[i + 1] >>> 34);
+ buf[off++] = (byte) (values[i + 1] >>> 26);
+ buf[off++] = (byte) (values[i + 1] >>> 18);
+ buf[off++] = (byte) (values[i + 1] >>> 10);
+ buf[off++] = (byte) (values[i + 1] >>> 2);
+
+ buf[off] = (byte) (values[i + 1] << 6);
+ buf[off++] |= values[i + 2] >>> 55;
+ buf[off++] = (byte) (values[i + 2] >>> 47);
+ buf[off++] = (byte) (values[i + 2] >>> 39);
+ buf[off++] = (byte) (values[i + 2] >>> 31);
+ buf[off++] = (byte) (values[i + 2] >>> 23);
+ buf[off++] = (byte) (values[i + 2] >>> 15);
+ buf[off++] = (byte) (values[i + 2] >>> 7);
+
+ buf[off] = (byte) (values[i + 2] << 1);
+ buf[off++] |= values[i + 3] >>> 60;
+ buf[off++] = (byte) (values[i + 3] >>> 52);
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 57;
+ buf[off++] = (byte) (values[i + 4] >>> 49);
+ buf[off++] = (byte) (values[i + 4] >>> 41);
+ buf[off++] = (byte) (values[i + 4] >>> 33);
+ buf[off++] = (byte) (values[i + 4] >>> 25);
+ buf[off++] = (byte) (values[i + 4] >>> 17);
+ buf[off++] = (byte) (values[i + 4] >>> 9);
+ buf[off++] = (byte) (values[i + 4] >>> 1);
+
+ buf[off] = (byte) (values[i + 4] << 7);
+ buf[off++] |= values[i + 5] >>> 54;
+ buf[off++] = (byte) (values[i + 5] >>> 46);
+ buf[off++] = (byte) (values[i + 5] >>> 38);
+ buf[off++] = (byte) (values[i + 5] >>> 30);
+ buf[off++] = (byte) (values[i + 5] >>> 22);
+ buf[off++] = (byte) (values[i + 5] >>> 14);
+ buf[off++] = (byte) (values[i + 5] >>> 6);
+
+ buf[off] = (byte) (values[i + 5] << 2);
+ buf[off++] |= values[i + 6] >>> 59;
+ buf[off++] = (byte) (values[i + 6] >>> 51);
+ buf[off++] = (byte) (values[i + 6] >>> 43);
+ buf[off++] = (byte) (values[i + 6] >>> 35);
+ buf[off++] = (byte) (values[i + 6] >>> 27);
+ buf[off++] = (byte) (values[i + 6] >>> 19);
+ buf[off++] = (byte) (values[i + 6] >>> 11);
+ buf[off++] = (byte) (values[i + 6] >>> 3);
+
+ buf[off] = (byte) (values[i + 6] << 5);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits62(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 54);
+ buf[off++] = (byte) (values[i + 0] >>> 46);
+ buf[off++] = (byte) (values[i + 0] >>> 38);
+ buf[off++] = (byte) (values[i + 0] >>> 30);
+ buf[off++] = (byte) (values[i + 0] >>> 22);
+ buf[off++] = (byte) (values[i + 0] >>> 14);
+ buf[off++] = (byte) (values[i + 0] >>> 6);
+
+ buf[off] = (byte) (values[i + 0] << 2);
+ buf[off++] |= values[i + 1] >>> 60;
+ buf[off++] = (byte) (values[i + 1] >>> 52);
+ buf[off++] = (byte) (values[i + 1] >>> 44);
+ buf[off++] = (byte) (values[i + 1] >>> 36);
+ buf[off++] = (byte) (values[i + 1] >>> 28);
+ buf[off++] = (byte) (values[i + 1] >>> 20);
+ buf[off++] = (byte) (values[i + 1] >>> 12);
+ buf[off++] = (byte) (values[i + 1] >>> 4);
+
+ buf[off] = (byte) (values[i + 1] << 4);
+ buf[off++] |= values[i + 2] >>> 58;
+ buf[off++] = (byte) (values[i + 2] >>> 50);
+ buf[off++] = (byte) (values[i + 2] >>> 42);
+ buf[off++] = (byte) (values[i + 2] >>> 34);
+ buf[off++] = (byte) (values[i + 2] >>> 26);
+ buf[off++] = (byte) (values[i + 2] >>> 18);
+ buf[off++] = (byte) (values[i + 2] >>> 10);
+ buf[off++] = (byte) (values[i + 2] >>> 2);
+
+ buf[off] = (byte) (values[i + 2] << 6);
+ buf[off++] |= values[i + 3] >>> 56;
+ buf[off++] = (byte) (values[i + 3] >>> 48);
+ buf[off++] = (byte) (values[i + 3] >>> 40);
+ buf[off++] = (byte) (values[i + 3] >>> 32);
+ buf[off++] = (byte) (values[i + 3] >>> 24);
+ buf[off++] = (byte) (values[i + 3] >>> 16);
+ buf[off++] = (byte) (values[i + 3] >>> 8);
+ buf[off++] = (byte) (values[i + 3]);
+
+ buf[off++] = (byte) (values[i + 4] >>> 54);
+ buf[off++] = (byte) (values[i + 4] >>> 46);
+ buf[off++] = (byte) (values[i + 4] >>> 38);
+ buf[off++] = (byte) (values[i + 4] >>> 30);
+ buf[off++] = (byte) (values[i + 4] >>> 22);
+ buf[off++] = (byte) (values[i + 4] >>> 14);
+ buf[off++] = (byte) (values[i + 4] >>> 6);
+
+ buf[off] = (byte) (values[i + 4] << 2);
+ buf[off++] |= values[i + 5] >>> 60;
+ buf[off++] = (byte) (values[i + 5] >>> 52);
+ buf[off++] = (byte) (values[i + 5] >>> 44);
+ buf[off++] = (byte) (values[i + 5] >>> 36);
+ buf[off++] = (byte) (values[i + 5] >>> 28);
+ buf[off++] = (byte) (values[i + 5] >>> 20);
+ buf[off++] = (byte) (values[i + 5] >>> 12);
+ buf[off++] = (byte) (values[i + 5] >>> 4);
+
+ buf[off] = (byte) (values[i + 5] << 4);
+ buf[off++] |= values[i + 6] >>> 58;
+ buf[off++] = (byte) (values[i + 6] >>> 50);
+ buf[off++] = (byte) (values[i + 6] >>> 42);
+ buf[off++] = (byte) (values[i + 6] >>> 34);
+ buf[off++] = (byte) (values[i + 6] >>> 26);
+ buf[off++] = (byte) (values[i + 6] >>> 18);
+ buf[off++] = (byte) (values[i + 6] >>> 10);
+ buf[off++] = (byte) (values[i + 6] >>> 2);
+
+ buf[off] = (byte) (values[i + 6] << 6);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) (values[i + 7]);
+ }
+
+ static void packBits63(final long[] values, final int i, final byte[] buf, int off) {
+ buf[off++] = (byte) (values[i + 0] >>> 55);
+ buf[off++] = (byte) (values[i + 0] >>> 47);
+ buf[off++] = (byte) (values[i + 0] >>> 39);
+ buf[off++] = (byte) (values[i + 0] >>> 31);
+ buf[off++] = (byte) (values[i + 0] >>> 23);
+ buf[off++] = (byte) (values[i + 0] >>> 15);
+ buf[off++] = (byte) (values[i + 0] >>> 7);
+
+ buf[off] = (byte) (values[i + 0] << 1);
+ buf[off++] |= values[i + 1] >>> 62;
+ buf[off++] = (byte) (values[i + 1] >>> 54);
+ buf[off++] = (byte) (values[i + 1] >>> 46);
+ buf[off++] = (byte) (values[i + 1] >>> 38);
+ buf[off++] = (byte) (values[i + 1] >>> 30);
+ buf[off++] = (byte) (values[i + 1] >>> 22);
+ buf[off++] = (byte) (values[i + 1] >>> 14);
+ buf[off++] = (byte) (values[i + 1] >>> 6);
+
+ buf[off] = (byte) (values[i + 1] << 2);
+ buf[off++] |= values[i + 2] >>> 61;
+ buf[off++] = (byte) (values[i + 2] >>> 53);
+ buf[off++] = (byte) (values[i + 2] >>> 45);
+ buf[off++] = (byte) (values[i + 2] >>> 37);
+ buf[off++] = (byte) (values[i + 2] >>> 29);
+ buf[off++] = (byte) (values[i + 2] >>> 21);
+ buf[off++] = (byte) (values[i + 2] >>> 13);
+ buf[off++] = (byte) (values[i + 2] >>> 5);
+
+ buf[off] = (byte) (values[i + 2] << 3);
+ buf[off++] |= values[i + 3] >>> 60;
+ buf[off++] = (byte) (values[i + 3] >>> 52);
+ buf[off++] = (byte) (values[i + 3] >>> 44);
+ buf[off++] = (byte) (values[i + 3] >>> 36);
+ buf[off++] = (byte) (values[i + 3] >>> 28);
+ buf[off++] = (byte) (values[i + 3] >>> 20);
+ buf[off++] = (byte) (values[i + 3] >>> 12);
+ buf[off++] = (byte) (values[i + 3] >>> 4);
+
+ buf[off] = (byte) (values[i + 3] << 4);
+ buf[off++] |= values[i + 4] >>> 59;
+ buf[off++] = (byte) (values[i + 4] >>> 51);
+ buf[off++] = (byte) (values[i + 4] >>> 43);
+ buf[off++] = (byte) (values[i + 4] >>> 35);
+ buf[off++] = (byte) (values[i + 4] >>> 27);
+ buf[off++] = (byte) (values[i + 4] >>> 19);
+ buf[off++] = (byte) (values[i + 4] >>> 11);
+ buf[off++] = (byte) (values[i + 4] >>> 3);
+
+ buf[off] = (byte) (values[i + 4] << 5);
+ buf[off++] |= values[i + 5] >>> 58;
+ buf[off++] = (byte) (values[i + 5] >>> 50);
+ buf[off++] = (byte) (values[i + 5] >>> 42);
+ buf[off++] = (byte) (values[i + 5] >>> 34);
+ buf[off++] = (byte) (values[i + 5] >>> 26);
+ buf[off++] = (byte) (values[i + 5] >>> 18);
+ buf[off++] = (byte) (values[i + 5] >>> 10);
+ buf[off++] = (byte) (values[i + 5] >>> 2);
+
+ buf[off] = (byte) (values[i + 5] << 6);
+ buf[off++] |= values[i + 6] >>> 57;
+ buf[off++] = (byte) (values[i + 6] >>> 49);
+ buf[off++] = (byte) (values[i + 6] >>> 41);
+ buf[off++] = (byte) (values[i + 6] >>> 33);
+ buf[off++] = (byte) (values[i + 6] >>> 25);
+ buf[off++] = (byte) (values[i + 6] >>> 17);
+ buf[off++] = (byte) (values[i + 6] >>> 9);
+ buf[off++] = (byte) (values[i + 6] >>> 1);
+
+ buf[off] = (byte) (values[i + 6] << 7);
+ buf[off++] |= values[i + 7] >>> 56;
+ buf[off++] = (byte) (values[i + 7] >>> 48);
+ buf[off++] = (byte) (values[i + 7] >>> 40);
+ buf[off++] = (byte) (values[i + 7] >>> 32);
+ buf[off++] = (byte) (values[i + 7] >>> 24);
+ buf[off++] = (byte) (values[i + 7] >>> 16);
+ buf[off++] = (byte) (values[i + 7] >>> 8);
+ buf[off] = (byte) values[i + 7];
+ }
+
+ static void unpackBits1(final long[] values, final int i, final byte[] buf, final int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off]) >>> 7) & 1;
+ values[i + 1] = (Byte.toUnsignedLong(buf[off]) >>> 6) & 1;
+ values[i + 2] = (Byte.toUnsignedLong(buf[off]) >>> 5) & 1;
+ values[i + 3] = (Byte.toUnsignedLong(buf[off]) >>> 4) & 1;
+ values[i + 4] = (Byte.toUnsignedLong(buf[off]) >>> 3) & 1;
+ values[i + 5] = (Byte.toUnsignedLong(buf[off]) >>> 2) & 1;
+ values[i + 6] = (Byte.toUnsignedLong(buf[off]) >>> 1) & 1;
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 1;
+ }
+
+ static void unpackBits2(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off]) >>> 6) & 3;
+ values[i + 1] = (Byte.toUnsignedLong(buf[off]) >>> 4) & 3;
+ values[i + 2] = (Byte.toUnsignedLong(buf[off]) >>> 2) & 3;
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]) & 3;
+ values[i + 4] = (Byte.toUnsignedLong(buf[off]) >>> 6) & 3;
+ values[i + 5] = (Byte.toUnsignedLong(buf[off]) >>> 4) & 3;
+ values[i + 6] = (Byte.toUnsignedLong(buf[off]) >>> 2) & 3;
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 3;
+ }
+
+ static void unpackBits3(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off]) >>> 5;
+ values[i + 1] = (Byte.toUnsignedLong(buf[off]) >>> 2) & 7;
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+ values[i + 3] = (Byte.toUnsignedLong(buf[off]) >>> 4) & 7;
+ values[i + 4] = (Byte.toUnsignedLong(buf[off]) >>> 1) & 7;
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+ values[i + 6] = (Byte.toUnsignedLong(buf[off]) >>> 3) & 7;
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 7;
+ }
+
+ static void unpackBits4(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off]) >>> 4;
+ values[i + 1] = Byte.toUnsignedLong(buf[off++]) & 0xf;
+ values[i + 2] = Byte.toUnsignedLong(buf[off]) >>> 4;
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]) & 0xf;
+ values[i + 4] = Byte.toUnsignedLong(buf[off]) >>> 4;
+ values[i + 5] = Byte.toUnsignedLong(buf[off++]) & 0xf;
+ values[i + 6] = Byte.toUnsignedLong(buf[off]) >>> 4;
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 0xf;
+ }
+
+ static void unpackBits5(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off]) >>> 1) & 0x1f;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off]) >>> 2) & 0x1f;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 0x1f;
+ }
+
+ static void unpackBits6(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]) & 0x3f;
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 0x3f;
+ }
+
+ static void unpackBits7(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = Byte.toUnsignedLong(buf[off]) & 0x7f;
+ }
+
+ static void unpackBits8(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits9(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits10(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits11(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits12(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits13(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits14(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits15(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits16(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits17(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits18(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits19(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits20(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits21(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits22(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits23(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits24(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits25(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 19;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 21;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 23;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits26(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 22;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 22;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits27(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 25;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 23;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 21;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits28(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits29(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 23;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 25;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 27;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits30(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 26;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 26;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits31(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 29;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 27;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 25;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits32(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits33(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 27;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 29;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 31;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 32;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits34(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 30;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 30;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]);
+ }
+
+ static void unpackBits35(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 33;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 31;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 29;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits36(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits37(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 31;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 23;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 33;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 30;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 35;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits38(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 34;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 34;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits39(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 37;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 35;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 33;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits40(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits41(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 35;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 37;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 39;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits42(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 38;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 38;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits43(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 41;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 39;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 37;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits44(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 40;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 40;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits45(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 42;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 39;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 23;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 41;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 43;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits46(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 44;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 42;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 44;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 42;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits47(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 46;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 45;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 43;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 41;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits48(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits49(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 42;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 43;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 45;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 46;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 47;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits50(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 44;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 46;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 44;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 46;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits51(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 46;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 49;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 47;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 50;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 45;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits52(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 48;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 48;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits53(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 50;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 47;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 23;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 49;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 46;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 51;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits54(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 52;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 50;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 52;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 50;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]);
+ }
+
+ static void unpackBits55(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 47;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 54;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 53;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 51;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 50;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 49;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits56(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]);
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits57(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 49;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 50;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 51;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 53;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 7) << 54;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 55;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 47;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 1) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits58(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 52;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 54;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 3) << 56;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 52;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 54;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 3) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]);
+ }
+
+ static void unpackBits59(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 51;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 54;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 57;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 49;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 55;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 47;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 1) << 58;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 53;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 7) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits60(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 56;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 56;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 56;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits61(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 53;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 7) << 58;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 55;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 47;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 1) << 60;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 57;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 49;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 54;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 3) << 59;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 51;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits62(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 54;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 3) << 60;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 58;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 56;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]);
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++])) << 54;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 3) << 60;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 58;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+ static void unpackBits63(final long[] values, final int i, final byte[] buf, int off) {
+ values[i + 0] = (Byte.toUnsignedLong(buf[off++])) << 55;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 47;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 39;
+ values[i + 0] |= (Byte.toUnsignedLong(buf[off++])) << 31;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 23;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 15;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off++]) << 7;
+ values[i + 0] |= Byte.toUnsignedLong(buf[off]) >>> 1;
+
+ values[i + 1] = (Byte.toUnsignedLong(buf[off++]) & 1) << 62;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 54;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 46;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 38;
+ values[i + 1] |= (Byte.toUnsignedLong(buf[off++])) << 30;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 22;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 14;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off++]) << 6;
+ values[i + 1] |= Byte.toUnsignedLong(buf[off]) >>> 2;
+
+ values[i + 2] = (Byte.toUnsignedLong(buf[off++]) & 3) << 61;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 53;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 45;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 37;
+ values[i + 2] |= (Byte.toUnsignedLong(buf[off++])) << 29;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 21;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 13;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off++]) << 5;
+ values[i + 2] |= Byte.toUnsignedLong(buf[off]) >>> 3;
+
+ values[i + 3] = (Byte.toUnsignedLong(buf[off++]) & 7) << 60;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 52;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 44;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 36;
+ values[i + 3] |= (Byte.toUnsignedLong(buf[off++])) << 28;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 20;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 12;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off++]) << 4;
+ values[i + 3] |= Byte.toUnsignedLong(buf[off]) >>> 4;
+
+ values[i + 4] = (Byte.toUnsignedLong(buf[off++]) & 0xf) << 59;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 51;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 43;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 35;
+ values[i + 4] |= (Byte.toUnsignedLong(buf[off++])) << 27;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 19;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 11;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off++]) << 3;
+ values[i + 4] |= Byte.toUnsignedLong(buf[off]) >>> 5;
+
+ values[i + 5] = (Byte.toUnsignedLong(buf[off++]) & 0x1f) << 58;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 50;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 42;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 34;
+ values[i + 5] |= (Byte.toUnsignedLong(buf[off++])) << 26;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 18;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 10;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off++]) << 2;
+ values[i + 5] |= Byte.toUnsignedLong(buf[off]) >>> 6;
+
+ values[i + 6] = (Byte.toUnsignedLong(buf[off++]) & 0x3f) << 57;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 49;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 41;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 33;
+ values[i + 6] |= (Byte.toUnsignedLong(buf[off++])) << 25;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 17;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 9;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off++]) << 1;
+ values[i + 6] |= Byte.toUnsignedLong(buf[off]) >>> 7;
+
+ values[i + 7] = (Byte.toUnsignedLong(buf[off++]) & 0x7f) << 56;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 48;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 40;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 32;
+ values[i + 7] |= (Byte.toUnsignedLong(buf[off++])) << 24;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 16;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off++]) << 8;
+ values[i + 7] |= Byte.toUnsignedLong(buf[off]);
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/BytesCompactCompressedHashIterator.java b/src/main/java/org/apache/datasketches/theta2/BytesCompactCompressedHashIterator.java
new file mode 100644
index 00000000..81a98592
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/BytesCompactCompressedHashIterator.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+/*
+ * This is to uncompress serial version 4 sketch incrementally
+ */
+class BytesCompactCompressedHashIterator implements HashIterator {
+ private byte[] bytes;
+ private int offset;
+ private int entryBits;
+ private int numEntries;
+ private int index;
+ private long previous;
+ private int offsetBits;
+ private long[] buffer;
+ private boolean isBlockMode;
+
+ BytesCompactCompressedHashIterator(
+ final byte[] bytes,
+ final int offset,
+ final int entryBits,
+ final int numEntries
+ ) {
+ this.bytes = bytes;
+ this.offset = offset;
+ this.entryBits = entryBits;
+ this.numEntries = numEntries;
+ index = -1;
+ previous = 0;
+ offsetBits = 0;
+ buffer = new long[8];
+ isBlockMode = numEntries >= 8;
+ }
+
+ @Override
+ public long get() {
+ return buffer[index & 7];
+ }
+
+ @Override
+ public boolean next() {
+ if (++index == numEntries) { return false; }
+ if (isBlockMode) {
+ if ((index & 7) == 0) {
+ if (numEntries - index >= 8) {
+ unpack8();
+ } else {
+ isBlockMode = false;
+ unpack1();
+ }
+ }
+ } else {
+ unpack1();
+ }
+ return true;
+ }
+
+ private void unpack1() {
+ final int i = index & 7;
+ BitPacking.unpackBits(buffer, i, entryBits, bytes, offset, offsetBits);
+ offset += (offsetBits + entryBits) >>> 3;
+ offsetBits = (offsetBits + entryBits) & 7;
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+
+ private void unpack8() {
+ BitPacking.unpackBitsBlock8(buffer, 0, bytes, offset, entryBits);
+ offset += entryBits;
+ for (int i = 0; i < 8; i++) {
+ buffer[i] += previous;
+ previous = buffer[i];
+ }
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/BytesCompactHashIterator.java b/src/main/java/org/apache/datasketches/theta2/BytesCompactHashIterator.java
new file mode 100644
index 00000000..9a475457
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/BytesCompactHashIterator.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import org.apache.datasketches.common.ByteArrayUtil;
+
+/*
+ * This is to iterate over serial version 3 sketch representation
+ */
+class BytesCompactHashIterator implements HashIterator {
+ final private byte[] bytes;
+ final private int offset;
+ final private int numEntries;
+ private int index;
+
+ BytesCompactHashIterator(
+ final byte[] bytes,
+ final int offset,
+ final int numEntries
+ ) {
+ this.bytes = bytes;
+ this.offset = offset;
+ this.numEntries = numEntries;
+ index = -1;
+ }
+
+ @Override
+ public long get() {
+ return ByteArrayUtil.getLongLE(bytes, offset + index * Long.BYTES);
+ }
+
+ @Override
+ public boolean next() {
+ return ++index < numEntries;
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/CompactOperations.java b/src/main/java/org/apache/datasketches/theta2/CompactOperations.java
new file mode 100644
index 00000000..ab342a1f
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/CompactOperations.java
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED;
+import static org.apache.datasketches.theta2.PreambleUtil.COMPACT_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.EMPTY_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.LG_NOM_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.ORDERED_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.READ_ONLY_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.SER_VER;
+import static org.apache.datasketches.theta2.PreambleUtil.SINGLEITEM_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.extractCurCount;
+import static org.apache.datasketches.theta2.PreambleUtil.extractFamilyID;
+import static org.apache.datasketches.theta2.PreambleUtil.extractFlags;
+import static org.apache.datasketches.theta2.PreambleUtil.extractLgArrLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSerVer;
+import static org.apache.datasketches.theta2.PreambleUtil.extractThetaLong;
+import static org.apache.datasketches.theta2.PreambleUtil.insertCurCount;
+import static org.apache.datasketches.theta2.PreambleUtil.insertFamilyID;
+import static org.apache.datasketches.theta2.PreambleUtil.insertFlags;
+import static org.apache.datasketches.theta2.PreambleUtil.insertP;
+import static org.apache.datasketches.theta2.PreambleUtil.insertPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.insertSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.insertSerVer;
+import static org.apache.datasketches.theta2.PreambleUtil.insertThetaLong;
+
+import java.lang.foreign.MemorySegment;
+import java.util.Arrays;
+
+import org.apache.datasketches.common.Family;
+import org.apache.datasketches.common.SketchesArgumentException;
+import org.apache.datasketches.common.SketchesStateException;
+
+/**
+ * @author Lee Rhodes
+ */
+final class CompactOperations {
+
+ private CompactOperations() {}
+
+ static CompactSketch componentsToCompact( //No error checking
+ final long thetaLong,
+ final int curCount,
+ final short seedHash,
+ final boolean srcEmpty,
+ final boolean srcCompact,
+ final boolean srcOrdered,
+ final boolean dstOrdered,
+ final MemorySegment dstWSeg,
+ final long[] hashArr) //may not be compacted, ordered or unordered, may be null
+ {
+ final boolean direct = dstWSeg != null;
+ final boolean empty = srcEmpty || ((curCount == 0) && (thetaLong == Long.MAX_VALUE));
+ final boolean single = (curCount == 1) && (thetaLong == Long.MAX_VALUE);
+ final long[] hashArrOut;
+ if (!srcCompact) {
+ hashArrOut = CompactOperations.compactCache(hashArr, curCount, thetaLong, dstOrdered);
+ } else {
+ hashArrOut = hashArr;
+ }
+ if (!srcOrdered && dstOrdered && !empty && !single) {
+ Arrays.sort(hashArrOut);
+ }
+ //Note: for empty or single we always output the ordered form.
+ final boolean dstOrderedOut = (empty || single) ? true : dstOrdered;
+ if (direct) {
+ final int preLongs = computeCompactPreLongs(empty, curCount, thetaLong);
+ int flags = READ_ONLY_FLAG_MASK | COMPACT_FLAG_MASK; //always LE
+ flags |= empty ? EMPTY_FLAG_MASK : 0;
+ flags |= dstOrderedOut ? ORDERED_FLAG_MASK : 0;
+ flags |= single ? SINGLEITEM_FLAG_MASK : 0;
+
+ final MemorySegment seg =
+ loadCompactMemory(hashArrOut, seedHash, curCount, thetaLong, dstWSeg, (byte)flags, preLongs);
+ return new DirectCompactSketch(seg);
+
+ } else { //Heap
+ if (empty) {
+ return EmptyCompactSketch.getInstance();
+ }
+ if (single) {
+ return new SingleItemSketch(hashArrOut[0], seedHash);
+ }
+ return new HeapCompactSketch(hashArrOut, empty, seedHash, curCount, thetaLong, dstOrderedOut);
+ }
+ }
+
+ /**
+ * Heapify or convert a source Theta Sketch MemorySegment image into a heap or target MemorySegment CompactSketch.
+ * This assumes hashSeed is OK; serVer = 3.
+ * @param srcSeg the given input source MemorySegment image. Can be Read Only.
+ * @param dstOrdered the desired ordering of the resulting CompactSketch
+ * @param dstWSeg Used for the target CompactSketch if it is MemorySegment-based. Must be Writable.
+ * @return a CompactSketch of the correct form.
+ */
+ @SuppressWarnings("unused")
+ static CompactSketch memoryToCompact(
+ final MemorySegment srcSeg,
+ final boolean dstOrdered,
+ final MemorySegment dstWSeg)
+ {
+ //extract Pre0 fields and Flags from srcMem
+ final int srcPreLongs = extractPreLongs(srcSeg);
+ final int srcSerVer = extractSerVer(srcSeg); //not used
+ final int srcFamId = extractFamilyID(srcSeg);
+ final int srcLgArrLongs = extractLgArrLongs(srcSeg);
+ final int srcFlags = extractFlags(srcSeg);
+ final short srcSeedHash = (short) extractSeedHash(srcSeg);
+
+ //srcFlags
+ final boolean srcReadOnlyFlag = (srcFlags & READ_ONLY_FLAG_MASK) > 0;
+ final boolean srcEmptyFlag = (srcFlags & EMPTY_FLAG_MASK) > 0;
+ final boolean srcCompactFlag = (srcFlags & COMPACT_FLAG_MASK) > 0;
+ final boolean srcOrderedFlag = (srcFlags & ORDERED_FLAG_MASK) > 0;
+ final boolean srcSingleFlag = (srcFlags & SINGLEITEM_FLAG_MASK) > 0;
+
+ final boolean single = srcSingleFlag
+ || SingleItemSketch.otherCheckForSingleItem(srcPreLongs, srcSerVer, srcFamId, srcFlags);
+
+ //extract pre1 and pre2 fields
+ final int curCount = single ? 1 : (srcPreLongs > 1) ? extractCurCount(srcSeg) : 0;
+ final long thetaLong = (srcPreLongs > 2) ? extractThetaLong(srcSeg) : Long.MAX_VALUE;
+
+ //do some basic checks ...
+ if (srcEmptyFlag) { assert (curCount == 0) && (thetaLong == Long.MAX_VALUE); }
+ if (single) { assert (curCount == 1) && (thetaLong == Long.MAX_VALUE); }
+ checkFamilyAndFlags(srcFamId, srcCompactFlag, srcReadOnlyFlag);
+
+ //dispatch empty and single cases
+ //Note: for empty and single we always output the ordered form.
+ final boolean dstOrderedOut = (srcEmptyFlag || single) ? true : dstOrdered;
+ if (srcEmptyFlag) {
+ if (dstWSeg != null) {
+ MemorySegment.copy(EmptyCompactSketch.EMPTY_COMPACT_SKETCH_ARR, 0, dstWSeg, JAVA_BYTE, 0, 8);
+ return new DirectCompactSketch(dstWSeg);
+ } else {
+ return EmptyCompactSketch.getInstance();
+ }
+ }
+ if (single) {
+ final long hash = srcSeg.get(JAVA_LONG_UNALIGNED, srcPreLongs << 3);
+ final SingleItemSketch sis = new SingleItemSketch(hash, srcSeedHash);
+ if (dstWSeg != null) {
+ MemorySegment.copy(sis.toByteArray(), 0, dstWSeg, JAVA_BYTE, 0, 16);
+ return new DirectCompactSketch(dstWSeg);
+ } else { //heap
+ return sis;
+ }
+ }
+
+ //extract hashArr > 1
+ final long[] hashArr;
+ if (srcCompactFlag) {
+ hashArr = new long[curCount];
+ MemorySegment.copy(srcSeg, JAVA_LONG_UNALIGNED, srcPreLongs << 3, hashArr, 0, curCount);
+ } else { //update sketch, thus hashTable form
+ final int srcCacheLen = 1 << srcLgArrLongs;
+ final long[] tempHashArr = new long[srcCacheLen];
+ MemorySegment.copy(srcSeg, JAVA_LONG_UNALIGNED, srcPreLongs << 3, tempHashArr, 0, srcCacheLen);
+ hashArr = compactCache(tempHashArr, curCount, thetaLong, dstOrderedOut);
+ }
+
+ final int flagsOut = READ_ONLY_FLAG_MASK | COMPACT_FLAG_MASK
+ | ((dstOrderedOut) ? ORDERED_FLAG_MASK : 0);
+
+ //load the destination.
+ if (dstWSeg != null) {
+ final MemorySegment tgtSeg = loadCompactMemory(hashArr, srcSeedHash, curCount, thetaLong, dstWSeg,
+ (byte)flagsOut, srcPreLongs);
+ return new DirectCompactSketch(tgtSeg);
+ } else { //heap
+ return new HeapCompactSketch(hashArr, srcEmptyFlag, srcSeedHash, curCount, thetaLong,
+ dstOrderedOut);
+ }
+ }
+
+ private static final void checkFamilyAndFlags(
+ final int srcFamId,
+ final boolean srcCompactFlag,
+ final boolean srcReadOnlyFlag) {
+ final Family srcFamily = Family.idToFamily(srcFamId);
+ if (srcCompactFlag) {
+ if ((srcFamily == Family.COMPACT) && srcReadOnlyFlag) { return; }
+ } else {
+ if (srcFamily == Family.ALPHA) { return; }
+ if (srcFamily == Family.QUICKSELECT) { return; }
+ }
+ throw new SketchesArgumentException(
+ "Possible Corruption: Family does not match flags: Family: "
+ + srcFamily.toString()
+ + ", Compact Flag: " + srcCompactFlag
+ + ", ReadOnly Flag: " + srcReadOnlyFlag);
+ }
+
+ //All arguments must be valid and correct including flags.
+ // Used as helper to create byte arrays as well as loading Memory for direct compact sketches
+ //Input must be writable, return can be Read Only
+ static final MemorySegment loadCompactMemory(
+ final long[] compactHashArr,
+ final short seedHash,
+ final int curCount,
+ final long thetaLong,
+ final MemorySegment dstWSeg,
+ final byte flags,
+ final int preLongs)
+ {
+ assert (dstWSeg != null) && (compactHashArr != null);
+ final int outLongs = preLongs + curCount;
+ final int outBytes = outLongs << 3;
+ final int dstBytes = (int) dstWSeg.byteSize();
+ if (outBytes > dstBytes) {
+ throw new SketchesArgumentException("Insufficient Memory: " + dstBytes
+ + ", Need: " + outBytes);
+ }
+ final byte famID = (byte) Family.COMPACT.getID();
+
+ //Caution: The following loads directly into Memory without creating a heap byte[] first,
+ // which would act as a pre-clearing, initialization mechanism. So it is important to make sure
+ // that all fields are initialized, even those that are not used by the CompactSketch.
+ // Otherwise, uninitialized fields could be filled with off-heap garbage, which could cause
+ // other problems downstream if those fields are not filtered out first.
+ // As written below, all fields are initialized avoiding an extra copy.
+
+ //The first 8 bytes (pre0)
+ insertPreLongs(dstWSeg, preLongs); //RF not used = 0
+ insertSerVer(dstWSeg, SER_VER);
+ insertFamilyID(dstWSeg, famID);
+ //The following initializes the lgNomLongs and lgArrLongs to 0.
+ //They are not used in CompactSketches.
+ dstWSeg.set(JAVA_SHORT_UNALIGNED, LG_NOM_LONGS_BYTE, (short)0);
+ insertFlags(dstWSeg, flags);
+ insertSeedHash(dstWSeg, seedHash);
+
+ if ((preLongs == 1) && (curCount == 1)) { //singleItem, theta = 1.0
+ dstWSeg.set(JAVA_LONG_UNALIGNED, 8, compactHashArr[0]);
+ return dstWSeg;
+ }
+ if (preLongs > 1) {
+ insertCurCount(dstWSeg, curCount);
+ insertP(dstWSeg, (float) 1.0);
+ }
+ if (preLongs > 2) {
+ insertThetaLong(dstWSeg, thetaLong);
+ }
+ if (curCount > 0) { //theta could be < 1.0.
+ //dstWSeg.putLongArray(preLongs << 3, compactHashArr, 0, curCount);
+ MemorySegment.copy(compactHashArr, 0, dstWSeg, JAVA_LONG_UNALIGNED, preLongs << 3, curCount);
+ }
+ return dstWSeg; //if prelongs == 3 & curCount == 0, theta could be < 1.0. This can be RO
+ }
+
+ /**
+ * Copies then compacts, cleans, and may sort the resulting array.
+ * The source cache can be a hash table with interstitial zeros or
+ * "dirty" values, which are hash values greater than theta.
+ * These can be generated by the Alpha sketch.
+ * @param srcCache anything
+ * @param curCount must be correct
+ * @param thetaLong The correct
+ * <a href="{@docRoot}/resources/dictionary.html#thetaLong">thetaLong</a>.
+ * @param dstOrdered true if output array must be sorted
+ * @return the compacted array.
+ */
+ static final long[] compactCache(final long[] srcCache, final int curCount,
+ final long thetaLong, final boolean dstOrdered) {
+ if (curCount == 0) {
+ return new long[0];
+ }
+ final long[] cacheOut = new long[curCount];
+ final int len = srcCache.length;
+ int j = 0;
+ for (int i = 0; i < len; i++) { //scan the full srcCache
+ final long v = srcCache[i];
+ if ((v <= 0L) || (v >= thetaLong) ) { continue; } //ignoring zeros or dirty values
+ cacheOut[j++] = v;
+ }
+ if (j < curCount) {
+ throw new SketchesStateException(
+ "Possible Corruption: curCount parameter is incorrect.");
+ }
+ if (dstOrdered && (curCount > 1)) {
+ Arrays.sort(cacheOut);
+ }
+ return cacheOut;
+ }
+
+ /*
+ * The truth table for empty, curCount and theta when compacting is as follows:
+ * <pre>
+ * Num Theta CurCount Empty State Name, Comments
+ * 0 1.0 0 T OK EMPTY: The Normal Empty State
+ * 1 1.0 0 F Internal This can occur internally as the result of an intersection of two exact,
+ * disjoint sets, or AnotB of two exact, identical sets. There is no probability
+ * distribution, so this is converted internally to EMPTY {1.0, 0, T}.
+ * This is handled in SetOperation.createCompactSketch().
+ * 2 1.0 !0 T Error Empty=T and curCount !0 should never coexist.
+ * This is checked in all compacting operations.
+ * 3 1.0 !0 F OK EXACT: This corresponds to a sketch in exact mode
+ * 4 <1.0 0 T Internal This can be an initial UpdateSketch state if p < 1.0,
+ * so change theta to 1.0. Return {Th = 1.0, 0, T}.
+ * This is handled in UpdateSketch.compact() and toByteArray().
+ * 5 <1.0 0 F OK This can result from set operations
+ * 6 <1.0 !0 T Error Empty=T and curCount !0 should never coexist.
+ * This is checked in all compacting operations.
+ * 7 <1.0 !0 F OK This corresponds to a sketch in estimation mode
+ * </pre>
+ * #4 is handled by <i>correctThetaOnCompat(boolean, int)</i> (below).
+ * #2 & #6 handled by <i>checkIllegalCurCountAndEmpty(boolean, int)</i>
+ */
+
+ /**
+ * This corrects a temporary anomalous condition where compact() is called on an UpdateSketch
+ * that was initialized with p < 1.0 and update() was never called. In this case Theta < 1.0,
+ * curCount = 0, and empty = true. The correction is to change Theta to 1.0, which makes the
+ * returning sketch empty. This should only be used in the compaction or serialization of an
+ * UpdateSketch.
+ * @param empty the given empty state
+ * @param curCount the given curCount
+ * @param thetaLong the given thetaLong
+ * @return thetaLong
+ */
+ static final long correctThetaOnCompact(final boolean empty, final int curCount,
+ final long thetaLong) { //handles #4 above
+ return (empty && (curCount == 0)) ? Long.MAX_VALUE : thetaLong;
+ }
+
+ /**
+ * This checks for the illegal condition where curCount > 0 and the state of
+ * empty = true. This check can be used anywhere a sketch is returned or a sketch is created
+ * from complete arguments.
+ * @param empty the given empty state
+ * @param curCount the given current count
+ */ //This handles #2 and #6 above
+ static final void checkIllegalCurCountAndEmpty(final boolean empty, final int curCount) {
+ if (empty && (curCount != 0)) { //this handles #2 and #6 above
+ throw new SketchesStateException("Illegal State: Empty=true and Current Count != 0.");
+ }
+ }
+
+ /**
+ * This compute number of preamble longs for a compact sketch based on <i>empty</i>,
+ * <i>curCount</i> and <i>thetaLong</i>.
+ * This also accommodates for EmptyCompactSketch and SingleItemSketch.
+ * @param empty The given empty state
+ * @param curCount The given current count (retained entries)
+ * @param thetaLong the current thetaLong
+ * @return the number of preamble longs
+ */
+ static final int computeCompactPreLongs(final boolean empty, final int curCount,
+ final long thetaLong) {
+ return (thetaLong < Long.MAX_VALUE) ? 3 : empty ? 1 : (curCount > 1) ? 2 : 1;
+ }
+
+ /**
+ * This checks for the singleItem Compact Sketch.
+ * @param empty the given empty state
+ * @param curCount the given curCount
+ * @param thetaLong the given thetaLong
+ * @return true if notEmpty, curCount = 1 and theta = 1.0;
+ */
+ static final boolean isSingleItem(final boolean empty, final int curCount,
+ final long thetaLong) {
+ return !empty && (curCount == 1) && (thetaLong == Long.MAX_VALUE);
+ }
+}
+
diff --git a/src/main/java/org/apache/datasketches/theta2/CompactSketch.java b/src/main/java/org/apache/datasketches/theta2/CompactSketch.java
new file mode 100644
index 00000000..0498eed3
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/CompactSketch.java
@@ -0,0 +1,478 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED;
+import static org.apache.datasketches.common.ByteArrayUtil.getShortLE;
+import static org.apache.datasketches.common.Family.idToFamily;
+import static org.apache.datasketches.theta2.PreambleUtil.COMPACT_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.EMPTY_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.FLAGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.ORDERED_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.PREAMBLE_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.READ_ONLY_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.SEED_HASH_SHORT;
+import static org.apache.datasketches.theta2.PreambleUtil.extractEntryBitsV4;
+import static org.apache.datasketches.theta2.PreambleUtil.extractFamilyID;
+import static org.apache.datasketches.theta2.PreambleUtil.extractFlags;
+import static org.apache.datasketches.theta2.PreambleUtil.extractNumEntriesBytesV4;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSerVer;
+import static org.apache.datasketches.theta2.PreambleUtil.extractThetaLongV4;
+import static org.apache.datasketches.theta2.PreambleUtil.wholeBytesToHoldBits;
+import static org.apache.datasketches.theta2.SingleItemSketch.otherCheckForSingleItem;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.common.Family;
+import org.apache.datasketches.common.SketchesArgumentException;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * The parent class of all the CompactSketches. CompactSketches are never created directly.
+ * They are created as a result of the compact() method of an UpdateSketch, a result of a
+ * getResult() of a SetOperation, or from a heapify method.
+ *
+ * <p>A CompactSketch is the simplest form of a Theta Sketch. It consists of a compact list
+ * (i.e., no intervening spaces) of hash values, which may be ordered or not, a value for theta
+ * and a seed hash. A CompactSketch is immutable (read-only),
+ * and the space required when stored is only the space required for the hash values and 8 to 24
+ * bytes of preamble. An empty CompactSketch consumes only 8 bytes.</p>
+ *
+ * @author Lee Rhodes
+ */
+public abstract class CompactSketch extends Sketch {
+
+ /**
+ * Heapify takes a CompactSketch image in a MemorySegment and instantiates an on-heap CompactSketch.
+ *
+ * <p>The resulting sketch will not retain any link to the source MemorySegment and all of its data will be
+ * copied to the heap CompactSketch.</p>
+ *
+ * <p>This method assumes that the sketch image was created with the correct hash seed, so it is not checked.
+ * The resulting on-heap CompactSketch will be given the seedHash derived from the given sketch image.
+ * However, Serial Version 1 sketch images do not have a seedHash field,
+ * so the resulting heapified CompactSketch will be given the hash of the DEFAULT_UPDATE_SEED.</p>
+ *
+ * @param srcSeg an image of a CompactSketch.
+ * @return a CompactSketch on the heap.
+ */
+ public static CompactSketch heapify(final MemorySegment srcSeg) {
+ return heapify(srcSeg, ThetaUtil.DEFAULT_UPDATE_SEED, false);
+ }
+
+ /**
+ * Heapify takes a CompactSketch image in Memory and instantiates an on-heap CompactSketch.
+ *
+ * <p>The resulting sketch will not retain any link to the source Memory and all of its data will be
+ * copied to the heap CompactSketch.</p>
+ *
+ * <p>This method checks if the given expectedSeed was used to create the source Memory image.
+ * However, SerialVersion 1 sketch images cannot be checked as they don't have a seedHash field,
+ * so the resulting heapified CompactSketch will be given the hash of the expectedSeed.</p>
+ *
+ * @param srcSeg an image of a CompactSketch that was created using the given expectedSeed.
+ * <a href="{@docRoot}/resources/dictionary.html#mem">See Memory</a>.
+ * @param expectedSeed the seed used to validate the given Memory image.
+ * <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>.
+ * @return a CompactSketch on the heap.
+ */
+ public static CompactSketch heapify(final MemorySegment srcSeg, final long expectedSeed) {
+ return heapify(srcSeg, expectedSeed, true);
+ }
+
+ private static CompactSketch heapify(final MemorySegment srcSeg, final long seed, final boolean enforceSeed) {
+ final int serVer = extractSerVer(srcSeg);
+ final int familyID = extractFamilyID(srcSeg);
+ final Family family = idToFamily(familyID);
+ if (family != Family.COMPACT) {
+ throw new IllegalArgumentException("Corrupted: " + family + " is not Compact!");
+ }
+ if (serVer == 4) {
+ return heapifyV4(srcSeg, seed, enforceSeed);
+ }
+ if (serVer == 3) {
+ final int flags = extractFlags(srcSeg);
+ final boolean srcOrdered = (flags & ORDERED_FLAG_MASK) != 0;
+ final boolean empty = (flags & EMPTY_FLAG_MASK) != 0;
+ if (enforceSeed && !empty) { PreambleUtil.checkMemorySeedHash(srcSeg, seed); }
+ return CompactOperations.memoryToCompact(srcSeg, srcOrdered, null);
+ }
+ //not SerVer 3, assume compact stored form
+ final short seedHash = ThetaUtil.computeSeedHash(seed);
+ if (serVer == 1) {
+ return ForwardCompatibility.heapify1to3(srcSeg, seedHash);
+ }
+ if (serVer == 2) {
+ return ForwardCompatibility.heapify2to3(srcSeg,
+ enforceSeed ? seedHash : (short) extractSeedHash(srcSeg));
+ }
+ throw new SketchesArgumentException("Unknown Serialization Version: " + serVer);
+ }
+
+ /**
+ * Wrap takes the CompactSketch image in given MemorySegment and refers to it directly.
+ * There is no data copying onto the java heap.
+ * The wrap operation enables fast read-only merging and access to all the public read-only API.
+ *
+ * <p>Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have
+ * been explicitly stored as direct sketches can be wrapped.
+ * Wrapping earlier serial version sketches will result in a heapify operation.
+ * These early versions were never designed to "wrap".</p>
+ *
+ * <p>Wrapping any subclass of this class that is empty or contains only a single item will
+ * result in heapified forms of empty and single item sketch respectively.
+ * This is actually faster and consumes less overall memory.</p>
+ *
+ * <p>This method assumes that the sketch image was created with the correct hash seed, so it is not checked.
+ * However, Serial Version 1 sketch images do not have a seedHash field,
+ * so the resulting on-heap CompactSketch will be given the hash of the DEFAULT_UPDATE_SEED.</p>
+ *
+ * @param srcSeg an image of a Sketch.
+ * @return a CompactSketch backed by the given MemorySegment except as above.
+ */
+ public static CompactSketch wrap(final MemorySegment srcSeg) {
+ return wrap(srcSeg, ThetaUtil.DEFAULT_UPDATE_SEED, false);
+ }
+
+ /**
+ * Wrap takes the sketch image in the given MemorySegment and refers to it directly.
+ * There is no data copying onto the java heap.
+ * The wrap operation enables fast read-only merging and access to all the public read-only API.
+ *
+ * <p>Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have
+ * been explicitly stored as direct sketches can be wrapped.
+ * Wrapping earlier serial version sketches will result in a heapify operation.
+ * These early versions were never designed to "wrap".</p>
+ *
+ * <p>Wrapping any subclass of this class that is empty or contains only a single item will
+ * result in heapified forms of empty and single item sketch respectively.
+ * This is actually faster and consumes less overall memory.</p>
+ *
+ * <p>This method checks if the given expectedSeed was used to create the source MemorySegment image.
+ * However, SerialVersion 1 sketches cannot be checked as they don't have a seedHash field,
+ * so the resulting heapified CompactSketch will be given the hash of the expectedSeed.</p>
+ *
+ * @param srcSeg an image of a Sketch that was created using the given expectedSeed.
+ * @param expectedSeed the seed used to validate the given MemorySegment image.
+ * <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>.
+ * @return a CompactSketch backed by the given MemorySegment except as above.
+ */
+ public static CompactSketch wrap(final MemorySegment srcSeg, final long expectedSeed) {
+ return wrap(srcSeg, expectedSeed, true);
+ }
+
+ private static CompactSketch wrap(final MemorySegment srcSeg, final long seed, final boolean enforceSeed) {
+ final int serVer = extractSerVer(srcSeg);
+ final int familyID = extractFamilyID(srcSeg);
+ final Family family = Family.idToFamily(familyID);
+ if (family != Family.COMPACT) {
+ throw new IllegalArgumentException("Corrupted: " + family + " is not Compact!");
+ }
+ final short seedHash = ThetaUtil.computeSeedHash(seed);
+
+ if (serVer == 4) {
+ return DirectCompactCompressedSketch.wrapInstance(srcSeg,
+ enforceSeed ? seedHash : (short) extractSeedHash(srcSeg));
+ }
+ else if (serVer == 3) {
+ if (PreambleUtil.isEmptyFlag(srcSeg)) {
+ return EmptyCompactSketch.getHeapInstance(srcSeg);
+ }
+ if (otherCheckForSingleItem(srcSeg)) {
+ return SingleItemSketch.heapify(srcSeg, enforceSeed ? seedHash : (short) extractSeedHash(srcSeg));
+ }
+ //not empty & not singleItem
+ final int flags = extractFlags(srcSeg);
+ final boolean compactFlag = (flags & COMPACT_FLAG_MASK) > 0;
+ if (!compactFlag) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have compact flag set");
+ }
+ final boolean readOnly = (flags & READ_ONLY_FLAG_MASK) > 0;
+ if (!readOnly) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have Read-Only flag set");
+ }
+ return DirectCompactSketch.wrapInstance(srcSeg,
+ enforceSeed ? seedHash : (short) extractSeedHash(srcSeg));
+ } //end of serVer 3
+ else if (serVer == 1) {
+ return ForwardCompatibility.heapify1to3(srcSeg, seedHash);
+ }
+ else if (serVer == 2) {
+ return ForwardCompatibility.heapify2to3(srcSeg,
+ enforceSeed ? seedHash : (short) extractSeedHash(srcSeg));
+ }
+ throw new SketchesArgumentException(
+ "Corrupted: Serialization Version " + serVer + " not recognized.");
+ }
+
+ /**
+ * Wrap takes the sketch image in the given MemorySegment and refers to it directly.
+ * There is no data copying onto the java heap.
+ * The wrap operation enables fast read-only merging and access to all the public read-only API.
+ *
+ * <p>Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have
+ * been explicitly stored as direct sketches can be wrapped.
+ * Wrapping earlier serial version sketches will result in a heapify operation.
+ * These early versions were never designed to "wrap".</p>
+ *
+ * <p>Wrapping any subclass of this class that is empty or contains only a single item will
+ * result in heapified forms of empty and single item sketch respectively.
+ * This is actually faster and consumes less overall memory.</p>
+ *
+ * <p>This method checks if the DEFAULT_UPDATE_SEED was used to create the source MemorySegment image.
+ * Note that SerialVersion 1 sketches cannot be checked as they don't have a seedHash field,
+ * so the resulting heapified CompactSketch will be given the hash of DEFAULT_UPDATE_SEED.</p>
+ *
+ * @param bytes a byte array image of a Sketch that was created using the DEFAULT_UPDATE_SEED.
+ *
+ * @return a CompactSketch backed by the given MemorySegment except as above.
+ */
+ public static CompactSketch wrap(final byte[] bytes) {
+ return wrap(bytes, ThetaUtil.DEFAULT_UPDATE_SEED, false);
+ }
+
+ /**
+ * Wrap takes the sketch image in the given MemorySegment and refers to it directly.
+ * There is no data copying onto the java heap.
+ * The wrap operation enables fast read-only merging and access to all the public read-only API.
+ *
+ * <p>Only "Direct" Serialization Version 3 (i.e, OpenSource) sketches that have
+ * been explicitly stored as direct sketches can be wrapped.
+ * Wrapping earlier serial version sketches will result in a heapify operation.
+ * These early versions were never designed to "wrap".</p>
+ *
+ * <p>Wrapping any subclass of this class that is empty or contains only a single item will
+ * result in heapified forms of empty and single item sketch respectively.
+ * This is actually faster and consumes less overall memory.</p>
+ *
+ * <p>This method checks if the given expectedSeed was used to create the source MemorySegment image.
+ * Note that SerialVersion 1 sketches cannot be checked as they don't have a seedHash field,
+ * so the resulting heapified CompactSketch will be given the hash of the expectedSeed.</p>
+ *
+ * @param bytes a byte array image of a Sketch that was created using the given expectedSeed.
+ * @param expectedSeed the seed used to validate the given MemorySegment image.
+ * <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>.
+ * @return a CompactSketch backed by the given MemorySegment except as above.
+ */
+ public static CompactSketch wrap(final byte[] bytes, final long expectedSeed) {
+ return wrap(bytes, expectedSeed, true);
+ }
+
+ private static CompactSketch wrap(final byte[] bytes, final long seed, final boolean enforceSeed) {
+ final int serVer = bytes[PreambleUtil.SER_VER_BYTE];
+ final int familyId = bytes[PreambleUtil.FAMILY_BYTE];
+ final Family family = Family.idToFamily(familyId);
+ if (family != Family.COMPACT) {
+ throw new IllegalArgumentException("Corrupted: " + family + " is not Compact!");
+ }
+ final short seedHash = ThetaUtil.computeSeedHash(seed);
+ if (serVer == 4) {
+ return WrappedCompactCompressedSketch.wrapInstance(bytes, seedHash);
+ } else if (serVer == 3) {
+ final int flags = bytes[FLAGS_BYTE];
+ if ((flags & EMPTY_FLAG_MASK) > 0) {
+ return EmptyCompactSketch.getHeapInstance(MemorySegment.ofArray(bytes));
+ }
+ final int preLongs = bytes[PREAMBLE_LONGS_BYTE];
+ if (otherCheckForSingleItem(preLongs, serVer, familyId, flags)) {
+ return SingleItemSketch.heapify(MemorySegment.ofArray(bytes), enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ }
+ //not empty & not singleItem
+ final boolean compactFlag = (flags & COMPACT_FLAG_MASK) > 0;
+ if (!compactFlag) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have compact flag set");
+ }
+ final boolean readOnly = (flags & READ_ONLY_FLAG_MASK) > 0;
+ if (!readOnly) {
+ throw new SketchesArgumentException(
+ "Corrupted: COMPACT family sketch image must have Read-Only flag set");
+ }
+ return WrappedCompactSketch.wrapInstance(bytes,
+ enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ } else if (serVer == 1) {
+ return ForwardCompatibility.heapify1to3(MemorySegment.ofArray(bytes), seedHash);
+ } else if (serVer == 2) {
+ return ForwardCompatibility.heapify2to3(MemorySegment.ofArray(bytes),
+ enforceSeed ? seedHash : getShortLE(bytes, SEED_HASH_SHORT));
+ }
+ throw new SketchesArgumentException(
+ "Corrupted: Serialization Version " + serVer + " not recognized.");
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public abstract CompactSketch compact(final boolean dstOrdered, final MemorySegment dstMem);
+
+ @Override
+ public int getCompactBytes() {
+ return getCurrentBytes();
+ }
+
+ @Override
+ int getCurrentDataLongs() {
+ return getRetainedEntries(true);
+ }
+
+ @Override
+ public Family getFamily() {
+ return Family.COMPACT;
+ }
+
+ @Override
+ public boolean isCompact() {
+ return true;
+ }
+
+ @Override
+ public double getEstimate() {
+ return Sketch.estimate(getThetaLong(), getRetainedEntries());
+ }
+
+ /**
+ * gets the sketch as a compressed byte array
+ * @return the sketch as a compressed byte array
+ */
+ public byte[] toByteArrayCompressed() {
+ if (!isOrdered() || getRetainedEntries() == 0 || (getRetainedEntries() == 1 && !isEstimationMode())) {
+ return toByteArray();
+ }
+ return toByteArrayV4();
+ }
+
+ private int computeMinLeadingZeros() {
+ // compression is based on leading zeros in deltas between ordered hash values
+ // assumes ordered sketch
+ long previous = 0;
+ long ored = 0;
+ final HashIterator it = iterator();
+ while (it.next()) {
+ final long delta = it.get() - previous;
+ ored |= delta;
+ previous = it.get();
+ }
+ return Long.numberOfLeadingZeros(ored);
+ }
+
+ private byte[] toByteArrayV4() {
+ final int preambleLongs = isEstimationMode() ? 2 : 1;
+ final int entryBits = 64 - computeMinLeadingZeros();
+ final int compressedBits = entryBits * getRetainedEntries();
+
+ // store num_entries as whole bytes since whole-byte blocks will follow (most probably)
+ final int numEntriesBytes = wholeBytesToHoldBits(32 - Integer.numberOfLeadingZeros(getRetainedEntries()));
+
+ final int sizeBytes = preambleLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(compressedBits);
+ final byte[] bytes = new byte[sizeBytes];
+ final MemorySegment wseg = MemorySegment.ofArray(bytes);
+ int offsetBytes = 0;
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) preambleLongs);
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) 4); // to do: add constant
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) Family.COMPACT.getID());
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) entryBits);
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) numEntriesBytes);
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) (COMPACT_FLAG_MASK | READ_ONLY_FLAG_MASK | ORDERED_FLAG_MASK));
+ wseg.set(JAVA_SHORT_UNALIGNED, offsetBytes, getSeedHash());
+ offsetBytes += Short.BYTES;
+ if (isEstimationMode()) {
+ wseg.set(JAVA_LONG_UNALIGNED, offsetBytes, getThetaLong());
+ offsetBytes += Long.BYTES;
+ }
+ int numEntries = getRetainedEntries();
+ for (int i = 0; i < numEntriesBytes; i++) {
+ wseg.set(JAVA_BYTE, offsetBytes++, (byte) (numEntries & 0xff));
+ numEntries >>>= 8;
+ }
+ long previous = 0;
+ final long[] deltas = new long[8];
+ final HashIterator it = iterator();
+ int i;
+ for (i = 0; i + 7 < getRetainedEntries(); i += 8) {
+ for (int j = 0; j < 8; j++) {
+ it.next();
+ deltas[j] = it.get() - previous;
+ previous = it.get();
+ }
+ BitPacking.packBitsBlock8(deltas, 0, bytes, offsetBytes, entryBits);
+ offsetBytes += entryBits;
+ }
+ int offsetBits = 0;
+ for (; i < getRetainedEntries(); i++) {
+ it.next();
+ final long delta = it.get() - previous;
+ previous = it.get();
+ BitPacking.packBits(delta, entryBits, bytes, offsetBytes, offsetBits);
+ offsetBytes += (offsetBits + entryBits) >>> 3;
+ offsetBits = (offsetBits + entryBits) & 7;
+ }
+ return bytes;
+ }
+
+ private static CompactSketch heapifyV4(final MemorySegment srcSeg, final long seed, final boolean enforceSeed) {
+ final int preLongs = extractPreLongs(srcSeg);
+ final int entryBits = extractEntryBitsV4(srcSeg);
+ final int numEntriesBytes = extractNumEntriesBytesV4(srcSeg);
+ final short seedHash = (short) extractSeedHash(srcSeg);
+ if (enforceSeed) { PreambleUtil.checkMemorySeedHash(srcSeg, seed); }
+ int offsetBytes = 8;
+ long theta = Long.MAX_VALUE;
+ if (preLongs > 1) {
+ theta = extractThetaLongV4(srcSeg);
+ offsetBytes += Long.BYTES;
+ }
+ int numEntries = 0;
+ for (int i = 0; i < numEntriesBytes; i++) {
+ numEntries |= Byte.toUnsignedInt(srcSeg.get(JAVA_BYTE, offsetBytes++)) << (i << 3);
+ }
+ final long[] entries = new long[numEntries];
+ final byte[] bytes = new byte[entryBits]; // temporary buffer for unpacking
+ int i;
+ for (i = 0; i + 7 < numEntries; i += 8) {
+ MemorySegment.copy(srcSeg, JAVA_BYTE, offsetBytes, bytes, 0, entryBits);
+ BitPacking.unpackBitsBlock8(entries, i, bytes, 0, entryBits);
+ offsetBytes += entryBits;
+ }
+ if (i < numEntries) {
+ MemorySegment.copy(srcSeg, JAVA_BYTE, offsetBytes, bytes, 0, wholeBytesToHoldBits((numEntries - i) * entryBits));
+ int offsetBits = 0;
+ offsetBytes = 0;
+ for (; i < numEntries; i++) {
+ BitPacking.unpackBits(entries, i, entryBits, bytes, offsetBytes, offsetBits);
+ offsetBytes += (offsetBits + entryBits) >>> 3;
+ offsetBits = (offsetBits + entryBits) & 7;
+ }
+ }
+ // undo deltas
+ long previous = 0;
+ for (i = 0; i < numEntries; i++) {
+ entries[i] += previous;
+ previous = entries[i];
+ }
+ return new HeapCompactSketch(entries, false, seedHash, numEntries, theta, true);
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentBackgroundThetaPropagation.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentBackgroundThetaPropagation.java
new file mode 100644
index 00000000..2d529c4c
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentBackgroundThetaPropagation.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Background propagation thread. Propagates a given sketch or a hash value from local threads
+ * buffers into the shared sketch which stores the most up-to-date estimation of number of unique
+ * items. This propagation is done at the background by dedicated threads, which allows
+ * application threads to continue updating their local buffer.
+ *
+ * @author eshcar
+ */
+class ConcurrentBackgroundThetaPropagation implements Runnable {
+
+ // Shared sketch to absorb the data
+ private final ConcurrentSharedThetaSketch sharedThetaSketch;
+
+ // Propagation flag of local buffer that is being processed.
+ // It is the synchronization primitive to coordinate the work of the propagation with the
+ // local buffer. Updated when the propagation completes.
+ private final AtomicBoolean localPropagationInProgress;
+
+ // Sketch to be propagated to shared sketch. Can be null if only a single hash is propagated
+ private final Sketch sketchIn;
+
+ // Hash of the datum to be propagated to shared sketch. Can be ConcurrentSharedThetaSketch.NOT_SINGLE_HASH
+ // if the data is propagated through a sketch.
+ private final long singleHash;
+
+ // The propagation epoch. The data can be propagated only within the context of this epoch.
+ // The data should not be propagated if this epoch is not equal to the
+ // shared sketch epoch.
+ private final long epoch;
+
+ ConcurrentBackgroundThetaPropagation(final ConcurrentSharedThetaSketch sharedThetaSketch,
+ final AtomicBoolean localPropagationInProgress, final Sketch sketchIn, final long singleHash,
+ final long epoch) {
+ this.sharedThetaSketch = sharedThetaSketch;
+ this.localPropagationInProgress = localPropagationInProgress;
+ this.sketchIn = sketchIn;
+ this.singleHash = singleHash;
+ this.epoch = epoch;
+ }
+
+ /**
+ * Propagation protocol:
+ * 1) validate propagation is executed at the context of the right epoch, otherwise abort
+ * 2) handle propagation: either of a single hash or of a sketch
+ * 3) complete propagation: ping local buffer
+ */
+ @Override
+ public void run() {
+ // 1) validate propagation is executed at the context of the right epoch, otherwise abort
+ if (!sharedThetaSketch.validateEpoch(epoch)) {
+ // invalid epoch - should not propagate
+ sharedThetaSketch.endPropagation(null, false);
+ return;
+ }
+
+ // 2) handle propagation: either of a single hash or of a sketch
+ if (singleHash != ConcurrentSharedThetaSketch.NOT_SINGLE_HASH) {
+ sharedThetaSketch.propagate(singleHash);
+ } else if (sketchIn != null) {
+ final long volTheta = sharedThetaSketch.getVolatileTheta();
+ assert volTheta <= sketchIn.getThetaLong() :
+ "volTheta = " + volTheta + ", bufTheta = " + sketchIn.getThetaLong();
+
+ // propagate values from input sketch one by one
+ final long[] cacheIn = sketchIn.getCache();
+
+ if (sketchIn.isOrdered()) { //Ordered compact, Use early stop
+ for (final long hashIn : cacheIn) {
+ if (hashIn >= volTheta) {
+ break; //early stop
+ }
+ sharedThetaSketch.propagate(hashIn);
+ }
+ } else { //not ordered, also may have zeros (gaps) in the array.
+ for (final long hashIn : cacheIn) {
+ if (hashIn > 0) {
+ sharedThetaSketch.propagate(hashIn);
+ }
+ }
+ }
+ }
+
+ // 3) complete propagation: ping local buffer
+ sharedThetaSketch.endPropagation(localPropagationInProgress, false);
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentDirectQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentDirectQuickSelectSketch.java
new file mode 100644
index 00000000..af591712
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentDirectQuickSelectSketch.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static org.apache.datasketches.theta2.PreambleUtil.THETA_LONG;
+
+import java.lang.foreign.MemorySegment;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.datasketches.common.ResizeFactor;
+import org.apache.datasketches.common.SuppressFBWarnings;
+
+/**
+ * A concurrent shared sketch that is based on DirectQuickSelectSketch.
+ * It reflects all data processed by a single or multiple update threads, and can serve queries at
+ * any time.
+ * Background propagation threads are used to propagate data from thread local buffers into this
+ * sketch which stores the most up-to-date estimation of number of unique items.
+ *
+ * @author eshcar
+ * @author Lee Rhodes
+ */
+final class ConcurrentDirectQuickSelectSketch extends DirectQuickSelectSketch
+ implements ConcurrentSharedThetaSketch {
+
+ // The propagation thread
+ private ExecutorService executorService_;
+
+ // A flag to coordinate between several eager propagation threads
+ private final AtomicBoolean sharedPropagationInProgress_;
+
+ // Theta value of concurrent sketch
+ private volatile long volatileThetaLong_;
+
+ // A snapshot of the estimated number of unique entries
+ private volatile double volatileEstimate_;
+
+ // Num of retained entries in which the sketch toggles from sync (exact) mode to async
+ // propagation mode
+ private final long exactLimit_;
+
+ // An epoch defines an interval between two resets. A propagation invoked at epoch i cannot
+ // affect the sketch at epoch j > i.
+ private volatile long epoch_;
+
+ /**
+ * Construct a new sketch instance and initialize the given Memory as its backing store.
+ *
+ * @param lgNomLongs <a href="{@docRoot}/resources/dictionary.html#lgNomLongs">See lgNomLongs</a>.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>.
+ * @param maxConcurrencyError the max error value including error induced by concurrency.
+ * @param dstSeg the given MemorySegment object destination. It cannot be null.
+ */
+ ConcurrentDirectQuickSelectSketch(final int lgNomLongs, final long seed,
+ final double maxConcurrencyError, final MemorySegment dstSeg) {
+ super(lgNomLongs, seed, 1.0F, //p
+ ResizeFactor.X1, //rf,
+ dstSeg, false); //unionGadget
+
+ volatileThetaLong_ = Long.MAX_VALUE;
+ volatileEstimate_ = 0;
+ exactLimit_ = ConcurrentSharedThetaSketch.computeExactLimit(1L << getLgNomLongs(),
+ maxConcurrencyError);
+ sharedPropagationInProgress_ = new AtomicBoolean(false);
+ epoch_ = 0;
+ initBgPropagationService();
+ }
+
+ ConcurrentDirectQuickSelectSketch(final UpdateSketch sketch, final long seed,
+ final double maxConcurrencyError, final MemorySegment dstSeg) {
+ super(sketch.getLgNomLongs(), seed, 1.0F, //p
+ ResizeFactor.X1, //rf,
+ dstSeg,
+ false); //unionGadget
+
+ exactLimit_ = ConcurrentSharedThetaSketch.computeExactLimit(1L << getLgNomLongs(),
+ maxConcurrencyError);
+ sharedPropagationInProgress_ = new AtomicBoolean(false);
+ epoch_ = 0;
+ initBgPropagationService();
+ for (final long hashIn : sketch.getCache()) {
+ propagate(hashIn);
+ }
+ wseg_.set(JAVA_LONG_UNALIGNED, THETA_LONG, sketch.getThetaLong());
+ updateVolatileTheta();
+ updateEstimationSnapshot();
+ }
+
+ //Sketch overrides
+
+ @Override
+ public double getEstimate() {
+ return volatileEstimate_;
+ }
+
+ @Override
+ public boolean isEstimationMode() {
+ return (getRetainedEntries(false) > exactLimit_) || super.isEstimationMode();
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ while (!sharedPropagationInProgress_.compareAndSet(false, true)) { } //busy wait till free
+ final byte[] res = super.toByteArray();
+ sharedPropagationInProgress_.set(false);
+ return res;
+ }
+
+ //UpdateSketch overrides
+
+ @Override
+ public UpdateSketch rebuild() {
+ super.rebuild();
+ updateEstimationSnapshot();
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * Takes care of mutual exclusion with propagation thread.
+ */
+ @Override
+ public void reset() {
+ advanceEpoch();
+ super.reset();
+ volatileThetaLong_ = Long.MAX_VALUE;
+ volatileEstimate_ = 0;
+ }
+
+ @Override
+ UpdateReturnState hashUpdate(final long hash) {
+ final String msg = "No update method should be called directly to a shared theta sketch."
+ + " Updating the shared sketch is only permitted through propagation from local sketches.";
+ throw new UnsupportedOperationException(msg);
+ }
+
+ //ConcurrentSharedThetaSketch declarations
+
+ @Override
+ public long getExactLimit() {
+ return exactLimit_;
+ }
+
+ @Override
+ public boolean startEagerPropagation() {
+ while (!sharedPropagationInProgress_.compareAndSet(false, true)) { } //busy wait till free
+ return (!isEstimationMode());// no eager propagation is allowed in estimation mode
+ }
+
+ @Override
+ public void endPropagation(final AtomicBoolean localPropagationInProgress, final boolean isEager) {
+ //update volatile theta, uniques estimate and propagation flag
+ updateVolatileTheta();
+ updateEstimationSnapshot();
+ if (isEager) {
+ sharedPropagationInProgress_.set(false);
+ }
+ if (localPropagationInProgress != null) {
+ localPropagationInProgress.set(false); //clear local propagation flag
+ }
+ }
+
+ @Override
+ public long getVolatileTheta() {
+ return volatileThetaLong_;
+ }
+
+ @Override
+ public void awaitBgPropagationTermination() {
+ try {
+ executorService_.shutdown();
+ while (!executorService_.awaitTermination(1, TimeUnit.MILLISECONDS)) {
+ Thread.sleep(1);
+ }
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public final void initBgPropagationService() {
+ executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().threadId());
+ }
+
+ @Override
+ public boolean propagate(final AtomicBoolean localPropagationInProgress,
+ final Sketch sketchIn, final long singleHash) {
+ final long epoch = epoch_;
+ if ((singleHash != NOT_SINGLE_HASH) // namely, is a single hash and
+ && (getRetainedEntries(false) < exactLimit_)) { // a small sketch then propagate myself (blocking)
+ if (!startEagerPropagation()) {
+ endPropagation(localPropagationInProgress, true);
+ return false;
+ }
+ if (!validateEpoch(epoch)) {
+ endPropagation(null, true); // do not change local flag
+ return true;
+ }
+ propagate(singleHash);
+ endPropagation(localPropagationInProgress, true);
+ return true;
+ }
+ // otherwise, be nonblocking, let background thread do the work
+ final ConcurrentBackgroundThetaPropagation job = new ConcurrentBackgroundThetaPropagation(
+ this, localPropagationInProgress, sketchIn, singleHash, epoch);
+ executorService_.execute(job);
+ return true;
+ }
+
+ @Override
+ public void propagate(final long singleHash) {
+ super.hashUpdate(singleHash);
+ }
+
+ @Override
+ public void updateEstimationSnapshot() {
+ volatileEstimate_ = super.getEstimate();
+ }
+
+ @Override
+ public void updateVolatileTheta() {
+ volatileThetaLong_ = getThetaLong();
+ }
+
+ @Override
+ public boolean validateEpoch(final long epoch) {
+ return epoch_ == epoch;
+ }
+
+ //Restricted
+
+ /**
+ * Advances the epoch while there is no background propagation
+ * This ensures a propagation invoked before the reset cannot affect the sketch after the reset
+ * is completed. Ignore VO_VOLATILE_INCREMENT findbugs warning, it is False Positive.
+ */
+ @SuppressFBWarnings(value = "VO_VOLATILE_INCREMENT", justification = "Likely False Positive, Fix Later")
+ private void advanceEpoch() {
+ awaitBgPropagationTermination();
+ startEagerPropagation();
+ ConcurrentPropagationService.resetExecutorService(Thread.currentThread().threadId());
+ //no inspection NonAtomicOperationOnVolatileField
+ // this increment of a volatile field is done within the scope of the propagation
+ // synchronization and hence is done by a single thread.
+ epoch_++;
+ endPropagation(null, true);
+ initBgPropagationService();
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapQuickSelectSketch.java
new file mode 100644
index 00000000..56e254b5
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapQuickSelectSketch.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.datasketches.common.ResizeFactor;
+import org.apache.datasketches.common.SuppressFBWarnings;
+
+/**
+ * A concurrent shared sketch that is based on HeapQuickSelectSketch.
+ * It reflects all data processed by a single or multiple update threads, and can serve queries at
+ * any time.
+ * Background propagation threads are used to propagate data from thread local buffers into this
+ * sketch which stores the most up-to-date estimation of number of unique items.
+ *
+ * @author eshcar
+ * @author Lee Rhodes
+ */
+final class ConcurrentHeapQuickSelectSketch extends HeapQuickSelectSketch
+ implements ConcurrentSharedThetaSketch {
+
+ // The propagation thread
+ private volatile ExecutorService executorService_;
+
+ //A flag to coordinate between several eager propagation threads
+ private final AtomicBoolean sharedPropagationInProgress_;
+
+ // Theta value of concurrent sketch
+ private volatile long volatileThetaLong_;
+
+ // A snapshot of the estimated number of unique entries
+ private volatile double volatileEstimate_;
+
+ // Num of retained entries in which the sketch toggles from sync (exact) mode to async
+ // propagation mode
+ private final long exactLimit_;
+
+ // An epoch defines an interval between two resets. A propagation invoked at epoch i cannot
+ // affect the sketch at epoch j > i.
+ private volatile long epoch_;
+
+ /**
+ * Construct a new sketch instance on the java heap.
+ *
+ * @param lgNomLongs <a href="{@docRoot}/resources/dictionary.html#lgNomLogs">See lgNomLongs</a>.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See seed</a>
+ * @param maxConcurrencyError the max error value including error induced by concurrency
+ *
+ */
+ ConcurrentHeapQuickSelectSketch(final int lgNomLongs, final long seed,
+ final double maxConcurrencyError) {
+ super(lgNomLongs, seed, 1.0F, //p
+ ResizeFactor.X1, //rf,
+ false); //unionGadget
+
+ volatileThetaLong_ = Long.MAX_VALUE;
+ volatileEstimate_ = 0;
+ exactLimit_ = ConcurrentSharedThetaSketch.computeExactLimit(1L << getLgNomLongs(),
+ maxConcurrencyError);
+ sharedPropagationInProgress_ = new AtomicBoolean(false);
+ epoch_ = 0;
+ initBgPropagationService();
+ }
+
+ ConcurrentHeapQuickSelectSketch(final UpdateSketch sketch, final long seed,
+ final double maxConcurrencyError) {
+ super(sketch.getLgNomLongs(), seed, 1.0F, //p
+ ResizeFactor.X1, //rf,
+ false); //unionGadget
+
+ exactLimit_ = ConcurrentSharedThetaSketch.computeExactLimit(1L << getLgNomLongs(),
+ maxConcurrencyError);
+ sharedPropagationInProgress_ = new AtomicBoolean(false);
+ epoch_ = 0;
+ initBgPropagationService();
+ for (final long hashIn : sketch.getCache()) {
+ propagate(hashIn);
+ }
+ thetaLong_ = sketch.getThetaLong();
+ updateVolatileTheta();
+ updateEstimationSnapshot();
+ }
+
+ //Sketch overrides
+
+ @Override
+ public double getEstimate() {
+ return volatileEstimate_;
+ }
+
+ @Override
+ public boolean isEstimationMode() {
+ return (getRetainedEntries(false) > exactLimit_) || super.isEstimationMode();
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ while (!sharedPropagationInProgress_.compareAndSet(false, true)) { } //busy wait till free
+ final byte[] res = super.toByteArray();
+ sharedPropagationInProgress_.set(false);
+ return res;
+ }
+
+ //UpdateSketch overrides
+
+ @Override
+ public UpdateSketch rebuild() {
+ super.rebuild();
+ updateEstimationSnapshot();
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * Takes care of mutual exclusion with propagation thread.
+ */
+ @Override
+ public void reset() {
+ advanceEpoch();
+ super.reset();
+ volatileThetaLong_ = Long.MAX_VALUE;
+ volatileEstimate_ = 0;
+ }
+
+ @Override
+ UpdateReturnState hashUpdate(final long hash) {
+ final String msg = "No update method should be called directly to a shared theta sketch."
+ + " Updating the shared sketch is only permitted through propagation from local sketches.";
+ throw new UnsupportedOperationException(msg);
+ }
+
+ //ConcurrentSharedThetaSketch declarations
+
+ @Override
+ public long getExactLimit() {
+ return exactLimit_;
+ }
+
+ @Override
+ public boolean startEagerPropagation() {
+ while (!sharedPropagationInProgress_.compareAndSet(false, true)) { } //busy wait till free
+ return (!isEstimationMode());// no eager propagation is allowed in estimation mode
+ }
+
+ @Override
+ public void endPropagation(final AtomicBoolean localPropagationInProgress, final boolean isEager) {
+ //update volatile theta, uniques estimate and propagation flag
+ updateVolatileTheta();
+ updateEstimationSnapshot();
+ if (isEager) {
+ sharedPropagationInProgress_.set(false);
+ }
+ if (localPropagationInProgress != null) {
+ localPropagationInProgress.set(false); //clear local propagation flag
+ }
+ }
+
+ @Override
+ public long getVolatileTheta() {
+ return volatileThetaLong_;
+ }
+
+ @Override
+ public void awaitBgPropagationTermination() {
+ try {
+ executorService_.shutdown();
+ while (!executorService_.awaitTermination(1, TimeUnit.MILLISECONDS)) {
+ Thread.sleep(1);
+ }
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void initBgPropagationService() {
+ executorService_ = ConcurrentPropagationService.getExecutorService(Thread.currentThread().threadId());
+ }
+
+ @Override
+ public boolean propagate(final AtomicBoolean localPropagationInProgress,
+ final Sketch sketchIn, final long singleHash) {
+ final long epoch = epoch_;
+ if ((singleHash != NOT_SINGLE_HASH) //namely, is a single hash and
+ && (getRetainedEntries(false) < exactLimit_)) { //a small sketch then propagate myself (blocking)
+ if (!startEagerPropagation()) {
+ endPropagation(localPropagationInProgress, true);
+ return false;
+ }
+ if (!validateEpoch(epoch)) {
+ endPropagation(null, true); // do not change local flag
+ return true;
+ }
+ propagate(singleHash);
+ endPropagation(localPropagationInProgress, true);
+ return true;
+ }
+ // otherwise, be nonblocking, let background thread do the work
+ final ConcurrentBackgroundThetaPropagation job = new ConcurrentBackgroundThetaPropagation(
+ this, localPropagationInProgress, sketchIn, singleHash, epoch);
+ executorService_.execute(job);
+ return true;
+ }
+
+ @Override
+ public void propagate(final long singleHash) {
+ super.hashUpdate(singleHash);
+ }
+
+ @Override
+ public void updateEstimationSnapshot() {
+ volatileEstimate_ = super.getEstimate();
+ }
+
+ @Override
+ public void updateVolatileTheta() {
+ volatileThetaLong_ = getThetaLong();
+ }
+
+ @Override
+ public boolean validateEpoch(final long epoch) {
+ return epoch_ == epoch;
+ }
+
+ //Restricted
+
+ /**
+ * Advances the epoch while there is no background propagation
+ * This ensures a propagation invoked before the reset cannot affect the sketch after the reset
+ * is completed.
+ */
+ @SuppressFBWarnings(value = "VO_VOLATILE_INCREMENT", justification = "Likely False Positive, Fix Later")
+ private void advanceEpoch() {
+ awaitBgPropagationTermination();
+ startEagerPropagation();
+ ConcurrentPropagationService.resetExecutorService(Thread.currentThread().threadId());
+ //no inspection NonAtomicOperationOnVolatileField
+ // this increment of a volatile field is done within the scope of the propagation
+ // synchronization and hence is done by a single thread
+ // Ignore a FindBugs warning
+ epoch_++;
+ endPropagation(null, true);
+ initBgPropagationService();
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapThetaBuffer.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapThetaBuffer.java
new file mode 100644
index 00000000..ab1d41a6
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentHeapThetaBuffer.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static org.apache.datasketches.theta2.UpdateReturnState.ConcurrentBufferInserted;
+import static org.apache.datasketches.theta2.UpdateReturnState.ConcurrentPropagated;
+import static org.apache.datasketches.theta2.UpdateReturnState.RejectedOverTheta;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.datasketches.common.ResizeFactor;
+import org.apache.datasketches.thetacommon.HashOperations;
+
+/**
+ * This is a theta filtering, bounded size buffer that operates in the context of a single writing
+ * thread. When the buffer becomes full its content is propagated into the shared sketch, which
+ * may be on a different thread. The limit on the buffer size is configurable. A bound of size 1
+ * allows the combination of buffers and shared sketch to maintain an error bound in real-time
+ * that is close to the error bound of a sequential theta sketch. Allowing larger buffer sizes
+ * enables amortization of the cost propagations and substantially improves overall system throughput.
+ * The error caused by the buffering is essentially a perspective of time and synchronization
+ * and not really a true error. At the end of a stream, after all the buffers have synchronized with
+ * the shared sketch, there is no additional error.
+ * Propagation is done either synchronously by the updating thread, or asynchronously by a
+ * background propagation thread.
+ *
+ * <p>This is a buffer, not a sketch, and it extends the <i>HeapQuickSelectSketch</i>
+ * in order to leverage some of the sketch machinery to make its work simple. However, if this
+ * buffer receives a query, like <i>getEstimate()</i>, the correct answer does not come from the super
+ * <i>HeapQuickSelectSketch</i>, which knows nothing about the concurrency relationship to the
+ * shared concurrent sketch, it must come from the shared concurrent sketch. As a result nearly all
+ * of the inherited sketch methods are redirected to the shared concurrent sketch.
+ *
+ * @author eshcar
+ * @author Lee Rhodes
+ */
+final class ConcurrentHeapThetaBuffer extends HeapQuickSelectSketch {
+
+ // Shared sketch consisting of the global sample set and theta value.
+ private final ConcurrentSharedThetaSketch shared;
+
+ // A flag indicating whether the shared sketch is in shared mode and requires eager propagation
+ // Initially this is true. Once it is set to false (estimation mode) it never flips back.
+ private boolean isExactMode;
+
+ // A flag to indicate if we expect the propagated data to be ordered
+ private final boolean propagateOrderedCompact;
+
+ // Propagation flag is set to true while propagation is in progress (or pending).
+ // It is the synchronization primitive to coordinate the work with the propagation thread.
+ private final AtomicBoolean localPropagationInProgress;
+
+ ConcurrentHeapThetaBuffer(final int lgNomLongs, final long seed,
+ final ConcurrentSharedThetaSketch shared, final boolean propagateOrderedCompact,
+ final int maxNumLocalThreads) {
+ super(computeLogBufferSize(lgNomLongs, shared.getExactLimit(), maxNumLocalThreads),
+ seed, 1.0F, //p
+ ResizeFactor.X1, //rf
+ false); //not a union gadget
+
+ this.shared = shared;
+ isExactMode = true;
+ this.propagateOrderedCompact = propagateOrderedCompact;
+ localPropagationInProgress = new AtomicBoolean(false);
+ }
+
+ private static int computeLogBufferSize(final int lgNomLongs, final long exactSize,
+ final int maxNumLocalBuffers) {
+ return Math.min(lgNomLongs, (int)Math.log(Math.sqrt(exactSize) / (2 * maxNumLocalBuffers)));
+ }
+
+ //concurrent restricted methods
+
+ /**
+ * Propagates a single hash value to the shared sketch
+ *
+ * @param hash to be propagated
+ */
+ private boolean propagateToSharedSketch(final long hash) {
+ //no inspection StatementWithEmptyBody
+ while (localPropagationInProgress.get()) {
+ } //busy wait until previous propagation completed
+ localPropagationInProgress.set(true);
+ final boolean res = shared.propagate(localPropagationInProgress, null, hash);
+ //in this case the parent empty_ and curCount_ were not touched
+ thetaLong_ = shared.getVolatileTheta();
+ return res;
+ }
+
+ /**
+ * Propagates the content of the buffer as a sketch to the shared sketch
+ */
+ private void propagateToSharedSketch() {
+ //no inspection StatementWithEmptyBody
+ while (localPropagationInProgress.get()) {
+ } //busy wait until previous propagation completed
+
+ final CompactSketch compactSketch = compact(propagateOrderedCompact, null);
+ localPropagationInProgress.set(true);
+ shared.propagate(localPropagationInProgress, compactSketch,
+ ConcurrentSharedThetaSketch.NOT_SINGLE_HASH);
+ super.reset();
+ thetaLong_ = shared.getVolatileTheta();
+ }
+
+ //Public Sketch overrides proxies to shared concurrent sketch
+
+ @Override
+ public int getCompactBytes() {
+ return shared.getCompactBytes();
+ }
+
+ @Override
+ public int getCurrentBytes() {
+ return shared.getCurrentBytes();
+ }
+
+ @Override
+ public double getEstimate() {
+ return shared.getEstimate();
+ }
+
+ @Override
+ public double getLowerBound(final int numStdDev) {
+ return shared.getLowerBound(numStdDev);
+ }
+
+ @Override
+ public double getUpperBound(final int numStdDev) {
+ return shared.getUpperBound(numStdDev);
+ }
+
+ @Override
+ public boolean hasMemorySegment() {
+ return false;
+ }
+
+ @Override
+ public boolean isDirect() {
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return shared.isEmpty();
+ }
+
+ @Override
+ public boolean isEstimationMode() {
+ return shared.isEstimationMode();
+ }
+
+ //End of proxies
+
+ @Override
+ public byte[] toByteArray() {
+ throw new UnsupportedOperationException("Local theta buffer need not be serialized");
+ }
+
+ //Public UpdateSketch overrides
+
+ @Override
+ public void reset() {
+ super.reset();
+ isExactMode = true;
+ localPropagationInProgress.set(false);
+ }
+
+ //Restricted UpdateSketch overrides
+
+ /**
+ * Updates buffer with given hash value.
+ * Triggers propagation to shared sketch if buffer is full.
+ *
+ * @param hash the given input hash value. A hash of zero or Long.MAX_VALUE is ignored.
+ * A negative hash value will throw an exception.
+ * @return
+ * <a href="{@docRoot}/resources/dictionary.html#updateReturnState">See Update Return State</a>
+ */
+ @Override
+ UpdateReturnState hashUpdate(final long hash) {
+ if (isExactMode) {
+ isExactMode = !shared.isEstimationMode();
+ }
+ HashOperations.checkHashCorruption(hash);
+ if ((getHashTableThreshold() == 0) || isExactMode ) {
+ //The over-theta and zero test
+ if (HashOperations.continueCondition(getThetaLong(), hash)) {
+ return RejectedOverTheta; //signal that hash was rejected due to theta or zero.
+ }
+ if (propagateToSharedSketch(hash)) {
+ return ConcurrentPropagated;
+ }
+ }
+ final UpdateReturnState state = super.hashUpdate(hash);
+ if (isOutOfSpace(getRetainedEntries(true) + 1)) {
+ propagateToSharedSketch();
+ return ConcurrentPropagated;
+ }
+ if (state == UpdateReturnState.InsertedCountIncremented) {
+ return ConcurrentBufferInserted;
+ }
+ return state;
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentPropagationService.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentPropagationService.java
new file mode 100644
index 00000000..92ca954f
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentPropagationService.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.datasketches.common.SuppressFBWarnings;
+
+/**
+ * Pool of threads to serve <i>all</i> propagation tasks in the system.
+ *
+ * @author Eshcar Hillel
+ */
+final class ConcurrentPropagationService {
+
+ static int NUM_POOL_THREADS = 3; // Default: 3 threads
+ private static volatile ConcurrentPropagationService instance = null; // Singleton
+ private static ExecutorService[] propagationExecutorService = null;
+
+ @SuppressFBWarnings(value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "Fix later")
+ private ConcurrentPropagationService() {
+ propagationExecutorService = new ExecutorService[NUM_POOL_THREADS];
+ }
+
+ //Factory: Get the singleton
+ @SuppressFBWarnings(value = "SSD_DO_NOT_USE_INSTANCE_LOCK_ON_SHARED_STATIC_DATA", justification = "Fix later")
+ private static ConcurrentPropagationService getInstance() {
+ if (instance == null) {
+ synchronized (ConcurrentPropagationService.class) {
+ if (instance == null) {
+ instance = new ConcurrentPropagationService(); //SpotBugs: SSD_DO_NOT_USE_INSTANCE_LOCK_ON_SHARED_STATIC_DATA
+ }
+ }
+ }
+ return instance;
+ }
+
+ public static ExecutorService getExecutorService(final long id) {
+ return getInstance().initExecutorService((int) id % NUM_POOL_THREADS);
+ }
+
+ @SuppressWarnings("static-access")
+ public static ExecutorService resetExecutorService(final long id) {
+ return getInstance().propagationExecutorService[(int) id % NUM_POOL_THREADS] = null;
+ }
+
+ @SuppressWarnings("static-method")
+ private ExecutorService initExecutorService(final int i) {
+ if (propagationExecutorService[i] == null) {
+ propagationExecutorService[i] = Executors.newSingleThreadExecutor();
+ }
+ return propagationExecutorService[i];
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/ConcurrentSharedThetaSketch.java b/src/main/java/org/apache/datasketches/theta2/ConcurrentSharedThetaSketch.java
new file mode 100644
index 00000000..5bf14704
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/ConcurrentSharedThetaSketch.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import java.lang.foreign.MemorySegment;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.datasketches.common.Util;
+
+/**
+ * An internal interface to define the API of a concurrent shared theta sketch.
+ * It reflects all data processed by a single or multiple update threads, and can serve queries at
+ * any time.
+ *
+ * @author eshcar
+ */
+interface ConcurrentSharedThetaSketch {
+
+ long NOT_SINGLE_HASH = -1L;
+ double MIN_ERROR = 0.0000001;
+
+ static long computeExactLimit(final long k, final double error) {
+ return 2 * Math.min(k, (long) Math.ceil(1.0 / Math.pow(Math.max(error,MIN_ERROR), 2.0)));
+ }
+
+ /**
+ * Returns flip point (number of updates) from exact to estimate mode.
+ * @return flip point from exact to estimate mode
+ */
+ long getExactLimit();
+
+ /**
+ * Ensures mutual exclusion. No other thread can update the shared sketch while propagation is
+ * in progress
+ * @return true if eager propagation was started
+ */
+ boolean startEagerPropagation();
+
+ /**
+ * Completes the propagation: end mutual exclusion block.
+ * Notifies the local thread the propagation is completed
+ *
+ * @param localPropagationInProgress the synchronization primitive through which propagator
+ * notifies local thread the propagation is completed
+ * @param isEager true if the propagation is in eager mode
+ */
+ void endPropagation(AtomicBoolean localPropagationInProgress, boolean isEager);
+
+ /**
+ * Returns the value of the volatile theta managed by the shared sketch
+ * @return the value of the volatile theta managed by the shared sketch
+ */
+ long getVolatileTheta();
+
+ /**
+ * Awaits termination of background (lazy) propagation tasks
+ */
+ void awaitBgPropagationTermination();
+
+ /**
+ * Init background (lazy) propagation service
+ */
+ void initBgPropagationService();
+
+ /**
+ * (Eager) Propagates the given sketch or hash value into this sketch
+ * @param localPropagationInProgress the flag to be updated when propagation is done
+ * @param sketchIn any Theta sketch with the data
+ * @param singleHash a single hash value
+ * @return true if propagation successfully started
+ */
+ boolean propagate(final AtomicBoolean localPropagationInProgress, final Sketch sketchIn,
+ final long singleHash);
+
+ /**
+ * (Lazy/Eager) Propagates the given hash value into this sketch
+ * @param singleHash a single hash value
+ */
+ void propagate(final long singleHash);
+
+ /**
+ * Updates the estimation of the number of unique entries by capturing a snapshot of the sketch
+ * data, namely, volatile theta and the num of valid entries in the sketch
+ */
+ void updateEstimationSnapshot();
+
+ /**
+ * Updates the value of the volatile theta by extracting it from the underlying sketch managed
+ * by the shared sketch
+ */
+ void updateVolatileTheta();
+
+ /**
+ * Validates the shared sketch is in the context of the given epoch
+ *
+ * @param epoch the epoch number to be validates
+ * @return true iff the shared sketch is in the context of the given epoch
+ */
+ boolean validateEpoch(long epoch);
+
+ //The following mirrors are public methods that already exist on the "extends" side of the dual
+ // inheritance. They are provided here to allow casts to this interface access
+ // to these methods without having to cast back to the extended parent class.
+ //
+ //This allows an internal class to cast either the Concurrent Direct or Concurrent Heap
+ //shared class to this interface and have access to the above special concurrent methods as
+ //well as the methods below.
+ //
+ //For the external user all of the below methods can be obtained by casting the shared
+ //sketch to UpdateSketch. However, these methods here also act as an alias so that an
+ //attempt to access these methods from the local buffer will be diverted to the shared
+ //sketch.
+
+ //From Sketch and MemoryStatus
+
+ int getCompactBytes();
+
+ int getCurrentBytes();
+
+ double getEstimate();
+
+ double getLowerBound(int numStdDev);
+
+ double getUpperBound(int numStdDev);
+
+ /**
+ * Returns true if this object's internal data is backed by a Memory object,
+ * which may be on-heap or off-heap.
+ * @return true if this object's internal data is backed by a Memory object.
+ */
+ boolean hasMemorySegment();
+
+ /**
+ * Returns true if this object's internal data is backed by direct (off-heap) Memory.
+ * @return true if this object's internal data is backed by direct (off-heap) Memory.
+ */
+ boolean isDirect();
+
+ /**
+ * Returns true if the two given MemorySegments refer to the same backing resource,
+ * which is either an off-heap memory location and size, or the same on-heap array object.
+ *
+ * <p>This is a convenient delegate of
+ * {@link org.apache.datasketches.common.Util#isSameResource(MemorySegment, MemorySegment) isSameResource()}</p>
+ *
+ * @param seg1 The first given MemorySegment
+ * @param seg2 The second given MemorySegment
+ * @return true if both MemorySegments are determined to be the same backing memory.
+ */
+ default boolean isSameResource(final MemorySegment seg1, final MemorySegment seg2) {
+ return Util.isSameResource(seg1, seg2);
+ }
+
+ boolean isEmpty();
+
+ boolean isEstimationMode();
+
+ byte[] toByteArray();
+
+ int getRetainedEntries(boolean valid);
+
+ CompactSketch compact();
+
+ CompactSketch compact(boolean ordered, MemorySegment wseg);
+
+ UpdateSketch rebuild();
+
+ void reset();
+}
+
diff --git a/src/main/java/org/apache/datasketches/theta2/DirectCompactCompressedSketch.java b/src/main/java/org/apache/datasketches/theta2/DirectCompactCompressedSketch.java
new file mode 100644
index 00000000..9be51c37
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/DirectCompactCompressedSketch.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.extractEntryBitsV4;
+import static org.apache.datasketches.theta2.PreambleUtil.extractNumEntriesBytesV4;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.extractThetaLongV4;
+import static org.apache.datasketches.theta2.PreambleUtil.wholeBytesToHoldBits;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * An off-heap (Direct), compact, compressed, read-only sketch. It is not empty, not a single item and ordered.
+ *
+ * <p>This sketch can only be associated with a Serialization Version 4 format binary image.</p>
+ *
+ * <p>This implementation uses data in a given MemorySegment that is owned and managed by the caller.
+ * This MemorySegment can be off-heap, which if managed properly will greatly reduce the need for
+ * the JVM to perform garbage collection.</p>
+ */
+class DirectCompactCompressedSketch extends DirectCompactSketch {
+ /**
+ * Construct this sketch with the given MemorySegment.
+ * @param seg Read-only MemorySegment object.
+ */
+ DirectCompactCompressedSketch(final MemorySegment seg) {
+ super(seg);
+ }
+
+ /**
+ * Wraps the given MemorySegment, which must be a SerVer 4 compressed CompactSketch image.
+ * Must check the validity of the Memory before calling.
+ * @param srcSeg The source MemorySegment
+ * @param seedHash The update seedHash.
+ * <a href="{@docRoot}/resources/dictionary.html#seedHash">See Seed Hash</a>.
+ * @return this sketch
+ */
+ static DirectCompactCompressedSketch wrapInstance(final MemorySegment srcSeg, final short seedHash) {
+ ThetaUtil.checkSeedHashes((short) extractSeedHash(srcSeg), seedHash);
+ return new DirectCompactCompressedSketch(srcSeg);
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public CompactSketch compact(final boolean dstOrdered, final MemorySegment dstSeg) {
+ if (dstSeg != null) {
+ MemorySegment.copy(seg_, 0, dstSeg, 0, getCurrentBytes());
+ return new DirectCompactSketch(dstSeg);
+ }
+ return CompactSketch.heapify(seg_);
+ }
+
+ @Override
+ public int getCurrentBytes() {
+ final int preLongs = extractPreLongs(seg_);
+ final int entryBits = extractEntryBitsV4(seg_);
+ final int numEntriesBytes = extractNumEntriesBytesV4(seg_);
+ return preLongs * Long.BYTES + numEntriesBytes + wholeBytesToHoldBits(getRetainedEntries() * entryBits);
+ }
+
+ private static final int START_PACKED_DATA_EXACT_MODE = 8;
+ private static final int START_PACKED_DATA_ESTIMATION_MODE = 16;
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //compact is always valid
+ // number of entries is stored using variable length encoding
+ // most significant bytes with all zeros are not stored
+ // one byte in the preamble has the number of non-zero bytes used
+ final int preLongs = extractPreLongs(seg_); // if > 1 then the second long has theta
+ final int numEntriesBytes = extractNumEntriesBytesV4(seg_);
+ int offsetBytes = preLongs > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE;
+ int numEntries = 0;
+ for (int i = 0; i < numEntriesBytes; i++) {
+ numEntries |= Byte.toUnsignedInt(seg_.get(JAVA_BYTE, offsetBytes++)) << (i << 3);
+ }
+ return numEntries;
+ }
+
+ @Override
+ public long getThetaLong() {
+ final int preLongs = extractPreLongs(seg_);
+ return (preLongs > 1) ? extractThetaLongV4(seg_) : Long.MAX_VALUE;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean isOrdered() {
+ return true;
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new MemoryCompactCompressedHashIterator(
+ seg_,
+ (extractPreLongs(seg_) > 1 ? START_PACKED_DATA_ESTIMATION_MODE : START_PACKED_DATA_EXACT_MODE)
+ + extractNumEntriesBytesV4(seg_),
+ extractEntryBitsV4(seg_),
+ getRetainedEntries()
+ );
+ }
+
+ //restricted methods
+
+ @Override
+ long[] getCache() {
+ final int numEntries = getRetainedEntries();
+ final long[] cache = new long[numEntries];
+ int i = 0;
+ final HashIterator it = iterator();
+ while (it.next()) {
+ cache[i++] = it.get();
+ }
+ return cache;
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/DirectCompactSketch.java b/src/main/java/org/apache/datasketches/theta2/DirectCompactSketch.java
new file mode 100644
index 00000000..188f2cd7
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/DirectCompactSketch.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static org.apache.datasketches.theta2.CompactOperations.checkIllegalCurCountAndEmpty;
+import static org.apache.datasketches.theta2.CompactOperations.memoryToCompact;
+import static org.apache.datasketches.theta2.PreambleUtil.ORDERED_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.extractCurCount;
+import static org.apache.datasketches.theta2.PreambleUtil.extractFlags;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.extractThetaLong;
+import static org.apache.datasketches.theta2.SingleItemSketch.otherCheckForSingleItem;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * An off-heap (Direct), compact, read-only sketch. The internal hash array can be either ordered
+ * or unordered. It is not empty, not a single item.
+ *
+ * <p>This sketch can only be associated with a Serialization Version 3 format binary image.</p>
+ *
+ * <p>This implementation uses data in a given MemorySegment that is owned and managed by the caller.
+ * This MemorySegment can be off-heap, which if managed properly will greatly reduce the need for
+ * the JVM to perform garbage collection.</p>
+ *
+ * @author Lee Rhodes
+ */
+class DirectCompactSketch extends CompactSketch {
+ final MemorySegment seg_;
+
+ /**
+ * Construct this sketch with the given MemorySegment.
+ * @param seg Read-only MemorySegment object with the order bit properly set.
+ */
+ DirectCompactSketch(final MemorySegment seg) {
+ seg_ = seg;
+ }
+
+ /**
+ * Wraps the given MemorySegment, which must be a SerVer 3, CompactSketch image.
+ * Must check the validity of the MemorySegment before calling. The order bit must be set properly.
+ * @param srcSeg the given MemorySegment
+ * @param seedHash The update seedHash.
+ * <a href="{@docRoot}/resources/dictionary.html#seedHash">See Seed Hash</a>.
+ * @return this sketch
+ */
+ static DirectCompactSketch wrapInstance(final MemorySegment srcSeg, final short seedHash) {
+ ThetaUtil.checkSeedHashes((short) extractSeedHash(srcSeg), seedHash);
+ return new DirectCompactSketch(srcSeg);
+ }
+
+ //Sketch Overrides
+
+ @Override
+ public CompactSketch compact(final boolean dstOrdered, final MemorySegment dstSeg) {
+ return memoryToCompact(seg_, dstOrdered, dstSeg);
+ }
+
+ @Override
+ public int getCurrentBytes() {
+ if (otherCheckForSingleItem(seg_)) { return 16; }
+ final int preLongs = extractPreLongs(seg_);
+ final int curCount = (preLongs == 1) ? 0 : extractCurCount(seg_);
+ return (preLongs + curCount) << 3;
+ }
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //compact is always valid
+ if (otherCheckForSingleItem(seg_)) { return 1; }
+ final int preLongs = extractPreLongs(seg_);
+ final int curCount = (preLongs == 1) ? 0 : extractCurCount(seg_);
+ return curCount;
+ }
+
+ @Override
+ public long getThetaLong() {
+ final int preLongs = extractPreLongs(seg_);
+ return (preLongs > 2) ? extractThetaLong(seg_) : Long.MAX_VALUE;
+ }
+
+ @Override
+ public boolean hasMemorySegment() {
+ return seg_ != null;
+ }
+
+ @Override
+ public boolean isDirect() {
+ return hasMemorySegment() ? seg_.isNative() : false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ final boolean emptyFlag = PreambleUtil.isEmptyFlag(seg_);
+ final long thetaLong = getThetaLong();
+ final int curCount = getRetainedEntries(true);
+ return emptyFlag || ((curCount == 0) && (thetaLong == Long.MAX_VALUE));
+ }
+
+ @Override
+ public boolean isOrdered() {
+ return (extractFlags(seg_) & ORDERED_FLAG_MASK) > 0;
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new MemoryHashIterator(seg_, getRetainedEntries(true), getThetaLong());
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ checkIllegalCurCountAndEmpty(isEmpty(), getRetainedEntries());
+ final int outBytes = getCurrentBytes();
+ final byte[] byteArrOut = new byte[outBytes];
+ MemorySegment.copy(seg_, JAVA_BYTE, 0, byteArrOut, 0, outBytes);
+ return byteArrOut;
+ }
+
+ //restricted methods
+
+ @Override
+ long[] getCache() {
+ if (otherCheckForSingleItem(seg_)) { return new long[] { seg_.get(JAVA_LONG_UNALIGNED, 8) }; }
+ final int preLongs = extractPreLongs(seg_);
+ final int curCount = (preLongs == 1) ? 0 : extractCurCount(seg_);
+ if (curCount > 0) {
+ final long[] cache = new long[curCount];
+ MemorySegment.copy(seg_, JAVA_LONG_UNALIGNED, preLongs << 3, cache, 0, curCount);
+ return cache;
+ }
+ return new long[0];
+ }
+
+ @Override
+ int getCompactPreambleLongs() {
+ return extractPreLongs(seg_);
+ }
+
+ @Override
+ int getCurrentPreambleLongs() {
+ return extractPreLongs(seg_);
+ }
+
+ @Override
+ MemorySegment getMemorySegment() {
+ return seg_;
+ }
+
+ @Override
+ short getSeedHash() {
+ return (short) extractSeedHash(seg_);
+ }
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketch.java b/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketch.java
new file mode 100644
index 00000000..32ae0d14
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketch.java
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_FLOAT_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static org.apache.datasketches.common.Util.LONG_MAX_VALUE_AS_DOUBLE;
+import static org.apache.datasketches.common.Util.newHeapSegment;
+import static org.apache.datasketches.theta2.PreambleUtil.EMPTY_FLAG_MASK;
+import static org.apache.datasketches.theta2.PreambleUtil.FLAGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.PREAMBLE_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.P_FLOAT;
+import static org.apache.datasketches.theta2.PreambleUtil.RETAINED_ENTRIES_INT;
+import static org.apache.datasketches.theta2.PreambleUtil.SER_VER;
+import static org.apache.datasketches.theta2.PreambleUtil.THETA_LONG;
+import static org.apache.datasketches.theta2.PreambleUtil.extractLgArrLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractLgNomLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.getMemBytes;
+import static org.apache.datasketches.theta2.PreambleUtil.insertCurCount;
+import static org.apache.datasketches.theta2.PreambleUtil.insertFamilyID;
+import static org.apache.datasketches.theta2.PreambleUtil.insertFlags;
+import static org.apache.datasketches.theta2.PreambleUtil.insertLgArrLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.insertLgNomLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.insertLgResizeFactor;
+import static org.apache.datasketches.theta2.PreambleUtil.insertP;
+import static org.apache.datasketches.theta2.PreambleUtil.insertPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.insertSeedHash;
+import static org.apache.datasketches.theta2.PreambleUtil.insertSerVer;
+import static org.apache.datasketches.theta2.PreambleUtil.insertThetaLong;
+import static org.apache.datasketches.theta2.PreambleUtil.insertUnionThetaLong;
+import static org.apache.datasketches.theta2.Rebuilder.actLgResizeFactor;
+import static org.apache.datasketches.theta2.Rebuilder.moveAndResize;
+import static org.apache.datasketches.theta2.Rebuilder.quickSelectAndRebuild;
+import static org.apache.datasketches.theta2.Rebuilder.resize;
+import static org.apache.datasketches.theta2.UpdateReturnState.InsertedCountIncremented;
+import static org.apache.datasketches.theta2.UpdateReturnState.InsertedCountIncrementedRebuilt;
+import static org.apache.datasketches.theta2.UpdateReturnState.InsertedCountIncrementedResized;
+import static org.apache.datasketches.theta2.UpdateReturnState.RejectedDuplicate;
+import static org.apache.datasketches.theta2.UpdateReturnState.RejectedOverTheta;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.common.Family;
+import org.apache.datasketches.common.ResizeFactor;
+import org.apache.datasketches.common.SketchesArgumentException;
+import org.apache.datasketches.thetacommon.HashOperations;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * The default Theta Sketch using the QuickSelect algorithm.
+ * This subclass implements methods, which affect the state (update, rebuild, reset)
+ *
+ * <p>This implementation uses data in a given Memory that is owned and managed by the caller.
+ * This Memory can be off-heap, which if managed properly will greatly reduce the need for
+ * the JVM to perform garbage collection.</p>
+ *
+ * @author Lee Rhodes
+ * @author Kevin Lang
+ */
+class DirectQuickSelectSketch extends DirectQuickSelectSketchR {
+
+ private DirectQuickSelectSketch(
+ final long seed,
+ final MemorySegment wseg) {
+ super(seed, wseg);
+ }
+
+ /**
+ * Construct a new sketch instance and initialize the given MemorySegment as its backing store.
+ *
+ * @param lgNomLongs <a href="{@docRoot}/resources/dictionary.html#lgNomLongs">See lgNomLongs</a>.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>.
+ * @param p
+ * <a href="{@docRoot}/resources/dictionary.html#p">See Sampling Probability, <i>p</i></a>
+ * @param rf Currently internally fixed at 2. Unless dstMem is not configured with a valid
+ * MemoryRequest, in which case the rf is effectively 1, which is no resizing at all and the
+ * dstMem must be large enough for a full sketch.
+ * <a href="{@docRoot}/resources/dictionary.html#resizeFactor">See Resize Factor</a>
+ * @param memReqSvr the given MemoryRequestServer
+ * @param dstSeg the given Memory object destination. It cannot be null.
+ * It will be cleared prior to use.
+ * @param unionGadget true if this sketch is implementing the Union gadget function.
+ * Otherwise, it is behaving as a normal QuickSelectSketch.
+ */
+ DirectQuickSelectSketch(
+ final int lgNomLongs,
+ final long seed,
+ final float p,
+ final ResizeFactor rf,
+ final MemorySegment dstSeg,
+ final boolean unionGadget) {
+ this(
+ checkMemSize(lgNomLongs, rf, dstSeg, unionGadget),
+ //SpotBugs CT_CONSTRUCTOR_THROW is false positive.
+ //this construction scheme is compliant with SEI CERT Oracle Coding Standard for Java / OBJ11-J
+ lgNomLongs,
+ seed,
+ p,
+ rf,
+ dstSeg,
+ unionGadget);
+ }
+
+ private DirectQuickSelectSketch(
+ final boolean secure, //required part of Finalizer Attack prevention
+ final int lgNomLongs,
+ final long seed,
+ final float p,
+ final ResizeFactor rf,
+ final MemorySegment dstSeg,
+ final boolean unionGadget) {
+ super(seed, dstSeg);
+ //Choose family, preambleLongs
+ final Family family;
+ final int preambleLongs;
+ if (unionGadget) {
+ preambleLongs = Family.UNION.getMinPreLongs();
+ family = Family.UNION;
+ }
+ else {
+ preambleLongs = Family.QUICKSELECT.getMinPreLongs();
+ family = Family.QUICKSELECT;
+ }
+
+ //Choose RF, minReqBytes, lgArrLongs.
+ final int lgRF = rf.lg();
+ final int lgArrLongs = (lgRF == 0) ? lgNomLongs + 1 : ThetaUtil.MIN_LG_ARR_LONGS;
+
+ //@formatter:off
+ //Build preamble
+ insertPreLongs(dstSeg, preambleLongs); //byte 0
+ insertLgResizeFactor(dstSeg, lgRF); //byte 0
+ insertSerVer(dstSeg, SER_VER); //byte 1
+ insertFamilyID(dstSeg, family.getID()); //byte 2
+ insertLgNomLongs(dstSeg, lgNomLongs); //byte 3
+ insertLgArrLongs(dstSeg, lgArrLongs); //byte 4
+ //flags: bigEndian = readOnly = compact = ordered = false; empty = true : 00100 = 4
+ insertFlags(dstSeg, EMPTY_FLAG_MASK); //byte 5
+ insertSeedHash(dstSeg, ThetaUtil.computeSeedHash(seed)); //bytes 6,7
+ insertCurCount(dstSeg, 0); //bytes 8-11
+ insertP(dstSeg, p); //bytes 12-15
+ final long thetaLong = (long)(p * LONG_MAX_VALUE_AS_DOUBLE);
+ insertThetaLong(dstSeg, thetaLong); //bytes 16-23
+ if (unionGadget) {
+ insertUnionThetaLong(dstSeg, thetaLong);
+ }
+ //@formatter:on
+
+ //clear hash table area
+ dstSeg.asSlice(preambleLongs << 3, Long.BYTES << lgArrLongs).fill((byte)0);
+
+ hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, lgArrLongs);
+ }
+
+ private static final boolean checkMemSize(
+ final int lgNomLongs, final ResizeFactor rf, final MemorySegment dstSeg, final boolean unionGadget) {
+ final int preambleLongs = (unionGadget) ? Family.UNION.getMinPreLongs() : Family.QUICKSELECT.getMinPreLongs();
+ final int lgRF = rf.lg();
+ final int lgArrLongs = (lgRF == 0) ? lgNomLongs + 1 : ThetaUtil.MIN_LG_ARR_LONGS;
+ final int minReqBytes = getMemBytes(lgArrLongs, preambleLongs);
+ final long curMemCapBytes = dstSeg.byteSize();
+ if (curMemCapBytes < minReqBytes) {
+ throw new SketchesArgumentException(
+ "Memory capacity is too small: " + curMemCapBytes + " < " + minReqBytes);
+ }
+ return true;
+ }
+
+ /**
+ * Wrap a sketch around the given source MemorySegment containing sketch data that originated from
+ * this sketch.
+ * @param srcSeg The given MemorySegment object must be in hash table form and not read only.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>
+ * @return instance of this sketch
+ */
+ static DirectQuickSelectSketch writableWrap(final MemorySegment srcSeg, final long seed) {
+ final int preambleLongs = extractPreLongs(srcSeg); //byte 0
+ final int lgNomLongs = extractLgNomLongs(srcSeg); //byte 3
+ final int lgArrLongs = extractLgArrLongs(srcSeg); //byte 4
+
+ UpdateSketch.checkUnionQuickSelectFamily(srcSeg, preambleLongs, lgNomLongs);
+ checkMemIntegrity(srcSeg, seed, preambleLongs, lgNomLongs, lgArrLongs);
+
+ if (isResizeFactorIncorrect(srcSeg, lgNomLongs, lgArrLongs)) {
+ //If incorrect it sets it to X2 which always works.
+ insertLgResizeFactor(srcSeg, ResizeFactor.X2.lg());
+ }
+
+ final DirectQuickSelectSketch dqss =
+ new DirectQuickSelectSketch(seed, srcSeg);
+ dqss.hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, lgArrLongs);
+ return dqss;
+ }
+
+ /**
+ * Fast-wrap a sketch around the given source MemorySegment containing sketch data that originated from
+ * this sketch. This does NO validity checking of the given Memory.
+ * @param srcSeg The given MemorySegment must be in hash table form and not read only.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>
+ * @return instance of this sketch
+ */
+ static DirectQuickSelectSketch fastWritableWrap(final MemorySegment srcSeg, final long seed) {
+ final int lgNomLongs = extractLgNomLongs(srcSeg); //byte 3
+ final int lgArrLongs = extractLgArrLongs(srcSeg); //byte 4
+
+ final DirectQuickSelectSketch dqss =
+ new DirectQuickSelectSketch(seed, srcSeg);
+ dqss.hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, lgArrLongs);
+ return dqss;
+ }
+
+ //Sketch
+
+ //UpdateSketch
+
+ @Override
+ public UpdateSketch rebuild() {
+ final int lgNomLongs = getLgNomLongs();
+ final int preambleLongs = wseg_.get(JAVA_BYTE, PREAMBLE_LONGS_BYTE) & 0X3F;
+ if (getRetainedEntries(true) > (1 << lgNomLongs)) {
+ quickSelectAndRebuild(wseg_, preambleLongs, lgNomLongs);
+ }
+ return this;
+ }
+
+ @Override
+ public void reset() {
+ //clear hash table
+ //hash table size and hashTableThreshold stays the same
+ //lgArrLongs stays the same
+ //thetaLongs resets to p
+ final int arrLongs = 1 << getLgArrLongs();
+ final int preambleLongs = wseg_.get(JAVA_BYTE, PREAMBLE_LONGS_BYTE) & 0X3F;
+ final int preBytes = preambleLongs << 3;
+ wseg_.asSlice(preBytes, arrLongs * 8L).fill((byte)0);
+ //flags: bigEndian = readOnly = compact = ordered = false; empty = true.
+ wseg_.set(JAVA_BYTE, FLAGS_BYTE, (byte) EMPTY_FLAG_MASK);
+ wseg_.set(JAVA_INT_UNALIGNED, RETAINED_ENTRIES_INT, 0);
+ final float p = wseg_.get(JAVA_FLOAT_UNALIGNED, P_FLOAT);
+ final long thetaLong = (long) (p * LONG_MAX_VALUE_AS_DOUBLE);
+ wseg_.set(JAVA_LONG_UNALIGNED, THETA_LONG, thetaLong);
+ }
+
+ //restricted methods
+
+ @Override
+ UpdateReturnState hashUpdate(final long hash) {
+ HashOperations.checkHashCorruption(hash);
+
+ wseg_.set(JAVA_BYTE, FLAGS_BYTE, (byte) (wseg_.get(JAVA_BYTE, FLAGS_BYTE) & ~EMPTY_FLAG_MASK));
+ final long thetaLong = getThetaLong();
+ final int lgNomLongs = getLgNomLongs();
+ //The over-theta test
+ if (HashOperations.continueCondition(thetaLong, hash)) {
+ return RejectedOverTheta; //signal that hash was rejected due to theta or zero.
+ }
+
+ final int lgArrLongs = getLgArrLongs();
+ final int preambleLongs = wseg_.get(JAVA_BYTE, PREAMBLE_LONGS_BYTE) & 0X3F;
+
+ //The duplicate test
+ final int index =
+ HashOperations.hashSearchOrInsertMemory(wseg_, lgArrLongs, hash, preambleLongs << 3);
+ if (index >= 0) {
+ return RejectedDuplicate; //Duplicate, not inserted
+ }
+ //insertion occurred, increment curCount
+ final int curCount = getRetainedEntries(true) + 1;
+ wseg_.set(JAVA_INT_UNALIGNED, RETAINED_ENTRIES_INT, curCount); //update curCount
+
+ if (isOutOfSpace(curCount)) { //we need to do something, we are out of space
+
+ if (lgArrLongs > lgNomLongs) { //at full size, rebuild
+ //Assumes no dirty values, changes thetaLong, curCount_
+ assert (lgArrLongs == (lgNomLongs + 1)) : "lgArr: " + lgArrLongs + ", lgNom: " + lgNomLongs;
+ //rebuild, refresh curCount based on # values in the hashtable.
+ quickSelectAndRebuild(wseg_, preambleLongs, lgNomLongs);
+ return InsertedCountIncrementedRebuilt;
+ } //end of rebuild, exit
+
+ else { //Not at full size, resize. Should not get here if lgRF = 0 and memCap is too small.
+ final int lgRF = getLgRF();
+ final int actLgRF = actLgResizeFactor(wseg_.byteSize(), lgArrLongs, preambleLongs, lgRF);
+ int tgtLgArrLongs = Math.min(lgArrLongs + actLgRF, lgNomLongs + 1);
+
+ if (actLgRF > 0) { //Expand in current Memory
+ //lgArrLongs will change; thetaLong, curCount will not
+ resize(wseg_, preambleLongs, lgArrLongs, tgtLgArrLongs);
+ hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, tgtLgArrLongs);
+ return InsertedCountIncrementedResized;
+ } //end of Expand in current memory, exit.
+
+ else {
+ //Request more memory, then resize. lgArrLongs will change; thetaLong, curCount will not
+ final int preBytes = preambleLongs << 3;
+ tgtLgArrLongs = Math.min(lgArrLongs + lgRF, lgNomLongs + 1);
+ final int tgtArrBytes = 8 << tgtLgArrLongs;
+ final int reqBytes = tgtArrBytes + preBytes;
+
+ //memReqSvr_ = (memReqSvr_ == null) ? wseg_.getMemoryRequestServer() : memReqSvr_;
+ //if (memReqSvr_ == null) { //in case the MRS is not enabled or null.
+ // throw new SketchesArgumentException("Out of Memory, MemoryRequestServer is null, cannot expand.");
+ //}
+ //final MemorySegment newDstSeg = memReqSvr_.request(wseg_, reqBytes);
+
+ final MemorySegment newDstSeg = newHeapSegment(reqBytes);
+
+ moveAndResize(wseg_, preambleLongs, lgArrLongs, newDstSeg, tgtLgArrLongs, thetaLong);
+ wseg_ = newDstSeg;
+
+ hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, tgtLgArrLongs);
+ return InsertedCountIncrementedResized;
+ } //end of Request more memory to resize
+ } //end of resize
+ } //end of isOutOfSpace
+ return InsertedCountIncremented;
+ }
+
+}
diff --git a/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketchR.java b/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketchR.java
new file mode 100644
index 00000000..33d37155
--- /dev/null
+++ b/src/main/java/org/apache/datasketches/theta2/DirectQuickSelectSketchR.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.datasketches.theta2;
+
+import static java.lang.foreign.ValueLayout.JAVA_BYTE;
+import static java.lang.foreign.ValueLayout.JAVA_FLOAT_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED;
+import static java.lang.foreign.ValueLayout.JAVA_LONG_UNALIGNED;
+import static org.apache.datasketches.theta2.CompactOperations.checkIllegalCurCountAndEmpty;
+import static org.apache.datasketches.theta2.CompactOperations.computeCompactPreLongs;
+import static org.apache.datasketches.theta2.CompactOperations.correctThetaOnCompact;
+import static org.apache.datasketches.theta2.PreambleUtil.FAMILY_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.LG_ARR_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.LG_NOM_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.LG_RESIZE_FACTOR_BIT;
+import static org.apache.datasketches.theta2.PreambleUtil.PREAMBLE_LONGS_BYTE;
+import static org.apache.datasketches.theta2.PreambleUtil.P_FLOAT;
+import static org.apache.datasketches.theta2.PreambleUtil.RETAINED_ENTRIES_INT;
+import static org.apache.datasketches.theta2.PreambleUtil.THETA_LONG;
+import static org.apache.datasketches.theta2.PreambleUtil.extractCurCount;
+import static org.apache.datasketches.theta2.PreambleUtil.extractLgArrLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractLgNomLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractPreLongs;
+import static org.apache.datasketches.theta2.PreambleUtil.extractThetaLong;
+import static org.apache.datasketches.theta2.PreambleUtil.insertThetaLong;
+
+import java.lang.foreign.MemorySegment;
+
+import org.apache.datasketches.common.Family;
+import org.apache.datasketches.common.ResizeFactor;
+import org.apache.datasketches.common.SketchesReadOnlyException;
+import org.apache.datasketches.common.SuppressFBWarnings;
+import org.apache.datasketches.thetacommon.ThetaUtil;
+
+/**
+ * The default Theta Sketch using the QuickSelect algorithm.
+ * This is the read-only implementation with non-functional methods, which affect the state.
+ *
+ * <p>This implementation uses data in a given Memory that is owned and managed by the caller.
+ * This Memory can be off-heap, which if managed properly will greatly reduce the need for
+ * the JVM to perform garbage collection.</p>
+ *
+ * @author Lee Rhodes
+ * @author Kevin Lang
+ */
+class DirectQuickSelectSketchR extends UpdateSketch {
+ static final double DQS_RESIZE_THRESHOLD = 15.0 / 16.0; //tuned for space
+ final long seed_; //provided, kept only on heap, never serialized.
+ int hashTableThreshold_; //computed, kept only on heap, never serialized.
+ MemorySegment wseg_; //A WritableMemory for child class, but no write methods here
+
+ //only called by DirectQuickSelectSketch and below
+ DirectQuickSelectSketchR(final long seed, final MemorySegment wseg) {
+ seed_ = seed;
+ wseg_ = wseg;
+ }
+
+ /**
+ * Wrap a sketch around the given source MemorySegment containing sketch data that originated from
+ * this sketch.
+ * @param srcSeg the source MemorySegment.
+ * The given MemorySegment object must be in hash table form and not read only.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>
+ * @return instance of this sketch
+ */
+ static DirectQuickSelectSketchR readOnlyWrap(final MemorySegment srcSeg, final long seed) {
+ final int preambleLongs = extractPreLongs(srcSeg); //byte 0
+ final int lgNomLongs = extractLgNomLongs(srcSeg); //byte 3
+ final int lgArrLongs = extractLgArrLongs(srcSeg); //byte 4
+
+ UpdateSketch.checkUnionQuickSelectFamily(srcSeg, preambleLongs, lgNomLongs);
+ checkMemIntegrity(srcSeg, seed, preambleLongs, lgNomLongs, lgArrLongs);
+
+ final DirectQuickSelectSketchR dqssr =
+ new DirectQuickSelectSketchR(seed, srcSeg);
+ dqssr.hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, lgArrLongs);
+ return dqssr;
+ }
+
+ /**
+ * Fast-wrap a sketch around the given source MemorySegment containing sketch data that originated from
+ * this sketch. This does NO validity checking of the given MemorySegment.
+ * @param srcSeg The given MemorySegment object must be in hash table form and not read only.
+ * @param seed <a href="{@docRoot}/resources/dictionary.html#seed">See Update Hash Seed</a>
+ * @return instance of this sketch
+ */
+ static DirectQuickSelectSketchR fastReadOnlyWrap(final MemorySegment srcSeg, final long seed) {
+ final int lgNomLongs = srcSeg.get(JAVA_BYTE, LG_NOM_LONGS_BYTE) & 0XFF;
+ final int lgArrLongs = srcSeg.get(JAVA_BYTE, LG_ARR_LONGS_BYTE) & 0XFF;
+
+ final DirectQuickSelectSketchR dqss =
+ new DirectQuickSelectSketchR(seed, srcSeg);
+ dqss.hashTableThreshold_ = getOffHeapHashTableThreshold(lgNomLongs, lgArrLongs);
+ return dqss;
+ }
+
+ //Sketch
+
+ @Override
+ public int getCurrentBytes() {
+ //not compact
+ final byte lgArrLongs = wseg_.get(JAVA_BYTE, LG_ARR_LONGS_BYTE);
+ final int preLongs = wseg_.get(JAVA_BYTE, PREAMBLE_LONGS_BYTE) & 0X3F;
+ final int lengthBytes = (preLongs + (1 << lgArrLongs)) << 3;
+ return lengthBytes;
+ }
+
+ @Override
+ public double getEstimate() {
+ final int curCount = extractCurCount(wseg_);
+ final long thetaLong = extractThetaLong(wseg_);
+ return Sketch.estimate(thetaLong, curCount);
+ }
+
+ @Override
+ public Family getFamily() {
+ final int familyID = wseg_.get(JAVA_BYTE, FAMILY_BYTE) & 0XFF;
+ return Family.idToFamily(familyID);
+ }
+
+ @Override
+ public int getRetainedEntries(final boolean valid) { //always valid
+ return wseg_.get(JAVA_INT_UNALIGNED, RETAINED_ENTRIES_INT);
+ }
+
+ @Override
+ public long getThetaLong() {
+ return isEmpty() ? Long.MAX_VALUE : wseg_.get(JAVA_LONG_UNALIGNED, THETA_LONG);
+ }
+
+ @Override
+ public boolean hasMemorySegment() {
+ return wseg_ != null;
+ }
+
+ @Override
+ public boolean isDirect() {
+ return hasMemorySegment() ? wseg_.isNative() : false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return PreambleUtil.isEmptyFlag(wseg_);
+ }
+
+ @Override
+ public HashIterator iterator() {
+ return new MemoryHashIterator(wseg_, 1 << getLgArrLongs(), getThetaLong());
+ }
+
+ @Override
+ public byte[] toByteArray() { //MY_FAMILY is stored in wmem_
+ checkIllegalCurCountAndEmpty(isEmpty(), extractCurCount(wseg_));
... 7304 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org