/src/tdengine/source/libs/decimal/src/decimal.c
Line | Count | Source |
1 | | /* |
2 | | * |
3 | | * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com> |
4 | | * |
5 | | * This program is free software: you can use, redistribute, and/or modify |
6 | | * it under the terms of the GNU Affero General Public License, version 3 |
7 | | * or later ("AGPL"), as published by the Free Software Foundation. |
8 | | * |
9 | | * This program is distributed in the hope that it will be useful, but WITHOUT |
10 | | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | | * FITNESS FOR A PARTICULAR PURPOSE. |
12 | | * |
13 | | * You should have received a copy of the GNU Affero General Public License |
14 | | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 | | */ |
16 | | |
17 | | #include "decimal.h" |
18 | | #include "tdataformat.h" |
19 | | #include "wideInteger.h" |
20 | | |
21 | | typedef enum DecimalInternalType { |
22 | | DECIMAL_64 = 0, |
23 | | DECIMAL_128 = 1, |
24 | | } DecimalInternalType; |
25 | | |
26 | | typedef enum DecimalRoundType { |
27 | | ROUND_TYPE_CEIL, |
28 | | ROUND_TYPE_FLOOR, |
29 | | ROUND_TYPE_TRUNC, |
30 | | ROUND_TYPE_HALF_ROUND_UP, |
31 | | } DecimalRoundType; |
32 | | |
33 | 0 | #define DECIMAL_GET_INTERNAL_TYPE(dataType) ((dataType) == TSDB_DATA_TYPE_DECIMAL ? DECIMAL_128 : DECIMAL_64) |
34 | | #define DECIMAL_GET_WORD_NUM(decimalInternalType) \ |
35 | | ((decimalInternalType) == DECIMAL_64 ? DECIMAL_WORD_NUM(Decimal64) : DECIMAL_WORD_NUM(Decimal128)) |
36 | | static SDecimalOps* getDecimalOpsImp(DecimalInternalType t); |
37 | | |
38 | | #define DECIMAL_MIN_ADJUSTED_SCALE 6 |
39 | | |
40 | | static Decimal64 SCALE_MULTIPLIER_64[TSDB_DECIMAL64_MAX_PRECISION + 1] = {1LL, |
41 | | 10LL, |
42 | | 100LL, |
43 | | 1000LL, |
44 | | 10000LL, |
45 | | 100000LL, |
46 | | 1000000LL, |
47 | | 10000000LL, |
48 | | 100000000LL, |
49 | | 1000000000LL, |
50 | | 10000000000LL, |
51 | | 100000000000LL, |
52 | | 1000000000000LL, |
53 | | 10000000000000LL, |
54 | | 100000000000000LL, |
55 | | 1000000000000000LL, |
56 | | 10000000000000000LL, |
57 | | 100000000000000000LL, |
58 | | 1000000000000000000LL}; |
59 | | |
60 | | typedef struct DecimalVar { |
61 | | DecimalInternalType type; |
62 | | int8_t precision; |
63 | | int8_t scale; |
64 | | int32_t exponent; |
65 | | int8_t sign; |
66 | | DecimalType* pDec; |
67 | | int32_t weight; |
68 | | } DecimalVar; |
69 | | |
70 | 0 | static uint8_t maxPrecision(DecimalInternalType type) { |
71 | 0 | switch (type) { |
72 | 0 | case DECIMAL_64: |
73 | 0 | return TSDB_DECIMAL64_MAX_PRECISION; |
74 | 0 | case DECIMAL_128: |
75 | 0 | return TSDB_DECIMAL128_MAX_PRECISION; |
76 | 0 | default: |
77 | 0 | return 0; |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | static const uint8_t typeConvertDecimalPrec[] = { |
82 | | 0, 1, 3, 5, 10, 19, TSDB_DECIMAL128_MAX_PRECISION, TSDB_DECIMAL_MAX_PRECISION, 0, 19, 10, 3, 5, 10, 20, 0, |
83 | | 0, 0, 0, 0, 0, 0}; |
84 | | |
85 | | int32_t decimalGetRetType(const SDataType* pLeftT, const SDataType* pRightT, EOperatorType opType, |
86 | 0 | SDataType* pOutType) { |
87 | 0 | if (pLeftT->type == TSDB_DATA_TYPE_JSON || pRightT->type == TSDB_DATA_TYPE_JSON || |
88 | 0 | pLeftT->type == TSDB_DATA_TYPE_VARBINARY || pRightT->type == TSDB_DATA_TYPE_VARBINARY) |
89 | 0 | return TSDB_CODE_TSC_INVALID_OPERATION; |
90 | 0 | if ((pLeftT->type >= TSDB_DATA_TYPE_BLOB && pLeftT->type <= TSDB_DATA_TYPE_GEOMETRY) || |
91 | 0 | (pRightT->type >= TSDB_DATA_TYPE_BLOB && pRightT->type <= TSDB_DATA_TYPE_GEOMETRY)) { |
92 | 0 | return TSDB_CODE_TSC_INVALID_OPERATION; |
93 | 0 | } |
94 | 0 | if (IS_FLOAT_TYPE(pLeftT->type) || IS_FLOAT_TYPE(pRightT->type) || IS_VAR_DATA_TYPE(pLeftT->type) || |
95 | 0 | IS_VAR_DATA_TYPE(pRightT->type)) { |
96 | 0 | pOutType->type = TSDB_DATA_TYPE_DOUBLE; |
97 | 0 | pOutType->bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; |
98 | 0 | return 0; |
99 | 0 | } |
100 | | |
101 | 0 | if (IS_NULL_TYPE(pLeftT->type) || IS_NULL_TYPE(pRightT->type)) { |
102 | 0 | pOutType->type = TSDB_DATA_TYPE_NULL; |
103 | 0 | pOutType->bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes; |
104 | 0 | return 0; |
105 | 0 | } |
106 | 0 | uint8_t p1 = pLeftT->precision, s1 = pLeftT->scale, p2 = pRightT->precision, s2 = pRightT->scale; |
107 | |
|
108 | 0 | if (!IS_DECIMAL_TYPE(pLeftT->type)) { |
109 | 0 | p1 = typeConvertDecimalPrec[pLeftT->type]; |
110 | 0 | s1 = 0; |
111 | 0 | } |
112 | 0 | if (!IS_DECIMAL_TYPE(pRightT->type)) { |
113 | 0 | p2 = typeConvertDecimalPrec[pRightT->type]; |
114 | 0 | s2 = 0; |
115 | 0 | } |
116 | |
|
117 | 0 | switch (opType) { |
118 | 0 | case OP_TYPE_ADD: |
119 | 0 | case OP_TYPE_SUB: |
120 | 0 | pOutType->scale = TMAX(s1, s2); |
121 | 0 | pOutType->precision = TMAX(p1 - s1, p2 - s2) + pOutType->scale + 1; |
122 | 0 | break; |
123 | 0 | case OP_TYPE_MULTI: |
124 | 0 | pOutType->scale = s1 + s2; |
125 | 0 | pOutType->precision = p1 + p2 + 1; |
126 | 0 | break; |
127 | 0 | case OP_TYPE_DIV: |
128 | 0 | pOutType->scale = TMAX(s1 + p2 + 1, DECIMAL_MIN_ADJUSTED_SCALE); |
129 | 0 | pOutType->precision = p1 - s1 + s2 + pOutType->scale; |
130 | 0 | break; |
131 | 0 | case OP_TYPE_REM: |
132 | 0 | pOutType->scale = TMAX(s1, s2); |
133 | 0 | pOutType->precision = TMIN(p1 - s1, p2 - s2) + pOutType->scale; |
134 | 0 | break; |
135 | 0 | default: |
136 | 0 | return TSDB_CODE_TSC_INVALID_OPERATION; |
137 | 0 | } |
138 | 0 | if (pOutType->precision > TSDB_DECIMAL_MAX_PRECISION) { |
139 | 0 | int8_t minScale = TMIN(DECIMAL_MIN_ADJUSTED_SCALE, pOutType->scale); |
140 | 0 | int8_t delta = pOutType->precision - TSDB_DECIMAL_MAX_PRECISION; |
141 | 0 | pOutType->precision = TSDB_DECIMAL_MAX_PRECISION; |
142 | 0 | pOutType->scale = TMAX(minScale, (int8_t)(pOutType->scale) - delta); |
143 | 0 | } |
144 | 0 | pOutType->type = TSDB_DATA_TYPE_DECIMAL; |
145 | 0 | pOutType->bytes = tDataTypes[pOutType->type].bytes; |
146 | 0 | return 0; |
147 | 0 | } |
148 | | |
149 | 0 | int32_t calcCurPrec(int32_t prec, int32_t places, int32_t exp, int32_t weight, int32_t firstValidScale) { |
150 | 0 | if (exp == 0) return prec + places; |
151 | 0 | if (exp < 0) { |
152 | 0 | if (weight + exp >= 0) return prec + places; |
153 | 0 | return prec + places - exp - weight; |
154 | 0 | } |
155 | 0 | if (weight > 0) return prec + places; |
156 | 0 | return prec + places - TMIN(firstValidScale - 1, exp); |
157 | 0 | } |
158 | | |
159 | 0 | int32_t calcActualWeight(int32_t prec, int32_t scale, int32_t exp, int32_t weight, int32_t firstValidScale) { |
160 | 0 | if (exp == 0) return prec - scale; |
161 | 0 | if (exp < 0) { |
162 | 0 | if (weight + exp >= 0) return weight + exp; |
163 | 0 | return 0; |
164 | 0 | } |
165 | 0 | if (weight > 0) return weight + exp; |
166 | 0 | if (firstValidScale == 0) return 0; |
167 | 0 | return TMAX(0, exp - firstValidScale); |
168 | 0 | } |
169 | | |
170 | 0 | static int32_t decimalVarFromStr(const char* str, int32_t len, DecimalVar* result) { |
171 | 0 | int32_t code = 0, pos = 0; |
172 | 0 | int32_t expectPrecision = result->precision; |
173 | 0 | int32_t expectScale = result->scale; |
174 | 0 | result->precision = 0; |
175 | 0 | result->scale = 0; |
176 | 0 | result->exponent = 0; |
177 | 0 | bool leadingZeroes = true, afterPoint = false, rounded = false, stop = false; |
178 | 0 | uint32_t places = 0; |
179 | 0 | result->sign = 1; |
180 | 0 | int32_t weight = 0; |
181 | 0 | int32_t firstValidScale = 0; |
182 | |
|
183 | 0 | if (len == 0) return TSDB_CODE_INVALID_DATA_FMT; |
184 | 0 | SDecimalOps* pOps = getDecimalOpsImp(result->type); |
185 | | |
186 | | // sign |
187 | 0 | switch (str[pos]) { |
188 | 0 | case '-': |
189 | 0 | result->sign = -1; |
190 | 0 | case '+': |
191 | 0 | pos++; |
192 | 0 | default: |
193 | 0 | break; |
194 | 0 | } |
195 | 0 | int32_t pos2 = pos; |
196 | 0 | while (pos2 < len) { |
197 | 0 | if (str[pos2] == 'e' || str[pos2] == 'E') { |
198 | 0 | int32_t expSign = 1; |
199 | 0 | int32_t exp = 0; |
200 | 0 | int32_t expPos = pos2 + 1; |
201 | 0 | if (expPos < len && (str[expPos] == '+' || str[expPos] == '-')) { |
202 | 0 | expSign = (str[expPos] == '-') ? -1 : 1; |
203 | 0 | expPos++; |
204 | 0 | } |
205 | 0 | while (expPos < len && isdigit((unsigned char)str[expPos])) { |
206 | 0 | int32_t digit = str[expPos] - '0'; |
207 | 0 | if (exp > (INT32_MAX - digit) / 10) { |
208 | 0 | exp = INT32_MAX; |
209 | 0 | break; |
210 | 0 | } |
211 | 0 | exp = exp * 10 + digit; |
212 | 0 | expPos++; |
213 | 0 | } |
214 | 0 | result->exponent = (expSign > 0) ? exp : -exp; |
215 | 0 | break; |
216 | 0 | } |
217 | 0 | pos2++; |
218 | 0 | } |
219 | |
|
220 | 0 | for (; pos < len && !stop; ++pos) { |
221 | 0 | switch (str[pos]) { |
222 | 0 | case '.': |
223 | 0 | weight = result->precision; |
224 | 0 | afterPoint = true; |
225 | 0 | leadingZeroes = false; |
226 | 0 | break; |
227 | 0 | case '0': |
228 | 0 | if (leadingZeroes) break; |
229 | 0 | if (afterPoint) { |
230 | 0 | places++; |
231 | 0 | break; |
232 | 0 | } |
233 | 0 | case '1': |
234 | 0 | case '2': |
235 | 0 | case '3': |
236 | 0 | case '4': |
237 | 0 | case '5': |
238 | 0 | case '6': |
239 | 0 | case '7': |
240 | 0 | case '8': |
241 | 0 | case '9': { |
242 | 0 | leadingZeroes = false; |
243 | 0 | ++places; |
244 | 0 | if (firstValidScale == 0 && afterPoint) firstValidScale = places; |
245 | |
|
246 | 0 | int32_t curPrec = calcCurPrec(result->precision, places, result->exponent, weight, firstValidScale); |
247 | 0 | int32_t scaleUp = 0; |
248 | 0 | Decimal64 delta = {0}; |
249 | 0 | if (curPrec > maxPrecision(result->type)) { |
250 | 0 | if (!afterPoint) return TSDB_CODE_DECIMAL_OVERFLOW; |
251 | 0 | int32_t curScale = result->scale - result->exponent + places; |
252 | 0 | if (rounded || curScale > expectScale + 1 /*scale already overflowed, no need do rounding*/ || |
253 | 0 | curPrec - 1 != maxPrecision(result->type) /* not the maxPrecision + 1 digit, no need do rounding*/ || |
254 | 0 | str[pos] < '5') |
255 | 0 | break; |
256 | | |
257 | | // Do rounding for the maxPrecision + 1 digit. |
258 | | // Here we cannot directly add this digit into the results, because it may cause overflow. |
259 | 0 | DECIMAL64_SET_VALUE(&delta, 1); |
260 | 0 | scaleUp = places - 1; |
261 | 0 | rounded = true; |
262 | 0 | } else { |
263 | 0 | scaleUp = places; |
264 | 0 | DECIMAL64_SET_VALUE(&delta, str[pos] - '0'); |
265 | 0 | } |
266 | | |
267 | 0 | result->precision += scaleUp; |
268 | 0 | if (afterPoint) result->scale += scaleUp; |
269 | 0 | while (scaleUp != 0) { |
270 | 0 | int32_t curScale = TMIN(17, scaleUp); |
271 | 0 | pOps->multiply(result->pDec, &SCALE_MULTIPLIER_64[curScale], DECIMAL_WORD_NUM(Decimal64)); |
272 | 0 | scaleUp -= curScale; |
273 | 0 | } |
274 | 0 | pOps->add(result->pDec, &delta, DECIMAL_WORD_NUM(Decimal64)); |
275 | 0 | places = 0; |
276 | 0 | } break; |
277 | 0 | case 'e': |
278 | 0 | case 'E': { |
279 | 0 | stop = true; |
280 | 0 | } break; |
281 | 0 | default: |
282 | 0 | stop = true; |
283 | 0 | break; |
284 | 0 | } |
285 | 0 | } |
286 | 0 | result->weight = calcActualWeight(result->precision, result->scale, result->exponent, weight, firstValidScale); |
287 | 0 | if (result->precision + result->scale > 0) result->scale -= result->exponent; |
288 | 0 | if (result->sign < 0) { |
289 | 0 | pOps->negate(result->pDec); |
290 | 0 | } |
291 | 0 | return code; |
292 | 0 | } |
293 | | |
294 | 0 | int32_t decimal64ToDataVal(const Decimal64* dec, SValue* pVal) { |
295 | 0 | VALUE_SET_TRIVIAL_DATUM(pVal, DECIMAL64_GET_VALUE(dec)); |
296 | 0 | return TSDB_CODE_SUCCESS; |
297 | 0 | } |
298 | | |
299 | 0 | int32_t decimal128ToDataVal(Decimal128* dec, SValue* pVal) { |
300 | 0 | void* pV = taosMemCalloc(1, sizeof(Decimal128)); |
301 | 0 | if (!pV) return terrno; |
302 | 0 | memcpy(pV, dec, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord)); |
303 | 0 | valueSetDatum(pVal, TSDB_DATA_TYPE_DECIMAL, pV, DECIMAL_WORD_NUM(Decimal128) * sizeof(DecimalWord)); |
304 | 0 | return TSDB_CODE_SUCCESS; |
305 | 0 | } |
306 | | |
307 | 0 | #define DECIMAL64_ONE SCALE_MULTIPLIER_64[0] |
308 | | |
309 | | #define DECIMAL64_GET_MAX(precision, pMax) \ |
310 | 0 | do { \ |
311 | 0 | *(pMax) = SCALE_MULTIPLIER_64[precision]; \ |
312 | 0 | decimal64Subtract(pMax, &DECIMAL64_ONE, DECIMAL_WORD_NUM(Decimal64)); \ |
313 | 0 | } while (0) |
314 | | |
315 | 0 | #define DECIMAL64_SIGN(pDec) (1 | (DECIMAL64_GET_VALUE(pDec) >> 63)) |
316 | | |
317 | 0 | static void decimal64GetWhole(const DecimalType* pDec, int8_t scale, DecimalType* pWhole) { |
318 | 0 | const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); |
319 | 0 | DECIMAL64_CLONE(pWhole, pDec); |
320 | 0 | Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale]; |
321 | 0 | pOps->divide(pWhole, &scaleMul, 1, NULL); |
322 | 0 | pOps->abs(pWhole); |
323 | 0 | } |
324 | | |
325 | 0 | static void decimal64GetFrac(const DecimalType* pDec, int8_t scale, DecimalType* pFrac) { |
326 | 0 | const SDecimalOps* pOps = getDecimalOpsImp(DECIMAL_64); |
327 | 0 | DECIMAL64_CLONE(pFrac, pDec); |
328 | 0 | Decimal64 scaleMul = SCALE_MULTIPLIER_64[scale]; |
329 | 0 | pOps->mod(pFrac, &scaleMul, 1); |
330 | 0 | pOps->abs(pFrac); |
331 | 0 | } |
332 | | |
333 | | static void decimal64Negate(DecimalType* pInt); |
334 | | static void decimal64Abs(DecimalType* pInt); |
335 | | static void decimal64Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
336 | | static void decimal64Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
337 | | static void decimal64Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
338 | | static void decimal64divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, |
339 | | DecimalType* pRemainder); |
340 | | static void decimal64Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
341 | | static bool decimal64Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
342 | | static bool decimal64Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
343 | | static bool decimal64Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
344 | | static void decimal64ScaleDown(Decimal64* pDec, uint8_t scaleDown, bool round); |
345 | | static void decimal64ScaleUp(Decimal64* pDec, uint8_t scaleUp); |
346 | | static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale); |
347 | | int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen); |
348 | | |
349 | | static void decimal64RoundWithPositiveScale(Decimal64* pDec, uint8_t prec, int8_t scale, uint8_t toPrec, |
350 | | uint8_t toScale, DecimalRoundType roundType, bool* overflow); |
351 | | |
352 | | static void decimal128Negate(DecimalType* pInt); |
353 | | static void decimal128Abs(DecimalType* pWord); |
354 | | static void decimal128Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
355 | | static void decimal128Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
356 | | static void decimal128Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
357 | | static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, |
358 | | DecimalType* pRemainder); |
359 | | static void decimal128Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
360 | | static bool decimal128Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
361 | | static bool decimal128Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
362 | | static bool decimal128Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum); |
363 | | static void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale); |
364 | | static void decimal128ScaleDown(Decimal128* pDec, uint8_t scaleDown, bool round); |
365 | | static void decimal128ScaleUp(Decimal128* pDec, uint8_t scaleUp); |
366 | | static int32_t decimal128CountLeadingBinaryZeros(const Decimal128* pDec); |
367 | | static int32_t decimal128FromInt64(DecimalType* pDec, uint8_t prec, uint8_t scale, int64_t val); |
368 | | static int32_t decimal128FromUint64(DecimalType* pDec, uint8_t prec, uint8_t scale, uint64_t val); |
369 | | int32_t decimal128ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen); |
370 | | // |
371 | | // rounding functions |
372 | | static void decimal128RoundWithPositiveScale(Decimal128* pDec, uint8_t prec, uint8_t scale, uint8_t toPrec, |
373 | | uint8_t toScale, DecimalRoundType roundType, bool* overflow); |
374 | | static void decimal128RoundWithNegativeScale(Decimal128* pDec, uint8_t prec, uint8_t scale, int8_t toScale, |
375 | | DecimalRoundType roundType, bool* overflow); |
376 | | static void decimal128ModifyScaleAndPrecision(Decimal128* pDec, uint8_t scale, uint8_t toPrec, int8_t toScale, |
377 | | bool* overflow); |
378 | | static int32_t decimal128CountRoundingDelta(const Decimal128* pDec, int8_t scale, int8_t toScale, |
379 | | DecimalRoundType roundType); |
380 | | |
381 | | SDecimalOps decimal64Ops = {decimal64Negate, decimal64Abs, decimal64Add, decimal64Subtract, |
382 | | decimal64Multiply, decimal64divide, decimal64Mod, decimal64Lt, |
383 | | decimal64Gt, decimal64Eq, decimal64ToStr}; |
384 | | SDecimalOps decimal128Ops = {decimal128Negate, decimal128Abs, decimal128Add, decimal128Subtract, |
385 | | decimal128Multiply, decimal128Divide, decimal128Mod, decimal128Lt, |
386 | | decimal128Gt, decimal128Eq, decimal128ToStr}; |
387 | | |
388 | 0 | static SDecimalOps* getDecimalOpsImp(DecimalInternalType t) { |
389 | 0 | switch (t) { |
390 | 0 | case DECIMAL_128: |
391 | 0 | return &decimal128Ops; |
392 | 0 | case DECIMAL_64: |
393 | 0 | return &decimal64Ops; |
394 | 0 | default: |
395 | 0 | return NULL; |
396 | 0 | } |
397 | 0 | } |
398 | 0 | const SDecimalOps* getDecimalOps(int8_t dataType) { return getDecimalOpsImp(DECIMAL_GET_INTERNAL_TYPE(dataType)); } |
399 | | |
400 | 0 | void makeDecimal64(Decimal64* pDec64, int64_t w) { DECIMAL64_SET_VALUE(pDec64, w); } |
401 | | |
402 | 0 | void decimal64Negate(DecimalType* pInt) { |
403 | 0 | Decimal64* pDec = pInt; |
404 | 0 | DECIMAL64_SET_VALUE(pDec, -DECIMAL64_GET_VALUE(pDec)); |
405 | 0 | } |
406 | 0 | void decimal64Abs(DecimalType* pInt) { |
407 | 0 | Decimal64* pDec = pInt; |
408 | 0 | DECIMAL64_SET_VALUE(pDec, TABS(DECIMAL64_GET_VALUE(pDec))); |
409 | 0 | } |
410 | 0 | void decimal64Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
411 | 0 | Decimal64* pDecL = pLeft; |
412 | 0 | const Decimal64* pDecR = pRight; |
413 | 0 | DECIMAL64_SET_VALUE(pDecL, SAFE_INT64_ADD(DECIMAL64_GET_VALUE(pDecL), DECIMAL64_GET_VALUE(pDecR))); |
414 | 0 | } |
415 | 0 | void decimal64Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
416 | 0 | Decimal64* pDecL = pLeft; |
417 | 0 | const Decimal64* pDecR = pRight; |
418 | 0 | DECIMAL64_SET_VALUE(pDecL, SAFE_INT64_SUBTRACT(DECIMAL64_GET_VALUE(pDecL), DECIMAL64_GET_VALUE(pDecR))); |
419 | 0 | } |
420 | 0 | void decimal64Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
421 | 0 | Decimal64* pDecL = pLeft; |
422 | 0 | Decimal64 decR = *((Decimal64*)pRight); |
423 | 0 | bool sign = DECIMAL64_SIGN(pDecL) != DECIMAL64_SIGN(&decR); |
424 | 0 | decimal64Abs(pLeft); |
425 | 0 | decimal64Abs(&decR); |
426 | 0 | uint64_t x = DECIMAL64_GET_VALUE(pDecL), y = DECIMAL64_GET_VALUE(&decR); |
427 | 0 | x *= y; |
428 | 0 | DECIMAL64_SET_VALUE(pDecL, x); |
429 | 0 | if (sign) decimal64Negate(pDecL); |
430 | 0 | } |
431 | 0 | void decimal64divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, DecimalType* pRemainder) { |
432 | 0 | Decimal64* pDecL = pLeft; |
433 | 0 | Decimal64 decR = *((Decimal64*)pRight); |
434 | 0 | Decimal64* pDecRemainder = pRemainder; |
435 | 0 | bool sign = DECIMAL64_SIGN(pDecL) != DECIMAL64_SIGN(&decR); |
436 | 0 | decimal64Abs(pDecL); |
437 | 0 | decimal64Abs(&decR); |
438 | 0 | uint64_t x = DECIMAL64_GET_VALUE(pDecL), y = DECIMAL64_GET_VALUE(&decR); |
439 | 0 | uint64_t z = x; |
440 | 0 | x /= y; |
441 | 0 | DECIMAL64_SET_VALUE(pDecL, x); |
442 | 0 | if (sign) decimal64Negate(pDecL); |
443 | 0 | if (pDecRemainder) { |
444 | 0 | z %= y; |
445 | 0 | DECIMAL64_SET_VALUE(pDecRemainder, z); |
446 | 0 | } |
447 | 0 | } |
448 | 0 | void decimal64Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
449 | 0 | Decimal64 remainder = {0}; |
450 | 0 | Decimal64* pDec = pLeft; |
451 | 0 | decimal64divide(pLeft, pRight, rightWordNum, &remainder); |
452 | 0 | DECIMAL64_SET_VALUE(pDec, DECIMAL64_GET_VALUE(&remainder)); |
453 | 0 | } |
454 | | |
455 | 0 | bool decimal64Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
456 | 0 | const Decimal64 *pDecL = pLeft, *pDecR = pRight; |
457 | 0 | return DECIMAL64_GET_VALUE(pDecL) < DECIMAL64_GET_VALUE(pDecR); |
458 | 0 | } |
459 | 0 | bool decimal64Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
460 | 0 | return DECIMAL64_GET_VALUE((Decimal64*)pLeft) > DECIMAL64_GET_VALUE((Decimal64*)pRight); |
461 | 0 | } |
462 | 0 | bool decimal64Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
463 | 0 | return DECIMAL64_GET_VALUE((Decimal64*)pLeft) == DECIMAL64_GET_VALUE(((Decimal64*)pRight)); |
464 | 0 | } |
465 | 0 | int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen) { |
466 | 0 | if (!pBuf) return TSDB_CODE_INVALID_PARA; |
467 | 0 | Decimal whole = {0}, frac = {0}; |
468 | 0 | int32_t pos = 0; |
469 | 0 | char buf[64] = {0}; |
470 | |
|
471 | 0 | if (DECIMAL64_SIGN((Decimal64*)pInt) == -1) { |
472 | 0 | pos = snprintf(buf, sizeof(buf), "-"); |
473 | 0 | } |
474 | 0 | decimal64GetWhole(pInt, scale, &whole); |
475 | 0 | pos += snprintf(buf + pos, bufLen - pos, "%" PRId64, DECIMAL64_GET_VALUE(&whole)); |
476 | 0 | if (scale > 0) { |
477 | 0 | decimal64GetFrac(pInt, scale, &frac); |
478 | 0 | if (DECIMAL64_GET_VALUE(&frac) != 0 || DECIMAL64_GET_VALUE(&whole) != 0) { |
479 | 0 | TAOS_STRCAT(buf + pos, "."); |
480 | 0 | pos += 1; |
481 | | // NOTE: never generate format string dynamically |
482 | | // decimalTest has been passed. |
483 | 0 | snprintf(buf + pos, bufLen - pos, "%0*" PRIu64, scale, DECIMAL64_GET_VALUE(&frac)); |
484 | 0 | } |
485 | 0 | } |
486 | 0 | TAOS_STRNCPY(pBuf, buf, bufLen); |
487 | 0 | return 0; |
488 | 0 | } |
489 | | |
490 | | // return 1 if positive or zero, else return -1 |
491 | 0 | #define DECIMAL128_SIGN(pDec) (1 | (DECIMAL128_HIGH_WORD(pDec) >> 63)) |
492 | | |
493 | | static const Decimal128 SCALE_MULTIPLIER_128[TSDB_DECIMAL128_MAX_PRECISION + 1] = { |
494 | | DEFINE_DECIMAL128(1LL, 0), |
495 | | DEFINE_DECIMAL128(10LL, 0), |
496 | | DEFINE_DECIMAL128(100LL, 0), |
497 | | DEFINE_DECIMAL128(1000LL, 0), |
498 | | DEFINE_DECIMAL128(10000LL, 0), |
499 | | DEFINE_DECIMAL128(100000LL, 0), |
500 | | DEFINE_DECIMAL128(1000000LL, 0), |
501 | | DEFINE_DECIMAL128(10000000LL, 0), |
502 | | DEFINE_DECIMAL128(100000000LL, 0), |
503 | | DEFINE_DECIMAL128(1000000000LL, 0), |
504 | | DEFINE_DECIMAL128(10000000000LL, 0), |
505 | | DEFINE_DECIMAL128(100000000000LL, 0), |
506 | | DEFINE_DECIMAL128(1000000000000LL, 0), |
507 | | DEFINE_DECIMAL128(10000000000000LL, 0), |
508 | | DEFINE_DECIMAL128(100000000000000LL, 0), |
509 | | DEFINE_DECIMAL128(1000000000000000LL, 0), |
510 | | DEFINE_DECIMAL128(10000000000000000LL, 0), |
511 | | DEFINE_DECIMAL128(100000000000000000LL, 0), |
512 | | DEFINE_DECIMAL128(1000000000000000000LL, 0), |
513 | | DEFINE_DECIMAL128(10000000000000000000ULL, 0LL), |
514 | | DEFINE_DECIMAL128(7766279631452241920ULL, 5LL), |
515 | | DEFINE_DECIMAL128(3875820019684212736ULL, 54LL), |
516 | | DEFINE_DECIMAL128(1864712049423024128ULL, 542LL), |
517 | | DEFINE_DECIMAL128(200376420520689664ULL, 5421LL), |
518 | | DEFINE_DECIMAL128(2003764205206896640ULL, 54210LL), |
519 | | DEFINE_DECIMAL128(1590897978359414784ULL, 542101LL), |
520 | | DEFINE_DECIMAL128(15908979783594147840ULL, 5421010LL), |
521 | | DEFINE_DECIMAL128(11515845246265065472ULL, 54210108LL), |
522 | | DEFINE_DECIMAL128(4477988020393345024ULL, 542101086LL), |
523 | | DEFINE_DECIMAL128(7886392056514347008ULL, 5421010862LL), |
524 | | DEFINE_DECIMAL128(5076944270305263616ULL, 54210108624LL), |
525 | | DEFINE_DECIMAL128(13875954555633532928ULL, 542101086242LL), |
526 | | DEFINE_DECIMAL128(9632337040368467968ULL, 5421010862427LL), |
527 | | DEFINE_DECIMAL128(4089650035136921600ULL, 54210108624275LL), |
528 | | DEFINE_DECIMAL128(4003012203950112768ULL, 542101086242752LL), |
529 | | DEFINE_DECIMAL128(3136633892082024448ULL, 5421010862427522LL), |
530 | | DEFINE_DECIMAL128(12919594847110692864ULL, 54210108624275221LL), |
531 | | DEFINE_DECIMAL128(68739955140067328ULL, 542101086242752217LL), |
532 | | DEFINE_DECIMAL128(687399551400673280ULL, 5421010862427522170LL), |
533 | | }; |
534 | | |
535 | 0 | static double getDoubleScaleMultiplier(uint8_t scale) { |
536 | 0 | static double SCALE_MULTIPLIER_DOUBLE[TSDB_DECIMAL_MAX_PRECISION + 1] = {0}; |
537 | 0 | static bool initialized = false; |
538 | 0 | if (!initialized) { |
539 | 0 | SCALE_MULTIPLIER_DOUBLE[0] = 1.0; |
540 | 0 | for (int32_t idx = 1; idx <= TSDB_DECIMAL_MAX_PRECISION; ++idx) { |
541 | 0 | SCALE_MULTIPLIER_DOUBLE[idx] = SCALE_MULTIPLIER_DOUBLE[idx - 1] * 10; |
542 | 0 | } |
543 | 0 | initialized = true; |
544 | 0 | } |
545 | 0 | return SCALE_MULTIPLIER_DOUBLE[scale]; |
546 | 0 | }; |
547 | | |
548 | 0 | #define DECIMAL128_ONE SCALE_MULTIPLIER_128[0] |
549 | | #define DECIMAL128_TEN SCALE_MULTIPLIER_128[1] |
550 | | |
551 | | // To calculate how many bits for integer X. |
552 | | // eg. 999(3 digits) -> 1111100111(10 bits) -> bitsForNumDigits[3] = 10 |
553 | | static const int32_t bitsForNumDigits[] = {0, 4, 7, 10, 14, 17, 20, 24, 27, 30, 34, 37, 40, |
554 | | 44, 47, 50, 54, 57, 60, 64, 67, 70, 74, 77, 80, 84, |
555 | | 87, 90, 94, 97, 100, 103, 107, 110, 113, 117, 120, 123, 127}; |
556 | | |
557 | | #define DECIMAL128_GET_MAX(precision, pMax) \ |
558 | 0 | do { \ |
559 | 0 | *(pMax) = SCALE_MULTIPLIER_128[precision]; \ |
560 | 0 | decimal128Subtract(pMax, &DECIMAL128_ONE, DECIMAL_WORD_NUM(Decimal128)); \ |
561 | 0 | } while (0) |
562 | | |
563 | 0 | void makeDecimal128(Decimal128* pDec128, int64_t hi, uint64_t low) { |
564 | 0 | DECIMAL128_SET_HIGH_WORD(pDec128, hi); |
565 | 0 | DECIMAL128_SET_LOW_WORD(pDec128, low); |
566 | 0 | } |
567 | | |
568 | 0 | static void makeDecimal128FromDecimal64(Decimal128* pTarget, Decimal64 decimal64) { |
569 | 0 | bool negative = false; |
570 | 0 | if (DECIMAL64_SIGN(&decimal64) == -1) { |
571 | 0 | decimal64Negate(&decimal64); |
572 | 0 | negative = true; |
573 | 0 | } |
574 | 0 | makeDecimal128(pTarget, 0, DECIMAL64_GET_VALUE(&decimal64)); |
575 | 0 | if (negative) decimal128Negate(pTarget); |
576 | 0 | } |
577 | | |
578 | 0 | static void decimal128Negate(DecimalType* pWord) { |
579 | 0 | Decimal128* pDec = (Decimal128*)pWord; |
580 | 0 | uint64_t lo = ~DECIMAL128_LOW_WORD(pDec) + 1; |
581 | 0 | int64_t hi = ~DECIMAL128_HIGH_WORD(pDec); |
582 | 0 | if (lo == 0) hi = SAFE_INT64_ADD(hi, 1); |
583 | 0 | makeDecimal128(pDec, hi, lo); |
584 | 0 | } |
585 | | |
586 | 0 | static void decimal128Abs(DecimalType* pWord) { |
587 | 0 | if (DECIMAL128_SIGN((Decimal128*)pWord) == -1) { |
588 | 0 | decimal128Negate(pWord); |
589 | 0 | } |
590 | 0 | } |
591 | | |
592 | | #define DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pTarget, rightDec, pWord) \ |
593 | 0 | if (rightWordNum != DECIMAL_WORD_NUM(Decimal128)) { \ |
594 | 0 | Decimal64 d64 = {0}; \ |
595 | 0 | makeDecimal64(&d64, *(int64_t*)pWord); \ |
596 | 0 | makeDecimal128FromDecimal64(&rightDec, d64); \ |
597 | 0 | pTarget = &rightDec; \ |
598 | 0 | } |
599 | | |
600 | 0 | static void decimal128Add(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
601 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
602 | 0 | Decimal128 right = {0}; |
603 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
604 | |
|
605 | 0 | int64_t hi = SAFE_INT64_ADD(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec)); |
606 | 0 | uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) + DECIMAL128_LOW_WORD(pRightDec); |
607 | 0 | hi = SAFE_INT64_ADD(hi, lo < DECIMAL128_LOW_WORD(pLeftDec)); |
608 | 0 | makeDecimal128(pLeftDec, hi, lo); |
609 | 0 | } |
610 | | |
611 | 0 | static void decimal128Subtract(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
612 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
613 | 0 | Decimal128 right = {0}; |
614 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
615 | |
|
616 | 0 | int64_t hi = SAFE_INT64_SUBTRACT(DECIMAL128_HIGH_WORD(pLeftDec), DECIMAL128_HIGH_WORD(pRightDec)); |
617 | 0 | uint64_t lo = DECIMAL128_LOW_WORD(pLeftDec) - DECIMAL128_LOW_WORD(pRightDec); |
618 | 0 | hi = SAFE_INT64_SUBTRACT(hi, lo > DECIMAL128_LOW_WORD(pLeftDec)); |
619 | 0 | makeDecimal128(pLeftDec, hi, lo); |
620 | 0 | } |
621 | | |
622 | 0 | static void decimal128Multiply(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
623 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
624 | 0 | Decimal128 right = {0}; |
625 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
626 | |
|
627 | 0 | bool negate = DECIMAL128_SIGN(pLeftDec) != DECIMAL128_SIGN(pRightDec); |
628 | 0 | Decimal128 x = *pLeftDec, y = *pRightDec; |
629 | 0 | decimal128Abs(&x); |
630 | 0 | decimal128Abs(&y); |
631 | |
|
632 | 0 | UInt128 res = {0}, tmp = {0}; |
633 | 0 | makeUInt128(&res, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x)); |
634 | 0 | makeUInt128(&tmp, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y)); |
635 | 0 | uInt128Multiply(&res, &tmp); |
636 | 0 | makeDecimal128(pLeftDec, uInt128Hi(&res), uInt128Lo(&res)); |
637 | 0 | if (negate) decimal128Negate(pLeftDec); |
638 | 0 | } |
639 | | |
640 | 0 | static bool decimal128Lt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
641 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
642 | 0 | Decimal128 right = {0}; |
643 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
644 | |
|
645 | 0 | return DECIMAL128_HIGH_WORD(pLeftDec) < DECIMAL128_HIGH_WORD(pRightDec) || |
646 | 0 | (DECIMAL128_HIGH_WORD(pLeftDec) == DECIMAL128_HIGH_WORD(pRightDec) && |
647 | 0 | DECIMAL128_LOW_WORD(pLeftDec) < DECIMAL128_LOW_WORD(pRightDec)); |
648 | 0 | } |
649 | | |
650 | | static void decimal128Divide(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum, |
651 | 0 | DecimalType* pRemainder) { |
652 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, *pRemainderDec = (Decimal128*)pRemainder; |
653 | 0 | Decimal128 right = {0}; |
654 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
655 | |
|
656 | 0 | bool leftNegate = DECIMAL128_SIGN(pLeftDec) == -1, rightNegate = DECIMAL128_SIGN(pRightDec) == -1; |
657 | 0 | UInt128 a = {0}, b = {0}, c = {0}, d = {0}; |
658 | 0 | Decimal128 x = *pLeftDec, y = *pRightDec; |
659 | 0 | decimal128Abs(&x); |
660 | 0 | decimal128Abs(&y); |
661 | 0 | makeUInt128(&a, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x)); |
662 | 0 | makeUInt128(&d, DECIMAL128_HIGH_WORD(&x), DECIMAL128_LOW_WORD(&x)); |
663 | 0 | makeUInt128(&b, DECIMAL128_HIGH_WORD(&y), DECIMAL128_LOW_WORD(&y)); |
664 | 0 | uInt128Divide(&a, &b); |
665 | 0 | uInt128Mod(&d, &b); |
666 | 0 | makeDecimal128(pLeftDec, uInt128Hi(&a), uInt128Lo(&a)); |
667 | 0 | if (pRemainder) makeDecimal128(pRemainderDec, uInt128Hi(&d), uInt128Lo(&d)); |
668 | 0 | if (leftNegate != rightNegate) decimal128Negate(pLeftDec); |
669 | 0 | if (leftNegate && pRemainder) decimal128Negate(pRemainderDec); |
670 | 0 | } |
671 | | |
672 | 0 | static void decimal128Mod(DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
673 | 0 | Decimal128 pLeftDec = *(Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight, right = {0}; |
674 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
675 | |
|
676 | 0 | decimal128Divide(&pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal128), |
677 | 0 | pLeft); |
678 | 0 | } |
679 | | |
680 | 0 | static bool decimal128Gt(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
681 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
682 | 0 | Decimal128 right = {0}; |
683 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
684 | |
|
685 | 0 | return decimal128Lt(pRightDec, pLeftDec, DECIMAL_WORD_NUM(Decimal128)); |
686 | 0 | } |
687 | | |
688 | 0 | static bool decimal128Eq(const DecimalType* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
689 | 0 | Decimal128 *pLeftDec = (Decimal128*)pLeft, *pRightDec = (Decimal128*)pRight; |
690 | 0 | Decimal128 right = {0}; |
691 | 0 | DECIMAL128_CHECK_RIGHT_WORD_NUM(rightWordNum, pRightDec, right, pRight); |
692 | |
|
693 | 0 | return DECIMAL128_HIGH_WORD(pLeftDec) == DECIMAL128_HIGH_WORD(pRightDec) && |
694 | 0 | DECIMAL128_LOW_WORD(pLeftDec) == DECIMAL128_LOW_WORD(pRightDec); |
695 | 0 | } |
696 | | |
697 | | #define DIGIT_NUM_ONCE 18 |
698 | 0 | static void extractDecimal128Digits(const Decimal128* pDec, uint64_t* digits, int32_t* digitNum) { |
699 | 0 | UInt128 a = {0}; |
700 | 0 | UInt128 b = {0}; |
701 | 0 | *digitNum = 0; |
702 | 0 | makeUInt128(&a, DECIMAL128_HIGH_WORD(pDec), DECIMAL128_LOW_WORD(pDec)); |
703 | 0 | while (!uInt128Eq(&a, &uInt128Zero)) { |
704 | 0 | uint64_t hi = uInt128Hi(&a); |
705 | 0 | uint64_t lo = uInt128Lo(&a); |
706 | |
|
707 | 0 | uint64_t hiQuotient = hi / k1e18; |
708 | 0 | uint64_t hiRemainder = hi % k1e18; |
709 | 0 | makeUInt128(&b, hiRemainder, lo); |
710 | 0 | uInt128Divide(&b, &uInt128_1e18); |
711 | 0 | uint64_t loQuotient = uInt128Lo(&b); |
712 | 0 | makeUInt128(&b, hiRemainder, lo); |
713 | 0 | uInt128Mod(&b, &uInt128_1e18); |
714 | 0 | uint64_t loRemainder = uInt128Lo(&b); |
715 | 0 | makeUInt128(&a, hiQuotient, loQuotient); |
716 | 0 | digits[(*digitNum)++] = loRemainder; |
717 | 0 | } |
718 | 0 | } |
719 | | |
720 | 0 | int32_t decimal128ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32_t bufLen) { |
721 | 0 | if (!pBuf) return TSDB_CODE_INVALID_PARA; |
722 | 0 | const Decimal128* pDec = (const Decimal128*)pInt; |
723 | 0 | bool negative = DECIMAL128_SIGN(pDec) == -1; |
724 | 0 | uint64_t segments[3] = {0}; |
725 | 0 | int32_t digitNum = 0; |
726 | 0 | char buf[64] = {0}, buf2[64] = {0}; |
727 | 0 | int32_t len = 0; |
728 | 0 | if (negative) { |
729 | 0 | Decimal128 copy = {0}; |
730 | 0 | makeDecimal128(©, DECIMAL128_HIGH_WORD(pDec), DECIMAL128_LOW_WORD(pDec)); |
731 | 0 | decimal128Abs(©); |
732 | 0 | extractDecimal128Digits(©, segments, &digitNum); |
733 | 0 | TAOS_STRNCAT(buf2, "-", 2); |
734 | 0 | } else { |
735 | 0 | extractDecimal128Digits(pDec, segments, &digitNum); |
736 | 0 | } |
737 | 0 | if (digitNum == 0) { |
738 | 0 | TAOS_STRNCPY(pBuf, "0", bufLen); |
739 | 0 | return 0; |
740 | 0 | } |
741 | 0 | for (int32_t i = digitNum - 1; i >= 0; --i) { |
742 | 0 | len += snprintf(buf + len, 64 - len, i == digitNum - 1 ? "%" PRIu64 : "%018" PRIu64, segments[i]); |
743 | 0 | } |
744 | 0 | int32_t wholeLen = len - scale; |
745 | 0 | if (wholeLen > 0) { |
746 | 0 | TAOS_STRNCAT(buf2, buf, wholeLen); |
747 | 0 | } else { |
748 | 0 | TAOS_STRNCAT(buf2, "0", 2); |
749 | 0 | } |
750 | 0 | if (scale > 0) { |
751 | 0 | static const char *format = "0000000000000000000000000000000000000000"; |
752 | 0 | TAOS_STRNCAT(buf2, ".", 2); |
753 | 0 | if (wholeLen < 0) TAOS_STRNCAT(buf2, format, TABS(wholeLen)); |
754 | 0 | TAOS_STRNCAT(buf2, buf + TMAX(0, wholeLen), scale); |
755 | 0 | } |
756 | 0 | TAOS_STRNCPY(pBuf, buf2, bufLen); |
757 | 0 | return 0; |
758 | 0 | } |
759 | | int32_t decimalToStr(const DecimalType* pDec, int8_t dataType, int8_t precision, int8_t scale, char* pBuf, |
760 | 0 | int32_t bufLen) { |
761 | 0 | DecimalInternalType iType = DECIMAL_GET_INTERNAL_TYPE(dataType); |
762 | 0 | switch (iType) { |
763 | 0 | case DECIMAL_64: |
764 | 0 | return decimal64ToStr(pDec, scale, pBuf, bufLen); |
765 | 0 | case DECIMAL_128: |
766 | 0 | return decimal128ToStr(pDec, scale, pBuf, bufLen); |
767 | 0 | default: |
768 | 0 | break; |
769 | 0 | } |
770 | 0 | return TSDB_CODE_INVALID_PARA; |
771 | 0 | } |
772 | | |
773 | | static int32_t decimalAddLargePositive(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
774 | 0 | const SDataType* pOT) { |
775 | 0 | Decimal wholeX = *pX, wholeY = *pY, fracX = {0}, fracY = {0}; |
776 | 0 | decimal128Divide(&wholeX, &SCALE_MULTIPLIER_128[pXT->scale], DECIMAL_WORD_NUM(Decimal), &fracX); |
777 | 0 | decimal128Divide(&wholeY, &SCALE_MULTIPLIER_128[pYT->scale], DECIMAL_WORD_NUM(Decimal), &fracY); |
778 | |
|
779 | 0 | uint8_t maxScale = TMAX(pXT->scale, pYT->scale); |
780 | 0 | decimal128ScaleUp(&fracX, maxScale - pXT->scale); |
781 | 0 | decimal128ScaleUp(&fracY, maxScale - pYT->scale); |
782 | |
|
783 | 0 | Decimal pMultiplier = SCALE_MULTIPLIER_128[maxScale]; |
784 | 0 | Decimal right = fracX; |
785 | 0 | Decimal carry = {0}; |
786 | 0 | decimal128Subtract(&pMultiplier, &fracY, DECIMAL_WORD_NUM(Decimal)); |
787 | 0 | if (!decimal128Gt(&pMultiplier, &fracX, DECIMAL_WORD_NUM(Decimal))) { |
788 | 0 | decimal128Subtract(&right, &pMultiplier, DECIMAL_WORD_NUM(Decimal)); |
789 | 0 | makeDecimal128(&carry, 0, 1); |
790 | 0 | } else { |
791 | 0 | decimal128Add(&right, &fracY, DECIMAL_WORD_NUM(Decimal)); |
792 | 0 | } |
793 | |
|
794 | 0 | decimal128ScaleDown(&right, maxScale - pOT->scale, true); |
795 | 0 | if (decimal128AddCheckOverflow(&wholeX, &wholeY, DECIMAL_WORD_NUM(Decimal))) { |
796 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
797 | 0 | } |
798 | 0 | decimal128Add(&wholeX, &wholeY, DECIMAL_WORD_NUM(Decimal)); |
799 | 0 | if (decimal128AddCheckOverflow(&wholeX, &carry, DECIMAL_WORD_NUM(Decimal))) { |
800 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
801 | 0 | } |
802 | 0 | decimal128Add(&wholeX, &carry, DECIMAL_WORD_NUM(Decimal)); |
803 | 0 | decimal128Multiply(&wholeX, &SCALE_MULTIPLIER_128[pOT->scale], DECIMAL_WORD_NUM(Decimal)); |
804 | 0 | decimal128Add(&wholeX, &right, DECIMAL_WORD_NUM(Decimal)); |
805 | 0 | *pX = wholeX; |
806 | 0 | return 0; |
807 | 0 | } |
808 | | |
809 | | static void decimalAddLargeNegative(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
810 | 0 | const SDataType* pOT) { |
811 | 0 | Decimal wholeX = *pX, wholeY = *pY, fracX = {0}, fracY = {0}; |
812 | 0 | decimal128Divide(&wholeX, &SCALE_MULTIPLIER_128[pXT->scale], DECIMAL_WORD_NUM(Decimal), &fracX); |
813 | 0 | decimal128Divide(&wholeY, &SCALE_MULTIPLIER_128[pYT->scale], DECIMAL_WORD_NUM(Decimal), &fracY); |
814 | |
|
815 | 0 | uint8_t maxScale = TMAX(pXT->scale, pYT->scale); |
816 | 0 | decimal128ScaleUp(&fracX, maxScale - pXT->scale); |
817 | 0 | decimal128ScaleUp(&fracY, maxScale - pYT->scale); |
818 | |
|
819 | 0 | decimal128Add(&wholeX, &wholeY, DECIMAL_WORD_NUM(Decimal)); |
820 | 0 | decimal128Add(&fracX, &fracY, DECIMAL_WORD_NUM(Decimal)); |
821 | |
|
822 | 0 | if (DECIMAL128_SIGN(&wholeX) == -1 && decimal128Gt(&fracX, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal128))) { |
823 | 0 | decimal128Add(&wholeX, &DECIMAL128_ONE, DECIMAL_WORD_NUM(Decimal)); |
824 | 0 | decimal128Subtract(&fracX, &SCALE_MULTIPLIER_128[maxScale], DECIMAL_WORD_NUM(Decimal)); |
825 | 0 | } else if (decimal128Gt(&wholeX, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal128)) && DECIMAL128_SIGN(&fracX) == -1) { |
826 | 0 | decimal128Subtract(&wholeX, &DECIMAL128_ONE, DECIMAL_WORD_NUM(Decimal)); |
827 | 0 | decimal128Add(&fracX, &SCALE_MULTIPLIER_128[maxScale], DECIMAL_WORD_NUM(Decimal)); |
828 | 0 | } |
829 | |
|
830 | 0 | decimal128ScaleDown(&fracX, maxScale - pOT->scale, true); |
831 | 0 | decimal128Multiply(&wholeX, &SCALE_MULTIPLIER_128[pOT->scale], DECIMAL_WORD_NUM(Decimal)); |
832 | 0 | decimal128Add(&wholeX, &fracX, DECIMAL_WORD_NUM(Decimal)); |
833 | 0 | *pX = wholeX; |
834 | 0 | } |
835 | | |
836 | | static int32_t decimalAdd(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
837 | 0 | const SDataType* pOT) { |
838 | 0 | int32_t code = 0; |
839 | 0 | if (pOT->precision < TSDB_DECIMAL_MAX_PRECISION) { |
840 | 0 | uint8_t maxScale = TMAX(pXT->scale, pYT->scale); |
841 | 0 | Decimal tmpY = *pY; |
842 | 0 | decimal128ScaleTo(pX, pXT->scale, maxScale); |
843 | 0 | decimal128ScaleTo(&tmpY, pYT->scale, maxScale); |
844 | 0 | decimal128Add(pX, &tmpY, DECIMAL_WORD_NUM(Decimal)); |
845 | 0 | } else { |
846 | 0 | int8_t signX = DECIMAL128_SIGN(pX), signY = DECIMAL128_SIGN(pY); |
847 | 0 | if (signX == 1 && signY == 1) { |
848 | 0 | code = decimalAddLargePositive(pX, pXT, pY, pYT, pOT); |
849 | 0 | } else if (signX == -1 && signY == -1) { |
850 | 0 | decimal128Negate(pX); |
851 | 0 | Decimal y = *pY; |
852 | 0 | decimal128Negate(&y); |
853 | 0 | code = decimalAddLargePositive(pX, pXT, &y, pYT, pOT); |
854 | 0 | decimal128Negate(pX); |
855 | 0 | } else { |
856 | 0 | decimalAddLargeNegative(pX, pXT, pY, pYT, pOT); |
857 | 0 | } |
858 | 0 | } |
859 | 0 | return code; |
860 | 0 | } |
861 | | |
862 | 0 | static void makeInt256FromDecimal128(Int256* pTarget, const Decimal128* pDec) { |
863 | 0 | bool negative = DECIMAL128_SIGN(pDec) == -1; |
864 | 0 | Decimal128 abs = *pDec; |
865 | 0 | decimal128Abs(&abs); |
866 | 0 | UInt128 tmp = {DECIMAL128_LOW_WORD(&abs), DECIMAL128_HIGH_WORD(&abs)}; |
867 | 0 | *pTarget = makeInt256(int128Zero, tmp); |
868 | 0 | if (negative) { |
869 | 0 | *pTarget = int256Negate(pTarget); |
870 | 0 | } |
871 | 0 | } |
872 | | |
873 | 0 | static Int256 int256ScaleBy(const Int256* pX, int32_t scale) { |
874 | 0 | Int256 result = *pX; |
875 | 0 | if (scale > 0) { |
876 | 0 | Int256 multiplier = {0}; |
877 | 0 | makeInt256FromDecimal128(&multiplier, &SCALE_MULTIPLIER_128[scale]); |
878 | 0 | result = int256Multiply(pX, &multiplier); |
879 | 0 | } else if (scale < 0) { |
880 | 0 | Int256 divisor = {0}; |
881 | 0 | makeInt256FromDecimal128(&divisor, &SCALE_MULTIPLIER_128[-scale]); |
882 | 0 | result = int256Divide(pX, &divisor); |
883 | 0 | Int256 remainder = int256Mod(pX, &divisor); |
884 | 0 | Int256 afterShift = int256RightShift(&divisor, 1); |
885 | 0 | remainder = int256Abs(&remainder); |
886 | 0 | if (!int256Gt(&afterShift, &remainder)) { |
887 | 0 | if (int256Gt(pX, &int256Zero)) { |
888 | 0 | result = int256Add(&result, &int256One); |
889 | 0 | } else { |
890 | 0 | result = int256Subtract(&result, &int256One); |
891 | 0 | } |
892 | 0 | } |
893 | 0 | } |
894 | 0 | return result; |
895 | 0 | } |
896 | | |
897 | 0 | static bool convertInt256ToDecimal128(const Int256* pX, Decimal128* pDec) { |
898 | 0 | bool overflow = false; |
899 | 0 | Int256 abs = int256Abs(pX); |
900 | 0 | bool isNegative = int256Lt(pX, &int256Zero); |
901 | 0 | UInt128 low = int256Lo(&abs); |
902 | 0 | uint64_t lowLow= uInt128Lo(&low); |
903 | 0 | uint64_t lowHigh = uInt128Hi(&low); |
904 | 0 | Int256 afterShift = int256RightShift(&abs, 128); |
905 | |
|
906 | 0 | if (int256Gt(&afterShift, &int256Zero)) { |
907 | 0 | overflow = true; |
908 | 0 | } else if (lowHigh > INT64_MAX) { |
909 | 0 | overflow = true; |
910 | 0 | } else { |
911 | 0 | makeDecimal128(pDec, lowHigh, lowLow); |
912 | 0 | if (decimal128Gt(pDec, &decimal128Max, DECIMAL_WORD_NUM(Decimal128))) { |
913 | 0 | overflow = true; |
914 | 0 | } |
915 | 0 | } |
916 | 0 | if (isNegative) { |
917 | 0 | decimal128Negate(pDec); |
918 | 0 | } |
919 | 0 | return overflow; |
920 | 0 | } |
921 | | |
922 | | static int32_t decimalMultiply(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
923 | 0 | const SDataType* pOT) { |
924 | 0 | if (pOT->precision < TSDB_DECIMAL_MAX_PRECISION) { |
925 | 0 | decimal128Multiply(pX, pY, DECIMAL_WORD_NUM(Decimal)); |
926 | 0 | } else if (decimal128Eq(pX, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal)) || |
927 | 0 | decimal128Eq(pY, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal))) { |
928 | 0 | makeDecimal128(pX, 0, 0); |
929 | 0 | } else { |
930 | 0 | int8_t deltaScale = pXT->scale + pYT->scale - pOT->scale; |
931 | 0 | Decimal xAbs = *pX, yAbs = *pY; |
932 | 0 | decimal128Abs(&xAbs); |
933 | 0 | decimal128Abs(&yAbs); |
934 | 0 | if (deltaScale == 0) { |
935 | | // no need to trim scale |
936 | 0 | Decimal max = DECIMAL128_MAX; |
937 | |
|
938 | 0 | decimal128Divide(&max, &yAbs, DECIMAL_WORD_NUM(Decimal), NULL); |
939 | 0 | if (decimal128Gt(&xAbs, &max, DECIMAL_WORD_NUM(Decimal))) { |
940 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
941 | 0 | } else { |
942 | 0 | decimal128Multiply(pX, pY, DECIMAL_WORD_NUM(Decimal)); |
943 | 0 | } |
944 | 0 | } else { |
945 | 0 | int32_t leadingZeros = decimal128CountLeadingBinaryZeros(&xAbs) + decimal128CountLeadingBinaryZeros(&yAbs); |
946 | 0 | if (leadingZeros <= 128) { |
947 | | // need to trim scale |
948 | 0 | Int256 x256 = {0}, y256 = {0}; |
949 | 0 | makeInt256FromDecimal128(&x256, pX); |
950 | 0 | makeInt256FromDecimal128(&y256, pY); |
951 | 0 | Int256 res = int256Multiply(&x256, &y256); |
952 | 0 | if (deltaScale != 0) { |
953 | 0 | res = int256ScaleBy(&res, -deltaScale); |
954 | 0 | } |
955 | 0 | bool overflow = convertInt256ToDecimal128(&res, pX); |
956 | 0 | if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW; |
957 | 0 | } else { |
958 | | // no need to trim scale |
959 | 0 | if (deltaScale <= 38) { |
960 | 0 | decimal128Multiply(pX, pY, DECIMAL_WORD_NUM(Decimal)); |
961 | 0 | decimal128ScaleDown(pX, deltaScale, true); |
962 | 0 | } else { |
963 | 0 | makeDecimal128(pX, 0, 0); |
964 | 0 | } |
965 | 0 | } |
966 | 0 | } |
967 | 0 | } |
968 | 0 | return 0; |
969 | 0 | } |
970 | | |
971 | | static int32_t decimalDivide(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
972 | 0 | const SDataType* pOT) { |
973 | 0 | if (decimal128Eq(pY, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal))) { |
974 | 0 | return TSDB_CODE_DIVISION_BY_ZERO; |
975 | 0 | } |
976 | | |
977 | 0 | int8_t deltaScale = pOT->scale + pYT->scale - pXT->scale; |
978 | |
|
979 | 0 | Decimal xTmp = *pX; |
980 | 0 | decimal128Abs(&xTmp); |
981 | 0 | int32_t bitsOccupied = 128 - decimal128CountLeadingBinaryZeros(&xTmp); |
982 | 0 | if (bitsOccupied + bitsForNumDigits[deltaScale] <= 127) { |
983 | 0 | xTmp = *pX; |
984 | 0 | decimal128ScaleUp(&xTmp, deltaScale); |
985 | 0 | Decimal remainder = {0}; |
986 | 0 | decimal128Divide(&xTmp, pY, DECIMAL_WORD_NUM(Decimal), &remainder); |
987 | |
|
988 | 0 | Decimal tmpY = *pY; |
989 | 0 | decimal128Abs(&tmpY); |
990 | 0 | decimal128Multiply(&remainder, &decimal128Two, DECIMAL_WORD_NUM(Decimal)); |
991 | 0 | decimal128Abs(&remainder); |
992 | 0 | if (!decimal128Lt(&remainder, &tmpY, DECIMAL_WORD_NUM(Decimal))) { |
993 | 0 | Decimal64 extra = {(DECIMAL128_SIGN(pX) ^ DECIMAL128_SIGN(pY)) + 1}; |
994 | 0 | decimal128Add(&xTmp, &extra, DECIMAL_WORD_NUM(Decimal64)); |
995 | 0 | } |
996 | 0 | *pX = xTmp; |
997 | 0 | } else { |
998 | 0 | Int256 x256 = {0}, y256 = {0}; |
999 | 0 | makeInt256FromDecimal128(&x256, pX); |
1000 | 0 | Int256 xScaledUp = int256ScaleBy(&x256, deltaScale); |
1001 | 0 | makeInt256FromDecimal128(&y256, pY); |
1002 | 0 | Int256 res = int256Divide(&xScaledUp, &y256); |
1003 | 0 | Int256 remainder = int256Mod(&xScaledUp, &y256); |
1004 | |
|
1005 | 0 | remainder = int256Multiply(&remainder, &int256Two); |
1006 | 0 | remainder = int256Abs(&remainder); |
1007 | 0 | y256 = int256Abs(&y256); |
1008 | 0 | if (!int256Lt(&remainder, &y256)) { |
1009 | 0 | if ((DECIMAL128_SIGN(pX) ^ DECIMAL128_SIGN(pY)) == 0) { |
1010 | 0 | res = int256Add(&res, &int256One); |
1011 | 0 | } else { |
1012 | 0 | res = int256Subtract(&res, &int256One); |
1013 | 0 | } |
1014 | 0 | } |
1015 | 0 | bool overflow = convertInt256ToDecimal128(&res, pX); |
1016 | 0 | if (overflow) return TSDB_CODE_DECIMAL_OVERFLOW; |
1017 | 0 | } |
1018 | 0 | return 0; |
1019 | 0 | } |
1020 | | |
1021 | | static int32_t decimalMod(Decimal* pX, const SDataType* pXT, const Decimal* pY, const SDataType* pYT, |
1022 | 0 | const SDataType* pOT) { |
1023 | 0 | if (decimal128Eq(pY, &DECIMAL128_ZERO, DECIMAL_WORD_NUM(Decimal))) { |
1024 | 0 | return TSDB_CODE_DIVISION_BY_ZERO; |
1025 | 0 | } |
1026 | 0 | Decimal xAbs = *pX, yAbs = *pY; |
1027 | 0 | decimal128Abs(&xAbs); |
1028 | 0 | decimal128Abs(&yAbs); |
1029 | 0 | int32_t xlz = decimal128CountLeadingBinaryZeros(&xAbs), ylz = decimal128CountLeadingBinaryZeros(&yAbs); |
1030 | 0 | if (pXT->scale < pYT->scale) { |
1031 | | // x scale up |
1032 | 0 | xlz = xlz - bitsForNumDigits[pYT->scale - pXT->scale]; |
1033 | 0 | } else if (pXT->scale > pYT->scale) { |
1034 | | // y scale up |
1035 | 0 | ylz = ylz - bitsForNumDigits[pXT->scale - pYT->scale]; |
1036 | 0 | } |
1037 | 0 | int32_t lz = TMIN(xlz, ylz); |
1038 | 0 | if (lz >= 2) { |
1039 | | // it's safe to scale up |
1040 | 0 | yAbs = *pY; |
1041 | 0 | decimal128ScaleTo(pX, pXT->scale, TMAX(pXT->scale, pYT->scale)); |
1042 | 0 | decimal128ScaleTo(&yAbs, pYT->scale, TMAX(pXT->scale, pYT->scale)); |
1043 | 0 | decimal128Mod(pX, &yAbs, DECIMAL_WORD_NUM(Decimal)); |
1044 | 0 | } else { |
1045 | 0 | Int256 x256 = {0}, y256 = {0}; |
1046 | 0 | makeInt256FromDecimal128(&x256, pX); |
1047 | 0 | makeInt256FromDecimal128(&y256, pY); |
1048 | 0 | if (pXT->scale < pYT->scale) { |
1049 | 0 | x256 = int256ScaleBy(&x256, pYT->scale - pXT->scale); |
1050 | 0 | } else if (pXT->scale > pYT->scale) { |
1051 | 0 | y256 = int256ScaleBy(&y256, pXT->scale - pYT->scale); |
1052 | 0 | } |
1053 | 0 | Int256 res = int256Mod(&x256, &y256); |
1054 | 0 | if (convertInt256ToDecimal128(&res, pX)) { |
1055 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1056 | 0 | } |
1057 | 0 | } |
1058 | 0 | return 0; |
1059 | 0 | } |
1060 | | |
1061 | | int32_t decimalOp(EOperatorType op, const SDataType* pLeftT, const SDataType* pRightT, const SDataType* pOutT, |
1062 | 0 | const void* pLeftData, const void* pRightData, void* pOutputData) { |
1063 | 0 | int32_t code = 0; |
1064 | |
|
1065 | 0 | Decimal left = {0}, right = {0}; |
1066 | 0 | SDataType lt = {.type = TSDB_DATA_TYPE_DECIMAL, |
1067 | 0 | .precision = TSDB_DECIMAL_MAX_PRECISION, |
1068 | 0 | .bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes, |
1069 | 0 | .scale = pLeftT->scale}; |
1070 | 0 | SDataType rt = {.type = TSDB_DATA_TYPE_DECIMAL, |
1071 | 0 | .precision = TSDB_DECIMAL_MAX_PRECISION, |
1072 | 0 | .bytes = tDataTypes[TSDB_DATA_TYPE_DECIMAL].bytes, |
1073 | 0 | .scale = 0}; |
1074 | 0 | if (pRightT) rt.scale = pRightT->scale; |
1075 | 0 | if (TSDB_DATA_TYPE_DECIMAL != pLeftT->type) { |
1076 | 0 | code = convertToDecimal(pLeftData, pLeftT, &left, <); |
1077 | 0 | if (TSDB_CODE_SUCCESS != code) return code; |
1078 | 0 | } else { |
1079 | 0 | left = *(Decimal*)pLeftData; |
1080 | 0 | } |
1081 | 0 | if (pRightT && TSDB_DATA_TYPE_DECIMAL != pRightT->type) { |
1082 | 0 | code = convertToDecimal(pRightData, pRightT, &right, &rt); |
1083 | 0 | if (TSDB_CODE_SUCCESS != code) return code; |
1084 | 0 | pRightData = &right; |
1085 | 0 | } else if (pRightData){ |
1086 | 0 | right = *(Decimal*)pRightData; |
1087 | 0 | } |
1088 | | #ifdef DEBUG |
1089 | | char left_var[64] = {0}, right_var[64] = {0}; |
1090 | | decimal128ToStr(&left, lt.scale, left_var, 64); |
1091 | | decimal128ToStr(&right, rt.scale, right_var, 64); |
1092 | | #endif |
1093 | | |
1094 | 0 | switch (op) { |
1095 | 0 | case OP_TYPE_ADD: |
1096 | 0 | code = decimalAdd(&left, <, &right, &rt, pOutT); |
1097 | 0 | break; |
1098 | 0 | case OP_TYPE_SUB: |
1099 | 0 | decimal128Negate(&right); |
1100 | 0 | code = decimalAdd(&left, <, &right, &rt, pOutT); |
1101 | 0 | break; |
1102 | 0 | case OP_TYPE_MULTI: |
1103 | 0 | code = decimalMultiply(&left, <, &right, &rt, pOutT); |
1104 | 0 | break; |
1105 | 0 | case OP_TYPE_DIV: |
1106 | 0 | code = decimalDivide(&left, <, &right, &rt, pOutT); |
1107 | 0 | break; |
1108 | 0 | case OP_TYPE_REM: |
1109 | 0 | code = decimalMod(&left, <, &right, &rt, pOutT); |
1110 | 0 | break; |
1111 | 0 | case OP_TYPE_MINUS: |
1112 | 0 | decimal128Negate(&left); |
1113 | 0 | break; |
1114 | 0 | default: |
1115 | 0 | code = TSDB_CODE_TSC_INVALID_OPERATION; |
1116 | 0 | break; |
1117 | 0 | } |
1118 | 0 | if (0 == code && pOutT->type != TSDB_DATA_TYPE_DECIMAL) { |
1119 | 0 | lt = *pOutT; |
1120 | 0 | lt.type = TSDB_DATA_TYPE_DECIMAL; |
1121 | 0 | code = convertToDecimal(&left, <, pOutputData, pOutT); |
1122 | 0 | } else { |
1123 | 0 | *(Decimal*)pOutputData = left; |
1124 | 0 | } |
1125 | 0 | return code; |
1126 | 0 | } |
1127 | | |
1128 | 0 | bool doCompareDecimal128(EOperatorType op, const Decimal128* pLeftDec, const Decimal128* pRightDec) { |
1129 | 0 | switch (op) { |
1130 | 0 | case OP_TYPE_GREATER_THAN: |
1131 | 0 | return decimal128Gt(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1132 | 0 | case OP_TYPE_GREATER_EQUAL: |
1133 | 0 | return !decimal128Lt(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1134 | 0 | case OP_TYPE_LOWER_THAN: |
1135 | 0 | return decimal128Lt(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1136 | 0 | case OP_TYPE_LOWER_EQUAL: |
1137 | 0 | return !decimal128Gt(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1138 | 0 | case OP_TYPE_EQUAL: |
1139 | 0 | return decimal128Eq(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1140 | 0 | case OP_TYPE_NOT_EQUAL: |
1141 | 0 | return !decimal128Eq(pLeftDec, pRightDec, DECIMAL_WORD_NUM(Decimal)); |
1142 | 0 | default: |
1143 | 0 | break; |
1144 | 0 | } |
1145 | 0 | return false; |
1146 | 0 | } |
1147 | | |
1148 | 0 | bool decimal64Compare(EOperatorType op, const SDecimalCompareCtx* pLeft, const SDecimalCompareCtx* pRight) { |
1149 | 0 | bool ret = false; |
1150 | 0 | uint8_t leftPrec = 0, leftScale = 0, rightPrec = 0, rightScale = 0; |
1151 | 0 | decimalFromTypeMod(pLeft->typeMod, &leftPrec, &leftScale); |
1152 | 0 | decimalFromTypeMod(pRight->typeMod, &rightPrec, &rightScale); |
1153 | 0 | int32_t deltaScale = leftScale - rightScale; |
1154 | |
|
1155 | 0 | Decimal64 leftDec = *(Decimal64*)pLeft->pData, rightDec = *(Decimal64*)pRight->pData; |
1156 | |
|
1157 | 0 | if (deltaScale != 0) { |
1158 | 0 | bool needInt128 = (deltaScale < 0 && leftPrec - deltaScale > TSDB_DECIMAL64_MAX_PRECISION) || |
1159 | 0 | (rightPrec + deltaScale > TSDB_DECIMAL64_MAX_PRECISION); |
1160 | 0 | if (needInt128) { |
1161 | 0 | Decimal128 dec128L = {0}, dec128R = {0}; |
1162 | 0 | makeDecimal128FromDecimal64(&dec128L, leftDec); |
1163 | 0 | makeDecimal128FromDecimal64(&dec128R, rightDec); |
1164 | 0 | return doCompareDecimal128(op, &dec128L, &dec128R); |
1165 | 0 | } else { |
1166 | 0 | if (deltaScale < 0) { |
1167 | 0 | decimal64ScaleUp(&leftDec, -deltaScale); |
1168 | 0 | } else { |
1169 | 0 | decimal64ScaleUp(&rightDec, deltaScale); |
1170 | 0 | } |
1171 | 0 | } |
1172 | 0 | } |
1173 | | |
1174 | 0 | switch (op) { |
1175 | 0 | case OP_TYPE_GREATER_THAN: |
1176 | 0 | return decimal64Gt(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1177 | 0 | case OP_TYPE_GREATER_EQUAL: |
1178 | 0 | return !decimal64Lt(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1179 | 0 | case OP_TYPE_LOWER_THAN: |
1180 | 0 | return decimal64Lt(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1181 | 0 | case OP_TYPE_LOWER_EQUAL: |
1182 | 0 | return !decimal64Gt(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1183 | 0 | case OP_TYPE_EQUAL: |
1184 | 0 | return decimal64Eq(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1185 | 0 | case OP_TYPE_NOT_EQUAL: |
1186 | 0 | return !decimal64Eq(&leftDec, &rightDec, DECIMAL_WORD_NUM(Decimal64)); |
1187 | 0 | default: |
1188 | 0 | break; |
1189 | 0 | } |
1190 | 0 | return ret; |
1191 | 0 | } |
1192 | | |
1193 | 0 | bool decimalCompare(EOperatorType op, const SDecimalCompareCtx* pLeft, const SDecimalCompareCtx* pRight) { |
1194 | 0 | if (pLeft->type == TSDB_DATA_TYPE_DECIMAL64 && pRight->type == TSDB_DATA_TYPE_DECIMAL64) { |
1195 | 0 | return decimal64Compare(op, pLeft, pRight); |
1196 | 0 | } |
1197 | 0 | bool ret = false; |
1198 | 0 | uint8_t leftPrec = 0, leftScale = 0, rightPrec = 0, rightScale = 0; |
1199 | 0 | decimalFromTypeMod(pLeft->typeMod, &leftPrec, &leftScale); |
1200 | 0 | decimalFromTypeMod(pRight->typeMod, &rightPrec, &rightScale); |
1201 | |
|
1202 | 0 | if (pLeft->type == TSDB_DATA_TYPE_DECIMAL64) { |
1203 | 0 | Decimal128 dec128 = {0}; |
1204 | 0 | makeDecimal128FromDecimal64(&dec128, *(Decimal64*)pLeft->pData); |
1205 | 0 | SDecimalCompareCtx leftCtx = {.pData = &dec128, |
1206 | 0 | .type = TSDB_DATA_TYPE_DECIMAL, |
1207 | 0 | .typeMod = decimalCalcTypeMod(TSDB_DECIMAL128_MAX_PRECISION, leftScale)}; |
1208 | 0 | return decimalCompare(op, &leftCtx, pRight); |
1209 | 0 | } else if (pRight->type == TSDB_DATA_TYPE_DECIMAL64) { |
1210 | 0 | Decimal128 dec128 = {0}; |
1211 | 0 | makeDecimal128FromDecimal64(&dec128, *(Decimal64*)pRight->pData); |
1212 | 0 | SDecimalCompareCtx rightCtx = {.pData = &dec128, |
1213 | 0 | .type = TSDB_DATA_TYPE_DECIMAL, |
1214 | 0 | .typeMod = decimalCalcTypeMod(TSDB_DECIMAL128_MAX_PRECISION, rightScale)}; |
1215 | 0 | return decimalCompare(op, pLeft, &rightCtx); |
1216 | 0 | } |
1217 | 0 | int32_t deltaScale = leftScale - rightScale; |
1218 | 0 | Decimal pLeftDec = *(Decimal*)pLeft->pData, pRightDec = *(Decimal*)pRight->pData; |
1219 | |
|
1220 | 0 | if (deltaScale != 0) { |
1221 | 0 | bool needInt256 = (deltaScale < 0 && leftPrec - deltaScale > TSDB_DECIMAL_MAX_PRECISION) || |
1222 | 0 | (rightPrec + deltaScale > TSDB_DECIMAL_MAX_PRECISION); |
1223 | 0 | if (needInt256) { |
1224 | 0 | Int256 x = {0}, y = {0}; |
1225 | 0 | makeInt256FromDecimal128(&x, &pLeftDec); |
1226 | 0 | makeInt256FromDecimal128(&y, &pRightDec); |
1227 | 0 | if (leftScale < rightScale) { |
1228 | 0 | x = int256ScaleBy(&x, rightScale - leftScale); |
1229 | 0 | } else { |
1230 | 0 | y = int256ScaleBy(&y, leftScale - rightScale); |
1231 | 0 | } |
1232 | 0 | switch (op) { |
1233 | 0 | case OP_TYPE_GREATER_THAN: |
1234 | 0 | return int256Gt(&x, &y); |
1235 | 0 | case OP_TYPE_GREATER_EQUAL: |
1236 | 0 | return !int256Lt(&x, &y); |
1237 | 0 | case OP_TYPE_LOWER_THAN: |
1238 | 0 | return int256Lt(&x, &y); |
1239 | 0 | case OP_TYPE_LOWER_EQUAL: |
1240 | 0 | return !int256Gt(&x, &y); |
1241 | 0 | case OP_TYPE_EQUAL: |
1242 | 0 | return int256Eq(&x, &y); |
1243 | 0 | case OP_TYPE_NOT_EQUAL: |
1244 | 0 | return !int256Eq(&x, &y); |
1245 | 0 | default: |
1246 | 0 | break; |
1247 | 0 | } |
1248 | 0 | return false; |
1249 | 0 | } else { |
1250 | 0 | if (deltaScale < 0) { |
1251 | 0 | decimal128ScaleUp(&pLeftDec, -deltaScale); |
1252 | 0 | } else { |
1253 | 0 | decimal128ScaleUp(&pRightDec, deltaScale); |
1254 | 0 | } |
1255 | 0 | } |
1256 | 0 | } |
1257 | 0 | return doCompareDecimal128(op, &pLeftDec, &pRightDec); |
1258 | 0 | } |
1259 | | |
1260 | 0 | #define ABS_INT64(v) (v) == INT64_MIN ? (uint64_t)INT64_MAX + 1 : (uint64_t)llabs(v) |
1261 | | #define ABS_UINT64(v) (v) |
1262 | | |
1263 | 0 | static int64_t int64FromDecimal64(const DecimalType* pDec, uint8_t prec, uint8_t scale) { |
1264 | 0 | Decimal64 rounded = *(Decimal64*)pDec; |
1265 | 0 | bool overflow = false; |
1266 | 0 | decimal64RoundWithPositiveScale(&rounded, prec, scale, prec, 0, ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1267 | 0 | if (overflow) return 0; |
1268 | | |
1269 | 0 | return DECIMAL64_GET_VALUE(&rounded); |
1270 | 0 | } |
1271 | | |
1272 | 0 | static uint64_t uint64FromDecimal64(const DecimalType* pDec, uint8_t prec, uint8_t scale) { |
1273 | 0 | Decimal64 rounded = *(Decimal64*)pDec; |
1274 | 0 | bool overflow = false; |
1275 | 0 | decimal64RoundWithPositiveScale(&rounded, prec, scale, prec, 0, ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1276 | 0 | if (overflow) return 0; |
1277 | | |
1278 | 0 | return DECIMAL64_GET_VALUE(&rounded); |
1279 | 0 | } |
1280 | | |
1281 | 0 | static int32_t decimal64FromInt64(DecimalType* pDec, uint8_t prec, uint8_t scale, int64_t val) { |
1282 | 0 | Decimal64 max = {0}; |
1283 | 0 | DECIMAL64_GET_MAX(prec - scale, &max); |
1284 | 0 | if (DECIMAL64_GET_VALUE(&max) < val || -DECIMAL64_GET_VALUE(&max) > val) { |
1285 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1286 | 0 | } |
1287 | 0 | DECIMAL64_SET_VALUE((Decimal64*)pDec, val); |
1288 | 0 | decimal64ScaleUp(pDec, scale); |
1289 | 0 | return 0; |
1290 | 0 | } |
1291 | | |
1292 | 0 | static int32_t decimal64FromUint64(DecimalType* pDec, uint8_t prec, uint8_t scale, uint64_t val) { |
1293 | 0 | Decimal64 max = {0}; |
1294 | 0 | DECIMAL64_GET_MAX(prec - scale, &max); |
1295 | 0 | if ((uint64_t)DECIMAL64_GET_VALUE(&max) < val) return TSDB_CODE_DECIMAL_OVERFLOW; |
1296 | 0 | DECIMAL64_SET_VALUE((Decimal64*)pDec, val); |
1297 | 0 | decimal64ScaleUp(pDec, scale); |
1298 | 0 | return 0; |
1299 | 0 | } |
1300 | | |
1301 | 0 | static int32_t decimal64FromDouble(DecimalType* pDec, uint8_t prec, uint8_t scale, double val) { |
1302 | 0 | double unscaled = val * getDoubleScaleMultiplier(scale); |
1303 | 0 | if (isnan(unscaled)) { |
1304 | 0 | goto __OVERFLOW__; |
1305 | 0 | } |
1306 | 0 | unscaled = round(unscaled); |
1307 | |
|
1308 | 0 | bool negative = unscaled < 0 ? true : false; |
1309 | 0 | double abs = TABS(unscaled); |
1310 | 0 | if (abs > ldexp(1.0, 63) - 1) { |
1311 | 0 | goto __OVERFLOW__; |
1312 | 0 | } |
1313 | | |
1314 | 0 | uint64_t result = (uint64_t)abs; |
1315 | 0 | makeDecimal64(pDec, result); |
1316 | 0 | Decimal64 max = {0}; |
1317 | 0 | DECIMAL64_GET_MAX(prec, &max); |
1318 | 0 | if (decimal64Gt(pDec, &max, DECIMAL_WORD_NUM(Decimal64))) goto __OVERFLOW__; |
1319 | 0 | if (negative) decimal64Negate(pDec); |
1320 | 0 | return 0; |
1321 | | |
1322 | 0 | __OVERFLOW__: |
1323 | 0 | makeDecimal64(pDec, 0); |
1324 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1325 | 0 | } |
1326 | | |
1327 | | static int32_t decimal64FromDecimal128(DecimalType* pDec, uint8_t prec, uint8_t scale, const DecimalType* pVal, |
1328 | 0 | uint8_t valPrec, uint8_t valScale) { |
1329 | 0 | Decimal128 dec128 = *(Decimal128*)pVal, tmpDec128 = {0}; |
1330 | 0 | bool negative = DECIMAL128_SIGN(&dec128) == -1; |
1331 | 0 | if (negative) decimal128Negate(&dec128); |
1332 | 0 | tmpDec128 = dec128; |
1333 | |
|
1334 | 0 | Decimal64 max = {0}; |
1335 | 0 | DECIMAL64_GET_MAX(prec - scale, &max); |
1336 | 0 | decimal128ScaleDown(&dec128, valScale, false); |
1337 | 0 | if (decimal128Gt(&dec128, &max, DECIMAL_WORD_NUM(Decimal64))) { |
1338 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1339 | 0 | } |
1340 | 0 | decimal128ScaleTo(&tmpDec128, valScale, scale); |
1341 | 0 | DECIMAL64_SET_VALUE((Decimal64*)pDec, DECIMAL128_LOW_WORD(&tmpDec128)); |
1342 | 0 | DECIMAL64_GET_MAX(prec, &max); |
1343 | 0 | if (decimal64Lt(&max, pDec, DECIMAL_WORD_NUM(Decimal64))) { |
1344 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1345 | 0 | } |
1346 | 0 | if (negative) decimal64Negate(pDec); |
1347 | 0 | return 0; |
1348 | 0 | } |
1349 | | |
1350 | | static int32_t decimal64FromDecimal64(DecimalType* pDec, uint8_t prec, uint8_t scale, const DecimalType* pVal, |
1351 | 0 | uint8_t valPrec, uint8_t valScale) { |
1352 | 0 | Decimal64 dec64 = *(Decimal64*)pVal, max = {0}; |
1353 | 0 | bool negative = DECIMAL64_SIGN(&dec64) == -1; |
1354 | 0 | if (negative) decimal64Negate(&dec64); |
1355 | 0 | *(Decimal64*)pDec = dec64; |
1356 | |
|
1357 | 0 | DECIMAL64_GET_MAX(prec - scale, &max); |
1358 | 0 | decimal64ScaleDown(&dec64, valScale, false); |
1359 | 0 | if (decimal64Lt(&max, &dec64, DECIMAL_WORD_NUM(Decimal64))) { |
1360 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1361 | 0 | } |
1362 | 0 | decimal64ScaleTo(pDec, valScale, scale); |
1363 | 0 | DECIMAL64_GET_MAX(prec, &max); |
1364 | 0 | if (decimal64Lt(&max, pDec, DECIMAL_WORD_NUM(Decimal64))) { |
1365 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1366 | 0 | } |
1367 | 0 | if (negative) decimal64Negate(pDec); |
1368 | 0 | return 0; |
1369 | 0 | } |
1370 | | |
1371 | 0 | static int64_t int64FromDecimal128(const DecimalType* pDec, uint8_t prec, uint8_t scale) { |
1372 | 0 | Decimal128 rounded = *(Decimal128*)pDec; |
1373 | 0 | bool overflow = false; |
1374 | 0 | decimal128RoundWithPositiveScale(&rounded, prec, scale, prec, 0, ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1375 | 0 | if (overflow) { |
1376 | 0 | return 0; |
1377 | 0 | } |
1378 | 0 | Decimal128 max = {0}, min = {0}; |
1379 | 0 | (void)decimal128FromInt64(&max, TSDB_DECIMAL128_MAX_PRECISION, 0, INT64_MAX); |
1380 | 0 | (void)decimal128FromInt64(&min, TSDB_DECIMAL128_MAX_PRECISION, 0, INT64_MIN); |
1381 | 0 | if (decimal128Gt(&rounded, &max, DECIMAL_WORD_NUM(Decimal128)) || decimal128Lt(&rounded, &min, DECIMAL_WORD_NUM(Decimal128))) { |
1382 | 0 | overflow = true; |
1383 | 0 | return (int64_t)DECIMAL128_LOW_WORD(&rounded); |
1384 | 0 | } |
1385 | | |
1386 | 0 | return (int64_t)DECIMAL128_LOW_WORD(&rounded); |
1387 | 0 | } |
1388 | | |
1389 | 0 | static uint64_t uint64FromDecimal128(const DecimalType* pDec, uint8_t prec, uint8_t scale) { |
1390 | 0 | Decimal128 rounded = *(Decimal128*)pDec; |
1391 | 0 | bool overflow = false; |
1392 | 0 | decimal128RoundWithPositiveScale(&rounded, prec, scale, prec, 0, ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1393 | 0 | if (overflow) return 0; |
1394 | | |
1395 | 0 | Decimal128 max = {0}; |
1396 | 0 | (void)decimal128FromUint64(&max, TSDB_DECIMAL128_MAX_PRECISION, 0, UINT64_MAX); |
1397 | 0 | if (decimal128Gt(&rounded, &max, DECIMAL_WORD_NUM(Decimal128)) || |
1398 | 0 | decimal128Lt(&rounded, &decimal128Zero, DECIMAL_WORD_NUM(Decimal128))) { |
1399 | 0 | overflow = true; |
1400 | 0 | return DECIMAL128_LOW_WORD(&rounded); |
1401 | 0 | } |
1402 | 0 | return DECIMAL128_LOW_WORD(&rounded); |
1403 | 0 | } |
1404 | | |
1405 | 0 | static int32_t decimal128FromInt64(DecimalType* pDec, uint8_t prec, uint8_t scale, int64_t val) { |
1406 | 0 | if (prec - scale <= 18) { |
1407 | 0 | Decimal64 max = {0}; |
1408 | 0 | DECIMAL64_GET_MAX(prec - scale, &max); |
1409 | 0 | if (DECIMAL64_GET_VALUE(&max) < val || -DECIMAL64_GET_VALUE(&max) > val) return TSDB_CODE_DECIMAL_OVERFLOW; |
1410 | 0 | } |
1411 | 0 | uint64_t valAbs = ABS_INT64(val); |
1412 | 0 | makeDecimal128(pDec, 0, valAbs); |
1413 | 0 | if (val < 0) decimal128Negate(pDec); |
1414 | 0 | decimal128ScaleUp(pDec, scale); |
1415 | 0 | return 0; |
1416 | 0 | } |
1417 | | |
1418 | 0 | static int32_t decimal128FromUint64(DecimalType* pDec, uint8_t prec, uint8_t scale, uint64_t val) { |
1419 | 0 | if (prec - scale <= 19) { |
1420 | 0 | Decimal128 max = {0}, decVal = {0}; |
1421 | 0 | DECIMAL128_GET_MAX(prec - scale, &max); |
1422 | 0 | makeDecimal128(&decVal, 0, val); |
1423 | 0 | if (decimal128Gt(&decVal, &max, DECIMAL_WORD_NUM(Decimal128))) { |
1424 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1425 | 0 | } |
1426 | 0 | } |
1427 | 0 | makeDecimal128(pDec, 0, val); |
1428 | 0 | decimal128ScaleUp(pDec, scale); |
1429 | 0 | return 0; |
1430 | 0 | } |
1431 | | |
1432 | 0 | static int32_t decimal128FromDouble(DecimalType* pDec, uint8_t prec, uint8_t scale, double val) { |
1433 | 0 | double unscaled = val * getDoubleScaleMultiplier(scale); |
1434 | 0 | if (isnan(unscaled)) { |
1435 | 0 | goto __OVERFLOW__; |
1436 | 0 | } |
1437 | 0 | unscaled = round(unscaled); |
1438 | |
|
1439 | 0 | bool negative = unscaled < 0 ? true : false; |
1440 | 0 | double abs = TABS(unscaled); |
1441 | 0 | if (abs > ldexp(1.0, 127) - 1) { |
1442 | 0 | goto __OVERFLOW__; |
1443 | 0 | } |
1444 | | |
1445 | 0 | uint64_t hi = (uint64_t)ldexp(abs, -64), lo = (uint64_t)(abs - ldexp((double)hi, 64)); |
1446 | 0 | makeDecimal128(pDec, hi, lo); |
1447 | 0 | Decimal128 max = {0}; |
1448 | 0 | DECIMAL128_GET_MAX(prec, &max); |
1449 | 0 | if (decimal128Gt(pDec, &max, DECIMAL_WORD_NUM(Decimal128))) goto __OVERFLOW__; |
1450 | 0 | if (negative) decimal128Negate(pDec); |
1451 | 0 | return 0; |
1452 | | |
1453 | 0 | __OVERFLOW__: |
1454 | 0 | *(Decimal128*)pDec = decimal128Zero; |
1455 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1456 | 0 | } |
1457 | | |
1458 | | static int32_t decimal128FromDecimal64(DecimalType* pDec, uint8_t prec, uint8_t scale, const DecimalType* pVal, |
1459 | 0 | uint8_t valPrec, uint8_t valScale) { |
1460 | 0 | Decimal64 dec64 = *(Decimal64*)pVal; |
1461 | 0 | bool negative = DECIMAL64_SIGN(&dec64) == -1; |
1462 | 0 | if (negative) decimal64Negate(&dec64); |
1463 | |
|
1464 | 0 | makeDecimal128(pDec, 0, DECIMAL64_GET_VALUE(&dec64)); |
1465 | 0 | Decimal128 max = {0}; |
1466 | 0 | DECIMAL128_GET_MAX(prec - scale, &max); |
1467 | 0 | decimal64ScaleDown(&dec64, valScale, false); |
1468 | 0 | if (decimal128Lt(&max, &dec64, DECIMAL_WORD_NUM(Decimal64))) { |
1469 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1470 | 0 | } |
1471 | 0 | decimal128ScaleTo(pDec, valScale, scale); |
1472 | 0 | DECIMAL128_GET_MAX(prec, &max); |
1473 | 0 | if (decimal128Lt(&max, pDec, DECIMAL_WORD_NUM(Decimal128))) { |
1474 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1475 | 0 | } |
1476 | 0 | if (negative) decimal128Negate(pDec); |
1477 | 0 | return 0; |
1478 | 0 | } |
1479 | | |
1480 | | static int32_t decimal128FromDecimal128(DecimalType* pDec, uint8_t prec, uint8_t scale, const DecimalType* pVal, |
1481 | 0 | uint8_t valPrec, uint8_t valScale) { |
1482 | 0 | bool negative = DECIMAL128_SIGN((Decimal128*)pVal) == -1; |
1483 | 0 | Decimal128 tmpDec = *(Decimal128*)pVal; |
1484 | 0 | if (negative) decimal128Negate(&tmpDec); |
1485 | 0 | *(Decimal128*)pDec = tmpDec; |
1486 | |
|
1487 | 0 | Decimal128 max = {0}; |
1488 | 0 | DECIMAL128_GET_MAX(prec - scale, &max); |
1489 | 0 | decimal128ScaleDown(&tmpDec, valScale, false); |
1490 | 0 | if (decimal128Lt(&max, &tmpDec, DECIMAL_WORD_NUM(Decimal128))) { |
1491 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1492 | 0 | } |
1493 | 0 | decimal128ScaleTo(pDec, valScale, scale); |
1494 | 0 | DECIMAL128_GET_MAX(prec, &max); |
1495 | 0 | if (decimal128Lt(&max, pDec, DECIMAL_WORD_NUM(Decimal128))) { |
1496 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1497 | 0 | } |
1498 | 0 | if (negative) decimal128Negate(pDec); |
1499 | 0 | return 0; |
1500 | 0 | } |
1501 | | |
1502 | | #define CONVERT_TO_DECIMAL(pData, pInputType, pOut, pOutType, decimal) \ |
1503 | 0 | do { \ |
1504 | 0 | int64_t val = 0; \ |
1505 | 0 | uint64_t uval = 0; \ |
1506 | 0 | double dval = 0; \ |
1507 | 0 | switch (pInputType->type) { \ |
1508 | 0 | case TSDB_DATA_TYPE_NULL: \ |
1509 | 0 | break; \ |
1510 | 0 | case TSDB_DATA_TYPE_BOOL: \ |
1511 | 0 | uval = *(const bool*)pData; \ |
1512 | 0 | code = decimal##FromUint64(pOut, pOutType->precision, pOutType->scale, uval); \ |
1513 | 0 | break; \ |
1514 | 0 | case TSDB_DATA_TYPE_TINYINT: \ |
1515 | 0 | val = *(const int8_t*)pData; \ |
1516 | 0 | code = decimal##FromInt64(pOut, pOutType->precision, pOutType->scale, val); \ |
1517 | 0 | break; \ |
1518 | 0 | case TSDB_DATA_TYPE_SMALLINT: \ |
1519 | 0 | val = *(const int16_t*)pData; \ |
1520 | 0 | code = decimal##FromInt64(pOut, pOutType->precision, pOutType->scale, val); \ |
1521 | 0 | break; \ |
1522 | 0 | case TSDB_DATA_TYPE_INT: \ |
1523 | 0 | val = *(const int32_t*)pData; \ |
1524 | 0 | code = decimal##FromInt64(pOut, pOutType->precision, pOutType->scale, val); \ |
1525 | 0 | break; \ |
1526 | 0 | case TSDB_DATA_TYPE_TIMESTAMP: \ |
1527 | 0 | case TSDB_DATA_TYPE_BIGINT: \ |
1528 | 0 | val = *(const int64_t*)pData; \ |
1529 | 0 | code = decimal##FromInt64(pOut, pOutType->precision, pOutType->scale, val); \ |
1530 | 0 | break; \ |
1531 | 0 | case TSDB_DATA_TYPE_UTINYINT: \ |
1532 | 0 | uval = *(const uint8_t*)pData; \ |
1533 | 0 | code = decimal##FromUint64(pOut, pOutType->precision, pOutType->scale, uval); \ |
1534 | 0 | break; \ |
1535 | 0 | case TSDB_DATA_TYPE_USMALLINT: \ |
1536 | 0 | uval = *(const uint16_t*)pData; \ |
1537 | 0 | code = decimal##FromUint64(pOut, pOutType->precision, pOutType->scale, uval); \ |
1538 | 0 | break; \ |
1539 | 0 | case TSDB_DATA_TYPE_UINT: \ |
1540 | 0 | uval = *(const uint32_t*)pData; \ |
1541 | 0 | code = decimal##FromUint64(pOut, pOutType->precision, pOutType->scale, uval); \ |
1542 | 0 | break; \ |
1543 | 0 | case TSDB_DATA_TYPE_UBIGINT: \ |
1544 | 0 | uval = *(const uint64_t*)pData; \ |
1545 | 0 | code = decimal##FromUint64(pOut, pOutType->precision, pOutType->scale, uval); \ |
1546 | 0 | break; \ |
1547 | 0 | case TSDB_DATA_TYPE_FLOAT: { \ |
1548 | 0 | dval = *(const float*)pData; \ |
1549 | 0 | code = decimal##FromDouble(pOut, pOutType->precision, pOutType->scale, dval); \ |
1550 | 0 | } break; \ |
1551 | 0 | case TSDB_DATA_TYPE_DOUBLE: { \ |
1552 | 0 | dval = *(const double*)pData; \ |
1553 | 0 | code = decimal##FromDouble(pOut, pOutType->precision, pOutType->scale, dval); \ |
1554 | 0 | } break; \ |
1555 | 0 | case TSDB_DATA_TYPE_DECIMAL64: { \ |
1556 | 0 | code = decimal##FromDecimal64(pOut, pOutType->precision, pOutType->scale, pData, pInputType->precision, \ |
1557 | 0 | pInputType->scale); \ |
1558 | 0 | } break; \ |
1559 | 0 | case TSDB_DATA_TYPE_DECIMAL: { \ |
1560 | 0 | code = decimal##FromDecimal128(pOut, pOutType->precision, pOutType->scale, pData, pInputType->precision, \ |
1561 | 0 | pInputType->scale); \ |
1562 | 0 | } break; \ |
1563 | 0 | case TSDB_DATA_TYPE_VARCHAR: \ |
1564 | 0 | case TSDB_DATA_TYPE_VARBINARY: \ |
1565 | 0 | case TSDB_DATA_TYPE_NCHAR: { \ |
1566 | 0 | code = decimal##FromStr(pData, pInputType->bytes, pOutType->precision, pOutType->scale, \ |
1567 | 0 | pOut); \ |
1568 | 0 | } break; \ |
1569 | 0 | default: \ |
1570 | 0 | code = TSDB_CODE_OPS_NOT_SUPPORT; \ |
1571 | 0 | break; \ |
1572 | 0 | } \ |
1573 | 0 | } while (0) |
1574 | | |
1575 | 0 | int32_t convertToDecimal(const void* pData, const SDataType* pInputType, void* pOut, const SDataType* pOutType) { |
1576 | 0 | int32_t code = 0; |
1577 | |
|
1578 | 0 | switch (pOutType->type) { |
1579 | 0 | case TSDB_DATA_TYPE_DECIMAL64: { |
1580 | 0 | CONVERT_TO_DECIMAL(pData, pInputType, pOut, pOutType, decimal64); |
1581 | 0 | } break; |
1582 | 0 | case TSDB_DATA_TYPE_DECIMAL: { |
1583 | 0 | CONVERT_TO_DECIMAL(pData, pInputType, pOut, pOutType, decimal128); |
1584 | 0 | } break; |
1585 | 0 | default: |
1586 | 0 | code = TSDB_CODE_INTERNAL_ERROR; |
1587 | 0 | break; |
1588 | 0 | } |
1589 | 0 | return code; |
1590 | 0 | } |
1591 | | |
1592 | 0 | void decimal64ScaleDown(Decimal64* pDec, uint8_t scaleDown, bool round) { |
1593 | 0 | if (scaleDown > 0) { |
1594 | 0 | Decimal64 divisor = SCALE_MULTIPLIER_64[scaleDown], remainder = {0}; |
1595 | 0 | decimal64divide(pDec, &divisor, DECIMAL_WORD_NUM(Decimal64), &remainder); |
1596 | 0 | if (round) { |
1597 | 0 | decimal64Abs(&remainder); |
1598 | 0 | Decimal64 half = SCALE_MULTIPLIER_64[scaleDown]; |
1599 | 0 | decimal64divide(&half, &decimal64Two, DECIMAL_WORD_NUM(Decimal64), NULL); |
1600 | 0 | if (!decimal64Lt(&remainder, &half, DECIMAL_WORD_NUM(Decimal64))) { |
1601 | 0 | Decimal64 delta = {DECIMAL64_SIGN(pDec)}; |
1602 | 0 | decimal64Add(pDec, &delta, DECIMAL_WORD_NUM(Decimal64)); |
1603 | 0 | } |
1604 | 0 | } |
1605 | 0 | } |
1606 | 0 | } |
1607 | | |
1608 | 0 | void decimal64ScaleUp(Decimal64* pDec, uint8_t scaleUp) { |
1609 | 0 | if (scaleUp > 0) { |
1610 | 0 | Decimal64 multiplier = SCALE_MULTIPLIER_64[scaleUp]; |
1611 | 0 | decimal64Multiply(pDec, &multiplier, DECIMAL_WORD_NUM(Decimal64)); |
1612 | 0 | } |
1613 | 0 | } |
1614 | | |
1615 | 0 | static void decimal64ScaleTo(Decimal64* pDec, uint8_t oldScale, uint8_t newScale) { |
1616 | 0 | if (newScale > oldScale) |
1617 | 0 | decimal64ScaleUp(pDec, newScale - oldScale); |
1618 | 0 | else if (newScale < oldScale) |
1619 | 0 | decimal64ScaleDown(pDec, oldScale - newScale, true); |
1620 | 0 | } |
1621 | | |
1622 | | static void decimal64ScaleAndCheckOverflow(Decimal64* pDec, int8_t scale, uint8_t toPrec, uint8_t toScale, |
1623 | 0 | bool* overflow) { |
1624 | 0 | int8_t deltaScale = toScale - scale; |
1625 | 0 | if (deltaScale >= 0) { |
1626 | 0 | Decimal64 max = {0}; |
1627 | 0 | DECIMAL64_GET_MAX(toPrec - deltaScale, &max); |
1628 | 0 | Decimal64 abs = *pDec; |
1629 | 0 | decimal64Abs(&abs); |
1630 | 0 | if (decimal64Gt(&abs, &max, DECIMAL_WORD_NUM(Decimal64))) { |
1631 | 0 | if (overflow) *overflow = true; |
1632 | 0 | } else { |
1633 | 0 | decimal64ScaleUp(pDec, deltaScale); |
1634 | 0 | } |
1635 | 0 | } else if (deltaScale < 0) { |
1636 | 0 | Decimal64 res = *pDec, max = {0}; |
1637 | 0 | decimal64ScaleDown(&res, -deltaScale, false); |
1638 | 0 | DECIMAL64_GET_MAX(toPrec, &max); |
1639 | 0 | Decimal64 abs = res; |
1640 | 0 | decimal64Abs(&abs); |
1641 | 0 | if (decimal64Gt(&abs, &max, DECIMAL_WORD_NUM(Decimal64))) { |
1642 | 0 | if (overflow) *overflow = true; |
1643 | 0 | } else { |
1644 | 0 | *pDec = res; |
1645 | 0 | } |
1646 | 0 | } |
1647 | 0 | } |
1648 | | |
1649 | | static int32_t decimal64CountRoundingDelta(const Decimal64* pDec, int8_t scale, int8_t toScale, |
1650 | 0 | DecimalRoundType roundType) { |
1651 | 0 | if (roundType == ROUND_TYPE_TRUNC || toScale >= scale) return 0; |
1652 | | |
1653 | 0 | Decimal64 dec = *pDec; |
1654 | 0 | int32_t res = 0; |
1655 | 0 | switch (roundType) { |
1656 | 0 | case ROUND_TYPE_HALF_ROUND_UP: { |
1657 | 0 | Decimal64 trailing = dec; |
1658 | 0 | decimal64Mod(&trailing, &SCALE_MULTIPLIER_64[scale - toScale], DECIMAL_WORD_NUM(Decimal64)); |
1659 | 0 | if (decimal64Eq(&trailing, &decimal64Zero, DECIMAL_WORD_NUM(Decimal64))) { |
1660 | 0 | res = 0; |
1661 | 0 | break; |
1662 | 0 | } |
1663 | 0 | Decimal64 trailingAbs = trailing, baseDiv2 = SCALE_MULTIPLIER_64[scale - toScale]; |
1664 | 0 | decimal64Abs(&trailingAbs); |
1665 | 0 | decimal64divide(&baseDiv2, &decimal64Two, DECIMAL_WORD_NUM(Decimal64), NULL); |
1666 | 0 | if (decimal64Lt(&trailingAbs, &baseDiv2, DECIMAL_WORD_NUM(Decimal64))) { |
1667 | 0 | res = 0; |
1668 | 0 | break; |
1669 | 0 | } |
1670 | 0 | res = DECIMAL64_SIGN(pDec) == 1 ? 1 : -1; |
1671 | 0 | } break; |
1672 | 0 | default: |
1673 | 0 | break; |
1674 | 0 | } |
1675 | 0 | return res; |
1676 | 0 | } |
1677 | | |
1678 | | static void decimal64RoundWithPositiveScale(Decimal64* pDec, uint8_t prec, int8_t scale, uint8_t toPrec, |
1679 | 0 | uint8_t toScale, DecimalRoundType roundType, bool* overflow) { |
1680 | 0 | Decimal64 scaled = *pDec; |
1681 | 0 | bool overflowLocal = false; |
1682 | | // scale up or down to toScale |
1683 | 0 | decimal64ScaleAndCheckOverflow(&scaled, scale, toPrec, toScale, &overflowLocal); |
1684 | 0 | if (overflowLocal) { |
1685 | 0 | if (overflow) *overflow = true; |
1686 | 0 | *pDec = decimal64Zero; |
1687 | 0 | return; |
1688 | 0 | } |
1689 | | |
1690 | | // calc rounding delta |
1691 | 0 | int32_t delta = decimal64CountRoundingDelta(pDec, scale, toScale, roundType); |
1692 | 0 | if (delta == 0) { |
1693 | 0 | *pDec = scaled; |
1694 | 0 | return; |
1695 | 0 | } |
1696 | | |
1697 | 0 | Decimal64 deltaDec = {delta}; |
1698 | | // add the delta |
1699 | 0 | decimal64Add(&scaled, &deltaDec, DECIMAL_WORD_NUM(Decimal64)); |
1700 | | |
1701 | | // check overflow again |
1702 | 0 | if (toPrec < prec) { |
1703 | 0 | Decimal64 max = {0}; |
1704 | 0 | DECIMAL64_GET_MAX(toPrec, &max); |
1705 | 0 | Decimal64 scaledAbs = scaled; |
1706 | 0 | decimal64Abs(&scaledAbs); |
1707 | 0 | if (decimal64Gt(&scaledAbs, &max, DECIMAL_WORD_NUM(Decimal64))) { |
1708 | 0 | if (overflow) *overflow = true; |
1709 | 0 | *pDec = decimal64Zero; |
1710 | 0 | return; |
1711 | 0 | } |
1712 | 0 | } |
1713 | 0 | *pDec = scaled; |
1714 | 0 | } |
1715 | | |
1716 | 0 | int32_t decimal64FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, Decimal64* pRes) { |
1717 | 0 | int32_t code = 0; |
1718 | 0 | DecimalVar var = {.type = DECIMAL_64, .pDec = pRes->words, .precision = expectPrecision, .scale = expectScale}; |
1719 | 0 | DECIMAL64_SET_VALUE(pRes, 0); |
1720 | 0 | code = decimalVarFromStr(str, len, &var); |
1721 | 0 | if (TSDB_CODE_SUCCESS != code) return code; |
1722 | 0 | if (var.weight > (int32_t)expectPrecision - expectScale) { |
1723 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1724 | 0 | } |
1725 | 0 | bool overflow = false; |
1726 | 0 | decimal64RoundWithPositiveScale(pRes, var.precision, var.scale, expectPrecision, expectScale, |
1727 | 0 | ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1728 | 0 | if (overflow) { |
1729 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1730 | 0 | } |
1731 | 0 | return code; |
1732 | 0 | } |
1733 | | |
1734 | 0 | static void decimal128ScaleDown(Decimal128* pDec, uint8_t scaleDown, bool round) { |
1735 | 0 | if (scaleDown > 0) { |
1736 | 0 | Decimal128 divisor = SCALE_MULTIPLIER_128[scaleDown], remainder = {0}; |
1737 | 0 | decimal128Divide(pDec, &divisor, 2, &remainder); |
1738 | 0 | if (round) { |
1739 | 0 | decimal128Abs(&remainder); |
1740 | 0 | Decimal128 half = SCALE_MULTIPLIER_128[scaleDown]; |
1741 | 0 | decimal128Divide(&half, &decimal128Two, 2, NULL); |
1742 | 0 | if (!decimal128Lt(&remainder, &half, DECIMAL_WORD_NUM(Decimal128))) { |
1743 | 0 | Decimal64 delta = {DECIMAL128_SIGN(pDec)}; |
1744 | 0 | decimal128Add(pDec, &delta, DECIMAL_WORD_NUM(Decimal64)); |
1745 | 0 | } |
1746 | 0 | } |
1747 | 0 | } |
1748 | 0 | } |
1749 | | |
1750 | 0 | static void decimal128ScaleUp(Decimal128* pDec, uint8_t scaleUp) { |
1751 | 0 | if (scaleUp > 0) { |
1752 | 0 | Decimal128 multiplier = SCALE_MULTIPLIER_128[scaleUp]; |
1753 | 0 | decimal128Multiply(pDec, &multiplier, DECIMAL_WORD_NUM(Decimal128)); |
1754 | 0 | } |
1755 | 0 | } |
1756 | | |
1757 | 0 | static void decimal128ScaleTo(Decimal128* pDec, uint8_t oldScale, uint8_t newScale) { |
1758 | 0 | if (newScale > oldScale) |
1759 | 0 | decimal128ScaleUp(pDec, newScale - oldScale); |
1760 | 0 | else if (newScale < oldScale) |
1761 | 0 | decimal128ScaleDown(pDec, oldScale - newScale, true); |
1762 | 0 | } |
1763 | | |
1764 | | int32_t decimal128FromStr(const char* str, int32_t len, uint8_t expectPrecision, uint8_t expectScale, |
1765 | 0 | Decimal128* pRes) { |
1766 | 0 | int32_t code = 0; |
1767 | 0 | DecimalVar var = {.type = DECIMAL_128, .pDec = pRes->words, .precision = expectPrecision, .scale = expectScale}; |
1768 | 0 | DECIMAL128_SET_HIGH_WORD(pRes, 0); |
1769 | 0 | DECIMAL128_SET_LOW_WORD(pRes, 0); |
1770 | 0 | code = decimalVarFromStr(str, len, &var); |
1771 | 0 | if (TSDB_CODE_SUCCESS != code) return code; |
1772 | 0 | if (var.weight > (int32_t)expectPrecision - expectScale) { |
1773 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1774 | 0 | } |
1775 | 0 | bool overflow = false; |
1776 | 0 | decimal128RoundWithPositiveScale(pRes, var.precision, var.scale, expectPrecision, expectScale, |
1777 | 0 | ROUND_TYPE_HALF_ROUND_UP, &overflow); |
1778 | 0 | if (overflow) { |
1779 | 0 | return TSDB_CODE_DECIMAL_OVERFLOW; |
1780 | 0 | } |
1781 | 0 | return code; |
1782 | 0 | } |
1783 | | |
1784 | | #if 0 |
1785 | | __int128 decimal128ToInt128(const Decimal128* pDec) { |
1786 | | __int128 ret = 0; |
1787 | | ret = DECIMAL128_HIGH_WORD(pDec); |
1788 | | ret <<= 64; |
1789 | | ret |= DECIMAL128_LOW_WORD(pDec); |
1790 | | return ret; |
1791 | | } |
1792 | | #endif |
1793 | | |
1794 | 0 | static int32_t decimal128CountLeadingBinaryZeros(const Decimal128* pDec) { |
1795 | 0 | if (DECIMAL128_HIGH_WORD(pDec) == 0) { |
1796 | 0 | return 64 + countLeadingZeros(DECIMAL128_LOW_WORD(pDec)); |
1797 | 0 | } else { |
1798 | 0 | return countLeadingZeros((uint64_t)DECIMAL128_HIGH_WORD(pDec)); |
1799 | 0 | } |
1800 | 0 | } |
1801 | | |
1802 | | #define IMPL_INTEGER_TYPE_FROM_DECIMAL_TYPE(oType, decimalType, sign) \ |
1803 | 0 | oType oType##From##decimalType(const DecimalType* pDec, uint8_t prec, uint8_t scale) { \ |
1804 | 0 | return (oType)sign##int64##From##decimalType(pDec, prec, scale); \ |
1805 | 0 | } Unexecuted instantiation: int8_tFromDecimal64 Unexecuted instantiation: int16_tFromDecimal64 Unexecuted instantiation: int32_tFromDecimal64 Unexecuted instantiation: int64_tFromDecimal64 Unexecuted instantiation: uint8_tFromDecimal64 Unexecuted instantiation: uint16_tFromDecimal64 Unexecuted instantiation: uint32_tFromDecimal64 Unexecuted instantiation: uint64_tFromDecimal64 Unexecuted instantiation: int8_tFromDecimal128 Unexecuted instantiation: int16_tFromDecimal128 Unexecuted instantiation: int32_tFromDecimal128 Unexecuted instantiation: int64_tFromDecimal128 Unexecuted instantiation: uint8_tFromDecimal128 Unexecuted instantiation: uint16_tFromDecimal128 Unexecuted instantiation: uint32_tFromDecimal128 Unexecuted instantiation: uint64_tFromDecimal128 |
1806 | | #define IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(oType, decimalType) \ |
1807 | | IMPL_INTEGER_TYPE_FROM_DECIMAL_TYPE(oType, decimalType, ) |
1808 | | #define IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(oType, decimalType) \ |
1809 | | IMPL_INTEGER_TYPE_FROM_DECIMAL_TYPE(oType, decimalType, u) |
1810 | | |
1811 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int8_t, Decimal64) |
1812 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int16_t, Decimal64) |
1813 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int32_t, Decimal64) |
1814 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int64_t, Decimal64) |
1815 | | |
1816 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint8_t, Decimal64) |
1817 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint16_t, Decimal64) |
1818 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint32_t, Decimal64) |
1819 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint64_t, Decimal64) |
1820 | | |
1821 | 0 | double doubleFromDecimal64(const void* pDec, uint8_t prec, uint8_t scale) { |
1822 | 0 | int32_t sign = DECIMAL64_SIGN((Decimal64*)pDec); |
1823 | 0 | Decimal64 abs = *(Decimal64*)pDec; |
1824 | 0 | decimal64Abs(&abs); |
1825 | 0 | return (double)DECIMAL64_GET_VALUE(&abs) * sign / getDoubleScaleMultiplier(scale); |
1826 | 0 | } |
1827 | | |
1828 | 0 | bool boolFromDecimal64(const void* pDec, uint8_t prec, uint8_t scale) { |
1829 | 0 | return !decimal64Eq(pDec, &decimal64Zero, DECIMAL_WORD_NUM(Decimal64)); |
1830 | 0 | } |
1831 | | |
1832 | | #define IMPL_REAL_TYPE_FROM_DECIMAL_TYPE(oType, decimalType) \ |
1833 | 0 | oType oType##From##decimalType(const DecimalType* pDec, uint8_t prec, uint8_t scale) { \ |
1834 | 0 | return (oType) double##From##decimalType(pDec, prec, scale); \ |
1835 | 0 | } Unexecuted instantiation: floatFromDecimal64 Unexecuted instantiation: floatFromDecimal128 |
1836 | | |
1837 | | IMPL_REAL_TYPE_FROM_DECIMAL_TYPE(float, Decimal64); |
1838 | | |
1839 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int8_t, Decimal128) |
1840 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int16_t, Decimal128) |
1841 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int32_t, Decimal128) |
1842 | | IMP_SIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(int64_t, Decimal128) |
1843 | | |
1844 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint8_t, Decimal128) |
1845 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint16_t, Decimal128) |
1846 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint32_t, Decimal128) |
1847 | | IMP_UNSIGNED_INTEGER_TYPE_FROM_DECIMAL_TYPE(uint64_t, Decimal128) |
1848 | | |
1849 | 0 | bool boolFromDecimal128(const void* pDec, uint8_t prec, uint8_t scale) { |
1850 | 0 | return !decimal128Eq(pDec, &decimal128Zero, DECIMAL_WORD_NUM(Decimal128)); |
1851 | 0 | } |
1852 | | |
1853 | 0 | double doubleFromDecimal128(const void* pDec, uint8_t prec, uint8_t scale) { |
1854 | 0 | int32_t sign = DECIMAL128_SIGN((Decimal128*)pDec); |
1855 | 0 | Decimal128 abs = *(Decimal128*)pDec; |
1856 | 0 | decimal128Abs(&abs); |
1857 | 0 | double unscaled = DECIMAL128_LOW_WORD(&abs); |
1858 | 0 | unscaled += ldexp((double)DECIMAL128_HIGH_WORD(&abs), 64); |
1859 | 0 | return (unscaled * sign) / getDoubleScaleMultiplier(scale); |
1860 | 0 | } |
1861 | | |
1862 | | IMPL_REAL_TYPE_FROM_DECIMAL_TYPE(float, Decimal128); |
1863 | | |
1864 | | static void decimal128RoundWithPositiveScale(Decimal128* pDec, uint8_t prec, uint8_t scale, uint8_t toPrec, |
1865 | 0 | uint8_t toScale, DecimalRoundType roundType, bool* overflow) { |
1866 | 0 | Decimal128 scaled = *pDec; |
1867 | 0 | bool overflowLocal = false; |
1868 | | // scale up or down to toScale |
1869 | 0 | decimal128ModifyScaleAndPrecision(&scaled, scale, toPrec, toScale, &overflowLocal); |
1870 | 0 | if (overflowLocal) { |
1871 | 0 | if (overflow) *overflow = true; |
1872 | 0 | *pDec = decimal128Zero; |
1873 | 0 | return; |
1874 | 0 | } |
1875 | | |
1876 | | // calc rounding delta, 1 or -1 |
1877 | 0 | int32_t delta = decimal128CountRoundingDelta(pDec, scale, toScale, roundType); |
1878 | 0 | if (delta == 0) { |
1879 | 0 | *pDec = scaled; |
1880 | 0 | return; |
1881 | 0 | } |
1882 | | |
1883 | 0 | Decimal64 deltaDec = {delta}; |
1884 | | // add the delta |
1885 | 0 | decimal128Add(&scaled, &deltaDec, DECIMAL_WORD_NUM(Decimal64)); |
1886 | | |
1887 | | // check overflow again |
1888 | 0 | if (toPrec < prec) { |
1889 | 0 | Decimal128 max = {0}; |
1890 | 0 | DECIMAL128_GET_MAX(toPrec, &max); |
1891 | 0 | Decimal128 scaledAbs = scaled; |
1892 | 0 | decimal128Abs(&scaledAbs); |
1893 | 0 | if (decimal128Gt(&scaledAbs, &max, DECIMAL_WORD_NUM(Decimal128))) { |
1894 | 0 | if (overflow) *overflow = true; |
1895 | 0 | *(Decimal128*)pDec = decimal128Zero; |
1896 | 0 | return; |
1897 | 0 | } |
1898 | 0 | } |
1899 | 0 | *(Decimal128*)pDec = scaled; |
1900 | 0 | } |
1901 | | |
1902 | | static void decimal128ModifyScaleAndPrecision(Decimal128* pDec, uint8_t scale, uint8_t toPrec, int8_t toScale, |
1903 | 0 | bool* overflow) { |
1904 | 0 | int8_t deltaScale = toScale - scale; |
1905 | 0 | if (deltaScale >= 0) { |
1906 | 0 | Decimal128 max = {0}; |
1907 | 0 | DECIMAL128_GET_MAX(toPrec - deltaScale, &max); |
1908 | 0 | Decimal128 abs = *pDec; |
1909 | 0 | decimal128Abs(&abs); |
1910 | 0 | if (decimal128Gt(&abs, &max, DECIMAL_WORD_NUM(Decimal128))) { |
1911 | 0 | if (overflow) *overflow = true; |
1912 | 0 | } else { |
1913 | 0 | decimal128ScaleUp(pDec, deltaScale); |
1914 | 0 | } |
1915 | 0 | } else { |
1916 | 0 | Decimal128 res = *pDec, max = {0}; |
1917 | 0 | decimal128ScaleDown(&res, -deltaScale, false); |
1918 | 0 | DECIMAL128_GET_MAX(toPrec, &max); |
1919 | 0 | if (decimal128Gt(&res, &max, DECIMAL_WORD_NUM(Decimal128))) { |
1920 | 0 | if (overflow) *overflow = true; |
1921 | 0 | } else { |
1922 | 0 | *(Decimal128*)pDec = res; |
1923 | 0 | } |
1924 | 0 | } |
1925 | 0 | } |
1926 | | |
1927 | | static int32_t decimal128CountRoundingDelta(const Decimal128* pDec, int8_t scale, int8_t toScale, |
1928 | 0 | DecimalRoundType roundType) { |
1929 | 0 | if (roundType == ROUND_TYPE_TRUNC || toScale >= scale) return 0; |
1930 | 0 | Decimal128 dec128 = *pDec; |
1931 | 0 | int32_t res = 0; |
1932 | 0 | switch (roundType) { |
1933 | 0 | case ROUND_TYPE_HALF_ROUND_UP: { |
1934 | 0 | Decimal128 trailing = dec128; |
1935 | 0 | decimal128Mod(&trailing, &SCALE_MULTIPLIER_128[scale - toScale], DECIMAL_WORD_NUM(Decimal128)); |
1936 | 0 | if (decimal128Eq(&trailing, &decimal128Zero, DECIMAL_WORD_NUM(Decimal128))) { |
1937 | 0 | res = 0; |
1938 | 0 | break; |
1939 | 0 | } |
1940 | 0 | Decimal128 tailingAbs = trailing, baseDiv2 = SCALE_MULTIPLIER_128[scale - toScale]; |
1941 | 0 | decimal128Abs(&tailingAbs); |
1942 | 0 | decimal128Divide(&baseDiv2, &decimal128Two, DECIMAL_WORD_NUM(Decimal128), NULL); |
1943 | 0 | if (decimal128Lt(&tailingAbs, &baseDiv2, DECIMAL_WORD_NUM(Decimal128))) { |
1944 | 0 | res = 0; |
1945 | 0 | break; |
1946 | 0 | } |
1947 | 0 | res = DECIMAL128_SIGN(pDec) == -1 ? -1 : 1; |
1948 | 0 | } break; |
1949 | 0 | case ROUND_TYPE_TRUNC: |
1950 | 0 | default: |
1951 | 0 | break; |
1952 | 0 | } |
1953 | 0 | return res; |
1954 | 0 | } |
1955 | | |
1956 | 0 | bool decimal128AddCheckOverflow(const Decimal128* pLeft, const DecimalType* pRight, uint8_t rightWordNum) { |
1957 | 0 | if (DECIMAL128_SIGN(pLeft) == 0) { |
1958 | 0 | Decimal128 max = decimal128Max; |
1959 | 0 | decimal128Subtract(&max, pLeft, DECIMAL_WORD_NUM(Decimal128)); |
1960 | 0 | return decimal128Lt(&max, pRight, rightWordNum); |
1961 | 0 | } else { |
1962 | 0 | Decimal128 min = decimal128Min; |
1963 | 0 | decimal128Subtract(&min, pLeft, DECIMAL_WORD_NUM(Decimal128)); |
1964 | 0 | return decimal128Gt(&min, pRight, rightWordNum); |
1965 | 0 | } |
1966 | 0 | } |
1967 | | |
1968 | 0 | int32_t TEST_decimal64From_int64_t(Decimal64* pDec, uint8_t prec, uint8_t scale, int64_t v) { |
1969 | 0 | return decimal64FromInt64(pDec, prec, scale, v); |
1970 | 0 | } |
1971 | 0 | int32_t TEST_decimal64From_uint64_t(Decimal64* pDec, uint8_t prec, uint8_t scale, uint64_t v) { |
1972 | 0 | return decimal64FromUint64(pDec, prec, scale, v); |
1973 | 0 | } |
1974 | 0 | int32_t TEST_decimal64From_double(Decimal64* pDec, uint8_t prec, uint8_t scale, double v) { |
1975 | 0 | return decimal64FromDouble(pDec, prec, scale, v); |
1976 | 0 | } |
1977 | 0 | double TEST_decimal64ToDouble(Decimal64* pDec, uint8_t prec, uint8_t scale) { |
1978 | 0 | return doubleFromDecimal64(pDec, prec, scale); |
1979 | 0 | } |
1980 | | |
1981 | 0 | int32_t TEST_decimal128From_int64_t(Decimal128* pDec, uint8_t prec, uint8_t scale, int64_t v) { |
1982 | 0 | return decimal128FromInt64(pDec, prec, scale, v); |
1983 | 0 | } |
1984 | 0 | int32_t TEST_decimal128From_uint64_t(Decimal128* pDec, uint8_t prec, uint8_t scale, uint64_t v) { |
1985 | 0 | return decimal128FromUint64(pDec, prec, scale, v); |
1986 | 0 | } |
1987 | 0 | int32_t TEST_decimal128From_double(Decimal128* pDec, uint8_t prec, uint8_t scale, double v) { |
1988 | 0 | return decimal128FromDouble(pDec, prec, scale, v); |
1989 | 0 | } |
1990 | 0 | double TEST_decimal128ToDouble(Decimal128* pDec, uint8_t prec, uint8_t scale) { |
1991 | 0 | return doubleFromDecimal128(pDec, prec, scale); |
1992 | 0 | } |
1993 | | |
1994 | | int32_t TEST_decimal64FromDecimal64(const Decimal64* pInput, uint8_t inputPrec, uint8_t inputScale, Decimal64* pOutput, |
1995 | 0 | uint8_t outputPrec, uint8_t outputScale) { |
1996 | 0 | return decimal64FromDecimal64(pOutput, outputPrec, outputScale, pInput, inputPrec, inputScale); |
1997 | 0 | } |
1998 | | |
1999 | | int32_t TEST_decimal64FromDecimal128(const Decimal128* pInput, uint8_t prec, uint8_t inputScale, Decimal64* pOutput, |
2000 | 0 | uint8_t outputPrec, uint8_t outputScale) { |
2001 | 0 | return decimal64FromDecimal128(pOutput, outputPrec, outputScale, pInput, prec, inputScale); |
2002 | 0 | } |
2003 | | |
2004 | | int32_t TEST_decimal128FromDecimal64(const Decimal64* pInput, uint8_t inputPrec, uint8_t inputScale, |
2005 | 0 | Decimal128* pOutput, uint8_t outputPrec, uint8_t outputScale) { |
2006 | 0 | return decimal128FromDecimal64(pOutput, outputPrec, outputScale, pInput, inputPrec, inputScale); |
2007 | 0 | } |
2008 | | int32_t TEST_decimal128FromDecimal128(const Decimal128* pDec, uint8_t prec, uint8_t scale, Decimal128* pOutput, |
2009 | 0 | uint8_t outputPrec, uint8_t outputScale) { |
2010 | 0 | return decimal128FromDecimal128(pOutput, outputPrec, outputScale, pDec, prec, scale); |
2011 | 0 | } |
2012 | | |
2013 | 0 | void encodeDecimal(const DecimalType* pDec, int8_t type, void* pBuf) { |
2014 | 0 | switch (type) { |
2015 | 0 | case TSDB_DATA_TYPE_DECIMAL64: |
2016 | 0 | *(DecimalWord*)pBuf = htobe64((DecimalWord)DECIMAL64_GET_VALUE((Decimal64*)pDec)); |
2017 | 0 | break; |
2018 | 0 | case TSDB_DATA_TYPE_DECIMAL: |
2019 | 0 | ((Decimal128*)pBuf)->words[0] = htobe64(DECIMAL128_LOW_WORD((Decimal128*)pDec)); |
2020 | 0 | ((Decimal128*)pBuf)->words[1] = htobe64(DECIMAL128_HIGH_WORD((Decimal128*)pDec)); |
2021 | 0 | break; |
2022 | 0 | default: |
2023 | 0 | break; |
2024 | 0 | } |
2025 | 0 | } |
2026 | | |
2027 | 0 | void decodeDecimal(const void* pBuf, int8_t type, DecimalType* pDec) { |
2028 | 0 | switch (type) { |
2029 | 0 | case TSDB_DATA_TYPE_DECIMAL64: |
2030 | 0 | DECIMAL64_SET_VALUE((Decimal64*)pDec, be64toh(*(DecimalWord*)pBuf)); |
2031 | 0 | break; |
2032 | 0 | case TSDB_DATA_TYPE_DECIMAL: |
2033 | 0 | DECIMAL128_SET_LOW_WORD((Decimal128*)pDec, be64toh(((Decimal128*)pBuf)->words[0])); |
2034 | 0 | DECIMAL128_SET_HIGH_WORD((Decimal128*)pDec, be64toh(((Decimal128*)pBuf)->words[1])); |
2035 | 0 | break; |
2036 | 0 | default: |
2037 | 0 | break; |
2038 | 0 | } |
2039 | 0 | } |