support decimal128 divide
This commit is contained in:
parent
cdba5bd9c0
commit
eb7b35881a
|
@ -47,7 +47,7 @@ int32_t decimal128FromStr(const char* str, int32_t len, uint8_t* precision, uint
|
|||
int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal);
|
||||
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal);
|
||||
|
||||
int32_t decimalToStr(DecimalWord* pDec, int8_t type, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen);
|
||||
int32_t decimalToStr(const DecimalWord* pDec, int8_t type, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen);
|
||||
|
||||
typedef struct SDecimalOps {
|
||||
void (*negate)(DecimalWord* pWord);
|
||||
|
@ -55,7 +55,7 @@ typedef struct SDecimalOps {
|
|||
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);
|
||||
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);
|
||||
|
|
|
@ -194,7 +194,7 @@ static int32_t decimalGetWhole(const DecimalWord* pDec, DecimalInternalType type
|
|||
if (type == DECIMAL_64) {
|
||||
pWhole[0] = *pDec;
|
||||
DecimalWord scaleMul = SCALE_MULTIPLIER_64[scale];
|
||||
pOps->divide(pWhole, &scaleMul, 1);
|
||||
pOps->divide(pWhole, &scaleMul, 1, NULL);
|
||||
if (TSDB_CODE_SUCCESS != 0) {
|
||||
// TODO wjm
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ 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);
|
||||
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);
|
||||
|
@ -236,7 +236,7 @@ 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);
|
||||
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);
|
||||
|
@ -270,7 +270,10 @@ 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) { *pLeft /= *pRight; }
|
||||
void decimal64divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum, DecimalWord* pRemainder) {
|
||||
*pLeft /= *pRight;
|
||||
if (pRemainder) *pRemainder = *pLeft % *pRight;
|
||||
}
|
||||
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; }
|
||||
|
@ -327,7 +330,7 @@ static void decimal128Abs(DecimalWord* pWord) {
|
|||
}
|
||||
|
||||
static void decimal128Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -338,7 +341,7 @@ static void decimal128Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t
|
|||
}
|
||||
|
||||
static void decimal128Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -349,7 +352,7 @@ static void decimal128Subtract(DecimalWord* pLeft, const DecimalWord* pRight, ui
|
|||
}
|
||||
|
||||
static void decimal128Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -367,7 +370,8 @@ static void decimal128Multiply(DecimalWord* pLeft, const DecimalWord* pRight, ui
|
|||
}
|
||||
|
||||
static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
// TODO wjm pRightDec use const
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -376,12 +380,34 @@ static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, ui
|
|||
DECIMAL128_LOW_WORDS(pLeftDec) < DECIMAL128_LOW_WORDS(pRightDec));
|
||||
}
|
||||
|
||||
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {}
|
||||
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum, DecimalWord* pRemainder) {
|
||||
Decimal128* pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, *pRemainderDec = (Decimal128*)pRemainder;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {}
|
||||
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));
|
||||
// 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));
|
||||
makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d));
|
||||
if (negate) decimal128Negate(pLeftDec->words);
|
||||
if (DECIMAL128_SIGN(pLeftDec) == -1) decimal128Negate(pRemainderDec->words);
|
||||
}
|
||||
|
||||
static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
|
||||
}
|
||||
|
||||
static bool decimal128Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -389,7 +415,7 @@ static bool decimal128Gt(const DecimalWord* pLeft, const DecimalWord* pRight, ui
|
|||
}
|
||||
|
||||
static bool decimal128Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = NULL;
|
||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||
Decimal128 right = {0};
|
||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||
|
||||
|
@ -450,7 +476,7 @@ static int32_t decimal128ToStr(const DecimalWord* pInt, uint8_t scale, char* pBu
|
|||
return len;
|
||||
}
|
||||
|
||||
int32_t decimalToStr(DecimalWord* pDec, int8_t dataType, int8_t precision, int8_t scale, char* pBuf, int32_t bufLen) {
|
||||
int32_t decimalToStr(const DecimalWord* 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);
|
||||
switch (iType) {
|
||||
|
|
|
@ -38,6 +38,12 @@ void extractWideInteger(__int128 a) {
|
|||
printArray<38 / DIGIT_NUM>(segments);
|
||||
}
|
||||
|
||||
void printDecimal128(const Decimal128* pDec, int8_t precision, int8_t scale) {
|
||||
char buf[64] = {0};
|
||||
decimalToStr(pDec->words, TSDB_DATA_TYPE_DECIMAL, precision, scale, buf, 64);
|
||||
cout << buf;
|
||||
}
|
||||
|
||||
__int128 generate_big_int128(uint32_t digitNum) {
|
||||
__int128 a = 0;
|
||||
for (int i = 0; i < digitNum + 1; ++i) {
|
||||
|
@ -68,6 +74,35 @@ TEST(decimal128, to_string) {
|
|||
ASSERT_STREQ(buf, "1234567890123456789012345678.901234567");
|
||||
}
|
||||
|
||||
TEST(decimal128, divide) {
|
||||
__int128 i = generate_big_int128(15);
|
||||
int64_t hi = i >> 64;
|
||||
uint64_t lo = i;
|
||||
Decimal128 d;
|
||||
makeDecimal128(&d, hi, lo);
|
||||
|
||||
Decimal128 d2 = {0};
|
||||
makeDecimal128(&d2, 0, 12345678);
|
||||
|
||||
auto ops = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||
Decimal128 remainder = {0};
|
||||
int8_t precision1 = 38, scale1 = 5, precision2 = 10, scale2 = 2;
|
||||
int8_t out_scale = 25;
|
||||
int8_t out_precision = std::min(precision1 - scale1 + scale2 + out_scale, 38);
|
||||
int8_t delta_scale = out_scale + scale2 - scale1;
|
||||
printDecimal128(&d, precision1, scale1);
|
||||
__int128 a = 1;
|
||||
while (delta_scale-- > 0) a *= 10;
|
||||
Decimal128 multiplier = {0};
|
||||
makeDecimal128(&multiplier, a >> 64, a);
|
||||
ops->multiply(d.words, multiplier.words, 2);
|
||||
cout << " / ";
|
||||
printDecimal128(&d2, precision2, scale2);
|
||||
cout << " = ";
|
||||
ops->divide(d.words, d2.words, 2, remainder.words);
|
||||
printDecimal128(&d, out_precision, out_scale);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
|
|
Loading…
Reference in New Issue