3636
3737#include " iceberg/iceberg_export.h"
3838#include " iceberg/result.h"
39+ #include " iceberg/util/int128.h"
3940#include " iceberg/util/macros.h"
4041
4142namespace iceberg {
@@ -51,34 +52,22 @@ class ICEBERG_EXPORT Decimal {
5152 static constexpr int32_t kMaxScale = 38 ;
5253
5354 // / \brief Default constructor initializes to zero.
54- constexpr Decimal () noexcept : data_{0 , 0 } {}
55-
56- // / \brief Construct a Decimal from an array of 2 64-bit integers.
57- explicit Decimal (std::array<uint64_t , 2 > data) noexcept : data_(std::move(data)) {}
55+ constexpr Decimal () noexcept = default;
5856
5957 // / \brief Create a Decimal from any integer not wider than 64 bits.
6058 template <typename T>
6159 requires (std::is_integral_v<T> && (sizeof (T) <= sizeof (uint64_t )))
6260 constexpr Decimal (T value) noexcept // NOLINT
6361 {
64- if (value < T{}) {
65- data_[highIndex ()] = ~static_cast <uint64_t >(0 );
66- } else {
67- data_[highIndex ()] = 0 ;
68- }
69- data_[lowIndex ()] = static_cast <uint64_t >(value);
62+ data_ = static_cast <int128_t >(value);
7063 }
7164
7265 // / \brief Parse a Decimal from a string representation.
7366 explicit Decimal (std::string_view str);
7467
7568 // / \brief Create a Decimal from two 64-bit integers.
7669 constexpr Decimal (int64_t high, uint64_t low) noexcept {
77- if constexpr (std::endian::native == std::endian::little) {
78- data_ = {low, static_cast <uint64_t >(high)};
79- } else {
80- data_ = {static_cast <uint64_t >(high), low};
81- }
70+ data_ = (static_cast <int128_t >(high) << 64 ) | low;
8271 }
8372
8473 // / \brief Negate the current Decimal value (in place)
@@ -141,10 +130,10 @@ class ICEBERG_EXPORT Decimal {
141130 }
142131
143132 // / \brief Get the high bits of the two's complement representation of the number.
144- constexpr int64_t high () const { return static_cast <int64_t >(data_[ highIndex ()] ); }
133+ constexpr int64_t high () const { return static_cast <int64_t >(data_ >> 64 ); }
145134
146135 // / \brief Get the low bits of the two's complement representation of the number.
147- constexpr uint64_t low () const { return data_[ lowIndex ()] ; }
136+ constexpr uint64_t low () const { return static_cast < uint64_t >(data_) ; }
148137
149138 // / \brief Convert the Decimal value to a base 10 decimal string with the given scale.
150139 // / \param scale The scale to use for the string representation.
@@ -229,19 +218,19 @@ class ICEBERG_EXPORT Decimal {
229218 }
230219
231220 const uint8_t * native_endian_bytes () const {
232- return reinterpret_cast <const uint8_t *>(data_. data () );
221+ return reinterpret_cast <const uint8_t *>(data_);
233222 }
234223
235224 // / \brief Returns the raw bytes of the value in native-endian byte order.
236225 std::array<uint8_t , kByteWidth > ToBytes () const ;
237226
238227 // / \brief Returns 1 if positive or zero, -1 if strictly negative.
239- int64_t Sign () const { return 1 | (static_cast < int64_t >(data_[ highIndex ()] ) >> 63 ); }
228+ int64_t Sign () const { return 1 | (high ( ) >> 63 ); }
240229
241230 // / \brief Check if the Decimal value is negative.
242- bool IsNegative () const { return static_cast < int64_t >(data_[ highIndex ()] ) < 0 ; }
231+ bool IsNegative () const { return ( high () >> 63 ) < 0 ; }
243232
244- explicit operator bool () const { return data_ != std::array< uint64_t , 2 >{ 0 , 0 } ; }
233+ explicit operator bool () const { return data_ != 0 ; }
245234
246235 friend bool operator ==(const Decimal& lhs, const Decimal& rhs) {
247236 return lhs.data_ == rhs.data_ ;
@@ -268,7 +257,7 @@ class ICEBERG_EXPORT Decimal {
268257 }
269258 }
270259
271- std::array< uint64_t , 2 > data_;
260+ int128_t data_{ 0 } ;
272261};
273262
274263ICEBERG_EXPORT std::ostream& operator <<(std::ostream& os, const Decimal& decimal);
0 commit comments