Skip to content

Commit 3eef81b

Browse files
committed
Fix handling of output offset in SkippableComposition classes
Previously, when outpos passed to headlessUncompress was greater than zero, the second scheme would receive an incorrect number of remaining integers to decode.
1 parent beb7460 commit 3eef81b

File tree

5 files changed

+82
-3
lines changed

5 files changed

+82
-3
lines changed

src/main/java/me/lemire/integercompression/SkippableComposition.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ public void headlessCompress(int[] in, IntWrapper inpos, int inlength, int[] out
5252
public void headlessUncompress(int[] in, IntWrapper inpos, int inlength, int[] out,
5353
IntWrapper outpos, int num) {
5454
int init = inpos.get();
55+
int outposInit = outpos.get();
56+
5557
F1.headlessUncompress(in, inpos, inlength, out, outpos, num);
5658
if (inpos.get() == init) {
5759
inpos.increment();
5860
}
5961
inlength -= inpos.get() - init;
60-
num -= outpos.get();
62+
num -= outpos.get() - outposInit;
6163
F2.headlessUncompress(in, inpos, inlength, out, outpos, num);
6264
}
6365

src/main/java/me/lemire/integercompression/differential/SkippableIntegratedComposition.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,15 @@ public void headlessUncompress(int[] in, IntWrapper inpos, int inlength,
6666
if (inlength == 0)
6767
return;
6868
int init = inpos.get();
69+
int outposInit = outpos.get();
70+
6971
F1.headlessUncompress(in, inpos, inlength, out, outpos,num,initvalue);
7072
if (inpos.get() == init) {
7173
inpos.increment();
7274
}
7375
inlength -= inpos.get() - init;
7476

75-
num -= outpos.get();
77+
num -= outpos.get() - outposInit;
7678
F2.headlessUncompress(in, inpos, inlength, out, outpos,num,initvalue);
7779
}
7880

src/main/java/me/lemire/longcompression/SkippableLongComposition.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ public void headlessCompress(long[] in, IntWrapper inpos, int inlength, long[] o
5353
public void headlessUncompress(long[] in, IntWrapper inpos, int inlength, long[] out,
5454
IntWrapper outpos, int num) {
5555
int init = inpos.get();
56+
int outposInit = outpos.get();
57+
5658
F1.headlessUncompress(in, inpos, inlength, out, outpos, num);
5759
if (inpos.get() == init) {
5860
inpos.increment();
5961
}
6062
inlength -= inpos.get() - init;
61-
num -= outpos.get();
63+
num -= outpos.get() - outposInit;
6264
F2.headlessUncompress(in, inpos, inlength, out, outpos, num);
6365
}
6466

src/test/java/me/lemire/integercompression/SkippableBasicTest.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import me.lemire.integercompression.differential.SkippableIntegratedIntegerCODEC;
1616
import org.junit.Test;
1717

18+
import static org.junit.Assert.assertArrayEquals;
1819
import static org.junit.Assert.assertTrue;
1920

2021
/**
@@ -236,4 +237,52 @@ private static void testMaxHeadlessCompressedLength(SkippableIntegerCODEC codec,
236237
}
237238
}
238239
}
240+
241+
@Test
242+
public void testUncompressOutputOffset_SkippableComposition() {
243+
for (int offset : new int[] {0, 1, 6}) {
244+
SkippableComposition codec = new SkippableComposition(new BinaryPacking(), new VariableByte());
245+
246+
int[] input = { 2, 3, 4, 5 };
247+
int[] compressed = new int[codec.maxHeadlessCompressedLength(new IntWrapper(0), input.length)];
248+
int[] uncompressed = new int[offset + input.length];
249+
250+
IntWrapper inputOffset = new IntWrapper(0);
251+
IntWrapper compressedOffset = new IntWrapper(0);
252+
253+
codec.headlessCompress(input, inputOffset, input.length, compressed, compressedOffset);
254+
255+
int compressedLength = compressedOffset.get();
256+
IntWrapper uncompressedOffset = new IntWrapper(offset);
257+
compressedOffset = new IntWrapper(0);
258+
codec.headlessUncompress(compressed, compressedOffset, compressedLength, uncompressed, uncompressedOffset, input.length);
259+
260+
assertArrayEquals(input, Arrays.copyOfRange(uncompressed, offset, offset + input.length));
261+
}
262+
}
263+
264+
@Test
265+
public void testUncompressOutputOffset_SkippableIntegratedComposition() {
266+
for (int offset : new int[] {0, 1, 6}) {
267+
SkippableIntegratedComposition codec = new SkippableIntegratedComposition(new IntegratedBinaryPacking(), new IntegratedVariableByte());
268+
269+
int[] input = { 2, 3, 4, 5 };
270+
int[] compressed = new int[codec.maxHeadlessCompressedLength(new IntWrapper(0), input.length)];
271+
int[] uncompressed = new int[offset + input.length];
272+
273+
IntWrapper inputOffset = new IntWrapper(0);
274+
IntWrapper compressedOffset = new IntWrapper(0);
275+
IntWrapper initValue = new IntWrapper(0);
276+
277+
codec.headlessCompress(input, inputOffset, input.length, compressed, compressedOffset, initValue);
278+
279+
int compressedLength = compressedOffset.get();
280+
IntWrapper uncompressedOffset = new IntWrapper(offset);
281+
compressedOffset = new IntWrapper(0);
282+
initValue = new IntWrapper(0);
283+
codec.headlessUncompress(compressed, compressedOffset, compressedLength, uncompressed, uncompressedOffset, input.length, initValue);
284+
285+
assertArrayEquals(input, Arrays.copyOfRange(uncompressed, offset, offset + input.length));
286+
}
287+
}
239288
}

src/test/java/me/lemire/longcompression/SkippableLongBasicTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import me.lemire.integercompression.TestUtils;
1616
import me.lemire.integercompression.VariableByte;
1717

18+
import static org.junit.Assert.assertArrayEquals;
1819
import static org.junit.Assert.assertTrue;
1920

2021
/**
@@ -167,4 +168,27 @@ private static void testMaxHeadlessCompressedLength(SkippableLongCODEC codec, in
167168
assertTrue(maxOutputLength <= outPos.get() + 1); // +1 because SkippableLongComposition always adds one extra integer for the potential header
168169
}
169170
}
171+
172+
@Test
173+
public void testUncompressOutputOffset_SkippableLongComposition() {
174+
for (int offset : new int[] {0, 1, 6}) {
175+
SkippableLongComposition codec = new SkippableLongComposition(new LongBinaryPacking(), new LongVariableByte());
176+
177+
long[] input = { 2, 3, 4, 5 };
178+
long[] compressed = new long[codec.maxHeadlessCompressedLength(new IntWrapper(0), input.length)];
179+
long[] uncompressed = new long[offset + input.length];
180+
181+
IntWrapper inputOffset = new IntWrapper(0);
182+
IntWrapper compressedOffset = new IntWrapper(0);
183+
184+
codec.headlessCompress(input, inputOffset, input.length, compressed, compressedOffset);
185+
186+
int compressedLength = compressedOffset.get();
187+
IntWrapper uncompressedOffset = new IntWrapper(offset);
188+
compressedOffset = new IntWrapper(0);
189+
codec.headlessUncompress(compressed, compressedOffset, compressedLength, uncompressed, uncompressedOffset, input.length);
190+
191+
assertArrayEquals(input, Arrays.copyOfRange(uncompressed, offset, offset + input.length));
192+
}
193+
}
170194
}

0 commit comments

Comments
 (0)