org.apache.kyuubi.jdbc.hive.common.FastHiveDecimal Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kyuubi.jdbc.hive.common;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* FastHiveDecimal is a mutable fast decimal object. It is the base class for both the HiveDecimal
* and HiveDecimalWritable classes. All fast* methods are protected so they cannot be accessed by
* clients of HiveDecimal and HiveDecimalWritable. HiveDecimal ensures it creates new objects when
* the value changes since it provides immutable semantics; HiveDecimalWritable does not create new
* objects since it provides mutable semantics.
*
* The methods in this class are shells that pickup the member variables from FastHiveDecimal
* parameters and pass them as individual parameters to static methods in the FastHiveDecimalImpl
* class that do the real work.
*
*
NOTE: The rationale for fast decimal is in FastHiveDecimalImpl.
*/
public class FastHiveDecimal {
/*
* We use protected for the fields so the FastHiveDecimalImpl class can access them. Other
* classes including HiveDecimal should not access these fields directly.
*/
// See FastHiveDecimalImpl for more details on these fields.
// -1 when negative; 0 when decimal is zero; 1 when positive.
protected int fastSignum;
// Decimal longwords.
protected long fast2;
protected long fast1;
protected long fast0;
// The number of integer digits in the decimal. When the integer portion is zero, this is 0.
protected int fastIntegerDigitCount;
// The scale of the decimal.
protected int fastScale;
// Used for legacy HiveDecimalV1 setScale compatibility for binary / display serialization of
// trailing zeroes (or rounding).
protected int fastSerializationScale;
protected FastHiveDecimal() {
fastReset();
}
protected FastHiveDecimal(FastHiveDecimal fastDec) {
this();
fastSignum = fastDec.fastSignum;
fast0 = fastDec.fast0;
fast1 = fastDec.fast1;
fast2 = fastDec.fast2;
fastIntegerDigitCount = fastDec.fastIntegerDigitCount;
fastScale = fastDec.fastScale;
// Not propagated.
fastSerializationScale = -1;
}
protected FastHiveDecimal(int fastSignum, FastHiveDecimal fastDec) {
this();
this.fastSignum = fastSignum;
fast0 = fastDec.fast0;
fast1 = fastDec.fast1;
fast2 = fastDec.fast2;
fastIntegerDigitCount = fastDec.fastIntegerDigitCount;
fastScale = fastDec.fastScale;
// Not propagated.
fastSerializationScale = -1;
}
protected FastHiveDecimal(
int fastSignum,
long fast0,
long fast1,
long fast2,
int fastIntegerDigitCount,
int fastScale) {
this();
this.fastSignum = fastSignum;
this.fast0 = fast0;
this.fast1 = fast1;
this.fast2 = fast2;
this.fastIntegerDigitCount = fastIntegerDigitCount;
this.fastScale = fastScale;
fastSerializationScale = -1;
}
protected FastHiveDecimal(long longValue) {
this();
FastHiveDecimalImpl.fastSetFromLong(longValue, this);
}
protected FastHiveDecimal(String string) {
this();
FastHiveDecimalImpl.fastSetFromString(string, false, this);
}
protected void fastReset() {
fastSignum = 0;
fast0 = 0;
fast1 = 0;
fast2 = 0;
fastIntegerDigitCount = 0;
fastScale = 0;
fastSerializationScale = -1;
}
protected void fastSet(FastHiveDecimal fastDec) {
fastSignum = fastDec.fastSignum;
fast0 = fastDec.fast0;
fast1 = fastDec.fast1;
fast2 = fastDec.fast2;
fastIntegerDigitCount = fastDec.fastIntegerDigitCount;
fastScale = fastDec.fastScale;
fastSerializationScale = fastDec.fastSerializationScale;
}
protected void fastSet(
int fastSignum,
long fast0,
long fast1,
long fast2,
int fastIntegerDigitCount,
int fastScale) {
this.fastSignum = fastSignum;
this.fast0 = fast0;
this.fast1 = fast1;
this.fast2 = fast2;
this.fastIntegerDigitCount = fastIntegerDigitCount;
this.fastScale = fastScale;
// Not specified.
fastSerializationScale = -1;
}
protected void fastSetSerializationScale(int fastSerializationScale) {
this.fastSerializationScale = fastSerializationScale;
}
protected int fastSerializationScale() {
return fastSerializationScale;
}
protected static final String STRING_ENFORCE_PRECISION_OUT_OF_RANGE =
"Decimal precision out of allowed range [1," + HiveDecimal.MAX_PRECISION + "]";
protected static final String STRING_ENFORCE_SCALE_OUT_OF_RANGE =
"Decimal scale out of allowed range [0," + HiveDecimal.MAX_SCALE + "]";
protected static final String STRING_ENFORCE_SCALE_LESS_THAN_EQUAL_PRECISION =
"Decimal scale must be less than or equal to precision";
protected boolean fastSetFromBigDecimal(BigDecimal bigDecimal, boolean allowRounding) {
return FastHiveDecimalImpl.fastSetFromBigDecimal(bigDecimal, allowRounding, this);
}
protected boolean fastSetFromBigInteger(BigInteger bigInteger) {
return FastHiveDecimalImpl.fastSetFromBigInteger(bigInteger, this);
}
protected boolean fastSetFromBigIntegerAndScale(BigInteger bigInteger, int scale) {
return FastHiveDecimalImpl.fastSetFromBigInteger(bigInteger, scale, this);
}
protected boolean fastSetFromString(String string, boolean trimBlanks) {
byte[] bytes = string.getBytes();
return fastSetFromBytes(bytes, 0, bytes.length, trimBlanks);
}
protected boolean fastSetFromBytes(byte[] bytes, int offset, int length, boolean trimBlanks) {
return FastHiveDecimalImpl.fastSetFromBytes(bytes, offset, length, trimBlanks, this);
}
protected boolean fastSetFromDigitsOnlyBytesAndScale(
boolean isNegative, byte[] bytes, int offset, int length, int scale) {
return FastHiveDecimalImpl.fastSetFromDigitsOnlyBytesAndScale(
isNegative, bytes, offset, length, scale, this);
}
protected void fastSetFromInt(int intValue) {
FastHiveDecimalImpl.fastSetFromInt(intValue, this);
}
protected void fastSetFromLong(long longValue) {
FastHiveDecimalImpl.fastSetFromLong(longValue, this);
}
protected boolean fastSetFromLongAndScale(long longValue, int scale) {
return FastHiveDecimalImpl.fastSetFromLongAndScale(longValue, scale, this);
}
protected boolean fastSetFromFloat(float floatValue) {
return FastHiveDecimalImpl.fastSetFromFloat(floatValue, this);
}
protected boolean fastSetFromDouble(double doubleValue) {
return FastHiveDecimalImpl.fastSetFromDouble(doubleValue, this);
}
protected void fastFractionPortion() {
FastHiveDecimalImpl.fastFractionPortion(fastSignum, fast0, fast1, fast2, fastScale, this);
}
protected void fastIntegerPortion() {
FastHiveDecimalImpl.fastIntegerPortion(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, this);
}
protected static final int FAST_SCRATCH_BUFFER_LEN_SERIALIZATION_UTILS_READ = 8 * 3;
protected boolean fastSerializationUtilsRead(
InputStream inputStream, int scale, byte[] scratchBytes) throws IOException, EOFException {
return FastHiveDecimalImpl.fastSerializationUtilsRead(inputStream, scale, scratchBytes, this);
}
protected boolean fastSetFromBigIntegerBytesAndScale(
byte[] bytes, int offset, int length, int scale) {
return FastHiveDecimalImpl.fastSetFromBigIntegerBytesAndScale(
bytes, offset, length, scale, this);
}
protected static final int SCRATCH_LONGS_LEN_FAST_SERIALIZATION_UTILS_WRITE = 6;
protected boolean fastSerializationUtilsWrite(OutputStream outputStream, long[] scratchLongs)
throws IOException {
return FastHiveDecimalImpl.fastSerializationUtilsWrite(
outputStream,
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
scratchLongs);
}
/*
* Deserializes 64-bit decimals up to the maximum 64-bit precision (18 decimal digits).
*/
protected void fastDeserialize64(long decimalLong, int scale) {
FastHiveDecimalImpl.fastDeserialize64(decimalLong, scale, this);
}
/*
* Serializes decimal64 up to the maximum 64-bit precision (18 decimal digits).
*/
protected long fastSerialize64(int scale) {
return FastHiveDecimalImpl.fastSerialize64(scale, fastSignum, fast1, fast0, fastScale);
}
// The fastBigIntegerBytes method returns 3 56 bit (7 byte) words and a possible sign byte.
// However, the fastBigIntegerBytes can take on trailing zeroes -- so make it larger.
protected static final int FAST_SCRATCH_BUFFER_LEN_BIG_INTEGER_BYTES = 1 + 48;
protected static final int FAST_SCRATCH_LONGS_LEN = 6;
protected int fastBigIntegerBytes(long[] scratchLongs, byte[] buffer) {
return FastHiveDecimalImpl.fastBigIntegerBytes(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastSerializationScale,
scratchLongs,
buffer);
}
protected int fastBigIntegerBytesScaled(
int serializationScale, long[] scratchLongs, byte[] buffer) {
return FastHiveDecimalImpl.fastBigIntegerBytesScaled(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
serializationScale,
scratchLongs,
buffer);
}
protected boolean fastIsByte() {
return FastHiveDecimalImpl.fastIsByte(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected byte fastByteValueClip() {
return FastHiveDecimalImpl.fastByteValueClip(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected boolean fastIsShort() {
return FastHiveDecimalImpl.fastIsShort(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected short fastShortValueClip() {
return FastHiveDecimalImpl.fastShortValueClip(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected boolean fastIsInt() {
return FastHiveDecimalImpl.fastIsInt(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected int fastIntValueClip() {
return FastHiveDecimalImpl.fastIntValueClip(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected boolean fastIsLong() {
return FastHiveDecimalImpl.fastIsLong(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected long fastLongValueClip() {
return FastHiveDecimalImpl.fastLongValueClip(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected float fastFloatValue() {
return FastHiveDecimalImpl.fastFloatValue(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected double fastDoubleValue() {
return FastHiveDecimalImpl.fastDoubleValue(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected BigInteger fastBigIntegerValue() {
return FastHiveDecimalImpl.fastBigIntegerValue(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, fastSerializationScale);
}
protected BigDecimal fastBigDecimalValue() {
return FastHiveDecimalImpl.fastBigDecimalValue(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected int fastScale() {
return fastScale;
}
protected int fastSignum() {
return fastSignum;
}
protected int fastCompareTo(FastHiveDecimal right) {
return FastHiveDecimalImpl.fastCompareTo(
fastSignum,
fast0,
fast1,
fast2,
fastScale,
right.fastSignum,
right.fast0,
right.fast1,
right.fast2,
right.fastScale);
}
protected static int fastCompareTo(FastHiveDecimal left, FastHiveDecimal right) {
return FastHiveDecimalImpl.fastCompareTo(
left.fastSignum,
left.fast0,
left.fast1,
left.fast2,
left.fastScale,
right.fastSignum,
right.fast0,
right.fast1,
right.fast2,
right.fastScale);
}
protected boolean fastEquals(FastHiveDecimal that) {
return FastHiveDecimalImpl.fastEquals(
fastSignum,
fast0,
fast1,
fast2,
fastScale,
that.fastSignum,
that.fast0,
that.fast1,
that.fast2,
that.fastScale);
}
protected void fastAbs() {
if (fastSignum == 0) {
return;
}
fastSignum = 1;
}
protected void fastNegate() {
if (fastSignum == 0) {
return;
}
fastSignum = (fastSignum == 1 ? -1 : 1);
}
protected int fastNewFasterHashCode() {
return FastHiveDecimalImpl.fastNewFasterHashCode(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected int fastHashCode() {
return FastHiveDecimalImpl.fastHashCode(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected int fastIntegerDigitCount() {
return fastIntegerDigitCount;
}
protected int fastSqlPrecision() {
return FastHiveDecimalImpl.fastSqlPrecision(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale);
}
protected int fastRawPrecision() {
return FastHiveDecimalImpl.fastRawPrecision(fastSignum, fast0, fast1, fast2);
}
protected boolean fastScaleByPowerOfTen(int n, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastScaleByPowerOfTen(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, n, fastResult);
}
@SuppressWarnings("deprecation")
protected static String fastRoundingModeToString(int roundingMode) {
String roundingModeString;
switch (roundingMode) {
case BigDecimal.ROUND_DOWN:
roundingModeString = "ROUND_DOWN";
break;
case BigDecimal.ROUND_UP:
roundingModeString = "ROUND_UP";
break;
case BigDecimal.ROUND_FLOOR:
roundingModeString = "ROUND_FLOOR";
break;
case BigDecimal.ROUND_CEILING:
roundingModeString = "ROUND_CEILING";
break;
case BigDecimal.ROUND_HALF_UP:
roundingModeString = "ROUND_HALF_UP";
break;
case BigDecimal.ROUND_HALF_EVEN:
roundingModeString = "ROUND_HALF_EVEN";
break;
default:
roundingModeString = "Unknown";
}
return roundingModeString + " (" + roundingMode + ")";
}
protected boolean fastRound(int newScale, int roundingMode, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastRound(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
newScale,
roundingMode,
fastResult);
}
protected boolean isAllZeroesBelow(int power) {
return FastHiveDecimalImpl.isAllZeroesBelow(fastSignum, fast0, fast1, fast2, power);
}
protected boolean fastEnforcePrecisionScale(int maxPrecision, int maxScale) {
if (maxPrecision <= 0 || maxPrecision > HiveDecimal.MAX_PRECISION) {
return false;
}
if (maxScale < 0 || maxScale > HiveDecimal.MAX_SCALE) {
return false;
}
/*
if (!fastIsValid()) {
fastRaiseInvalidException();
}
*/
FastCheckPrecisionScaleStatus status =
FastHiveDecimalImpl.fastCheckPrecisionScale(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
maxPrecision,
maxScale);
switch (status) {
case NO_CHANGE:
return true;
case OVERFLOW:
return false;
case UPDATE_SCALE_DOWN:
{
if (!FastHiveDecimalImpl.fastUpdatePrecisionScale(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
maxPrecision,
maxScale,
status,
this)) {
return false;
}
/*
if (!fastIsValid()) {
fastRaiseInvalidException();
}
*/
return true;
}
default:
throw new RuntimeException(
"Unknown fast decimal check precision and scale status " + status);
}
}
protected FastCheckPrecisionScaleStatus fastCheckPrecisionScale(int maxPrecision, int maxScale) {
return FastHiveDecimalImpl.fastCheckPrecisionScale(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, maxPrecision, maxScale);
}
protected static enum FastCheckPrecisionScaleStatus {
NO_CHANGE,
OVERFLOW,
UPDATE_SCALE_DOWN;
}
protected boolean fastUpdatePrecisionScale(
int maxPrecision,
int maxScale,
FastCheckPrecisionScaleStatus status,
FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastUpdatePrecisionScale(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
maxPrecision,
maxScale,
status,
fastResult);
}
protected boolean fastAdd(FastHiveDecimal fastRight, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastAdd(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastRight.fastSignum,
fastRight.fast0,
fastRight.fast1,
fastRight.fast2,
fastRight.fastIntegerDigitCount,
fastRight.fastScale,
fastResult);
}
protected boolean fastSubtract(FastHiveDecimal fastRight, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastSubtract(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastRight.fastSignum,
fastRight.fast0,
fastRight.fast1,
fastRight.fast2,
fastRight.fastIntegerDigitCount,
fastRight.fastScale,
fastResult);
}
protected boolean fastMultiply(FastHiveDecimal fastRight, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastMultiply(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastRight.fastSignum,
fastRight.fast0,
fastRight.fast1,
fastRight.fast2,
fastRight.fastIntegerDigitCount,
fastRight.fastScale,
fastResult);
}
protected boolean fastRemainder(FastHiveDecimal fastRight, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastRemainder(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastRight.fastSignum,
fastRight.fast0,
fastRight.fast1,
fastRight.fast2,
fastRight.fastIntegerDigitCount,
fastRight.fastScale,
fastResult);
}
protected boolean fastDivide(FastHiveDecimal fastRight, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastDivide(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
fastRight.fastSignum,
fastRight.fast0,
fastRight.fast1,
fastRight.fast2,
fastRight.fastIntegerDigitCount,
fastRight.fastScale,
fastResult);
}
protected boolean fastPow(int exponent, FastHiveDecimal fastResult) {
return FastHiveDecimalImpl.fastPow(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, exponent, fastResult);
}
protected String fastToString(byte[] scratchBuffer) {
return FastHiveDecimalImpl.fastToString(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, -1, scratchBuffer);
}
protected String fastToString() {
return FastHiveDecimalImpl.fastToString(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, -1);
}
protected String fastToFormatString(int formatScale) {
return FastHiveDecimalImpl.fastToFormatString(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, formatScale);
}
protected String fastToFormatString(int formatScale, byte[] scratchBuffer) {
return FastHiveDecimalImpl.fastToFormatString(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
formatScale,
scratchBuffer);
}
protected String fastToDigitsOnlyString() {
return FastHiveDecimalImpl.fastToDigitsOnlyString(fast0, fast1, fast2, fastIntegerDigitCount);
}
// Sign, zero, dot, 2 * digits (to support toFormatString which can add a lot of trailing zeroes).
protected static final int FAST_SCRATCH_BUFFER_LEN_TO_BYTES =
1 + 1 + 1 + 2 * FastHiveDecimalImpl.MAX_DECIMAL_DIGITS;
protected int fastToBytes(byte[] scratchBuffer) {
return FastHiveDecimalImpl.fastToBytes(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, -1, scratchBuffer);
}
protected int fastToFormatBytes(int formatScale, byte[] scratchBuffer) {
return FastHiveDecimalImpl.fastToFormatBytes(
fastSignum,
fast0,
fast1,
fast2,
fastIntegerDigitCount,
fastScale,
formatScale,
scratchBuffer);
}
protected int fastToDigitsOnlyBytes(byte[] scratchBuffer) {
return FastHiveDecimalImpl.fastToDigitsOnlyBytes(
fast0, fast1, fast2, fastIntegerDigitCount, scratchBuffer);
}
@Override
public String toString() {
return FastHiveDecimalImpl.fastToString(
fastSignum, fast0, fast1, fast2, fastIntegerDigitCount, fastScale, -1);
}
protected boolean fastIsValid() {
return FastHiveDecimalImpl.fastIsValid(this);
}
protected void fastRaiseInvalidException() {
FastHiveDecimalImpl.fastRaiseInvalidException(this);
}
protected void fastRaiseInvalidException(String parameters) {
FastHiveDecimalImpl.fastRaiseInvalidException(this, parameters);
}
}