From 40e2c33e48ee810c8062a779915c7c79b3ef9685 Mon Sep 17 00:00:00 2001 From: Raunaq Morarka Date: Mon, 22 Jun 2026 11:53:39 +0530 Subject: [PATCH 1/5] Fix VectorFastPFOR corruption on reused output buffers slowpack OR-accumulates into the output, so a reused buffer kept stale bits. Zero the target words first. --- pom.xml | 12 +++++ .../vector/VectorBitPacker.java | 6 +++ .../vector/VectorFastPFORTest.java | 49 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/test/java/me/lemire/integercompression/vector/VectorFastPFORTest.java diff --git a/pom.xml b/pom.xml index 180a49d..ccdc909 100644 --- a/pom.xml +++ b/pom.xml @@ -105,6 +105,18 @@ + + default-testCompile + test-compile + + testCompile + + + + me/lemire/integercompression/vector/* + + + - - org.apache.felix diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index f134601..4d652dd 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,11 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 module me.lemire.integercompression { - // This is currently only for advanced users: - // requires jdk.incubator.vector; + // Optional at runtime: only consumers of the vector package (VectorFastPFOR) + // need jdk.incubator.vector resolved (e.g. --add-modules jdk.incubator.vector). + // Scalar consumers resolve without it. + requires static jdk.incubator.vector; exports me.lemire.integercompression; exports me.lemire.longcompression; exports me.lemire.longcompression.differential; exports me.lemire.integercompression.differential; - // exports me.lemire.integercompression.vector; + exports me.lemire.integercompression.vector; } From 9093b1ad4e3a526a333825b2de1392f064251227 Mon Sep 17 00:00:00 2001 From: Raunaq Morarka Date: Fri, 19 Jun 2026 22:58:51 +0530 Subject: [PATCH 5/5] Cover VectorFastPFOR with the shared codec test suites SkippableBasicTest exercises maxHeadlessCompressedLength, so implement it (mirroring FastPFOR) rather than throwing. --- .../lemire/integercompression/vector/VectorFastPFOR.java | 8 +++++++- src/test/java/me/lemire/integercompression/BasicTest.java | 2 ++ .../me/lemire/integercompression/SkippableBasicTest.java | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/lemire/integercompression/vector/VectorFastPFOR.java b/src/main/java/me/lemire/integercompression/vector/VectorFastPFOR.java index adbe432..cc755c8 100644 --- a/src/main/java/me/lemire/integercompression/vector/VectorFastPFOR.java +++ b/src/main/java/me/lemire/integercompression/vector/VectorFastPFOR.java @@ -54,6 +54,8 @@ */ public class VectorFastPFOR implements IntegerCODEC, SkippableIntegerCODEC { private final static int OVERHEAD_OF_EACH_EXCEPT = 8; + private static final int OVERHEAD_OF_EACH_PAGE_IN_INTS = 36; + private static final int OVERHEAD_OF_EACH_BLOCK_IN_INTS = 1; public final static int DEFAULT_PAGE_SIZE = 64 << 10; public final static int BLOCK_SIZE = 256; @@ -257,7 +259,11 @@ public void headlessUncompress(int[] in, IntWrapper inpos, int inlength, @Override public int maxHeadlessCompressedLength(IntWrapper compressedPositions, int inlength) { - throw new UnsupportedOperationException("Calculating the max compressed length is not supported yet."); + inlength = inlength - inlength % BLOCK_SIZE; + int pageCount = (inlength + pageSize - 1) / pageSize; + int blockCount = inlength / BLOCK_SIZE; + int blockSizeInInts = OVERHEAD_OF_EACH_BLOCK_IN_INTS + BLOCK_SIZE; + return OVERHEAD_OF_EACH_PAGE_IN_INTS * pageCount + blockSizeInInts * blockCount + 24; } private void loadMetaData(int[] in, int inexcept, int bytesize) { diff --git a/src/test/java/me/lemire/integercompression/BasicTest.java b/src/test/java/me/lemire/integercompression/BasicTest.java index b29ae0d..6743017 100644 --- a/src/test/java/me/lemire/integercompression/BasicTest.java +++ b/src/test/java/me/lemire/integercompression/BasicTest.java @@ -17,6 +17,7 @@ import me.lemire.integercompression.differential.IntegratedVariableByte; import me.lemire.integercompression.differential.XorBinaryPacking; import me.lemire.integercompression.synth.ClusteredDataGenerator; +import me.lemire.integercompression.vector.VectorFastPFOR; import org.junit.Test; @@ -43,6 +44,7 @@ public class BasicTest { new Composition(new OptPFDS16(), new VariableByte()), new Composition(new FastPFOR128(), new VariableByte()), new Composition(new FastPFOR(), new VariableByte()), + new Composition(new VectorFastPFOR(), new VariableByte()), new Simple9(), new Simple16(), new GroupSimple9(), diff --git a/src/test/java/me/lemire/integercompression/SkippableBasicTest.java b/src/test/java/me/lemire/integercompression/SkippableBasicTest.java index 881dada..ca919d4 100644 --- a/src/test/java/me/lemire/integercompression/SkippableBasicTest.java +++ b/src/test/java/me/lemire/integercompression/SkippableBasicTest.java @@ -13,6 +13,7 @@ import me.lemire.integercompression.differential.IntegratedVariableByte; import me.lemire.integercompression.differential.SkippableIntegratedComposition; import me.lemire.integercompression.differential.SkippableIntegratedIntegerCODEC; +import me.lemire.integercompression.vector.VectorFastPFOR; import org.junit.Test; import static org.junit.Assert.assertArrayEquals; @@ -37,6 +38,7 @@ public class SkippableBasicTest { new SkippableComposition(new OptPFDS16(), new VariableByte()), new SkippableComposition(new FastPFOR128(), new VariableByte()), new SkippableComposition(new FastPFOR(), new VariableByte()), + new SkippableComposition(new VectorFastPFOR(), new VariableByte()), new Simple9(), new Simple16() };