public static boolean fastSerializationUtilsWrite()

in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [2016:2161]


  public static boolean fastSerializationUtilsWrite(
      OutputStream outputStream,
      int fastSignum,
      long fast0,
      long fast1,
      long fast2,
      int fastIntegerDigitCount,
      int fastScale,
      long[] scratchLongs)
      throws IOException {

    boolean isNegative = (fastSignum == -1);

    /*
     * The sign is encoded as the least significant bit.
     *
     * We need to adjust our decimal before conversion to binary.
     *
     * Positive:
     *   Multiply by 2.
     *
     * Negative:
     *   Logic in SerializationUtils.writeBigInteger does a negate on the BigInteger. We
     *   do not have to since FastHiveDecimal stores the numbers unsigned in fast0, fast1,
     *   and fast2.  We do need to subtract one though.
     *
     *   And then multiply by 2 and add in the 1 sign bit.
     *
     *   CONSIDER: This could be combined.
     */
    long adjust0;
    long adjust1;
    long adjust2;

    if (isNegative) {

      // Subtract 1.
      long r0 = fast0 - 1;
      long r1;
      if (r0 < 0) {
        adjust0 = r0 + MULTIPLER_LONGWORD_DECIMAL;
        r1 = fast1 - 1;
      } else {
        adjust0 = r0;
        r1 = fast1;
      }
      if (r1 < 0) {
        adjust1 = r1 + MULTIPLER_LONGWORD_DECIMAL;
        adjust2 = fast2 - 1;
      } else {
        adjust1 = r1;
        adjust2 = fast2;
      }
      if (adjust2 < 0) {
        return false;
      }

      // Now multiply by 2 and add 1 sign bit.
      r0 = adjust0 * 2 + 1;
      adjust0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
      r1 = adjust1 * 2 + r0 / MULTIPLER_LONGWORD_DECIMAL;
      adjust1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
      adjust2 = adjust2 * 2 + r1 / MULTIPLER_LONGWORD_DECIMAL;

    } else {

      // Multiply by 2 to make room for 0 sign bit.
      long r0 = fast0 * 2;
      adjust0 = r0 % MULTIPLER_LONGWORD_DECIMAL;
      final long r1 = fast1 * 2 + r0 / MULTIPLER_LONGWORD_DECIMAL;
      adjust1 = r1 % MULTIPLER_LONGWORD_DECIMAL;
      adjust2 = fast2 * 2 + r1 / MULTIPLER_LONGWORD_DECIMAL;
    }

    /*
     * Use common decimal to binary conversion method we share with fastBigIntegerBytes.
     */
    if (!doDecimalToBinaryConversion(
        adjust0,
        adjust1,
        adjust2,
        FAST_HIVE_DECIMAL_TWO_POWER_63_INVERSE,
        SERIALIZATION_UTILS_WRITE_QUOTIENT_INTEGER_WORD_NUM,
        SERIALIZATION_UTILS_WRITE_QUOTIENT_INTEGER_DIGIT_NUM,
        FAST_HIVE_DECIMAL_TWO_POWER_63,
        scratchLongs)) {
      // Overflow.
      return false;
    }

    long lowerWord63 = scratchLongs[0];
    long middleWord63 = scratchLongs[1];
    long highWord63 = scratchLongs[2];

    int wordCount;
    if (highWord63 != 0) {
      wordCount = 3;
    } else if (middleWord63 != 0) {
      wordCount = 2;
    } else {
      wordCount = 1;
    }

    // Write out the first 63 bits worth of data.
    long lowBits = lowerWord63;
    for (int i = 0; i < 9; ++i) {
      // If this is the last byte, leave the high bit off
      if (wordCount == 1 && (lowBits & ~0x7f) == 0) {
        outputStream.write((byte) lowBits);
        return true;
      } else {
        outputStream.write((byte) (0x80 | (lowBits & 0x7f)));
        lowBits >>>= 7;
      }
    }
    if (wordCount <= 1) {
      throw new RuntimeException("Expecting write word count > 1");
    }

    lowBits = middleWord63;
    for (int i = 0; i < 9; ++i) {
      // If this is the last byte, leave the high bit off
      if (wordCount == 2 && (lowBits & ~0x7f) == 0) {
        outputStream.write((byte) lowBits);
        return true;
      } else {
        outputStream.write((byte) (0x80 | (lowBits & 0x7f)));
        lowBits >>>= 7;
      }
    }

    lowBits = highWord63;
    for (int i = 0; i < 9; ++i) {
      // If this is the last byte, leave the high bit off
      if ((lowBits & ~0x7f) == 0) {
        outputStream.write((byte) lowBits);
        return true;
      } else {
        outputStream.write((byte) (0x80 | (lowBits & 0x7f)));
        lowBits >>>= 7;
      }
    }

    // Should not get here.
    throw new RuntimeException("Unexpected");
  }