public static boolean fastSetFromBigInteger(
      BigInteger bigInteger, int scale, int precision, FastHiveDecimal fastResult) {

    if (scale < 0) {

      // Multiply by 10^(-scale) to normalize.  We do not use negative scale in our representation.
      //
      // Example:
      //    4.172529E+20 has a negative scale -20 since scale is number of digits below the dot.
      //    417252900000000000000 normalized as scale 0.
      //
      bigInteger = bigInteger.multiply(BIG_INTEGER_TEN.pow(-scale));
      scale = 0;
    }

    int signum = bigInteger.signum();
    if (signum == 0) {
      // Zero.
      return true;
    } else if (signum == -1) {
      // Normalize to positive.
      bigInteger = bigInteger.negate();
    }

    if (precision < 0) {
      // A slow way to get the number of decimal digits.
      precision = bigInteger.toString().length();
    }

    // System.out.println("FAST_SET_FROM_BIG_INTEGER adjusted bigInteger " + bigInteger + " precision " + precision);

    int integerDigitCount = precision - scale;
    // System.out.println("FAST_SET_FROM_BIG_INTEGER integerDigitCount " + integerDigitCount + " scale " + scale);
    int maxScale;
    if (integerDigitCount >= 0) {
      if (integerDigitCount > HiveDecimal.MAX_PRECISION) {
        return false;
      }
      maxScale = HiveDecimal.MAX_SCALE - integerDigitCount;
    } else {
      maxScale = HiveDecimal.MAX_SCALE;
    }
    // System.out.println("FAST_SET_FROM_BIG_INTEGER maxScale " + maxScale);

    if (scale > maxScale) {

      // A larger scale is ok -- we will knock off lower digits and round.

      final int trimAwayCount = scale - maxScale;
      // System.out.println("FAST_SET_FROM_BIG_INTEGER trimAwayCount " + trimAwayCount);
      if (trimAwayCount > 1) {
        // First, throw away digits below round digit.
        BigInteger bigIntegerThrowAwayBelowRoundDigitDivisor = BIG_INTEGER_TEN.pow(trimAwayCount - 1);
        bigInteger = bigInteger.divide(bigIntegerThrowAwayBelowRoundDigitDivisor);
      }
      // System.out.println("FAST_SET_FROM_BIG_INTEGER with round digit bigInteger " + bigInteger + " length " + bigInteger.toString().length());

      BigInteger[] quotientAndRemainder = bigInteger.divideAndRemainder(BIG_INTEGER_TEN);
      // System.out.println("FAST_SET_FROM_BIG_INTEGER quotientAndRemainder " + Arrays.toString(quotientAndRemainder));

      BigInteger quotient = quotientAndRemainder[0];
      if (quotientAndRemainder[1].intValue() >= 5) {
        if (quotient.equals(BIG_INTEGER_MAX_DECIMAL)) {

          // 38 9's digits.
          // System.out.println("FAST_SET_FROM_BIG_INTEGER quotient is BIG_INTEGER_MAX_DECIMAL");

          if (maxScale == 0) {
            // No room above for rounding.
            return false;
          }

          // System.out.println("FAST_SET_FROM_BIG_INTEGER reached here... scale " + scale + " maxScale " + maxScale);
          // Rounding results in 10^N.
          bigInteger = BIG_INTEGER_TEN.pow(integerDigitCount);
          maxScale = 0;
        } else {

          // Round up.
          bigInteger = quotient.add(BigInteger.ONE);
        }
      } else {

        // No rounding.
        bigInteger = quotient;
      }
      scale = maxScale;
    }
    if (!fastSetFromBigInteger(bigInteger, fastResult)) {
      return false;
    }

    if (fastResult.fast0 == 0 && fastResult.fast1 == 0 && fastResult.fast2 == 0) {
      fastResult.fastSignum = 0;
    } else {
      fastResult.fastSignum = signum;
      fastResult.fastIntegerDigitCount = Math.max(0, fastResult.fastIntegerDigitCount - scale);
      fastResult.fastScale = scale;

      final int trailingZeroCount =
          fastTrailingDecimalZeroCount(
              fastResult.fast0, fastResult.fast1, fastResult.fast2,
              fastResult.fastIntegerDigitCount, scale);
      if (trailingZeroCount > 0) {
        doFastScaleDown(
            fastResult,
            trailingZeroCount,
            fastResult);
        fastResult.fastScale -= trailingZeroCount;
      }
    }

    return true;
  }
Creates a fast decimal from a BigInteger with a specified scale.

NOTE: The fastSetFromBigInteger method requires the caller to pass a fastResult
parameter has been reset for better performance.

@param bigInteger the value to set as an integer
@param scale the scale to use
@param precision the precision to use
@param fastResult an object to reuse
@return True if the BigInteger and scale were successfully converted to a decimal.
storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java