Skip to content

Commit d2c623b

Browse files
antonwolfyvtavana
andauthored
Rework implementation of dpnp.unwrap function (#1950)
* Align doc page of Mathematical functions with numpy * Implement dpnp.unwrap() function * Enable muted tests * Add more tests * Resolve pre-commit issue * Apply suggestions from code review Co-authored-by: vtavana <120411540+vtavana@users.noreply.github.com> * Replace dpnp.copyto with dpnp.where --------- Co-authored-by: vtavana <120411540+vtavana@users.noreply.github.com>
1 parent 0c3dfe5 commit d2c623b

13 files changed

+221
-130
lines changed

doc/reference/math.rst

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Mathematical Functions
1+
Mathematical functions
22
======================
33

44
.. https://docs.scipy.org/doc/numpy/reference/routines.math.html
@@ -14,10 +14,14 @@ Trigonometric functions
1414
dpnp.cos
1515
dpnp.tan
1616
dpnp.arcsin
17+
dpnp.asin
1718
dpnp.arccos
19+
dpnp.acos
1820
dpnp.arctan
21+
dpnp.atan
1922
dpnp.hypot
2023
dpnp.arctan2
24+
dpnp.atan2
2125
dpnp.degrees
2226
dpnp.radians
2327
dpnp.unwrap
@@ -37,8 +41,11 @@ Hyperbolic functions
3741
dpnp.cosh
3842
dpnp.tanh
3943
dpnp.arcsinh
44+
dpnp.asinh
4045
dpnp.arccosh
46+
dpnp.acosh
4147
dpnp.arctanh
48+
dpnp.atanh
4249

4350

4451
Rounding
@@ -48,8 +55,8 @@ Rounding
4855
:toctree: generated/
4956
:nosignatures:
5057

51-
dpnp.around
5258
dpnp.round
59+
dpnp.around
5360
dpnp.rint
5461
dpnp.fix
5562
dpnp.floor
@@ -68,15 +75,17 @@ Sums, products, differences
6875
dpnp.sum
6976
dpnp.nanprod
7077
dpnp.nansum
78+
dpnp.cumulative_sum
79+
dpnp.cumulative_prod
7180
dpnp.cumprod
7281
dpnp.cumsum
7382
dpnp.nancumprod
7483
dpnp.nancumsum
7584
dpnp.diff
7685
dpnp.ediff1d
7786
dpnp.gradient
78-
dpnp.trapz
7987
dpnp.cross
88+
dpnp.trapezoid
8089

8190

8291
Exponents and logarithms
@@ -127,6 +136,7 @@ Floating point routines
127136

128137
Rational routines
129138
-----------------
139+
130140
.. autosummary::
131141
:toctree: generated/
132142
:nosignatures:
@@ -144,15 +154,17 @@ Arithmetic operations
144154

145155
dpnp.add
146156
dpnp.reciprocal
147-
dpnp.negative
148157
dpnp.positive
158+
dpnp.negative
149159
dpnp.multiply
150160
dpnp.divide
151161
dpnp.power
162+
dpnp.pow
152163
dpnp.subtract
153164
dpnp.true_divide
154165
dpnp.floor_divide
155-
dpnp.floor_power
166+
dpnp.float_power
167+
156168
dpnp.fmod
157169
dpnp.mod
158170
dpnp.modf
@@ -175,7 +187,7 @@ Handling complex numbers
175187
dpnp.proj
176188

177189

178-
Extrema Finding
190+
Extrema finding
179191
---------------
180192

181193
.. autosummary::
@@ -187,6 +199,7 @@ Extrema Finding
187199
dpnp.amax
188200
dpnp.fmax
189201
dpnp.nanmax
202+
190203
dpnp.minimum
191204
dpnp.min
192205
dpnp.amin
@@ -203,17 +216,21 @@ Miscellaneous
203216

204217
dpnp.convolve
205218
dpnp.clip
219+
206220
dpnp.sqrt
207221
dpnp.cbrt
208222
dpnp.square
209223
dpnp.rsqrt
224+
210225
dpnp.abs
211226
dpnp.absolute
212227
dpnp.fabs
213228
dpnp.sign
229+
dpnp.heaviside
230+
214231
dpnp.nan_to_num
215-
dpnp.bartlett
216-
dpnp.blackman
217-
dpnp.hamming
218-
dpnp.hanning
219-
dpnp.kaiser
232+
dpnp.real_if_close
233+
234+
dpnp.interp
235+
236+
dpnp.bitwise_count

dpnp/dpnp_algo/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11

22
set(dpnp_algo_pyx_deps
33
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_statistics.pxi
4-
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_trigonometric.pxi
54
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_sorting.pxi
65
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_mathematical.pxi
76
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_indexing.pxi

dpnp/dpnp_algo/dpnp_algo.pyx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ include "dpnp_algo_mathematical.pxi"
6363
include "dpnp_algo_sorting.pxi"
6464
include "dpnp_algo_special.pxi"
6565
include "dpnp_algo_statistics.pxi"
66-
include "dpnp_algo_trigonometric.pxi"
6766

6867

6968
ctypedef c_dpctl.DPCTLSyclEventRef(*fptr_dpnp_flatten_t)(c_dpctl.DPCTLSyclQueueRef,

dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi

Lines changed: 0 additions & 63 deletions
This file was deleted.

dpnp/dpnp_iface_trigonometric.py

Lines changed: 102 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,18 @@
3838
"""
3939

4040
# pylint: disable=protected-access
41-
# pylint: disable=c-extension-no-member
42-
# pylint: disable=duplicate-code
4341
# pylint: disable=no-name-in-module
4442

4543

4644
import dpctl.tensor as dpt
4745
import dpctl.tensor._tensor_elementwise_impl as ti
4846
import dpctl.tensor._type_utils as dtu
49-
import numpy
5047

5148
import dpnp
5249
import dpnp.backend.extensions.ufunc._ufunc_impl as ufi
5350
import dpnp.backend.extensions.vm._vm_impl as vmi
5451

55-
from .dpnp_algo import (
56-
dpnp_unwrap,
57-
)
5852
from .dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc
59-
from .dpnp_utils import call_origin
6053
from .dpnp_utils.dpnp_utils_reduction import dpnp_wrap_reduction_call
6154

6255
__all__ = [
@@ -2194,38 +2187,122 @@ def reduce_hypot(x, /, *, axis=None, dtype=None, keepdims=False, out=None):
21942187
)
21952188

21962189

2197-
def unwrap(x1, **kwargs):
2198-
"""
2199-
Unwrap by changing deltas between values to 2*pi complement.
2190+
def unwrap(p, discont=None, axis=-1, *, period=2 * dpnp.pi):
2191+
r"""
2192+
Unwrap by taking the complement of large deltas with respect to the period.
2193+
2194+
This unwraps a signal `p` by changing elements which have an absolute
2195+
difference from their predecessor of more than ``max(discont, period / 2)``
2196+
to their `period`-complementary values.
2197+
2198+
For the default case where `period` is :math:`2\pi` and `discont` is
2199+
:math:`\pi`, this unwraps a radian phase `p` such that adjacent differences
2200+
are never greater than :math:`\pi` by adding :math:`2k\pi` for some integer
2201+
:math:`k`.
22002202
22012203
For full documentation refer to :obj:`numpy.unwrap`.
22022204
2203-
Limitations
2204-
-----------
2205-
Input array is supported as :class:`dpnp.ndarray`.
2206-
Input array data types are limited by supported DPNP :ref:`Data types`.
2205+
Parameters
2206+
----------
2207+
p : {dpnp.ndarray, usm_ndarray}
2208+
Input array.
2209+
discont : {float, None}, optional
2210+
Maximum discontinuity between values, default is ``period / 2``. Values
2211+
below ``period / 2`` are treated as if they were ``period / 2``. To
2212+
have an effect different from the default, `discont` should be larger
2213+
than ``period / 2``.
2214+
Default: ``None``.
2215+
axis : int, optional
2216+
Axis along which unwrap will operate, default is the last axis.
2217+
Default: ``-1``.
2218+
period : float, optional
2219+
Size of the range over which the input wraps.
2220+
Default: ``2 * pi``.
2221+
2222+
Returns
2223+
-------
2224+
out : dpnp.ndarray
2225+
Output array.
22072226
22082227
See Also
22092228
--------
22102229
:obj:`dpnp.rad2deg` : Convert angles from radians to degrees.
22112230
:obj:`dpnp.deg2rad` : Convert angles from degrees to radians.
22122231
2232+
Notes
2233+
-----
2234+
If the discontinuity in `p` is smaller than ``period / 2``, but larger than
2235+
`discont`, no unwrapping is done because taking the complement would only
2236+
make the discontinuity larger.
2237+
22132238
Examples
22142239
--------
22152240
>>> import dpnp as np
22162241
>>> phase = np.linspace(0, np.pi, num=5)
2217-
>>> for i in range(3, 5):
2218-
>>> phase[i] += np.pi
2219-
>>> out = np.unwrap(phase)
2220-
>>> [i for i in out]
2221-
[0.0, 0.78539816, 1.57079633, 5.49778714, 6.28318531]
2242+
>>> phase[3:] += np.pi
2243+
>>> phase
2244+
array([0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531])
2245+
>>> np.unwrap(phase)
2246+
array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ])
2247+
2248+
>>> phase = np.array([0, 1, 2, -1, 0])
2249+
>>> np.unwrap(phase, period=4)
2250+
array([0, 1, 2, 3, 4])
2251+
2252+
>>> phase = np.array([1, 2, 3, 4, 5, 6, 1, 2, 3])
2253+
>>> np.unwrap(phase, period=6)
2254+
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
2255+
2256+
>>> phase = np.array([2, 3, 4, 5, 2, 3, 4, 5])
2257+
>>> np.unwrap(phase, period=4)
2258+
array([2, 3, 4, 5, 6, 7, 8, 9])
2259+
2260+
>>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180
2261+
>>> np.unwrap(phase_deg, period=360)
2262+
array([-180., -140., -100., -60., -20., 20., 60., 100., 140.,
2263+
180., 220., 260., 300., 340., 380., 420., 460., 500.,
2264+
540.])
22222265
22232266
"""
22242267

2225-
x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
2226-
if kwargs:
2227-
pass
2228-
elif x1_desc:
2229-
return dpnp_unwrap(x1_desc).get_pyobj()
2268+
dpnp.check_supported_arrays_type(p)
22302269

2231-
return call_origin(numpy.unwrap, x1, **kwargs)
2270+
p_nd = p.ndim
2271+
p_diff = dpnp.diff(p, axis=axis)
2272+
2273+
if discont is None:
2274+
discont = period / 2
2275+
2276+
# full slices
2277+
slice1 = [slice(None, None)] * p_nd
2278+
slice1[axis] = slice(1, None)
2279+
slice1 = tuple(slice1)
2280+
2281+
dt = dpnp.result_type(p_diff, period)
2282+
if dpnp.issubdtype(dt, dpnp.integer):
2283+
interval_high, rem = divmod(period, 2)
2284+
boundary_ambiguous = rem == 0
2285+
else:
2286+
interval_high = period / 2
2287+
boundary_ambiguous = True
2288+
interval_low = -interval_high
2289+
2290+
ddmod = p_diff - interval_low
2291+
ddmod = dpnp.remainder(ddmod, period, out=ddmod)
2292+
ddmod += interval_low
2293+
2294+
if boundary_ambiguous:
2295+
mask = ddmod == interval_low
2296+
mask &= p_diff > 0
2297+
ddmod = dpnp.where(mask, interval_high, ddmod, out=ddmod)
2298+
2299+
ph_correct = dpnp.subtract(ddmod, p_diff, out=ddmod)
2300+
abs_p_diff = dpnp.abs(p_diff, out=p_diff)
2301+
ph_correct = dpnp.where(abs_p_diff < discont, 0, ph_correct, out=ph_correct)
2302+
2303+
up = dpnp.astype(p, dtype=dt, copy=True)
2304+
up[slice1] = p[slice1]
2305+
# TODO: replace, once dpctl-1757 resolved
2306+
# up[slice1] += ph_correct.cumsum(axis=axis)
2307+
up[slice1] += ph_correct.cumsum(axis=axis, dtype=dt)
2308+
return up

tests/skipped_tests.tbl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_heaviside_nan_inf
247247

248248
tests/third_party/cupy/math_tests/test_rounding.py::TestRounding::test_fix
249249

250-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
251-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period
252-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont_and_period
253-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_axis
254-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_discont
255-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_without_axis
256-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_period
257-
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_discont_and_period
258-
259250
tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_0_{a_shape=(), b_shape=(), shape=(4, 3, 2)}::test_beta
260251
tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_1_{a_shape=(), b_shape=(), shape=(3, 2)}::test_beta
261252
tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_2_{a_shape=(), b_shape=(3, 2), shape=(4, 3, 2)}::test_beta

0 commit comments

Comments
 (0)