Skip to content

Commit 8d40838

Browse files
author
George Bouroutzoglou
committed
Make appendBitAndRemoveAtIndex more general (and renamed it)
Similarly to insertInLong it now works with any number of bits (<= BITS_PER_LONG) instead of one. Will be useful in removeRange for sure
1 parent d416823 commit 8d40838

File tree

1 file changed

+22
-25
lines changed

1 file changed

+22
-25
lines changed

src/main/java/gr/geompokon/bitarray/BitArray.java

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -364,47 +364,44 @@ private long insertInLong(long lastValue, int lastLength, int longIndex, int ind
364364
private void removeAndShiftAllLeft(int longIndex, int indexInLong) {
365365
// start at the end and work back to current long index
366366
int currentLongIndex = getLongIndex(elements - 1);
367-
int leftmostBit = 0; // dud value for first shift
367+
long leftmostBit = 0; // dud value for first shift
368368
// keep adding the old MSB as LSB of the previous long index and shifting the rest to the left
369369
while (currentLongIndex > longIndex) {
370-
leftmostBit = appendBitAndRemoveAtIndex(leftmostBit, currentLongIndex--, 0);
370+
leftmostBit = removeAtIndexAndAppend(leftmostBit, 1, currentLongIndex--, 0);
371371
}
372-
// add the final MSB as LSB of {@code longIndex} and shift only the bits to the removed's right
373-
appendBitAndRemoveAtIndex(leftmostBit, longIndex, indexInLong);
372+
// add the final MSB as LSB of longIndex and shift only the bits to the popped bit's right
373+
removeAtIndexAndAppend(leftmostBit, 1, longIndex, indexInLong);
374374
}
375375

376376
/**
377-
* Appends the bit at the end of the long specified by the arguments and removes the bit at {@code indexInLong}.
377+
* Removes the {@code lastLength} bits from the long specified by {@code longIndex} starting from {@code indexInLong}
378+
* and then appends the same length of bits from {@code lastValue} at the end of the long. The
378379
*
379-
* <p>
380-
* Since {@code indexInLong} can be at the middle of the long word, removing the bit is done by splitting the
381-
* long in two parts, clearing the desired bit and shifting once to restore the order of the previous bits.
382-
* </p>
383-
*
384-
* @param bit the bit to be appended to the long
380+
* @param lastValue bits to be appended to the long
381+
* @param lastLength length in bits of the last value
385382
* @param longIndex index of the long in the {@code data} array
386-
* @param indexInLong index of the bit in the long
387-
* @return bit at {@code longIndex} that was popped out
383+
* @param indexInLong index of the first removed bit in the long
384+
* @return bits that were popped from the long
388385
*/
389-
private int appendBitAndRemoveAtIndex(int bit, int longIndex, int indexInLong) {
386+
private long removeAtIndexAndAppend(long lastValue, int lastLength, int longIndex, int indexInLong) {
390387
// get right side [indexInLong : ], can not be empty, will be shifted
391388
long rightSide = (data[longIndex] << indexInLong) >>> indexInLong;
392389
// get left side [0 : indexInLong), can be empty, will remain intact
393-
long leftSide = data[longIndex] - rightSide;
390+
long leftSide = data[longIndex] & ~rightSide;
394391

395-
// save MSB
396-
int rightSideMSB = getBitInLong(rightSide, indexInLong);
397-
// clear MSB and shift to the left to make it "disappear"
398-
rightSide &= ~singleBitMask(indexInLong);
399-
rightSide <<= 1;
400-
// append the previous bit
401-
rightSide += bit;
392+
// save removed values
393+
long poppedValues = selectBits(rightSide, indexInLong, lastLength) >>> (BITS_PER_LONG - indexInLong - lastLength);
394+
395+
// clear copied bits and shift to the left
396+
rightSide = (rightSide << indexInLong + lastLength) >>> indexInLong;
397+
// append the previous bits
398+
rightSide |= lastValue;
402399

403400
// re-join the two parts
404-
data[longIndex] = leftSide + rightSide;
401+
data[longIndex] = leftSide ^ rightSide;
405402

406-
// return the MSB
407-
return rightSideMSB;
403+
// return the popped bits
404+
return poppedValues;
408405
}
409406

410407
/**

0 commit comments

Comments
 (0)