Bug 1552724 - python-cffi test fail on ppc64le
Summary: python-cffi test fail on ppc64le
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: python-cffi
Version: 29
Hardware: Unspecified
OS: Unspecified
low
unspecified
Target Milestone: ---
Assignee: Miro Hrončok
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Keywords:
Depends On: 1677888
Blocks: PPCTracker 1556161
TreeView+ depends on / blocked
 
Reported: 2018-03-07 15:53 UTC by Mairi Dulaney
Modified: 2019-03-28 10:07 UTC (History)
17 users (show)

(edit)
Clone Of:
(edit)
Last Closed: 2019-03-28 10:07:33 UTC


Attachments (Terms of Use)

Description Mairi Dulaney 2018-03-07 15:53:32 UTC
Description of problem:

This is a tracking bug for python-cffi-1.11.5-1, which currently fails to build on little endian ppc64 due to rounding issues.

____________________________ TestNewFFI1.test_float ____________________________                                                              
                                                                                                                                              
self = <testing.cffi1.test_new_ffi_1.TestNewFFI1 object at 0x7fffb993d630>                                                                    
                                                                                                                                              
    def test_float(self):                                                                                                                     
        p = ffi.new("float[]", [-2, -2.5])                                                                                                    
        assert p[0] == -2.0                                                                                                                   
        assert p[1] == -2.5                                                                                                                   
        p[1] += 17.75                                                                                                                         
        assert p[1] == 15.25                                                                                                                  
        #                                                                                                                                     
        p = ffi.new("float*", 15.75)                                                                                                          
        assert p[0] == 15.75                                                                                                                  
        py.test.raises(TypeError, int, p)                                                                                                     
        py.test.raises(TypeError, float, p)                                                                                                   
        p[0] = 0.0                                                                                                                            
        assert bool(p) is True                                                                                                                
        #                                                                                                                                     
        p = ffi.new("float*", 1.1)                                                                                                            
        f = p[0]                                                                                                                              
        assert f != 1.1      # because of rounding effect                                                                                     
        assert abs(f - 1.1) < 1E-7                                                                                                            
        #                                                                                                                                     
        INF = 1E200 * 1E200                                                                                                                   
        assert 1E200 != INF                                                                                                                   
        p[0] = 1E200                                                                                                                          
>       assert p[0] == INF     # infinite, not enough precision                                                                               
E       assert 21918092.0 == inf                                                                                                              
                                                                                                                                              
testing/cffi1/test_new_ffi_1.py:474: AssertionErro


______________________________ TestFFI.test_float ______________________________                                                              
                                                                                                                                              
self = <testing.cffi0.test_ffi_backend.TestFFI object at 0x7fffb97dd2b0>                                                                      
                                                                                                                                              
    def test_float(self):                                                                                                                     
        ffi = FFI(backend=self.Backend())                                                                                                     
        p = ffi.new("float[]", [-2, -2.5])                                                                                                    
        assert p[0] == -2.0                                                                                                                   
        assert p[1] == -2.5                                                                                                                   
        p[1] += 17.75                                                                                                                         
        assert p[1] == 15.25                                                                                                                  
        #                                                                                                                                     
        p = ffi.new("float*", 15.75)                                                                                                          
        assert p[0] == 15.75                                                                                                                  
        py.test.raises(TypeError, int, p)                                                                                                     
        py.test.raises(TypeError, float, p)                                                                                                   
        p[0] = 0.0                                                                                                                            
        assert bool(p) is True                                                                                                                
        #                                                                                                                                     
        p = ffi.new("float*", 1.1)                                                                                                            
        f = p[0]                                                                                                                              
        assert f != 1.1      # because of rounding effect                                                                                     
        assert abs(f - 1.1) < 1E-7                                                                                                            
        #                                                                                                                                     
        INF = 1E200 * 1E200                                                                                                                   
        assert 1E200 != INF                                                                                                                   
        p[0] = 1E200                                                                                                                          
