Coverage Report

Created: 2024-11-22 20:18

/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