public static void shiftRightArray8(int[] values, int rightShifts, Slice result)
    {
        if (values.length != NUMBER_OF_INTS * 2) {
            throw new IllegalArgumentException("Incorrect values length");
        }
        if (rightShifts == 0) {
            for (int i = NUMBER_OF_INTS; i < 2 * NUMBER_OF_INTS; i++) {
                if (values[i] != 0) {
                    throwOverflowException();
                }
            }
            for (int i = 0; i < NUMBER_OF_INTS; i++) {
                setRawInt(result, i, values[i]);
            }
            return;
        }

        int wordShifts = rightShifts / 32;
        int bitShiftsInWord = rightShifts % 32;
        int shiftRestore = 32 - bitShiftsInWord;

        // check round-ups before settings values to result.
        // be aware that result could be the same object as decimal.
        boolean roundCarry;
        if (bitShiftsInWord == 0) {
            roundCarry = values[wordShifts - 1] < 0;
        }
        else {
            roundCarry = (values[wordShifts] & (1 << (bitShiftsInWord - 1))) != 0;
        }

        int r0 = values[0 + wordShifts];
        int r1 = values[1 + wordShifts];
        int r2 = values[2 + wordShifts];
        int r3 = values[3 + wordShifts];
        int r4 = wordShifts >= 4 ? 0 : values[4 + wordShifts];
        int r5 = wordShifts >= 3 ? 0 : values[5 + wordShifts];
        int r6 = wordShifts >= 2 ? 0 : values[6 + wordShifts];
        int r7 = wordShifts >= 1 ? 0 : values[7 + wordShifts];

        if (bitShiftsInWord > 0) {
            r0 = (r0 >>> bitShiftsInWord) | (r1 << shiftRestore);
            r1 = (r1 >>> bitShiftsInWord) | (r2 << shiftRestore);
            r2 = (r2 >>> bitShiftsInWord) | (r3 << shiftRestore);
            r3 = (r3 >>> bitShiftsInWord) | (r4 << shiftRestore);
        }

        if ((r4 >>> bitShiftsInWord) != 0 || r5 != 0 || r6 != 0 || r7 != 0) {
            throwOverflowException();
        }

        if (r3 < 0) {
            throwOverflowException();
        }

        // increment
        if (roundCarry) {
            r0++;
            if (r0 == 0) {
                r1++;
                if (r1 == 0) {
                    r2++;
                    if (r2 == 0) {
                        r3++;
                        if (r3 < 0) {
                            throwOverflowException();
                        }
                    }
                }
            }
        }

        pack(result, r0, r1, r2, r3, false);
    }
@Test
    public void testShiftRightArray8()
    {
        assertShiftRightArray8(TWO.pow(1), 0);
        assertShiftRightArray8(TWO.pow(1), 1);
        assertShiftRightArray8(TWO.pow(1), 10);

        assertShiftRightArray8(TWO.pow(15).add(TWO.pow(3)), 2);
        assertShiftRightArray8(TWO.pow(15).add(TWO.pow(3)), 10);
        assertShiftRightArray8(TWO.pow(15).add(TWO.pow(3)), 20);

        assertShiftRightArray8(TWO.pow(70), 30);
        assertShiftRightArray8(TWO.pow(70).subtract(TWO.pow(1)), 30, true);
        assertShiftRightArray8(TWO.pow(70), 32);
        assertShiftRightArray8(TWO.pow(70).subtract(TWO.pow(1)), 32, true);
        assertShiftRightArray8(TWO.pow(120), 70);
        assertShiftRightArray8(TWO.pow(120).subtract(TWO.pow(1)), 70, true);
        assertShiftRightArray8(TWO.pow(120), 96);
        assertShiftRightArray8(TWO.pow(120).subtract(TWO.pow(1)), 96, true);

        assertShiftRightArray8(MAX_DECIMAL_UNSCALED_VALUE, 20, true);
        assertShiftRightArray8(MAX_DECIMAL_UNSCALED_VALUE.multiply(MAX_DECIMAL_UNSCALED_VALUE), 130);

        assertShiftRightArray8(TWO.pow(256).subtract(BigInteger.ONE), 130, true);

        assertShiftRightArray8Overflow(TWO.pow(156), 1);
        assertShiftRightArray8Overflow(MAX_DECIMAL_UNSCALED_VALUE.multiply(MAX_DECIMAL_UNSCALED_VALUE), 20);
        assertShiftRightArray8Overflow(TWO.pow(256).subtract(BigInteger.ONE), 129);
    }