private static void scaleDownTenArray8RoundUp(int[] array, short tenScale) {
    assert (array.length == 8);
    if (tenScale > MAX_DIGITS) {

      // then definitely this will end up zero.
      Arrays.fill(array, 0);
      return;
    }
    if (tenScale <= SqlMathUtil.MAX_POWER_TEN_INT31) {
      int divisor = SqlMathUtil.POWER_TENS_INT31[tenScale];
      assert (divisor > 0);
      boolean round = divideCheckRound(array, divisor);
      if (round) {
        incrementArray(array);
      }
      return;
    }

    // division by inverse multiplication.
    final int[] inverse = SqlMathUtil.INVERSE_POWER_TENS_INT128[tenScale].v;
    final int inverseWordShift = SqlMathUtil.INVERSE_POWER_TENS_INT128_WORD_SHIFTS[tenScale];
    assert (inverseWordShift <= 3);
    assert (inverse[3] != 0);
    for (int i = 5 + inverseWordShift; i < 8; ++i) {
      if (array[i] != 0) {
        SqlMathUtil.throwOverflowException(); // because inverse[3] is
                                              // not zero
      }
    }

    int z4 = 0, z5 = 0, z6 = 0, z7 = 0; // because inverse is scaled 2^128,
                                        // these will become v0-v3
    int z8 = 0, z9 = 0, z10 = 0; // for wordshift
    long product = 0L;

    product += (inverse[0] & SqlMathUtil.LONG_MASK)
        * (array[4] & SqlMathUtil.LONG_MASK)
        + (inverse[1] & SqlMathUtil.LONG_MASK)
        * (array[3] & SqlMathUtil.LONG_MASK)
        + (inverse[2] & SqlMathUtil.LONG_MASK)
        * (array[2] & SqlMathUtil.LONG_MASK)
        + (inverse[3] & SqlMathUtil.LONG_MASK)
        * (array[1] & SqlMathUtil.LONG_MASK);
    z4 = (int) product;
    product >>>= 32;

    product += (inverse[0] & SqlMathUtil.LONG_MASK)
        * (array[5] & SqlMathUtil.LONG_MASK)
        + (inverse[1] & SqlMathUtil.LONG_MASK)
        * (array[4] & SqlMathUtil.LONG_MASK)
        + (inverse[2] & SqlMathUtil.LONG_MASK)
        * (array[3] & SqlMathUtil.LONG_MASK)
        + (inverse[3] & SqlMathUtil.LONG_MASK)
        * (array[2] & SqlMathUtil.LONG_MASK);
    z5 = (int) product;
    product >>>= 32;

    product += (inverse[0] & SqlMathUtil.LONG_MASK)
        * (array[6] & SqlMathUtil.LONG_MASK)
        + (inverse[1] & SqlMathUtil.LONG_MASK)
        * (array[5] & SqlMathUtil.LONG_MASK)
        + (inverse[2] & SqlMathUtil.LONG_MASK)
        * (array[4] & SqlMathUtil.LONG_MASK)
        + (inverse[3] & SqlMathUtil.LONG_MASK)
        * (array[3] & SqlMathUtil.LONG_MASK);
    z6 = (int) product;
    product >>>= 32;

    product += (inverse[0] & SqlMathUtil.LONG_MASK)
        * (array[7] & SqlMathUtil.LONG_MASK)
        + (inverse[1] & SqlMathUtil.LONG_MASK)
        * (array[6] & SqlMathUtil.LONG_MASK)
        + (inverse[2] & SqlMathUtil.LONG_MASK)
        * (array[5] & SqlMathUtil.LONG_MASK)
        + (inverse[3] & SqlMathUtil.LONG_MASK)
        * (array[4] & SqlMathUtil.LONG_MASK);
    z7 = (int) product;
    product >>>= 32;

    if (inverseWordShift >= 1) {
      product += (inverse[1] & SqlMathUtil.LONG_MASK)
          * (array[7] & SqlMathUtil.LONG_MASK)
          + (inverse[2] & SqlMathUtil.LONG_MASK)
          * (array[6] & SqlMathUtil.LONG_MASK)
          + (inverse[3] & SqlMathUtil.LONG_MASK)
          * (array[5] & SqlMathUtil.LONG_MASK);
      z8 = (int) product;
      product >>>= 32;

      if (inverseWordShift >= 2) {
        product += (inverse[2] & SqlMathUtil.LONG_MASK)
            * (array[7] & SqlMathUtil.LONG_MASK)
            + (inverse[3] & SqlMathUtil.LONG_MASK)
            * (array[6] & SqlMathUtil.LONG_MASK);
        z9 = (int) product;
        product >>>= 32;

        if (inverseWordShift >= 3) {
          product += (inverse[3] & SqlMathUtil.LONG_MASK)
              * (array[7] & SqlMathUtil.LONG_MASK);
          z10 = (int) product;
          product >>>= 32;
        }
      }
    }

    if (product != 0) {
      SqlMathUtil.throwOverflowException();
    }

    // if inverse is word-shifted for accuracy, shift it back here.
    switch (inverseWordShift) {
    case 1:
      z4 = z5;
      z5 = z6;
      z6 = z7;
      z7 = z8;
      break;
    case 2:
      z4 = z6;
      z5 = z7;
      z6 = z8;
      z7 = z9;
      break;
    case 3:
      z4 = z7;
      z5 = z8;
      z6 = z9;
      z7 = z10;
      break;
    default:
      break;
    }

    // now, correct +1 error and rounding up.
    final int[] power = SqlMathUtil.POWER_TENS_INT128[tenScale].v;
    final int[] half = SqlMathUtil.ROUND_POWER_TENS_INT128[tenScale].v;

    int d0, d1, d2, d3, d4;
    product = (array[0] & SqlMathUtil.LONG_MASK)
        - (power[0] & SqlMathUtil.LONG_MASK) * (z4 & SqlMathUtil.LONG_MASK);
    d0 = (int) product;

    product = (array[1] & SqlMathUtil.LONG_MASK)
        - (power[0] & SqlMathUtil.LONG_MASK) * (z5 & SqlMathUtil.LONG_MASK)
        - (power[1] & SqlMathUtil.LONG_MASK) * (z4 & SqlMathUtil.LONG_MASK)
        - ((int) -(product >> 32));
    d1 = (int) product;

    product = (array[2] & SqlMathUtil.LONG_MASK)
        - (power[0] & SqlMathUtil.LONG_MASK) * (z6 & SqlMathUtil.LONG_MASK)
        - (power[1] & SqlMathUtil.LONG_MASK) * (z5 & SqlMathUtil.LONG_MASK)
        - (power[2] & SqlMathUtil.LONG_MASK) * (z4 & SqlMathUtil.LONG_MASK)
        - ((int) -(product >> 32));
    d2 = (int) product;

    product = (array[3] & SqlMathUtil.LONG_MASK)
        - (power[0] & SqlMathUtil.LONG_MASK) * (z7 & SqlMathUtil.LONG_MASK)
        - (power[1] & SqlMathUtil.LONG_MASK) * (z6 & SqlMathUtil.LONG_MASK)
        - (power[2] & SqlMathUtil.LONG_MASK) * (z5 & SqlMathUtil.LONG_MASK)
        - (power[3] & SqlMathUtil.LONG_MASK) * (z4 & SqlMathUtil.LONG_MASK)
        - ((int) -(product >> 32));
    d3 = (int) product;

    product = (array[4] & SqlMathUtil.LONG_MASK)
        - (power[1] & SqlMathUtil.LONG_MASK) * (z7 & SqlMathUtil.LONG_MASK)
        - (power[2] & SqlMathUtil.LONG_MASK) * (z6 & SqlMathUtil.LONG_MASK)
        - (power[3] & SqlMathUtil.LONG_MASK) * (z5 & SqlMathUtil.LONG_MASK)
        - ((int) -(product >> 32));
    d4 = (int) product;

    // If the difference is larger than 2^128 (d4 != 0), then D is
    // definitely larger than power, so increment.
    // otherwise, compare it with power and half.
    boolean increment = (d4 != 0)
        || (compareTo(d0, d1, d2, d3, half[0], half[1], half[2], half[3]) >= 0);

    array[0] = z4;
    array[1] = z5;
    array[2] = z6;
    array[3] = z7;
    if (increment) {
      incrementArray(array);
    }
  }
Scales down the given array (8 elements) for 10**tenScale. This method is
frequently called from multiply(), so highly optimized. It's lengthy, but
this is inevitable to avoid array/object creation. <h2>Summary of this
method</h2>
<p>
This method employs division by inverse multiplication (except easy cases).
because all inverses of powers of tens are pre-calculated, this is much
faster than doing divisions. The matrix multiplication benchmark hit 3x
performance with this. because the inverse is a little bit smaller than
real value, the result is same or smaller than accurate answer, not larger.
we take care of it after the first multiplication.
</p>
<p>
Then, multiply it with power of tens (which is accurate) to correct +1
error and rounding up. let D = array - z * power: if D >= power/2, then
++z. Otherwise, do nothing.
</p>

@param array
         array to scale down. in AND out. length must be 8.
@param tenScale
         distance to scale down
common/src/java/org/apache/hadoop/hive/common/type/UnsignedInt128.java