zeroshade commented on code in PR #43957:
URL: https://github.com/apache/arrow/pull/43957#discussion_r1761537759
##########
cpp/src/arrow/util/basic_decimal.h:
##########
@@ -166,6 +167,317 @@ class ARROW_EXPORT GenericBasicDecimal {
}
};
+template <typename BaseType>
+class ARROW_EXPORT BasicDecimal {
+ public:
+ static_assert(
+ std::is_same_v<BaseType, int32_t> || std::is_same_v<BaseType, int64_t>,
+ "for bitwidths larger than 64 bits use BasicDecimal128 and
BasicDecimal256");
+
+ static constexpr int kMaxPrecision = std::numeric_limits<BaseType>::digits10;
+ static constexpr int kMaxScale = kMaxPrecision;
+ static constexpr int kBitWidth = sizeof(BaseType) * CHAR_BIT;
+ static constexpr int kByteWidth = sizeof(BaseType);
+
+ /// \brief Empty constructor creates a decimal with a value of 0.
+ constexpr BasicDecimal() noexcept : value_(0) {}
+
+ /// \brief Create a decimal from any integer not wider than 64 bits.
+ template <typename T,
+ typename = typename std::enable_if<
+ std::is_integral<T>::value && (sizeof(T) <= sizeof(int64_t)),
T>::type>
+ constexpr BasicDecimal(T value) noexcept // NOLINT(runtime/explicit)
+ : value_(static_cast<BaseType>(value)) {}
+
+ /// \brief Create a decimal from an array of bytes.
+ ///
+ /// Bytes are assumed to be in native-endian byte order.
+ explicit BasicDecimal(const uint8_t* bytes) { memcpy(&value_, bytes,
sizeof(value_)); }
+
+ const uint8_t* native_endian_bytes() const {
+ return reinterpret_cast<const uint8_t*>(&value_);
+ }
+
+ uint8_t* mutable_native_endian_bytes() { return
reinterpret_cast<uint8_t*>(&value_); }
+
+ /// \brief Return the raw bytes of the value in native-endian byte order.
+ std::array<uint8_t, kByteWidth> ToBytes() const {
+ std::array<uint8_t, kByteWidth> out{{0}};
+ memcpy(out.data(), &value_, kByteWidth);
+ return out;
+ }
+
+ /// \brief Copy the raw bytes of the value in native-endian byte order
+ void ToBytes(uint8_t* out) const { memcpy(out, &value_, kByteWidth); }
+
+ /// \brief Return 1 if positive or 0, -1 if strictly negative
+ int64_t Sign() const { return 1 | (value_ >> (sizeof(kBitWidth) - 1)); }
+
+ bool IsNegative() const { return value_ < 0; }
+
+ explicit operator bool() const { return value_ != 0; }
+
+ friend bool operator==(const BasicDecimal& left, const BasicDecimal& right) {
+ return left.value_ == right.value_;
+ }
+
+ friend bool operator!=(const BasicDecimal& left, const BasicDecimal& right) {
+ return left.value_ != right.value_;
+ }
+
+ BaseType value() const { return value_; }
+
+ /// \brief count hte number of leading binary zeroes.
+ int32_t CountLeadingBinaryZeros() const;
+
+ constexpr uint64_t low_bits() const { return static_cast<uint64_t>(value_); }
+
+ protected:
+ BaseType value_;
+};
+
+class BasicDecimal64;
+
+class ARROW_EXPORT BasicDecimal32 : public BasicDecimal<int32_t> {
+ public:
+ using BasicDecimal<int32_t>::BasicDecimal;
+ using ValueType = int32_t;
+
+ /// \brief Negate the current value (in-place)
+ BasicDecimal32& Negate();
+ /// \brief Absolute value (in-place)
+ BasicDecimal32& Abs();
+ /// \brief Absolute value
+ static BasicDecimal32 Abs(const BasicDecimal32& left);
+ /// \brief Add a number to this one. The result is truncated to 32 bits.
+ BasicDecimal32& operator+=(const BasicDecimal32& right);
+ /// \brief Subtract a number from this one. The result is truncated to 32
bits.
+ BasicDecimal32& operator-=(const BasicDecimal32& right);
+ /// \brief Multiply this number by another. The result is truncated to 32
bits.
+ BasicDecimal32& operator*=(const BasicDecimal32& right);
Review Comment:
I tried using CRTP, still gives a compiler error that it can't initialize a
reference to the derived class from the base class :smile:. probably because
`*this` is still the type of the base class, not the derived
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]