This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 29679 - [XQ3Ts] same-key-008
Summary: [XQ3Ts] same-key-008
Status: CLOSED FIXED
Alias: None
Product: XPath / XQuery / XSLT
Classification: Unclassified
Component: XQuery 3 & XPath 3 Test Suite (show other bugs)
Version: Candidate Recommendation
Hardware: PC Windows NT
: P2 normal
Target Milestone: ---
Assignee: O'Neil Delpratt
QA Contact: Mailing list for public feedback on specs from XSL and XML Query WGs
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-06-01 15:29 UTC by Tim Mills
Modified: 2016-07-27 13:32 UTC (History)
2 users (show)

See Also:


Attachments

Description Tim Mills 2016-06-01 15:29:00 UTC
I'm not convinced that the expected result does not depend on implementation-defined behaviour.

Consider looking up the map entry with key

1 div 3 cast as xs:float

using the key 

(1 div 3 cast as xs:float) cast as xs:decimal

According to the rules of casting, the result is 

"the xs:decimal value, within the set of xs:decimal values that the implementation is capable of representing, that is numerically closest to SV. If two values are equally close, then the one that is closest to zero is chosen. "

Under Saxon, I get 0.3333333432674407958984375.

Assuming this is exactly accurate, it requires more than the minimum 18 digits for decimal.  Therefore other implementations may legitimately return something different, and thus the keys may not match under the rules for op:same-key.
Comment 1 Josh Spiegel 2016-06-01 16:02:24 UTC
In this case, it falls under this clause of op:same-key:

"$k1 and $k2 when converted to decimal numbers with no rounding or loss of precision are mathematically equal"

And if I understand you correctly, in your case the lossy decimal created by the cast is different from the lossless decimal created internally by the map implementation.  

In other words, for this query:

  let $f := 1 div 3 cast as xs:float
  let $m := map { $f : 1 }
  return
     map:contains($m, xs:decimal($f))

You will return false but other implementations may return true.

It does seem that the specification allows this but at the same time this test is useful for implementations that do have implementations of decimal that can losslessly represent float and double.

Perhaps we could add a feature in the test suite to tag and optionally filter tests like this.  I have several test bugs on my plate that I could apply this to.
Comment 2 O'Neil Delpratt 2016-06-07 15:32:20 UTC
This bug is related to the email: https://lists.w3.org/Archives/Public/public-xsl-query/2016Jun/0000.html
Comment 3 Tim Mills 2016-07-18 16:09:34 UTC
I was wrong to close this bug.

  DECIMAL PLACES
  123456789012345678

(A) 1/3 float cast to decimal (exact)
0.3333333432674407958984375 
                   ^
(B) 1/3 double cast to decimal (exact)
333314829616256247390992939472198486328125 
                   ^
(C) 1/3 decimal (using 18 decimal places, the minimum required by the specification)
0.333333333333333333
                   ^

So for an implementation which meets the minimum requirement of 18 decimal places in xs:decimal, this test will fail because (A) and (B) require more than 18 decimal places to represent exactly.
Comment 4 Tim Mills 2016-07-18 16:10:17 UTC
Test same-key-025 has a similar problem.
Comment 5 Michael Kay 2016-07-18 16:37:58 UTC
Yes, I think you are correct.

When you take an xs:float value F, for example the xs:float approximation to the value of 1/3, and cast to a decimal, you don't necessarily get a decimal that is mathematically equal to F. That is to say

op:same-key(xs:decimal(F), F)

is not necessarily true.

I think what happened is that in the email thread we decided to retain the status quo in the spec, but we never decided that the test case was therefore valid.
Comment 6 Josh Spiegel 2016-07-18 17:06:11 UTC
For implementations that can represent the float exactly as a decimal number, op:same-key(xs:decimal(F), F) is always true.  I acknowledged in comment 1 that implementations that can not do this may return false in this case.
Comment 7 Tim Mills 2016-07-27 12:57:39 UTC
I have added the dependency suggested by Josh (arbitraryPrecisionDecimal).

This resolves the issue.