Skip to content
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

implement dpnp.signbit and dpnp.proj #1535

Merged
merged 3 commits into from
Aug 27, 2023
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
1 change: 1 addition & 0 deletions doc/reference/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ Handling complex numbers
dpnp.imag
dpnp.conj
dpnp.conjugate
dpnp.proj


Extrema Finding
Expand Down
1 change: 1 addition & 0 deletions doc/reference/ufunc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Math operations
dpnp.log10
dpnp.expm1
dpnp.log1p
dpnp.proj
dpnp.sqrt
dpnp.square
dpnp.reciprocal
Expand Down
79 changes: 79 additions & 0 deletions dpnp/dpnp_algo/dpnp_elementwise_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,14 @@
"dpnp_logical_or",
"dpnp_logical_xor",
"dpnp_multiply",
"dpnp_negative",
"dpnp_not_equal",
"dpnp_proj",
"dpnp_remainder",
"dpnp_right_shift",
"dpnp_round",
"dpnp_sign",
"dpnp_signbit",
"dpnp_sin",
"dpnp_sqrt",
"dpnp_square",
Expand Down Expand Up @@ -1456,6 +1460,43 @@ def dpnp_not_equal(x1, x2, out=None, order="K"):
return dpnp_array._create_from_usm_ndarray(res_usm)


_proj_docstring = """
proj(x, out=None, order="K")

Computes projection of each element `x_i` for input array `x`.

Args:
x (dpnp.ndarray):
Input array, expected to have numeric data type.
out ({None, dpnp.ndarray}, optional):
Output array to populate.
Array have the correct shape and the expected data type.
order ("C","F","A","K", optional):
Memory layout of the newly output array, if parameter `out` is `None`.
Default: "K".
Returns:
dpnp.ndarray:
An array containing the element-wise projection.
The returned array has the same data type as `x`.
"""


proj_func = UnaryElementwiseFunc(
"proj", ti._proj_result_type, ti._proj, _proj_docstring
)


def dpnp_proj(x, out=None, order="K"):
"""Invokes proj() from dpctl.tensor implementation for proj() function."""

# dpctl.tensor only works with usm_ndarray
x1_usm = dpnp.get_usm_ndarray(x)
out_usm = None if out is None else dpnp.get_usm_ndarray(out)

res_usm = proj_func(x1_usm, out=out_usm, order=order)
return dpnp_array._create_from_usm_ndarray(res_usm)


_remainder_docstring_ = """
remainder(x1, x2, out=None, order='K')
Calculates the remainder of division for each element `x1_i` of the input array
Expand Down Expand Up @@ -1642,6 +1683,44 @@ def dpnp_sign(x, out=None, order="K"):
return dpnp_array._create_from_usm_ndarray(res_usm)


_signbit_docstring = """
signbit(x, out=None, order="K")

Computes an indication of whether the sign bit of each element `x_i` of
input array `x` is set.

Args:
x (dpnp.ndarray):
Input array, expected to have numeric data type.
out ({None, dpnp.ndarray}, optional):
Output array to populate.
Array have the correct shape and the expected data type.
order ("C","F","A","K", optional):
Memory layout of the newly output array, if parameter `out` is `None`.
Default: "K".
Returns:
dpnp.ndarray:
An array containing the element-wise results. The returned array
must have a data type of `bool`.
"""


signbit_func = UnaryElementwiseFunc(
"signbit", ti._signbit_result_type, ti._signbit, _signbit_docstring
)


def dpnp_signbit(x, out=None, order="K"):
"""Invokes signbit() from dpctl.tensor implementation for signbit() function."""

# dpctl.tensor only works with usm_ndarray
x1_usm = dpnp.get_usm_ndarray(x)
out_usm = None if out is None else dpnp.get_usm_ndarray(out)

res_usm = signbit_func(x1_usm, out=out_usm, order=order)
return dpnp_array._create_from_usm_ndarray(res_usm)


_sin_docstring = """
sin(x, out=None, order='K')
Computes sine for each element `x_i` of input array `x`.
Expand Down
124 changes: 124 additions & 0 deletions dpnp/dpnp_iface_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@
dpnp_floor_divide,
dpnp_multiply,
dpnp_negative,
dpnp_proj,
dpnp_remainder,
dpnp_round,
dpnp_sign,
dpnp_signbit,
dpnp_subtract,
dpnp_trunc,
)
Expand Down Expand Up @@ -101,10 +103,12 @@
"negative",
"power",
"prod",
"proj",
"remainder",
"rint",
"round",
"sign",
"signbit",
"subtract",
"sum",
"trapz",
Expand Down Expand Up @@ -1562,6 +1566,65 @@ def negative(
)


