Skip to content

BUG: np.gcd returns negative result for INT_MIN input on s390x #31359

Description

@stratakis

Describe the issue:

np.gcd returns a negative value when one of the inputs is the minimum value of a signed integer type on s390x. The signed-to-unsigned absolute value conversion in npy_gcd (npy_math_internal.h.src) uses a < 0 ? -a : a, which is undefined behavior when a = INT_MIN.

Found it when running tests on a RHEL9/CentOS Stream 9 machine with Python3.14 and GCC 11.5. I wasn't able to reproduce it on other archs or even later GCC versions.


___________________ TestRationalFunctions.test_gcd_overflow ____________________

self = <test_umath.TestRationalFunctions object at 0x3ff66a32690>

    def test_gcd_overflow(self):
        for dtype in (np.int32, np.int64):
            # verify that we don't overflow when taking abs(x)
            # not relevant for lcm, where the result is unrepresentable anyway
            a = dtype(np.iinfo(dtype).min)  # negative power of two
            q = -(a // 4)
>           assert_equal(np.gcd(a,  q * 3), q)
E           AssertionError: 
E           Items are not equal:
E            ACTUAL: np.int32(-536870912)
E            DESIRED: np.int32(536870912)

a          = np.int32(-2147483648)
dtype      = <class 'numpy.int32'>
q          = np.int32(536870912)
self       = <test_umath.TestRationalFunctions object at 0x3ff66a32690>

This seems to be fixed when using -fwrapv

Reproduce the code example:

import numpy as np
a = np.int32(np.iinfo(np.int32).min)
q = -(a // 4)
print(np.gcd(a, q * 3))

That should produce 536870912, instead it produces -536870912

Error message:

Python and NumPy Versions:

Numpy 2.3.4 (but also reproduced on latest versions
Python 3.14
GCC 11.5.0
CFLAGS: -O2 -march=z14

Runtime Environment:

[{'numpy_version': '2.3.4',
'python': '3.14.3 (main, Feb 4 2026, 00:00:00) [GCC 11.5.0 20240719 (Red '
'Hat 11.5.0-14)]',
'uname': uname_result(system='Linux', node='removed', release='5.14.0-697.el9.s390x', version='#1 SMP Wed Apr 22 08:43:20 UTC 2026', machine='s390x')},
{'simd_extensions': {'baseline': [],
'found': ['VX', 'VXE', 'VXE2'],
'not_found': []}},
{'available_backends': ['NETLIB', 'OPENBLAS-OPENMP'],
'current_backend': 'OPENBLAS-OPENMP',
'filepath': '/usr/lib64/libflexiblas.so.3.0',
'internal_api': 'flexiblas',
'loaded_backends': ['OPENBLAS-OPENMP'],
'num_threads': 4,
'prefix': 'libflexiblas',
'user_api': 'blas',
'version': '3.0.4'},
{'architecture': 'Z14',
'filepath': '/usr/lib64/libopenblaso-r0.3.29.so',
'internal_api': 'openblas',
'num_threads': 4,
'prefix': 'libopenblas',
'threading_layer': 'openmp',
'user_api': 'blas',
'version': '0.3.29'},
{'filepath': '/usr/lib64/libgomp.so.1.0.0',
'internal_api': 'openmp',
'num_threads': 4,
'prefix': 'libgomp',
'user_api': 'openmp',
'version': None}]

How does this issue affect you or how did you find it:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions