fix decimal from str and decimal to str

This commit is contained in:
wangjiaming0909 2025-01-08 16:24:20 +08:00
parent 765ca45bf2
commit 9634a3867d
3 changed files with 253 additions and 194 deletions

View File

@ -251,7 +251,7 @@ struct SValue {
union {
int64_t val;
struct {
uint8_t *pData; // TODO wjm free or no free???
uint8_t *pData; // TODO wjm free or no free??? use single interface to destroy pData.
uint32_t nData;
};
};

View File

@ -24,13 +24,18 @@ extern "C" {
#include "ttypes.h"
typedef struct SDataType SDataType;
typedef struct SValue SValue;
typedef void DecimalType;
typedef struct Decimal64 {
DecimalWord words[1];
DecimalWord words[1]; // do not touch it directly, use DECIMAL64_GET_VALUE MACRO
} Decimal64;
#define DECIMAL64_GET_VALUE(pDec) (int64_t)((pDec)->words[0])
#define DECIMAL64_SET_VALUE(pDec, val) (*(int64_t*)((pDec)->words)) = (int64_t)(val)
#define DECIMAL64_CLONE(pDst, pFrom) ((Decimal64*)(pDst))->words[0] = ((Decimal64*)(pFrom))->words[0]
typedef struct Decimal128 {
DecimalWord words[2];
DecimalWord words[2]; // do not touch it directly, use DECIMAL128_HIGH_WORD/DECIMAL128_LOW_WORD
} Decimal128;
#define Decimal Decimal128
@ -38,7 +43,7 @@ typedef struct Decimal128 {
#define makeDecimal makeDecimal128
// TODO wjm check if we need to expose these functions in decimal.h
void makeDecimal64(Decimal64* pDec64, DecimalWord w);
void makeDecimal64(Decimal64* pDec64, int64_t w);
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low);
#define DECIMAL_WORD_NUM(TYPE) sizeof(TYPE) / sizeof(DecimalWord)
@ -53,7 +58,7 @@ int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision,
int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal);
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal);
int32_t decimalToStr(const DecimalWord* pDec, int8_t type, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen);
int32_t decimalToStr(const DecimalType* pDec, int8_t type, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen);
int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOperatorType opType, SDataType* pOutType);
int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pRightT, const SDataType* pOutT,
@ -62,17 +67,17 @@ int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* p
// TODO wjm change rightWordNum to DecimalType??
typedef struct SDecimalOps {
void (*negate)(DecimalWord* pWord);
void (*abs)(DecimalWord* pWord);
void (*add)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
void (*subtract)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
void (*multiply)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
void (*divide)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum, DecimalWord* pRemainder);
void (*mod)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
bool (*lt)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
bool (*gt)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
bool (*eq)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
int32_t (*toStr)(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
void (*negate)(DecimalType* pWord);
void (*abs)(DecimalType* pWord);
void (*add)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
void (*subtract)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
void (*multiply)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
void (*divide)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, DecimalType* pRemainder);
void (*mod)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
bool (*lt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
bool (*gt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
bool (*eq)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
int32_t (*toStr)(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
} SDecimalOps;
SDecimalOps* getDecimalOps(int8_t dataType);

View File

@ -36,7 +36,7 @@ typedef struct DecimalVar {
uint8_t scale;
int32_t exponent;
int8_t sign;
DecimalWord* words;
DecimalType* pDec;
} DecimalVar;
static uint8_t maxPrecision(DecimalInternalType type) {
@ -167,9 +167,9 @@ static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* resul
}
DecimalWord ten = 10, digit = str[pos] - '0';
while (places-- > 0) {
pOps->multiply(result->words, &ten, 1);
pOps->multiply(result->pDec, &ten, 1);
}
pOps->add(result->words, &digit, 1);
pOps->add(result->pDec, &digit, 1);
places = 0;
break;
}
@ -183,21 +183,20 @@ static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* resul
}
}
if (result->sign < 0) {
DecimalWord sign = (DecimalWord)result->sign;
pOps->multiply(result->words, &sign, 1);
pOps->negate(result->pDec);
}
return code;
}
int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal) {
VALUE_SET_TRIVIAL_DATUM(pVal, dec->words[0]);
VALUE_SET_TRIVIAL_DATUM(pVal, DECIMAL64_GET_VALUE(dec));
return TSDB_CODE_SUCCESS;
}
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal) {
void* pV = taosMemCalloc(1, sizeof(Decimal128));
if (!pV) return terrno;
memcpy(pV, dec->words, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord));
memcpy(pV, dec, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord));
valueSetDatum(pVal, TSDB_DATA_TYPE_DECIMAL, pV, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord));
return TSDB_CODE_SUCCESS;
}
@ -225,18 +224,20 @@ static Decimal64 SCALE_MULTIPLIER_64[19] = {1LL,
#define DECIMAL64_ONE SCALE_MULTIPLIER_64[0]
#define DECIMAL64_GET_MAX(precision, pMax) \
do { \
*(pMax) = SCALE_MULTIPLIER_64[precision]; \
decimal64Subtract((pMax)->words, DECIMAL64_ONE.words, DECIMAL_WORD_NUM(Decimal64)); \
#define DECIMAL64_GET_MAX(precision, pMax) \
do { \
*(pMax) = SCALE_MULTIPLIER_64[precision]; \
decimal64Subtract(pMax, &DECIMAL64_ONE, DECIMAL_WORD_NUM(Decimal64)); \
} while (0)
static int32_t decimalGetWhole(const DecimalWord* pDec, DecimalInternalType type, int8_t scale, DecimalWord* pWhole) {
#define DECIMAL64_SIGN(pDec) (1 | (DECIMAL64_GET_VALUE(pDec) >> 63))
static int32_t decimalGetWhole(const DecimalType* pDec, DecimalInternalType type, int8_t scale, DecimalType* pWhole) {
SDecimalOps* pOps = getDecimalOpsImp(type);
if (type == DECIMAL_64) {
pWhole[0] = *pDec;
DECIMAL64_CLONE(pWhole, pDec);
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
pOps->divide(pWhole, scaleMul.words, 1, NULL);
pOps->divide(pWhole, &scaleMul, 1, NULL);
if (TSDB_CODE_SUCCESS != 0) {
// TODO wjm
}
@ -244,55 +245,55 @@ static int32_t decimalGetWhole(const DecimalWord* pDec, DecimalInternalType type
} else {
memcpy(pWhole, pDec, DECIMAL_GET_WORD_NUM(type) * sizeof(DecimalWord));
// TODO wjm
// pOps.divide(pWhole->words, )
// pOps.divide(pWhole, )
}
return 0;
}
static int32_t decimalGetFrac(const DecimalWord* pDec, DecimalInternalType type, int8_t scale, DecimalWord* pFrac) {
static int32_t decimalGetFrac(const DecimalType* pDec, DecimalInternalType type, int8_t scale, DecimalType* pFrac) {
SDecimalOps* pOps = getDecimalOpsImp(type);
if (type == DECIMAL_64) {
pFrac[0] = *pDec;
DECIMAL64_CLONE(pFrac, pDec);
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
pOps->mod(pFrac, scaleMul.words, 1);
pOps->mod(pFrac, &scaleMul, 1);
pOps->abs(pFrac);
} else {
}
return 0;
}
static void decimal64Negate(DecimalWord* pInt);
static void decimal64Abs(DecimalWord* pInt);
static void decimal64Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal64Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal64Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal64divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
DecimalWord* pRemainder);
static void decimal64Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal64Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal64Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal64Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static int32_t decimal64ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
static void decimal64Negate(DecimalType* pInt);
static void decimal64Abs(DecimalType* pInt);
static void decimal64Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal64Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal64Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal64divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
DecimalType* pRemainder);
static void decimal64Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal64Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal64Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal64Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
static void decimal128Negate(DecimalWord* pInt);
static void decimal128Abs(DecimalWord* pWord);
static void decimal128Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal128Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal128Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
DecimalWord* pRemainder);
static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal128Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static bool decimal128Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
static void decimal128Negate(DecimalType* pInt);
static void decimal128Abs(DecimalType* pWord);
static void decimal128Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal128Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal128Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
DecimalType* pRemainder);
static void decimal128Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal128Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal128Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static bool decimal128Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
static int32_t decimal128ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale);
SDecimalOps decimal64Ops = {decimal64Negate, decimal64Abs, decimal64Add, decimal64Subtract,
decimal64Multiply, decimal64divide, decimal64Mod, decimal64Lt,
decimal64Gt, decimal64Eq, decimal64ToStr};
SDecimalOps decimal128Ops = {decimal128Negate, decimal128Abs, decimal128Add, decimal128Subtract,
decimal128Multiply, decimal128divide, decimal128Mod, decimal128Lt,
decimal128Multiply, decimal128Divide, decimal128Mod, decimal128Lt,
decimal128Gt, decimal128Eq, decimal128ToStr};
static SDecimalOps* getDecimalOpsImp(DecimalInternalType t) {
@ -307,116 +308,167 @@ static SDecimalOps* getDecimalOpsImp(DecimalInternalType t) {
}
SDecimalOps* getDecimalOps(int8_t dataType) { return getDecimalOpsImp(DECIMAL_GET_INTERNAL_TYPE(dataType)); }
void makeDecimal64(Decimal64* pDec64, DecimalWord w) { pDec64->words[0] = w; }
void makeDecimal64(Decimal64* pDec64, int64_t w) { DECIMAL64_SET_VALUE(pDec64, w); }
// TODO wjm handle overflow problem of DecimalWord
void decimal64Negate(DecimalWord* pInt) { *pInt = -(int64_t)(*pInt); }
void decimal64Abs(DecimalWord* pInt) { *pInt = TABS(*pInt); }
void decimal64Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft += *pRight; }
void decimal64Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft -= *pRight; }
void decimal64Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft *= *pRight; }
void decimal64divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum, DecimalWord* pRemainder) {
*pLeft /= *pRight;
if (pRemainder) *pRemainder = *pLeft % *pRight;
// it's impossible that pDec == INT64_MIN, only 18 digits can be accepted.
void decimal64Negate(DecimalType* pInt) {
Decimal64* pDec = pInt;
DECIMAL64_SET_VALUE(pDec, -DECIMAL64_GET_VALUE(pDec));
}
void decimal64Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft %= *pRight; }
bool decimal64Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { return *pLeft < *pRight; }
bool decimal64Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { return *pLeft > *pRight; }
bool decimal64Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
return *pLeft == *pRight;
void decimal64Abs(DecimalType* pInt) {
Decimal64* pDec = pInt;
DECIMAL64_SET_VALUE(pDec, TABS(DECIMAL64_GET_VALUE(pDec)));
}
int32_t decimal64ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen) {
void decimal64Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal64* pDecL = pLeft;
const Decimal64* pDecR = pRight;
DECIMAL64_SET_VALUE(pDecL, SAFE_INT64_ADD(DECIMAL64_GET_VALUE(pDecL), DECIMAL64_GET_VALUE(pDecR)));
}
void decimal64Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal64* pDecL = pLeft;
const Decimal64* pDecR = pRight;
DECIMAL64_SET_VALUE(pDecL, SAFE_INT64_SUBTRACT(DECIMAL64_GET_VALUE(pDecL), DECIMAL64_GET_VALUE(pDecR)));
}
void decimal64Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal64* pDecL = pLeft;
Decimal64 decR = *((Decimal64*)pRight);
bool sign = DECIMAL64_SIGN(pDecL) != DECIMAL64_SIGN(&decR);
decimal64Abs(pLeft);
decimal64Abs(&decR);
uint64_t x = DECIMAL64_GET_VALUE(pDecL), y = DECIMAL64_GET_VALUE(&decR);
x *= y;
DECIMAL64_SET_VALUE(pDecL, x);
if (sign) decimal64Negate(pDecL);
}
void decimal64divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, DecimalType* pRemainder) {
Decimal64* pDecL = pLeft;
Decimal64 decR = *((Decimal64*)pRight);
Decimal64* pDecRemainder = pRemainder;
bool sign = DECIMAL64_SIGN(pDecL) != DECIMAL64_SIGN(&decR);
decimal64Abs(pDecL);
decimal64Abs(&decR);
uint64_t x = DECIMAL64_GET_VALUE(pDecL), y = DECIMAL64_GET_VALUE(&decR);
uint64_t z = x;
x /= y;
DECIMAL64_SET_VALUE(pDecL, x);
if (sign) decimal64Negate(pDecL);
if (pDecRemainder) {
z %= y;
DECIMAL64_SET_VALUE(pDecRemainder, z);
}
}
void decimal64Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal64 remainder = {0};
Decimal64* pDec = pLeft;
decimal64divide(pLeft, pRight, rightWordNum, &remainder);
DECIMAL64_SET_VALUE(pDec, DECIMAL64_GET_VALUE(&remainder));
}
bool decimal64Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
const Decimal64 *pDecL = pLeft, *pDecR = pRight;
return DECIMAL64_GET_VALUE(pDecL) < DECIMAL64_GET_VALUE(pDecR);
}
bool decimal64Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
return DECIMAL64_GET_VALUE((Decimal64*)pLeft) > DECIMAL64_GET_VALUE((Decimal64*)pRight);
}
bool decimal64Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
return DECIMAL64_GET_VALUE((Decimal64*)pLeft) == DECIMAL64_GET_VALUE(((Decimal64*)pRight));
}
int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen) {
char format[16] = "\%0";
snprintf(format+2, 14, "%"PRIu8 PRIu64, scale);
return snprintf(pBuf, bufLen, *pInt != 0 ? format : "%"PRIu64, *pInt);
snprintf(format + 2, 14, "%" PRIu8 PRIu64, scale);
return snprintf(pBuf, bufLen, DECIMAL64_GET_VALUE((Decimal64*)pInt) != 0 ? format : "%" PRIu64,
DECIMAL64_GET_VALUE((Decimal64*)pInt));
}
// TODO wjm handle endian problem
#define DECIMAL128_LOW_WORDS(pDec) (uint64_t)((pDec)->words[0])
#define DECIMAL128_HIGH_WORDS(pDec) (int64_t)((pDec)->words[1])
#define DECIMAL128_LOW_WORD(pDec) (uint64_t)((pDec)->words[0])
#define DECIMAL128_SET_LOW_WORD(pDec, val) (pDec)->words[0] = val
#define DECIMAL128_HIGH_WORD(pDec) (int64_t)((pDec)->words[1])
#define DECIMAL128_SET_HIGH_WORD(pDec, val) *(int64_t*)((pDec)->words + 1) = val
// return 1 if positive or zero, else return -1
#define DECIMAL128_SIGN(pDec) (1 | (DECIMAL128_HIGH_WORDS(pDec) >> 63))
#define DECIMAL128_SIGN(pDec) (1 | (DECIMAL128_HIGH_WORD(pDec) >> 63))
// TODO wjm handle endian problem
#define DEFINE_DECIMAL128(lo, hi) {lo, hi}
static Decimal128 SCALE_MULTIPLIER_128[38 + 1] = {
DEFINE_DECIMAL128( 1LL,0),
DEFINE_DECIMAL128( 10LL,0),
DEFINE_DECIMAL128( 100LL,0),
DEFINE_DECIMAL128( 1000LL,0),
DEFINE_DECIMAL128( 10000LL,0),
DEFINE_DECIMAL128( 100000LL,0),
DEFINE_DECIMAL128( 1000000LL,0),
DEFINE_DECIMAL128( 10000000LL,0),
DEFINE_DECIMAL128( 100000000LL,0),
DEFINE_DECIMAL128( 1000000000LL,0),
DEFINE_DECIMAL128( 10000000000LL,0),
DEFINE_DECIMAL128( 100000000000LL,0),
DEFINE_DECIMAL128( 1000000000000LL,0),
DEFINE_DECIMAL128( 10000000000000LL,0),
DEFINE_DECIMAL128( 100000000000000LL,0),
DEFINE_DECIMAL128( 1000000000000000LL,0),
DEFINE_DECIMAL128( 10000000000000000LL,0),
DEFINE_DECIMAL128( 100000000000000000LL,0),
DEFINE_DECIMAL128( 1000000000000000000LL,0),
DEFINE_DECIMAL128( 10000000000000000000ULL,0LL),
DEFINE_DECIMAL128( 7766279631452241920ULL,5LL),
DEFINE_DECIMAL128( 3875820019684212736ULL,54LL),
DEFINE_DECIMAL128( 1864712049423024128ULL,542LL),
DEFINE_DECIMAL128( 200376420520689664ULL,5421LL),
DEFINE_DECIMAL128( 2003764205206896640ULL,54210LL),
DEFINE_DECIMAL128( 1590897978359414784ULL,542101LL),
DEFINE_DECIMAL128( 15908979783594147840ULL,5421010LL),
DEFINE_DECIMAL128( 11515845246265065472ULL,54210108LL),
DEFINE_DECIMAL128( 4477988020393345024ULL,542101086LL),
DEFINE_DECIMAL128( 7886392056514347008ULL,5421010862LL),
DEFINE_DECIMAL128( 5076944270305263616ULL,54210108624LL),
DEFINE_DECIMAL128( 13875954555633532928ULL,542101086242LL),
DEFINE_DECIMAL128( 9632337040368467968ULL,5421010862427LL),
DEFINE_DECIMAL128( 4089650035136921600ULL,54210108624275LL),
DEFINE_DECIMAL128( 4003012203950112768ULL,542101086242752LL),
DEFINE_DECIMAL128( 3136633892082024448ULL,5421010862427522LL),
DEFINE_DECIMAL128( 12919594847110692864ULL,54210108624275221LL),
DEFINE_DECIMAL128( 68739955140067328ULL,542101086242752217LL),
DEFINE_DECIMAL128( 687399551400673280ULL,5421010862427522170LL),
DEFINE_DECIMAL128(1LL, 0),
DEFINE_DECIMAL128(10LL, 0),
DEFINE_DECIMAL128(100LL, 0),
DEFINE_DECIMAL128(1000LL, 0),
DEFINE_DECIMAL128(10000LL, 0),
DEFINE_DECIMAL128(100000LL, 0),
DEFINE_DECIMAL128(1000000LL, 0),
DEFINE_DECIMAL128(10000000LL, 0),
DEFINE_DECIMAL128(100000000LL, 0),
DEFINE_DECIMAL128(1000000000LL, 0),
DEFINE_DECIMAL128(10000000000LL, 0),
DEFINE_DECIMAL128(100000000000LL, 0),
DEFINE_DECIMAL128(1000000000000LL, 0),
DEFINE_DECIMAL128(10000000000000LL, 0),
DEFINE_DECIMAL128(100000000000000LL, 0),
DEFINE_DECIMAL128(1000000000000000LL, 0),
DEFINE_DECIMAL128(10000000000000000LL, 0),
DEFINE_DECIMAL128(100000000000000000LL, 0),
DEFINE_DECIMAL128(1000000000000000000LL, 0),
DEFINE_DECIMAL128(10000000000000000000ULL, 0LL),
DEFINE_DECIMAL128(7766279631452241920ULL, 5LL),
DEFINE_DECIMAL128(3875820019684212736ULL, 54LL),
DEFINE_DECIMAL128(1864712049423024128ULL, 542LL),
DEFINE_DECIMAL128(200376420520689664ULL, 5421LL),
DEFINE_DECIMAL128(2003764205206896640ULL, 54210LL),
DEFINE_DECIMAL128(1590897978359414784ULL, 542101LL),
DEFINE_DECIMAL128(15908979783594147840ULL, 5421010LL),
DEFINE_DECIMAL128(11515845246265065472ULL, 54210108LL),
DEFINE_DECIMAL128(4477988020393345024ULL, 542101086LL),
DEFINE_DECIMAL128(7886392056514347008ULL, 5421010862LL),
DEFINE_DECIMAL128(5076944270305263616ULL, 54210108624LL),
DEFINE_DECIMAL128(13875954555633532928ULL, 542101086242LL),
DEFINE_DECIMAL128(9632337040368467968ULL, 5421010862427LL),
DEFINE_DECIMAL128(4089650035136921600ULL, 54210108624275LL),
DEFINE_DECIMAL128(4003012203950112768ULL, 542101086242752LL),
DEFINE_DECIMAL128(3136633892082024448ULL, 5421010862427522LL),
DEFINE_DECIMAL128(12919594847110692864ULL, 54210108624275221LL),
DEFINE_DECIMAL128(68739955140067328ULL, 542101086242752217LL),
DEFINE_DECIMAL128(687399551400673280ULL, 5421010862427522170LL),
};
#define DECIMAL128_ONE SCALE_MULTIPLIER_128[0]
#define DECIMAL128_TEN SCALE_MULTIPLIER_128[1]
#define DECIMAL128_GET_MAX(precision, pMax) \
do { \
*(pMax) = SCALE_MULTIPLIER_128[precision]; \
decimal128Subtract((pMax)->words, DECIMAL128_ONE.words, DECIMAL_WORD_NUM(Decimal128)); \
#define DECIMAL128_GET_MAX(precision, pMax) \
do { \
*(pMax) = SCALE_MULTIPLIER_128[precision]; \
decimal128Subtract(pMax, &DECIMAL128_ONE, DECIMAL_WORD_NUM(Decimal128)); \
} while (0)
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low) {
// TODO wjm handle endian problem
pDec128->words[1] = hi;
pDec128->words[0] = low;
DECIMAL128_SET_HIGH_WORD(pDec128, hi);
DECIMAL128_SET_LOW_WORD(pDec128, low);
}
static void makeDecimal128FromDecimal64(Decimal128* pTarget, Decimal64 decimal64) {
DecimalWord zero = 0, sign = 0;
if (decimal64Lt(decimal64.words, &zero, 1)) {
decimal64Negate(decimal64.words);
sign = -1;
bool negative = false;
if (DECIMAL64_SIGN(&decimal64) == -1) {
decimal64Negate(&decimal64);
negative = true;
}
makeDecimal128(pTarget, sign, (uint64_t)decimal64.words[0]);
makeDecimal128(pTarget, 0, DECIMAL64_GET_VALUE(&decimal64));
if (negative) decimal128Negate(pTarget);
}
static void decimal128Negate(DecimalWord* pWord) {
static void decimal128Negate(DecimalType* pWord) {
Decimal128* pDec = (Decimal128*)pWord;
uint64_t lo = ~DECIMAL128_LOW_WORDS(pDec) + 1;
int64_t hi = ~DECIMAL128_HIGH_WORDS(pDec);
uint64_t lo = ~DECIMAL128_LOW_WORD(pDec) + 1;
int64_t hi = ~DECIMAL128_HIGH_WORD(pDec);
if (lo == 0) hi = SAFE_INT64_ADD(hi, 1);
makeDecimal128(pDec, hi, lo);
}
static void decimal128Abs(DecimalWord* pWord) {
DecimalWord zero = 0;
if (decimal128Lt(pWord, &zero, 1)) {
static void decimal128Abs(DecimalType* pWord) {
if (DECIMAL128_SIGN((Decimal128*)pWord) == -1) {
decimal128Negate(pWord);
}
}
@ -425,64 +477,64 @@ static void decimal128Abs(DecimalWord* pWord) {
#define DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pTarget, rightDec, pWord) \
if (rightWordNum != WORD_NUM(Decimal128)) { \
Decimal64 d64 = {0}; \
makeDecimal64(&d64, *pWord); \
makeDecimal64(&d64, *(int64_t*)pWord); \
makeDecimal128FromDecimal64(&rightDec, d64); \
pTarget = &rightDec; \
}
static void decimal128Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static void decimal128Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
int64_t hi = SAFE_INT64_ADD(DECIMAL128_HIGH_WORDS(pLeftDec), DECIMAL128_HIGH_WORDS(pRightDec));
uint64_t lo = DECIMAL128_LOW_WORDS(pLeftDec) + DECIMAL128_LOW_WORDS(pRightDec);
hi = SAFE_INT64_ADD(hi, lo < DECIMAL128_LOW_WORDS(pLeftDec));
int64_t hi = SAFE_INT64_ADD(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec));
uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) + DECIMAL128_LOW_WORD(pRightDec);
hi = SAFE_INT64_ADD(hi, lo < DECIMAL128_LOW_WORD(pLeftDec));
makeDecimal128(pLeftDec, hi, lo);
}
static void decimal128Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static void decimal128Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
int64_t hi = SAFE_INT64_SUBTRACT(DECIMAL128_HIGH_WORDS(pLeftDec), DECIMAL128_HIGH_WORDS(pRightDec));
uint64_t lo = DECIMAL128_LOW_WORDS(pLeftDec) - DECIMAL128_LOW_WORDS(pRightDec);
hi = SAFE_INT64_SUBTRACT(hi, lo > DECIMAL128_LOW_WORDS(pLeftDec));
int64_t hi = SAFE_INT64_SUBTRACT(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec));
uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) - DECIMAL128_LOW_WORD(pRightDec);
hi = SAFE_INT64_SUBTRACT(hi, lo > DECIMAL128_LOW_WORD(pLeftDec));
makeDecimal128(pLeftDec, hi, lo);
}
static void decimal128Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static void decimal128Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec);
Decimal128 x = *pLeftDec, y = *pRightDec;
decimal128Abs(x.words);
decimal128Abs(y.words);
decimal128Abs(&x);
decimal128Abs(&y);
UInt128 res = {0}, tmp = {0};
makeUInt128(&res, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
makeUInt128(&tmp, DECIMAL128_HIGH_WORDS(&y), DECIMAL128_LOW_WORDS(&y));
makeUInt128(&res, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
makeUInt128(&tmp, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y));
uInt128Multiply(&res, &tmp);
makeDecimal128(pLeftDec, uInt128Hi(&res), uInt128Lo(&res));
if (negate) decimal128Negate(pLeftDec->words);
if (negate) decimal128Negate(pLeftDec);
}
static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static bool decimal128Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
// TODO wjm pRightDec use const
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
return DECIMAL128_HIGH_WORDS(pLeftDec) < DECIMAL128_HIGH_WORDS(pRightDec) ||
(DECIMAL128_HIGH_WORDS(pLeftDec) == DECIMAL128_HIGH_WORDS(pRightDec) &&
DECIMAL128_LOW_WORDS(pLeftDec) < DECIMAL128_LOW_WORDS(pRightDec));
return DECIMAL128_HIGH_WORD(pLeftDec) < DECIMAL128_HIGH_WORD(pRightDec) ||
(DECIMAL128_HIGH_WORD(pLeftDec) == DECIMAL128_HIGH_WORD(pRightDec) &&
DECIMAL128_LOW_WORD(pLeftDec) < DECIMAL128_LOW_WORD(pRightDec));
}
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
DecimalWord* pRemainder) {
static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
DecimalType* pRemainder) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, *pRemainderDec = (Decimal128*)pRemainder;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
@ -490,36 +542,37 @@ static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint
bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec);
UInt128 a = {0}, b = {0}, c = {0}, d = {0};
Decimal128 x = *pLeftDec, y = *pRightDec;
decimal128Abs(x.words);
decimal128Abs(y.words);
makeUInt128(&a, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
makeUInt128(&d, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
makeUInt128(&b, DECIMAL128_HIGH_WORDS(&y), DECIMAL128_LOW_WORDS(&y));
decimal128Abs(&x);
decimal128Abs(&y);
makeUInt128(&a, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
makeUInt128(&d, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
makeUInt128(&b, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y));
// TODO wjm refine the interface, so that here do not need to copy a
uInt128Divide(&a, &b);
uInt128Mod(&d, &b);
makeDecimal128(pLeftDec, uInt128Hi(&a), uInt128Lo(&a));
if (pRemainder) makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d));
if (negate) decimal128Negate(pLeftDec->words);
if (DECIMAL128_SIGN(pLeftDec) == -1 && pRemainder) decimal128Negate(pRemainderDec->words);
if (negate) decimal128Negate(pLeftDec);
if (DECIMAL128_SIGN(pLeftDec) == -1 && pRemainder) decimal128Negate(pRemainderDec);
}
static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {}
static void decimal128Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {}
static bool decimal128Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static bool decimal128Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
return decimal128Lt(pRightDec->words, pLeftDec->words, WORD_NUM(Decimal128));
return decimal128Lt(pRightDec, pLeftDec, WORD_NUM(Decimal128));
}
static bool decimal128Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
static bool decimal128Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) {
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
Decimal128 right = {0};
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
return pLeftDec->words == pRightDec->words;
return DECIMAL128_HIGH_WORD(pLeftDec) == DECIMAL128_HIGH_WORD(pRightDec) &&
DECIMAL128_LOW_WORD(pLeftDec) == DECIMAL128_LOW_WORD(pRightDec);
}
static void extractDecimal128Digits(const Decimal128* pDec, uint64_t* digits, int32_t* digitNum) {
@ -528,7 +581,7 @@ static void extractDecimal128Digits(const Decimal128* pDec, uint64_t* digits, in
UInt128 a = {0};
UInt128 b = {0};
*digitNum = 0;
makeUInt128(&a, DECIMAL128_HIGH_WORDS(pDec), DECIMAL128_LOW_WORDS(pDec));
makeUInt128(&a, DECIMAL128_HIGH_WORD(pDec), DECIMAL128_LOW_WORD(pDec));
while (!uInt128Eq(&a, &uInt128Zero)) {
uint64_t hi = a >> 64;
uint64_t lo = a;
@ -547,21 +600,23 @@ static void extractDecimal128Digits(const Decimal128* pDec, uint64_t* digits, in
}
// TODO wjm checkBuflen
static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen) {
static int32_t decimal128ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen) {
const Decimal128* pDec = (const Decimal128*)pInt;
bool negative = DECIMAL128_SIGN(pDec) < 0;
uint64_t segments[3] = {0};
int32_t digitNum = 0;
char buf[64] = {0};
int32_t len = 0;
if (negative) {
Decimal128 copy = {0};
makeDecimal128(&copy, DECIMAL128_HIGH_WORDS(pDec), DECIMAL128_LOW_WORDS(pDec));
decimal128Abs(copy.words);
makeDecimal128(&copy, DECIMAL128_HIGH_WORD(pDec), DECIMAL128_LOW_WORD(pDec));
decimal128Abs(&copy);
extractDecimal128Digits(&copy, segments, &digitNum);
buf[0] = '-';
len = 1;
} else {
extractDecimal128Digits(pDec, segments, &digitNum);
}
int32_t len = 0;
for (int32_t i = digitNum - 1; i >= 0; --i) {
// TODO wjm test 0.0000000000000000000000000000000001
len += snprintf(buf + len, 64 - len, i == digitNum - 1 ? "%" PRIu64 : "%018" PRIu64, segments[i]);
@ -577,7 +632,7 @@ static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBu
return 0;
}
// TODO wjm refine this interface
int32_t decimalToStr(const DecimalWord* pDec, int8_t dataType, int8_t precision, int8_t scale, char* pBuf,
int32_t decimalToStr(const DecimalType* pDec, int8_t dataType, int8_t precision, int8_t scale, char* pBuf,
int32_t bufLen) {
pBuf[0] = '\0';
DecimalInternalType iType = DECIMAL_GET_INTERNAL_TYPE(dataType);
@ -586,19 +641,19 @@ int32_t decimalToStr(const DecimalWord* pDec, int8_t dataType, int8_t precision,
int32_t wordNum = DECIMAL_GET_WORD_NUM(iType);
SDecimalOps* pOps = getDecimalOpsImp(iType);
Decimal whole = {0}, frac = {0};
DecimalWord zero = 0;
DecimalWord zero = 0;// TODO wjm remove zero, use SIGN
int32_t pos = 0;
if (pOps->lt(pDec, &zero, 1)) {
pos = sprintf(pBuf, "-");
}
int32_t code = decimalGetWhole(pDec, iType, scale, whole.words);
if (!pOps->eq(whole.words, &zero, 1)) {
pos += pOps->toStr(whole.words, scale, pBuf + pos, bufLen - pos);
int32_t code = decimalGetWhole(pDec, iType, scale, &whole);
if (!pOps->eq(&whole, &zero, 1)) {
pos += pOps->toStr(&whole, scale, pBuf + pos, bufLen - pos);
}
code = decimalGetFrac(pDec, iType, scale, frac.words);
if (frac.words[0] != 0) pos += snprintf(pBuf + pos, bufLen - pos, ".");
pOps->toStr(frac.words, scale, pBuf + pos, bufLen - pos);
code = decimalGetFrac(pDec, iType, scale, &frac);
if (DECIMAL64_GET_VALUE(&frac) != 0) pos += snprintf(pBuf + pos, bufLen - pos, ".");
pOps->toStr(&frac, scale, pBuf + pos, bufLen - pos);
return 0;
}
case DECIMAL_128:
@ -627,7 +682,7 @@ int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pR
SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
switch (op) {
case OP_TYPE_ADD:
pOps->add(pLeft.words, pRight.words, WORD_NUM(Decimal));
pOps->add(&pLeft, &pRight, WORD_NUM(Decimal));
break;
default:
break;
@ -638,8 +693,8 @@ int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pR
#define ABS_INT64(v) (v) == INT64_MIN ? (uint64_t)INT64_MAX + 1 : (uint64_t)llabs(v)
#define ABS_UINT64(v) (v)
#define DECIMAL64_IS_OVERFLOW(v, max) decimal64Gt((v).words, max.words, DECIMAL_WORD_NUM(Decimal64))
#define DECIMAL128_IS_OVERFLOW(v, max) decimal128Gt((v).words, max.words, DECIMAL_WORD_NUM(Decimal128))
#define DECIMAL64_IS_OVERFLOW(v, max) decimal64Gt(&(v), &max, DECIMAL_WORD_NUM(Decimal64))
#define DECIMAL128_IS_OVERFLOW(v, max) decimal128Gt(&(v), &max, DECIMAL_WORD_NUM(Decimal128))
#define CHECK_OVERFLOW_AND_MAKE_DECIMAL64(pDec, v, max, ABS) \
({ \
@ -764,44 +819,43 @@ int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* p
void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale) {
if (newScale < oldScale) {
Decimal64 divisor = SCALE_MULTIPLIER_64[oldScale - newScale];
decimal64divide(pDec->words, divisor.words, 1, NULL);
decimal64divide(pDec, &divisor, 1, NULL);
}
}
int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale,
Decimal64* result) {
int32_t code = 0;
DecimalVar var = {.type = DECIMAL_64, .words = result->words};
DecimalVar var = {.type = DECIMAL_64, .pDec = result->words};
code = decimalVarFromStr(str, len, &var);
if (TSDB_CODE_SUCCESS != code) return code;
Decimal64 max = {0};
DECIMAL64_GET_MAX(expectPrecision - expectScale, &max);
if (decimal64Gt(result->words, max.words, 1)) {
if (var.scale > expectScale) decimal64ScaleTo(result, var.scale, expectScale);
if (decimal64Gt(result, &max, 1)) {
return TSDB_CODE_DECIMAL_OVERFLOW;
}
if (var.scale > expectScale) decimal64ScaleTo(result, var.scale, expectScale);
return code;
}
void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale) {
if (newScale < oldScale) {
Decimal128 divisor = SCALE_MULTIPLIER_128[oldScale - newScale];
decimal128divide(pDec->words, divisor.words, 2, NULL);
decimal128Divide(pDec, &divisor, 2, NULL);
}
}
int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale,
Decimal128* result) {
int32_t code = 0;
DecimalVar var = {.type = DECIMAL_128, .words = result->words};
DecimalVar var = {.type = DECIMAL_128, .pDec = result->words};
code = decimalVarFromStr(str, len, &var);
if (TSDB_CODE_SUCCESS != code) return code;
Decimal128 max = {0};
DECIMAL128_GET_MAX(expectPrecision - expectScale, &max);
if (decimal128Gt(result->words, max.words, 2)) {
if (var.scale > expectScale) decimal128ScaleTo(result, var.scale, expectScale);
if (decimal128Gt(result, &max, 2)) {
return TSDB_CODE_DECIMAL_OVERFLOW;
}
if (var.scale > expectScale) decimal128ScaleTo(result, var.scale, expectScale);
return code;
}