From 8dae602f4343964a52a109c952055480e008834b Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Wed, 20 Dec 2023 13:00:35 -0600 Subject: [PATCH 1/9] implement dpnp.reciprocal and dpnp.angle --- dpnp/backend/include/dpnp_iface_fptr.hpp | 2 - dpnp/backend/kernels/dpnp_krnl_elemwise.cpp | 9 -- dpnp/dpnp_algo/dpnp_algo.pxd | 3 - dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi | 5 -- dpnp/dpnp_algo/dpnp_elementwise_common.py | 84 ++++++++++++++++++- dpnp/dpnp_iface_bitwise.py | 2 - dpnp/dpnp_iface_manipulation.py | 8 +- dpnp/dpnp_iface_mathematical.py | 66 ++++++++++++++- dpnp/dpnp_iface_nanfunctions.py | 22 ++--- dpnp/dpnp_iface_searching.py | 8 +- dpnp/dpnp_iface_statistics.py | 14 ++-- dpnp/dpnp_iface_trigonometric.py | 55 ++++++++---- tests/skipped_tests.tbl | 4 - tests/skipped_tests_gpu.tbl | 3 - tests/test_mathematical.py | 41 +++++++++ tests/test_strides.py | 35 +++++--- tests/test_sycl_queue.py | 2 + tests/test_umath.py | 45 ++++++++-- tests/test_usm_type.py | 2 + .../core_tests/test_ndarray_complex_ops.py | 6 +- .../cupy/math_tests/test_arithmetic.py | 65 ++++++++++++-- .../cupy/sorting_tests/test_search.py | 6 +- .../cupy/statistics_tests/test_order.py | 1 - 23 files changed, 382 insertions(+), 106 deletions(-) diff --git a/dpnp/backend/include/dpnp_iface_fptr.hpp b/dpnp/backend/include/dpnp_iface_fptr.hpp index cc0cb9e32a1b..4a06f975c3d2 100644 --- a/dpnp/backend/include/dpnp_iface_fptr.hpp +++ b/dpnp/backend/include/dpnp_iface_fptr.hpp @@ -233,8 +233,6 @@ enum class DPNPFuncName : size_t parameters */ DPNP_FN_REMAINDER, /**< Used in numpy.remainder() impl */ DPNP_FN_RECIP, /**< Used in numpy.recip() impl */ - DPNP_FN_RECIP_EXT, /**< Used in numpy.recip() impl, requires extra - parameters */ DPNP_FN_REPEAT, /**< Used in numpy.repeat() impl */ DPNP_FN_RIGHT_SHIFT, /**< Used in numpy.right_shift() impl */ DPNP_FN_RNG_BETA, /**< Used in numpy.random.beta() impl */ diff --git a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp index 58186ba482e5..b9c0de126eeb 100644 --- a/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_elemwise.cpp @@ -928,15 +928,6 @@ static void func_map_init_elemwise_1arg_1type(func_map_t &fmap) fmap[DPNPFuncName::DPNP_FN_RECIP][eft_DBL][eft_DBL] = { eft_DBL, (void *)dpnp_recip_c_default}; - fmap[DPNPFuncName::DPNP_FN_RECIP_EXT][eft_INT][eft_INT] = { - eft_INT, (void *)dpnp_recip_c_ext}; - fmap[DPNPFuncName::DPNP_FN_RECIP_EXT][eft_LNG][eft_LNG] = { - eft_LNG, (void *)dpnp_recip_c_ext}; - fmap[DPNPFuncName::DPNP_FN_RECIP_EXT][eft_FLT][eft_FLT] = { - eft_FLT, (void *)dpnp_recip_c_ext}; - fmap[DPNPFuncName::DPNP_FN_RECIP_EXT][eft_DBL][eft_DBL] = { - eft_DBL, (void *)dpnp_recip_c_ext}; - fmap[DPNPFuncName::DPNP_FN_SIGN][eft_INT][eft_INT] = { eft_INT, (void *)dpnp_sign_c_default}; fmap[DPNPFuncName::DPNP_FN_SIGN][eft_LNG][eft_LNG] = { diff --git a/dpnp/dpnp_algo/dpnp_algo.pxd b/dpnp/dpnp_algo/dpnp_algo.pxd index 4d59ffcf496d..3e9336a63555 100644 --- a/dpnp/dpnp_algo/dpnp_algo.pxd +++ b/dpnp/dpnp_algo/dpnp_algo.pxd @@ -106,8 +106,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_QR_EXT DPNP_FN_RADIANS DPNP_FN_RADIANS_EXT - DPNP_FN_RECIP - DPNP_FN_RECIP_EXT DPNP_FN_RNG_BETA DPNP_FN_RNG_BETA_EXT DPNP_FN_RNG_BINOMIAL @@ -324,4 +322,3 @@ Trigonometric functions """ cpdef dpnp_descriptor dpnp_degrees(dpnp_descriptor array1) cpdef dpnp_descriptor dpnp_radians(dpnp_descriptor array1) -cpdef dpnp_descriptor dpnp_recip(dpnp_descriptor array1) diff --git a/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi b/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi index 5904b62d11a6..14348d852dcf 100644 --- a/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi +++ b/dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi @@ -38,7 +38,6 @@ and the rest of the library __all__ += [ 'dpnp_degrees', 'dpnp_radians', - 'dpnp_recip', 'dpnp_unwrap' ] @@ -47,10 +46,6 @@ cpdef utils.dpnp_descriptor dpnp_degrees(utils.dpnp_descriptor x1): return call_fptr_1in_1out_strides(DPNP_FN_DEGREES_EXT, x1) -cpdef utils.dpnp_descriptor dpnp_recip(utils.dpnp_descriptor x1): - return call_fptr_1in_1out_strides(DPNP_FN_RECIP_EXT, x1) - - cpdef utils.dpnp_descriptor dpnp_radians(utils.dpnp_descriptor x1): return call_fptr_1in_1out_strides(DPNP_FN_RADIANS_EXT, x1) diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index a3ac7a8f0a6c..7d470424e1de 100644 --- a/dpnp/dpnp_algo/dpnp_elementwise_common.py +++ b/dpnp/dpnp_algo/dpnp_elementwise_common.py @@ -38,6 +38,7 @@ "dpnp_acos", "dpnp_acosh", "dpnp_add", + "dpnp_angle", "dpnp_asin", "dpnp_asinh", "dpnp_atan", @@ -88,6 +89,7 @@ "dpnp_power", "dpnp_proj", "dpnp_real", + "dpnp_reciprocal", "dpnp_remainder", "dpnp_right_shift", "dpnp_round", @@ -189,6 +191,7 @@ def _make_unary_func( ): impl_fn = dpt_unary_fn.get_implementation_function() type_resolver_fn = dpt_unary_fn.get_type_result_resolver_function() + acceptance_fn = dpt_unary_fn.get_type_promotion_path_acceptance_function() def _call_func(src, dst, sycl_queue, depends=None): """A callback to register in UnaryElementwiseFunc class of dpctl.tensor""" @@ -202,7 +205,7 @@ def _call_func(src, dst, sycl_queue, depends=None): return impl_fn(src, dst, sycl_queue, depends) func = dpt_unary_fn.__class__( - name, type_resolver_fn, _call_func, fn_docstring + name, type_resolver_fn, _call_func, fn_docstring, acceptance_fn ) return func @@ -411,6 +414,45 @@ def dpnp_add(x1, x2, out=None, order="K"): return _get_result(res_usm, out=out) +_angle_docstring = """ +angle(x, out=None, order="K") + +Computes the phase angle (also called the argument) of each element `x_i` for +input array `x`. + +Args: + x (dpnp.ndarray): + Input array, expected to have a complex-valued floating-point data type. + out ({None, dpnp.ndarray}, optional): + Output array to populate. + Array must 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 phase angles. + The returned array has a floating-point data type determined + by the Type Promotion Rules. +""" + +angle_func = _make_unary_func("angle", dpt.angle, _angle_docstring) + + +def dpnp_angle(x, out=None, order="K"): + """Invokes angle() from dpctl.tensor implementation for angle() 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 = angle_func(x1_usm, out=out_usm, order=order) + if out is None: + return dpnp_array._create_from_usm_ndarray(res_usm) + else: + return out + + _asin_docstring = """ asin(x, out=None, order='K') @@ -2459,6 +2501,46 @@ def dpnp_real(x, out=None, order="K"): return _get_result(res_usm, out=out) +_reciprocal_docstring = """ +reciprocal(x, out=None, order="K") + +Computes the reciprocal of each element `x_i` for input array `x`. + +Args: + x (dpnp.ndarray): + Input array, expected to have a real-valued floating-point data type. + out ({None, dpnp.ndarray}, optional): + Output array to populate. + Array must 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 reciprocals. + The returned array has a floating-point data type determined + by the Type Promotion Rules. +""" + +reciprocal_func = _make_unary_func( + "reciprocal", dpt.reciprocal, _reciprocal_docstring +) + + +def dpnp_reciprocal(x, out=None, order="K"): + """Invokes reciprocal() from dpctl.tensor implementation for reciprocal() 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 = reciprocal_func(x1_usm, out=out_usm, order=order) + if out is None: + return dpnp_array._create_from_usm_ndarray(res_usm) + else: + return out + + _remainder_docstring = """ remainder(x1, x2, out=None, order='K') diff --git a/dpnp/dpnp_iface_bitwise.py b/dpnp/dpnp_iface_bitwise.py index b4a25c4de336..1d7f3432e87a 100644 --- a/dpnp/dpnp_iface_bitwise.py +++ b/dpnp/dpnp_iface_bitwise.py @@ -1,5 +1,3 @@ -# cython: language_level=3 -# distutils: language = c++ # -*- coding: utf-8 -*- # ***************************************************************************** # Copyright (c) 2016-2024, Intel Corporation diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index 4d593a396523..ac83102c715a 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -1174,7 +1174,7 @@ def ravel(a, order="C"): Parameters ---------- - x : {dpnp_array, usm_ndarray} + x : {dpnp.array, usm_ndarray} Input array. The elements in `a` are read in the order specified by order, and packed as a 1-D array. order : {'C', 'F'}, optional @@ -1187,7 +1187,7 @@ def ravel(a, order="C"): Returns ------- - out : dpnp_array + out : dpnp.array A contiguous 1-D array of the same subtype as `a`, with shape (a.size,). See Also @@ -1220,7 +1220,7 @@ def repeat(a, repeats, axis=None): Parameters ---------- - x : {dpnp_array, usm_ndarray} + x : {dpnp.array, usm_ndarray} Input array. repeat : int or array of int The number of repetitions for each element. `repeats` is broadcasted to fit @@ -1231,7 +1231,7 @@ def repeat(a, repeats, axis=None): Returns ------- - out : dpnp_array + out : dpnp.array Output array which has the same shape as `a`, except along the given axis. See Also diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index add9c1304ce6..fc7047add6f8 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.py @@ -54,6 +54,7 @@ check_nd_call_func, dpnp_abs, dpnp_add, + dpnp_angle, dpnp_ceil, dpnp_conj, dpnp_copysign, @@ -82,6 +83,7 @@ "abs", "absolute", "add", + "angle", "around", "ceil", "clip", @@ -291,6 +293,62 @@ def add( ) +def angle(z, deg=False): + """ + Return the angle of the complex argument. + + For full documentation refer to :obj:`numpy.angle`. + + Parameters + ---------- + x : {dpnp.array, usm_ndarray} + Input array, expected to have a complex-valued floating-point data type. + deg : bool, optional + Return angle in degrees if True, radians if False (default). + + Returns + ------- + out : dpnp.ndarray + The counterclockwise angle from the positive real axis on + the complex plane in the range `(-pi, pi]`. + The returned array has a floating-point data type determined + by the Type Promotion Rules. + + Notes + ----- + Although the angle of the complex number 0 is undefined, `dpnp.angle(0)` returns the value 0. + + See Also + -------- + :obj:`dpnp.arctan2` : Element-wise arc tangent of `x1/x2` choosing the quadrant correctly. + :obj:`dpnp.absolute` : Calculate the absolute value element-wise. + + Examples + -------- + >>> import dpnp as np + >>> a = np.array([1.0, 1.0j, 1+1j]) + >>> np.angle(a) # in radians + array([0. , 1.57079633, 0.78539816]) # may vary + + >>> np.angle(a, deg=True) # in degrees + array([ 0., 90., 45.]) + + """ + + if not dpnp.isscalar(z): + dpnp.check_supported_arrays_type(z) + res = dpnp_angle(z) + if deg is True: + res = res * (180 / dpnp.pi) + return res + else: + return call_origin( + numpy.angle, + z, + deg=deg, + ) + + def around(x, /, decimals=0, out=None): """ Round an array to the given number of decimals. @@ -390,12 +448,12 @@ def clip(a, a_min, a_max, *, out=None, order="K", **kwargs): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Array containing elements to clip. - a_min, a_max : {dpnp_array, usm_ndarray, None} + a_min, a_max : {dpnp.array, usm_ndarray, None} Minimum and maximum value. If ``None``, clipping is not performed on the corresponding edge. Only one of `a_min` and `a_max` may be ``None``. Both are broadcast against `a`. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional The results will be placed in this array. It may be the input array for in-place clipping. `out` must be of the right shape to hold the output. Its type is preserved. order : {"C", "F", "A", "K", None}, optional @@ -404,7 +462,7 @@ def clip(a, a_min, a_max, *, out=None, order="K", **kwargs): Returns ------- - out : dpnp_array + out : dpnp.array An array with the elements of `a`, but where values < `a_min` are replaced with `a_min`, and those > `a_max` with `a_max`. diff --git a/dpnp/dpnp_iface_nanfunctions.py b/dpnp/dpnp_iface_nanfunctions.py index 18f4ff0e87dd..ff06a5d0eb63 100644 --- a/dpnp/dpnp_iface_nanfunctions.py +++ b/dpnp/dpnp_iface_nanfunctions.py @@ -72,14 +72,14 @@ def _replace_nan(a, val): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. val : float NaN values are set to `val` before doing the operation. Returns ------- - out : {dpnp_array} + out : {dpnp.array} If `a` is of inexact type, return a copy of `a` with the NaNs replaced by the fill value, otherwise return `a`. mask: {bool, None} @@ -110,13 +110,13 @@ def nanargmax(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the maximum value of the flattened array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -178,13 +178,13 @@ def nanargmin(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the minimum value of the flattened array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -320,14 +320,14 @@ def nanmax(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which maximum values must be computed. By default, the maximum value must be computed over the entire array. If a tuple of integers, maximum values must be computed over multiple axes. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -531,14 +531,14 @@ def nanmin(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which minimum values must be computed. By default, the minimum value must be computed over the entire array. If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional @@ -908,7 +908,7 @@ def nanvar( Parameters ---------- - a : {dpnp_array, usm_ndarray}: + a : {dpnp.array, usm_ndarray}: Input array. axis : int or tuple of ints, optional axis or axes along which the variances must be computed. If a tuple diff --git a/dpnp/dpnp_iface_searching.py b/dpnp/dpnp_iface_searching.py index 260dfab6e5be..05d41a04998f 100644 --- a/dpnp/dpnp_iface_searching.py +++ b/dpnp/dpnp_iface_searching.py @@ -57,13 +57,13 @@ def argmax(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the maximum value of the flattened array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -141,13 +141,13 @@ def argmin(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the minimum value of the flattened array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional diff --git a/dpnp/dpnp_iface_statistics.py b/dpnp/dpnp_iface_statistics.py index cf0423de2260..660a88b73e88 100644 --- a/dpnp/dpnp_iface_statistics.py +++ b/dpnp/dpnp_iface_statistics.py @@ -72,7 +72,7 @@ def _count_reduce_items(arr, axis, where=True): Parameters ---------- - arr : {dpnp_array, usm_ndarray} + arr : {dpnp.array, usm_ndarray} Input array. axis : int or tuple of ints, optional axis or axes along which the number of items used in a reduction operation must be counted. @@ -485,14 +485,14 @@ def max(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which maximum values must be computed. By default, the maximum value must be computed over the entire array. If a tuple of integers, maximum values must be computed over multiple axes. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -706,14 +706,14 @@ def min(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp_array, usm_ndarray} + a : {dpnp.array, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which minimum values must be computed. By default, the minimum value must be computed over the entire array. If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.array, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional @@ -805,7 +805,7 @@ def ptp( Limitations ----------- - Input array is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray`. + Input array is supported as :class:`dpnp.dpnp.array` or :class:`dpctl.tensor.usm_ndarray`. Examples -------- @@ -958,7 +958,7 @@ def var( Parameters ---------- - a : {dpnp_array, usm_ndarray}: + a : {dpnp.array, usm_ndarray}: Input array. axis : int or tuple of ints, optional axis or axes along which the variances must be computed. If a tuple diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index c293707e2b9f..16b456330874 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1,5 +1,3 @@ -# cython: language_level=3 -# distutils: language = c++ # -*- coding: utf-8 -*- # ***************************************************************************** # Copyright (c) 2016-2024, Intel Corporation @@ -69,6 +67,7 @@ dpnp_log2, dpnp_log10, dpnp_logaddexp, + dpnp_reciprocal, dpnp_rsqrt, dpnp_sin, dpnp_sinh, @@ -1415,36 +1414,64 @@ def logsumexp(x, axis=None, out=None, dtype=None, keepdims=False): return dpnp.get_result_array(result, out, casting="same_kind") -def reciprocal(x1, **kwargs): +def reciprocal( + x, + /, + out=None, + *, + order="K", + where=True, + dtype=None, + subok=True, + **kwargs, +): """ Return the reciprocal of the argument, element-wise. For full documentation refer to :obj:`numpy.reciprocal`. + Parameters + ---------- + x : {dpnp.array, usm_ndarray} + Input array. + out : {None, dpnp.ndarray}, optional + Output array to populate. + Array must 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 + ------- + out : dpnp.ndarray + An array containing the element-wise reciprocals. + Limitations ----------- - Input array is supported as :obj:`dpnp.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 DPNP :ref:`Data types`. Examples -------- >>> import dpnp as np >>> x = np.array([1, 2., 3.33]) - >>> out = np.reciprocal(x) - >>> [i for i in out] - [1.0, 0.5, 0.3003003] + >>> np.reciprocal(x) + array([1.0, 0.5, 0.3003003]) """ - x1_desc = dpnp.get_dpnp_descriptor( - x1, copy_when_strides=False, copy_when_nondefault_queue=False + return check_nd_call_func( + numpy.reciprocal, + dpnp_reciprocal, + x, + out=out, + where=where, + order=order, + dtype=dtype, + subok=subok, + **kwargs, ) - if x1_desc and not kwargs: - return dpnp_recip(x1_desc).get_pyobj() - - return call_origin(numpy.reciprocal, x1, **kwargs) def reduce_hypot(x, axis=None, out=None, dtype=None, keepdims=False): diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index 8958c7f8f217..bc79f538a5e0 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -77,7 +77,6 @@ tests/test_strides.py::test_strides_1arg[(10,)-None-degrees] tests/test_strides.py::test_strides_1arg[(10,)-None-fabs] tests/test_strides.py::test_strides_1arg[(10,)-None-radians] tests/test_strides.py::test_strides_erf[(10,)-None] -tests/test_strides.py::test_strides_reciprocal[(10,)-None] tests/test_umath.py::test_umaths[('divmod', 'ii')] tests/test_umath.py::test_umaths[('divmod', 'll')] @@ -103,7 +102,6 @@ tests/test_umath.py::test_umaths[('nextafter', 'dd')] tests/test_umath.py::test_umaths[('spacing', 'f')] tests/test_umath.py::test_umaths[('spacing', 'd')] -tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestAngle::test_angle tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestRealImag::test_imag_inplace tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestRealImag::test_real_inplace tests/third_party/cupy/core_tests/test_ndarray_conversion.py::TestNdarrayToBytes_param_0_{shape=()}::test_item @@ -399,8 +397,6 @@ tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticBinary2_para tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticBinary2_param_545_{arg1=array([[1, 2, 3], [4, 5, 6]]), arg2=array([[0, 1, 2], [3, 4, 5]]), dtype=float64, name='fmod', use_dtype=False}::test_binary tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticModf::test_modf -tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_3_{name='angle', nargs=1}::test_raises_with_numpy_input - tests/third_party/cupy/math_tests/test_explog.py::TestExplog::test_logaddexp2 tests/third_party/cupy/math_tests/test_explog.py::TestExplog::test_logaddexp2_infinities tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_frexp diff --git a/tests/skipped_tests_gpu.tbl b/tests/skipped_tests_gpu.tbl index a6a2886ad86a..3770c0fa9b96 100644 --- a/tests/skipped_tests_gpu.tbl +++ b/tests/skipped_tests_gpu.tbl @@ -186,7 +186,6 @@ tests/test_linalg.py::test_matrix_rank[None-[[1, 2], [3, 4]]-float32] tests/test_linalg.py::test_matrix_rank[None-[[1, 2], [3, 4]]-int64] tests/test_linalg.py::test_matrix_rank[None-[[1, 2], [3, 4]]-int32] -tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestAngle::test_angle tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestRealImag::test_imag_inplace tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py::TestRealImag::test_real_inplace @@ -495,8 +494,6 @@ tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_par tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_2_{shapes=[(3, 2), (3, 4)]}::test_invalid_broadcast tests/third_party/cupy/manipulation_tests/test_dims.py::TestInvalidBroadcast_param_3_{shapes=[(0,), (2,)]}::test_invalid_broadcast -tests/third_party/cupy/math_tests/test_arithmetic.py::TestArithmeticRaisesWithNumpyInput_param_3_{name='angle', nargs=1}::test_raises_with_numpy_input - tests/third_party/cupy/math_tests/test_explog.py::TestExplog::test_logaddexp2 tests/third_party/cupy/math_tests/test_explog.py::TestExplog::test_logaddexp2_infinities tests/third_party/cupy/math_tests/test_floating.py::TestFloating::test_frexp diff --git a/tests/test_mathematical.py b/tests/test_mathematical.py index 86c31dc25ae3..16f5131fe195 100644 --- a/tests/test_mathematical.py +++ b/tests/test_mathematical.py @@ -29,6 +29,47 @@ ) +class TestAngle: + @pytest.mark.parametrize("deg", [True, False]) + def test_angle_bool(self, deg): + dp_a = dpnp.array([True, False]) + np_a = dp_a.asnumpy() + + expected = numpy.angle(np_a, deg=deg) + result = dpnp.angle(dp_a, deg=deg) + + # In Numpy, for boolean arguments the output data type is always default floating data type. + # while data type of output in DPNP is determined by Type Promotion Rules. + # data type should not be compared + assert_allclose(result.asnumpy(), expected) + + @pytest.mark.parametrize( + "dtype", get_all_dtypes(no_bool=True, no_complex=True) + ) + @pytest.mark.parametrize("deg", [True, False]) + def test_angle(self, dtype, deg): + dp_a = dpnp.arange(10, dtype=dtype) + np_a = dp_a.asnumpy() + + expected = numpy.angle(np_a, deg=deg) + result = dpnp.angle(dp_a, deg=deg) + + assert_dtype_allclose(result, expected) + + @pytest.mark.parametrize("dtype", get_complex_dtypes()) + @pytest.mark.parametrize("deg", [True, False]) + def test_angle_complex(self, dtype, deg): + a = numpy.random.rand(10) + b = numpy.random.rand(10) + np_a = numpy.array(a + 1j * b, dtype=dtype) + dp_a = dpnp.array(np_a) + + expected = numpy.angle(np_a, deg=deg) + result = dpnp.angle(dp_a, deg=deg) + + assert_dtype_allclose(result, expected) + + class TestClip: @pytest.mark.parametrize( "dtype", get_all_dtypes(no_bool=True, no_none=True, no_complex=True) diff --git a/tests/test_strides.py b/tests/test_strides.py index 903341f10006..eb8a89698ece 100644 --- a/tests/test_strides.py +++ b/tests/test_strides.py @@ -6,7 +6,12 @@ import dpnp -from .helper import assert_dtype_allclose, get_all_dtypes +from .helper import ( + assert_dtype_allclose, + get_all_dtypes, + get_complex_dtypes, + get_float_complex_dtypes, +) def _getattr(ex, str_): @@ -171,21 +176,27 @@ def test_strides_erf(dtype, shape): assert_allclose(result, expected, rtol=1e-06) -@pytest.mark.parametrize("dtype", get_all_dtypes(no_bool=True, no_complex=True)) -@pytest.mark.parametrize("shape", [(10,)], ids=["(10,)"]) -def test_strides_reciprocal(dtype, shape): - start, stop = 1, numpy.prod(shape) + 1 +@pytest.mark.parametrize("dtype", get_float_complex_dtypes()) +def test_reciprocal(dtype): + dpa = dpnp.arange(1, 11, dtype=dtype)[::2] + a = numpy.arange(1, 11, dtype=dtype)[::2] - a = numpy.arange(start, stop, dtype=dtype).reshape(shape) - b = a[::2] + result = dpnp.reciprocal(dpa) + expected = numpy.reciprocal(a) - dpa = dpnp.reshape(dpnp.arange(start, stop, dtype=dtype), shape) - dpb = dpa[::2] + assert_dtype_allclose(result, expected) - result = dpnp.reciprocal(dpb) - expected = numpy.reciprocal(b) - assert_allclose(result, expected, rtol=1e-06) +@pytest.mark.parametrize("dtype", get_complex_dtypes()) +def test_angle(dtype): + a = numpy.random.rand(10) + b = numpy.random.rand(10) + z = numpy.array(a + 1j * b, dtype=dtype)[::2] + dpz = dpnp.array(z) + + result = dpnp.angle(dpz) + expected = numpy.angle(z) + assert_dtype_allclose(result, expected) @pytest.mark.parametrize( diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index fd09d08b5beb..8ae0a5364498 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -333,6 +333,7 @@ def test_meshgrid(device_x, device_y): [ pytest.param("average", [1.0, 2.0, 4.0, 7.0]), pytest.param("abs", [-1.2, 1.2]), + pytest.param("angle", [[1.0 + 1.0j, 2.0 + 3.0j]]), pytest.param("arccos", [-0.5, 0.0, 0.5]), pytest.param("arccosh", [1.5, 3.5, 5.0]), pytest.param("arcsin", [-0.5, 0.0, 0.5]), @@ -388,6 +389,7 @@ def test_meshgrid(device_x, device_y): pytest.param( "real", [complex(1.0, 2.0), complex(3.0, 4.0), complex(5.0, 6.0)] ), + pytest.param("reciprocal", [1.0, 2.0, 4.0, 7.0]), pytest.param("sign", [-5.0, 0.0, 4.5]), pytest.param("signbit", [-5.0, 0.0, 4.5]), pytest.param( diff --git a/tests/test_umath.py b/tests/test_umath.py index d9bbacdf4ef3..551ce4cac0a2 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -9,6 +9,7 @@ from .helper import ( assert_dtype_allclose, get_all_dtypes, + get_float_complex_dtypes, get_float_dtypes, has_support_aspect16, has_support_aspect64, @@ -263,14 +264,46 @@ def test_invalid_shape(self, shape): with pytest.raises(ValueError): dpnp.cbrt(dp_array, out=dp_out) + +class TestReciprocal: + @pytest.mark.parametrize("dtype", get_float_complex_dtypes()) + def test_reciprocal(self, dtype): + np_array = numpy.arange(1, 7, dtype=dtype) + expected = numpy.reciprocal(np_array) + + dp_out_dtype = ( + dtype + if has_support_aspect64() + else dpnp.complex64 + if numpy.iscomplexobj(np_array) + else dpnp.float32 + ) + dp_array = dpnp.array(np_array) + dp_out = dpnp.empty(6, dtype=dp_out_dtype) + result = dpnp.reciprocal(dp_array, out=dp_out) + + assert result is dp_out + assert_dtype_allclose(result, expected) + + @pytest.mark.parametrize("dtype", get_float_complex_dtypes()[:-1]) + def test_invalid_dtype(self, dtype): + dpnp_dtype = get_float_complex_dtypes()[-1] + dp_array = dpnp.arange(1, 10, dtype=dpnp_dtype) + dp_out = dpnp.empty(9, dtype=dtype) + + with pytest.raises(TypeError): + dpnp.reciprocal(dp_array, out=dp_out) + + @pytest.mark.parametrize("dtype", get_float_dtypes()) @pytest.mark.parametrize( - "out", - [4, (), [], (3, 7), [2, 4]], - ids=["4", "()", "[]", "(3, 7)", "[2, 4]"], + "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] ) - def test_invalid_out(self, out): - a = dpnp.arange(10) - numpy.testing.assert_raises(TypeError, dpnp.cbrt, a, out) + def test_invalid_shape(self, shape, dtype): + dp_array = dpnp.arange(10, dtype=dtype) + dp_out = dpnp.empty(shape, dtype=dtype) + + with pytest.raises(ValueError): + dpnp.reciprocal(dp_array, out=dp_out) class TestRsqrt: diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index fa4a14090b37..e2fdc5d6a589 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -400,6 +400,7 @@ def test_meshgrid(usm_type_x, usm_type_y): [ pytest.param("average", [1.0, 2.0, 4.0, 7.0]), pytest.param("abs", [-1.2, 1.2]), + pytest.param("angle", [[1.0 + 1.0j, 2.0 + 3.0j]]), pytest.param("arccos", [-0.5, 0.0, 0.5]), pytest.param("arccosh", [1.5, 3.5, 5.0]), pytest.param("arcsin", [-0.5, 0.0, 0.5]), @@ -449,6 +450,7 @@ def test_meshgrid(usm_type_x, usm_type_y): pytest.param( "real", [complex(1.0, 2.0), complex(3.0, 4.0), complex(5.0, 6.0)] ), + pytest.param("reciprocal", [1.0, 2.0, 4.0, 7.0]), pytest.param("reduce_hypot", [1.0, 2.0, 4.0, 7.0]), pytest.param("rsqrt", [1, 8, 27]), pytest.param("sign", [-5.0, 0.0, 4.5]), diff --git a/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py b/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py index 4f807e3b864b..8dfe304da294 100644 --- a/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py +++ b/tests/third_party/cupy/core_tests/test_ndarray_complex_ops.py @@ -4,10 +4,10 @@ import pytest import dpnp as cupy +from tests.helper import has_support_aspect64 from tests.third_party.cupy import testing -@testing.gpu class TestConj(unittest.TestCase): @testing.for_all_dtypes() @testing.numpy_cupy_array_almost_equal() @@ -38,10 +38,9 @@ def test_conjugate_pass(self, xp, dtype): return y -@testing.gpu class TestAngle(unittest.TestCase): @testing.for_all_dtypes() - @testing.numpy_cupy_array_almost_equal() + @testing.numpy_cupy_array_almost_equal(type_check=has_support_aspect64()) def test_angle(self, xp, dtype): x = testing.shaped_arange((2, 3), xp, dtype) return xp.angle(x) @@ -154,7 +153,6 @@ def test_imag_inplace(self, dtype): assert cupy.all(x == expected) -@testing.gpu class TestScalarConversion(unittest.TestCase): @testing.for_all_dtypes() def test_scalar_conversion(self, dtype): diff --git a/tests/third_party/cupy/math_tests/test_arithmetic.py b/tests/third_party/cupy/math_tests/test_arithmetic.py index 6c0dea517508..6528800dc3b0 100644 --- a/tests/third_party/cupy/math_tests/test_arithmetic.py +++ b/tests/third_party/cupy/math_tests/test_arithmetic.py @@ -15,12 +15,17 @@ unsigned_int_types = [] int_types = signed_int_types + unsigned_int_types all_types = float_types + int_types + complex_types +negative_types_wo_fp16 = ( + [numpy.bool_] + + [numpy.float32, numpy.float64] + + [numpy.int16, numpy.int32, numpy.int64] + + complex_types +) negative_types = float_types + signed_int_types + complex_types negative_no_complex_types = float_types + signed_int_types no_complex_types = float_types + int_types -@testing.gpu @testing.parameterize( *( testing.product( @@ -53,7 +58,7 @@ ) ) ) -class TestArithmeticRaisesWithNumpyInput(unittest.TestCase): +class TestArithmeticRaisesWithNumpyInput: def test_raises_with_numpy_input(self): nargs = self.nargs name = self.name @@ -65,11 +70,10 @@ def test_raises_with_numpy_input(self): # We don't test all-cupy-array inputs here continue arys = [xp.array([2, -3]) for xp in input_xp_list] - with self.assertRaises(TypeError): + with pytest.raises(TypeError): func(*arys) -@testing.gpu @testing.parameterize( *( testing.product( @@ -84,6 +88,32 @@ def test_raises_with_numpy_input(self): "name": ["conj", "conjugate", "real", "imag"], } ) + + testing.product( + { + "arg1": ( + [ + testing.shaped_arange((2, 3), numpy, dtype=d) + for d in all_types + ] + + [0, 0.0j, 0j, 2, 2.0, 2j, True, False] + ), + "deg": [True, False], + "name": ["angle"], + } + ) + + testing.product( + { + "arg1": ( + [ + numpy.array([-3, -2, -1, 1, 2, 3], dtype=d) + for d in negative_types_wo_fp16 + ] + + [0, 0.0j, 0j, 2, 2.0, 2j, -2, -2.0, -2j, True, False] + ), + "deg": [True, False], + "name": ["angle"], + } + ) + testing.product( { "arg1": ( @@ -99,13 +129,36 @@ def test_raises_with_numpy_input(self): ) ) @pytest.mark.usefixtures("allow_fall_back_on_numpy") -class TestArithmeticUnary(unittest.TestCase): +class TestArithmeticUnary: @testing.numpy_cupy_allclose(atol=1e-5, type_check=has_support_aspect64()) def test_unary(self, xp): arg1 = self.arg1 if isinstance(arg1, numpy.ndarray): arg1 = xp.asarray(arg1) - y = getattr(xp, self.name)(arg1) + + if self.name in ("reciprocal") and xp is numpy: + # In Numpy, for integer arguments with absolute value larger than 1 the result is always zero. + # We need to convert the input data type to float then compare the output with DPNP. + if isinstance(arg1, numpy.ndarray) and numpy.issubdtype( + arg1.dtype, numpy.integer + ): + np_dtype = ( + numpy.float64 if has_support_aspect64() else numpy.float32 + ) + arg1 = xp.asarray(arg1, dtype=np_dtype) + + if self.name in {"angle"}: + y = getattr(xp, self.name)(arg1, self.deg) + # In Numpy, for boolean arguments the output data type is always default floating data type. + # while data type of output in DPNP is determined by Type Promotion Rules. + if ( + isinstance(arg1, cupy.ndarray) + and cupy.issubdtype(arg1.dtype, cupy.bool) + and has_support_aspect64() + ): + y = y.astype(cupy.float64) + else: + y = getattr(xp, self.name)(arg1) # if self.name in ("real", "imag"): # Some NumPy functions return Python scalars for Python scalar diff --git a/tests/third_party/cupy/sorting_tests/test_search.py b/tests/third_party/cupy/sorting_tests/test_search.py index d14503d6c17b..11343da25a5a 100644 --- a/tests/third_party/cupy/sorting_tests/test_search.py +++ b/tests/third_party/cupy/sorting_tests/test_search.py @@ -9,8 +9,7 @@ # from cupy.core import _accelerator -@testing.gpu -class TestSearch(unittest.TestCase): +class TestSearch: @testing.for_all_dtypes(no_complex=True) @testing.numpy_cupy_allclose() def test_argmax_all(self, xp, dtype): @@ -218,7 +217,6 @@ def test_argmin_zero_size_axis1(self, xp, dtype): # return a.argmax() -@testing.gpu @testing.parameterize( *testing.product( { @@ -228,7 +226,7 @@ def test_argmin_zero_size_axis1(self, xp, dtype): } ) ) -class TestArgMinMaxDtype(unittest.TestCase): +class TestArgMinMaxDtype: @testing.for_dtypes( dtypes=[numpy.int8, numpy.int16, numpy.int32, numpy.int64], name="result_dtype", diff --git a/tests/third_party/cupy/statistics_tests/test_order.py b/tests/third_party/cupy/statistics_tests/test_order.py index 62ac2f72b361..3805933d4902 100644 --- a/tests/third_party/cupy/statistics_tests/test_order.py +++ b/tests/third_party/cupy/statistics_tests/test_order.py @@ -1,4 +1,3 @@ -import unittest import warnings import numpy From a58f76cccfdc9fbc1f48d09a15651d8728456a34 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 5 Jan 2024 16:56:23 -0600 Subject: [PATCH 2/9] fix docstring --- dpnp/dpnp_iface_arraycreation.py | 14 +++++++------- dpnp/dpnp_iface_manipulation.py | 8 ++++---- dpnp/dpnp_iface_mathematical.py | 10 +++++----- dpnp/dpnp_iface_nanfunctions.py | 22 +++++++++++----------- dpnp/dpnp_iface_searching.py | 8 ++++---- dpnp/dpnp_iface_statistics.py | 14 +++++++------- dpnp/dpnp_iface_trigonometric.py | 10 +++++----- 7 files changed, 43 insertions(+), 43 deletions(-) diff --git a/dpnp/dpnp_iface_arraycreation.py b/dpnp/dpnp_iface_arraycreation.py index 9dfe2ef13d20..067eb3fbb526 100644 --- a/dpnp/dpnp_iface_arraycreation.py +++ b/dpnp/dpnp_iface_arraycreation.py @@ -788,7 +788,7 @@ def empty_like( Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` Parameter `order` is supported with values ``"C"`` or ``"F"``. Parameter `subok` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. @@ -1050,7 +1050,7 @@ def full_like( Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` Parameter `order` is supported only with values ``"C"`` and ``"F"``. Parameter `subok` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. @@ -1396,7 +1396,7 @@ def meshgrid(*xi, copy=True, sparse=False, indexing="xy"): Limitations ----------- - Each array instance from `xi` is supported as either :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray`. + Each array instance from `xi` is supported as either :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. Parameter `copy` is supported only with default value ``True``. Parameter `sparse` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. @@ -1653,7 +1653,7 @@ def ones_like( Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` Parameter `order` is supported with values ``"C"`` or ``"F"``. Parameter `subok` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. @@ -1823,7 +1823,7 @@ def tril(x1, /, *, k=0): Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. Parameter `k` is supported only of integer data type. Otherwise the function will be executed sequentially on CPU. @@ -1867,7 +1867,7 @@ def triu(x1, /, *, k=0): Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` with two or more dimensions. Parameter `k` is supported only of integer data type. Otherwise the function will be executed sequentially on CPU. @@ -2055,7 +2055,7 @@ def zeros_like( Limitations ----------- - Parameter `x1` is supported as :class:`dpnp.dpnp_array` or :class:`dpctl.tensor.usm_ndarray` + Parameter `x1` is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray` Parameter `order` is supported with values ``"C"`` or ``"F"``. Parameter `subok` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. diff --git a/dpnp/dpnp_iface_manipulation.py b/dpnp/dpnp_iface_manipulation.py index ac83102c715a..6a48e4d1e105 100644 --- a/dpnp/dpnp_iface_manipulation.py +++ b/dpnp/dpnp_iface_manipulation.py @@ -1174,7 +1174,7 @@ def ravel(a, order="C"): Parameters ---------- - x : {dpnp.array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array. The elements in `a` are read in the order specified by order, and packed as a 1-D array. order : {'C', 'F'}, optional @@ -1187,7 +1187,7 @@ def ravel(a, order="C"): Returns ------- - out : dpnp.array + out : dpnp.ndarray A contiguous 1-D array of the same subtype as `a`, with shape (a.size,). See Also @@ -1220,7 +1220,7 @@ def repeat(a, repeats, axis=None): Parameters ---------- - x : {dpnp.array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array. repeat : int or array of int The number of repetitions for each element. `repeats` is broadcasted to fit @@ -1231,7 +1231,7 @@ def repeat(a, repeats, axis=None): Returns ------- - out : dpnp.array + out : dpnp.ndarray Output array which has the same shape as `a`, except along the given axis. See Also diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index fc7047add6f8..20564569c372 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.py @@ -301,7 +301,7 @@ def angle(z, deg=False): Parameters ---------- - x : {dpnp.array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array, expected to have a complex-valued floating-point data type. deg : bool, optional Return angle in degrees if True, radians if False (default). @@ -448,12 +448,12 @@ def clip(a, a_min, a_max, *, out=None, order="K", **kwargs): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Array containing elements to clip. - a_min, a_max : {dpnp.array, usm_ndarray, None} + a_min, a_max : {dpnp.ndarray, usm_ndarray, None} Minimum and maximum value. If ``None``, clipping is not performed on the corresponding edge. Only one of `a_min` and `a_max` may be ``None``. Both are broadcast against `a`. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional The results will be placed in this array. It may be the input array for in-place clipping. `out` must be of the right shape to hold the output. Its type is preserved. order : {"C", "F", "A", "K", None}, optional @@ -462,7 +462,7 @@ def clip(a, a_min, a_max, *, out=None, order="K", **kwargs): Returns ------- - out : dpnp.array + out : dpnp.ndarray An array with the elements of `a`, but where values < `a_min` are replaced with `a_min`, and those > `a_max` with `a_max`. diff --git a/dpnp/dpnp_iface_nanfunctions.py b/dpnp/dpnp_iface_nanfunctions.py index ff06a5d0eb63..dda0e0bd2c7d 100644 --- a/dpnp/dpnp_iface_nanfunctions.py +++ b/dpnp/dpnp_iface_nanfunctions.py @@ -72,14 +72,14 @@ def _replace_nan(a, val): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. val : float NaN values are set to `val` before doing the operation. Returns ------- - out : {dpnp.array} + out : {dpnp.ndarray} If `a` is of inexact type, return a copy of `a` with the NaNs replaced by the fill value, otherwise return `a`. mask: {bool, None} @@ -110,13 +110,13 @@ def nanargmax(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the maximum value of the flattened array. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -178,13 +178,13 @@ def nanargmin(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the minimum value of the flattened array. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -320,14 +320,14 @@ def nanmax(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which maximum values must be computed. By default, the maximum value must be computed over the entire array. If a tuple of integers, maximum values must be computed over multiple axes. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -531,14 +531,14 @@ def nanmin(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which minimum values must be computed. By default, the minimum value must be computed over the entire array. If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional @@ -908,7 +908,7 @@ def nanvar( Parameters ---------- - a : {dpnp.array, usm_ndarray}: + a : {dpnp.ndarray, usm_ndarray}: Input array. axis : int or tuple of ints, optional axis or axes along which the variances must be computed. If a tuple diff --git a/dpnp/dpnp_iface_searching.py b/dpnp/dpnp_iface_searching.py index 05d41a04998f..4df311ad45e8 100644 --- a/dpnp/dpnp_iface_searching.py +++ b/dpnp/dpnp_iface_searching.py @@ -57,13 +57,13 @@ def argmax(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the maximum value of the flattened array. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -141,13 +141,13 @@ def argmin(a, axis=None, out=None, *, keepdims=False): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int, optional Axis along which to search. If ``None``, the function must return the index of the minimum value of the flattened array. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional diff --git a/dpnp/dpnp_iface_statistics.py b/dpnp/dpnp_iface_statistics.py index 660a88b73e88..2568acd71f1c 100644 --- a/dpnp/dpnp_iface_statistics.py +++ b/dpnp/dpnp_iface_statistics.py @@ -72,7 +72,7 @@ def _count_reduce_items(arr, axis, where=True): Parameters ---------- - arr : {dpnp.array, usm_ndarray} + arr : {dpnp.ndarray, usm_ndarray} Input array. axis : int or tuple of ints, optional axis or axes along which the number of items used in a reduction operation must be counted. @@ -485,14 +485,14 @@ def max(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which maximum values must be computed. By default, the maximum value must be computed over the entire array. If a tuple of integers, maximum values must be computed over multiple axes. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool @@ -706,14 +706,14 @@ def min(a, axis=None, out=None, keepdims=False, initial=None, where=True): Parameters ---------- - a : {dpnp.array, usm_ndarray} + a : {dpnp.ndarray, usm_ndarray} Input array. axis : int or tuple of ints, optional Axis or axes along which minimum values must be computed. By default, the minimum value must be computed over the entire array. If a tuple of integers, minimum values must be computed over multiple axes. Default: ``None``. - out : {dpnp.array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. keepdims : bool, optional @@ -805,7 +805,7 @@ def ptp( Limitations ----------- - Input array is supported as :class:`dpnp.dpnp.array` or :class:`dpctl.tensor.usm_ndarray`. + Input array is supported as :class:`dpnp.dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. Examples -------- @@ -958,7 +958,7 @@ def var( Parameters ---------- - a : {dpnp.array, usm_ndarray}: + a : {dpnp.ndarray, usm_ndarray}: Input array. axis : int or tuple of ints, optional axis or axes along which the variances must be computed. If a tuple diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index 16b456330874..4316db1e40c7 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1345,14 +1345,14 @@ def logsumexp(x, axis=None, out=None, dtype=None, keepdims=False): Parameters ---------- - x : {dpnp_array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array, expected to have a real-valued data type. axis : int or tuple of ints, optional Axis or axes along which values must be computed. If a tuple of unique integers, values are computed over multiple axes. If ``None``, the result is computed over the entire array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. dtype : data type, optional @@ -1432,7 +1432,7 @@ def reciprocal( Parameters ---------- - x : {dpnp.array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array. out : {None, dpnp.ndarray}, optional Output array to populate. @@ -1480,14 +1480,14 @@ def reduce_hypot(x, axis=None, out=None, dtype=None, keepdims=False): Parameters ---------- - x : {dpnp_array, usm_ndarray} + x : {dpnp.ndarray, usm_ndarray} Input array, expected to have a real-valued data type. axis : int or tuple of ints, optional Axis or axes along which values must be computed. If a tuple of unique integers, values are computed over multiple axes. If ``None``, the result is computed over the entire array. Default: ``None``. - out : {dpnp_array, usm_ndarray}, optional + out : {dpnp.ndarray, usm_ndarray}, optional If provided, the result will be inserted into this array. It should be of the appropriate shape and dtype. dtype : data type, optional From da11aa763791cf7f73e4ef9f26fb2811a4fe61c8 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Fri, 5 Jan 2024 18:12:56 -0600 Subject: [PATCH 3/9] skip umath test for reciprocal --- tests/test_umath.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_umath.py b/tests/test_umath.py index 551ce4cac0a2..11ed9b3441d1 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -83,6 +83,9 @@ def test_umaths(test_cases): args = get_args(args_str, sh, xp=numpy) iargs = get_args(args_str, sh, xp=dpnp) + if umath == "reciprocal" and iargs[0].dtype in [dpnp.int32, dpnp.int64]: + pytest.skip("For integer input array, numpy.reciprocal returns zero.") + # original expected = getattr(numpy, umath)(*args) From 14eee497f33d5d291ac7ff848bb21f1495e1b3a8 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 9 Jan 2024 09:52:12 -0600 Subject: [PATCH 4/9] address comments --- dpnp/dpnp_iface_mathematical.py | 71 ++++++++----------- dpnp/dpnp_iface_trigonometric.py | 4 ++ tests/test_umath.py | 2 +- .../cupy/math_tests/test_arithmetic.py | 5 -- 4 files changed, 36 insertions(+), 46 deletions(-) diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index 20564569c372..7ed945ee6c2f 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.py @@ -321,6 +321,7 @@ def angle(z, deg=False): See Also -------- :obj:`dpnp.arctan2` : Element-wise arc tangent of `x1/x2` choosing the quadrant correctly. + :obj:`dpnp.arctan` : Trigonometric inverse tangent, element-wise. :obj:`dpnp.absolute` : Calculate the absolute value element-wise. Examples @@ -335,18 +336,11 @@ def angle(z, deg=False): """ - if not dpnp.isscalar(z): - dpnp.check_supported_arrays_type(z) - res = dpnp_angle(z) - if deg is True: - res = res * (180 / dpnp.pi) - return res - else: - return call_origin( - numpy.angle, - z, - deg=deg, - ) + dpnp.check_supported_arrays_type(z) + res = dpnp_angle(z) + if deg is True: + res = res * (180 / dpnp.pi) + return res def around(x, /, decimals=0, out=None): @@ -1536,21 +1530,23 @@ def gradient(x1, *varargs, **kwargs): return call_origin(numpy.gradient, x1, *varargs, **kwargs) -def imag(x): +def imag(val): """ Return the imaginary part of the complex argument. For full documentation refer to :obj:`numpy.imag`. + Parameters + ---------- + x : {dpnp.ndarray, usm_ndarray} + Input array. + Returns ------- out : dpnp.ndarray - The imaginary component of the complex argument. - - Limitations - ----------- - Parameter `x` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. - Input array data types are limited by supported DPNP :ref:`Data types`. + The imaginary component of the complex argument. If `val` is real, + the type of `val` is used for the output. If `val` has complex + elements, the returned type is float. See Also -------- @@ -1574,12 +1570,8 @@ def imag(x): """ - if dpnp.isscalar(x): - # input has to be an array - pass - else: - return dpnp_imag(x) - return call_origin(numpy.imag, x) + dpnp.check_supported_arrays_type(val) + return dpnp_imag(val) def maximum( @@ -2268,21 +2260,23 @@ def proj( ) -def real(x): +def real(val): """ Return the real part of the complex argument. For full documentation refer to :obj:`numpy.real`. + Parameters + ---------- + x : {dpnp.ndarray, usm_ndarray} + Input array. + Returns ------- out : dpnp.ndarray - The real component of the complex argument. - - Limitations - ----------- - Parameter `x` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. - Input array data types are limited by supported DPNP :ref:`Data types`. + The real component of the complex argument. If `val` is real, + the type of `val` is used for the output. If `val` has complex + elements, the returned type is float. See Also -------- @@ -2309,15 +2303,12 @@ def real(x): array(1.) """ - if dpnp.isscalar(x): - # input has to be an array - pass + + dpnp.check_supported_arrays_type(val) + if dpnp.issubsctype(val.dtype, dpnp.complexfloating): + return dpnp_real(val) else: - if dpnp.issubsctype(x.dtype, dpnp.complexfloating): - return dpnp_real(x) - else: - return x - return call_origin(numpy.real, x) + return val def remainder( diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index 4316db1e40c7..d074e4ca1ba8 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1452,6 +1452,10 @@ def reciprocal( Keyword argument `kwargs` is currently unsupported. Otherwise the function will be executed sequentially on CPU. + See Also + -------- + :obj:`dpnp.rsqrt` : Return the reciprocal square-root of an array, element-wise. + Examples -------- >>> import dpnp as np diff --git a/tests/test_umath.py b/tests/test_umath.py index 11ed9b3441d1..18cb249d5d01 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -83,7 +83,7 @@ def test_umaths(test_cases): args = get_args(args_str, sh, xp=numpy) iargs = get_args(args_str, sh, xp=dpnp) - if umath == "reciprocal" and iargs[0].dtype in [dpnp.int32, dpnp.int64]: + if umath == "reciprocal" and args[0].dtype in [numpy.int32, numpy.int64]: pytest.skip("For integer input array, numpy.reciprocal returns zero.") # original diff --git a/tests/third_party/cupy/math_tests/test_arithmetic.py b/tests/third_party/cupy/math_tests/test_arithmetic.py index 6528800dc3b0..9297b3de937f 100644 --- a/tests/third_party/cupy/math_tests/test_arithmetic.py +++ b/tests/third_party/cupy/math_tests/test_arithmetic.py @@ -83,7 +83,6 @@ def test_raises_with_numpy_input(self): testing.shaped_arange((2, 3), numpy, dtype=d) for d in all_types ] - + [0, 0.0j, 0j, 2, 2.0, 2j, True, False] ), "name": ["conj", "conjugate", "real", "imag"], } @@ -95,7 +94,6 @@ def test_raises_with_numpy_input(self): testing.shaped_arange((2, 3), numpy, dtype=d) for d in all_types ] - + [0, 0.0j, 0j, 2, 2.0, 2j, True, False] ), "deg": [True, False], "name": ["angle"], @@ -108,7 +106,6 @@ def test_raises_with_numpy_input(self): numpy.array([-3, -2, -1, 1, 2, 3], dtype=d) for d in negative_types_wo_fp16 ] - + [0, 0.0j, 0j, 2, 2.0, 2j, -2, -2.0, -2j, True, False] ), "deg": [True, False], "name": ["angle"], @@ -121,14 +118,12 @@ def test_raises_with_numpy_input(self): testing.shaped_arange((2, 3), numpy, dtype=d) + 1 for d in all_types ] - + [2, 2.0] ), "name": ["reciprocal"], } ) ) ) -@pytest.mark.usefixtures("allow_fall_back_on_numpy") class TestArithmeticUnary: @testing.numpy_cupy_allclose(atol=1e-5, type_check=has_support_aspect64()) def test_unary(self, xp): From a6b5c05fc5a4371585afc5c72603c88d64eb7c40 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 9 Jan 2024 11:15:57 -0600 Subject: [PATCH 5/9] add a note for reciprocal --- dpnp/dpnp_iface_trigonometric.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index d074e4ca1ba8..ffc7ad31d005 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1446,6 +1446,13 @@ def reciprocal( out : dpnp.ndarray An array containing the element-wise reciprocals. + Notes + ----- + If `x` has a integral data type, the output has the default + real-valued floating-point data type for the device where + input array `x` is allocated. If `x` has a floating-point + data type, the output has the same data type. + Limitations ----------- Parameters `where`, `dtype` and `subok` are supported with their default values. From a6d85806cdd2352b58ed7dbf09098c0d35a9a114 Mon Sep 17 00:00:00 2001 From: vtavana <120411540+vtavana@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:08:51 -0600 Subject: [PATCH 6/9] Update dpnp/dpnp_iface_trigonometric.py Co-authored-by: Anton <100830759+antonwolfy@users.noreply.github.com> --- dpnp/dpnp_iface_trigonometric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index ffc7ad31d005..092e0be19712 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1448,7 +1448,7 @@ def reciprocal( Notes ----- - If `x` has a integral data type, the output has the default + If `x` has a integral data type, the output will have the default real-valued floating-point data type for the device where input array `x` is allocated. If `x` has a floating-point data type, the output has the same data type. From 2e59ee9afb47b105dba0674e75cf6bf4359bf374 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Tue, 9 Jan 2024 15:15:45 -0600 Subject: [PATCH 7/9] fix docstring --- dpnp/dpnp_iface_trigonometric.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpnp/dpnp_iface_trigonometric.py b/dpnp/dpnp_iface_trigonometric.py index 092e0be19712..2be5c96217a4 100644 --- a/dpnp/dpnp_iface_trigonometric.py +++ b/dpnp/dpnp_iface_trigonometric.py @@ -1451,7 +1451,7 @@ def reciprocal( If `x` has a integral data type, the output will have the default real-valued floating-point data type for the device where input array `x` is allocated. If `x` has a floating-point - data type, the output has the same data type. + data type, the output will have the same data type. Limitations ----------- From 98edb71f2cf7973f559982ae83a5a80835d3ca14 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Wed, 17 Jan 2024 11:51:16 -0600 Subject: [PATCH 8/9] update retunrs for angle and reciprocal update out keyword implementation for angle and reciprocal to make it consistent with implementation of other functions --- dpnp/dpnp_algo/dpnp_elementwise_common.py | 10 +-- tests/test_umath.py | 74 ++++++++++------------- 2 files changed, 35 insertions(+), 49 deletions(-) diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index 7d470424e1de..0bdcd1035724 100644 --- a/dpnp/dpnp_algo/dpnp_elementwise_common.py +++ b/dpnp/dpnp_algo/dpnp_elementwise_common.py @@ -447,10 +447,7 @@ def dpnp_angle(x, out=None, order="K"): out_usm = None if out is None else dpnp.get_usm_ndarray(out) res_usm = angle_func(x1_usm, out=out_usm, order=order) - if out is None: - return dpnp_array._create_from_usm_ndarray(res_usm) - else: - return out + return _get_result(res_usm, out=out) _asin_docstring = """ @@ -2535,10 +2532,7 @@ def dpnp_reciprocal(x, out=None, order="K"): out_usm = None if out is None else dpnp.get_usm_ndarray(out) res_usm = reciprocal_func(x1_usm, out=out_usm, order=order) - if out is None: - return dpnp_array._create_from_usm_ndarray(res_usm) - else: - return out + return _get_result(res_usm, out=out) _remainder_docstring = """ diff --git a/tests/test_umath.py b/tests/test_umath.py index 18cb249d5d01..b1cca385ecbf 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -268,47 +268,6 @@ def test_invalid_shape(self, shape): dpnp.cbrt(dp_array, out=dp_out) -class TestReciprocal: - @pytest.mark.parametrize("dtype", get_float_complex_dtypes()) - def test_reciprocal(self, dtype): - np_array = numpy.arange(1, 7, dtype=dtype) - expected = numpy.reciprocal(np_array) - - dp_out_dtype = ( - dtype - if has_support_aspect64() - else dpnp.complex64 - if numpy.iscomplexobj(np_array) - else dpnp.float32 - ) - dp_array = dpnp.array(np_array) - dp_out = dpnp.empty(6, dtype=dp_out_dtype) - result = dpnp.reciprocal(dp_array, out=dp_out) - - assert result is dp_out - assert_dtype_allclose(result, expected) - - @pytest.mark.parametrize("dtype", get_float_complex_dtypes()[:-1]) - def test_invalid_dtype(self, dtype): - dpnp_dtype = get_float_complex_dtypes()[-1] - dp_array = dpnp.arange(1, 10, dtype=dpnp_dtype) - dp_out = dpnp.empty(9, dtype=dtype) - - with pytest.raises(TypeError): - dpnp.reciprocal(dp_array, out=dp_out) - - @pytest.mark.parametrize("dtype", get_float_dtypes()) - @pytest.mark.parametrize( - "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] - ) - def test_invalid_shape(self, shape, dtype): - dp_array = dpnp.arange(10, dtype=dtype) - dp_out = dpnp.empty(shape, dtype=dtype) - - with pytest.raises(ValueError): - dpnp.reciprocal(dp_array, out=dp_out) - - class TestRsqrt: @pytest.mark.usefixtures("suppress_divide_numpy_warnings") @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) @@ -397,6 +356,39 @@ def test_invalid_out(self, out): numpy.testing.assert_raises(TypeError, numpy.square, a.asnumpy(), out) +class TestReciprocal: + @pytest.mark.parametrize("dtype", get_float_complex_dtypes()) + def test_reciprocal(self, dtype): + np_array, expected = _get_numpy_arrays("reciprocal", dtype, [-5, 5, 10]) + + dp_array = dpnp.array(np_array) + out_dtype = _get_output_data_type(dtype) + dp_out = dpnp.empty(expected.shape, dtype=out_dtype) + result = dpnp.reciprocal(dp_array, out=dp_out) + + assert result is dp_out + assert_dtype_allclose(result, expected) + + @pytest.mark.parametrize("dtype", get_float_complex_dtypes()[:-1]) + def test_invalid_dtype(self, dtype): + dpnp_dtype = get_float_complex_dtypes()[-1] + dp_array = dpnp.arange(10, dtype=dpnp_dtype) + dp_out = dpnp.empty(10, dtype=dtype) + + with pytest.raises(TypeError): + dpnp.reciprocal(dp_array, out=dp_out) + + @pytest.mark.parametrize( + "shape", [(0,), (15,), (2, 2)], ids=["(0,)", "(15, )", "(2,2)"] + ) + def test_invalid_shape(self, shape): + dp_array = dpnp.arange(10) + dp_out = dpnp.empty(shape) + + with pytest.raises(ValueError): + dpnp.reciprocal(dp_array, out=dp_out) + + class TestArctan2: @pytest.mark.parametrize("dtype", get_all_dtypes(no_complex=True)) def test_arctan2(self, dtype): From 61b2e0e3918296f01de276a64f428599e32ff181 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Sat, 20 Jan 2024 14:57:00 +0100 Subject: [PATCH 9/9] Updated TestReciprocal to be compliant with the latest available dpctl in internal CI --- tests/test_umath.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_umath.py b/tests/test_umath.py index d4f681768deb..8e04a439bc93 100644 --- a/tests/test_umath.py +++ b/tests/test_umath.py @@ -383,7 +383,9 @@ def test_invalid_dtype(self, dtype): dp_array = dpnp.arange(10, dtype=dpnp_dtype) dp_out = dpnp.empty(10, dtype=dtype) - with pytest.raises(TypeError): + # TODO: change it to ValueError, when dpctl + # is being used in internal CI + with pytest.raises((TypeError, ValueError)): dpnp.reciprocal(dp_array, out=dp_out) @pytest.mark.parametrize(