fix decimal from str and decimal to str
This commit is contained in:
parent
765ca45bf2
commit
9634a3867d
|
@ -251,7 +251,7 @@ struct SValue {
|
||||||
union {
|
union {
|
||||||
int64_t val;
|
int64_t val;
|
||||||
struct {
|
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;
|
uint32_t nData;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,13 +24,18 @@ extern "C" {
|
||||||
#include "ttypes.h"
|
#include "ttypes.h"
|
||||||
typedef struct SDataType SDataType;
|
typedef struct SDataType SDataType;
|
||||||
typedef struct SValue SValue;
|
typedef struct SValue SValue;
|
||||||
|
typedef void DecimalType;
|
||||||
|
|
||||||
typedef struct Decimal64 {
|
typedef struct Decimal64 {
|
||||||
DecimalWord words[1];
|
DecimalWord words[1]; // do not touch it directly, use DECIMAL64_GET_VALUE MACRO
|
||||||
} Decimal64;
|
} 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 {
|
typedef struct Decimal128 {
|
||||||
DecimalWord words[2];
|
DecimalWord words[2]; // do not touch it directly, use DECIMAL128_HIGH_WORD/DECIMAL128_LOW_WORD
|
||||||
} Decimal128;
|
} Decimal128;
|
||||||
|
|
||||||
#define Decimal Decimal128
|
#define Decimal Decimal128
|
||||||
|
@ -38,7 +43,7 @@ typedef struct Decimal128 {
|
||||||
#define makeDecimal makeDecimal128
|
#define makeDecimal makeDecimal128
|
||||||
|
|
||||||
// TODO wjm check if we need to expose these functions in decimal.h
|
// 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);
|
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low);
|
||||||
|
|
||||||
#define DECIMAL_WORD_NUM(TYPE) sizeof(TYPE) / sizeof(DecimalWord)
|
#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 decimal64ToDataVal(const Decimal64* dec, SValue* pVal);
|
||||||
int32_t decimal128ToDataVal(Decimal128* 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 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,
|
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??
|
// TODO wjm change rightWordNum to DecimalType??
|
||||||
typedef struct SDecimalOps {
|
typedef struct SDecimalOps {
|
||||||
void (*negate)(DecimalWord* pWord);
|
void (*negate)(DecimalType* pWord);
|
||||||
void (*abs)(DecimalWord* pWord);
|
void (*abs)(DecimalType* pWord);
|
||||||
void (*add)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
void (*add)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
void (*subtract)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
void (*subtract)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
void (*multiply)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
void (*multiply)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
void (*divide)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum, DecimalWord* pRemainder);
|
void (*divide)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, DecimalType* pRemainder);
|
||||||
void (*mod)(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
void (*mod)(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
bool (*lt)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
bool (*lt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
bool (*gt)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
bool (*gt)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
bool (*eq)(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
bool (*eq)(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
int32_t (*toStr)(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
|
int32_t (*toStr)(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
|
||||||
} SDecimalOps;
|
} SDecimalOps;
|
||||||
|
|
||||||
SDecimalOps* getDecimalOps(int8_t dataType);
|
SDecimalOps* getDecimalOps(int8_t dataType);
|
||||||
|
|
|
@ -36,7 +36,7 @@ typedef struct DecimalVar {
|
||||||
uint8_t scale;
|
uint8_t scale;
|
||||||
int32_t exponent;
|
int32_t exponent;
|
||||||
int8_t sign;
|
int8_t sign;
|
||||||
DecimalWord* words;
|
DecimalType* pDec;
|
||||||
} DecimalVar;
|
} DecimalVar;
|
||||||
|
|
||||||
static uint8_t maxPrecision(DecimalInternalType type) {
|
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';
|
DecimalWord ten = 10, digit = str[pos] - '0';
|
||||||
while (places-- > 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;
|
places = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -183,21 +183,20 @@ static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* resul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result->sign < 0) {
|
if (result->sign < 0) {
|
||||||
DecimalWord sign = (DecimalWord)result->sign;
|
pOps->negate(result->pDec);
|
||||||
pOps->multiply(result->words, &sign, 1);
|
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal) {
|
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;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal) {
|
int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal) {
|
||||||
void* pV = taosMemCalloc(1, sizeof(Decimal128));
|
void* pV = taosMemCalloc(1, sizeof(Decimal128));
|
||||||
if (!pV) return terrno;
|
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));
|
valueSetDatum(pVal, TSDB_DATA_TYPE_DECIMAL, pV, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord));
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -225,18 +224,20 @@ static Decimal64 SCALE_MULTIPLIER_64[19] = {1LL,
|
||||||
|
|
||||||
#define DECIMAL64_ONE SCALE_MULTIPLIER_64[0]
|
#define DECIMAL64_ONE SCALE_MULTIPLIER_64[0]
|
||||||
|
|
||||||
#define DECIMAL64_GET_MAX(precision, pMax) \
|
#define DECIMAL64_GET_MAX(precision, pMax) \
|
||||||
do { \
|
do { \
|
||||||
*(pMax) = SCALE_MULTIPLIER_64[precision]; \
|
*(pMax) = SCALE_MULTIPLIER_64[precision]; \
|
||||||
decimal64Subtract((pMax)->words, DECIMAL64_ONE.words, DECIMAL_WORD_NUM(Decimal64)); \
|
decimal64Subtract(pMax, &DECIMAL64_ONE, DECIMAL_WORD_NUM(Decimal64)); \
|
||||||
} while (0)
|
} 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);
|
SDecimalOps* pOps = getDecimalOpsImp(type);
|
||||||
if (type == DECIMAL_64) {
|
if (type == DECIMAL_64) {
|
||||||
pWhole[0] = *pDec;
|
DECIMAL64_CLONE(pWhole, pDec);
|
||||||
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
|
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
|
||||||
pOps->divide(pWhole, scaleMul.words, 1, NULL);
|
pOps->divide(pWhole, &scaleMul, 1, NULL);
|
||||||
if (TSDB_CODE_SUCCESS != 0) {
|
if (TSDB_CODE_SUCCESS != 0) {
|
||||||
// TODO wjm
|
// TODO wjm
|
||||||
}
|
}
|
||||||
|
@ -244,55 +245,55 @@ static int32_t decimalGetWhole(const DecimalWord* pDec, DecimalInternalType type
|
||||||
} else {
|
} else {
|
||||||
memcpy(pWhole, pDec, DECIMAL_GET_WORD_NUM(type) * sizeof(DecimalWord));
|
memcpy(pWhole, pDec, DECIMAL_GET_WORD_NUM(type) * sizeof(DecimalWord));
|
||||||
// TODO wjm
|
// TODO wjm
|
||||||
// pOps.divide(pWhole->words, )
|
// pOps.divide(pWhole, )
|
||||||
}
|
}
|
||||||
return 0;
|
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);
|
SDecimalOps* pOps = getDecimalOpsImp(type);
|
||||||
if (type == DECIMAL_64) {
|
if (type == DECIMAL_64) {
|
||||||
pFrac[0] = *pDec;
|
DECIMAL64_CLONE(pFrac, pDec);
|
||||||
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
|
Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale];
|
||||||
pOps->mod(pFrac, scaleMul.words, 1);
|
pOps->mod(pFrac, &scaleMul, 1);
|
||||||
pOps->abs(pFrac);
|
pOps->abs(pFrac);
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decimal64Negate(DecimalWord* pInt);
|
static void decimal64Negate(DecimalType* pInt);
|
||||||
static void decimal64Abs(DecimalWord* pInt);
|
static void decimal64Abs(DecimalType* pInt);
|
||||||
static void decimal64Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal64Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal64Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal64Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal64Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal64Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal64divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
|
static void decimal64divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
|
||||||
DecimalWord* pRemainder);
|
DecimalType* pRemainder);
|
||||||
static void decimal64Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal64Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static bool decimal64Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static bool decimal64Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static bool decimal64Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static bool decimal64Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static bool decimal64Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static bool decimal64Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static int32_t decimal64ToStr(const DecimalWord* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
|
static int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen);
|
||||||
|
|
||||||
static void decimal128Negate(DecimalWord* pInt);
|
static void decimal128Negate(DecimalType* pInt);
|
||||||
static void decimal128Abs(DecimalWord* pWord);
|
static void decimal128Abs(DecimalType* pWord);
|
||||||
static void decimal128Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal128Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal128Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal128Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal128Multiply(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal128Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
|
static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
|
||||||
DecimalWord* pRemainder);
|
DecimalType* pRemainder);
|
||||||
static void decimal128Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static void decimal128Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
static bool decimal128Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static bool decimal128Lt(const 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);
|
||||||
static bool decimal128Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum);
|
static bool decimal128Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum);
|
||||||
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);
|
||||||
static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale);
|
static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale);
|
||||||
|
|
||||||
SDecimalOps decimal64Ops = {decimal64Negate, decimal64Abs, decimal64Add, decimal64Subtract,
|
SDecimalOps decimal64Ops = {decimal64Negate, decimal64Abs, decimal64Add, decimal64Subtract,
|
||||||
decimal64Multiply, decimal64divide, decimal64Mod, decimal64Lt,
|
decimal64Multiply, decimal64divide, decimal64Mod, decimal64Lt,
|
||||||
decimal64Gt, decimal64Eq, decimal64ToStr};
|
decimal64Gt, decimal64Eq, decimal64ToStr};
|
||||||
SDecimalOps decimal128Ops = {decimal128Negate, decimal128Abs, decimal128Add, decimal128Subtract,
|
SDecimalOps decimal128Ops = {decimal128Negate, decimal128Abs, decimal128Add, decimal128Subtract,
|
||||||
decimal128Multiply, decimal128divide, decimal128Mod, decimal128Lt,
|
decimal128Multiply, decimal128Divide, decimal128Mod, decimal128Lt,
|
||||||
decimal128Gt, decimal128Eq, decimal128ToStr};
|
decimal128Gt, decimal128Eq, decimal128ToStr};
|
||||||
|
|
||||||
static SDecimalOps* getDecimalOpsImp(DecimalInternalType t) {
|
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)); }
|
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
|
// TODO wjm handle overflow problem of DecimalWord
|
||||||
void decimal64Negate(DecimalWord* pInt) { *pInt = -(int64_t)(*pInt); }
|
// it's impossible that pDec == INT64_MIN, only 18 digits can be accepted.
|
||||||
void decimal64Abs(DecimalWord* pInt) { *pInt = TABS(*pInt); }
|
void decimal64Negate(DecimalType* pInt) {
|
||||||
void decimal64Add(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft += *pRight; }
|
Decimal64* pDec = pInt;
|
||||||
void decimal64Subtract(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft -= *pRight; }
|
DECIMAL64_SET_VALUE(pDec, -DECIMAL64_GET_VALUE(pDec));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
void decimal64Mod(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { *pLeft %= *pRight; }
|
void decimal64Abs(DecimalType* pInt) {
|
||||||
bool decimal64Lt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { return *pLeft < *pRight; }
|
Decimal64* pDec = pInt;
|
||||||
bool decimal64Gt(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) { return *pLeft > *pRight; }
|
DECIMAL64_SET_VALUE(pDec, TABS(DECIMAL64_GET_VALUE(pDec)));
|
||||||
bool decimal64Eq(const DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum) {
|
|
||||||
return *pLeft == *pRight;
|
|
||||||
}
|
}
|
||||||
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";
|
char format[16] = "\%0";
|
||||||
snprintf(format+2, 14, "%"PRIu8 PRIu64, scale);
|
snprintf(format + 2, 14, "%" PRIu8 PRIu64, scale);
|
||||||
return snprintf(pBuf, bufLen, *pInt != 0 ? format : "%"PRIu64, *pInt);
|
return snprintf(pBuf, bufLen, DECIMAL64_GET_VALUE((Decimal64*)pInt) != 0 ? format : "%" PRIu64,
|
||||||
|
DECIMAL64_GET_VALUE((Decimal64*)pInt));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO wjm handle endian problem
|
// TODO wjm handle endian problem
|
||||||
#define DECIMAL128_LOW_WORDS(pDec) (uint64_t)((pDec)->words[0])
|
#define DECIMAL128_LOW_WORD(pDec) (uint64_t)((pDec)->words[0])
|
||||||
#define DECIMAL128_HIGH_WORDS(pDec) (int64_t)((pDec)->words[1])
|
#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
|
// 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
|
// TODO wjm handle endian problem
|
||||||
#define DEFINE_DECIMAL128(lo, hi) {lo, hi}
|
#define DEFINE_DECIMAL128(lo, hi) {lo, hi}
|
||||||
|
|
||||||
static Decimal128 SCALE_MULTIPLIER_128[38 + 1] = {
|
static Decimal128 SCALE_MULTIPLIER_128[38 + 1] = {
|
||||||
DEFINE_DECIMAL128( 1LL,0),
|
DEFINE_DECIMAL128(1LL, 0),
|
||||||
DEFINE_DECIMAL128( 10LL,0),
|
DEFINE_DECIMAL128(10LL, 0),
|
||||||
DEFINE_DECIMAL128( 100LL,0),
|
DEFINE_DECIMAL128(100LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000LL,0),
|
DEFINE_DECIMAL128(1000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000LL,0),
|
DEFINE_DECIMAL128(10000LL, 0),
|
||||||
DEFINE_DECIMAL128( 100000LL,0),
|
DEFINE_DECIMAL128(100000LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000000LL,0),
|
DEFINE_DECIMAL128(1000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000000LL,0),
|
DEFINE_DECIMAL128(10000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 100000000LL,0),
|
DEFINE_DECIMAL128(100000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000000000LL,0),
|
DEFINE_DECIMAL128(1000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000000000LL,0),
|
DEFINE_DECIMAL128(10000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 100000000000LL,0),
|
DEFINE_DECIMAL128(100000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000000000000LL,0),
|
DEFINE_DECIMAL128(1000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000000000000LL,0),
|
DEFINE_DECIMAL128(10000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 100000000000000LL,0),
|
DEFINE_DECIMAL128(100000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000000000000000LL,0),
|
DEFINE_DECIMAL128(1000000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000000000000000LL,0),
|
DEFINE_DECIMAL128(10000000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 100000000000000000LL,0),
|
DEFINE_DECIMAL128(100000000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 1000000000000000000LL,0),
|
DEFINE_DECIMAL128(1000000000000000000LL, 0),
|
||||||
DEFINE_DECIMAL128( 10000000000000000000ULL,0LL),
|
DEFINE_DECIMAL128(10000000000000000000ULL, 0LL),
|
||||||
DEFINE_DECIMAL128( 7766279631452241920ULL,5LL),
|
DEFINE_DECIMAL128(7766279631452241920ULL, 5LL),
|
||||||
DEFINE_DECIMAL128( 3875820019684212736ULL,54LL),
|
DEFINE_DECIMAL128(3875820019684212736ULL, 54LL),
|
||||||
DEFINE_DECIMAL128( 1864712049423024128ULL,542LL),
|
DEFINE_DECIMAL128(1864712049423024128ULL, 542LL),
|
||||||
DEFINE_DECIMAL128( 200376420520689664ULL,5421LL),
|
DEFINE_DECIMAL128(200376420520689664ULL, 5421LL),
|
||||||
DEFINE_DECIMAL128( 2003764205206896640ULL,54210LL),
|
DEFINE_DECIMAL128(2003764205206896640ULL, 54210LL),
|
||||||
DEFINE_DECIMAL128( 1590897978359414784ULL,542101LL),
|
DEFINE_DECIMAL128(1590897978359414784ULL, 542101LL),
|
||||||
DEFINE_DECIMAL128( 15908979783594147840ULL,5421010LL),
|
DEFINE_DECIMAL128(15908979783594147840ULL, 5421010LL),
|
||||||
DEFINE_DECIMAL128( 11515845246265065472ULL,54210108LL),
|
DEFINE_DECIMAL128(11515845246265065472ULL, 54210108LL),
|
||||||
DEFINE_DECIMAL128( 4477988020393345024ULL,542101086LL),
|
DEFINE_DECIMAL128(4477988020393345024ULL, 542101086LL),
|
||||||
DEFINE_DECIMAL128( 7886392056514347008ULL,5421010862LL),
|
DEFINE_DECIMAL128(7886392056514347008ULL, 5421010862LL),
|
||||||
DEFINE_DECIMAL128( 5076944270305263616ULL,54210108624LL),
|
DEFINE_DECIMAL128(5076944270305263616ULL, 54210108624LL),
|
||||||
DEFINE_DECIMAL128( 13875954555633532928ULL,542101086242LL),
|
DEFINE_DECIMAL128(13875954555633532928ULL, 542101086242LL),
|
||||||
DEFINE_DECIMAL128( 9632337040368467968ULL,5421010862427LL),
|
DEFINE_DECIMAL128(9632337040368467968ULL, 5421010862427LL),
|
||||||
DEFINE_DECIMAL128( 4089650035136921600ULL,54210108624275LL),
|
DEFINE_DECIMAL128(4089650035136921600ULL, 54210108624275LL),
|
||||||
DEFINE_DECIMAL128( 4003012203950112768ULL,542101086242752LL),
|
DEFINE_DECIMAL128(4003012203950112768ULL, 542101086242752LL),
|
||||||
DEFINE_DECIMAL128( 3136633892082024448ULL,5421010862427522LL),
|
DEFINE_DECIMAL128(3136633892082024448ULL, 5421010862427522LL),
|
||||||
DEFINE_DECIMAL128( 12919594847110692864ULL,54210108624275221LL),
|
DEFINE_DECIMAL128(12919594847110692864ULL, 54210108624275221LL),
|
||||||
DEFINE_DECIMAL128( 68739955140067328ULL,542101086242752217LL),
|
DEFINE_DECIMAL128(68739955140067328ULL, 542101086242752217LL),
|
||||||
DEFINE_DECIMAL128( 687399551400673280ULL,5421010862427522170LL),
|
DEFINE_DECIMAL128(687399551400673280ULL, 5421010862427522170LL),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DECIMAL128_ONE SCALE_MULTIPLIER_128[0]
|
#define DECIMAL128_ONE SCALE_MULTIPLIER_128[0]
|
||||||
#define DECIMAL128_TEN SCALE_MULTIPLIER_128[1]
|
#define DECIMAL128_TEN SCALE_MULTIPLIER_128[1]
|
||||||
|
|
||||||
#define DECIMAL128_GET_MAX(precision, pMax) \
|
#define DECIMAL128_GET_MAX(precision, pMax) \
|
||||||
do { \
|
do { \
|
||||||
*(pMax) = SCALE_MULTIPLIER_128[precision]; \
|
*(pMax) = SCALE_MULTIPLIER_128[precision]; \
|
||||||
decimal128Subtract((pMax)->words, DECIMAL128_ONE.words, DECIMAL_WORD_NUM(Decimal128)); \
|
decimal128Subtract(pMax, &DECIMAL128_ONE, DECIMAL_WORD_NUM(Decimal128)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low) {
|
void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low) {
|
||||||
// TODO wjm handle endian problem
|
DECIMAL128_SET_HIGH_WORD(pDec128, hi);
|
||||||
pDec128->words[1] = hi;
|
DECIMAL128_SET_LOW_WORD(pDec128, low);
|
||||||
pDec128->words[0] = low;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void makeDecimal128FromDecimal64(Decimal128* pTarget, Decimal64 decimal64) {
|
static void makeDecimal128FromDecimal64(Decimal128* pTarget, Decimal64 decimal64) {
|
||||||
DecimalWord zero = 0, sign = 0;
|
bool negative = false;
|
||||||
if (decimal64Lt(decimal64.words, &zero, 1)) {
|
if (DECIMAL64_SIGN(&decimal64) == -1) {
|
||||||
decimal64Negate(decimal64.words);
|
decimal64Negate(&decimal64);
|
||||||
sign = -1;
|
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;
|
Decimal128* pDec = (Decimal128*)pWord;
|
||||||
uint64_t lo = ~DECIMAL128_LOW_WORDS(pDec) + 1;
|
uint64_t lo = ~DECIMAL128_LOW_WORD(pDec) + 1;
|
||||||
int64_t hi = ~DECIMAL128_HIGH_WORDS(pDec);
|
int64_t hi = ~DECIMAL128_HIGH_WORD(pDec);
|
||||||
if (lo == 0) hi = SAFE_INT64_ADD(hi, 1);
|
if (lo == 0) hi = SAFE_INT64_ADD(hi, 1);
|
||||||
makeDecimal128(pDec, hi, lo);
|
makeDecimal128(pDec, hi, lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decimal128Abs(DecimalWord* pWord) {
|
static void decimal128Abs(DecimalType* pWord) {
|
||||||
DecimalWord zero = 0;
|
if (DECIMAL128_SIGN((Decimal128*)pWord) == -1) {
|
||||||
if (decimal128Lt(pWord, &zero, 1)) {
|
|
||||||
decimal128Negate(pWord);
|
decimal128Negate(pWord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -425,64 +477,64 @@ static void decimal128Abs(DecimalWord* pWord) {
|
||||||
#define DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pTarget, rightDec, pWord) \
|
#define DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pTarget, rightDec, pWord) \
|
||||||
if (rightWordNum != WORD_NUM(Decimal128)) { \
|
if (rightWordNum != WORD_NUM(Decimal128)) { \
|
||||||
Decimal64 d64 = {0}; \
|
Decimal64 d64 = {0}; \
|
||||||
makeDecimal64(&d64, *pWord); \
|
makeDecimal64(&d64, *(int64_t*)pWord); \
|
||||||
makeDecimal128FromDecimal64(&rightDec, d64); \
|
makeDecimal128FromDecimal64(&rightDec, d64); \
|
||||||
pTarget = &rightDec; \
|
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 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||||
|
|
||||||
int64_t hi = SAFE_INT64_ADD(DECIMAL128_HIGH_WORDS(pLeftDec), DECIMAL128_HIGH_WORDS(pRightDec));
|
int64_t hi = SAFE_INT64_ADD(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec));
|
||||||
uint64_t lo = DECIMAL128_LOW_WORDS(pLeftDec) + DECIMAL128_LOW_WORDS(pRightDec);
|
uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) + DECIMAL128_LOW_WORD(pRightDec);
|
||||||
hi = SAFE_INT64_ADD(hi, lo < DECIMAL128_LOW_WORDS(pLeftDec));
|
hi = SAFE_INT64_ADD(hi, lo < DECIMAL128_LOW_WORD(pLeftDec));
|
||||||
makeDecimal128(pLeftDec, hi, lo);
|
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 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||||
|
|
||||||
int64_t hi = SAFE_INT64_SUBTRACT(DECIMAL128_HIGH_WORDS(pLeftDec), DECIMAL128_HIGH_WORDS(pRightDec));
|
int64_t hi = SAFE_INT64_SUBTRACT(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec));
|
||||||
uint64_t lo = DECIMAL128_LOW_WORDS(pLeftDec) - DECIMAL128_LOW_WORDS(pRightDec);
|
uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) - DECIMAL128_LOW_WORD(pRightDec);
|
||||||
hi = SAFE_INT64_SUBTRACT(hi, lo > DECIMAL128_LOW_WORDS(pLeftDec));
|
hi = SAFE_INT64_SUBTRACT(hi, lo > DECIMAL128_LOW_WORD(pLeftDec));
|
||||||
makeDecimal128(pLeftDec, hi, lo);
|
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 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||||
|
|
||||||
bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec);
|
bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec);
|
||||||
Decimal128 x = *pLeftDec, y = *pRightDec;
|
Decimal128 x = *pLeftDec, y = *pRightDec;
|
||||||
decimal128Abs(x.words);
|
decimal128Abs(&x);
|
||||||
decimal128Abs(y.words);
|
decimal128Abs(&y);
|
||||||
|
|
||||||
UInt128 res = {0}, tmp = {0};
|
UInt128 res = {0}, tmp = {0};
|
||||||
makeUInt128(&res, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
|
makeUInt128(&res, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
|
||||||
makeUInt128(&tmp, DECIMAL128_HIGH_WORDS(&y), DECIMAL128_LOW_WORDS(&y));
|
makeUInt128(&tmp, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y));
|
||||||
uInt128Multiply(&res, &tmp);
|
uInt128Multiply(&res, &tmp);
|
||||||
makeDecimal128(pLeftDec, uInt128Hi(&res), uInt128Lo(&res));
|
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
|
// TODO wjm pRightDec use const
|
||||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
||||||
|
|
||||||
return DECIMAL128_HIGH_WORDS(pLeftDec) < DECIMAL128_HIGH_WORDS(pRightDec) ||
|
return DECIMAL128_HIGH_WORD(pLeftDec) < DECIMAL128_HIGH_WORD(pRightDec) ||
|
||||||
(DECIMAL128_HIGH_WORDS(pLeftDec) == DECIMAL128_HIGH_WORDS(pRightDec) &&
|
(DECIMAL128_HIGH_WORD(pLeftDec) == DECIMAL128_HIGH_WORD(pRightDec) &&
|
||||||
DECIMAL128_LOW_WORDS(pLeftDec) < DECIMAL128_LOW_WORDS(pRightDec));
|
DECIMAL128_LOW_WORD(pLeftDec) < DECIMAL128_LOW_WORD(pRightDec));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decimal128divide(DecimalWord* pLeft, const DecimalWord* pRight, uint8_t rightWordNum,
|
static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum,
|
||||||
DecimalWord* pRemainder) {
|
DecimalType* pRemainder) {
|
||||||
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, *pRemainderDec = (Decimal128*)pRemainder;
|
Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, *pRemainderDec = (Decimal128*)pRemainder;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
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);
|
bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec);
|
||||||
UInt128 a = {0}, b = {0}, c = {0}, d = {0};
|
UInt128 a = {0}, b = {0}, c = {0}, d = {0};
|
||||||
Decimal128 x = *pLeftDec, y = *pRightDec;
|
Decimal128 x = *pLeftDec, y = *pRightDec;
|
||||||
decimal128Abs(x.words);
|
decimal128Abs(&x);
|
||||||
decimal128Abs(y.words);
|
decimal128Abs(&y);
|
||||||
makeUInt128(&a, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
|
makeUInt128(&a, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
|
||||||
makeUInt128(&d, DECIMAL128_HIGH_WORDS(&x), DECIMAL128_LOW_WORDS(&x));
|
makeUInt128(&d, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x));
|
||||||
makeUInt128(&b, DECIMAL128_HIGH_WORDS(&y), DECIMAL128_LOW_WORDS(&y));
|
makeUInt128(&b, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y));
|
||||||
// TODO wjm refine the interface, so that here do not need to copy a
|
// TODO wjm refine the interface, so that here do not need to copy a
|
||||||
uInt128Divide(&a, &b);
|
uInt128Divide(&a, &b);
|
||||||
uInt128Mod(&d, &b);
|
uInt128Mod(&d, &b);
|
||||||
makeDecimal128(pLeftDec, uInt128Hi(&a), uInt128Lo(&a));
|
makeDecimal128(pLeftDec, uInt128Hi(&a), uInt128Lo(&a));
|
||||||
if (pRemainder) makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d));
|
if (pRemainder) makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d));
|
||||||
if (negate) decimal128Negate(pLeftDec->words);
|
if (negate) decimal128Negate(pLeftDec);
|
||||||
if (DECIMAL128_SIGN(pLeftDec) == -1 && pRemainder) decimal128Negate(pRemainderDec->words);
|
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 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
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 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight;
|
||||||
Decimal128 right = {0};
|
Decimal128 right = {0};
|
||||||
DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight);
|
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) {
|
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 a = {0};
|
||||||
UInt128 b = {0};
|
UInt128 b = {0};
|
||||||
*digitNum = 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)) {
|
while (!uInt128Eq(&a, &uInt128Zero)) {
|
||||||
uint64_t hi = a >> 64;
|
uint64_t hi = a >> 64;
|
||||||
uint64_t lo = a;
|
uint64_t lo = a;
|
||||||
|
@ -547,21 +600,23 @@ static void extractDecimal128Digits(const Decimal128* pDec, uint64_t* digits, in
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO wjm checkBuflen
|
// 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;
|
const Decimal128* pDec = (const Decimal128*)pInt;
|
||||||
bool negative = DECIMAL128_SIGN(pDec) < 0;
|
bool negative = DECIMAL128_SIGN(pDec) < 0;
|
||||||
uint64_t segments[3] = {0};
|
uint64_t segments[3] = {0};
|
||||||
int32_t digitNum = 0;
|
int32_t digitNum = 0;
|
||||||
char buf[64] = {0};
|
char buf[64] = {0};
|
||||||
|
int32_t len = 0;
|
||||||
if (negative) {
|
if (negative) {
|
||||||
Decimal128 copy = {0};
|
Decimal128 copy = {0};
|
||||||
makeDecimal128(©, DECIMAL128_HIGH_WORDS(pDec), DECIMAL128_LOW_WORDS(pDec));
|
makeDecimal128(©, DECIMAL128_HIGH_WORD(pDec), DECIMAL128_LOW_WORD(pDec));
|
||||||
decimal128Abs(copy.words);
|
decimal128Abs(©);
|
||||||
extractDecimal128Digits(©, segments, &digitNum);
|
extractDecimal128Digits(©, segments, &digitNum);
|
||||||
|
buf[0] = '-';
|
||||||
|
len = 1;
|
||||||
} else {
|
} else {
|
||||||
extractDecimal128Digits(pDec, segments, &digitNum);
|
extractDecimal128Digits(pDec, segments, &digitNum);
|
||||||
}
|
}
|
||||||
int32_t len = 0;
|
|
||||||
for (int32_t i = digitNum - 1; i >= 0; --i) {
|
for (int32_t i = digitNum - 1; i >= 0; --i) {
|
||||||
// TODO wjm test 0.0000000000000000000000000000000001
|
// TODO wjm test 0.0000000000000000000000000000000001
|
||||||
len += snprintf(buf + len, 64 - len, i == digitNum - 1 ? "%" PRIu64 : "%018" PRIu64, segments[i]);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
// TODO wjm refine this interface
|
// 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) {
|
int32_t bufLen) {
|
||||||
pBuf[0] = '\0';
|
pBuf[0] = '\0';
|
||||||
DecimalInternalType iType = DECIMAL_GET_INTERNAL_TYPE(dataType);
|
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);
|
int32_t wordNum = DECIMAL_GET_WORD_NUM(iType);
|
||||||
SDecimalOps* pOps = getDecimalOpsImp(iType);
|
SDecimalOps* pOps = getDecimalOpsImp(iType);
|
||||||
Decimal whole = {0}, frac = {0};
|
Decimal whole = {0}, frac = {0};
|
||||||
DecimalWord zero = 0;
|
DecimalWord zero = 0;// TODO wjm remove zero, use SIGN
|
||||||
int32_t pos = 0;
|
int32_t pos = 0;
|
||||||
|
|
||||||
if (pOps->lt(pDec, &zero, 1)) {
|
if (pOps->lt(pDec, &zero, 1)) {
|
||||||
pos = sprintf(pBuf, "-");
|
pos = sprintf(pBuf, "-");
|
||||||
}
|
}
|
||||||
int32_t code = decimalGetWhole(pDec, iType, scale, whole.words);
|
int32_t code = decimalGetWhole(pDec, iType, scale, &whole);
|
||||||
if (!pOps->eq(whole.words, &zero, 1)) {
|
if (!pOps->eq(&whole, &zero, 1)) {
|
||||||
pos += pOps->toStr(whole.words, scale, pBuf + pos, bufLen - pos);
|
pos += pOps->toStr(&whole, scale, pBuf + pos, bufLen - pos);
|
||||||
}
|
}
|
||||||
code = decimalGetFrac(pDec, iType, scale, frac.words);
|
code = decimalGetFrac(pDec, iType, scale, &frac);
|
||||||
if (frac.words[0] != 0) pos += snprintf(pBuf + pos, bufLen - pos, ".");
|
if (DECIMAL64_GET_VALUE(&frac) != 0) pos += snprintf(pBuf + pos, bufLen - pos, ".");
|
||||||
pOps->toStr(frac.words, scale, pBuf + pos, bufLen - pos);
|
pOps->toStr(&frac, scale, pBuf + pos, bufLen - pos);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case DECIMAL_128:
|
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);
|
SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_TYPE_ADD:
|
case OP_TYPE_ADD:
|
||||||
pOps->add(pLeft.words, pRight.words, WORD_NUM(Decimal));
|
pOps->add(&pLeft, &pRight, WORD_NUM(Decimal));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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_INT64(v) (v) == INT64_MIN ? (uint64_t)INT64_MAX + 1 : (uint64_t)llabs(v)
|
||||||
#define ABS_UINT64(v) (v)
|
#define ABS_UINT64(v) (v)
|
||||||
|
|
||||||
#define DECIMAL64_IS_OVERFLOW(v, max) decimal64Gt((v).words, max.words, DECIMAL_WORD_NUM(Decimal64))
|
#define DECIMAL64_IS_OVERFLOW(v, max) decimal64Gt(&(v), &max, DECIMAL_WORD_NUM(Decimal64))
|
||||||
#define DECIMAL128_IS_OVERFLOW(v, max) decimal128Gt((v).words, max.words, DECIMAL_WORD_NUM(Decimal128))
|
#define DECIMAL128_IS_OVERFLOW(v, max) decimal128Gt(&(v), &max, DECIMAL_WORD_NUM(Decimal128))
|
||||||
|
|
||||||
#define CHECK_OVERFLOW_AND_MAKE_DECIMAL64(pDec, v, max, ABS) \
|
#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) {
|
void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale) {
|
||||||
if (newScale < oldScale) {
|
if (newScale < oldScale) {
|
||||||
Decimal64 divisor = SCALE_MULTIPLIER_64[oldScale - newScale];
|
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,
|
int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale,
|
||||||
Decimal64* result) {
|
Decimal64* result) {
|
||||||
int32_t code = 0;
|
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);
|
code = decimalVarFromStr(str, len, &var);
|
||||||
if (TSDB_CODE_SUCCESS != code) return code;
|
if (TSDB_CODE_SUCCESS != code) return code;
|
||||||
Decimal64 max = {0};
|
Decimal64 max = {0};
|
||||||
DECIMAL64_GET_MAX(expectPrecision - expectScale, &max);
|
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;
|
return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||||
}
|
}
|
||||||
if (var.scale > expectScale) decimal64ScaleTo(result, var.scale, expectScale);
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale) {
|
void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale) {
|
||||||
if (newScale < oldScale) {
|
if (newScale < oldScale) {
|
||||||
Decimal128 divisor = SCALE_MULTIPLIER_128[oldScale - newScale];
|
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,
|
int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale,
|
||||||
Decimal128* result) {
|
Decimal128* result) {
|
||||||
int32_t code = 0;
|
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);
|
code = decimalVarFromStr(str, len, &var);
|
||||||
if (TSDB_CODE_SUCCESS != code) return code;
|
if (TSDB_CODE_SUCCESS != code) return code;
|
||||||
Decimal128 max = {0};
|
Decimal128 max = {0};
|
||||||
DECIMAL128_GET_MAX(expectPrecision - expectScale, &max);
|
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;
|
return TSDB_CODE_DECIMAL_OVERFLOW;
|
||||||
}
|
}
|
||||||
if (var.scale > expectScale) decimal128ScaleTo(result, var.scale, expectScale);
|
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue