You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by em...@apache.org on 2020/08/08 02:57:41 UTC
[arrow] branch master updated: ARROW-9671: [C++] Fix a bug in
BasicDecimal128 constructor that interprets uint64_t integers with highest
bit set as negative.
This is an automated email from the ASF dual-hosted git repository.
emkornfield pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/master by this push:
new 3d0a9d5 ARROW-9671: [C++] Fix a bug in BasicDecimal128 constructor that interprets uint64_t integers with highest bit set as negative.
3d0a9d5 is described below
commit 3d0a9d58b6fe29dcb208c3fa244c789449517988
Author: Mingyu Zhong <my...@google.com>
AuthorDate: Fri Aug 7 19:56:01 2020 -0700
ARROW-9671: [C++] Fix a bug in BasicDecimal128 constructor that interprets uint64_t integers with highest bit set as negative.
Closes #7915 from MingyuZhong/bn
Lead-authored-by: Mingyu Zhong <my...@google.com>
Co-authored-by: Micah Kornfield <mi...@google.com>
Signed-off-by: Micah Kornfield <em...@gmail.com>
---
cpp/src/arrow/util/basic_decimal.h | 7 ++++---
cpp/src/arrow/util/decimal_test.cc | 22 ++++++++++++++++------
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/cpp/src/arrow/util/basic_decimal.h b/cpp/src/arrow/util/basic_decimal.h
index 01feeac..23c38bb 100644
--- a/cpp/src/arrow/util/basic_decimal.h
+++ b/cpp/src/arrow/util/basic_decimal.h
@@ -51,10 +51,11 @@ class ARROW_EXPORT BasicDecimal128 {
/// \brief Convert any integer value into a BasicDecimal128.
template <typename T,
- typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
+ typename = typename std::enable_if<
+ std::is_integral<T>::value && (sizeof(T) <= sizeof(uint64_t)), T>::type>
constexpr BasicDecimal128(T value) noexcept
- : BasicDecimal128(static_cast<int64_t>(value) >= 0 ? 0 : -1,
- static_cast<uint64_t>(value)) {}
+ : BasicDecimal128(value >= T{0} ? 0 : -1, static_cast<uint64_t>(value)) { // NOLINT
+ }
/// \brief Create a BasicDecimal128 from an array of bytes. Bytes are assumed to be in
/// native-endian byte order.
diff --git a/cpp/src/arrow/util/decimal_test.cc b/cpp/src/arrow/util/decimal_test.cc
index b62992c..856f10e 100644
--- a/cpp/src/arrow/util/decimal_test.cc
+++ b/cpp/src/arrow/util/decimal_test.cc
@@ -218,8 +218,7 @@ TEST(DecimalZerosTest, NoLeadingZerosDecimalPoint) {
template <typename T>
class Decimal128Test : public ::testing::Test {
public:
- Decimal128Test() : value_(42) {}
- const T value_;
+ Decimal128Test() {}
};
using Decimal128Types =
@@ -231,18 +230,29 @@ using Decimal128Types =
TYPED_TEST_SUITE(Decimal128Test, Decimal128Types);
TYPED_TEST(Decimal128Test, ConstructibleFromAnyIntegerType) {
- Decimal128 value(this->value_);
- ASSERT_EQ(42, value.low_bits());
+ Decimal128 value(TypeParam{42});
+ EXPECT_EQ(42, value.low_bits());
+ EXPECT_EQ(0, value.high_bits());
+
+ Decimal128 max_value(std::numeric_limits<TypeParam>::max());
+ EXPECT_EQ(std::numeric_limits<TypeParam>::max(), max_value.low_bits());
+ EXPECT_EQ(0, max_value.high_bits());
+
+ Decimal128 min_value(std::numeric_limits<TypeParam>::min());
+ EXPECT_EQ(std::numeric_limits<TypeParam>::min(), min_value.low_bits());
+ EXPECT_EQ((std::is_signed<TypeParam>::value ? -1 : 0), min_value.high_bits());
}
TEST(Decimal128TestTrue, ConstructibleFromBool) {
Decimal128 value(true);
- ASSERT_EQ(1, value.low_bits());
+ EXPECT_EQ(1, value.low_bits());
+ EXPECT_EQ(0, value.high_bits());
}
TEST(Decimal128TestFalse, ConstructibleFromBool) {
Decimal128 value(false);
- ASSERT_EQ(0, value.low_bits());
+ EXPECT_EQ(0, value.low_bits());
+ EXPECT_EQ(0, value.high_bits());
}
TEST(Decimal128Test, Division) {