Commit 92a0b75b authored by Sam Sneddon's avatar Sam Sneddon Committed by GitHub

Fix several issues in overflow checks (GH-3591)

* Fix #3588: Make existing overflow code safe

Signed overflow is undefined behaviour in C and compilers can and do optimized on that basis.

* Speed up our overflow impls

Note this is primarily based on performance of compilers which do not
support __builtin_add_overflow (i.e., not Clang >= 3.4 & gcc >= 5),
mostly looking at several gcc 4 releases (used by older, supported,
RHEL releases and Debian 8 "Jessie") and MSVC.

* Use __builtin_XXX_overflow if available

This is much quicker in general, as these all just then read the overflow flag from the status register.
parent 78b799d0
This diff is collapsed.
cimport cython cimport cython
cdef object two = 2 cdef object two = 2
cdef int size_in_bits = sizeof(INT) * 8
cdef int size_in_bits_ = sizeof(INT) * 8
cdef bint is_signed_ = not ((<INT>-1) > 0) cdef bint is_signed_ = not ((<INT>-1) > 0)
cdef INT max_value_ = <INT>(two ** (size_in_bits - is_signed_) - 1) cdef INT max_value_ = <INT>(two ** (size_in_bits_ - is_signed_) - 1)
cdef INT min_value_ = ~max_value_ cdef INT min_value_ = ~max_value_
cdef INT half_ = max_value_ // <INT>2 cdef INT half_ = max_value_ // <INT>2
# Python visible. # Python visible.
size_in_bits = size_in_bits_
is_signed = is_signed_ is_signed = is_signed_
max_value = max_value_ max_value = max_value_
min_value = min_value_ min_value = min_value_
...@@ -230,6 +231,17 @@ def test_lshift(INT a, int b): ...@@ -230,6 +231,17 @@ def test_lshift(INT a, int b):
""" """
>>> test_lshift(1, 10) >>> test_lshift(1, 10)
1024 1024
>>> test_lshift(1, size_in_bits - 2) == 1 << (size_in_bits - 2)
True
>>> test_lshift(0, size_in_bits - 1)
0
>>> test_lshift(1, size_in_bits - 1) == 1 << (size_in_bits - 1) if not is_signed else True
True
>>> if is_signed: expect_overflow(test_lshift, 1, size_in_bits - 1)
>>> expect_overflow(test_lshift, 0, size_in_bits)
>>> expect_overflow(test_lshift, 1, size_in_bits)
>>> expect_overflow(test_lshift, 0, size_in_bits + 1)
>>> expect_overflow(test_lshift, 1, size_in_bits + 1)
>>> expect_overflow(test_lshift, 1, 100) >>> expect_overflow(test_lshift, 1, 100)
>>> expect_overflow(test_lshift, max_value, 1) >>> expect_overflow(test_lshift, max_value, 1)
>>> test_lshift(max_value, 0) == max_value >>> test_lshift(max_value, 0) == max_value
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment