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 2023/06/07 18:29:19 UTC
[daffodil] branch main updated: Support text numbers that parse to negative zero double
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 0299a828f Support text numbers that parse to negative zero double
0299a828f is described below
commit 0299a828fc6f52abaf36961b92f0c03cb89bb6b8
Author: Steve Lawrence <sl...@apache.org>
AuthorDate: Wed Jun 7 12:34:14 2023 -0400
Support text numbers that parse to negative zero double
ICU parses negative zero to a Double type, which we do not currently
allow, expecting only Infinifity or NaN. This modifies the assertion to
allow negative zero as well.
DAFFODIL-2818
---
.../parsers/ConvertTextStandardNumberParser.scala | 17 ++++++++-----
.../runtime1/processors/input/TestICU.scala | 29 ++++++++++++++++++++++
.../section05/simple_types/SimpleTypes.tdml | 12 +++++++++
.../section05/simple_types/TestSimpleTypes.scala | 1 +
4 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ConvertTextStandardNumberParser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ConvertTextStandardNumberParser.scala
index e5c05a5ca..29513c6f4 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ConvertTextStandardNumberParser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/ConvertTextStandardNumberParser.scala
@@ -81,8 +81,11 @@ trait TextDecimalVirtualPointMixin {
bd.scaleByPowerOfTen(-textDecimalVirtualPoint)
}
case d: JDouble => {
- // ICU only returns doubles if they are infinity/NaN, these cannot be scaled
- Assert.invariant(d.isNaN || d.isInfinite)
+ // ICU only returns doubles if they are -INF, INF, NaN, or negative zero, which do not
+ // need scaling
+ Assert.invariant(
+ d.isNaN || d.isInfinite || JDouble.doubleToLongBits(d) == 0x8000000000000000L,
+ )
d
}
// $COVERAGE-OFF$
@@ -228,10 +231,12 @@ case class ConvertTextStandardNumberParser(
}
}
case d: JDouble => {
- // ICU returns a Double only if it parsed NaN, Infinity, or -Infinity. We will later
- // pass this value in primNumber.fromNumber, which will fail if the primitive type
- // does not allow NaN/Infinity
- Assert.invariant(d.isNaN || d.isInfinite)
+ // ICU returns a Double only if it parsed NaN, Infinity, -Infinity, or negative
+ // zero. We will later pass this value in primNumber.fromNumber, which will fail if
+ // the primitive type does not allow NaN/Infinity
+ Assert.invariant(
+ d.isNaN || d.isInfinite || JDouble.doubleToLongBits(d) == 0x8000000000000000L,
+ )
d
}
case bd: ICUBigDecimal => {
diff --git a/daffodil-runtime1/src/test/scala/org/apache/daffodil/runtime1/processors/input/TestICU.scala b/daffodil-runtime1/src/test/scala/org/apache/daffodil/runtime1/processors/input/TestICU.scala
index 647404c71..fdb5d3aca 100644
--- a/daffodil-runtime1/src/test/scala/org/apache/daffodil/runtime1/processors/input/TestICU.scala
+++ b/daffodil-runtime1/src/test/scala/org/apache/daffodil/runtime1/processors/input/TestICU.scala
@@ -23,6 +23,7 @@ import java.text.ParsePosition
import org.apache.daffodil.lib.calendar.TextCalendarConstants
+import com.ibm.icu.math.{ BigDecimal => ICUBigDecimal }
import com.ibm.icu.text.DecimalFormat
import com.ibm.icu.text.DecimalFormatSymbols
import com.ibm.icu.text.SimpleDateFormat
@@ -276,4 +277,32 @@ class TestICU {
assertEquals(dfs.getNaN, df.format(JDouble.NaN))
}
+ /**
+ * Regardless of the ICU number pattern or text being parsed, ICU always returns the following
+ * types
+ *
+ * - Double if the parsed value is INF, -INF, NaN, or negative zero
+ * - Long if the parsed value has no fractional parts and fits in a long
+ * - ICUBigDecimal otherwise
+ */
+ @Test def test_floatingPointReturnType(): Unit = {
+ val dfs = new DecimalFormatSymbols()
+ val df = new DecimalFormat("", dfs)
+ df.applyPattern("###0.0##;-###0.0##")
+
+ assertTrue(df.parse("1.0", pp).isInstanceOf[Long])
+ assertTrue(df.parse("-1.0", pp).isInstanceOf[Long])
+ assertTrue(df.parse("0.0", pp).isInstanceOf[Long])
+ assertTrue(df.parse("9223372036854775807", pp).isInstanceOf[Long])
+
+ assertTrue(df.parse(dfs.getNaN, pp).isInstanceOf[Double])
+ assertTrue(df.parse(dfs.getInfinity, pp).isInstanceOf[Double])
+ assertTrue(df.parse("-" + dfs.getInfinity, pp).isInstanceOf[Double])
+ assertTrue(df.parse("-0.0", pp).isInstanceOf[Double])
+
+ assertTrue(df.parse("9223372036854775808", pp).isInstanceOf[ICUBigDecimal])
+ assertTrue(df.parse("122.75", pp).isInstanceOf[ICUBigDecimal])
+ assertTrue(df.parse("0.3", pp).isInstanceOf[ICUBigDecimal])
+ }
+
}
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
index ee7b5bcd5..68921b3df 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/SimpleTypes.tdml
@@ -3683,6 +3683,18 @@
</tdml:errors>
</tdml:unparserTestCase>
+ <tdml:parserTestCase name="double_negativeZero" root="doubleText"
+ model="SimpleTypes-Embedded.dfdl.xsd" description="Section 5 Schema types-double - DFDL-5-009R"
+ roundTrip="false">
+
+ <tdml:document><![CDATA[-0.0]]></tdml:document>
+ <tdml:infoset>
+ <tdml:dfdlInfoset>
+ <doubleText>-0.0</doubleText>
+ </tdml:dfdlInfoset>
+ </tdml:infoset>
+ </tdml:parserTestCase>
+
<tdml:parserTestCase name="float_text" root="floatText"
model="SimpleTypes-Embedded.dfdl.xsd" description="Section 5 Simple type-float - DFDL-5-008R"
roundTrip="false">
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
index 42fe7f94d..63cb1cdcf 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/section05/simple_types/TestSimpleTypes.scala
@@ -821,6 +821,7 @@ class TestSimpleTypes {
runner.runOneTest("characterDuringValidDouble")
}
@Test def test_double_unparseError(): Unit = { runner.runOneTest("double_unparseError") }
+ @Test def test_double_negativeZero(): Unit = { runner.runOneTest("double_negativeZero") }
@Test def test_float_text(): Unit = { runner.runOneTest("float_text") }
@Test def test_float_text2(): Unit = { runner.runOneTest("float_text2") }