Skip to content

Test regressions on 32-bit architectures: test/test_encode.py::test_encode[binary{32,64]] and test/test_round.py::test_stochastic_rounding_scalar_eq_array #57

Description

@mgorny

Sorry for the late report, but it seems that the current version has some regressions on 32-bit architectures. I can reproduce both on i686 and ARM.

============================= test session starts ==============================
platform linux -- Python 3.13.11, pytest-9.0.3, pluggy-1.6.0
rootdir: /tmp/gfloat
configfile: pyproject.toml
plugins: nbval-0.11.0
collected 42 items

test/test_encode.py FF                                                   [  4%]
test/test_round.py ................FFFF................FFFF              [100%]

=================================== FAILURES ===================================
____________________________ test_encode[binary32] _____________________________

fi = FormatInfo(name='binary32', k=32, precision=24, bias=127, is_signed=True, domain=<Domain.Extended: 2>, has_nz=True, num_high_nans=8388607, has_subnormals=True, is_twos_complement=False)

    @pytest.mark.parametrize("fi", sample_formats)
    def test_encode(fi: FormatInfo) -> None:
        dec = lambda v: decode_float(fi, v).fval
    
        if fi.bits <= 8:
            step = 1
        elif fi.bits <= 16:
            step = 13
        elif fi.bits <= 32:
            step = 73013
        elif fi.bits <= 64:
            step = (73013 << 32) + 39
    
        for i in range(0, 2**fi.bits, step):
            fv = decode_float(fi, i)
            code = encode_float(fi, fv.fval)
            assert (i == code) or (np.isnan(fv.fval) and code == fi.code_of_nan)
            fv2 = decode_float(fi, code)
            np.testing.assert_equal(fv2.fval, fv.fval)
    
        codes = np.arange(0, 2**fi.bits, step, dtype=np.uint64)
        fvals = np.array([decode_float(fi, int(i)).fval for i in codes])
        enc_codes = encode_ndarray(fi, fvals)
        expected_codes: npt.NDArray
        if fi.num_nans == 0:
            assert not np.any(np.isnan(fvals))
            expected_codes = codes
        else:
            expected_codes = np.where(np.isnan(fvals), fi.code_of_nan, codes)
>       np.testing.assert_equal(enc_codes, expected_codes)
E       AssertionError: 
E       Arrays are not equal
E       
E       Mismatched elements: 29297 / 58825 (49.8%)
E       First 5 mismatches are at indices:
E        [29413]: 18446744071562115689 (ACTUAL), 2147531369 (DESIRED)
E        [29414]: 18446744071562188702 (ACTUAL), 2147604382 (DESIRED)
E        [29415]: 18446744071562261715 (ACTUAL), 2147677395 (DESIRED)
E        [29416]: 18446744071562334728 (ACTUAL), 2147750408 (DESIRED)
E        [29417]: 18446744071562407741 (ACTUAL), 2147823421 (DESIRED)
E       Max absolute difference among violations: 4294967296
E       Max relative difference among violations: 1.99995556
E        ACTUAL: array([         0,      73013,     146026, ..., 4294967295, 4294967295,
E              4294967295], shape=(58825,), dtype=uint64)
E        DESIRED: array([         0,      73013,     146026, ..., 4294967295, 4294967295,
E              4294967295], shape=(58825,), dtype=uint64)

test/test_encode.py:42: AssertionError
____________________________ test_encode[binary64] _____________________________

fi = FormatInfo(name='binary64', k=64, precision=53, bias=1023, is_signed=True, domain=<Domain.Extended: 2>, has_nz=True, num_high_nans=4503599627370495, has_subnormals=True, is_twos_complement=False)

    @pytest.mark.parametrize("fi", sample_formats)
    def test_encode(fi: FormatInfo) -> None:
        dec = lambda v: decode_float(fi, v).fval
    
        if fi.bits <= 8:
            step = 1
        elif fi.bits <= 16:
            step = 13
        elif fi.bits <= 32:
            step = 73013
        elif fi.bits <= 64:
            step = (73013 << 32) + 39
    
        for i in range(0, 2**fi.bits, step):
            fv = decode_float(fi, i)
            code = encode_float(fi, fv.fval)
            assert (i == code) or (np.isnan(fv.fval) and code == fi.code_of_nan)
            fv2 = decode_float(fi, code)
            np.testing.assert_equal(fv2.fval, fv.fval)
    
        codes = np.arange(0, 2**fi.bits, step, dtype=np.uint64)
        fvals = np.array([decode_float(fi, int(i)).fval for i in codes])
        enc_codes = encode_ndarray(fi, fvals)
        expected_codes: npt.NDArray
        if fi.num_nans == 0:
            assert not np.any(np.isnan(fvals))
            expected_codes = codes
        else:
            expected_codes = np.where(np.isnan(fvals), fi.code_of_nan, codes)
