You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by we...@apache.org on 2018/08/06 19:40:19 UTC
[arrow] 04/15: ARROW-2480: [C++] Enable casting the value of a
decimal to int32_t or int64_t
This is an automated email from the ASF dual-hosted git repository.
wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git
commit 495bf36bedc8614dd49e309760b66f912987c800
Author: Antoine Pitrou <an...@python.org>
AuthorDate: Sat Aug 4 18:37:08 2018 -0400
ARROW-2480: [C++] Enable casting the value of a decimal to int32_t or int64_t
Author: Antoine Pitrou <an...@python.org>
Author: Phillip Cloud <cp...@gmail.com>
Closes #1917 from cpcloud/ARROW-2480 and squashes the following commits:
456624e4 <Antoine Pitrou> Try to fix other compile error
d9c2955a <Antoine Pitrou> Try to fix gcc 4.8 failure
609efaec <Phillip Cloud> ARROW-2480: Enable casting the value of a decimal to int32_t or int64_t
---
cpp/src/arrow/util/decimal-test.cc | 26 ++++++++++++++++++++++++++
cpp/src/arrow/util/decimal.h | 18 ++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/cpp/src/arrow/util/decimal-test.cc b/cpp/src/arrow/util/decimal-test.cc
index 0877617..61884a1 100644
--- a/cpp/src/arrow/util/decimal-test.cc
+++ b/cpp/src/arrow/util/decimal-test.cc
@@ -436,4 +436,30 @@ TEST(Decimal128Test, TestFromBigEndianBadLength) {
ASSERT_RAISES(Invalid, Decimal128::FromBigEndian(0, 17, &out));
}
+TEST(Decimal128Test, TestToInteger) {
+ Decimal128 value1("1234");
+ int32_t out1;
+
+ Decimal128 value2("-1234");
+ int64_t out2;
+
+ ASSERT_OK(value1.ToInteger(&out1));
+ ASSERT_EQ(1234, out1);
+
+ ASSERT_OK(value1.ToInteger(&out2));
+ ASSERT_EQ(1234, out2);
+
+ ASSERT_OK(value2.ToInteger(&out1));
+ ASSERT_EQ(-1234, out1);
+
+ ASSERT_OK(value2.ToInteger(&out2));
+ ASSERT_EQ(-1234, out2);
+
+ Decimal128 invalid_int32(static_cast<int64_t>(std::pow(2, 31)));
+ ASSERT_RAISES(Invalid, invalid_int32.ToInteger(&out1));
+
+ Decimal128 invalid_int64("12345678912345678901");
+ ASSERT_RAISES(Invalid, invalid_int64.ToInteger(&out2));
+}
+
} // namespace arrow
diff --git a/cpp/src/arrow/util/decimal.h b/cpp/src/arrow/util/decimal.h
index b3180cb..7280362 100644
--- a/cpp/src/arrow/util/decimal.h
+++ b/cpp/src/arrow/util/decimal.h
@@ -20,11 +20,14 @@
#include <array>
#include <cstdint>
+#include <limits>
+#include <sstream>
#include <string>
#include <type_traits>
#include "arrow/status.h"
#include "arrow/util/macros.h"
+#include "arrow/util/type_traits.h"
#include "arrow/util/visibility.h"
namespace arrow {
@@ -134,6 +137,21 @@ class ARROW_EXPORT Decimal128 {
/// \brief Convert Decimal128 from one scale to another
Status Rescale(int32_t original_scale, int32_t new_scale, Decimal128* out) const;
+ /// \brief Convert to a signed integer
+ template <typename T, typename = EnableIfIsOneOf<T, int32_t, int64_t>>
+ Status ToInteger(T* out) const {
+ constexpr auto min_value = std::numeric_limits<T>::min();
+ constexpr auto max_value = std::numeric_limits<T>::max();
+ const auto& self = *this;
+ if (self < min_value || self > max_value) {
+ std::stringstream buf;
+ buf << "Invalid cast from Decimal128 to " << sizeof(T) << " byte integer";
+ return Status::Invalid(buf.str());
+ }
+ *out = static_cast<T>(low_bits_);
+ return Status::OK();
+ }
+
private:
int64_t high_bits_;
uint64_t low_bits_;