/root/doris/be/src/runtime/decimalv2_value.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "runtime/decimalv2_value.h" |
19 | | |
20 | | #include <fmt/format.h> |
21 | | |
22 | | #include <cmath> |
23 | | #include <cstring> |
24 | | #include <iostream> |
25 | | #include <utility> |
26 | | |
27 | | #include "util/string_parser.hpp" |
28 | | |
29 | | namespace doris { |
30 | | |
31 | | const int128_t DecimalV2Value::MAX_DECIMAL_VALUE; |
32 | | |
33 | 1.12k | static inline int128_t abs(const int128_t& x) { |
34 | 1.12k | return (x < 0) ? -x : x; |
35 | 1.12k | } |
36 | | |
37 | | // x>=0 && y>=0 |
38 | 4 | static int do_add(int128_t x, int128_t y, int128_t* result) { |
39 | 4 | int error = E_DEC_OK; |
40 | 4 | if (DecimalV2Value::MAX_DECIMAL_VALUE - x >= y) { |
41 | 4 | *result = x + y; |
42 | 4 | } else { |
43 | 0 | *result = DecimalV2Value::MAX_DECIMAL_VALUE; |
44 | 0 | error = E_DEC_OVERFLOW; |
45 | 0 | } |
46 | 4 | return error; |
47 | 4 | } |
48 | | |
49 | | // x>=0 && y>=0 |
50 | 2 | static int do_sub(int128_t x, int128_t y, int128_t* result) { |
51 | 2 | int error = E_DEC_OK; |
52 | 2 | *result = x - y; |
53 | 2 | return error; |
54 | 2 | } |
55 | | |
56 | | // clear leading zero for __int128 |
57 | 2 | static int clz128(unsigned __int128 v) { |
58 | 2 | if (v == 0) return sizeof(__int128); |
59 | 2 | unsigned __int128 shifted = v >> 64; |
60 | 2 | if (shifted != 0) { |
61 | 0 | return __builtin_clzll(shifted); |
62 | 2 | } else { |
63 | 2 | return __builtin_clzll(v) + 64; |
64 | 2 | } |
65 | 2 | } |
66 | | |
67 | | // x>0 && y>0 |
68 | 1 | static int do_mul(int128_t x, int128_t y, int128_t* result) { |
69 | 1 | int error = E_DEC_OK; |
70 | 1 | int128_t max128 = ~(static_cast<int128_t>(1ll) << 127); |
71 | | |
72 | 1 | int leading_zero_bits = clz128(x) + clz128(y); |
73 | 1 | if (leading_zero_bits < sizeof(int128_t) || max128 / x < y) { |
74 | 0 | *result = DecimalV2Value::MAX_DECIMAL_VALUE; |
75 | 0 | error = E_DEC_OVERFLOW; |
76 | 0 | return error; |
77 | 0 | } |
78 | | |
79 | 1 | int128_t product = x * y; |
80 | 1 | *result = product / DecimalV2Value::ONE_BILLION; |
81 | | |
82 | | // overflow |
83 | 1 | if (*result > DecimalV2Value::MAX_DECIMAL_VALUE) { |
84 | 0 | *result = DecimalV2Value::MAX_DECIMAL_VALUE; |
85 | 0 | error = E_DEC_OVERFLOW; |
86 | 0 | return error; |
87 | 0 | } |
88 | | |
89 | | // truncate with round |
90 | 1 | int128_t remainder = product % DecimalV2Value::ONE_BILLION; |
91 | 1 | if (remainder != 0) { |
92 | 0 | error = E_DEC_TRUNCATED; |
93 | 0 | if (remainder >= (DecimalV2Value::ONE_BILLION >> 1)) { |
94 | 0 | *result += 1; |
95 | 0 | } |
96 | 0 | } |
97 | | |
98 | 1 | return error; |
99 | 1 | } |
100 | | |
101 | | // x>0 && y>0 |
102 | 2 | static int do_div(int128_t x, int128_t y, int128_t* result) { |
103 | 2 | int error = E_DEC_OK; |
104 | 2 | int128_t dividend = x * DecimalV2Value::ONE_BILLION; |
105 | 2 | *result = dividend / y; |
106 | | |
107 | | // overflow |
108 | 2 | int128_t remainder = dividend % y; |
109 | 2 | if (remainder != 0) { |
110 | 0 | error = E_DEC_TRUNCATED; |
111 | 0 | if (remainder >= (y >> 1)) { |
112 | 0 | *result += 1; |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 2 | return error; |
117 | 2 | } |
118 | | |
119 | | // x>0 && y>0 |
120 | 0 | static int do_mod(int128_t x, int128_t y, int128_t* result) { |
121 | 0 | int error = E_DEC_OK; |
122 | 0 | *result = x % y; |
123 | 0 | return error; |
124 | 0 | } |
125 | | |
126 | 3 | DecimalV2Value operator+(const DecimalV2Value& v1, const DecimalV2Value& v2) { |
127 | 3 | int128_t result; |
128 | 3 | int128_t x = v1.value(); |
129 | 3 | int128_t y = v2.value(); |
130 | 3 | if (x == 0) { |
131 | 0 | result = y; |
132 | 3 | } else if (y == 0) { |
133 | 0 | result = x; |
134 | 3 | } else if (x > 0) { |
135 | 2 | if (y > 0) { |
136 | 2 | do_add(x, y, &result); |
137 | 2 | } else { |
138 | 0 | do_sub(x, -y, &result); |
139 | 0 | } |
140 | 2 | } else { // x < 0 |
141 | 1 | if (y > 0) { |
142 | 1 | do_sub(y, -x, &result); |
143 | 1 | } else { |
144 | 0 | do_add(-x, -y, &result); |
145 | 0 | result = -result; |
146 | 0 | } |
147 | 1 | } |
148 | | |
149 | 3 | return DecimalV2Value(result); |
150 | 3 | } |
151 | | |
152 | 4 | DecimalV2Value operator-(const DecimalV2Value& v1, const DecimalV2Value& v2) { |
153 | 4 | int128_t result; |
154 | 4 | int128_t x = v1.value(); |
155 | 4 | int128_t y = v2.value(); |
156 | 4 | if (x == 0) { |
157 | 1 | result = -y; |
158 | 3 | } else if (y == 0) { |
159 | 0 | result = x; |
160 | 3 | } else if (x > 0) { |
161 | 2 | if (y > 0) { |
162 | 1 | do_sub(x, y, &result); |
163 | 1 | } else { |
164 | 1 | do_add(x, -y, &result); |
165 | 1 | } |
166 | 2 | } else { // x < 0 |
167 | 1 | if (y > 0) { |
168 | 1 | do_add(-x, y, &result); |
169 | 1 | result = -result; |
170 | 1 | } else { |
171 | 0 | do_sub(-x, -y, &result); |
172 | 0 | result = -result; |
173 | 0 | } |
174 | 1 | } |
175 | | |
176 | 4 | return DecimalV2Value(result); |
177 | 4 | } |
178 | | |
179 | 2 | DecimalV2Value operator*(const DecimalV2Value& v1, const DecimalV2Value& v2) { |
180 | 2 | int128_t result; |
181 | 2 | int128_t x = v1.value(); |
182 | 2 | int128_t y = v2.value(); |
183 | | |
184 | 2 | if (x == 0 || y == 0) return DecimalV2Value(0); |
185 | | |
186 | 1 | bool is_positive = (x > 0 && y > 0) || (x < 0 && y < 0); |
187 | | |
188 | 1 | do_mul(abs(x), abs(y), &result); |
189 | | |
190 | 1 | if (!is_positive) result = -result; |
191 | | |
192 | 1 | return DecimalV2Value(result); |
193 | 2 | } |
194 | | |
195 | 2 | DecimalV2Value operator/(const DecimalV2Value& v1, const DecimalV2Value& v2) { |
196 | 2 | int128_t result; |
197 | 2 | int128_t x = v1.value(); |
198 | 2 | int128_t y = v2.value(); |
199 | | |
200 | 2 | DCHECK(y != 0); |
201 | 2 | if (x == 0 || y == 0) return DecimalV2Value(0); |
202 | 2 | bool is_positive = (x > 0 && y > 0) || (x < 0 && y < 0); |
203 | 2 | do_div(abs(x), abs(y), &result); |
204 | | |
205 | 2 | if (!is_positive) result = -result; |
206 | | |
207 | 2 | return DecimalV2Value(result); |
208 | 2 | } |
209 | | |
210 | 0 | DecimalV2Value operator%(const DecimalV2Value& v1, const DecimalV2Value& v2) { |
211 | 0 | int128_t result; |
212 | 0 | int128_t x = v1.value(); |
213 | 0 | int128_t y = v2.value(); |
214 | |
|
215 | 0 | DCHECK(y != 0); |
216 | 0 | if (x == 0 || y == 0) return DecimalV2Value(0); |
217 | | |
218 | 0 | do_mod(x, y, &result); |
219 | |
|
220 | 0 | return DecimalV2Value(result); |
221 | 0 | } |
222 | | |
223 | 0 | std::ostream& operator<<(std::ostream& os, DecimalV2Value const& decimal_value) { |
224 | 0 | return os << decimal_value.to_string(); |
225 | 0 | } |
226 | | |
227 | 0 | std::istream& operator>>(std::istream& ism, DecimalV2Value& decimal_value) { |
228 | 0 | std::string str_buff; |
229 | 0 | ism >> str_buff; |
230 | 0 | decimal_value.parse_from_str(str_buff.c_str(), str_buff.size()); |
231 | 0 | return ism; |
232 | 0 | } |
233 | | |
234 | 1 | DecimalV2Value operator-(const DecimalV2Value& v) { |
235 | 1 | return DecimalV2Value(-v.value()); |
236 | 1 | } |
237 | | |
238 | 1 | DecimalV2Value& DecimalV2Value::operator+=(const DecimalV2Value& other) { |
239 | 1 | *this = *this + other; |
240 | 1 | return *this; |
241 | 1 | } |
242 | | |
243 | | // Solve a one-dimensional quadratic equation: ax2 + bx + c =0 |
244 | | // Reference: https://gist.github.com/miloyip/1fcc1859c94d33a01957cf41a7c25fdf |
245 | | // Reference: https://www.zhihu.com/question/51381686 |
246 | | static std::pair<double, double> quadratic_equation_naive(__uint128_t a, __uint128_t b, |
247 | 0 | __uint128_t c) { |
248 | 0 | __uint128_t dis = b * b - 4 * a * c; |
249 | | // assert(dis >= 0); |
250 | | // not handling complex root |
251 | 0 | double sqrtdis = std::sqrt(static_cast<double>(dis)); |
252 | 0 | double a_r = static_cast<double>(a); |
253 | 0 | double b_r = static_cast<double>(b); |
254 | 0 | double x1 = (-b_r - sqrtdis) / (a_r + a_r); |
255 | 0 | double x2 = (-b_r + sqrtdis) / (a_r + a_r); |
256 | 0 | return std::make_pair(x1, x2); |
257 | 0 | } |
258 | | |
259 | 0 | static inline double sgn(double x) { |
260 | 0 | if (x > 0) |
261 | 0 | return 1; |
262 | 0 | else if (x < 0) |
263 | 0 | return -1; |
264 | 0 | else |
265 | 0 | return 0; |
266 | 0 | } |
267 | | |
268 | | // In the above quadratic_equation_naive solution process, we found that -b + sqrtdis will |
269 | | // get the correct answer, and -b-sqrtdis will get the wrong answer. For two close floating-point |
270 | | // decimals a, b, a-b will cause larger errors than a + b, which is called catastrophic cancellation. |
271 | | // Both -b and sqrtdis are positive numbers. We can first find the roots brought by -b + sqrtdis, |
272 | | // and then use the product of the two roots of the quadratic equation in one unknown to find another root |
273 | 0 | static std::pair<double, double> quadratic_equation_better(int128_t a, int128_t b, int128_t c) { |
274 | 0 | if (b == 0) return quadratic_equation_naive(a, b, c); |
275 | 0 | int128_t dis = b * b - 4 * a * c; |
276 | | // assert(dis >= 0); |
277 | | // not handling complex root |
278 | 0 | if (dis < 0) return std::make_pair(0, 0); |
279 | | |
280 | | // There may be a loss of precision, but here is used to find the mantissa of the square root. |
281 | | // The current SCALE=9, which is less than the 15 significant digits of the double type, |
282 | | // so theoretically the loss of precision will not be reflected in the result. |
283 | 0 | double sqrtdis = std::sqrt(static_cast<double>(dis)); |
284 | 0 | double a_r = static_cast<double>(a); |
285 | 0 | double b_r = static_cast<double>(b); |
286 | 0 | double c_r = static_cast<double>(c); |
287 | | // Here b comes from an unsigned integer, and sgn(b) is always 1, |
288 | | // which is only used to preserve the complete algorithm |
289 | 0 | double x1 = (-b_r - sgn(b_r) * sqrtdis) / (a_r + a_r); |
290 | 0 | double x2 = c_r / (a_r * x1); |
291 | 0 | return std::make_pair(x1, x2); |
292 | 0 | } |
293 | | |
294 | | // Large integer square roots, returns the integer part. |
295 | | // The time complexity is lower than the traditional dichotomy |
296 | | // and Newton iteration method, and the number of iterations is fixed. |
297 | | // in real-time systems, functions that execute an unpredictable number of iterations |
298 | | // will make the total time per task unpredictable, and introduce jitter |
299 | | // Reference: https://www.embedded.com/integer-square-roots/ |
300 | | // Reference: https://link.zhihu.com/?target=https%3A//gist.github.com/miloyip/69663b78b26afa0dcc260382a6034b1a |
301 | | // Reference: https://www.zhihu.com/question/35122102 |
302 | 0 | static std::pair<__uint128_t, __uint128_t> sqrt_integer(__uint128_t n) { |
303 | 0 | __uint128_t remainder = 0, root = 0; |
304 | 0 | for (size_t i = 0; i < 64; i++) { |
305 | 0 | root <<= 1; |
306 | 0 | ++root; |
307 | 0 | remainder <<= 2; |
308 | 0 | remainder |= n >> 126; |
309 | 0 | n <<= 2; // Extract 2 MSB from n |
310 | 0 | if (root <= remainder) { |
311 | 0 | remainder -= root; |
312 | 0 | ++root; |
313 | 0 | } else { |
314 | 0 | --root; |
315 | 0 | } |
316 | 0 | } |
317 | 0 | return std::make_pair(root >>= 1, remainder); |
318 | 0 | } |
319 | | |
320 | | // According to the integer part and the remainder of the square root, |
321 | | // Use one-dimensional quadratic equation to solve the fractional part of the square root |
322 | 0 | static double sqrt_fractional(int128_t sqrt_int, int128_t remainder) { |
323 | 0 | std::pair<double, double> p = quadratic_equation_better(1, 2 * sqrt_int, -remainder); |
324 | 0 | if ((0 < p.first) && (p.first < 1)) return p.first; |
325 | 0 | if ((0 < p.second) && (p.second < 1)) return p.second; |
326 | 0 | return 0; |
327 | 0 | } |
328 | | |
329 | | const int128_t DecimalV2Value::SQRT_MOLECULAR_MAGNIFICATION = get_scale_base(PRECISION / 2); |
330 | | const int128_t DecimalV2Value::SQRT_DENOMINATOR = |
331 | | int128_t(std::sqrt(ONE_BILLION) * get_scale_base(PRECISION / 2 - SCALE)); |
332 | | |
333 | 0 | DecimalV2Value DecimalV2Value::sqrt(const DecimalV2Value& v) { |
334 | 0 | int128_t x = v.value(); |
335 | 0 | std::pair<__uint128_t, __uint128_t> sqrt_integer_ret; |
336 | 0 | bool is_negative = (x < 0); |
337 | 0 | if (x == 0) { |
338 | 0 | return DecimalV2Value(0); |
339 | 0 | } |
340 | 0 | sqrt_integer_ret = sqrt_integer(abs(x)); |
341 | 0 | int128_t integer_root = static_cast<int128_t>(sqrt_integer_ret.first); |
342 | 0 | int128_t integer_remainder = static_cast<int128_t>(sqrt_integer_ret.second); |
343 | 0 | double fractional = sqrt_fractional(integer_root, integer_remainder); |
344 | | |
345 | | // Multiplying by SQRT_MOLECULAR_MAGNIFICATION here will not overflow, |
346 | | // because integer_root can be up to 64 bits. |
347 | 0 | int128_t molecular_integer = integer_root * SQRT_MOLECULAR_MAGNIFICATION; |
348 | 0 | int128_t molecular_fractional = |
349 | 0 | static_cast<int128_t>(fractional * SQRT_MOLECULAR_MAGNIFICATION); |
350 | 0 | int128_t ret = (molecular_integer + molecular_fractional) / SQRT_DENOMINATOR; |
351 | 0 | if (is_negative) ret = -ret; |
352 | 0 | return DecimalV2Value(ret); |
353 | 0 | } |
354 | | |
355 | 63 | int DecimalV2Value::parse_from_str(const char* decimal_str, int32_t length) { |
356 | 63 | int32_t error = E_DEC_OK; |
357 | 63 | StringParser::ParseResult result = StringParser::PARSE_SUCCESS; |
358 | | |
359 | 63 | _value = StringParser::string_to_decimal<TYPE_DECIMALV2>(decimal_str, length, PRECISION, SCALE, |
360 | 63 | &result); |
361 | 63 | if (!config::allow_invalid_decimalv2_literal && result != StringParser::PARSE_SUCCESS) { |
362 | 2 | error = E_DEC_BAD_NUM; |
363 | 61 | } else if (config::allow_invalid_decimalv2_literal && result == StringParser::PARSE_FAILURE) { |
364 | 0 | error = E_DEC_BAD_NUM; |
365 | 0 | } |
366 | 63 | return error; |
367 | 63 | } |
368 | | |
369 | 1.08k | std::string DecimalV2Value::to_string(int scale) const { |
370 | 1.08k | int64_t int_val = int_value(); |
371 | 1.08k | int32_t frac_val = abs(frac_value()); |
372 | 1.08k | if (scale < 0 || scale > SCALE) { |
373 | 69 | if (frac_val == 0) { |
374 | 21 | scale = 0; |
375 | 48 | } else { |
376 | 48 | scale = SCALE; |
377 | 332 | while (frac_val != 0 && frac_val % 10 == 0) { |
378 | 284 | frac_val = frac_val / 10; |
379 | 284 | scale--; |
380 | 284 | } |
381 | 48 | } |
382 | 1.01k | } else { |
383 | | // roundup to FIX 17191 |
384 | 1.01k | if (scale < SCALE) { |
385 | 22 | int32_t frac_val_tmp = frac_val / SCALE_TRIM_ARRAY[scale]; |
386 | 22 | if (frac_val / SCALE_TRIM_ARRAY[scale + 1] % 10 >= 5) { |
387 | 2 | frac_val_tmp++; |
388 | 2 | if (frac_val_tmp >= SCALE_TRIM_ARRAY[9 - scale]) { |
389 | 2 | frac_val_tmp = 0; |
390 | 2 | _value >= 0 ? int_val++ : int_val--; |
391 | 2 | } |
392 | 2 | } |
393 | 22 | frac_val = frac_val_tmp; |
394 | 22 | } |
395 | 1.01k | } |
396 | 1.08k | auto f_int = fmt::format_int(int_val); |
397 | 1.08k | if (scale == 0) { |
398 | 21 | return f_int.str(); |
399 | 21 | } |
400 | 1.06k | std::string str; |
401 | 1.06k | if (_value < 0 && int_val == 0 && frac_val != 0) { |
402 | 4 | str.reserve(f_int.size() + scale + 2); |
403 | 4 | str.push_back('-'); |
404 | 1.05k | } else { |
405 | 1.05k | str.reserve(f_int.size() + scale + 1); |
406 | 1.05k | } |
407 | 1.06k | str.append(f_int.data(), f_int.size()); |
408 | 1.06k | str.push_back('.'); |
409 | 1.06k | if (frac_val == 0) { |
410 | 110 | str.append(scale, '0'); |
411 | 951 | } else { |
412 | 951 | auto f_frac = fmt::format_int(frac_val); |
413 | 951 | if (f_frac.size() < scale) { |
414 | 26 | str.append(scale - f_frac.size(), '0'); |
415 | 26 | } |
416 | 951 | str.append(f_frac.data(), f_frac.size()); |
417 | 951 | } |
418 | 1.06k | return str; |
419 | 1.08k | } |
420 | | |
421 | 17 | int32_t DecimalV2Value::to_buffer(char* buffer, int scale) const { |
422 | 17 | int64_t int_val = int_value(); |
423 | 17 | int32_t frac_val = abs(frac_value()); |
424 | 17 | if (scale < 0 || scale > SCALE) { |
425 | 9 | if (frac_val == 0) { |
426 | 4 | scale = 0; |
427 | 5 | } else { |
428 | 5 | scale = SCALE; |
429 | 25 | while (frac_val != 0 && frac_val % 10 == 0) { |
430 | 20 | frac_val = frac_val / 10; |
431 | 20 | scale--; |
432 | 20 | } |
433 | 5 | } |
434 | 9 | } else { |
435 | | // roundup to FIX 17191 |
436 | 8 | if (scale < SCALE) { |
437 | 8 | int32_t frac_val_tmp = frac_val / SCALE_TRIM_ARRAY[scale]; |
438 | 8 | if (frac_val / SCALE_TRIM_ARRAY[scale + 1] % 10 >= 5) { |
439 | 2 | frac_val_tmp++; |
440 | 2 | if (frac_val_tmp >= SCALE_TRIM_ARRAY[9 - scale]) { |
441 | 2 | frac_val_tmp = 0; |
442 | 2 | _value >= 0 ? int_val++ : int_val--; |
443 | 2 | } |
444 | 2 | } |
445 | 8 | frac_val = frac_val_tmp; |
446 | 8 | } |
447 | 8 | } |
448 | 17 | int extra_sign_size = 0; |
449 | 17 | if (_value < 0 && int_val == 0 && frac_val != 0) { |
450 | 2 | *buffer++ = '-'; |
451 | 2 | extra_sign_size = 1; |
452 | 2 | } |
453 | 17 | auto f_int = fmt::format_int(int_val); |
454 | 17 | memcpy(buffer, f_int.data(), f_int.size()); |
455 | 17 | if (scale == 0) { |
456 | 4 | return f_int.size(); |
457 | 4 | } |
458 | 13 | *(buffer + f_int.size()) = '.'; |
459 | 13 | buffer = buffer + f_int.size() + 1; |
460 | 13 | if (frac_val == 0) { |
461 | 5 | memset(buffer, '0', scale); |
462 | 8 | } else { |
463 | 8 | auto f_frac = fmt::format_int(frac_val); |
464 | 8 | if (f_frac.size() < scale) { |
465 | 2 | memset(buffer, '0', scale - f_frac.size()); |
466 | 2 | buffer = buffer + scale - f_frac.size(); |
467 | 2 | } |
468 | 8 | memcpy(buffer, f_frac.data(), f_frac.size()); |
469 | 8 | } |
470 | 13 | return f_int.size() + scale + 1 + extra_sign_size; |
471 | 17 | } |
472 | | |
473 | 66 | std::string DecimalV2Value::to_string() const { |
474 | 66 | return to_string(-1); |
475 | 66 | } |
476 | | |
477 | | // NOTE: only change abstract value, do not change sign |
478 | 2 | void DecimalV2Value::to_max_decimal(int32_t precision, int32_t scale) { |
479 | 2 | static const int64_t INT_MAX_VALUE[PRECISION] = {9ll, |
480 | 2 | 99ll, |
481 | 2 | 999ll, |
482 | 2 | 9999ll, |
483 | 2 | 99999ll, |
484 | 2 | 999999ll, |
485 | 2 | 9999999ll, |
486 | 2 | 99999999ll, |
487 | 2 | 999999999ll, |
488 | 2 | 9999999999ll, |
489 | 2 | 99999999999ll, |
490 | 2 | 999999999999ll, |
491 | 2 | 9999999999999ll, |
492 | 2 | 99999999999999ll, |
493 | 2 | 999999999999999ll, |
494 | 2 | 9999999999999999ll, |
495 | 2 | 99999999999999999ll, |
496 | 2 | 999999999999999999ll}; |
497 | 2 | static const int32_t FRAC_MAX_VALUE[SCALE] = {900000000, 990000000, 999000000, |
498 | 2 | 999900000, 999990000, 999999000, |
499 | 2 | 999999900, 999999990, 999999999}; |
500 | | |
501 | | // precision > 0 && scale >= 0 && scale <= SCALE |
502 | 2 | if (precision <= 0 || scale < 0) return; |
503 | 2 | if (scale > SCALE) scale = SCALE; |
504 | | |
505 | | // precision: (scale, PRECISION] |
506 | 2 | if (precision > PRECISION) precision = PRECISION; |
507 | 2 | if (precision - scale > PRECISION - SCALE) { |
508 | 0 | precision = PRECISION - SCALE + scale; |
509 | 2 | } else if (precision <= scale) { |
510 | 0 | LOG(WARNING) << "Warning: error precision: " << precision << " or scale: " << scale; |
511 | 0 | precision = scale + 1; // correct error precision |
512 | 0 | } |
513 | | |
514 | 2 | int64_t int_value = INT_MAX_VALUE[precision - scale - 1]; |
515 | 2 | int64_t frac_value = scale == 0 ? 0 : FRAC_MAX_VALUE[scale - 1]; |
516 | 2 | _value = static_cast<int128_t>(int_value) * DecimalV2Value::ONE_BILLION + frac_value; |
517 | 2 | } |
518 | | |
519 | 0 | std::size_t hash_value(DecimalV2Value const& value) { |
520 | 0 | return value.hash(0); |
521 | 0 | } |
522 | | |
523 | 52 | int DecimalV2Value::round(DecimalV2Value* to, int rounding_scale, DecimalRoundMode op) { |
524 | 52 | int32_t error = E_DEC_OK; |
525 | 52 | int128_t result; |
526 | | |
527 | 52 | if (rounding_scale >= SCALE) return error; |
528 | 52 | if (rounding_scale < -(PRECISION - SCALE)) return 0; |
529 | | |
530 | 52 | int128_t base = get_scale_base(SCALE - rounding_scale); |
531 | 52 | result = _value / base; |
532 | | |
533 | 52 | int one = _value > 0 ? 1 : -1; |
534 | 52 | int128_t remainder = _value % base; |
535 | 52 | switch (op) { |
536 | 16 | case HALF_UP: |
537 | 16 | case HALF_EVEN: |
538 | 16 | if (abs(remainder) >= (base >> 1)) { |
539 | 4 | result = (result + one) * base; |
540 | 12 | } else { |
541 | 12 | result = result * base; |
542 | 12 | } |
543 | 16 | break; |
544 | 12 | case CEILING: |
545 | 12 | if (remainder > 0 && _value > 0) { |
546 | 4 | result = (result + one) * base; |
547 | 8 | } else { |
548 | 8 | result = result * base; |
549 | 8 | } |
550 | 12 | break; |
551 | 12 | case FLOOR: |
552 | 12 | if (remainder < 0 && _value < 0) { |
553 | 4 | result = (result + one) * base; |
554 | 8 | } else { |
555 | 8 | result = result * base; |
556 | 8 | } |
557 | 12 | break; |
558 | 12 | case TRUNCATE: |
559 | 12 | result = result * base; |
560 | 12 | break; |
561 | 0 | default: |
562 | 0 | break; |
563 | 52 | } |
564 | | |
565 | 52 | to->set_value(result); |
566 | 52 | return error; |
567 | 52 | } |
568 | | |
569 | 3 | bool DecimalV2Value::greater_than_scale(int scale) { |
570 | 3 | if (scale >= SCALE || scale < 0) { |
571 | 0 | return false; |
572 | 3 | } else if (scale == SCALE) { |
573 | 0 | return true; |
574 | 0 | } |
575 | | |
576 | 3 | int frac_val = frac_value(); |
577 | 3 | if (scale == 0) { |
578 | 0 | bool ret = frac_val == 0 ? false : true; |
579 | 0 | return ret; |
580 | 0 | } |
581 | | |
582 | 3 | static const int values[SCALE] = {1, 10, 100, 1000, 10000, |
583 | 3 | 100000, 1000000, 10000000, 100000000}; |
584 | | |
585 | 3 | int base = values[SCALE - scale]; |
586 | 3 | if (frac_val % base != 0) return true; |
587 | 1 | return false; |
588 | 3 | } |
589 | | |
590 | | } // end namespace doris |