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