iceberg-cpp
Loading...
Searching...
No Matches
decimal.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#pragma once
21
26
27#include <array>
28#include <compare>
29#include <cstdint>
30#include <iosfwd>
31#include <string>
32#include <string_view>
33#include <type_traits>
34#include <vector>
35
36#include "iceberg/iceberg_export.h"
37#include "iceberg/result.h"
39#include "iceberg/util/int128.h"
40
41namespace iceberg {
42
46class ICEBERG_EXPORT Decimal : public util::Formattable {
47 public:
48 static constexpr int32_t kBitWidth = 128;
49 static constexpr int32_t kByteWidth = kBitWidth / 8;
50 static constexpr int32_t kMaxPrecision = 38;
51 static constexpr int32_t kMaxScale = 38;
52
54 constexpr Decimal() noexcept = default;
55
57 constexpr Decimal(int128_t value) noexcept // NOLINT implicit conversion
58 : data_(value) {}
59
61 template <typename T>
62 requires(std::is_integral_v<T> && (sizeof(T) <= sizeof(uint64_t)))
63 constexpr Decimal(T value) noexcept // NOLINT implicit conversion
64 : data_(static_cast<int128_t>(value)) {}
65
69 explicit Decimal(std::string_view str);
70
72 constexpr Decimal(int64_t high, uint64_t low) noexcept {
73 data_ = (static_cast<int128_t>(high) << 64) | low;
74 }
75
77 Decimal& Negate();
78
80 Decimal& Abs();
81
83 static Decimal Abs(const Decimal& value);
84
86 Decimal& operator+=(const Decimal& other);
87
89 Decimal& operator-=(const Decimal& other);
90
92 Decimal& operator*=(const Decimal& other);
93
104 Result<std::pair<Decimal, Decimal>> Divide(const Decimal& divisor) const;
105
107 Decimal& operator/=(const Decimal& other);
108
110 Decimal& operator|=(const Decimal& other);
111
113 Decimal& operator&=(const Decimal& other);
114
116 Decimal& operator<<=(uint32_t shift);
117
119 Decimal operator<<(uint32_t shift) const {
120 Decimal result(*this);
121 result <<= shift;
122 return result;
123 }
124
126 Decimal& operator>>=(uint32_t shift);
127
129 Decimal operator>>(uint32_t shift) const {
130 Decimal result(*this);
131 result >>= shift;
132 return result;
133 }
134
136 constexpr int128_t value() const { return data_; }
137
139 constexpr int64_t high() const { return static_cast<int64_t>(data_ >> 64); }
140
142 constexpr uint64_t low() const { return static_cast<uint64_t>(data_); }
143
147 Result<std::string> ToString(int32_t scale) const;
148
150 std::string ToIntegerString() const;
151
153 std::string ToString() const override { return ToIntegerString(); }
154
161 static Result<Decimal> FromString(std::string_view str, int32_t* precision = nullptr,
162 int32_t* scale = nullptr);
163
167 static Result<Decimal> FromBigEndian(const uint8_t* data, int32_t length);
168
172 std::vector<uint8_t> ToBigEndian() const;
173
175 Result<Decimal> Rescale(int32_t orig_scale, int32_t new_scale) const;
176
180 bool FitsInPrecision(int32_t precision) const;
181
183 std::strong_ordering operator<=>(const Decimal& other) const {
184 if (high() != other.high()) {
185 return high() <=> other.high();
186 }
187 return low() <=> other.low();
188 }
189
191 static std::partial_ordering Compare(const Decimal& lhs, const Decimal& rhs,
192 int32_t lhs_scale, int32_t rhs_scale);
193
194 const uint8_t* native_endian_bytes() const {
195 return reinterpret_cast<const uint8_t*>(&data_);
196 }
197
199 std::array<uint8_t, kByteWidth> ToBytes() const;
200
202 int64_t Sign() const { return 1 | (high() >> 63); }
203
205 bool IsNegative() const { return (high() >> 63) < 0; }
206
207 explicit operator bool() const { return data_ != 0; }
208
209 friend bool operator==(const Decimal& lhs, const Decimal& rhs) {
210 return lhs.data_ == rhs.data_;
211 }
212
213 friend bool operator!=(const Decimal& lhs, const Decimal& rhs) {
214 return lhs.data_ != rhs.data_;
215 }
216
217 ICEBERG_EXPORT friend Decimal operator-(const Decimal& operand);
218 ICEBERG_EXPORT friend Decimal operator~(const Decimal& operand);
219
220 ICEBERG_EXPORT friend Decimal operator+(const Decimal& lhs, const Decimal& rhs);
221 ICEBERG_EXPORT friend Decimal operator-(const Decimal& lhs, const Decimal& rhs);
222 ICEBERG_EXPORT friend Decimal operator*(const Decimal& lhs, const Decimal& rhs);
223 ICEBERG_EXPORT friend Decimal operator/(const Decimal& lhs, const Decimal& rhs);
224 ICEBERG_EXPORT friend Decimal operator%(const Decimal& lhs, const Decimal& rhs);
225
226 private:
227 int128_t data_{0};
228};
229
230ICEBERG_EXPORT std::ostream& operator<<(std::ostream& os, const Decimal& decimal);
231
232} // namespace iceberg
Represents 128-bit fixed-point decimal numbers. The max decimal precision that can be safely represen...
Definition decimal.h:46
Decimal operator>>(uint32_t shift) const
Shift right by the given number of bits.
Definition decimal.h:129
std::strong_ordering operator<=>(const Decimal &other) const
Spaceship operator for three-way comparison.
Definition decimal.h:183
constexpr uint64_t low() const
Get the low bits of the two's complement representation of the number.
Definition decimal.h:142
bool IsNegative() const
Check if the Decimal value is negative.
Definition decimal.h:205
constexpr Decimal(T value) noexcept
Create a Decimal from any integer not wider than 64 bits.
Definition decimal.h:63
constexpr int128_t value() const
Get the underlying 128-bit integer representation of the number.
Definition decimal.h:136
constexpr int64_t high() const
Get the high bits of the two's complement representation of the number.
Definition decimal.h:139
std::string ToString() const override
Returns an integer string representation of the decimal value.
Definition decimal.h:153
constexpr Decimal(int64_t high, uint64_t low) noexcept
Create a Decimal from two 64-bit integers.
Definition decimal.h:72
Decimal operator<<(uint32_t shift) const
Shift left by the given number of bits.
Definition decimal.h:119
constexpr Decimal() noexcept=default
Default constructor initializes to zero.
int64_t Sign() const
Returns 1 if positive or zero, -1 if strictly negative.
Definition decimal.h:202
Interface for objects that can be formatted via std::format.
Definition formattable.h:36
constexpr T ToBigEndian(T value)
Convert a value to big-endian format.
Definition endian.h:80
constexpr T FromBigEndian(T value)
Convert a value from big-endian format.
Definition endian.h:90
std::shared_ptr< DecimalType > decimal(int32_t precision, int32_t scale)
Create a DecimalType with the given precision and scale.
Definition type.cc:380
128-bit integer type