Skip to content

Test operator special cases #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions array_api_tests/special_cases/test_dunder_abs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
Special cases tests for __abs__.

These tests are generated from the special cases listed in the spec.

NOTE: This file is generated automatically by the generate_stubs.py script. Do
not modify it directly.
"""

from ..array_helpers import NaN, assert_exactly_equal, exactly_equal, infinity, zero
from ..hypothesis_helpers import numeric_arrays

from hypothesis import given


@given(numeric_arrays)
def test_abs_special_cases_one_arg_equal_1(arg1):
"""
Special case test for `__abs__(self, /)`:

- If `x_i` is `NaN`, the result is `NaN`.

"""
res = (arg1).__abs__()
mask = exactly_equal(arg1, NaN(arg1.shape, arg1.dtype))
assert_exactly_equal(res[mask], (NaN(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays)
def test_abs_special_cases_one_arg_equal_2(arg1):
"""
Special case test for `__abs__(self, /)`:

- If `x_i` is `-0`, the result is `+0`.

"""
res = (arg1).__abs__()
mask = exactly_equal(arg1, -zero(arg1.shape, arg1.dtype))
assert_exactly_equal(res[mask], (zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays)
def test_abs_special_cases_one_arg_equal_3(arg1):
"""
Special case test for `__abs__(self, /)`:

- If `x_i` is `-infinity`, the result is `+infinity`.

"""
res = (arg1).__abs__()
mask = exactly_equal(arg1, -infinity(arg1.shape, arg1.dtype))
assert_exactly_equal(res[mask], (infinity(arg1.shape, arg1.dtype))[mask])
225 changes: 225 additions & 0 deletions array_api_tests/special_cases/test_dunder_add.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
"""
Special cases tests for __add__.

These tests are generated from the special cases listed in the spec.

NOTE: This file is generated automatically by the generate_stubs.py script. Do
not modify it directly.
"""

from ..array_helpers import (NaN, assert_exactly_equal, exactly_equal, infinity, isfinite,
logical_and, logical_or, non_zero, zero)
from ..hypothesis_helpers import numeric_arrays

from hypothesis import given


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_either(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If either `x1_i` or `x2_i` is `NaN`, the result is `NaN`.

"""
res = arg1.__add__(arg2)
mask = logical_or(exactly_equal(arg1, NaN(arg1.shape, arg1.dtype)), exactly_equal(arg2, NaN(arg1.shape, arg1.dtype)))
assert_exactly_equal(res[mask], (NaN(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_1(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `+infinity` and `x2_i` is `-infinity`, the result is `NaN`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, infinity(arg1.shape, arg1.dtype)), exactly_equal(arg2, -infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (NaN(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_2(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `-infinity` and `x2_i` is `+infinity`, the result is `NaN`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, -infinity(arg1.shape, arg1.dtype)), exactly_equal(arg2, infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (NaN(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_3(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `+infinity` and `x2_i` is `+infinity`, the result is `+infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, infinity(arg1.shape, arg1.dtype)), exactly_equal(arg2, infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_4(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `-infinity` and `x2_i` is `-infinity`, the result is `-infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, -infinity(arg1.shape, arg1.dtype)), exactly_equal(arg2, -infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (-infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_5(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `+infinity` and `x2_i` is a finite number, the result is `+infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, infinity(arg1.shape, arg1.dtype)), isfinite(arg2))
assert_exactly_equal(res[mask], (infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_6(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `-infinity` and `x2_i` is a finite number, the result is `-infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, -infinity(arg1.shape, arg1.dtype)), isfinite(arg2))
assert_exactly_equal(res[mask], (-infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_7(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is a finite number and `x2_i` is `+infinity`, the result is `+infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(isfinite(arg1), exactly_equal(arg2, infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_8(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is a finite number and `x2_i` is `-infinity`, the result is `-infinity`.

"""
res = arg1.__add__(arg2)
mask = logical_and(isfinite(arg1), exactly_equal(arg2, -infinity(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (-infinity(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_9(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `-0` and `x2_i` is `-0`, the result is `-0`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, -zero(arg1.shape, arg1.dtype)), exactly_equal(arg2, -zero(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (-zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_10(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `-0` and `x2_i` is `+0`, the result is `+0`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, -zero(arg1.shape, arg1.dtype)), exactly_equal(arg2, zero(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_11(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `+0` and `x2_i` is `-0`, the result is `+0`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, zero(arg1.shape, arg1.dtype)), exactly_equal(arg2, -zero(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_12(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is `+0` and `x2_i` is `+0`, the result is `+0`.

"""
res = arg1.__add__(arg2)
mask = logical_and(exactly_equal(arg1, zero(arg1.shape, arg1.dtype)), exactly_equal(arg2, zero(arg2.shape, arg2.dtype)))
assert_exactly_equal(res[mask], (zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__equal_13(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is a nonzero finite number and `x2_i` is `-x1_i`, the result is `+0`.

"""
res = arg1.__add__(arg2)
mask = logical_and(logical_and(isfinite(arg1), non_zero(arg1)), exactly_equal(arg2, -arg1))
assert_exactly_equal(res[mask], (zero(arg1.shape, arg1.dtype))[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_either__equal(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is either `+0` or `-0` and `x2_i` is a nonzero finite number, the result is `x2_i`.

"""
res = arg1.__add__(arg2)
mask = logical_and(logical_or(exactly_equal(arg1, zero(arg1.shape, arg1.dtype)), exactly_equal(arg1, -zero(arg1.shape, arg1.dtype))), logical_and(isfinite(arg2), non_zero(arg2)))
assert_exactly_equal(res[mask], (arg2)[mask])


@given(numeric_arrays, numeric_arrays)
def test_add_special_cases_two_args_equal__either(arg1, arg2):
"""
Special case test for `__add__(self, other, /)`:

- If `x1_i` is a nonzero finite number and `x2_i` is either `+0` or `-0`, the result is `x1_i`.

"""
res = arg1.__add__(arg2)
mask = logical_and(logical_and(isfinite(arg1), non_zero(arg1)), logical_or(exactly_equal(arg2, zero(arg2.shape, arg2.dtype)), exactly_equal(arg2, -zero(arg2.shape, arg2.dtype))))
assert_exactly_equal(res[mask], (arg1)[mask])

# TODO: Implement REMAINING test for:
# - In the remaining cases, when neither `infinity`, `+0`, `-0`, nor a `NaN` is involved, and the operands have the same mathematical sign or have different magnitudes, the sum must be computed and rounded to the nearest representable value according to IEEE 754-2019 and a supported round mode. If the magnitude is too large to represent, the operation overflows and the result is an `infinity` of appropriate mathematical sign.
Loading