private static boolean doDecimalToBinaryConversion(
      long fast0, long fast1, long fast2,
      FastHiveDecimal fastInverseConst,
      int quotientIntegerWordNum,
      int quotientIntegerDigitNum,
      FastHiveDecimal fastMultiplierConst,
      long[] scratchLongs) {

    long lowerBinaryWord;
    long middleBinaryWord = 0;
    long highBinaryWord = 0;

    if (fastCompareTo(
            1,
            fast0, fast1, fast2, 0,
            1,
            fastMultiplierConst.fast0, fastMultiplierConst.fast1, fastMultiplierConst.fast2, 0) < 0) {

      // Optimize: whole decimal fits in one binary word.

      lowerBinaryWord =
          fast1 * MULTIPLER_LONGWORD_DECIMAL
        + fast0;

    } else {

      // Do division/remainder to get lower binary word; quotient will either be middle decimal
      // or be both high and middle decimal that requires another division/remainder.

      if (!doDecimalToBinaryDivisionRemainder(
          fast0, fast1, fast2,
          fastInverseConst,
          quotientIntegerWordNum,
          quotientIntegerDigitNum,
          fastMultiplierConst,
          scratchLongs)) {
        // Overflow.
        return false;
      }

      // Unpack the output.
      long quotientFast0 = scratchLongs[0];
      long quotientFast1 = scratchLongs[1];
      long quotientFast2 = scratchLongs[2];

      lowerBinaryWord = scratchLongs[3];

      if (fastCompareTo(
          1,
          quotientFast0, quotientFast1, quotientFast2, 0,
          1,
          fastMultiplierConst.fast0, fastMultiplierConst.fast1, fastMultiplierConst.fast2, 0) < 0) {

        // Optimize: whole decimal fits in two binary words.

        middleBinaryWord =
            quotientFast1 * MULTIPLER_LONGWORD_DECIMAL
          + quotientFast0;

      } else {
        if (!doDecimalToBinaryDivisionRemainder(
            quotientFast0, quotientFast1, quotientFast2,
            fastInverseConst,
            quotientIntegerWordNum,
            quotientIntegerDigitNum,
            fastMultiplierConst,
            scratchLongs)) {
          // Overflow.
          return false;
        }

        highBinaryWord =
            scratchLongs[1] * MULTIPLER_LONGWORD_DECIMAL
          + scratchLongs[0];

        middleBinaryWord = scratchLongs[3];

      }
    }

    scratchLongs[0] = lowerBinaryWord;
    scratchLongs[1] = middleBinaryWord;
    scratchLongs[2] = highBinaryWord;

    return true;
  }
Convert a fast decimal into 3 binary words of N bits each.

The 3 binary words will form a large binary value that is the unsigned unscaled decimal value:

   highWord * 2^(M+L) + middleWord * 2^L + lowerWord.

Where L is the number of bits in the lower word; M is the number of bits in the middle word.
We let L and M be different to support the SerializationUtil serialization where the lower
word is 62 bits and the remaining words are 63 bits...

The fast decimal is longwords of 16 digits each and we need binary words of 2^N.  Since
we are in decimal form, we have do work to get to convert to binary form.

See the comments for doDecimalToBinaryDivisionRemainder for details on the parameters.

The lowerWord is produced by calling doDecimalToBinaryDivisionRemainder.  The quotient from
that is passed to doDecimalToBinaryDivisionRemainder to produce the middleWord.  The final
quotient is used to produce the highWord.

@return True if the 3 binary words were produced without overflow.  Overflow is not expected.
storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java