You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ja...@apache.org on 2019/02/11 18:29:42 UTC

[incubator-daffodil] branch master updated: Return xs:decimal when dividing xs:long

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

jadams pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-daffodil.git


The following commit(s) were added to refs/heads/master by this push:
     new a20ff41  Return xs:decimal when dividing xs:long
a20ff41 is described below

commit a20ff4172807f5e0264ce68142f15f9798df1e8b
Author: Josh Adams <ja...@tresys.com>
AuthorDate: Thu Feb 7 10:28:02 2019 -0500

    Return xs:decimal when dividing xs:long
    
    Originally dividing xs:long was returning a double, but it should have
    been returning a decimal instead. Similar fixes have been made for other
    integer based types.
    
    DAFFODIL-2063
---
 .../org/apache/daffodil/dpath/NodeInfoUtils.scala  |  4 +-
 .../org/apache/daffodil/dpath/NumericOps.scala     | 80 +++-------------------
 .../section23/dfdl_expressions/expressions.tdml    | 30 ++++++++
 .../dfdl_expressions/TestDFDLExpressions2.scala    |  3 +
 4 files changed, 45 insertions(+), 72 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/NodeInfoUtils.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/NodeInfoUtils.scala
index 8d9052f..bfe3bbf 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/NodeInfoUtils.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/NodeInfoUtils.scala
@@ -86,9 +86,9 @@ object NodeInfoUtils {
       case Decimal => Decimal
       case Integer => Decimal
       case Double => Double
-      case Long => Double
+      case Long => Decimal
       case Float => Float
-      case Int => Float
+      case Int => Decimal
       case ArrayIndex => ArrayIndex
       case _ => Assert.usageError("Unsupported return type: %s".format(resultType))
     }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NumericOps.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NumericOps.scala
index 5be6845..d5cc702 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NumericOps.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/NumericOps.scala
@@ -99,13 +99,7 @@ case object TimesInteger extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(v1).multiply(asBigInt(v2)) }
 }
 case object DivInteger extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JBigDecimal = {
-    val v2bd = asBigDecimal(v2)
-    if (v2bd.compareTo(JBigDecimal.ZERO) == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asBigDecimal(v1).divide(v2bd)
-  }
+  def operate(v1: JNumber, v2: JNumber): JBigDecimal = { DivDecimal.operate(v1, v2) }
 }
 case object IDivInteger extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(DivInteger.operate(v1, v2)) }
@@ -124,13 +118,7 @@ case object TimesNonNegativeInteger extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(v1).multiply(asBigInt(v2)) }
 }
 case object DivNonNegativeInteger extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JBigDecimal = {
-    val v2bd = asBigDecimal(v2)
-    if (v2bd.compareTo(JBigDecimal.ZERO) == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asBigDecimal(v1).divide(v2bd)
-  }
+  def operate(v1: JNumber, v2: JNumber): JBigDecimal = { DivDecimal.operate(v1, v2) }
 }
 case object IDivNonNegativeInteger extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(DivNonNegativeInteger.operate(v1, v2)) }
@@ -149,13 +137,7 @@ case object TimesUnsignedLong extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(v1).multiply(asBigInt(v2)) }
 }
 case object DivUnsignedLong extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JBigDecimal = {
-    val v2bd = asBigDecimal(v2)
-    if (v2bd.compareTo(JBigDecimal.ZERO) == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asBigDecimal(v1).divide(v2bd)
-  }
+  def operate(v1: JNumber, v2: JNumber): JBigDecimal = { DivDecimal.operate(v1, v2) }
 }
 case object IDivUnsignedLong extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JBigInt = { asBigInt(DivUnsignedLong.operate(v1, v2)) }
@@ -174,13 +156,7 @@ case object TimesLong extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asLong(v1) * asLong(v2) }
 }
 case object DivLong extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2l = asLong(v2)
-    if (v2l == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asDouble(v1) / v2l
-  }
+  def operate(v1: JNumber, v2: JNumber): JBigDecimal = { DivDecimal.operate(v1, v2) }
 }
 case object IDivLong extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asLong(DivLong.operate(v1, v2)) }
@@ -199,13 +175,7 @@ case object TimesUnsignedInt extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asLong(v1) * asLong(v2) }
 }
 case object DivUnsignedInt extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2l = asLong(v2)
-    if (v2l == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asDouble(v1) / v2l
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivUnsignedInt extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asLong(DivUnsignedInt.operate(v1, v2)) }
@@ -224,13 +194,7 @@ case object TimesInt extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asInt(v1) * asInt(v2) }
 }
 case object DivInt extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2i = asInt(v2)
-    if (v2i == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asFloat(v1) / v2i
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivInt extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asInt(DivInt.operate(v1, v2)) }
@@ -249,13 +213,7 @@ case object TimesUnsignedShort extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asInt(v1) * asInt(v2) }
 }
 case object DivUnsignedShort extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2i = asInt(v2)
