/root/doris/be/src/olap/decimal12.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 <cstdint> | 
| 21 |  | #include <iostream> | 
| 22 |  | #include <string> | 
| 23 |  |  | 
| 24 |  | #include "olap/utils.h" | 
| 25 |  |  | 
| 26 |  | namespace doris { | 
| 27 |  | #include "common/compile_check_begin.h" | 
| 28 |  |  | 
| 29 |  | // the sign of integer must be same as fraction | 
| 30 |  | struct decimal12_t { | 
| 31 | 6 |     decimal12_t& operator+=(const decimal12_t& value) { | 
| 32 | 6 |         fraction += value.fraction; | 
| 33 | 6 |         integer += value.integer; | 
| 34 |  |  | 
| 35 | 6 |         if (fraction >= FRAC_RATIO) { | 
| 36 | 0 |             integer += 1; | 
| 37 | 0 |             fraction -= FRAC_RATIO; | 
| 38 | 6 |         } else if (fraction <= -FRAC_RATIO) { | 
| 39 | 1 |             integer -= 1; | 
| 40 | 1 |             fraction += FRAC_RATIO; | 
| 41 | 1 |         } | 
| 42 |  |  | 
| 43 |  |         // if sign of fraction is different from integer | 
| 44 | 6 |         if ((fraction != 0) && (integer != 0) && (fraction ^ integer) < 0) { | 
| 45 | 0 |             bool sign = integer < 0; | 
| 46 | 0 |             integer += (sign ? 1 : -1); | 
| 47 | 0 |             fraction += (sign ? -FRAC_RATIO : FRAC_RATIO); | 
| 48 | 0 |         } | 
| 49 |  |  | 
| 50 |  |         //LOG(WARNING) << "agg: int=" << integer << ", frac=" << fraction; | 
| 51 |  |         //_set_flag(); | 
| 52 | 6 |         return *this; | 
| 53 | 6 |     } | 
| 54 |  |  | 
| 55 | 64 |     bool operator==(const decimal12_t& value) const { return cmp(value) == 0; } | 
| 56 |  |  | 
| 57 | 95.4k |     auto operator<=>(const decimal12_t& value) const { return cmp(value) <=> 0; } | 
| 58 |  |  | 
| 59 | 95.5k |     int32_t cmp(const decimal12_t& other) const { | 
| 60 | 95.5k |         if (integer > other.integer) { | 
| 61 | 47.7k |             return 1; | 
| 62 | 47.8k |         } else if (integer == other.integer) { | 
| 63 | 68 |             if (fraction > other.fraction) { | 
| 64 | 0 |                 return 1; | 
| 65 | 68 |             } else if (fraction == other.fraction) { | 
| 66 | 68 |                 return 0; | 
| 67 | 68 |             } | 
| 68 | 68 |         } | 
| 69 |  |  | 
| 70 | 47.7k |         return -1; | 
| 71 | 95.5k |     } | 
| 72 |  |  | 
| 73 | 7 |     std::string to_string() const { | 
| 74 | 7 |         char buf[128] = {'\0'}; | 
| 75 |  |  | 
| 76 | 7 |         if (integer < 0 || fraction < 0) { | 
| 77 | 0 |             snprintf(buf, sizeof(buf), "-%" PRIu64 ".%09u", std::abs(integer), std::abs(fraction)); | 
| 78 | 7 |         } else { | 
| 79 | 7 |             snprintf(buf, sizeof(buf), "%" PRIu64 ".%09u", std::abs(integer), std::abs(fraction)); | 
| 80 | 7 |         } | 
| 81 |  |  | 
| 82 | 7 |         return std::string(buf); | 
| 83 | 7 |     } | 
| 84 |  |  | 
| 85 |  |     // Not modify this structure, ZoneMap use this from_string and to_string | 
| 86 |  |     // to serialize decimalv2 value to segment files | 
| 87 | 5 |     Status from_string(const std::string& str) { | 
| 88 | 5 |         integer = 0; | 
| 89 | 5 |         fraction = 0; | 
| 90 | 5 |         const char* value_string = str.c_str(); | 
| 91 | 5 |         const char* sign = strchr(value_string, '-'); | 
| 92 |  |  | 
| 93 | 5 |         if (sign != nullptr) { | 
| 94 | 0 |             if (sign != value_string) { | 
| 95 | 0 |                 return Status::Error<ErrorCode::INVALID_ARGUMENT>( | 
| 96 | 0 |                         "decimal12_t::from_string meet invalid sign"); | 
| 97 | 0 |             } else { | 
| 98 | 0 |                 ++value_string; | 
| 99 | 0 |             } | 
| 100 | 0 |         } | 
| 101 |  |  | 
| 102 | 5 |         const char* sepr = strchr(value_string, '.'); | 
| 103 | 5 |         if ((sepr != nullptr && sepr - value_string > MAX_INT_DIGITS_NUM) || | 
| 104 | 5 |             (sepr == nullptr && strlen(value_string) > MAX_INT_DIGITS_NUM)) { | 
| 105 | 1 |             integer = 999999999999999999; | 
| 106 | 1 |             fraction = 999999999; | 
| 107 | 4 |         } else { | 
| 108 | 4 |             int32_t f = 0; | 
| 109 | 4 |             int64_t i = 0; | 
| 110 | 4 |             if (sepr == value_string) { | 
| 111 | 0 |                 sscanf(value_string, ".%9d", &f); | 
| 112 | 4 |             } else { | 
| 113 | 4 |                 sscanf(value_string, "%18" PRId64 ".%9d", &i, &f); | 
| 114 | 4 |             } | 
| 115 | 4 |             integer = i; | 
| 116 | 4 |             fraction = f; | 
| 117 |  |  | 
| 118 | 4 |             int64_t frac_len = | 
| 119 | 4 |                     (nullptr != sepr) ? MAX_FRAC_DIGITS_NUM - static_cast<int64_t>(strlen(sepr + 1)) | 
| 120 | 4 |                                       : MAX_FRAC_DIGITS_NUM; | 
| 121 | 4 |             frac_len = frac_len > 0 ? frac_len : 0; | 
| 122 | 4 |             fraction *= g_power_table[frac_len]; | 
| 123 | 4 |         } | 
| 124 |  |  | 
| 125 | 5 |         if (sign != nullptr) { | 
| 126 | 0 |             fraction = -fraction; | 
| 127 | 0 |             integer = -integer; | 
| 128 | 0 |         } | 
| 129 |  |  | 
| 130 | 5 |         return Status::OK(); | 
| 131 | 5 |     } | 
| 132 |  |  | 
| 133 |  |     static const int32_t FRAC_RATIO = 1000000000; | 
| 134 |  |     static const int32_t MAX_INT_DIGITS_NUM = 18; | 
| 135 |  |     static const int32_t MAX_FRAC_DIGITS_NUM = 9; | 
| 136 |  |  | 
| 137 |  |     int64_t integer; | 
| 138 |  |     int32_t fraction; | 
| 139 |  | } __attribute__((packed)); | 
| 140 |  |  | 
| 141 |  | static_assert(std::is_trivial<decimal12_t>::value, "decimal12_t should be a POD type"); | 
| 142 |  |  | 
| 143 | 0 | inline std::ostream& operator<<(std::ostream& os, const decimal12_t& val) { | 
| 144 | 0 |     os << val.to_string(); | 
| 145 | 0 |     return os; | 
| 146 | 0 | } | 
| 147 |  |  | 
| 148 |  | #include "common/compile_check_end.h" | 
| 149 |  | } // namespace doris |