@@ -364,47 +364,44 @@ private long insertInLong(long lastValue, int lastLength, int longIndex, int ind
364
364
private void removeAndShiftAllLeft (int longIndex , int indexInLong ) {
365
365
// start at the end and work back to current long index
366
366
int currentLongIndex = getLongIndex (elements - 1 );
367
- int leftmostBit = 0 ; // dud value for first shift
367
+ long leftmostBit = 0 ; // dud value for first shift
368
368
// keep adding the old MSB as LSB of the previous long index and shifting the rest to the left
369
369
while (currentLongIndex > longIndex ) {
370
- leftmostBit = appendBitAndRemoveAtIndex (leftmostBit , currentLongIndex --, 0 );
370
+ leftmostBit = removeAtIndexAndAppend (leftmostBit , 1 , currentLongIndex --, 0 );
371
371
}
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 );
374
374
}
375
375
376
376
/**
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
378
379
*
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
385
382
* @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
388
385
*/
389
- private int appendBitAndRemoveAtIndex ( int bit , int longIndex , int indexInLong ) {
386
+ private long removeAtIndexAndAppend ( long lastValue , int lastLength , int longIndex , int indexInLong ) {
390
387
// get right side [indexInLong : ], can not be empty, will be shifted
391
388
long rightSide = (data [longIndex ] << indexInLong ) >>> indexInLong ;
392
389
// get left side [0 : indexInLong), can be empty, will remain intact
393
- long leftSide = data [longIndex ] - rightSide ;
390
+ long leftSide = data [longIndex ] & ~ rightSide ;
394
391
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 ;
402
399
403
400
// re-join the two parts
404
- data [longIndex ] = leftSide + rightSide ;
401
+ data [longIndex ] = leftSide ^ rightSide ;
405
402
406
- // return the MSB
407
- return rightSideMSB ;
403
+ // return the popped bits
404
+ return poppedValues ;
408
405
}
409
406
410
407
/**
0 commit comments