Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Update dpnp.ediff1d() function #1970

Merged
merged 15 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions dpnp/backend/include/dpnp_iface_fptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,9 @@ enum class DPNPFuncName : size_t
DPNP_FN_DOT, /**< Used in numpy.dot() impl */
DPNP_FN_DOT_EXT, /**< Used in numpy.dot() impl, requires extra parameters */
DPNP_FN_EDIFF1D, /**< Used in numpy.ediff1d() impl */
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
DPNP_FN_EDIFF1D_EXT, /**< Used in numpy.ediff1d() impl, requires extra
parameters */
DPNP_FN_ERF, /**< Used in scipy.special.erf impl */
DPNP_FN_ERF_EXT, /**< Used in scipy.special.erf impl, requires extra
parameters */
DPNP_FN_ERF, /**< Used in scipy.special.erf impl */
DPNP_FN_ERF_EXT, /**< Used in scipy.special.erf impl, requires extra
parameters */
DPNP_FN_INITVAL, /**< Used in numpy ones, ones_like, zeros, zeros_like impls
*/
DPNP_FN_INITVAL_EXT, /**< Used in numpy ones, ones_like, zeros, zeros_like
Expand Down
25 changes: 0 additions & 25 deletions dpnp/backend/kernels/dpnp_krnl_mathematical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,22 +152,6 @@ void (*dpnp_ediff1d_default_c)(void *,
const size_t *) =
dpnp_ediff1d_c<_DataType_input, _DataType_output>;

template <typename _DataType_input, typename _DataType_output>
DPCTLSyclEventRef (*dpnp_ediff1d_ext_c)(DPCTLSyclQueueRef,
void *,
const size_t,
const size_t,
const shape_elem_type *,
const shape_elem_type *,
const void *,
const size_t,
const size_t,
const shape_elem_type *,
const shape_elem_type *,
const size_t *,
const DPCTLEventVectorRef) =
dpnp_ediff1d_c<_DataType_input, _DataType_output>;

template <typename _KernelNameSpecialization1,
typename _KernelNameSpecialization2>
class dpnp_modf_c_kernel;
Expand Down Expand Up @@ -269,15 +253,6 @@ void func_map_init_mathematical(func_map_t &fmap)
fmap[DPNPFuncName::DPNP_FN_EDIFF1D][eft_DBL][eft_DBL] = {
eft_DBL, (void *)dpnp_ediff1d_default_c<double, double>};

fmap[DPNPFuncName::DPNP_FN_EDIFF1D_EXT][eft_INT][eft_INT] = {
eft_LNG, (void *)dpnp_ediff1d_ext_c<int32_t, int64_t>};
fmap[DPNPFuncName::DPNP_FN_EDIFF1D_EXT][eft_LNG][eft_LNG] = {
eft_LNG, (void *)dpnp_ediff1d_ext_c<int64_t, int64_t>};
fmap[DPNPFuncName::DPNP_FN_EDIFF1D_EXT][eft_FLT][eft_FLT] = {
eft_FLT, (void *)dpnp_ediff1d_ext_c<float, float>};
fmap[DPNPFuncName::DPNP_FN_EDIFF1D_EXT][eft_DBL][eft_DBL] = {
eft_DBL, (void *)dpnp_ediff1d_ext_c<double, double>};

fmap[DPNPFuncName::DPNP_FN_MODF][eft_INT][eft_INT] = {
eft_DBL, (void *)dpnp_modf_default_c<int32_t, double>};
fmap[DPNPFuncName::DPNP_FN_MODF][eft_LNG][eft_LNG] = {
Expand Down
1 change: 0 additions & 1 deletion dpnp/dpnp_algo/dpnp_algo.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na
cdef enum DPNPFuncName "DPNPFuncName":
DPNP_FN_CHOOSE_EXT
DPNP_FN_CORRELATE_EXT
DPNP_FN_EDIFF1D_EXT
DPNP_FN_ERF_EXT
DPNP_FN_MEDIAN_EXT
DPNP_FN_MODF_EXT
Expand Down
57 changes: 0 additions & 57 deletions dpnp/dpnp_algo/dpnp_algo_mathematical.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ and the rest of the library
# NO IMPORTs here. All imports must be placed into main "dpnp_algo.pyx" file

__all__ += [
"dpnp_ediff1d",
"dpnp_modf",
]

Expand All @@ -46,62 +45,6 @@ ctypedef c_dpctl.DPCTLSyclEventRef(*fptr_1in_2out_t)(c_dpctl.DPCTLSyclQueueRef,
const c_dpctl.DPCTLEventVectorRef)


cpdef utils.dpnp_descriptor dpnp_ediff1d(utils.dpnp_descriptor x1):

if x1.size <= 1:
return utils.dpnp_descriptor(dpnp.empty(0, dtype=x1.dtype)) # TODO need to call dpnp_empty instead

# Convert type (x1.dtype) to C enum DPNPFuncType
cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype)

# get the FPTR data structure
cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_EDIFF1D_EXT, param1_type, param1_type)

result_type = dpnp_DPNPFuncType_to_dtype( < size_t > kernel_data.return_type)

# Currently shape and strides of the input array are not took into account for the function ediff1d
cdef shape_type_c x1_shape = (x1.size,)
cdef shape_type_c x1_strides = utils.strides_to_vector(None, x1_shape)

x1_obj = x1.get_array()

cdef shape_type_c result_shape = (x1.size - 1,)
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)

cdef shape_type_c result_strides = utils.strides_to_vector(result.strides, result_shape)

result_sycl_queue = result.get_array().sycl_queue

cdef c_dpctl.SyclQueue q = <c_dpctl.SyclQueue> result_sycl_queue
cdef c_dpctl.DPCTLSyclQueueRef q_ref = q.get_queue_ref()

# Call FPTR function
cdef fptr_1in_1out_strides_t func = <fptr_1in_1out_strides_t > kernel_data.ptr
cdef c_dpctl.DPCTLSyclEventRef event_ref = func(q_ref,
result.get_data(),
result.size,
result.ndim,
result_shape.data(),
result_strides.data(),
x1.get_data(),
x1.size,
x1.ndim,
x1_shape.data(),
x1_strides.data(),
NULL,
NULL) # dep_events_ref

with nogil: c_dpctl.DPCTLEvent_WaitAndThrow(event_ref)
c_dpctl.DPCTLEvent_Delete(event_ref)

return result


cpdef tuple dpnp_modf(utils.dpnp_descriptor x1):
""" Convert string type names (array.dtype) to C enum DPNPFuncType """
cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(x1.dtype)
Expand Down
119 changes: 90 additions & 29 deletions dpnp/dpnp_iface_mathematical.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@
import dpnp.backend.extensions.vm._vm_impl as vmi

from .backend.extensions.sycl_ext import _sycl_ext_impl
from .dpnp_algo import (
dpnp_ediff1d,
dpnp_modf,
)
from .dpnp_algo import dpnp_modf
from .dpnp_algo.dpnp_elementwise_common import (
DPNPAngle,
DPNPBinaryFunc,
Expand Down Expand Up @@ -1268,49 +1265,113 @@ def diff(a, n=1, axis=-1, prepend=None, append=None):
)


def ediff1d(x1, to_end=None, to_begin=None):
def ediff1d(ary, to_end=None, to_begin=None):
"""
The differences between consecutive elements of an array.

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

Limitations
-----------
Parameter `x1`is supported as :class:`dpnp.ndarray`.
Keyword arguments `to_end` and `to_begin` are currently supported only
with default values `None`.
Otherwise the function will be executed sequentially on CPU.
Input array data types are limited by supported DPNP :ref:`Data types`.
Parameters
----------
ary : {dpnp.ndarray, usm_ndarray}
If necessary, will be flattened before the differences are taken.
to_end : {array_like}, optional
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
Number(s) to append at the end of the returned differences.
Default: ``None``.
to_begin : {array_like}, optional
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
Number(s) to prepend at the beginning of the returned differences.
Default: ``None``.

Returns
-------
out : dpnp.ndarray
The differences. Loosely, this is ``ary.flat[1:] - ary.flat[:-1]``.
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

See Also
--------
:obj:`dpnp.diff` : Calculate the n-th discrete difference along the given
axis.
:obj:`dpnp.gradient` : Return the gradient of an N-dimensional array.

Examples
--------
>>> import dpnp as np
>>> a = np.array([1, 2, 4, 7, 0])
>>> result = np.ediff1d(a)
>>> [x for x in result]
[1, 2, 3, -7]
>>> b = np.array([[1, 2, 4], [1, 6, 24]])
>>> result = np.ediff1d(b)
>>> [x for x in result]
[1, 2, -3, 5, 18]
>>> x = np.array([1, 2, 4, 7, 0])
>>> np.ediff1d(x)
array([ 1, 2, 3, -7])

>>> np.ediff1d(x, to_begin=-99, to_end=np.array([88, 99]))
array([-99, 1, 2, 3, -7, 88, 99])

The returned array is always 1D.

>>> y = np.array([[1, 2, 4], [1, 6, 24]])
>>> np.ediff1d(y)
array([ 1, 2, -3, 5, 18])

"""

x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
if x1_desc:
if to_begin is not None:
pass
elif to_end is not None:
pass
else:
return dpnp_ediff1d(x1_desc).get_pyobj()
dpnp.check_supported_arrays_type(ary)
if ary.ndim > 1:
ary = ary.ravel()

ary_dtype = ary.dtype
ary_usm_type = ary.usm_type
ary_sycl_queue = ary.sycl_queue
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

# fast track default case
if to_begin is None and to_end is None:
return ary[1:] - ary[:-1]

if to_begin is None:
l_begin = 0
else:
to_begin = dpnp.asarray(
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
to_begin, usm_type=ary_usm_type, sycl_queue=ary_sycl_queue
)
if not dpnp.can_cast(to_begin, ary_dtype, casting="same_kind"):
raise TypeError(
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
"dtype of `to_begin` must be compatible "
"with input `ary` under the `same_kind` rule."
)

to_begin_ndim = to_begin.ndim

if to_begin_ndim > 1:
to_begin = to_begin.ravel()
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

l_begin = len(to_begin) if to_begin_ndim != 0 else 1
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

if to_end is None:
l_end = 0
else:
to_end = dpnp.asarray(
to_end, usm_type=ary_usm_type, sycl_queue=ary_sycl_queue
)
if not dpnp.can_cast(to_end, ary_dtype, casting="same_kind"):
raise TypeError(
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved
"dtype of `to_end` must be compatible "
"with input `ary` under the `same_kind` rule."
)

to_end_ndim = to_end.ndim

if to_end_ndim > 1:
to_end = to_end.ravel()
vlad-perevezentsev marked this conversation as resolved.
Show resolved Hide resolved

l_end = len(to_end) if to_end_ndim != 0 else 1

# calculating using in place operation
l_diff = max(len(ary) - 1, 0)
result = dpnp.empty_like(ary, shape=l_diff + l_begin + l_end)

if l_begin > 0:
result[:l_begin] = to_begin
if l_end > 0:
result[l_begin + l_diff :] = to_end
dpnp.subtract(ary[1:], ary[:-1], out=result[l_begin : l_begin + l_diff])

return call_origin(numpy.ediff1d, x1, to_end=to_end, to_begin=to_begin)
return result


_FABS_DOCSTRING = """
Expand Down
Loading
Loading