diff --git a/dpnp/dpnp_algo/dpnp_algo.pxd b/dpnp/dpnp_algo/dpnp_algo.pxd index 3142f33e0d7..423076bc9c5 100644 --- a/dpnp/dpnp_algo/dpnp_algo.pxd +++ b/dpnp/dpnp_algo/dpnp_algo.pxd @@ -120,7 +120,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_EIG_EXT DPNP_FN_EIGVALS DPNP_FN_EIGVALS_EXT - DPNP_FN_EQUAL_EXT DPNP_FN_ERF DPNP_FN_ERF_EXT DPNP_FN_EYE @@ -149,8 +148,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_FMOD_EXT DPNP_FN_FULL DPNP_FN_FULL_LIKE - DPNP_FN_GREATER_EXT - DPNP_FN_GREATER_EQUAL_EXT DPNP_FN_HYPOT DPNP_FN_HYPOT_EXT DPNP_FN_IDENTITY @@ -165,8 +162,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_KRON_EXT DPNP_FN_LEFT_SHIFT DPNP_FN_LEFT_SHIFT_EXT - DPNP_FN_LESS_EXT - DPNP_FN_LESS_EQUAL_EXT DPNP_FN_LOG DPNP_FN_LOG_EXT DPNP_FN_LOG10 @@ -200,7 +195,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_NEGATIVE DPNP_FN_NEGATIVE_EXT DPNP_FN_NONZERO - DPNP_FN_NOT_EQUAL_EXT DPNP_FN_ONES DPNP_FN_ONES_LIKE DPNP_FN_PARTITION @@ -481,18 +475,12 @@ cpdef dpnp_descriptor dpnp_right_shift(dpnp_descriptor x1_obj, """ Logic functions """ -cpdef dpnp_descriptor dpnp_equal(dpnp_descriptor array1, dpnp_descriptor input2) -cpdef dpnp_descriptor dpnp_greater(dpnp_descriptor input1, dpnp_descriptor input2) -cpdef dpnp_descriptor dpnp_greater_equal(dpnp_descriptor input1, dpnp_descriptor input2) cpdef dpnp_descriptor dpnp_isclose(dpnp_descriptor input1, dpnp_descriptor input2, double rtol=*, double atol=*, cpp_bool equal_nan=*) -cpdef dpnp_descriptor dpnp_less(dpnp_descriptor input1, dpnp_descriptor input2) -cpdef dpnp_descriptor dpnp_less_equal(dpnp_descriptor input1, dpnp_descriptor input2) cpdef dpnp_descriptor dpnp_logical_and(dpnp_descriptor input1, dpnp_descriptor input2) cpdef dpnp_descriptor dpnp_logical_not(dpnp_descriptor input1) cpdef dpnp_descriptor dpnp_logical_or(dpnp_descriptor input1, dpnp_descriptor input2) cpdef dpnp_descriptor dpnp_logical_xor(dpnp_descriptor input1, dpnp_descriptor input2) -cpdef dpnp_descriptor dpnp_not_equal(dpnp_descriptor input1, dpnp_descriptor input2) """ diff --git a/dpnp/dpnp_algo/dpnp_algo_logic.pxi b/dpnp/dpnp_algo/dpnp_algo_logic.pxi index f84e90b186f..a45d3e0eb63 100644 --- a/dpnp/dpnp_algo/dpnp_algo_logic.pxi +++ b/dpnp/dpnp_algo/dpnp_algo_logic.pxi @@ -39,20 +39,14 @@ __all__ += [ "dpnp_all", "dpnp_allclose", "dpnp_any", - "dpnp_equal", - "dpnp_greater", - "dpnp_greater_equal", "dpnp_isclose", "dpnp_isfinite", "dpnp_isinf", "dpnp_isnan", - "dpnp_less", - "dpnp_less_equal", "dpnp_logical_and", "dpnp_logical_not", "dpnp_logical_or", "dpnp_logical_xor", - "dpnp_not_equal" ] @@ -167,30 +161,6 @@ cpdef utils.dpnp_descriptor dpnp_any(utils.dpnp_descriptor array1): return result -cpdef utils.dpnp_descriptor dpnp_equal(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_EQUAL_EXT, x1_obj, x2_obj, dtype, out, where, func_name="equal") - - -cpdef utils.dpnp_descriptor dpnp_greater(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_GREATER_EXT, x1_obj, x2_obj, dtype, out, where, func_name="greater") - - -cpdef utils.dpnp_descriptor dpnp_greater_equal(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_GREATER_EQUAL_EXT, x1_obj, x2_obj, dtype, out, where, func_name="greater_equal") - - cpdef utils.dpnp_descriptor dpnp_isclose(utils.dpnp_descriptor input1, utils.dpnp_descriptor input2, double rtol=1e-05, @@ -255,22 +225,6 @@ cpdef utils.dpnp_descriptor dpnp_isnan(utils.dpnp_descriptor input1): return result -cpdef utils.dpnp_descriptor dpnp_less(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_LESS_EXT, x1_obj, x2_obj, dtype, out, where, func_name="less") - - -cpdef utils.dpnp_descriptor dpnp_less_equal(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_LESS_EQUAL_EXT, x1_obj, x2_obj, dtype, out, where, func_name="less_equal") - - cpdef utils.dpnp_descriptor dpnp_logical_and(utils.dpnp_descriptor x1_obj, utils.dpnp_descriptor x2_obj, object dtype=None, @@ -300,11 +254,3 @@ cpdef utils.dpnp_descriptor dpnp_logical_xor(utils.dpnp_descriptor x1_obj, utils.dpnp_descriptor out=None, object where=True): return call_fptr_2in_1out_strides(DPNP_FN_LOGICAL_XOR_EXT, x1_obj, x2_obj, dtype, out, where, func_name="logical_xor") - - -cpdef utils.dpnp_descriptor dpnp_not_equal(utils.dpnp_descriptor x1_obj, - utils.dpnp_descriptor x2_obj, - object dtype=None, - utils.dpnp_descriptor out=None, - object where=True): - return call_fptr_2in_1out_strides(DPNP_FN_NOT_EQUAL_EXT, x1_obj, x2_obj, dtype, out, where, func_name="not_equal") diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index a4dd92cec74..61341c87090 100644 --- a/dpnp/dpnp_algo/dpnp_elementwise_common.py +++ b/dpnp/dpnp_algo/dpnp_elementwise_common.py @@ -36,11 +36,22 @@ import dpnp.backend.extensions.vm._vm_impl as vmi from dpnp.dpnp_array import dpnp_array -__all__ = ["dpnp_add", "dpnp_divide", "dpnp_multiply", "dpnp_subtract"] +__all__ = [ + "dpnp_add", + "dpnp_divide", + "dpnp_equal", + "dpnp_greater", + "dpnp_greater_equal", + "dpnp_less", + "dpnp_less_equal", + "dpnp_multiply", + "dpnp_not_equal", + "dpnp_subtract", +] _add_docstring_ = """ -add(x1, x2, out=None, order='K') +add(x1, x2, out=None, order="K") Calculates the sum for each element `x1_i` of the input array `x1` with the respective element `x2_i` of the input array `x2`. @@ -85,7 +96,7 @@ def dpnp_add(x1, x2, out=None, order="K"): _divide_docstring_ = """ -divide(x1, x2, out=None, order='K') +divide(x1, x2, out=None, order="K") Calculates the ratio for each element `x1_i` of the input array `x1` with the respective element `x2_i` of the input array `x2`. @@ -162,8 +173,209 @@ def _call_divide_inplace(lhs, rhs, sycl_queue, depends=None): return dpnp_array._create_from_usm_ndarray(res_usm) +_equal_docstring_ = """ + +equal(x1, x2, out=None, order="K") +Calculates equality results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + an array containing the result of element-wise equality comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_equal(x1, x2, out=None, order="K"): + """Invokes equal() from dpctl.tensor implementation for equal() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "equal", ti._equal_result_type, ti._equal, _equal_docstring_ + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + +_greater_docstring_ = """ +greater(x1, x2, out=None, order="K") + +Calculates the greater-than results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + an array containing the result of element-wise greater-than comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_greater(x1, x2, out=None, order="K"): + """Invokes greater() from dpctl.tensor implementation for greater() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "greater", ti._greater_result_type, ti._greater, _greater_docstring_ + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + +_greater_equal_docstring_ = """ +greater_equal(x1, x2, out=None, order="K") + +Calculates the greater-than or equal-to results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + an array containing the result of element-wise greater-than or equal-to comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_greater_equal(x1, x2, out=None, order="K"): + """Invokes greater_equal() from dpctl.tensor implementation for greater_equal() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "greater_equal", + ti._greater_equal_result_type, + ti._greater_equal, + _greater_equal_docstring_, + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + +_less_docstring_ = """ +less(x1, x2, out=None, order="K") + +Calculates the less-than results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + an array containing the result of element-wise less-than comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_less(x1, x2, out=None, order="K"): + """Invokes less() from dpctl.tensor implementation for less() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "less", ti._less_result_type, ti._less, _less_docstring_ + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + +_less_equal_docstring_ = """ +less_equal(x1, x2, out=None, order="K") + +Calculates the less-than or equal-to results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + An array containing the result of element-wise less-than or equal-to comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_less_equal(x1, x2, out=None, order="K"): + """Invokes less_equal() from dpctl.tensor implementation for less_equal() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "less_equal", + ti._less_equal_result_type, + ti._less_equal, + _less_equal_docstring_, + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + _multiply_docstring_ = """ -multiply(x1, x2, out=None, order='K') +multiply(x1, x2, out=None, order="K") Calculates the product for each element `x1_i` of the input array `x1` with the respective element `x2_i` of the input array `x2`. @@ -211,8 +423,50 @@ def dpnp_multiply(x1, x2, out=None, order="K"): return dpnp_array._create_from_usm_ndarray(res_usm) +_not_equal_docstring_ = """ +not_equal(x1, x2, out=None, order="K") + +Calculates inequality results for each element `x1_i` of +the input array `x1` the respective element `x2_i` of the input array `x2`. + +Args: + x1 (dpnp.ndarray): + First input array, expected to have numeric data type. + x2 (dpnp.ndarray): + Second input array, also 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", None, optional): + Memory layout of the newly output array, if parameter `out` is `None`. + Default: "K". +Returns: + dpnp.ndarray: + an array containing the result of element-wise inequality comparison. + The data type of the returned array is determined by the Type Promotion Rules. +""" + + +def dpnp_not_equal(x1, x2, out=None, order="K"): + """Invokes not_equal() from dpctl.tensor implementation for not_equal() function.""" + + # dpctl.tensor only works with usm_ndarray or scalar + x1_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x1) + x2_usm_or_scalar = dpnp.get_usm_ndarray_or_scalar(x2) + out_usm = None if out is None else dpnp.get_usm_ndarray(out) + + func = BinaryElementwiseFunc( + "not_equal", + ti._not_equal_result_type, + ti._not_equal, + _not_equal_docstring_, + ) + res_usm = func(x1_usm_or_scalar, x2_usm_or_scalar, out=out_usm, order=order) + return dpnp_array._create_from_usm_ndarray(res_usm) + + _subtract_docstring_ = """ -subtract(x1, x2, out=None, order='K') +subtract(x1, x2, out=None, order="K") Calculates the difference bewteen each element `x1_i` of the input array `x1` and the respective element `x2_i` of the input array `x2`. diff --git a/dpnp/dpnp_iface_logic.py b/dpnp/dpnp_iface_logic.py index 658459bd303..45c521596c2 100644 --- a/dpnp/dpnp_iface_logic.py +++ b/dpnp/dpnp_iface_logic.py @@ -46,6 +46,16 @@ from dpnp.dpnp_algo import * from dpnp.dpnp_utils import * +from .dpnp_algo.dpnp_elementwise_common import ( + dpnp_equal, + dpnp_greater, + dpnp_greater_equal, + dpnp_less, + dpnp_less_equal, + dpnp_not_equal, +) +from .dpnp_iface_mathematical import _check_nd_call + __all__ = [ "all", "allclose", @@ -223,7 +233,18 @@ def any(x1, /, axis=None, out=None, keepdims=False, *, where=True): ) -def equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def equal( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 == x2) element-wise. @@ -238,10 +259,9 @@ def equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -256,54 +276,37 @@ def equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): >>> import dpnp as np >>> x1 = np.array([0, 1, 3]) >>> x2 = np.arange(3) - >>> out = np.equal(x1, x2) - >>> [i for i in out] - [True, True, False] + >>> np.equal(x1, x2) + array([ True, True, False]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_equal(x1_desc, x2_desc).get_pyobj() - - return call_origin( - numpy.equal, x1, x2, out=out, where=where, dtype=dtype, subok=subok + return _check_nd_call( + numpy.equal, + dpnp_equal, + x1, + x2, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) -def greater(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def greater( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 > x2) element-wise. @@ -318,10 +321,9 @@ def greater(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -336,54 +338,36 @@ def greater(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): >>> import dpnp as np >>> x1 = np.array([4, 2]) >>> x2 = np.array([2, 2]) - >>> out = np.greater(x1, x2) - >>> [i for i in out] - [True, False] - + >>> np.greater(x1, x2) + array([ True, False]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_greater(x1_desc, x2_desc).get_pyobj() - - return call_origin( - numpy.greater, x1, x2, out=out, where=where, dtype=dtype, subok=subok + return _check_nd_call( + numpy.greater, + dpnp_greater, + x1, + x2, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) -def greater_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def greater_equal( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 >= x2) element-wise. @@ -398,10 +382,9 @@ def greater_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -416,56 +399,22 @@ def greater_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): >>> import dpnp as np >>> x1 = np.array([4, 2, 1]) >>> x2 = np.array([2, 2, 2]) - >>> out = np.greater_equal(x1, x2) - >>> [i for i in out] - [True, True, False] + >>> np.greater_equal(x1, x2) + array([ True, True, False]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_greater_equal(x1_desc, x2_desc).get_pyobj() - - return call_origin( + return _check_nd_call( numpy.greater_equal, + dpnp_greater_equal, x1, x2, out=out, where=where, + order=order, dtype=dtype, subok=subok, + **kwargs, ) @@ -646,7 +595,18 @@ def isnan(x1, out=None, **kwargs): return call_origin(numpy.isnan, x1, out, **kwargs) -def less(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def less( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 < x2) element-wise. @@ -661,10 +621,9 @@ def less(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -679,54 +638,37 @@ def less(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): >>> import dpnp as np >>> x1 = np.array([1, 2]) >>> x2 = np.array([2, 2]) - >>> out = np.less(x1, x2) - >>> [i for i in out] - [True, False] + >>> np.less(x1, x2) + array([ True, False]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_less(x1_desc, x2_desc).get_pyobj() - - return call_origin( - numpy.less, x1, x2, out=out, where=where, dtype=dtype, subok=subok + return _check_nd_call( + numpy.less, + dpnp_less, + x1, + x2, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) -def less_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def less_equal( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 <= x2) element-wise. @@ -741,10 +683,9 @@ def less_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -758,51 +699,23 @@ def less_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): -------- >>> import dpnp as np >>> x1 = np.array([4, 2, 1]) - >>> x2 = np.array([2, 2, 2]) - >>> out = np.less_equal(x1, x2) - >>> [i for i in out] - [False, True, True] + >>> x2 = np.array([2, 2, 2] + >>> np.less_equal(x1, x2) + array([False, True, True]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_less_equal(x1_desc, x2_desc).get_pyobj() - - return call_origin( - numpy.less_equal, x1, x2, out=out, where=where, dtype=dtype, subok=subok + return _check_nd_call( + numpy.less_equal, + dpnp_less_equal, + x1, + x2, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) @@ -1111,7 +1024,18 @@ def logical_xor(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ) -def not_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): +def not_equal( + x1, + x2, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the truth value of (x1 != x2) element-wise. @@ -1126,10 +1050,9 @@ def not_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): ----------- Parameters `x1` and `x2` are supported as either scalar, :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`, but both `x1` and `x2` can not be scalars at the same time. - Parameters `out`, `where`, `dtype` and `subok` are supported with their default values. + Parameters `where`, `dtype` and `subok` are supported with their default values. Otherwise the function will be executed sequentially on CPU. - Input array data types are limited by supported DPNP :ref:`Data types`, - excluding `dpnp.complex64` and `dpnp.complex128`. + Input array data types are limited by supported DPNP :ref:`Data types`. See Also -------- @@ -1144,48 +1067,20 @@ def not_equal(x1, x2, /, out=None, *, where=True, dtype=None, subok=True): >>> import dpnp as np >>> x1 = np.array([1., 2.]) >>> x2 = np.arange(1., 3.) - >>> out = np.not_equal(x1, x2) - >>> [i for i in out] - [False, False] + >>> np.not_equal(x1, x2) + array([False, False]) """ - if out is not None: - pass - elif where is not True: - pass - elif dtype is not None: - pass - elif subok is not True: - pass - elif dpnp.isscalar(x1) and dpnp.isscalar(x2): - # at least either x1 or x2 has to be an array - pass - else: - # get USM type and queue to copy scalar from the host memory into a USM allocation - usm_type, queue = ( - get_usm_allocations([x1, x2]) - if dpnp.isscalar(x1) or dpnp.isscalar(x2) - else (None, None) - ) - - x1_desc = dpnp.get_dpnp_descriptor( - x1, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - x2_desc = dpnp.get_dpnp_descriptor( - x2, - copy_when_strides=False, - copy_when_nondefault_queue=False, - alloc_usm_type=usm_type, - alloc_queue=queue, - ) - if x1_desc and x2_desc: - return dpnp_not_equal(x1_desc, x2_desc).get_pyobj() - - return call_origin( - numpy.not_equal, x1, x2, out=out, where=where, dtype=dtype, subok=subok + return _check_nd_call( + numpy.not_equal, + dpnp_not_equal, + x1, + x2, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) diff --git a/dpnp/random/dpnp_algo_random.pyx b/dpnp/random/dpnp_algo_random.pyx index 7c6eaae16ff..b46b4827f7e 100644 --- a/dpnp/random/dpnp_algo_random.pyx +++ b/dpnp/random/dpnp_algo_random.pyx @@ -458,7 +458,13 @@ cdef class MT19937(_Engine): MT19937_Delete(&self.mt19937) cdef bint is_uint_range(self, value): - return value >= 0 and value <= numpy.iinfo(numpy.uint32).max + if value < 0: + return False + + max_val = numpy.iinfo(numpy.uint32).max + if isinstance(value, dpnp_array): + max_val = dpnp.array(max_val, dtype=numpy.uint32) + return value <= max_val cdef class MCG59(_Engine): @@ -489,7 +495,13 @@ cdef class MCG59(_Engine): MCG59_Delete(&self.mcg59) cdef bint is_uint64_range(self, value): - return value >= 0 and value <= numpy.iinfo(numpy.uint64).max + if value < 0: + return False + + max_val = numpy.iinfo(numpy.uint64).max + if isinstance(value, dpnp_array): + max_val = dpnp.array(max_val, dtype=numpy.uint64) + return value <= max_val cpdef utils.dpnp_descriptor dpnp_rng_beta(double a, double b, size): diff --git a/tests/test_random_state.py b/tests/test_random_state.py index 5b3c937ac18..f6be26202fb 100644 --- a/tests/test_random_state.py +++ b/tests/test_random_state.py @@ -12,6 +12,7 @@ ) import dpnp +from dpnp.dpnp_array import dpnp_array from dpnp.random import RandomState from .helper import is_cpu_device @@ -547,6 +548,9 @@ def test_zero_size(self, zero_size): ids=["[2]", "dpnp.array([2])", "numpy.array([2])"], ) def test_bounds_fallback(self, low, high): + if isinstance(high, dpnp_array) and high.dtype == numpy.int32: + pytest.skip("NumPy fails: 'high' is out of bounds for int32") + seed = 15 size = (3, 2, 5)