You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ra...@apache.org on 2019/07/15 10:48:04 UTC

[arrow] branch master updated: ARROW-5925: [Gandiva][C++] fix rounding in decimal to int cast

This is an automated email from the ASF dual-hosted git repository.

ravindra 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 b3693db  ARROW-5925: [Gandiva][C++] fix rounding in decimal to int cast
b3693db is described below

commit b3693db4590a60f5d33a098d1f57a5bfbc0c1f47
Author: Pindikura Ravindra <ra...@dremio.com>
AuthorDate: Mon Jul 15 16:17:41 2019 +0530

    ARROW-5925: [Gandiva][C++] fix rounding in decimal to int cast
    
    Author: Pindikura Ravindra <ra...@dremio.com>
    
    Closes #4864 from pravindra/arrow-5925 and squashes the following commits:
    
    2c432c36c <Pindikura Ravindra> ARROW-5925:  fix rounding in decimal to int cast
---
 cpp/src/gandiva/precompiled/decimal_ops.cc          | 21 ++++++++++-----------
 cpp/src/gandiva/precompiled/decimal_ops_test.cc     |  4 ++--
 cpp/src/gandiva/tests/decimal_test.cc               |  2 +-
 .../gandiva/evaluator/ProjectorDecimalTest.java     |  6 +++---
 4 files changed, 16 insertions(+), 17 deletions(-)

diff --git a/cpp/src/gandiva/precompiled/decimal_ops.cc b/cpp/src/gandiva/precompiled/decimal_ops.cc
index 6f20f59..3dd74d7 100644
--- a/cpp/src/gandiva/precompiled/decimal_ops.cc
+++ b/cpp/src/gandiva/precompiled/decimal_ops.cc
@@ -467,7 +467,7 @@ int32_t Compare(const BasicDecimalScalar128& x, const BasicDecimalScalar128& y)
 
 #define DECIMAL_OVERFLOW_IF(condition, overflow) \
   do {                                           \
-    if (condition) {                             \
+    if (*overflow || (condition)) {              \
       *overflow = true;                          \
       return 0;                                  \
     }                                            \
@@ -531,16 +531,6 @@ BasicDecimal128 FromInt64(int64_t in, int32_t precision, int32_t scale, bool* ov
   return in * BasicDecimal128::GetScaleMultiplier(scale);
 }
 
-int64_t ToInt64(const BasicDecimalScalar128& in, bool* overflow) {
-  BasicDecimal128 whole, fraction;
-
-  in.value().GetWholeAndFraction(in.scale(), &whole, &fraction);
-  DECIMAL_OVERFLOW_IF((whole > std::numeric_limits<int64_t>::max()) ||
-                          (whole < std::numeric_limits<int64_t>::min()),
-                      overflow);
-  return static_cast<int64_t>(whole.low_bits());
-}
-
 // Helper function to modify the scale and/or precision of a decimal value.
 static BasicDecimal128 ModifyScaleAndPrecision(const BasicDecimalScalar128& x,
                                                int32_t out_precision, int32_t out_scale,
@@ -702,5 +692,14 @@ BasicDecimal128 Convert(const BasicDecimalScalar128& x, int32_t out_precision,
                                 RoundType::kRoundTypeHalfRoundUp, overflow);
 }
 
+int64_t ToInt64(const BasicDecimalScalar128& in, bool* overflow) {
+  auto rounded = RoundWithPositiveScale(in, in.precision(), 0 /*scale*/,
+                                        RoundType::kRoundTypeHalfRoundUp, overflow);
+  DECIMAL_OVERFLOW_IF((rounded > std::numeric_limits<int64_t>::max()) ||
+                          (rounded < std::numeric_limits<int64_t>::min()),
+                      overflow);
+  return static_cast<int64_t>(rounded.low_bits());
+}
+
 }  // namespace decimalops
 }  // namespace gandiva
diff --git a/cpp/src/gandiva/precompiled/decimal_ops_test.cc b/cpp/src/gandiva/precompiled/decimal_ops_test.cc
index b4fe2e6..ef40e61 100644
--- a/cpp/src/gandiva/precompiled/decimal_ops_test.cc
+++ b/cpp/src/gandiva/precompiled/decimal_ops_test.cc
@@ -1009,8 +1009,8 @@ TEST_F(TestDecimalSql, ToInt64) {
   std::vector<std::tuple<int64_t, DecimalScalar128, bool>> test_values = {
       // simple ones
       std::make_tuple(-16, DecimalScalar128{-16285, 38, 3}, false),
-      std::make_tuple(-162, DecimalScalar128{-16285, 38, 2}, false),
-      std::make_tuple(-1, DecimalScalar128{-16285, 38, 4}, false),
+      std::make_tuple(-163, DecimalScalar128{-16285, 38, 2}, false),
+      std::make_tuple(-2, DecimalScalar128{-16285, 38, 4}, false),
 
       // border cases
       std::make_tuple(INT64_MIN, DecimalScalar128{INT64_MIN, 38, 0}, false),
diff --git a/cpp/src/gandiva/tests/decimal_test.cc b/cpp/src/gandiva/tests/decimal_test.cc
index 2c29ccf..7e07c12 100644
--- a/cpp/src/gandiva/tests/decimal_test.cc
+++ b/cpp/src/gandiva/tests/decimal_test.cc
@@ -491,7 +491,7 @@ TEST_F(TestDecimal, TestCastFunctions) {
       outputs[4]);
 
   // castBIGINT(decimal)
-  EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 1, -1, -1}), outputs[5]);
+  EXPECT_ARROW_ARRAY_EQUALS(MakeArrowArrayInt64({1, 2, -1, -2}), outputs[5]);
 
   // castDOUBLE(decimal)
   EXPECT_ARROW_ARRAY_EQUALS(array_float64, outputs[6]);
diff --git a/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ProjectorDecimalTest.java b/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ProjectorDecimalTest.java
index 8b38edb..37cc49b 100644
--- a/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ProjectorDecimalTest.java
+++ b/java/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ProjectorDecimalTest.java
@@ -533,8 +533,8 @@ public class ProjectorDecimalTest extends org.apache.arrow.gandiva.evaluator.Bas
     List<ValueVector> output = null;
     ArrowRecordBatch batch = null;
     try {
-      int numRows = 4;
-      String[] aValues = new String[]{"1.23", "1.58", "-1.23", "-1.58"};
+      int numRows = 5;
+      String[] aValues = new String[]{"1.23", "1.50", "98765.78", "-1.23", "-1.58"};
       DecimalVector valuesa = decimalVector(aValues, decimalType.getPrecision(), decimalType.getScale());
       batch = new ArrowRecordBatch(
           numRows,
@@ -556,7 +556,7 @@ public class ProjectorDecimalTest extends org.apache.arrow.gandiva.evaluator.Bas
       eval.evaluate(batch, output);
 
       // compare the outputs.
-      long[] expected = {1, 1, -1, -1};
+      long[] expected = {1, 2, 98766, -1, -2};
       for (int i = 0; i < numRows; i++) {
         assertFalse(resultVector.isNull(i));
         assertEquals(expected[i], resultVector.get(i));