From 03276b7f0cbdff482dae0b0a7c28c6a59615c341 Mon Sep 17 00:00:00 2001 From: Vahid Tavanashad Date: Mon, 16 Oct 2023 13:28:36 -0400 Subject: [PATCH] implement dpnp.max and dpnp.min using dpctl.tensor functions --- dpnp/backend/include/dpnp_iface_fptr.hpp | 26 ++- dpnp/backend/kernels/dpnp_krnl_statistics.cpp | 42 ----- dpnp/dpnp_algo/dpnp_algo.pxd | 10 - dpnp/dpnp_algo/dpnp_algo_statistics.pxi | 171 ------------------ dpnp/dpnp_algo/dpnp_elementwise_common.py | 2 - dpnp/dpnp_array.py | 13 +- dpnp/dpnp_iface_mathematical.py | 12 +- dpnp/dpnp_iface_statistics.py | 166 +++++++++-------- tests/skipped_tests.tbl | 5 - tests/skipped_tests_gpu.tbl | 1 + tests/test_statistics.py | 21 ++- tests/test_sycl_queue.py | 2 + tests/test_usm_type.py | 2 + 13 files changed, 132 insertions(+), 341 deletions(-) diff --git a/dpnp/backend/include/dpnp_iface_fptr.hpp b/dpnp/backend/include/dpnp_iface_fptr.hpp index 3df04000413..409755af919 100644 --- a/dpnp/backend/include/dpnp_iface_fptr.hpp +++ b/dpnp/backend/include/dpnp_iface_fptr.hpp @@ -214,20 +214,18 @@ enum class DPNPFuncName : size_t DPNP_FN_MATRIX_RANK_EXT, /**< Used in numpy.linalg.matrix_rank() impl, requires extra parameters */ DPNP_FN_MAX, /**< Used in numpy.max() impl */ - DPNP_FN_MAX_EXT, /**< Used in numpy.max() impl, requires extra parameters */ - DPNP_FN_MAXIMUM, /**< Used in numpy.fmax() impl */ - DPNP_FN_MAXIMUM_EXT, /**< Used in numpy.fmax() impl , requires extra - parameters */ - DPNP_FN_MEAN, /**< Used in numpy.mean() impl */ - DPNP_FN_MEDIAN, /**< Used in numpy.median() impl */ - DPNP_FN_MEDIAN_EXT, /**< Used in numpy.median() impl, requires extra - parameters */ - DPNP_FN_MIN, /**< Used in numpy.min() impl */ - DPNP_FN_MIN_EXT, /**< Used in numpy.min() impl, requires extra parameters */ - DPNP_FN_MINIMUM, /**< Used in numpy.fmin() impl */ - DPNP_FN_MINIMUM_EXT, /**< Used in numpy.fmax() impl, requires extra - parameters */ - DPNP_FN_MODF, /**< Used in numpy.modf() impl */ + DPNP_FN_MAXIMUM, /**< Used in numpy.fmax() impl */ + DPNP_FN_MAXIMUM_EXT, /**< Used in numpy.fmax() impl , requires extra + parameters */ + DPNP_FN_MEAN, /**< Used in numpy.mean() impl */ + DPNP_FN_MEDIAN, /**< Used in numpy.median() impl */ + DPNP_FN_MEDIAN_EXT, /**< Used in numpy.median() impl, requires extra + parameters */ + DPNP_FN_MIN, /**< Used in numpy.min() impl */ + DPNP_FN_MINIMUM, /**< Used in numpy.fmin() impl */ + DPNP_FN_MINIMUM_EXT, /**< Used in numpy.fmax() impl, requires extra + parameters */ + DPNP_FN_MODF, /**< Used in numpy.modf() impl */ DPNP_FN_MODF_EXT, /**< Used in numpy.modf() impl, requires extra parameters */ DPNP_FN_MULTIPLY, /**< Used in numpy.multiply() impl */ diff --git a/dpnp/backend/kernels/dpnp_krnl_statistics.cpp b/dpnp/backend/kernels/dpnp_krnl_statistics.cpp index b0c1016b803..059262a29c8 100644 --- a/dpnp/backend/kernels/dpnp_krnl_statistics.cpp +++ b/dpnp/backend/kernels/dpnp_krnl_statistics.cpp @@ -511,18 +511,6 @@ void (*dpnp_max_default_c)(void *, const shape_elem_type *, size_t) = dpnp_max_c<_DataType>; -template -DPCTLSyclEventRef (*dpnp_max_ext_c)(DPCTLSyclQueueRef, - void *, - void *, - const size_t, - const shape_elem_type *, - size_t, - const shape_elem_type *, - size_t, - const DPCTLEventVectorRef) = - dpnp_max_c<_DataType>; - template DPCTLSyclEventRef dpnp_mean_c(DPCTLSyclQueueRef q_ref, void *array1_in, @@ -895,18 +883,6 @@ void (*dpnp_min_default_c)(void *, const shape_elem_type *, size_t) = dpnp_min_c<_DataType>; -template -DPCTLSyclEventRef (*dpnp_min_ext_c)(DPCTLSyclQueueRef, - void *, - void *, - const size_t, - const shape_elem_type *, - size_t, - const shape_elem_type *, - size_t, - const DPCTLEventVectorRef) = - dpnp_min_c<_DataType>; - template DPCTLSyclEventRef dpnp_nanvar_c(DPCTLSyclQueueRef q_ref, void *array1_in, @@ -1302,15 +1278,6 @@ void func_map_init_statistics(func_map_t &fmap) fmap[DPNPFuncName::DPNP_FN_MAX][eft_DBL][eft_DBL] = { eft_DBL, (void *)dpnp_max_default_c}; - fmap[DPNPFuncName::DPNP_FN_MAX_EXT][eft_INT][eft_INT] = { - eft_INT, (void *)dpnp_max_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MAX_EXT][eft_LNG][eft_LNG] = { - eft_LNG, (void *)dpnp_max_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MAX_EXT][eft_FLT][eft_FLT] = { - eft_FLT, (void *)dpnp_max_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MAX_EXT][eft_DBL][eft_DBL] = { - eft_DBL, (void *)dpnp_max_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MEAN][eft_INT][eft_INT] = { eft_DBL, (void *)dpnp_mean_default_c}; fmap[DPNPFuncName::DPNP_FN_MEAN][eft_LNG][eft_LNG] = { @@ -1359,15 +1326,6 @@ void func_map_init_statistics(func_map_t &fmap) fmap[DPNPFuncName::DPNP_FN_MIN][eft_DBL][eft_DBL] = { eft_DBL, (void *)dpnp_min_default_c}; - fmap[DPNPFuncName::DPNP_FN_MIN_EXT][eft_INT][eft_INT] = { - eft_INT, (void *)dpnp_min_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MIN_EXT][eft_LNG][eft_LNG] = { - eft_LNG, (void *)dpnp_min_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MIN_EXT][eft_FLT][eft_FLT] = { - eft_FLT, (void *)dpnp_min_ext_c}; - fmap[DPNPFuncName::DPNP_FN_MIN_EXT][eft_DBL][eft_DBL] = { - eft_DBL, (void *)dpnp_min_ext_c}; - fmap[DPNPFuncName::DPNP_FN_NANVAR][eft_INT][eft_INT] = { eft_INT, (void *)dpnp_nanvar_default_c}; fmap[DPNPFuncName::DPNP_FN_NANVAR][eft_LNG][eft_LNG] = { diff --git a/dpnp/dpnp_algo/dpnp_algo.pxd b/dpnp/dpnp_algo/dpnp_algo.pxd index da6aef0ccd9..a82b6fafbc8 100644 --- a/dpnp/dpnp_algo/dpnp_algo.pxd +++ b/dpnp/dpnp_algo/dpnp_algo.pxd @@ -108,14 +108,10 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na DPNP_FN_MATMUL_EXT DPNP_FN_MATRIX_RANK DPNP_FN_MATRIX_RANK_EXT - DPNP_FN_MAX - DPNP_FN_MAX_EXT DPNP_FN_MAXIMUM DPNP_FN_MAXIMUM_EXT DPNP_FN_MEDIAN DPNP_FN_MEDIAN_EXT - DPNP_FN_MIN - DPNP_FN_MIN_EXT DPNP_FN_MINIMUM DPNP_FN_MINIMUM_EXT DPNP_FN_MODF @@ -373,12 +369,6 @@ Array manipulation routines cpdef dpnp_descriptor dpnp_repeat(dpnp_descriptor array1, repeats, axes=*) -""" -Statistics functions -""" -cpdef dpnp_descriptor dpnp_min(dpnp_descriptor a, axis) - - """ Sorting functions """ diff --git a/dpnp/dpnp_algo/dpnp_algo_statistics.pxi b/dpnp/dpnp_algo/dpnp_algo_statistics.pxi index 43463c7791d..34e0684fcbf 100644 --- a/dpnp/dpnp_algo/dpnp_algo_statistics.pxi +++ b/dpnp/dpnp_algo/dpnp_algo_statistics.pxi @@ -38,9 +38,7 @@ and the rest of the library __all__ += [ "dpnp_average", "dpnp_correlate", - "dpnp_max", "dpnp_median", - "dpnp_min", "dpnp_nanvar", "dpnp_std", "dpnp_var", @@ -64,16 +62,6 @@ ctypedef c_dpctl.DPCTLSyclEventRef(*custom_statistic_1in_1out_func_ptr_t)(c_dpct void *, void * , shape_elem_type * , size_t, shape_elem_type * , size_t, const c_dpctl.DPCTLEventVectorRef) -ctypedef c_dpctl.DPCTLSyclEventRef(*custom_statistic_1in_1out_func_ptr_t_max)(c_dpctl.DPCTLSyclQueueRef, - void *, - void * , - const size_t, - shape_elem_type * , - size_t, - shape_elem_type * , - size_t, - const c_dpctl.DPCTLEventVectorRef) - cdef utils.dpnp_descriptor call_fptr_custom_std_var_1in_1out(DPNPFuncName fptr_name, utils.dpnp_descriptor x1, ddof): cdef shape_type_c x1_shape = x1.shape @@ -177,86 +165,6 @@ cpdef utils.dpnp_descriptor dpnp_correlate(utils.dpnp_descriptor x1, utils.dpnp_ return result -cdef utils.dpnp_descriptor _dpnp_max(utils.dpnp_descriptor x1, _axis_, shape_type_c result_shape): - cdef shape_type_c x1_shape = x1.shape - cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype) - - cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_MAX_EXT, param1_type, param1_type) - - x1_obj = x1.get_array() - - # create result array with type given by FPTR data - cdef utils.dpnp_descriptor result = utils.create_output_descriptor(result_shape, - kernel_data.return_type, - None, - device=x1_obj.sycl_device, - usm_type=x1_obj.usm_type, - sycl_queue=x1_obj.sycl_queue) - - result_sycl_queue = result.get_array().sycl_queue - - cdef c_dpctl.SyclQueue q = result_sycl_queue - cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref() - - cdef custom_statistic_1in_1out_func_ptr_t_max func = kernel_data.ptr - cdef shape_type_c axis - cdef Py_ssize_t axis_size = 0 - cdef shape_type_c axis_ = axis - - if _axis_ is not None: - axis = _axis_ - axis_.reserve(len(axis)) - for shape_it in axis: - axis_.push_back(shape_it) - axis_size = len(axis) - - cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref, - x1.get_data(), - result.get_data(), - result.size, - x1_shape.data(), - x1.ndim, - axis_.data(), - axis_size, - NULL) # dep_events_ref - - with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref) - c_dpctl.DPCTLEvent_Delete(event_ref) - - return result - - -cpdef utils.dpnp_descriptor dpnp_max(utils.dpnp_descriptor x1, axis): - cdef shape_type_c x1_shape = x1.shape - cdef shape_type_c output_shape - - if axis is None: - axis_ = axis - output_shape.push_back(1) - else: - if isinstance(axis, int): - if axis < 0: - axis_ = tuple([x1.ndim - axis]) - else: - axis_ = tuple([axis]) - else: - _axis_ = [] - for i in range(len(axis)): - if axis[i] < 0: - _axis_.append(x1.ndim - axis[i]) - else: - _axis_.append(axis[i]) - axis_ = tuple(_axis_) - - output_shape.resize(len(x1_shape) - len(axis_), 0) - ind = 0 - for id, shape_axis in enumerate(x1_shape): - if id not in axis_: - output_shape[ind] = shape_axis - ind += 1 - - return _dpnp_max(x1, axis_, output_shape) - cpdef utils.dpnp_descriptor dpnp_median(utils.dpnp_descriptor array1): cdef shape_type_c x1_shape = array1.shape cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(array1.dtype) @@ -301,85 +209,6 @@ cpdef utils.dpnp_descriptor dpnp_median(utils.dpnp_descriptor array1): return result -cpdef utils.dpnp_descriptor _dpnp_min(utils.dpnp_descriptor x1, _axis_, shape_type_c shape_output): - cdef shape_type_c x1_shape = x1.shape - cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype) - - cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_MIN_EXT, param1_type, param1_type) - - x1_obj = x1.get_array() - - cdef utils.dpnp_descriptor result = utils.create_output_descriptor(shape_output, - kernel_data.return_type, - None, - device=x1_obj.sycl_device, - usm_type=x1_obj.usm_type, - sycl_queue=x1_obj.sycl_queue) - - result_sycl_queue = result.get_array().sycl_queue - - cdef c_dpctl.SyclQueue q = result_sycl_queue - cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref() - - cdef custom_statistic_1in_1out_func_ptr_t_max func = kernel_data.ptr - cdef shape_type_c axis - cdef Py_ssize_t axis_size = 0 - cdef shape_type_c axis_ = axis - - if _axis_ is not None: - axis = _axis_ - axis_.reserve(len(axis)) - for shape_it in axis: - if shape_it < 0: - raise ValueError("DPNP algo::_dpnp_min(): Negative values in 'shape' are not allowed") - axis_.push_back(shape_it) - axis_size = len(axis) - - cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref, - x1.get_data(), - result.get_data(), - result.size, - x1_shape.data(), - x1.ndim, - axis_.data(), - axis_size, - NULL) # dep_events_ref - - with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref) - c_dpctl.DPCTLEvent_Delete(event_ref) - - return result - - -cpdef utils.dpnp_descriptor dpnp_min(utils.dpnp_descriptor x1, axis): - cdef shape_type_c x1_shape = x1.shape - cdef shape_type_c shape_output - - if axis is None: - axis_ = axis - shape_output = (1,) - else: - if isinstance(axis, int): - if axis < 0: - axis_ = tuple([x1.ndim - axis]) - else: - axis_ = tuple([axis]) - else: - _axis_ = [] - for i in range(len(axis)): - if axis[i] < 0: - _axis_.append(x1.ndim - axis[i]) - else: - _axis_.append(axis[i]) - axis_ = tuple(_axis_) - - for id, shape_axis in enumerate(x1_shape): - if id not in axis_: - shape_output.push_back(shape_axis) - - return _dpnp_min(x1, axis_, shape_output) - - cpdef utils.dpnp_descriptor dpnp_nanvar(utils.dpnp_descriptor arr, ddof): # dpnp_isnan does not support USM array as input in comparison to dpnp.isnan cdef utils.dpnp_descriptor mask_arr = dpnp.get_dpnp_descriptor(dpnp.isnan(arr.get_pyobj()), diff --git a/dpnp/dpnp_algo/dpnp_elementwise_common.py b/dpnp/dpnp_algo/dpnp_elementwise_common.py index 61cc1991720..eb0f63abbc0 100644 --- a/dpnp/dpnp_algo/dpnp_elementwise_common.py +++ b/dpnp/dpnp_algo/dpnp_elementwise_common.py @@ -1,5 +1,3 @@ -# cython: language_level=3 -# distutils: language = c++ # -*- coding: utf-8 -*- # ***************************************************************************** # Copyright (c) 2023, Intel Corporation diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index ce80de31be5..ca16bb9a70c 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -25,7 +25,6 @@ # ***************************************************************************** import dpctl.tensor as dpt -import numpy import dpnp @@ -939,9 +938,9 @@ def max( self, axis=None, out=None, - keepdims=numpy._NoValue, - initial=numpy._NoValue, - where=numpy._NoValue, + keepdims=False, + initial=None, + where=True, ): """Return the maximum along an axis.""" @@ -956,9 +955,9 @@ def min( self, axis=None, out=None, - keepdims=numpy._NoValue, - initial=numpy._NoValue, - where=numpy._NoValue, + keepdims=False, + initial=None, + where=True, ): """Return the minimum along a given axis.""" diff --git a/dpnp/dpnp_iface_mathematical.py b/dpnp/dpnp_iface_mathematical.py index 650c0478e17..2639564c38d 100644 --- a/dpnp/dpnp_iface_mathematical.py +++ b/dpnp/dpnp_iface_mathematical.py @@ -1400,9 +1400,9 @@ def maximum( :obj:`dpnp.fmax` : Element-wise maximum of two arrays, ignores NaNs. :obj:`dpnp.amax` : The maximum value of an array along a given axis, propagates NaNs. :obj:`dpnp.nanmax` : The maximum value of an array along a given axis, ignores NaNs. - :obj:`dpnp.fmin` : Element-wise minimum of two arrays, ignores NaNs. - :obj:`dpnp.amix` : The minimum value of an array along a given axis, propagates NaNs. - :obj:`dpnp.nanmix` : The minimum value of an array along a given axis, ignores NaNs. + :obj:`dpnp.fmax` : Element-wise maximum of two arrays, ignores NaNs. + :obj:`dpnp.amax` : The maximum value of an array along a given axis, propagates NaNs. + :obj:`dpnp.nanmax` : The maximum value of an array along a given axis, ignores NaNs. Examples -------- @@ -1479,9 +1479,9 @@ def minimum( :obj:`dpnp.fmin` : Element-wise minimum of two arrays, ignores NaNs. :obj:`dpnp.amin` : The minimum value of an array along a given axis, propagates NaNs. :obj:`dpnp.nanmin` : The minimum value of an array along a given axis, ignores NaNs. - :obj:`dpnp.fmax` : Element-wise maximum of two arrays, ignores NaNs. - :obj:`dpnp.amax` : The maximum value of an array along a given axis, propagates NaNs. - :obj:`dpnp.nanmax` : The maximum value of an array along a given axis, ignores NaNs. + :obj:`dpnp.fmin` : Element-wise minimum of two arrays, ignores NaNs. + :obj:`dpnp.amin` : The minimum value of an array along a given axis, propagates NaNs. + :obj:`dpnp.nanmin` : The minimum value of an array along a given axis, ignores NaNs. Examples -------- diff --git a/dpnp/dpnp_iface_statistics.py b/dpnp/dpnp_iface_statistics.py index c7254ad6d01..2374d25a9f2 100644 --- a/dpnp/dpnp_iface_statistics.py +++ b/dpnp/dpnp_iface_statistics.py @@ -1,5 +1,3 @@ -# cython: language_level=3 -# distutils: language = c++ # -*- coding: utf-8 -*- # ***************************************************************************** # Copyright (c) 2016-2023, Intel Corporation @@ -352,69 +350,65 @@ def histogram(a, bins=10, range=None, density=None, weights=None): ) -def max(x1, axis=None, out=None, keepdims=False, initial=None, where=True): +def max(a, axis=None, out=None, keepdims=False, initial=None, where=True): """ Return the maximum of an array or maximum along an axis. + Returns + ------- + out : dpnp.ndarray + Maximum of `a`. + Limitations ----------- - Input array is supported as :obj:`dpnp.ndarray`. + Input array `a` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. + Parameters `out`, `where`, and `initial` are supported only with their default values. Otherwise the function will be executed sequentially on CPU. - Parameter `out` is supported only with default value ``None``. Input array data types are limited by supported DPNP :ref:`Data types`. + See Also + -------- + :obj:`dpnp.min` : Return tha minimum of an array. + :obj:`dpnp.maximum` : Element-wise maximum of two arrays, propagates NaNs. + :obj:`dpnp.fmax` : Element-wise maximum of two arrays, ignores NaNs. + :obj:`dpnp.amax` : The maximum value of an array along a given axis, propagates NaNs. + :obj:`dpnp.nanmax` : The maximum value of an array along a given axis, ignores NaNs. + Examples -------- >>> import dpnp as np >>> a = np.arange(4).reshape((2,2)) - >>> a.shape - (2, 2) - >>> [i for i in a] - [0, 1, 2, 3] + >>> a + array([[0, 1], + [2, 3]]) >>> np.max(a) - 3 + array(3) - """ + >>> np.max(a, axis=0) # Maxima along the first axis + array([2, 3]) + >>> np.max(a, axis=1) # Maxima along the second axis + array([1, 3]) - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False) - if x1_desc: - # Negative values in 'shape' are not allowed in input array - # 306-322 check on negative and duplicate axis - isaxis = True - if axis is not None: - if dpnp.isscalar(axis): - if axis < 0: - isaxis = False - else: - for val in axis: - if val < 0: - isaxis = False - break - if isaxis: - for i in range(len(axis)): - for j in range(len(axis)): - if i != j: - if axis[i] == axis[j]: - isaxis = False - break - - if not isaxis: - pass - elif out is not None: - pass - elif keepdims: - pass - elif initial is not None: - pass - elif where is not True: - pass - else: - result_obj = dpnp_max(x1_desc, axis).get_pyobj() - result = dpnp.convert_single_elem_array_to_scalar(result_obj) + >>> b = np.arange(5, dtype=float) + >>> b[2] = np.NaN + >>> np.max(b) + array(nan) - return result + """ + + if out is not None: + pass + elif initial is not None: + pass + elif where is not True: + pass + else: + dpt_array = dpnp.get_usm_ndarray(a) + return dpnp_array._create_from_usm_ndarray( + dpt.max(dpt_array, axis=axis, keepdims=keepdims) + ) - return call_origin(numpy.max, x1, axis, out, keepdims, initial, where) + return call_origin(numpy.max, a, axis, out, keepdims, initial, where) def mean(x, /, *, axis=None, dtype=None, keepdims=False, out=None, where=True): @@ -564,47 +558,67 @@ def median(x1, axis=None, out=None, overwrite_input=False, keepdims=False): return call_origin(numpy.median, x1, axis, out, overwrite_input, keepdims) -def min(x1, axis=None, out=None, keepdims=False, initial=None, where=True): +def min(a, axis=None, out=None, keepdims=False, initial=None, where=True): """ - Return the minimum along a given axis. + Return the minimum of an array or maximum along an axis. + + For full documentation refer to :obj:`numpy.min`. + + Returns + ------- + out : dpnp.ndarray + Minimum of `a`. Limitations ----------- - Input array is supported as :obj:`dpnp.ndarray`. + Input array `a` is only supported as either :class:`dpnp.ndarray` or :class:`dpctl.tensor.usm_ndarray`. + Parameters `out`, `where`, and `initial` are supported only with their default values. Otherwise the function will be executed sequentially on CPU. - Parameter `out` is supported only with default value ``None``. Input array data types are limited by supported DPNP :ref:`Data types`. + See Also + -------- + :obj:`dpnp.max` : Return tha maximum of an array. + :obj:`dpnp.minimum` : Element-wise minimum of two arrays, propagates NaNs. + :obj:`dpnp.fmin` : Element-wise minimum of two arrays, ignores NaNs. + :obj:`dpnp.amin` : The minimum value of an array along a given axis, propagates NaNs. + :obj:`dpnp.nanmin` : The minimum value of an array along a given axis, ignores NaNs. + Examples -------- >>> import dpnp as np >>> a = np.arange(4).reshape((2,2)) - >>> a.shape - (2, 2) - >>> [i for i in a] - [0, 1, 2, 3] + >>> a + array([[0, 1], + [2, 3]]) >>> np.min(a) - 0 + array(0) - """ + >>> np.min(a, axis=0) # Minima along the first axis + array([0, 1]) + >>> np.min(a, axis=1) # Minima along the second axis + array([0, 2]) - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False) - if x1_desc: - if out is not None: - pass - elif keepdims: - pass - elif initial is not None: - pass - elif where is not True: - pass - else: - result_obj = dpnp_min(x1_desc, axis).get_pyobj() - result = dpnp.convert_single_elem_array_to_scalar(result_obj) + >>> b = np.arange(5, dtype=float) + >>> b[2] = np.NaN + >>> np.min(b) + array(nan) - return result + """ + + if out is not None: + pass + elif initial is not None: + pass + elif where is not True: + pass + else: + dpt_array = dpnp.get_usm_ndarray(a) + return dpnp_array._create_from_usm_ndarray( + dpt.min(dpt_array, axis=axis, keepdims=keepdims) + ) - return call_origin(numpy.min, x1, axis, out, keepdims, initial, where) + return call_origin(numpy.min, a, axis, out, keepdims, initial, where) def nanvar(x1, axis=None, dtype=None, out=None, ddof=0, keepdims=False): @@ -619,7 +633,7 @@ def nanvar(x1, axis=None, dtype=None, out=None, ddof=0, keepdims=False): Parameter `axis` is supported only with default value ``None``. Parameter `dtype` is supported only with default value ``None``. Parameter `out` is supported only with default value ``None``. - Parameter `keepdims` is supported only with default value ``numpy._NoValue``. + Parameter `keepdims` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. """ @@ -665,7 +679,7 @@ def std(x1, axis=None, dtype=None, out=None, ddof=0, keepdims=False): Parameter `axis` is supported only with default value ``None``. Parameter `dtype` is supported only with default value ``None``. Parameter `out` is supported only with default value ``None``. - Parameter `keepdims` is supported only with default value ``numpy._NoValue``. + Parameter `keepdims` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. Input array data types are limited by supported DPNP :ref:`Data types`. @@ -723,7 +737,7 @@ def var(x1, axis=None, dtype=None, out=None, ddof=0, keepdims=False): Parameter `axis` is supported only with default value ``None``. Parameter `dtype` is supported only with default value ``None``. Parameter `out` is supported only with default value ``None``. - Parameter `keepdims` is supported only with default value ``numpy._NoValue``. + Parameter `keepdims` is supported only with default value ``False``. Otherwise the function will be executed sequentially on CPU. Input array data types are limited by supported DPNP :ref:`Data types`. diff --git a/tests/skipped_tests.tbl b/tests/skipped_tests.tbl index c1b4fcb37c9..8fdb70ddf4d 100644 --- a/tests/skipped_tests.tbl +++ b/tests/skipped_tests.tbl @@ -121,7 +121,6 @@ tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayFlatte tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayFlatten::test_flatten_order_copied tests/third_party/cupy/core_tests/test_ndarray_copy_and_view.py::TestArrayFlatten::test_flatten_order_transposed -tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestArrayReduction::test_min_nan tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestArrayReduction::test_ptp_all tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestArrayReduction::test_ptp_all_keepdims tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestArrayReduction::test_ptp_axis0 @@ -806,14 +805,10 @@ tests/third_party/cupy/random_tests/test_sample.py::TestMultinomial_param_4_{siz tests/third_party/cupy/random_tests/test_sample.py::TestRandint2::test_bound_float1 tests/third_party/cupy/random_tests/test_sample.py::TestRandint2::test_goodness_of_fit tests/third_party/cupy/random_tests/test_sample.py::TestRandint2::test_goodness_of_fit_2 - tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers2::test_bound_1 tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers2::test_bound_2 tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers2::test_goodness_of_fit tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers2::test_goodness_of_fit_2 -tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers::test_high_is_none -tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers::test_normal -tests/third_party/cupy/random_tests/test_sample.py::TestRandomIntegers::test_size_is_not_none tests/third_party/cupy/sorting_tests/test_count.py::TestCount::test_count_nonzero tests/third_party/cupy/sorting_tests/test_count.py::TestCount::test_count_nonzero_int_axis diff --git a/tests/skipped_tests_gpu.tbl b/tests/skipped_tests_gpu.tbl index e1be1a64647..301fbc456ae 100644 --- a/tests/skipped_tests_gpu.tbl +++ b/tests/skipped_tests_gpu.tbl @@ -273,6 +273,7 @@ tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestCubReduction_pa tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestCubReduction_param_6_{order='F', shape=(10, 20, 30)}::test_cub_min tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestCubReduction_param_7_{order='F', shape=(10, 20, 30, 40)}::test_cub_max tests/third_party/cupy/core_tests/test_ndarray_reduction.py::TestCubReduction_param_7_{order='F', shape=(10, 20, 30, 40)}::test_cub_min + tests/third_party/cupy/creation_tests/test_basic.py::TestBasicReshape_param_0_{shape=4}::test_empty_like_K_strides_reshape tests/third_party/cupy/creation_tests/test_basic.py::TestBasicReshape_param_1_{shape=(4,)}::test_empty_like_K_strides_reshape tests/third_party/cupy/creation_tests/test_basic.py::TestBasicReshape_param_2_{shape=(4, 2)}::test_empty_like_K_strides_reshape diff --git a/tests/test_statistics.py b/tests/test_statistics.py index 4020c6c21d7..2a8a3e3269a 100644 --- a/tests/test_statistics.py +++ b/tests/test_statistics.py @@ -21,18 +21,23 @@ def test_median(dtype, size): assert_allclose(dpnp_res, np_res) -@pytest.mark.usefixtures("allow_fall_back_on_numpy") -@pytest.mark.parametrize("axis", [0, 1, -1, 2, -2, (1, 2), (0, -2)]) -@pytest.mark.parametrize( - "dtype", get_all_dtypes(no_none=True, no_bool=True, no_complex=True) -) -def test_max(axis, dtype): +@pytest.mark.parametrize("axis", [None, 0, 1, -1, 2, -2, (1, 2), (0, -2)]) +@pytest.mark.parametrize("keepdims", [False, True]) +@pytest.mark.parametrize("dtype", get_all_dtypes(no_none=True, no_bool=True)) +def test_max_min(axis, keepdims, dtype): a = numpy.arange(768, dtype=dtype).reshape((4, 4, 6, 8)) ia = dpnp.array(a) - np_res = numpy.max(a, axis=axis) - dpnp_res = dpnp.max(ia, axis=axis) + np_res = numpy.max(a, axis=axis, keepdims=keepdims) + dpnp_res = dpnp.max(ia, axis=axis, keepdims=keepdims) + + assert dpnp_res.shape == np_res.shape + assert_allclose(dpnp_res, np_res) + + np_res = numpy.min(a, axis=axis, keepdims=keepdims) + dpnp_res = dpnp.min(ia, axis=axis, keepdims=keepdims) + assert dpnp_res.shape == np_res.shape assert_allclose(dpnp_res, np_res) diff --git a/tests/test_sycl_queue.py b/tests/test_sycl_queue.py index e7e649de290..136ff1c7181 100644 --- a/tests/test_sycl_queue.py +++ b/tests/test_sycl_queue.py @@ -259,6 +259,8 @@ def test_meshgrid(device_x, device_y): pytest.param("log10", [1.0, 2.0, 4.0, 7.0]), pytest.param("log1p", [1.0e-10, 1.0, 2.0, 4.0, 7.0]), pytest.param("log2", [1.0, 2.0, 4.0, 7.0]), + pytest.param("max", [1.0, 2.0, 4.0, 7.0]), + pytest.param("min", [1.0, 2.0, 4.0, 7.0]), pytest.param("nancumprod", [1.0, dpnp.nan]), pytest.param("nancumsum", [1.0, dpnp.nan]), pytest.param("nanprod", [1.0, dpnp.nan]), diff --git a/tests/test_usm_type.py b/tests/test_usm_type.py index 122f7165158..260feade4e0 100644 --- a/tests/test_usm_type.py +++ b/tests/test_usm_type.py @@ -348,6 +348,8 @@ def test_meshgrid(usm_type_x, usm_type_y): pytest.param("log10", [1.0, 2.0, 4.0, 7.0]), pytest.param("log1p", [1.0e-10, 1.0, 2.0, 4.0, 7.0]), pytest.param("log2", [1.0, 2.0, 4.0, 7.0]), + pytest.param("max", [1.0, 2.0, 4.0, 7.0]), + pytest.param("min", [1.0, 2.0, 4.0, 7.0]), pytest.param("negative", [1.0, 0.0, -1.0]), pytest.param("positive", [1.0, 0.0, -1.0]), pytest.param("proj", [complex(1.0, 2.0), complex(dp.inf, -1.0)]),