Skip to content

Commit 87163d0

Browse files
authored
add gradient function (#503)
* add gradient function
1 parent 995a37d commit 87163d0

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

dpnp/dpnp_algo/dpnp_algo_mathematical.pyx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ __all__ += [
5757
"dpnp_floor",
5858
"dpnp_floor_divide",
5959
"dpnp_fmod",
60+
"dpnp_gradient",
6061
'dpnp_hypot',
6162
"dpnp_maximum",
6263
"dpnp_minimum",
@@ -294,6 +295,27 @@ cpdef dparray dpnp_fmod(dparray x1, dparray x2):
294295
return call_fptr_2in_1out(DPNP_FN_FMOD, x1, x2, x1.shape)
295296

296297

298+
cpdef dparray dpnp_gradient(dparray y1, int dx=1):
299+
300+
size = y1.size
301+
302+
cdef dparray result = dparray(size, dtype=dpnp.float64)
303+
304+
cur = (y1[1] - y1[0]) / dx
305+
306+
result._setitem_scalar(0, cur)
307+
308+
cur = (y1[-1] - y1[-2]) / dx
309+
310+
result._setitem_scalar(size - 1, cur)
311+
312+
for i in range(1, size - 1):
313+
cur = (y1[i + 1] - y1[i - 1]) / (2 * dx)
314+
result._setitem_scalar(i, cur)
315+
316+
return result
317+
318+
297319
cpdef dparray dpnp_hypot(dparray x1, dparray x2):
298320
return call_fptr_2in_1out(DPNP_FN_HYPOT, x1, x2, x1.shape)
299321

dpnp/dpnp_iface_mathematical.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"fmax",
7070
"fmin",
7171
"fmod",
72+
"gradient",
7273
"maximum",
7374
"minimum",
7475
"mod",
@@ -795,6 +796,48 @@ def fmod(x1, x2, **kwargs):
795796
return call_origin(numpy.fmod, x1, x2, **kwargs)
796797

797798

799+
def gradient(y1, *varargs, **kwargs):
800+
"""
801+
Return the gradient of an array.
802+
803+
For full documentation refer to :obj:`numpy.gradient`.
804+
805+
Limitations
806+
-----------
807+
Parameter ``y1`` is supported as :obj:`dpnp.ndarray`.
808+
Argument ``varargs[0]`` is supported as `int`.
809+
Keyword arguments ``kwargs`` are currently unsupported.
810+
Otherwise the functions will be executed sequentially on CPU.
811+
Input array data types are limited by supported DPNP :ref:`Data types`.
812+
813+
Example
814+
-------
815+
>>> import dpnp as np
816+
>>> y = np.array([1, 2, 4, 7, 11, 16], dtype=float)
817+
>>> result = np.gradient(y)
818+
>>> [x for x in result]
819+
[1.0, 1.5, 2.5, 3.5, 4.5, 5.0]
820+
>>> result = np.gradient(y, 2)
821+
>>> [x for x in result]
822+
[0.5, 0.75, 1.25, 1.75, 2.25, 2.5]
823+
824+
"""
825+
if not use_origin_backend(y1) and not kwargs:
826+
if not isinstance(y1, dparray):
827+
pass
828+
elif len(varargs) > 1:
829+
pass
830+
elif len(varargs) == 1 and not isinstance(varargs[0], int):
831+
pass
832+
else:
833+
if len(varargs) == 0:
834+
return dpnp_gradient(y1)
835+
836+
return dpnp_gradient(y1, varargs[0])
837+
838+
return call_origin(numpy.gradient, y1, *varargs, **kwargs)
839+
840+
798841
def maximum(x1, x2, **kwargs):
799842
"""
800843
Element-wise maximum of array elements.

tests/test_mathematical.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,55 @@ def test_cross_3x3(self, x1, x2, axisa, axisb, axisc, axis):
215215
result = inp.cross(ix1_, ix2_, axisa, axisb, axisc, axis)
216216
expected = numpy.cross(x1_, x2_, axisa, axisb, axisc, axis)
217217
numpy.testing.assert_array_equal(expected, result)
218+
219+
220+
class TestGradient:
221+
222+
@pytest.mark.parametrize("array", [[2, 3, 6, 8, 4, 9],
223+
[3., 4., 7.5, 9.],
224+
[2, 6, 8, 10]])
225+
def test_gradient_y1(self, array):
226+
y1 = numpy.array(array)
227+
iy1 = inp.array(y1)
228+
229+
result = inp.gradient(iy1)
230+
expected = numpy.gradient(y1)
231+
numpy.testing.assert_array_equal(expected, result)
232+
233+
@pytest.mark.parametrize("array", [[2, 3, 6, 8, 4, 9],
234+
[3., 4., 7.5, 9.],
235+
[2, 6, 8, 10]])
236+
@pytest.mark.parametrize("dx", [2, 3.5])
237+
def test_gradient_y1_dx(self, array, dx):
238+
y1 = numpy.array(array)
239+
iy1 = inp.array(y1)
240+
241+
result = inp.gradient(iy1, dx)
242+
expected = numpy.gradient(y1, dx)
243+
numpy.testing.assert_array_equal(expected, result)
244+
245+
246+
class TestGradient:
247+
248+
@pytest.mark.parametrize("array", [[2, 3, 6, 8, 4, 9],
249+
[3., 4., 7.5, 9.],
250+
[2, 6, 8, 10]])
251+
def test_gradient_y1(self, array):
252+
y1 = numpy.array(array)
253+
iy1 = inp.array(y1)
254+
255+
result = inp.gradient(iy1)
256+
expected = numpy.gradient(y1)
257+
numpy.testing.assert_array_equal(expected, result)
258+
259+
@pytest.mark.parametrize("array", [[2, 3, 6, 8, 4, 9],
260+
[3., 4., 7.5, 9.],
261+
[2, 6, 8, 10]])
262+
@pytest.mark.parametrize("dx", [2, 3.5])
263+
def test_gradient_y1_dx(self, array, dx):
264+
y1 = numpy.array(array)
265+
iy1 = inp.array(y1)
266+
267+
result = inp.gradient(iy1, dx)
268+
expected = numpy.gradient(y1, dx)
269+
numpy.testing.assert_array_equal(expected, result)

0 commit comments

Comments
 (0)