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");
}