GNOME Bugzilla – Bug 123297
Incorrect result due to computations in extended precision
Last modified: 2009-08-15 18:40:50 UTC
This is a bug also reported in the Debian BTS (bug #206549). As I don't know if libxslt has been compiled with bad switches (Debian-only bug?) or if this is a real bug in libxslt, I report it here too. I've also added some comments about the use of the double type. Consider the following files: ---- test.xml ---------------------------------------------------- <?xml version="1.0" standalone="yes"?> <root/> ------------------------------------------------------------------ ---- test.xsl ---------------------------------------------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" indent="no"/> <xsl:template match="/"> <xsl:choose> <xsl:when test="9007199254740992 + 1.00001 = 9007199254740992"> <xsl:text>equal</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>different</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text> </xsl:text> </xsl:template> </xsl:stylesheet> ------------------------------------------------------------------ On my machine (x86), this gives: $ xsltproc --version Using libxml 20511, libxslt 10033 and libexslt 722 xsltproc was compiled against libxml 20510, libxslt 10033 and libexslt 722 libxslt 10033 was compiled against libxml 20510 libexslt 722 was compiled against libxml 20510 $ xsltproc test.xsl test.xml equal But it seems that the XPath recommendation requires the computations to be performed in double precision only, as it is said: "A number can have any double-precision 64-bit format IEEE 754 value"; in this case, "different" should have been output (i.e. when double rounding, one in extended precision then one in double precision, is avoided). This behavior (output = "different") has been confirmed by someone else, using an x86 processor. The fact that libxslt uses the type double of the C standard doesn't mean that it uses the IEEE-754 double precision, as required by the XPath specifications. The IEEE-754 standard allows intermediate computations to be preformed in a higher precision (called extended precision) but in this case, a way to switch this behavior off should also be provided. Some languages allow extended precision (e.g. C), but other languages don't or provide both behaviors depending on some conditions (e.g. Java). In other words, the XPath specifications are stricter than the C standard. AFAIK, the solution is to change the rounding precision when need be (e.g. with __setfpucw on x86, but I don't know if there is a compiler switch to do that automatically).
Libxslt being a library, changing the floating point behaviour of the processor is not acceptable in my opinion. Daniel
When entering a function that needs to do an IEEE-754 double-precision operation, you could get the current FP mode, modify it, and before returning, restore the old FP mode. If you think that this would be too complicated, the behaviour should be documented (perhaps in the features, saying that libxslt may use extended precision internally, depending on the processor, and if the user wants full XPath conformance, the double-precision rounding should be forced from the calling program). This would be acceptable IMHO. And how about xsltproc? It is not a library, and I think that it should switch to double-precision rounding on x86 processors.
if you know how to do this, and care about it, provide a patch. It it's portable enough and don't break the regression tests it's likely to be integrated. Daniel
It seems that only Linux/x86 computes in extended precision by default (I've done tests on FreeBSD and NetBSD machines, and I've been told that MS Windows also configures the processor to round in double precision instead of extended precision). A patch wouldn't be portable (unfortunately), but with a #if preprocessing directive that would be true only under Linux, this should solve the problem in practice on every machine I know of. Would such a patch be OK? FYI about these floating-point problems on Linux/x86 and how a patch could be written: http://www.srware.com/linux_numerics.txt