package org.apache.lucene.util.packed; /* * 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. */ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.LongBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Random; import org.apache.lucene.codecs.CodecUtil; import org.apache.lucene.store.Directory; import org.apache.lucene.store.IOContext; import org.apache.lucene.store.IndexInput; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.LongsRef; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase.Slow; import org.apache.lucene.util._TestUtil; import org.apache.lucene.util.packed.PackedInts.Reader; @Slow public class TestPackedInts extends LuceneTestCase { public void testBitsRequired() { assertEquals(61, PackedInts.bitsRequired((long)Math.pow(2, 61)-1)); assertEquals(61, PackedInts.bitsRequired(0x1FFFFFFFFFFFFFFFL)); assertEquals(62, PackedInts.bitsRequired(0x3FFFFFFFFFFFFFFFL)); assertEquals(63, PackedInts.bitsRequired(0x7FFFFFFFFFFFFFFFL)); } public void testMaxValues() { assertEquals("1 bit -> max == 1", 1, PackedInts.maxValue(1)); assertEquals("2 bit -> max == 3", 3, PackedInts.maxValue(2)); assertEquals("8 bit -> max == 255", 255, PackedInts.maxValue(8)); assertEquals("63 bit -> max == Long.MAX_VALUE", Long.MAX_VALUE, PackedInts.maxValue(63)); assertEquals("64 bit -> max == Long.MAX_VALUE (same as for 63 bit)", Long.MAX_VALUE, PackedInts.maxValue(64)); } public void testPackedInts() throws IOException { int num = atLeast(3); for (int iter = 0; iter < num; iter++) { for(int nbits=1;nbits<=64;nbits++) { final long maxValue = PackedInts.maxValue(nbits); final int valueCount = _TestUtil.nextInt(random(), 1, 600); final int bufferSize = random().nextBoolean() ? _TestUtil.nextInt(random(), 0, 48) : _TestUtil.nextInt(random(), 0, 4096); final Directory d = newDirectory(); IndexOutput out = d.createOutput("out.bin", newIOContext(random())); PackedInts.Writer w = PackedInts.getWriter( out, valueCount, nbits, random().nextFloat()); final long startFp = out.getFilePointer(); final int actualValueCount = random().nextBoolean() ? valueCount : _TestUtil.nextInt(random(), 0, valueCount); final long[] values = new long[valueCount]; for(int i=0;i<actualValueCount;i++) { values[i] = _TestUtil.nextLong(random(), 0, maxValue); w.add(values[i]); } w.finish(); final long fp = out.getFilePointer(); out.close(); // packed writers should only write longs assertEquals(0, (fp - startFp) % 8); // ensure that finish() added the (valueCount-actualValueCount) missing values final long bytes; switch (w.getFormat()) { case PACKED: bytes = (long) Math.ceil((double) valueCount * w.bitsPerValue / 64) << 3; break; case PACKED_SINGLE_BLOCK: final int valuesPerBlock = 64 / w.bitsPerValue; bytes = (long) Math.ceil((double) valueCount / valuesPerBlock) << 3; break; default: bytes = -1; } assertEquals(bytes, fp - startFp); {// test header IndexInput in = d.openInput("out.bin", newIOContext(random())); // header = codec header | bitsPerValue | valueCount | format CodecUtil.checkHeader(in, PackedInts.CODEC_NAME, PackedInts.VERSION_START, PackedInts.VERSION_CURRENT); // codec header assertEquals(w.bitsPerValue, in.readVInt()); assertEquals(valueCount, in.readVInt()); assertEquals(w.getFormat().getId(), in.readVInt()); assertEquals(startFp, in.getFilePointer()); in.close(); } {// test reader IndexInput in = d.openInput("out.bin", newIOContext(random())); PackedInts.Reader r = PackedInts.getReader(in); assertEquals(fp, in.getFilePointer()); for(int i=0;i<valueCount;i++) { assertEquals("index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.getClass().getSimpleName(), values[i], r.get(i)); } in.close(); } { // test reader iterator next IndexInput in = d.openInput("out.bin", newIOContext(random())); PackedInts.ReaderIterator r = PackedInts.getReaderIterator(in, bufferSize); for(int i=0;i<valueCount;i++) { assertEquals("index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.getClass().getSimpleName(), values[i], r.next()); assertEquals(i, r.ord()); } assertEquals(fp, in.getFilePointer()); in.close(); } { // test reader iterator bulk next IndexInput in = d.openInput("out.bin", newIOContext(random())); PackedInts.ReaderIterator r = PackedInts.getReaderIterator(in, bufferSize); int i = 0; while (i < valueCount) { final int count = _TestUtil.nextInt(random(), 1, 95); final LongsRef next = r.next(count); for (int k = 0; k < next.length; ++k) { assertEquals("index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + r.getClass().getSimpleName(), values[i + k], next.longs[next.offset + k]); } i += next.length; } assertEquals(fp, in.getFilePointer()); in.close(); } { // test direct reader get IndexInput in = d.openInput("out.bin", newIOContext(random())); PackedInts.Reader intsEnum = PackedInts.getDirectReader(in); for (int i = 0; i < valueCount; i++) { final String msg = "index=" + i + " valueCount=" + valueCount + " nbits=" + nbits + " for " + intsEnum.getClass().getSimpleName(); final int index = random().nextInt(valueCount); long value = intsEnum.get(index); assertEquals(msg, value, values[index]); } in.close(); } d.close(); } } } public void testControlledEquality() { final int VALUE_COUNT = 255; final int BITS_PER_VALUE = 8; List<PackedInts.Mutable> packedInts = createPackedInts(VALUE_COUNT, BITS_PER_VALUE); for (PackedInts.Mutable packedInt: packedInts) { for (int i = 0 ; i < packedInt.size() ; i++) { packedInt.set(i, i+1); } } assertListEquality(packedInts); } public void testRandomBulkCopy() { final int numIters = atLeast(3); for(int iter=0;iter<numIters;iter++) { if (VERBOSE) { System.out.println("\nTEST: iter=" + iter); } final int valueCount = atLeast(100000); int bits1 = _TestUtil.nextInt(random(), 1, 64); int bits2 = _TestUtil.nextInt(random(), 1, 64); if (bits1 > bits2) { int tmp = bits1; bits1 = bits2; bits2 = tmp; } if (VERBOSE) { System.out.println(" valueCount=" + valueCount + " bits1=" + bits1 + " bits2=" + bits2); } final PackedInts.Mutable packed1 = PackedInts.getMutable(valueCount, bits1, PackedInts.COMPACT); final PackedInts.Mutable packed2 = PackedInts.getMutable(valueCount, bits2, PackedInts.COMPACT); final long maxValue = PackedInts.maxValue(bits1); for(int i=0;i<valueCount;i++) { final long val = _TestUtil.nextLong(random(), 0, maxValue); packed1.set(i, val); packed2.set(i, val); } final long[] buffer = new long[valueCount]; // Copy random slice over, 20 times: for(int iter2=0;iter2<20;iter2++) { int start = random().nextInt(valueCount-1); int len = _TestUtil.nextInt(random(), 1, valueCount-start); int offset; if (VERBOSE) { System.out.println(" copy " + len + " values @ " + start); } if (len == valueCount) { offset = 0; } else { offset = random().nextInt(valueCount - len); } if (random().nextBoolean()) { int got = packed1.get(start, buffer, offset, len); assertTrue(got <= len); int sot = packed2.set(start, buffer, offset, got); assertTrue(sot <= got); } else { PackedInts.copy(packed1, offset, packed2, offset, len, random().nextInt(10 * len)); } /* for(int i=0;i<valueCount;i++) { assertEquals("value " + i, packed1.get(i), packed2.get(i)); } */ } for(int i=0;i<valueCount;i++) { assertEquals("value " + i, packed1.get(i), packed2.get(i)); } } } public void testRandomEquality() { final int numIters = atLeast(2); for (int i = 0; i < numIters; ++i) { final int valueCount = _TestUtil.nextInt(random(), 1, 300); for (int bitsPerValue = 1 ; bitsPerValue <= 64 ; bitsPerValue++) { assertRandomEquality(valueCount, bitsPerValue, random().nextLong()); } } } private static void assertRandomEquality(int valueCount, int bitsPerValue, long randomSeed) { List<PackedInts.Mutable> packedInts = createPackedInts(valueCount, bitsPerValue); for (PackedInts.Mutable packedInt: packedInts) { try { fill(packedInt, PackedInts.maxValue(bitsPerValue), randomSeed); } catch (Exception e) { e.printStackTrace(System.err); fail(String.format(Locale.ROOT, "Exception while filling %s: valueCount=%d, bitsPerValue=%s", packedInt.getClass().getSimpleName(), valueCount, bitsPerValue)); } } assertListEquality(packedInts); } private static List<PackedInts.Mutable> createPackedInts( int valueCount, int bitsPerValue) { List<PackedInts.Mutable> packedInts = new ArrayList<PackedInts.Mutable>(); if (bitsPerValue <= 8) { packedInts.add(new Direct8(valueCount)); } if (bitsPerValue <= 16) { packedInts.add(new Direct16(valueCount)); } if (bitsPerValue <= 24 && valueCount <= Packed8ThreeBlocks.MAX_SIZE) { packedInts.add(new Packed8ThreeBlocks(valueCount)); } if (bitsPerValue <= 32) { packedInts.add(new Direct32(valueCount)); } if (bitsPerValue <= 48 && valueCount <= Packed16ThreeBlocks.MAX_SIZE) { packedInts.add(new Packed16ThreeBlocks(valueCount)); } if (bitsPerValue <= 63) { packedInts.add(new Packed64(valueCount, bitsPerValue)); } packedInts.add(new Direct64(valueCount)); for (int bpv = bitsPerValue; bpv <= Packed64SingleBlock.MAX_SUPPORTED_BITS_PER_VALUE; ++bpv) { if (Packed64SingleBlock.isSupported(bpv)) { packedInts.add(Packed64SingleBlock.create(valueCount, bpv)); } } return packedInts; } private static void fill(PackedInts.Mutable packedInt, long maxValue, long randomSeed) { Random rnd2 = new Random(randomSeed); for (int i = 0 ; i < packedInt.size() ; i++) { long value = _TestUtil.nextLong(rnd2, 0, maxValue); packedInt.set(i, value); assertEquals(String.format(Locale.ROOT, "The set/get of the value at index %d should match for %s", i, packedInt.getClass().getSimpleName()), value, packedInt.get(i)); } } private static void assertListEquality( List<? extends PackedInts.Reader> packedInts) { assertListEquality("", packedInts); } private static void assertListEquality( String message, List<? extends PackedInts.Reader> packedInts) { if (packedInts.size() == 0) { return; } PackedInts.Reader base = packedInts.get(0); int valueCount = base.size(); for (PackedInts.Reader packedInt: packedInts) { assertEquals(message + ". The number of values should be the same ", valueCount, packedInt.size()); } for (int i = 0 ; i < valueCount ; i++) { for (int j = 1 ; j < packedInts.size() ; j++) { assertEquals(String.format(Locale.ROOT, "%s. The value at index %d should be the same for %s and %s", message, i, base.getClass().getSimpleName(), packedInts.get(j).getClass().getSimpleName()), base.get(i), packedInts.get(j).get(i)); } } } public void testSingleValue() throws Exception { for (int bitsPerValue = 1; bitsPerValue <= 64; ++bitsPerValue) { Directory dir = newDirectory(); IndexOutput out = dir.createOutput("out", newIOContext(random())); PackedInts.Writer w = PackedInts.getWriter(out, 1, bitsPerValue, PackedInts.DEFAULT); long value = 17L & PackedInts.maxValue(bitsPerValue); w.add(value); w.finish(); final long end = out.getFilePointer(); out.close(); IndexInput in = dir.openInput("out", newIOContext(random())); Reader reader = PackedInts.getReader(in); String msg = "Impl=" + w.getClass().getSimpleName() + ", bitsPerValue=" + bitsPerValue; assertEquals(msg, 1, reader.size()); assertEquals(msg, value, reader.get(0)); assertEquals(msg, end, in.getFilePointer()); in.close(); dir.close(); } } public void testSecondaryBlockChange() { PackedInts.Mutable mutable = new Packed64(26, 5); mutable.set(24, 31); assertEquals("The value #24 should be correct", 31, mutable.get(24)); mutable.set(4, 16); assertEquals("The value #24 should remain unchanged", 31, mutable.get(24)); } /* Check if the structures properly handle the case where index * bitsPerValue > Integer.MAX_VALUE NOTE: this test allocates 256 MB */ public void testIntOverflow() { int INDEX = (int)Math.pow(2, 30)+1; int BITS = 2; Packed64 p64 = null; try { p64 = new Packed64(INDEX, BITS); } catch (OutOfMemoryError oome) { // This can easily happen: we're allocating a // long[] that needs 256-273 MB. Heap is 512 MB, // but not all of that is available for large // objects ... empirical testing shows we only // have ~ 67 MB free. } if (p64 != null) { p64.set(INDEX-1, 1); assertEquals("The value at position " + (INDEX-1) + " should be correct for Packed64", 1, p64.get(INDEX-1)); p64 = null; } Packed64SingleBlock p64sb = null; try { p64sb = Packed64SingleBlock.create(INDEX, BITS); } catch (OutOfMemoryError oome) { // Ignore: see comment above } if (p64sb != null) { p64sb.set(INDEX - 1, 1); assertEquals("The value at position " + (INDEX-1) + " should be correct for " + p64sb.getClass().getSimpleName(), 1, p64sb.get(INDEX-1)); } int index = Integer.MAX_VALUE / 24 + 1; Packed8ThreeBlocks p8 = null; try { p8 = new Packed8ThreeBlocks(index); } catch (OutOfMemoryError oome) { // Ignore: see comment above } if (p8 != null) { p8.set(index - 1, 1); assertEquals("The value at position " + (index-1) + " should be correct for Packed8ThreeBlocks", 1, p8.get(index-1)); p8 = null; } index = Integer.MAX_VALUE / 48 + 1; Packed16ThreeBlocks p16 = null; try { p16 = new Packed16ThreeBlocks(index); } catch (OutOfMemoryError oome) { // Ignore: see comment above } if (p16 != null) { p16.set(index - 1, 1); assertEquals("The value at position " + (index-1) + " should be correct for Packed16ThreeBlocks", 1, p16.get(index-1)); p16 = null; } } public void testFill() { final int valueCount = 1111; final int from = random().nextInt(valueCount + 1); final int to = from + random().nextInt(valueCount + 1 - from); for (int bpv = 1; bpv <= 64; ++bpv) { final long val = _TestUtil.nextLong(random(), 0, PackedInts.maxValue(bpv)); List<PackedInts.Mutable> packedInts = createPackedInts(valueCount, bpv); for (PackedInts.Mutable ints : packedInts) { String msg = ints.getClass().getSimpleName() + " bpv=" + bpv + ", from=" + from + ", to=" + to + ", val=" + val; ints.fill(0, ints.size(), 1); ints.fill(from, to, val); for (int i = 0; i < ints.size(); ++i) { if (i >= from && i < to) { assertEquals(msg + ", i=" + i, val, ints.get(i)); } else { assertEquals(msg + ", i=" + i, 1, ints.get(i)); } } } } } public void testBulkGet() { final int valueCount = 1111; final int index = random().nextInt(valueCount); final int len = _TestUtil.nextInt(random(), 1, valueCount * 2); final int off = random().nextInt(77); for (int bpv = 1; bpv <= 64; ++bpv) { long mask = PackedInts.maxValue(bpv); List<PackedInts.Mutable> packedInts = createPackedInts(valueCount, bpv); for (PackedInts.Mutable ints : packedInts) { for (int i = 0; i < ints.size(); ++i) { ints.set(i, (31L * i - 1099) & mask); } long[] arr = new long[off+len]; String msg = ints.getClass().getSimpleName() + " valueCount=" + valueCount + ", index=" + index + ", len=" + len + ", off=" + off; final int gets = ints.get(index, arr, off, len); assertTrue(msg, gets > 0); assertTrue(msg, gets <= len); assertTrue(msg, gets <= ints.size() - index); for (int i = 0; i < arr.length; ++i) { String m = msg + ", i=" + i; if (i >= off && i < off + gets) { assertEquals(m, ints.get(i - off + index), arr[i]); } else { assertEquals(m, 0, arr[i]); } } } } } public void testBulkSet() { final int valueCount = 1111; final int index = random().nextInt(valueCount); final int len = _TestUtil.nextInt(random(), 1, valueCount * 2); final int off = random().nextInt(77); long[] arr = new long[off+len]; for (int bpv = 1; bpv <= 64; ++bpv) { long mask = PackedInts.maxValue(bpv); List<PackedInts.Mutable> packedInts = createPackedInts(valueCount, bpv); for (int i = 0; i < arr.length; ++i) { arr[i] = (31L * i + 19) & mask; } for (PackedInts.Mutable ints : packedInts) { String msg = ints.getClass().getSimpleName() + " valueCount=" + valueCount + ", index=" + index + ", len=" + len + ", off=" + off; final int sets = ints.set(index, arr, off, len); assertTrue(msg, sets > 0); assertTrue(msg, sets <= len); for (int i = 0; i < ints.size(); ++i) { String m = msg + ", i=" + i; if (i >= index && i < index + sets) { assertEquals(m, arr[off - index + i], ints.get(i)); } else { assertEquals(m, 0, ints.get(i)); } } } } } public void testCopy() { final int valueCount = _TestUtil.nextInt(random(), 5, 600); final int off1 = random().nextInt(valueCount); final int off2 = random().nextInt(valueCount); final int len = random().nextInt(Math.min(valueCount - off1, valueCount - off2)); final int mem = random().nextInt(1024); for (int bpv = 1; bpv <= 64; ++bpv) { long mask = PackedInts.maxValue(bpv); for (PackedInts.Mutable r1 : createPackedInts(valueCount, bpv)) { for (int i = 0; i < r1.size(); ++i) { r1.set(i, (31L * i - 1023) & mask); } for (PackedInts.Mutable r2 : createPackedInts(valueCount, bpv)) { String msg = "src=" + r1 + ", dest=" + r2 + ", srcPos=" + off1 + ", destPos=" + off2 + ", len=" + len + ", mem=" + mem; PackedInts.copy(r1, off1, r2, off2, len, mem); for (int i = 0; i < r2.size(); ++i) { String m = msg + ", i=" + i; if (i >= off2 && i < off2 + len) { assertEquals(m, r1.get(i - off2 + off1), r2.get(i)); } else { assertEquals(m, 0, r2.get(i)); } } } } } } public void testGrowableWriter() { final int valueCount = 113 + random().nextInt(1111); GrowableWriter wrt = new GrowableWriter(1, valueCount, PackedInts.DEFAULT); wrt.set(4, 2); wrt.set(7, 10); wrt.set(valueCount - 10, 99); wrt.set(99, 999); wrt.set(valueCount - 1, 1 << 10); assertEquals(1 << 10, wrt.get(valueCount - 1)); wrt.set(99, (1 << 23) - 1); assertEquals(1 << 10, wrt.get(valueCount - 1)); wrt.set(1, Long.MAX_VALUE); assertEquals(1 << 10, wrt.get(valueCount - 1)); assertEquals(Long.MAX_VALUE, wrt.get(1)); assertEquals(2, wrt.get(4)); assertEquals((1 << 23) - 1, wrt.get(99)); assertEquals(10, wrt.get(7)); assertEquals(99, wrt.get(valueCount - 10)); assertEquals(1 << 10, wrt.get(valueCount - 1)); } public void testSave() throws IOException { final int valueCount = _TestUtil.nextInt(random(), 1, 2048); for (int bpv = 1; bpv <= 64; ++bpv) { final int maxValue = (int) Math.min(PackedInts.maxValue(31), PackedInts.maxValue(bpv)); final RAMDirectory directory = new RAMDirectory(); List<PackedInts.Mutable> packedInts = createPackedInts(valueCount, bpv); for (PackedInts.Mutable mutable : packedInts) { for (int i = 0; i < mutable.size(); ++i) { mutable.set(i, random().nextInt(maxValue)); } IndexOutput out = directory.createOutput("packed-ints.bin", IOContext.DEFAULT); mutable.save(out); out.close(); IndexInput in = directory.openInput("packed-ints.bin", IOContext.DEFAULT); PackedInts.Reader reader = PackedInts.getReader(in); assertEquals(mutable.getBitsPerValue(), reader.getBitsPerValue()); assertEquals(valueCount, reader.size()); if (mutable instanceof Packed64SingleBlock) { // make sure that we used the right format so that the reader has // the same performance characteristics as the mutable that has been // serialized assertTrue(reader instanceof Packed64SingleBlock); } else { assertFalse(reader instanceof Packed64SingleBlock); } for (int i = 0; i < valueCount; ++i) { assertEquals(mutable.get(i), reader.get(i)); } in.close(); directory.deleteFile("packed-ints.bin"); } } } public void testEncodeDecode() { for (PackedInts.Format format : PackedInts.Format.values()) { for (int bpv = 1; bpv <= 64; ++bpv) { if (!format.isSupported(bpv)) { continue; } String msg = format + " " + bpv; final PackedInts.Encoder encoder = PackedInts.getEncoder(format, PackedInts.VERSION_CURRENT, bpv); final PackedInts.Decoder decoder = PackedInts.getDecoder(format, PackedInts.VERSION_CURRENT, bpv); final int blockCount = encoder.blockCount(); final int valueCount = encoder.valueCount(); assertEquals(blockCount, decoder.blockCount()); assertEquals(valueCount, decoder.valueCount()); final int iterations = random().nextInt(100); final int blocksOffset = random().nextInt(100); final int valuesOffset = random().nextInt(100); final int blocksOffset2 = random().nextInt(100); final int blocksLen = iterations * blockCount; // 1. generate random inputs final long[] blocks = new long[blocksOffset + blocksLen]; for (int i = 0; i < blocks.length; ++i) { blocks[i] = random().nextLong(); if (format == PackedInts.Format.PACKED_SINGLE_BLOCK && 64 % bpv != 0) { // clear highest bits for packed final int toClear = 64 % bpv; blocks[i] = (blocks[i] << toClear) >>> toClear; } } // 2. decode final long[] values = new long[valuesOffset + iterations * valueCount]; decoder.decode(blocks, blocksOffset, values, valuesOffset, iterations); for (long value : values) { assertTrue(value <= PackedInts.maxValue(bpv)); } // test decoding to int[] final int[] intValues; if (bpv <= 32) { intValues = new int[values.length]; decoder.decode(blocks, blocksOffset, intValues, valuesOffset, iterations); assertTrue(equals(intValues, values)); } else { intValues = null; } // 3. re-encode final long[] blocks2 = new long[blocksOffset2 + blocksLen]; encoder.encode(values, valuesOffset, blocks2, blocksOffset2, iterations); assertArrayEquals(msg, Arrays.copyOfRange(blocks, blocksOffset, blocks.length), Arrays.copyOfRange(blocks2, blocksOffset2, blocks2.length)); // test encoding from int[] if (bpv <= 32) { final long[] blocks3 = new long[blocks2.length]; encoder.encode(intValues, valuesOffset, blocks3, blocksOffset2, iterations); assertArrayEquals(msg, blocks2, blocks3); } // 4. byte[] decoding final byte[] byteBlocks = new byte[8 * blocks.length]; ByteBuffer.wrap(byteBlocks).asLongBuffer().put(blocks); final long[] values2 = new long[valuesOffset + iterations * valueCount]; decoder.decode(byteBlocks, blocksOffset * 8, values2, valuesOffset, iterations); for (long value : values2) { assertTrue(msg, value <= PackedInts.maxValue(bpv)); } assertArrayEquals(msg, values, values2); // test decoding to int[] if (bpv <= 32) { final int[] intValues2 = new int[values2.length]; decoder.decode(byteBlocks, blocksOffset * 8, intValues2, valuesOffset, iterations); assertTrue(msg, equals(intValues2, values2)); } // 5. byte[] encoding final byte[] blocks3 = new byte[8 * (blocksOffset2 + blocksLen)]; encoder.encode(values, valuesOffset, blocks3, 8 * blocksOffset2, iterations); assertEquals(msg, LongBuffer.wrap(blocks2), ByteBuffer.wrap(blocks3).asLongBuffer()); // test encoding from int[] if (bpv <= 32) { final byte[] blocks4 = new byte[blocks3.length]; encoder.encode(intValues, valuesOffset, blocks4, 8 * blocksOffset2, iterations); assertArrayEquals(msg, blocks3, blocks4); } } } } private static boolean equals(int[] ints, long[] longs) { if (ints.length != longs.length) { return false; } for (int i = 0; i < ints.length; ++i) { if ((ints[i] & 0xFFFFFFFFL) != longs[i]) { return false; } } return true; } }