-    if (v2i == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asFloat(v1) / v2i
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivUnsignedShort extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asInt(DivUnsignedShort.operate(v1, v2)) }
@@ -274,13 +232,7 @@ case object TimesShort extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asShort(v1) * asShort(v2) }
 }
 case object DivShort extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2i = asInt(v2)
-    if (v2i == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asFloat(v1) / v2i
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivShort extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asShort(DivShort.operate(v1, v2)) }
@@ -299,13 +251,7 @@ case object TimesUnsignedByte extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asShort(v1) * asShort(v2) }
 }
 case object DivUnsignedByte extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2i = asInt(v2)
-    if (v2i == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asFloat(v1) / v2i
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivUnsignedByte extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asShort(DivUnsignedByte.operate(v1, v2)) }
@@ -324,13 +270,7 @@ case object TimesByte extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asByte(v1) * asByte(v2) }
 }
 case object DivByte extends NumericOp {
-  def operate(v1: JNumber, v2: JNumber): JNumber = {
-    val v2i = asInt(v2)
-    if (v2i == 0) {
-      throw new ArithmeticException("/ by zero")
-    }
-    asFloat(v1) / v2i
-  }
+  def operate(v1: JNumber, v2: JNumber): JNumber = { DivDecimal.operate(v1, v2) }
 }
 case object IDivByte extends NumericOp {
   def operate(v1: JNumber, v2: JNumber): JNumber = { asByte(DivByte.operate(v1, v2)) }
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions.tdml
index 91e8fed..6b56480 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions.tdml
@@ -7047,6 +7047,9 @@
     <xs:element name="div19" type="xs:double" dfdl:inputValueCalc="{ xs:double(5) div xs:double('INF') }" />
     <xs:element name="div20" type="xs:float" dfdl:inputValueCalc="{ xs:float(5) div xs:float('INF') }" />
     <xs:element name="div21" type="xs:double" dfdl:inputValueCalc="{ 90.0 div 1234567.0 }" />
+    <xs:element name="div22" type="xs:decimal" dfdl:inputValueCalc="{ (9 * xs:long(5)) div 1600 }" />
+    <xs:element name="div23" type="xs:double" dfdl:inputValueCalc="{ (9 * xs:long(5)) div 1600 }" />
+    <xs:element name="div24" type="xs:float" dfdl:inputValueCalc="{ (xs:int(5)) div xs:int(3) }" />
 
     <xs:element name="idiv01" type="xs:int" dfdl:inputValueCalc="{ xs:double(5) idiv xs:double(2) }" />
     <xs:element name="idiv02" type="xs:int" dfdl:inputValueCalc="{ xs:float(5) idiv xs:float(2) }" />
@@ -7184,6 +7187,33 @@
     <tdml:infoset><tdml:dfdlInfoset><div21>7.290005321703885E-5</div21></tdml:dfdlInfoset></tdml:infoset>
   </tdml:parserTestCase>
 
+  <tdml:parserTestCase name="div22" root="div22" model="XPathDiv" description="Section 23 - DFDL Expressions - div"
+    config="cfg_errorOnResultCoercion">
+    <tdml:document></tdml:document>
+    <tdml:infoset><tdml:dfdlInfoset><div22>0.028125</div22></tdml:dfdlInfoset></tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="div23" root="div23" model="XPathDiv" description="Section 23 - DFDL Expressions - div"
+    config="cfg_errorOnResultCoercion">
+    <tdml:document></tdml:document>
+      <tdml:errors>
+        <tdml:error>Expression result type</tdml:error>
+        <tdml:error>Decimal</tdml:error>
+        <tdml:error>must be manually cast</tdml:error>
+        <tdml:error>Double</tdml:error>
+      </tdml:errors>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="div24" root="div24" model="XPathDiv" description="Section 23 - DFDL Expressions - div"
+    config="cfg_errorOnResultCoercion">
+    <tdml:document></tdml:document>
+      <tdml:errors>
+        <tdml:error>Expression result type</tdml:error>
+        <tdml:error>Decimal</tdml:error>
+        <tdml:error>must be manually cast</tdml:error>
+        <tdml:error>Float</tdml:error>
+      </tdml:errors>
+  </tdml:parserTestCase>
 
   <tdml:parserTestCase name="idiv01" root="idiv01" model="XPathDiv" description="Section 23 - DFDL Expressions - idiv">
     <tdml:document></tdml:document>
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions2.scala
index e452a77..cb38c7c 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions2.scala
@@ -94,6 +94,9 @@ class TestDFDLExpressions2 {
   @Test def test_div19 { runner.runOneTest("div19") }
   @Test def test_div20 { runner.runOneTest("div20") }
   @Test def test_div21 { runner.runOneTest("div21") }
+  @Test def test_div22 { runner.runOneTest("div22") }
+  @Test def test_div23 { runner.runOneTest("div23") }
+  @Test def test_div24 { runner.runOneTest("div24") }
 
   @Test def test_idiv01 { runner.runOneTest("idiv01") }
   @Test def test_idiv02 { runner.runOneTest("idiv02") }