>       assert p[0] == INF     # infinite, not enough precision                                                                               
E       AssertionError                                                                                                                        
                                                                                                                                              
testing/cffi0/backend_tests.py:416: AssertionError


______________________________ test_complex_types ______________________________                                                              
                                                                                                                                              
    def test_complex_types():                                                                                                                 
        INF = 1E200 * 1E200                                                                                                                   
        for name in ["float", "double"]:                                                                                                      
            p = new_primitive_type(name + " _Complex")                                                                                        
            assert bool(cast(p, 0)) is False                                                                                                  
            assert bool(cast(p, INF))                                                                                                         
            assert bool(cast(p, -INF))                                                                                                        
            assert bool(cast(p, 0j)) is False                                                                                                 
            assert bool(cast(p, INF*1j))                                                                                                      
            assert bool(cast(p, -INF*1j))                                                                                                     
            # "can't convert complex to float", like CPython's "float(0j)"                                                                    
            py.test.raises(TypeError, int, cast(p, -150))                                                                                     
            py.test.raises(TypeError, long, cast(p, -150))                                                                                    
            py.test.raises(TypeError, float, cast(p, -150))                                                                                   
            assert complex(cast(p, 1.25)) == 1.25                                                                                             
            assert complex(cast(p, 1.25j)) == 1.25j                                                                                           
            assert complex(cast(p, complex(0,INF))) == complex(0,INF)                                                                         
            assert complex(cast(p, -INF)) == -INF                                                                                             
            if name == "float":                                                                                                               
                assert complex(cast(p, 1.1j)) != 1.1j         # rounding error                                                                
>               assert complex(cast(p, 1E200+3j)) == INF+3j   # limited range                                                                 
E               AssertionError: assert (21918092+3j) == (inf + 3j)                                                                            
E                +  where (21918092+3j) = complex(<cdata 'float _Complex' (21918092+3j)>)                                                     
E                +    where <cdata 'float _Complex' (21918092+3j)> = cast(<ctype 'float _Complex'>, (1e+200 + 3j))                            
                                                                                                                                              
c/test_c.py:211: AssertionError


_______________________________ test_float_types _______________________________                                                              
                                                                                                                                              
    def test_float_types():                                                                                                                   
        INF = 1E200 * 1E200                                                                                                                   
        for name in ["float", "double"]:                                                                                                      
            p = new_primitive_type(name)                                                                                                      
            assert bool(cast(p, 0)) is False      # since 1.7                                                                                 
            assert bool(cast(p, -0.0)) is False   # since 1.7                                                                                 
            assert bool(cast(p, 1e-42)) is True                                                                                               
            assert bool(cast(p, -1e-42)) is True                                                                                              
            assert bool(cast(p, INF))                                                                                                         
            assert bool(cast(p, -INF))                                                                                                        
            assert bool(cast(p, float("nan")))                                                                                                
            assert int(cast(p, -150)) == -150                                                                                                 
            assert int(cast(p, 61.91)) == 61                                                                                                  
            assert long(cast(p, 61.91)) == 61                                                                                                 
            assert type(int(cast(p, 61.91))) is int                                                                                           
            assert type(int(cast(p, 1E22))) is long                                                                                           
            assert type(long(cast(p, 61.91))) is long                                                                                         
            assert type(long(cast(p, 1E22))) is long                                                                                          
            py.test.raises(OverflowError, int, cast(p, INF))                                                                                  
            py.test.raises(OverflowError, int, cast(p, -INF))                                                                                 
            assert float(cast(p, 1.25)) == 1.25                                                                                               
            assert float(cast(p, INF)) == INF                                                                                                 
            assert float(cast(p, -INF)) == -INF                                                                                               
            if name == "float":                                                                                                               
                assert float(cast(p, 1.1)) != 1.1     # rounding error                                                                        
