You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by ja...@apache.org on 2014/06/26 22:45:12 UTC
[12/16] git commit: DRILL-605: Round up decimal when truncating
fractional part
DRILL-605: Round up decimal when truncating fractional part
Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/70e71fc0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/70e71fc0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/70e71fc0
Branch: refs/heads/master
Commit: 70e71fc0acab044cb5eb63e39aa0eaf750d0aa5e
Parents: 69a0788
Author: Mehant Baid <me...@gmail.com>
Authored: Fri Jun 20 20:15:04 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Wed Jun 25 18:04:33 2014 -0700
----------------------------------------------------------------------
.../drill/common/util/DecimalUtility.java | 6 +-
.../templates/Decimal/CastVarCharDecimal.java | 61 ++++++++++++++++++--
.../drill/exec/physical/impl/TestDecimal.java | 6 +-
3 files changed, 63 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/70e71fc0/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java b/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
index 7f1a4a0..0ac870a 100644
--- a/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
+++ b/common/src/main/java/org/apache/drill/common/util/DecimalUtility.java
@@ -276,7 +276,7 @@ public class DecimalUtility {
}
// Truncate the input as per the scale provided
- input = input.setScale(scale, BigDecimal.ROUND_DOWN);
+ input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);
// Separate out the integer part
BigDecimal integerPart = input.setScale(0, BigDecimal.ROUND_DOWN);
@@ -329,14 +329,14 @@ public class DecimalUtility {
}
public static int getDecimal9FromBigDecimal(BigDecimal input, int scale, int precision) {
// Truncate/ or pad to set the input to the correct scale
- input = input.setScale(scale, BigDecimal.ROUND_DOWN);
+ input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);
return (input.unscaledValue().intValue());
}
public static long getDecimal18FromBigDecimal(BigDecimal input, int scale, int precision) {
// Truncate or pad to set the input to the correct scale
- input = input.setScale(scale, BigDecimal.ROUND_DOWN);
+ input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);
return (input.unscaledValue().longValue());
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/70e71fc0/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
index ceebc0a..8a50bb6 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
@@ -84,6 +84,7 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
int integerStartIndex = readIndex;
int integerEndIndex = endIndex;
boolean leadingDigitFound = false;
+ boolean round = false;
int radix = 10;
@@ -96,8 +97,10 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
// Integer end index is just before the scale part begins
integerEndIndex = scaleIndex - 1;
// If the number of fractional digits is > scale specified we might have to truncate
- endIndex = (scaleIndex + out.scale) < endIndex ? (scaleIndex + out.scale) : endIndex;
-
+ if ((scaleIndex + out.scale) < endIndex ) {
+ endIndex = scaleIndex + out.scale;
+ round = true;
+ }
continue;
} else {
// If its not a '.' we expect only numbers
@@ -129,6 +132,21 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
" Total Digits: " + (out.scale + (integerEndIndex - integerStartIndex)));
}
+ // Check if we need to round up
+ if (round == true) {
+ next = in.buffer.getByte(endIndex);
+ next = (byte) Character.digit(next, radix);
+ if (next == -1) {
+ // not a valid digit
+ byte[] buf = new byte[in.end - in.start];
+ in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
+ throw new org.apache.drill.common.exceptions.DrillRuntimeException(new String(buf, com.google.common.base.Charsets.UTF_8));
+ }
+ if (next > 4) {
+ out.value++;
+ }
+ }
+
// Number of fractional digits in the input
int fractionalDigits = (scaleIndex == -1) ? 0 : ((endIndex - scaleIndex));
@@ -180,7 +198,6 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
}
public void eval() {
-
out.buffer = buffer;
out.start = 0;
@@ -225,6 +242,7 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
int radix = 10;
boolean leadingDigitFound = false;
+ boolean round = false;
/* This is the first pass, we get the number of integer digits and based on the provided scale
* we compute which index into the ByteBuf we start storing the integer part of the Decimal
@@ -239,7 +257,10 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
// We have found the decimal point. we can compute the starting index into the Decimal's bytebuf
scaleIndex = readIndex;
// We may have to truncate fractional part if > scale
- scaleEndIndex = ((in.end - scaleIndex) <= out.scale) ? in.end : (scaleIndex + out.scale);
+ if ((in.end - scaleIndex) > out.scale) {
+ scaleEndIndex = scaleIndex + out.scale;
+ round = true;
+ }
break;
}
@@ -337,9 +358,41 @@ public class Cast${type.from}${type.to} implements DrillSimpleFunc {
// added another digit to the current index
ndigits++;
}
+
+ // round up the decimal if we had to chop off a part of it
+ if (round == true) {
+ next = in.buffer.getByte(scaleEndIndex);
+
+ // We expect only numbers beyond this
+ next = (byte) Character.digit(next, radix);
+
+ if (next == -1) {
+ // not a valid digit
+ byte[] buf = new byte[in.end - in.start];
+ in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
+ throw new NumberFormatException(new String(buf, com.google.common.base.Charsets.UTF_8));
+ }
+ if (next > 4) {
+ // Need to round up
+ out.setInteger(decimalBufferIndex, out.getInteger(decimalBufferIndex)+1);
+ }
+ }
// Pad zeroes in the fractional part so that number of digits = MAX_DIGITS
int padding = (int) org.apache.drill.common.util.DecimalUtility.getPowerOfTen((int) (org.apache.drill.common.util.DecimalUtility.MAX_DIGITS - ndigits));
out.setInteger(decimalBufferIndex, out.getInteger(decimalBufferIndex) * padding);
+
+ int carry = 0;
+ do {
+ // propogate the carry
+ int tempValue = out.getInteger(decimalBufferIndex) + carry;
+ if (tempValue >= org.apache.drill.common.util.DecimalUtility.DIGITS_BASE) {
+ carry = tempValue / org.apache.drill.common.util.DecimalUtility.DIGITS_BASE;
+ tempValue = (tempValue % org.apache.drill.common.util.DecimalUtility.DIGITS_BASE);
+ } else {
+ carry = 0;
+ }
+ out.setInteger(decimalBufferIndex--, tempValue);
+ } while (carry > 0 && decimalBufferIndex >= 0);
}
out.setSign(sign);
}
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/70e71fc0/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
index 093366f..489336a 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
@@ -66,7 +66,7 @@ public class TestDecimal extends PopUnitTestBase{
QueryResultBatch batch = results.get(0);
assertTrue(batchLoader.load(batch.getHeader().getDef(), batch.getData()));
- String decimal9Output[] = {"99.0000", "11.1234", "0.1000", "-0.1200", "-123.1234", "-1.0001"};
+ String decimal9Output[] = {"99.0000", "11.1235", "0.1000", "-0.1200", "-123.1234", "-1.0001"};
String decimal18Output[] = {"123456789.000000000", "11.123456789", "0.100000000", "-0.100400000", "-987654321.123456789", "-2.030100000"};
Iterator<VectorWrapper<?>> itr = batchLoader.iterator();
@@ -111,8 +111,8 @@ public class TestDecimal extends PopUnitTestBase{
QueryResultBatch batch = results.get(0);
assertTrue(batchLoader.load(batch.getHeader().getDef(), batch.getData()));
- String decimal9Output[] = {"99.0000", "11.1234", "0.1000", "-0.1200", "-123.1234", "-1.0001"};
- String decimal38Output[] = {"123456789.0000", "11.1234", "0.1000", "-0.1004", "-987654321.1234", "-2.0301"};
+ String decimal9Output[] = {"99.0000", "11.1235", "0.1000", "-0.1200", "-123.1234", "-1.0001"};
+ String decimal38Output[] = {"123456789.0000", "11.1235", "0.1000", "-0.1004", "-987654321.1235", "-2.0301"};
Iterator<VectorWrapper<?>> itr = batchLoader.iterator();