Coverage Report

Created: 2024-11-22 20:18

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