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

slawrence pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git


The following commit(s) were added to refs/heads/main by this push:
     new 854a2929f Prefer xs:double over xs:decimal for numeric operations
854a2929f is described below

commit 854a2929f5366b85ac506a341b49d76e8a1c6061
Author: Steve Lawrence <[email protected]>
AuthorDate: Wed Oct 15 14:23:49 2025 -0400

    Prefer xs:double over xs:decimal for numeric operations
    
    Commit 6650eb918e modified numeric operations so that if the args did
    not have any common parent type (e.g. xs:double and xs:int) then we
    always promoted to xs:decimal. However, this caused tiny changes in
    precision for some operations so could lead to minor backwards
    incompatibilities.
    
    This modifies the logic so we only promote numeric operations to
    xs:decimal if one of the args is a xs:nonNegativeInteger, xs:integer, or
    xs:decimal (i.e. arbitrary-precision types). If neither arg is
    arbitrary-precision, then it means both args have finite precision
    (xs:float, xs:double, xs:long, xs:unsignedLong, or subtype) and so we
    promote to xs:double. This should give more efficient performance,
    maintains fixed-precision/width operations, and maintains backwards
    compatibility with previous versions of Daffodil.
    
    DAFFODIL-2574
---
 .../apache/daffodil/core/dpath/NodeInfoUtils.scala    | 19 ++++++++++++++++++-
 .../section23/dfdl_expressions/expressions.tdml       | 13 +++++++++++++
 .../section23/dfdl_expressions/expressions2.tdml      |  2 +-
 .../dfdl_expressions/TestDFDLExpressions.scala        |  3 +++
 4 files changed, 35 insertions(+), 2 deletions(-)

diff --git 
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala
 
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala
index 931332835..6ea89b392 100644
--- 
a/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala
+++ 
b/daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala
@@ -99,7 +99,24 @@ object NodeInfoUtils {
     val lub = NodeInfoUtils.typeLeastUpperBound(leftArgType, rightArgType)
     val argType = lub match {
       case ArrayIndex => Long
-      case SignedNumeric => Decimal // lub of float/double and other types
+      case SignedNumeric => {
+        // SignedNumeric is the least upper bound of float, double, and 
decimal/subtypes. One of
+        // the args must be a float or double, so we must promote to either 
Double or Decimal.
+        // If one of the args is arbitrary width/precision (i.e. non-negative 
integer or a
+        // parent type) then we promote the args to Decimal to maintain that 
level of precision.
+        // Otherwise, it means both args are finite width/precision and we 
promote both args to
+        // Double. This provides efficient math and maintains limited 
precision operations while
+        // still having reasonably good precision. This also maintains 
compatibility with older
+        // version of Daffodil that did most math using Doubles
+        if (
+          NonNegativeInteger.isSubtypeOf(leftArgType) ||
+          NonNegativeInteger.isSubtypeOf(rightArgType)
+        ) {
+          Decimal
+        } else {
+          Double
+        }
+      }
       case Decimal => Decimal
       case Double => Double
       case Float => Float
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 7301e4164..9dc1ae1ed 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
@@ -7427,6 +7427,9 @@ blastoff
     <xs:element name="mod02" type="xs:double" dfdl:inputValueCalc="{ 
xs:double(10.5) mod xs:double(3) }" />
     <xs:element name="mod03" type="xs:float" dfdl:inputValueCalc="{ 
xs:float(10.5) mod xs:float(3) }" />
     <xs:element name="mod04" type="xs:decimal" dfdl:inputValueCalc="{ 
xs:decimal(10.5) mod xs:decimal(3) }" />
+
+    <xs:element name="precision01" type="xs:double" dfdl:inputValueCalc="{ 
xs:int(3) + xs:double(xs:int(34) div xs:double(60.0)) }" />
+    <xs:element name="precision02" type="xs:double" dfdl:inputValueCalc="{ 
xs:integer(3) + xs:double(xs:integer(34) div xs:double(60.0)) }" />
   </tdml:defineSchema>
 
   <tdml:parserTestCase name="div01" root="div01" model="XPathMath" 
description="Section 23 - DFDL Expressions - div">
@@ -7770,6 +7773,16 @@ blastoff
     
<tdml:infoset><tdml:dfdlInfoset><mod04>1.5</mod04></tdml:dfdlInfoset></tdml:infoset>
   </tdml:parserTestCase>
 
+  <tdml:parserTestCase name="precision01" root="precision01" model="XPathMath" 
description="Section 23 - DFDL Expressions - div">
+    <tdml:document></tdml:document>
+    
<tdml:infoset><tdml:dfdlInfoset><precision01>3.5666666666666664</precision01></tdml:dfdlInfoset></tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:parserTestCase name="precision02" root="precision02" model="XPathMath" 
description="Section 23 - DFDL Expressions - div">
+    <tdml:document></tdml:document>
+    
<tdml:infoset><tdml:dfdlInfoset><precision02>3.566666666666667</precision02></tdml:dfdlInfoset></tdml:infoset>
+  </tdml:parserTestCase>
+
   <tdml:defineSchema name="DFDLCheckRange">
     <xs:include 
schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
     <dfdl:format ref="ex:GeneralFormat" />
diff --git 
a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions2.tdml
 
b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions2.tdml
index 1602028d6..7337a8cba 100644
--- 
a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions2.tdml
+++ 
b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_expressions/expressions2.tdml
@@ -218,7 +218,7 @@
     <tdml:errors>
       <tdml:error>Schema Definition Error</tdml:error>
       <tdml:error>If-expression branches must have similar types</tdml:error>
-      <tdml:error>Decimal</tdml:error>
+      <tdml:error>Double</tdml:error>
       <tdml:error>String</tdml:error>
     </tdml:errors>
   </tdml:parserTestCase>
diff --git 
a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
 
b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
index 8459131f0..47295ae7d 100644
--- 
a/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
+++ 
b/daffodil-test/src/test/scala/org/apache/daffodil/section23/dfdl_expressions/TestDFDLExpressions.scala
@@ -417,6 +417,9 @@ class TestDFDLExpressions extends TdmlTests {
   @Test def mod03 = test
   @Test def mod04 = test
 
+  @Test def precision01 = test
+  @Test def precision02 = test
+
   // DFDL-1617 - should detect errors due to query-style expressions
   @Test def query_style_01 = test
   @Test def query_style_02 = test

Reply via email to