>       np.testing.assert_equal(enc_codes, expected_codes)
E       AssertionError: 
E       Arrays are not equal
E       
E       Mismatched elements: 29398 / 58825 (50%)
E       First 5 mismatches are at indices:
E        [29413]: 204960135479523 (ACTUAL), 9223576996990255331 (DESIRED)
E        [29414]: 518548582662410 (ACTUAL), 9223890585437438218 (DESIRED)
E        [29415]: 832137029845297 (ACTUAL), 9224204173884621105 (DESIRED)
E        [29416]: 1145725477028184 (ACTUAL), 9224517762331803992 (DESIRED)
E        [29417]: 1459313924211071 (ACTUAL), 9224831350778986879 (DESIRED)
E       Max absolute difference among violations: 9223372036854775808
E       Max relative difference among violations: 0.99997778
E        ACTUAL: array([                   0,      313588447182887,      627176894365774,
E              ..., 18446744073709551615, 18446744073709551615,
E              18446744073709551615], shape=(58825,), dtype=uint64)
E        DESIRED: array([                   0,      313588447182887,      627176894365774,
E              ..., 18446744073709551615, 18446744073709551615,
E              18446744073709551615], shape=(58825,), dtype=uint64)

test/test_encode.py:42: AssertionError
____ test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.Stochastic] ____

rnd = <RoundMode.Stochastic: 6>, srnumbits = 32, sat = True

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
__ test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticOdd] ___

rnd = <RoundMode.StochasticOdd: 7>, srnumbits = 32, sat = True

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
__ test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticFast] __

rnd = <RoundMode.StochasticFast: 8>, srnumbits = 32, sat = True

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
_ test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticFastest] _

rnd = <RoundMode.StochasticFastest: 9>, srnumbits = 32, sat = True

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
___ test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.Stochastic] ____

rnd = <RoundMode.Stochastic: 6>, srnumbits = 32, sat = False

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
__ test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticOdd] __

rnd = <RoundMode.StochasticOdd: 7>, srnumbits = 32, sat = False

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
_ test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticFast] __

rnd = <RoundMode.StochasticFast: 8>, srnumbits = 32, sat = False

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
_ test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticFastest] _

rnd = <RoundMode.StochasticFastest: 9>, srnumbits = 32, sat = False

    @pytest.mark.parametrize(
        "rnd",
        (
            RoundMode.Stochastic,
            RoundMode.StochasticOdd,
            RoundMode.StochasticFast,
            RoundMode.StochasticFastest,
        ),
    )
    @pytest.mark.parametrize("srnumbits", [3, 8, 9, 16, 32])
    @pytest.mark.parametrize("sat", (True, False))
    def test_stochastic_rounding_scalar_eq_array(
        rnd: RoundMode, srnumbits: int, sat: bool
    ) -> None:
        fi = format_info_ocp_e5m2
    
        v0 = decode_ndarray(fi, np.arange(255))
        v1 = decode_ndarray(fi, np.arange(255) + 1)
        ok = np.isfinite(v0) & np.isfinite(v1)
        v0 = v0[ok]
        v1 = v1[ok]
    
        for alpha in (0, 0.3, 0.5, 0.6, 0.7, 0.9, 1.25):
            v = _linterp(v0, v1, alpha)
            assert np.isfinite(v).all()
>           srbits = np.random.randint(0, 2**srnumbits, v.shape)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

test/test_round.py:594: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
numpy/random/mtrand.pyx:799: in numpy.random.mtrand.RandomState.randint
    ???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   ValueError: high is out of bounds for int32

numpy/random/_bounded_integers.pyx:1423: ValueError
=============================== warnings summary ===============================
test/test_round.py: 27520 warnings
  /tmp/gfloat/src/gfloat/round.py:23: DeprecationWarning: Bitwise inversion '~' on bool is deprecated and will be removed in Python 3.16. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
    should_round_away = (x > floored + 0.5) | ((x == floored + 0.5) & ~pred(floored))

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED test/test_encode.py::test_encode[binary32] - AssertionError: 
FAILED test/test_encode.py::test_encode[binary64] - AssertionError: 
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.Stochastic]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticOdd]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticFast]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[True-32-RoundMode.StochasticFastest]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.Stochastic]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticOdd]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticFast]
FAILED test/test_round.py::test_stochastic_rounding_scalar_eq_array[False-32-RoundMode.StochasticFastest]
================ 10 failed, 32 passed, 27520 warnings in 32.12s ================

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No 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