| /* |
| * 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 |