public void shiftValuesRight(final int numberOfBinaryOrdersOfMagnitude) {
        if (numberOfBinaryOrdersOfMagnitude < 0) {
            throw new IllegalArgumentException("Cannot shift by a negative number of magnitudes");
        }

        if (numberOfBinaryOrdersOfMagnitude == 0) {
            return;
        }
        if (getTotalCount() == getCountAtIndex(0)) {
            // (no need to shift any values if all recorded values are at the 0 value level:)
            return;
        }

        final int shiftAmount = subBucketHalfCount * numberOfBinaryOrdersOfMagnitude;

        // indicate underflow if minValue is in the range being shifted from:
        int minNonZeroValueIndex = countsArrayIndex(getMinNonZeroValue());
        // Any shifting into the bottom-most half bucket would represents a loss of accuracy,
        // and a non-reversible operation. Therefore any non-0 value that falls in an
        // index below (shiftAmount + subBucketHalfCount) would represent an underflow:
        if (minNonZeroValueIndex < shiftAmount + subBucketHalfCount) {
            throw new ArrayIndexOutOfBoundsException(
                    "Operation would underflow and lose precision of already recorded value counts");
        }

        // perform shift:

        long maxValueBeforeShift = maxValueUpdater.getAndSet(this, 0);
        long minNonZeroValueBeforeShift = minNonZeroValueUpdater.getAndSet(this, Long.MAX_VALUE);

        // move normalizingIndexOffset
        shiftNormalizingIndexByOffset(-shiftAmount, false);

        // adjust min, max:
        updateMinAndMax(maxValueBeforeShift >> numberOfBinaryOrdersOfMagnitude);
        if (minNonZeroValueBeforeShift < Long.MAX_VALUE) {
            updateMinAndMax(minNonZeroValueBeforeShift >> numberOfBinaryOrdersOfMagnitude);
        }
    }
public void shiftValuesRight ( final int numberOfBinaryOrdersOfMagnitude ) { if ( numberOfBinaryOrdersOfMagnitude < 0 ) { throw new IllegalArgumentException ( "Cannot shift by a negative number of magnitudes" ) ; } if ( numberOfBinaryOrdersOfMagnitude == 0 ) { return ; } if ( getTotalCount ( ) == getCountAtIndex ( 0 ) ) { return ; } final int shiftAmount = subBucketHalfCount * numberOfBinaryOrdersOfMagnitude ; int minNonZeroValueIndex = countsArrayIndex ( getMinNonZeroValue ( ) ) ; if ( minNonZeroValueIndex < shiftAmount + subBucketHalfCount ) { throw new ArrayIndexOutOfBoundsException ( "Operation would underflow and lose precision of already recorded value counts" ) ; } long maxValueBeforeShift = maxValueUpdater . getAndSet ( this , 0 ) ; long minNonZeroValueBeforeShift = minNonZeroValueUpdater . getAndSet ( this , Long . MAX_VALUE ) ; shiftNormalizingIndexByOffset ( - shiftAmount , false ) ; updateMinAndMax ( maxValueBeforeShift > > numberOfBinaryOrdersOfMagnitude ) ; if ( minNonZeroValueBeforeShift < Long . MAX_VALUE ) { updateMinAndMax ( minNonZeroValueBeforeShift > > numberOfBinaryOrdersOfMagnitude ) ; } }
Shift recorded values to the right (the equivalent of a &gt;&gt; shift operation on all recorded values). The
configured integer value range limits and value precision setting will remain unchanged.
<p>
Shift right operations that do not underflow are reversible with a shift left operation with no loss of
information. An {@link ArrayIndexOutOfBoundsException} reflecting an "underflow" conditions will be thrown
if any recorded values may lose representation accuracy as a result of the attempted shift operation.
<p>
For a shift of a single order of magnitude, expect such an underflow exception if any recorded non-zero
values up to [numberOfSignificantValueDigits (rounded up to nearest power of 2) multiplied by
(2 ^ numberOfBinaryOrdersOfMagnitude) currently exist in the histogram.

@param numberOfBinaryOrdersOfMagnitude The number of binary orders of magnitude to shift by