public int compareToScaleTen(UnsignedInt128 o, short tenScale) {

    // easier case. take a quick path
    if (tenScale == 0) {
      return compareTo(o);
    }

    // if o is zero, easy.
    if (o.isZero()) {
      return this.isZero() ? 0 : 1;
    } else if (this.isZero()) {

      // if this is zero, we need to check if o might become zero after
      // scaling down.
      // this is not easy because there might be rounding.
      if (tenScale > 0) {

        // scaling up, so o is definitely larger
        return -1;
      }
      if (tenScale < -SqlMathUtil.MAX_POWER_TEN_INT128) {

        // any value will become zero. even no possibility of rounding
        return 0;
      } else {

        // compare with 5 * 10**-tenScale
        // example: tenScale=-1. o will be zero after scaling if o>=5.
        boolean oZero = o
            .compareTo(SqlMathUtil.ROUND_POWER_TENS_INT128[-tenScale]) < 0;
        return oZero ? 0 : -1;
      }
    }

    // another quick path
    if (this.fitsInt32() && o.fitsInt32()
        && tenScale <= SqlMathUtil.MAX_POWER_TEN_INT31) {
      long v0Long = this.v[0] & SqlMathUtil.LONG_MASK;
      long o0;
      if (tenScale < 0) {
        if (tenScale < -SqlMathUtil.MAX_POWER_TEN_INT31) {

          // this scales down o.v[0] to 0 because 2^32 = 4.2E9. No
          // possibility of rounding.
          o0 = 0L;
        } else {

          // divide by 10**-tenScale. check for rounding.
          o0 = (o.v[0] & SqlMathUtil.LONG_MASK)
              / SqlMathUtil.POWER_TENS_INT31[-tenScale];
          long remainder = (o.v[0] & SqlMathUtil.LONG_MASK)
              % SqlMathUtil.POWER_TENS_INT31[-tenScale];
          if (remainder >= SqlMathUtil.ROUND_POWER_TENS_INT31[-tenScale]) {
            assert (o0 >= 0);
            ++o0; // this is safe because o0 is positive
          }
        }
      } else {

        // tenScale <= SqlMathUtil.MAX_POWER_TEN_INT31
        // so, we can make this as a long comparison
        o0 = (o.v[0] & SqlMathUtil.LONG_MASK)
            * (SqlMathUtil.POWER_TENS_INT31[tenScale] & SqlMathUtil.LONG_MASK);
      }
      return SqlMathUtil.compareUnsignedLong(v0Long, o0);
    }

    // unfortunately no quick path. let's do scale up/down
    int[] ov = o.v.clone();
    if (tenScale < 0) {

      // scale down. does rounding
      scaleDownTenArray4RoundUp(ov, (short) -tenScale);
    } else {

      // scale up
      boolean overflow = scaleUpTenArray(ov, tenScale);
      if (overflow) {

        // overflow is not an error here. it just means "this" is
        // smaller
        return -1;
      }
    }

    return compareTo(ov);
  }
Compares with the given object after scaling up/down it for 10**scaleUp.
This method is not destructive. Used from {@link Decimal128}.

@param o
         the object to compare with
@param tenScale
         power of 10 to scale up (if positive) or down (if negative) the
         given object.
@return a negative integer, zero, or a positive integer as this object is
        less than, equal to, or greater than the specified object.
common/src/java/org/apache/hadoop/hive/common/type/UnsignedInt128.java