public static boolean fastSetFromBigIntegerBytesAndScale()

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


  public static boolean fastSetFromBigIntegerBytesAndScale(
      byte[] bytes, int offset, int length, int scale, FastHiveDecimal fastResult) {

    final int bytesLength = bytes.length;

    if (offset < 0 || offset >= bytesLength) {
      return false;
    }
    final int end = offset + length;
    if (end <= offset || end > bytesLength) {
      return false;
    }

    final int startOffset = offset;

    // Roughly based on BigInteger code.

    boolean isNegative = (bytes[offset] < 0);
    if (isNegative) {

      // Find first non-sign (0xff) byte of input.
      while (offset < end) {
        if (bytes[offset] != -1) {
          break;
        }
        offset++;
      }
      if (offset > end) {
        return false;
      }
    } else {

      // Strip leading zeroes -- although there shouldn't be any for a decimal.

      while (offset < end && bytes[offset] == 0) {
        offset++;
      }
      if (offset >= end) {
        // Zero.
        return true;
      }
    }

    long lowerWord56 = 0;
    long middleWord56 = 0;
    long highWord56 = 0;

    int reverseIndex = end;

    long work;
    int shift;

    final int lowestCount = Math.min(reverseIndex - offset, 7);
    shift = 0;
    for (int i = 0; i < lowestCount; i++) {
      work = bytes[--reverseIndex] & 0xFF;
      lowerWord56 |= work << shift;
      shift += 8;
    }

    if (reverseIndex <= offset) {
      if (isNegative) {
        lowerWord56 = ~lowerWord56 & ((1L << shift) - 1);
      }
    } else {

      // Go on to middle word.

      final int middleCount = Math.min(reverseIndex - offset, 7);
      shift = 0;
      for (int i = 0; i < middleCount; i++) {
        work = bytes[--reverseIndex] & 0xFF;
        middleWord56 |= work << shift;
        shift += 8;
      }
      if (reverseIndex <= offset) {
        if (isNegative) {
          lowerWord56 = ~lowerWord56 & LONG_56_BIT_MASK;
          middleWord56 = ~middleWord56 & ((1L << shift) - 1);
        }
      } else {

        // Go on to high word.

        final int highCount = Math.min(reverseIndex - offset, 7);
        shift = 0;
        for (int i = 0; i < highCount; i++) {
          work = bytes[--reverseIndex] & 0xFF;
          highWord56 |= work << shift;
          shift += 8;
        }
        if (isNegative) {
          // We only need to apply negation to all 3 words when there are 3 words, etc.
          lowerWord56 = ~lowerWord56 & LONG_56_BIT_MASK;
          middleWord56 = ~middleWord56 & LONG_56_BIT_MASK;
          highWord56 = ~highWord56 & ((1L << shift) - 1);
        }
      }
    }

    if (!doBinaryToDecimalConversion(
        lowerWord56,
        middleWord56,
        highWord56,
        FAST_HIVE_DECIMAL_TWO_POWER_56,
        FAST_HIVE_DECIMAL_TWO_POWER_112, // 2^(56 + 56)
        fastResult)) {
      // Overflow.  Use slower alternate.
      return doAlternateSetFromBigIntegerBytesAndScale(
          bytes, startOffset, length, scale, fastResult);
    }

    // System.out.println("fastSetFromBigIntegerBytesAndScale fast0 " + fastResult.fast0 + " fast1 "
    // + fastResult.fast1 + " fast2 " + fastResult.fast2);
    if (isNegative) {
      if (!doAddSameScaleSameSign(
          /* resultSignum */ 1,
          fastResult.fast0,
          fastResult.fast1,
          fastResult.fast2,
          1,
          0,
          0,
          fastResult)) {
        // Overflow.  Use slower alternate.
        return doAlternateSetFromBigIntegerBytesAndScale(
            bytes, startOffset, length, scale, fastResult);
      }
    }

    if (fastResult.fast0 == 0 && fastResult.fast1 == 0 && fastResult.fast2 == 0) {
      fastResult.fastSignum = 0;
    } else {
      fastResult.fastSignum = (isNegative ? -1 : 1);
      fastResult.fastScale = scale;
      final int rawPrecision = fastRawPrecision(fastResult);
      fastResult.fastIntegerDigitCount = Math.max(0, rawPrecision - scale);

      /*
       * Just in case we deserialize a decimal with trailing zeroes...
       */
      final int resultTrailingZeroCount =
          fastTrailingDecimalZeroCount(
              fastResult.fast0,
              fastResult.fast1,
              fastResult.fast2,
              fastResult.fastIntegerDigitCount,
              fastResult.fastScale);
      if (resultTrailingZeroCount > 0) {
        doFastScaleDown(fastResult, resultTrailingZeroCount, fastResult);

        fastResult.fastScale -= resultTrailingZeroCount;
      }
    }

    return true;
  }