>               assert float(cast(p, 1E200)) == INF   # limited range                                                                         
E               AssertionError: assert 21918092.0 == inf                                                                                      
E                +  where 21918092.0 = float(<cdata 'float' 21918092.0>)                                                                      
E                +    where <cdata 'float' 21918092.0> = cast(<ctype 'float'>, 1e+200)                                                        
                                                                                                                                              
c/test_c.py:182: AssertionError

Comment 1 Mairi Dulaney 2018-03-10 05:12:31 UTC
Buf filed upstream:

https://bitbucket.org/cffi/cffi/issues/361/tests-fail-due-to-rounding-and-complex

Comment 2 Mairi Dulaney 2018-03-21 21:26:10 UTC
Upstream seems to think this is a problem with glibc, so assigning accordingly.

Comment 3 Carlos O'Donell 2018-03-21 22:59:28 UTC
(In reply to John Dulaney from comment #2)
> Upstream seems to think this is a problem with glibc, so assigning
> accordingly.

I don't see any notes that this is a glibc or gcc problem.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>

int
main (void)
{
  float pf, inff;
  pf = 1e200f;
  inff = 1e200f * 1e200f;
  assert (pf == inff);
  return 0;
}

gcc -O0 -g3 -o math-test ./math-test.c
./math-test.c: In function ‘main’:
./math-test.c:10:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
   pf = 1e200f;
   ^~
./math-test.c:11:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]
   inff = 1e200f * 1e200f;
   ^~~~
./math-test.c:11:3: warning: floating constant exceeds range of ‘float’ [-Woverflow]

As expected, because they all overflow the range of float.

./math-test

Does not assert. Therefore pf is infinity.

Something is wrong with FFI's conversion of the value to the type.

I also do not see where anyone says this is a glibc error.

Though as noted there might still be a compiler issue, but that hasn't been ruled out.

You need to work out the issue in more detail.

Comment 4 Jan Kurik 2018-08-14 10:11:49 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 29 development cycle.
Changing version to '29'.

Comment 5 Miro Hrončok 2018-08-22 19:37:34 UTC
The tests are commented out. I will run them again, but skip float tests on ppc64le for now.

I think after https://fedoraproject.org/wiki/Changes/PPC64LE_Float128_Transition this might no longer be a problem.

Comment 6 Matěj Cepl 2018-09-21 05:22:24 UTC
(In reply to Carlos O'Donell from comment #3)
> I also do not see where anyone says this is a glibc error.
> 
> Though as noted there might still be a compiler issue, but that hasn't been
> ruled out.

See the current conversation on the BitBucket issue. I don't think the conclusion is "This is a GCC bug", but more like "Pleeease, we are out of our depth here. Would somebody from the around the GCC come and tell us what's going on?".

Comment 7 Petr Viktorin 2019-01-07 13:43:10 UTC
Setting this to low priority.

It would be great if someone else would get to this earlier than we can. If that's your case, please assign the bug to yourself (and adjust priority accordingly).

Comment 8 Victor Stinner 2019-03-05 13:27:07 UTC
Can this issue be related to the test_ctypes failure https://bugzilla.redhat.com/show_bug.cgi?id=1540995 which was caused by this GCC fix? https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88892

Comment 9 Florian Weimer 2019-03-05 13:31:53 UTC
(In reply to Victor Stinner from comment #8)
> Can this issue be related to the test_ctypes failure
> https://bugzilla.redhat.com/show_bug.cgi?id=1540995 which was caused by this
> GCC fix? https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88892

Do you mean “fixed by” and not ”caused by”?  Yes, since float types are involved in both cases, this is a possibility.

I have not investigated this bug here because the reproducer in the description does not look very self-contained by me, but then I don't know anything about python-cffi.

Comment 10 Victor Stinner 2019-03-05 13:45:52 UTC
Oops, I mean caused by the GCC bug. This bug now fixed in Rawhide.

Comment 11 Miro Hrončok 2019-03-27 11:34:00 UTC
Seems to be OK on the recent version.


Note You need to log in before you can comment on or make changes to this bug.