Index: src/test/org/apache/lucene/util/packed/TestPackedInts.java =================================================================== --- src/test/org/apache/lucene/util/packed/TestPackedInts.java (revision 930109) +++ src/test/org/apache/lucene/util/packed/TestPackedInts.java (working copy) @@ -222,4 +222,11 @@ dir.close(); } + + public void testMutableBug() throws Exception { + PackedInts.Mutable mutable = PackedInts.getMutable(26, 5); + mutable.set(24, 31); + mutable.set(4, 16); + assertEquals("The value #24 should remain unchanged", 31, mutable.get(24)); + } } Index: src/java/org/apache/lucene/util/packed/Packed64.java =================================================================== --- src/java/org/apache/lucene/util/packed/Packed64.java (revision 930109) +++ src/java/org/apache/lucene/util/packed/Packed64.java (working copy) @@ -78,22 +78,26 @@ * The setter requires more masking than the getter. */ private static final long[][] WRITE_MASKS = - new long[ENTRY_SIZE][ENTRY_SIZE * FAC_BITPOS]; + new long[ENTRY_SIZE][ENTRY_SIZE * FAC_BITPOS]; static { - for (int elementBits = 1 ; elementBits <= BLOCK_SIZE ; elementBits++) { - long elementPosMask = ~(~0L << elementBits); - int[] currentShifts = SHIFTS[elementBits]; - long[] currentMasks = WRITE_MASKS[elementBits]; - for (int bitPos = 0 ; bitPos < BLOCK_SIZE ; bitPos++) { - int base = bitPos * FAC_BITPOS; - currentMasks[base ] =~((elementPosMask + for (int elementBits = 1 ; elementBits <= BLOCK_SIZE ; elementBits++) { + long elementPosMask = ~(~0L << elementBits); + int[] currentShifts = SHIFTS[elementBits]; + long[] currentMasks = WRITE_MASKS[elementBits]; + for (int bitPos = 0 ; bitPos < BLOCK_SIZE ; bitPos++) { + int base = bitPos * FAC_BITPOS; + currentMasks[base ] =~((elementPosMask << currentShifts[base + 1]) >>> currentShifts[base]); - currentMasks[base+1] = ~(elementPosMask - << currentShifts[base + 2]); - currentMasks[base+2] = currentShifts[base + 2] == 0 ? 0 : ~0; - } + currentMasks[base+1] = + ~(elementPosMask << currentShifts[base + 2]); + currentMasks[base+2] = currentShifts[base + 2] == 0 ? 0 : ~0; + if (bitPos <= BLOCK_SIZE - elementBits) { // Second block not used + currentMasks[base+1] = ~0; // Keep all bits + currentMasks[base+2] = 0; // Or with 0 + } } + } } /* The bits */ Index: src/java/org/apache/lucene/util/packed/Packed32.java =================================================================== --- src/java/org/apache/lucene/util/packed/Packed32.java (revision 930109) +++ src/java/org/apache/lucene/util/packed/Packed32.java (working copy) @@ -77,7 +77,7 @@ * The setter requires more masking than the getter. */ private static final int[][] WRITE_MASKS = - new int[ENTRY_SIZE][ENTRY_SIZE * FAC_BITPOS]; + new int[ENTRY_SIZE][ENTRY_SIZE * FAC_BITPOS]; static { for (int elementBits = 1 ; elementBits <= BLOCK_SIZE ; elementBits++) { int elementPosMask = ~(~0 << elementBits); @@ -86,11 +86,15 @@ for (int bitPos = 0 ; bitPos < BLOCK_SIZE ; bitPos++) { int base = bitPos * FAC_BITPOS; currentMasks[base ] =~((elementPosMask - << currentShifts[base + 1]) - >>> currentShifts[base]); + << currentShifts[base + 1]) + >>> currentShifts[base]); currentMasks[base+1] = ~(elementPosMask - << currentShifts[base + 2]); + << currentShifts[base + 2]); currentMasks[base+2] = currentShifts[base + 2] == 0 ? 0 : ~0; + if (bitPos <= BLOCK_SIZE - elementBits) { // Second block not used + currentMasks[base+1] = ~0; // Keep all bits + currentMasks[base+2] = 0; // Or with 0 + } } } }