| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #pragma once | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <string> | |
| #include <vector> | |
| #include "paimon/visibility.h" | |
| namespace paimon { | |
| class Bytes; | |
| /// A data structure representing data of Decimal. It might be stored in a compact representation | |
| /// (as a long value) if values are small enough. | |
| class PAIMON_EXPORT Decimal { | |
| public: | |
| using int128_t = __int128_t; | |
| using uint128_t = __uint128_t; | |
| Decimal(int32_t precision, int32_t scale, int128_t value) | |
| : precision_(precision), scale_(scale), value_(value) {} | |
| /// Get the **precision** of this decimal. | |
| /// | |
| /// The precision is the number of digits in the unscaled value. | |
| int32_t Precision() const { | |
| return precision_; | |
| } | |
| /// Get the **scale** of this decimal. | |
| int32_t Scale() const { | |
| return scale_; | |
| } | |
| /// Get the underlying int128_t value of this decimal. | |
| int128_t Value() const { | |
| return value_; | |
| } | |
| /// Get the low 64 bits of the decimal value. | |
| uint64_t LowBits() const { | |
| return static_cast<uint64_t>(value_ & 0xFFFFFFFFFFFFFFFF); | |
| } | |
| /// Get the high 64 bits of the decimal value. | |
| uint64_t HighBits() const { | |
| return static_cast<uint64_t>(value_ >> 64); | |
| } | |
| /// @return Whether the decimal value is small enough to be stored in a long. | |
| bool IsCompact() const { | |
| return precision_ <= MAX_COMPACT_PRECISION; | |
| } | |
| std::string ToString() const; | |
| /// @return Whether the decimal value is small enough to be stored in a long. | |
| static bool IsCompact(int32_t precision) { | |
| return precision <= MAX_COMPACT_PRECISION; | |
| } | |
| /// Creates an instance of `Decimal` from an unscaled long value and the given precision and | |
| /// scale. | |
| static Decimal FromUnscaledLong(int64_t unscaled_long, int32_t precision, int32_t scale) { | |
| return {precision, scale, unscaled_long}; | |
| } | |
| /// @return A long describing the **unscaled value** of this decimal. | |
| int64_t ToUnscaledLong() const { | |
| int64_t ret = 0; | |
| uint64_t low_bits = (value_ & 0xFFFFFFFFFFFFFFFF); | |
| memcpy(&ret, &low_bits, sizeof(uint64_t)); | |
| return ret; | |
| } | |
| /// @return A byte array describing the **unscaled value** of this decimal. | |
| std::vector<char> ToUnscaledBytes() const; | |
| /// Creates an instance of `Decimal` from an unscaled byte array value and the given precision | |
| /// and scale. | |
| static Decimal FromUnscaledBytes(int32_t precision, int32_t scale, Bytes* bytes); | |
| bool operator==(const Decimal& other) const { | |
| if (this == &other) { | |
| return true; | |
| } | |
| return CompareTo(other) == 0; | |
| } | |
| bool operator<(const Decimal& other) const { | |
| if (this == &other) { | |
| return false; | |
| } | |
| return CompareTo(other) < 0; | |
| } | |
| bool operator>(const Decimal& other) const { | |
| if (this == &other) { | |
| return false; | |
| } | |
| return CompareTo(other) > 0; | |
| } | |
| int32_t CompareTo(const Decimal& other) const; | |
| static constexpr int32_t DEFAULT_PRECISION = 10; | |
| static constexpr int32_t DEFAULT_SCALE = 0; | |
| static constexpr int32_t MIN_PRECISION = 1; | |
| static constexpr int32_t MAX_PRECISION = 38; | |
| private: | |
| static constexpr int32_t MAX_COMPACT_PRECISION = 18; | |
| static const int128_t INT128_MAXIMUM_VALUE; | |
| static const int128_t INT128_MINIMUM_VALUE; | |
| static const int64_t POWERS_OF_TEN[MAX_COMPACT_PRECISION + 1]; | |
| static int32_t clz_u128(uint128_t u); | |
| static int32_t count_leading_zero_bytes(uint128_t u); | |
| static int32_t count_leading_all_ones_bytes(uint128_t u); | |
| static int128_t DownScaleInt128(int128_t value, int32_t scale); | |
| static int128_t ScaleInt128(int128_t value, int32_t scale, bool* overflow); | |
| private: | |
| int32_t precision_ = 0; | |
| int32_t scale_ = 0; | |
| int128_t value_ = 0; | |
| }; | |
| } // namespace paimon |