This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author xdegaye
Recipients tim.peters, vstinner, xdegaye
Date 2019-12-07.11:32:07
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1575718328.32.0.686761855241.issue38992@roundup.psfhosted.org>
In-reply-to
Content
Title: testFsum failure caused by constant folding of a float expression

Description:
------------
Python (Python 3.9.0a1+ heads/master-dirty:ea9835c5d1) is built on a Linux x86_64. This native interpreter is used to cross-compile Python (using the same source) to Android API 24. Next the installation is done locally to DESTDIR by running 'make install' with the env var DESTDIR set and the standard library modules are compiled by the native interpreter during this process.  The content of DESTDIR is then copied to an arm64 android device (Huawei FWIW). The test_math.MathTests.testFsum test fails on the android device with:

AssertionError: -4.309103330548428e+214 != -1.0

This occurs when testing '([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0)' in test_values.

Next the test_math.py file is touched on the android device to force recompilation of the module and testFsum becomes surprisingly successful.

Investigation:
--------------
The hexadecimal representation of 1.7**n on x86_64 and arm64 are:
* different for n in (10, 100, 1000)
* equal for n in [0, 9] or 11

on x86_64:
>>> 1.7**10
201.59939004489993
>>> (1.7**10).hex()
'0x1.9332e34080c95p+7'

on arm64:
>>> 1.7**10
201.59939004489996
>>> (1.7**10).hex()
'0x1.9332e34080c96p+7'

The output of the following foo.py module that has been run on x86_64 and arm64 are attached to this issue:

#######################
import math, dis

def test_fsum():
    x = [1.7**(i+1)-1.7**i for i in range(10)] + [-1.7**10]
    return x

y = test_fsum()
print(y)
print(math.fsum(y))
dis.dis(test_fsum)
#######################

The only difference between both dissasembly of test_fsum() is at bytecode 16 that loads the folded constant 1.7**10.

Conclusion:
-----------
The compilation of the expression '[1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000]' on x86_64 folds '1.7**1000' to 2.8113918290273277e+230 When the list comprehension (the first term of the expression) is executed on arm64, then 1.7**1000 is evaluated as 2.8113918290273273e+230.  On arm64 1.7**1000 - 2.8113918290273277e+230 = -4.309103330548428e+214, hence the AssertionError above.

This is confirmed by changing testFsum to prevent constant folding by replacing 1000 in the testFsum expression with a variable whose value is 1000.  In that case the test_math module compiled on x86_64 is successful on arm64. This could be a fix for this issue unless this fix would be hiding another problem such as .pyc files portability across different platforms and my knowledge of IEEE 754 is too superficial to answer that point.
History
Date User Action Args
2019-12-07 11:32:08xdegayesetrecipients: + xdegaye, tim.peters, vstinner
2019-12-07 11:32:08xdegayesetmessageid: <1575718328.32.0.686761855241.issue38992@roundup.psfhosted.org>
2019-12-07 11:32:08xdegayelinkissue38992 messages
2019-12-07 11:32:07xdegayecreate