def proj(
vtavana marked this conversation as resolved.
Show resolved Hide resolved
x,
/,
out=None,
*,
order="K",
where=True,
dtype=None,
subok=True,
**kwargs,
):
"""
Returns the projection of a number onto the Riemann sphere.

For all infinite complex numbers (including the cases where one component is infinite and the other is `NaN`),
the function returns `(inf, 0.0)` or `(inf, -0.0)`.
For finite complex numbers, the input is returned.
All real-valued numbers are treated as complex numbers with positive zero imaginary part.

Returns
-------
out : dpnp.ndarray
The projection of each element of `x`.

Limitations
-----------
Parameters `x` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`.
Parameters `where`, `dtype` and `subok` are supported with their default values.
Keyword arguments `kwargs` are currently unsupported.
Input array data types are limited by supported DPNP :ref:`Data types`.

See Also
--------
:obj:`dpnp.abs` : Returns the magnitude of a complex number, element-wise.
vtavana marked this conversation as resolved.
Show resolved Hide resolved
:obj:`dpnp.conj` : Return the complex conjugate, element-wise.

Examples
--------
>>> import dpnp as np
>>> np.proj(np.array([1, -2.3, 2.1-1.7j]))
array([ 1. +0.j, -2.3+0.j, 2.1-1.7.j])

>>> np.proj(np.array([complex(1,np.inf), complex(1,-np.inf), complex(np.inf,-1),]))
array([inf+0.j, inf-0.j, inf-0.j])
"""

return check_nd_call_func(
None,
dpnp_proj,
x,
out=out,
where=where,
order=order,
dtype=dtype,
subok=subok,
**kwargs,
)


def power(x1, x2, /, out=None, *, where=True, dtype=None, subok=True, **kwargs):
"""
First array elements raised to powers from second array, element-wise.
Expand Down Expand Up @@ -1931,6 +1994,10 @@ def sign(
Input array data types are limited by supported DPNP :ref:`Data types`.
However, if the input array data type is complex, the function will be executed sequentially on CPU.

See Also
--------
:obj:`dpnp.signbit` : Returns element-wise `True` where signbit is set (less than zero).

Examples
--------
>>> import dpnp as np
Expand Down Expand Up @@ -1968,6 +2035,63 @@ def sign(
)


def signbit(
x,
/,
out=None,
*,
order="K",
where=True,
dtype=None,
subok=True,
**kwargs,
):
"""
Returns element-wise `True` where signbit is set (less than zero).

For full documentation refer to :obj:`numpy.signbit`.

Returns
-------
out : dpnp.ndarray
A boolean array with indication of the sign of each element of `x`.

