zeroshade commented on code in PR #43957:
URL: https://github.com/apache/arrow/pull/43957#discussion_r1765544427
##########
cpp/src/arrow/util/decimal.cc:
##########
@@ -742,6 +1106,78 @@ static inline uint64_t UInt64FromBigEndian(const uint8_t*
bytes, int32_t length)
return ::arrow::bit_util::FromBigEndian(result);
}
+Result<Decimal32> Decimal32::FromBigEndian(const uint8_t* bytes, int32_t
length) {
+ static constexpr int32_t kMinDecimalBytes = 1;
+ static constexpr int32_t kMaxDecimalBytes = 4;
+
+ if (ARROW_PREDICT_FALSE(length < kMinDecimalBytes || length >
kMaxDecimalBytes)) {
+ return Status::Invalid("Length of byte array passed to
Decimal32::FromBigEndian was ",
+ length, ", but must be between ", kMinDecimalBytes,
" and ",
+ kMaxDecimalBytes);
+ }
+
+ const bool is_negative = static_cast<int8_t>(bytes[0]) < 0;
+
+ uint32_t result = 0;
+ memcpy(reinterpret_cast<uint8_t*>(&result) + kMaxDecimalBytes - length,
bytes, length);
+
+ const auto value = bit_util::FromBigEndian(result);
+ const int32_t bits_offset = std::max(0, length - kMaxDecimalBytes);
+ if (bits_offset == 8) {
+ return Decimal32(value);
+ }
+
+ int32_t final_value = -1 * (is_negative && length < kMaxDecimalBytes);
+ final_value = SafeLeftShift(final_value, bits_offset * CHAR_BIT);
+ final_value |= value;
+ return Decimal32(final_value);
+}
+
+Status Decimal32::ToArrowStatus(DecimalStatus dstatus) const {
+ return arrow::ToArrowStatus(dstatus, 32);
+}
+
+std::ostream& operator<<(std::ostream& os, const Decimal32& decimal) {
+ os << decimal.ToIntegerString();
+ return os;
+}
+
+Result<Decimal64> Decimal64::FromBigEndian(const uint8_t* bytes, int32_t
length) {
+ static constexpr int32_t kMinDecimalBytes = 1;
Review Comment:
updated and fixed
##########
cpp/src/arrow/util/decimal.h:
##########
@@ -31,6 +31,243 @@
namespace arrow {
+class Decimal64;
+
+/// Represents a signed 32-bit decimal value in two's complement.
+/// Calulations wrap around and overflow is ignored.
+/// The max decimal precision that can be safely represented is
+/// 9 significant digits.
+///
+/// The implementation is split into two parts :
+///
+/// 1. BasicDecimal32
+/// - can be safely compiled to IR without references to libstdc++
+/// 2. Decimal32
+/// - has additional functionality on top of BasicDecimal32 to deal with
+/// strings and streams
+class ARROW_EXPORT Decimal32 : public BasicDecimal32 {
+ public:
+ /// \cond FALSE
+ // (need to avoid a duplicate definition in sphinx)
+ using BasicDecimal32::BasicDecimal32;
+ /// \endcond
+
+ /// \brief constructor creates a Decimal32 from a BasicDecimal32
+ constexpr Decimal32(const BasicDecimal32& value) noexcept // NOLINT
runtime/explicit
+ : BasicDecimal32(value) {}
+
+ /// \brief Parse the number from a base 10 string representation
+ explicit Decimal32(const std::string& value);
+
+ /// \brief Empty constructor creates a Decimal32 with a value of 0
+ /// this is required for some older compilers
+ constexpr Decimal32() noexcept : BasicDecimal32() {}
+
+ /// \brief Divide this number by right and return the result.
+ ///
+ /// This operation is not destructive.
+ /// The answer rounds to zero. Signs work like:
+ /// 21 / 5 -> 4, 1
+ /// -21 / 5 -> -4, -1
+ /// 21 / -5 -> -4, 1
+ /// -21 / -5 -> 4, -1
+ /// \param[in] divisor the number to divide by
+ /// \return the pair of the quotient and the remainder
+ Result<std::pair<Decimal32, Decimal32>> Divide(const Decimal32& divisor)
const {
+ std::pair<Decimal32, Decimal32> result;
+ auto dstatus = BasicDecimal32::Divide(divisor, &result.first,
&result.second);
+ ARROW_RETURN_NOT_OK(ToArrowStatus(dstatus));
+ return result;
+ }
+
+ /// \brief Convert the Decimal32 value to a base 10 decimal string with the
given scale
+ std::string ToString(int32_t scale) const;
Review Comment:
tests added
--
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]