Coverage Report

Created: 2025-09-10 18:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/doris/be/src/runtime/decimalv2_value.h
Line
Count
Source
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
#pragma once
19
20
#include <glog/logging.h>
21
#include <stdint.h>
22
23
// IWYU pragma: no_include <bits/std_abs.h>
24
#include <cmath> // IWYU pragma: keep
25
#include <cstdint>
26
#include <cstdlib>
27
#include <iostream>
28
#include <string>
29
#include <string_view>
30
31
#include "util/hash_util.hpp"
32
#include "vec/core/extended_types.h"
33
34
namespace doris {
35
#include "common/compile_check_begin.h"
36
37
typedef __int128_t int128_t;
38
39
enum DecimalError {
40
    E_DEC_OK = 0,
41
    E_DEC_TRUNCATED = 1,
42
    E_DEC_OVERFLOW = 2,
43
    E_DEC_DIV_ZERO = 4,
44
    E_DEC_BAD_NUM = 8,
45
    E_DEC_OOM = 16,
46
47
    E_DEC_ERROR = 31,
48
    E_DEC_FATAL_ERROR = 30
49
};
50
51
enum DecimalRoundMode { HALF_UP = 1, HALF_EVEN = 2, CEILING = 3, FLOOR = 4, TRUNCATE = 5 };
52
53
class DecimalV2Value {
54
public:
55
    using NativeType = __int128_t;
56
    friend DecimalV2Value operator+(const DecimalV2Value& v1, const DecimalV2Value& v2);
57
    friend DecimalV2Value operator-(const DecimalV2Value& v1, const DecimalV2Value& v2);
58
    friend DecimalV2Value operator*(const DecimalV2Value& v1, const DecimalV2Value& v2);
59
    friend DecimalV2Value operator/(const DecimalV2Value& v1, const DecimalV2Value& v2);
60
    friend std::istream& operator>>(std::istream& ism, DecimalV2Value& decimal_value);
61
    friend DecimalV2Value operator-(const DecimalV2Value& v);
62
63
    static constexpr int32_t PRECISION = 27;
64
    static constexpr int32_t SCALE = 9;
65
    static constexpr int32_t SCALE_TRIM_ARRAY[SCALE + 1] = {
66
            1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
67
    static constexpr uint32_t ONE_BILLION = 1000000000;
68
    static constexpr int64_t MAX_INT_VALUE = 999999999999999999;
69
    static constexpr int32_t MAX_FRAC_VALUE = 999999999;
70
    static constexpr int64_t MAX_INT64 = 9223372036854775807ll;
71
    // In sqrt, the integer part and the decimal part of the square root to be solved separately are
72
    // multiplied by the PRECISION/2 power of 10, so that they can be placed in an int128_t variable
73
    static const int128_t SQRT_MOLECULAR_MAGNIFICATION;
74
    // sqrt(ONE_BILLION) * pow(10, PRECISION/2 - SCALE), it is used to calculate SCALE of the sqrt result
75
    static const int128_t SQRT_DENOMINATOR;
76
77
    static const int128_t MAX_DECIMAL_VALUE =
78
            static_cast<int128_t>(MAX_INT64) * ONE_BILLION + MAX_FRAC_VALUE;
79
80
    DecimalV2Value() = default;
81
91
    const int128_t& value() const { return _value; }
82
1.35k
    int128_t& value() { return _value; }
83
84
63
    DecimalV2Value(const std::string& decimal_str) {
85
63
        parse_from_str(decimal_str.c_str(), decimal_str.size());
86
63
    }
87
88
0
    DecimalV2Value(const std::string_view& decimal_str) {
89
0
        parse_from_str(decimal_str.data(), decimal_str.size());
90
0
    }
91
    // Construct from olap engine
92
38
    DecimalV2Value(int64_t int_value, int64_t frac_value) {
93
38
        from_olap_decimal(int_value, frac_value);
94
38
    }
95
96
38
    bool from_olap_decimal(int64_t int_value, int64_t frac_value) {
97
38
        bool success = true;
98
38
        bool is_negative = (int_value < 0 || frac_value < 0);
99
38
        if (is_negative) {
100
11
            int_value = std::abs(int_value);
101
11
            frac_value = std::abs(frac_value);
102
11
        }
103
104
        //if (int_value > MAX_INT_VALUE) {
105
        //    int_value = MAX_INT_VALUE;
106
        //    success = false;
107
        //}
108
109
38
        if (frac_value > MAX_FRAC_VALUE) {
110
1
            frac_value = MAX_FRAC_VALUE;
111
1
            success = false;
112
1
        }
113
114
38
        _value = static_cast<int128_t>(int_value) * ONE_BILLION + frac_value;
115
38
        if (is_negative) _value = -_value;
116
117
38
        return success;
118
38
    }
119
120
12.6k
    explicit DecimalV2Value(int128_t int_value) { _value = int_value; }
121
122
50
    void set_value(int128_t value) { _value = value; }
123
124
1
    DecimalV2Value& assign_from_float(const float float_value) {
125
1
        _value = static_cast<int128_t>(float_value * ONE_BILLION);
126
1
        return *this;
127
1
    }
128
129
51
    DecimalV2Value& assign_from_double(const double double_value) {
130
51
        _value = static_cast<int128_t>(double_value * ONE_BILLION);
131
51
        return *this;
132
51
    }
133
134
    // These cast functions are needed in "functions.cc", which is generated by python script.
135
    // e.g. "ComputeFunctions::Cast_DecimalV2Value_double()"
136
    // Discard the scale part
137
    // ATTN: invoker must make sure no OVERFLOW
138
15.4k
    operator int64_t() const { return static_cast<int64_t>(_value / ONE_BILLION); }
139
140
    // These cast functions are needed in "functions.cc", which is generated by python script.
141
    // e.g. "ComputeFunctions::Cast_DecimalV2Value_double()"
142
    // Discard the scale part
143
    // ATTN: invoker must make sure no OVERFLOW
144
0
    operator int128_t() const { return static_cast<int128_t>(_value / ONE_BILLION); }
145
146
0
    operator wide::Int256() const {
147
0
        wide::Int256 result;
148
0
        wide::Int256::_impl::wide_integer_from_builtin(result, _value);
149
0
        return result;
150
0
    }
151
152
0
    operator bool() const { return _value != 0; }
153
154
0
    operator int8_t() const { return static_cast<char>(operator int64_t()); }
155
156
0
    operator int16_t() const { return static_cast<int16_t>(operator int64_t()); }
157
158
0
    operator int32_t() const { return static_cast<int32_t>(operator int64_t()); }
159
160
0
    operator size_t() const { return static_cast<size_t>(operator int64_t()); }
161
162
0
    operator float() const { return (float)operator double(); }
163
164
0
    operator double() const {
165
0
        std::string str_buff = to_string();
166
0
        double result = std::strtod(str_buff.c_str(), nullptr);
167
0
        return result;
168
0
    }
169
170
    DecimalV2Value& operator+=(const DecimalV2Value& other);
171
172
    // To be Compatible with OLAP
173
    // ATTN: NO-OVERFLOW should be guaranteed.
174
15.4k
    int64_t int_value() const { return operator int64_t(); }
175
176
    // To be Compatible with OLAP
177
    // NOTE: return a negative value if decimal is negative.
178
    // ATTN: the max length of fraction part in OLAP is 9, so the 'big digits' except the first one
179
    // will be truncated.
180
15.4k
    int32_t frac_value() const { return static_cast<int32_t>(_value % ONE_BILLION); }
181
182
29
    bool operator==(const DecimalV2Value& other) const { return _value == other.value(); }
183
184
35
    auto operator<=>(const DecimalV2Value& other) const { return _value <=> other.value(); }
185
186
    // change to maximum value for given precision and scale
187
    // precision/scale - see decimal_bin_size() below
188
    // to              - decimal where where the result will be stored
189
    void to_max_decimal(int precision, int frac);
190
0
    void to_min_decimal(int precision, int frac) {
191
0
        to_max_decimal(precision, frac);
192
0
        if (_value > 0) _value = -_value;
193
0
    }
194
195
    // The maximum of fraction part is "scale".
196
    // If the length of fraction part is less than "scale", '0' will be filled.
197
    std::string to_string(int scale) const;
198
199
    int32_t to_buffer(char* buffer, int scale) const;
200
201
    // Output actual "scale", remove ending zeroes.
202
    std::string to_string() const;
203
204
    // Convert string to decimal
205
    // @param from - value to convert. Doesn't have to be \0 terminated!
206
    //               will stop at the fist non-digit char(nor '.' 'e' 'E'),
207
    //               or reaches the length
208
    // @param length - maximum length
209
    // @return error number.
210
    //
211
    // E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW/E_DEC_BAD_NUM/E_DEC_OOM
212
    // In case of E_DEC_FATAL_ERROR *to is set to decimal zero
213
    // (to make error handling easier)
214
    //
215
    // e.g. "1.2"  ".2"  "1.2e-3"  "1.2e3"
216
    int parse_from_str(const char* decimal_str, size_t length);
217
218
0
    std::string get_debug_info() const { return to_string(); }
219
220
5
    static DecimalV2Value get_min_decimal() {
221
5
        return DecimalV2Value(-MAX_INT_VALUE, MAX_FRAC_VALUE);
222
5
    }
223
224
7
    static DecimalV2Value get_max_decimal() {
225
7
        return DecimalV2Value(MAX_INT_VALUE, MAX_FRAC_VALUE);
226
7
    }
227
228
0
    static DecimalV2Value get_min_decimal(int precision, int scale) {
229
0
        DCHECK(precision > 0 && precision <= 27 && scale >= 0 && scale <= 9 && precision >= scale &&
230
0
               (precision - scale <= 18));
231
0
        return DecimalV2Value(
232
0
                -MAX_INT_VALUE % static_cast<int64_t>(get_scale_base(18 - precision + scale)),
233
0
                MAX_FRAC_VALUE / static_cast<int64_t>(get_scale_base(9 - scale)) *
234
0
                        static_cast<int64_t>(get_scale_base(9 - scale)));
235
0
    }
236
237
0
    static DecimalV2Value get_max_decimal(int precision, int scale) {
238
0
        DCHECK(precision > 0 && precision <= 27 && scale >= 0 && scale <= 9 && precision >= scale &&
239
0
               (precision - scale <= 18));
240
0
        return DecimalV2Value(
241
0
                MAX_INT_VALUE % static_cast<int64_t>(get_scale_base(18 - precision + scale)),
242
0
                MAX_FRAC_VALUE / static_cast<int64_t>(get_scale_base(9 - scale)) *
243
0
                        static_cast<int64_t>(get_scale_base(9 - scale)));
244
0
    }
245
246
    // Solve Square root for int128
247
    static DecimalV2Value sqrt(const DecimalV2Value& v);
248
249
    // set DecimalV2Value to zero
250
0
    void set_to_zero() { _value = 0; }
251
252
0
    void to_abs_value() {
253
0
        if (_value < 0) _value = -_value;
254
0
    }
255
256
18
    uint32_t hash(uint32_t seed) const { return HashUtil::hash(&_value, sizeof(_value), seed); }
257
258
1
    int32_t precision() const { return PRECISION; }
259
260
1.34k
    int32_t scale() const { return SCALE; }
261
262
    bool greater_than_scale(int scale);
263
264
    int round(DecimalV2Value* to, int scale, DecimalRoundMode mode);
265
266
52
    inline static int128_t get_scale_base(int scale) {
267
52
        static const int128_t values[] = {
268
52
                static_cast<int128_t>(1ll),
269
52
                static_cast<int128_t>(10ll),
270
52
                static_cast<int128_t>(100ll),
271
52
                static_cast<int128_t>(1000ll),
272
52
                static_cast<int128_t>(10000ll),
273
52
                static_cast<int128_t>(100000ll),
274
52
                static_cast<int128_t>(1000000ll),
275
52
                static_cast<int128_t>(10000000ll),
276
52
                static_cast<int128_t>(100000000ll),
277
52
                static_cast<int128_t>(1000000000ll),
278
52
                static_cast<int128_t>(10000000000ll),
279
52
                static_cast<int128_t>(100000000000ll),
280
52
                static_cast<int128_t>(1000000000000ll),
281
52
                static_cast<int128_t>(10000000000000ll),
282
52
                static_cast<int128_t>(100000000000000ll),
283
52
                static_cast<int128_t>(1000000000000000ll),
284
52
                static_cast<int128_t>(10000000000000000ll),
285
52
                static_cast<int128_t>(100000000000000000ll),
286
52
                static_cast<int128_t>(1000000000000000000ll),
287
52
                static_cast<int128_t>(1000000000000000000ll) * 10ll,
288
52
                static_cast<int128_t>(1000000000000000000ll) * 100ll,
289
52
                static_cast<int128_t>(1000000000000000000ll) * 1000ll,
290
52
                static_cast<int128_t>(1000000000000000000ll) * 10000ll,
291
52
                static_cast<int128_t>(1000000000000000000ll) * 100000ll,
292
52
                static_cast<int128_t>(1000000000000000000ll) * 1000000ll,
293
52
                static_cast<int128_t>(1000000000000000000ll) * 10000000ll,
294
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000ll,
295
52
                static_cast<int128_t>(1000000000000000000ll) * 1000000000ll,
296
52
                static_cast<int128_t>(1000000000000000000ll) * 10000000000ll,
297
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000ll,
298
52
                static_cast<int128_t>(1000000000000000000ll) * 1000000000000ll,
299
52
                static_cast<int128_t>(1000000000000000000ll) * 10000000000000ll,
300
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000000ll,
301
52
                static_cast<int128_t>(1000000000000000000ll) * 1000000000000000ll,
302
52
                static_cast<int128_t>(1000000000000000000ll) * 10000000000000000ll,
303
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000000000ll,
304
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000000000ll * 10ll,
305
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000000000ll * 100ll,
306
52
                static_cast<int128_t>(1000000000000000000ll) * 100000000000000000ll * 1000ll};
307
52
        if (scale >= 0 && scale < 38) return values[scale];
308
0
        return -1; // Overflow
309
52
    }
310
311
2
    bool is_zero() const { return _value == 0; }
312
313
private:
314
    int128_t _value;
315
};
316
317
DecimalV2Value operator+(const DecimalV2Value& v1, const DecimalV2Value& v2);
318
DecimalV2Value operator-(const DecimalV2Value& v1, const DecimalV2Value& v2);
319
DecimalV2Value operator*(const DecimalV2Value& v1, const DecimalV2Value& v2);
320
DecimalV2Value operator/(const DecimalV2Value& v1, const DecimalV2Value& v2);
321
DecimalV2Value operator%(const DecimalV2Value& v1, const DecimalV2Value& v2);
322
323
DecimalV2Value operator-(const DecimalV2Value& v);
324
325
std::ostream& operator<<(std::ostream& os, DecimalV2Value const& decimal_value);
326
std::istream& operator>>(std::istream& ism, DecimalV2Value& decimal_value);
327
328
std::size_t hash_value(DecimalV2Value const& value);
329
330
#include "common/compile_check_end.h"
331
} // end namespace doris
332
333
template <>
334
struct std::hash<doris::DecimalV2Value> {
335
0
    size_t operator()(const doris::DecimalV2Value& v) const { return doris::hash_value(v); }
336
};
337
338
template <>
339
struct std::equal_to<doris::DecimalV2Value> {
340
8
    bool operator()(const doris::DecimalV2Value& lhs, const doris::DecimalV2Value& rhs) const {
341
8
        return lhs == rhs;
342
8
    }
343
};