Limitations
-----------
Parameters `x` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`.
Parameters `where`, `dtype` and `subok` are supported with their default values.
Keyword argument `kwargs` is currently unsupported.
Otherwise the function will be executed sequentially on CPU.
Input array data types are limited by supported real-valued data types.

See Also
--------
:obj:`dpnp.sign` : Returns an element-wise indication of the sign of a number.

Examples
--------
>>> import dpnp as np
>>> np.signbit(np.array([-1.2]))
array([True])

>>> np.signbit(np.array([1, -2.3, 2.1]))
array([False, True, False])

"""

return check_nd_call_func(
numpy.signbit,
dpnp_signbit,
x,
out=out,
where=where,
order=order,
dtype=dtype,
subok=subok,
**kwargs,
)


def subtract(
x1,
x2,
Expand Down
3 changes: 0 additions & 3 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ tests/test_umath.py::test_umaths[('positive', 'i')]
tests/test_umath.py::test_umaths[('positive', 'l')]
tests/test_umath.py::test_umaths[('positive', 'f')]
tests/test_umath.py::test_umaths[('positive', 'd')]
tests/test_umath.py::test_umaths[('signbit', 'f')]
tests/test_umath.py::test_umaths[('signbit', 'd')]
tests/test_umath.py::test_umaths[('spacing', 'f')]
tests/test_umath.py::test_umaths[('spacing', 'd')]

Expand Down Expand Up @@ -517,7 +515,6 @@ tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_frexp
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_ldexp
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_nextafter_combination
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_nextafter_float
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_signbit

tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_clip_min_max_none
tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_external_clip4
Expand Down
3 changes: 0 additions & 3 deletions tests/skipped_tests_gpu.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ tests/test_umath.py::test_umaths[('positive', 'i')]
tests/test_umath.py::test_umaths[('positive', 'l')]
tests/test_umath.py::test_umaths[('positive', 'f')]
tests/test_umath.py::test_umaths[('positive', 'd')]
tests/test_umath.py::test_umaths[('signbit', 'f')]
tests/test_umath.py::test_umaths[('signbit', 'd')]
tests/test_umath.py::test_umaths[('spacing', 'f')]
tests/test_umath.py::test_umaths[('spacing', 'd')]

Expand Down Expand Up @@ -659,7 +657,6 @@ tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_frexp
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_ldexp
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_nextafter_combination
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_nextafter_float
tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_signbit

tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_clip_min_max_none
tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_external_clip4
Expand Down
43 changes: 43 additions & 0 deletions tests/test_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from .helper import (
get_all_dtypes,
get_complex_dtypes,
get_float_complex_dtypes,
get_float_dtypes,
has_support_aspect64,
Expand Down Expand Up @@ -442,6 +443,48 @@ def test_sign_boolean():
dpnp.sign(dpnp_a)


@pytest.mark.parametrize(
"data",
[[2, 0, -2], [1.1, -1.1]],
ids=["[2, 0, -2]", "[1.1, -1.1]"],
)
@pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True))
def test_signbit(data, dtype):
vtavana marked this conversation as resolved.
Show resolved Hide resolved
np_a = numpy.array(data, dtype=dtype)
dpnp_a = dpnp.array(data, dtype=dtype)

result = dpnp.signbit(dpnp_a)
expected = numpy.signbit(np_a)
assert_allclose(result, expected)


@pytest.mark.parametrize("dtype", get_complex_dtypes())
def test_projection_infinity(dtype):
X = [
complex(1, 2),
complex(dpnp.inf, -1),
complex(0, -dpnp.inf),
complex(-dpnp.inf, dpnp.nan),
]
Y = [
complex(1, 2),
complex(dpnp.inf, -0.0),
complex(dpnp.inf, -0.0),
complex(dpnp.inf, 0.0),
]

result = dpnp.proj(dpnp.array(X, dtype=dtype))
expected = dpnp.array(Y, dtype=dtype)
assert_allclose(result, expected)


@pytest.mark.parametrize("dtype", get_all_dtypes())
def test_projection(dtype):
result = dpnp.proj(dpnp.array(1, dtype=dtype))
expected = dpnp.array(complex(1, 0))
assert_allclose(result, expected)


@pytest.mark.parametrize("val_type", get_all_dtypes(no_none=True))
@pytest.mark.parametrize("data_type", get_all_dtypes())
@pytest.mark.parametrize("val", [1.5, 1, 5], ids=["1.5", "1", "5"])
Expand Down
Loading