You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by sl...@apache.org on 2021/11/10 16:17:00 UTC

[daffodil] branch main updated: Add dfdlx:doubleToRawLong and dfdlx:doubleFromRawLong functions

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 098bb66  Add dfdlx:doubleToRawLong and dfdlx:doubleFromRawLong functions
098bb66 is described below

commit 098bb66fc44da51e7fabbc0eff178e1a7cafc8df
Author: Min Phyo Aung <ma...@owlcyberdefense.com>
AuthorDate: Fri Nov 5 15:30:57 2021 -0400

    Add dfdlx:doubleToRawLong and dfdlx:doubleFromRawLong functions
    
    Added two new functions for converting to/from double and long to preserve binary data floating point conversion.
    
    DAFFODIL-2353
---
 .../org/apache/daffodil/dpath/Expression.scala     | 15 ++++++-
 .../org/apache/daffodil/dpath/DFDLXFunctions.scala | 19 +++++++-
 .../section23/dfdl_functions/Functions.tdml        | 52 ++++++++++++++++++++++
 .../dfdl_expressions/TestDFDLExpressions.scala     |  3 ++
 4 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
index fa44ca0..7f437b0 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dpath/Expression.scala
@@ -584,7 +584,6 @@ case class WholeExpression(
     // object will have been created and given this as its parent pointer.
     //
     Assert.invariant(subExpr == ifor || ifor.isInstanceOf[FunctionCallExpression])
-
     // The result of this function will be used to coerce the result of the
     // expression to the target type. However, we do not always want to allow
     // type coercion even when it might be possible. For example, if the
@@ -596,7 +595,6 @@ case class WholeExpression(
     // then we should still allow that coercion. Below we allow coercion
     // between decimal-like types where precision would not be lost, and all
     // integer-like types (which check for precision loss when evaluated).
-
     val allowCoercion = (inherentType, targetType) match {
       case (_, _) if inherentType == targetType => true
       case (_, _) if (inherentType.isSubtypeOf(NodeInfo.String) && targetType.isSubtypeOf(NodeInfo.String)) => true
@@ -1663,6 +1661,9 @@ case class FunctionCallExpression(functionQNameString: String, expressions: List
           NodeInfo.Boolean, NodeInfo.String, DFDLContainsDFDLEntities(_, _))
       }
 
+
+
+
       case (RefQName(_, "testBit", DFDL), args) => {
         DFDLTestBitExpr(functionQNameString, functionQName, args)
       }
@@ -1687,6 +1688,16 @@ case class FunctionCallExpression(functionQNameString: String, expressions: List
 
       //End typeValueCalc related functions
 
+      case (RefQName(_, "doubleFromRawLong", DFDLX), args) => {
+        FNOneArgExpr(functionQNameString, functionQName, args,
+           NodeInfo.Double, NodeInfo.Long, DFDLXDoubleFromRawLong(_, _))
+      }
+
+      case (RefQName(_, "doubleToRawLong", DFDLX), args) => {
+        FNOneArgExpr(functionQNameString, functionQName, args,
+          NodeInfo.Long, NodeInfo.Double, DFDLXDoubleToRawLong(_, _))
+      }
+
       case (RefQName(_, "lookAhead", DFDLX), args) =>
         FNTwoArgsExpr(functionQNameString, functionQName, args,
           NodeInfo.NonNegativeInteger, NodeInfo.UnsignedInt, NodeInfo.UnsignedInt, DFDLXLookAhead(_))
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
index cf87e3c..bb29b26 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/dpath/DFDLXFunctions.scala
@@ -18,7 +18,7 @@
 package org.apache.daffodil.dpath
 
 import java.math.{BigInteger => JBigInt}
-
+import java.lang.{Double => JDouble}
 import org.apache.daffodil.dpath.NodeInfo.PrimType.PrimNumeric
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.infoset.DINode
@@ -31,6 +31,8 @@ import org.apache.daffodil.processors.unparsers.UnparseError
 import org.apache.daffodil.util.Maybe.Nope
 import org.apache.daffodil.util.Maybe.One
 import passera.unsigned.{UByte, UInt, ULong, UShort}
+import org.apache.daffodil.infoset.DataValue.DataValueLong
+import org.apache.daffodil.infoset.DataValue.DataValueDouble
 
 /**
  * This is the "logical" shift left.
@@ -269,3 +271,18 @@ case class DFDLXLookAhead(recipes: List[CompiledDPath])
     }
   }
 }
+
+
+case class DFDLXDoubleFromRawLong(recipes: CompiledDPath, argType: NodeInfo.Kind )
+  extends FNOneArg(recipes, argType) {
+  override def computeValue(value: DataValuePrimitive, dstate: DState): DataValueDouble = {
+    JDouble.longBitsToDouble(value.getLong)
+  }
+}
+
+case class DFDLXDoubleToRawLong(recipes: CompiledDPath, argType: NodeInfo.Kind )
+  extends FNOneArg(recipes, argType) {
+  override def computeValue(value: DataValuePrimitive, dstate: DState): DataValueLong = {
+    JDouble.doubleToRawLongBits(value.getDouble)
+  }
+}
\ No newline at end of file
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
index bfc5542..fc2e4b8 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section23/dfdl_functions/Functions.tdml
@@ -13920,4 +13920,56 @@
     <tdml:infoset><tdml:dfdlInfoset><pow34>NaN</pow34></tdml:dfdlInfoset></tdml:infoset>
   </tdml:parserTestCase>
 
+	<tdml:defineSchema name="DoubleToRawLong.dfdl.xsd">
+		<xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+		<dfdl:format ref="ex:GeneralFormat" lengthUnits="bytes" representation="binary" />
+		<xs:element name="root">
+			<xs:complexType>
+				<xs:sequence>
+					<xs:element type="xs:double" name="DoubleValue" dfdl:length="8" />
+					<xs:element type="xs:long" name="LongValue" dfdl:inputValueCalc="{ dfdlx:doubleToRawLong(../ex:DoubleValue) }" />
+				</xs:sequence>
+			</xs:complexType>
+		</xs:element>
+	</tdml:defineSchema>
+	<tdml:parserTestCase name="DoubleToRawLong" root="root" model="DoubleToRawLong.dfdl.xsd" description="Extensions - DoubleToRawLong">
+		<tdml:document>
+			<tdml:documentPart type="byte">5DC8 225C AF53 6E1F</tdml:documentPart>
+		</tdml:document>
+		<tdml:infoset>
+			<tdml:dfdlInfoset>
+				<root>
+					<DoubleValue>5.886014640420331E143</DoubleValue>
+					<LongValue>6757689022343245343</LongValue>
+				</root>
+			</tdml:dfdlInfoset>
+		</tdml:infoset>
+	</tdml:parserTestCase>
+  <tdml:defineSchema name="DoubleFromRawLong.dfdl.xsd">
+    <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd" />
+      <dfdl:format ref="ex:GeneralFormat" lengthUnits="bytes" representation="binary" />
+        <xs:element name="root">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element type="xs:long" name="LongValue" dfdl:length="8" />
+              <xs:element type="xs:double" name="DoubleValue" dfdl:inputValueCalc="{ dfdlx:doubleFromRawLong(../ex:LongValue) }" />
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+  </tdml:defineSchema>
+
+  <tdml:parserTestCase name="DoubleFromRawLong" root="root" model="DoubleFromRawLong.dfdl.xsd" description="Extensions - doubleFromRawLong">
+    <tdml:document>
+      <tdml:documentPart type="byte">5DC8 225C AF53 6E1F</tdml:documentPart>
+      </tdml:document>
+        <tdml:infoset>
+          <tdml:dfdlInfoset>
+            <root>
+              <LongValue>6757689022343245343</LongValue>
+              <DoubleValue>5.886014640420331E143</DoubleValue>
+            </root>
+          </tdml:dfdlInfoset>
+        </tdml:infoset>
+  </tdml:parserTestCase>
+
 </tdml:testSuite>
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 67a4574..fc63c00 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
@@ -1031,4 +1031,7 @@ class TestDFDLExpressions {
   @Test def test_short_parent_axis_01(): Unit = { runner.runOneTest("short_parent_axis_01") }
 
   @Test def test_element_long_form_whitespace(): Unit = { runner.runOneTest("element_long_form_whitespace") }
+
+  @Test def test_DoubleFromRawLong(): Unit = { runner2.runOneTest("DoubleFromRawLong") }
+  @Test def test_DoubleToRawLong(): Unit = { runner2.runOneTest("DoubleToRawLong") }
 }