|
39 | 39 |
|
40 | 40 |
|
41 | 41 | import dpctl.tensor as dpt
|
| 42 | +import dpctl.tensor._accumulation as da |
42 | 43 | import dpctl.utils as du
|
43 | 44 | import numpy
|
44 | 45 | from numpy.core.numeric import (
|
@@ -855,42 +856,101 @@ def cumprod(x1, **kwargs):
|
855 | 856 | return call_origin(numpy.cumprod, x1, **kwargs)
|
856 | 857 |
|
857 | 858 |
|
858 |
| -def cumsum(x1, **kwargs): |
| 859 | +def cumsum(a, axis=None, dtype=None, out=None): |
859 | 860 | """
|
860 | 861 | Return the cumulative sum of the elements along a given axis.
|
861 | 862 |
|
862 | 863 | For full documentation refer to :obj:`numpy.cumsum`.
|
863 | 864 |
|
864 |
| - Limitations |
865 |
| - ----------- |
866 |
| - Parameter `x` is supported as :obj:`dpnp.ndarray`. |
867 |
| - Keyword argument `kwargs` is currently unsupported. |
868 |
| - Otherwise the function will be executed sequentially on CPU. |
869 |
| - Input array data types are limited by supported DPNP :ref:`Data types`. |
| 865 | + Parameters |
| 866 | + ---------- |
| 867 | + a : {dpnp.ndarray, usm_ndarray} |
| 868 | + Input array. |
| 869 | + axis : int, optional |
| 870 | + Axis along which the cumulative sum is computed. The default (``None``) |
| 871 | + is to compute the cumsum over the flattened array. |
| 872 | + dtype : dtype, optional |
| 873 | + Type of the returned array and of the accumulator in which the elements |
| 874 | + are summed. If `dtype` is not specified, it defaults to the dtype of |
| 875 | + `a`, unless `a` has an integer dtype with a precision less than that of |
| 876 | + the default platform integer. In that case, the default platform |
| 877 | + integer is used. |
| 878 | + out : {dpnp.ndarray, usm_ndarray}, optional |
| 879 | + Alternative output array in which to place the result. It must have the |
| 880 | + same shape and buffer length as the expected output but the type will |
| 881 | + be cast if necessary. |
| 882 | +
|
| 883 | + Returns |
| 884 | + ------- |
| 885 | + out : dpnp.ndarray |
| 886 | + A new array holding the result is returned unless `out` is specified, |
| 887 | + in which case a reference to `out` is returned. The result has the same |
| 888 | + size as `a`, and the same shape as `a` if `axis` is not ``None`` or `a` |
| 889 | + is a 1-d array. |
870 | 890 |
|
871 | 891 | See Also
|
872 | 892 | --------
|
873 |
| - :obj:`dpnp.diff` : Calculate the n-th discrete difference along the given axis. |
| 893 | + :obj:`dpnp.sum` : Sum array elements. |
| 894 | + :obj:`dpnp.diff` : Calculate the n-th discrete difference along given axis. |
874 | 895 |
|
875 | 896 | Examples
|
876 | 897 | --------
|
877 | 898 | >>> import dpnp as np
|
878 |
| - >>> a = np.array([1, 2, 4]) |
879 |
| - >>> result = np.cumsum(a) |
880 |
| - >>> [x for x in result] |
881 |
| - [1, 2, 7] |
882 |
| - >>> b = np.array([[1, 2, 3], [4, 5, 6]]) |
883 |
| - >>> result = np.cumsum(b) |
884 |
| - >>> [x for x in result] |
885 |
| - [1, 2, 6, 10, 15, 21] |
| 899 | + >>> a = np.array([[1, 2, 3], [4, 5, 6]]) |
| 900 | + >>> a |
| 901 | + array([[1, 2, 3], |
| 902 | + [4, 5, 6]]) |
| 903 | + >>> np.cumsum(a) |
| 904 | + array([ 1, 3, 6, 10, 15, 21]) |
| 905 | + >>> np.cumsum(a, dtype=float) # specifies type of output value(s) |
| 906 | + array([ 1., 3., 6., 10., 15., 21.]) |
| 907 | +
|
| 908 | + >>> np.cumsum(a, axis=0) # sum over rows for each of the 3 columns |
| 909 | + array([[1, 2, 3], |
| 910 | + [5, 7, 9]]) |
| 911 | + >>> np.cumsum(a, axis=1) # sum over columns for each of the 2 rows |
| 912 | + array([[ 1, 3, 6], |
| 913 | + [ 4, 9, 15]]) |
| 914 | +
|
| 915 | + ``cumsum(b)[-1]`` may not be equal to ``sum(b)`` |
| 916 | +
|
| 917 | + >>> b = np.array([1, 2e-9, 3e-9] * 10000) |
| 918 | + >>> b.cumsum().dtype == b.sum().dtype == np.float64 |
| 919 | + True |
| 920 | + >>> b.cumsum()[-1] == b.sum() |
| 921 | + array(False) |
886 | 922 |
|
887 | 923 | """
|
888 | 924 |
|
889 |
| - x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False) |
890 |
| - if x1_desc and not kwargs: |
891 |
| - return dpnp_cumsum(x1_desc).get_pyobj() |
| 925 | + dpnp.check_supported_arrays_type(a) |
| 926 | + if a.ndim > 1 and axis is None: |
| 927 | + usm_a = dpnp.ravel(a).get_array() |
| 928 | + else: |
| 929 | + usm_a = dpnp.get_usm_ndarray(a) |
| 930 | + |
| 931 | + input_out = out |
| 932 | + if out is None: |
| 933 | + usm_out = None |
| 934 | + else: |
| 935 | + dpnp.check_supported_arrays_type(out) |
| 936 | + if dpnp.issubdtype(out.dtype, dpnp.integer): |
| 937 | + int_dt = da._default_accumulation_dtype(out.dtype, out.sycl_queue) |
| 938 | + |
| 939 | + # create a copy if dtype mismatches default integer type |
| 940 | + out = dpnp.astype(out, dtype=int_dt, copy=False) |
892 | 941 |
|
893 |
| - return call_origin(numpy.cumsum, x1, **kwargs) |
| 942 | + usm_out = dpnp.get_usm_ndarray(out) |
| 943 | + |
| 944 | + res_usm = dpt.cumulative_sum(usm_a, axis=axis, dtype=dtype, out=usm_out) |
| 945 | + if out is None: |
| 946 | + return dpnp_array._create_from_usm_ndarray(res_usm) |
| 947 | + elif input_out is not out: |
| 948 | + dpnp.copyto(input_out, out, casting="unsafe") |
| 949 | + |
| 950 | + if not isinstance(input_out, dpnp_array): |
| 951 | + return dpnp_array._create_from_usm_ndarray(input_out) |
| 952 | + else: |
| 953 | + return out |
894 | 954 |
|
895 | 955 |
|
896 | 956 | def diff(a, n=1, axis=-1, prepend=None, append=None):
|
|
0 commit comments