diff --git a/cpp/src/arrow/array/array_decimal.h b/cpp/src/arrow/array/array_decimal.h index 7a35da7fa7aa2..0f8d8101912f8 100644 --- a/cpp/src/arrow/array/array_decimal.h +++ b/cpp/src/arrow/array/array_decimal.h @@ -45,6 +45,6 @@ class ARROW_EXPORT BaseDecimalArray : public FixedSizeBinaryArray { }; // Backward compatibility -using DecimalArray = Decimal128Array; +using DecimalArray = BaseDecimalArray<128>; } // namespace arrow diff --git a/cpp/src/arrow/array/array_dict_test.cc b/cpp/src/arrow/array/array_dict_test.cc index 498fbd8a812fb..2bc36a82d1123 100644 --- a/cpp/src/arrow/array/array_dict_test.cc +++ b/cpp/src/arrow/array/array_dict_test.cc @@ -933,12 +933,6 @@ void TestDecimalDictionaryBuilderDoubleTableSize( ASSERT_TRUE(expected.Equals(result)); } -// TEST(TestDecimal64DictionaryBuilder, DoubleTableSize) { -// const auto& decimal_type = arrow::decimal64(18, 0); -// Decimal64Builder decimal_builder(decimal_type); -// TestDecimalDictionaryBuilderDoubleTableSize(decimal_type, decimal_builder); -// } - TEST(TestDecimal128DictionaryBuilder, DoubleTableSize) { const auto& decimal_type = arrow::decimal128(21, 0); Decimal128Builder decimal_builder(decimal_type); diff --git a/cpp/src/arrow/array/builder_decimal.h b/cpp/src/arrow/array/builder_decimal.h index ebad9127d86d6..a04dfd415fdaf 100644 --- a/cpp/src/arrow/array/builder_decimal.h +++ b/cpp/src/arrow/array/builder_decimal.h @@ -63,6 +63,6 @@ class ARROW_EXPORT BaseDecimalBuilder : public FixedSizeBinaryBuilder { }; // Backward compatibility -using DecimalBuilder = Decimal128Builder; +using DecimalBuilder = BaseDecimalBuilder<128>; } // namespace arrow diff --git a/cpp/src/arrow/util/basic_decimal.cc b/cpp/src/arrow/util/basic_decimal.cc index ccf7af82c0827..e1ca749e0c27d 100644 --- a/cpp/src/arrow/util/basic_decimal.cc +++ b/cpp/src/arrow/util/basic_decimal.cc @@ -1186,8 +1186,11 @@ DecimalStatus BasicDecimalAnyWidth::Divide(const BasicDecimalAnyWidth& di bool dividen_was_negative = Sign() == -1; bool divisor_was_negative = divisor.Sign() == -1; - *result = value / divisor.value; - *remainder = value % divisor.value; + BasicDecimalAnyWidth dividen_abs = BasicDecimalAnyWidth::Abs(*this); + BasicDecimalAnyWidth divisor_abs = BasicDecimalAnyWidth::Abs(divisor); + + *result = dividen_abs.value / divisor_abs.value; + *remainder = dividen_abs.value % divisor_abs.value; FixDivisionSigns(result, remainder, dividen_was_negative, divisor_was_negative); return DecimalStatus::kSuccess; diff --git a/cpp/src/arrow/util/basic_decimal.h b/cpp/src/arrow/util/basic_decimal.h index 6fc8b6f53d573..2e458c46b699b 100644 --- a/cpp/src/arrow/util/basic_decimal.h +++ b/cpp/src/arrow/util/basic_decimal.h @@ -339,6 +339,7 @@ ARROW_EXPORT BasicDecimal256 operator/(const BasicDecimal256& left, template class ARROW_EXPORT BasicDecimalAnyWidth { public: + static constexpr int bit_width = width; using ValueType = typename IntTypes::signed_type; /// \brief Empty constructor creates a BasicDecimal with a value of 0. constexpr BasicDecimalAnyWidth() noexcept : value(0) {} @@ -354,16 +355,16 @@ class ARROW_EXPORT BasicDecimalAnyWidth { constexpr BasicDecimalAnyWidth(T value) noexcept : value(static_cast(value)) {} + /// \brief Create a BasicDecimal from an array of bytes. Bytes are assumed to be in + /// native-endian byte order. + explicit BasicDecimalAnyWidth(const uint8_t* bytes); + /// \brief Upcast BasicDecimal with less widths template ::type> constexpr BasicDecimalAnyWidth(const BasicDecimalAnyWidth<_width>& other) noexcept : value(static_cast(other.Value())) {} - /// \brief Create a BasicDecimal from an array of bytes. Bytes are assumed to be in - /// native-endian byte order. - explicit BasicDecimalAnyWidth(const uint8_t* bytes); - /// \brief Negate the current value (in-place) BasicDecimalAnyWidth& Negate(); @@ -373,6 +374,17 @@ class ARROW_EXPORT BasicDecimalAnyWidth { /// \brief Absolute value static BasicDecimalAnyWidth Abs(const BasicDecimalAnyWidth& left); + /// 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 + /// \param[out] result the quotient + /// \param[out] remainder the remainder after the division DecimalStatus Divide(const BasicDecimalAnyWidth& divisor, BasicDecimalAnyWidth* result, BasicDecimalAnyWidth* remainder) const; diff --git a/cpp/src/arrow/util/decimal.h b/cpp/src/arrow/util/decimal.h index 0f8f8d3060213..e8cec7f1f68ab 100644 --- a/cpp/src/arrow/util/decimal.h +++ b/cpp/src/arrow/util/decimal.h @@ -317,16 +317,4 @@ class ARROW_EXPORT DecimalAnyWidth : public BasicDecimalAnyWidth { Status ToArrowStatus(DecimalStatus dstatus) const; }; -// class ARROW_EXPORT Decimal16 : DecimalAnyWidth<16> { -// using DecimalAnyWidth<16>::DecimalAnyWidth; -// }; - -// class ARROW_EXPORT Decimal32 : DecimalAnyWidth<32> { -// using DecimalAnyWidth<32>::DecimalAnyWidth; -// }; - -// class ARROW_EXPORT Decimal64 : DecimalAnyWidth<64> { -// using DecimalAnyWidth<64>::DecimalAnyWidth; -// }; - } // namespace arrow diff --git a/cpp/src/arrow/util/decimal_test.cc b/cpp/src/arrow/util/decimal_test.cc index 2065472a99385..95bb3ac0c8a20 100644 --- a/cpp/src/arrow/util/decimal_test.cc +++ b/cpp/src/arrow/util/decimal_test.cc @@ -1729,20 +1729,20 @@ const std::vector>> TYPED_TEST(DecimalAnyWidthTest, BinaryOperations) { using ValueType = typename arrow::DecimalAnyWidthTest_BinaryOperations_Test< gtest_TypeParam_>::TypeParam::ValueType; - using ArrowValueType = typename arrow::CTypeTraits::ArrowType; auto DecimalFns = DecimalAnyWidthBinaryParams::value; auto NumericFns = DecimalAnyWidthBinaryParams::value; for (size_t i = 0; i < DecimalFns.size(); i++) { - for (auto x : GetRandomNumbers(8)) { - for (auto y : GetRandomNumbers(8)) { + for (ValueType x : GetRandomNumbers(8)) { + for (ValueType y : GetRandomNumbers(8)) { TypeParam d1(x), d2(y); - auto result = DecimalFns[i].second(d1, d2); - auto reference = static_cast(NumericFns[i].second(x, y)); + TypeParam result = DecimalFns[i].second(d1, d2); + ValueType reference = static_cast(NumericFns[i].second(x, y)); ASSERT_EQ(reference, result) - << d1 << " " << DecimalFns[i].first << " " << d2 << " " - << " != " << result; + << "(" << x << " " << DecimalFns[i].first << " " << y << " = " << reference + << ") != (" << d1 << " " << DecimalFns[i].first << " " << d2 << " = " + << result << ")"; } } }