Skip to content

Rework implementation of dpnp.unwrap function #1950

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

Merged
merged 10 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
39 changes: 28 additions & 11 deletions doc/reference/math.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Mathematical Functions
Mathematical functions
======================

.. https://docs.scipy.org/doc/numpy/reference/routines.math.html
Expand All @@ -14,10 +14,14 @@ Trigonometric functions
dpnp.cos
dpnp.tan
dpnp.arcsin
dpnp.asin
dpnp.arccos
dpnp.acos
dpnp.arctan
dpnp.atan
dpnp.hypot
dpnp.arctan2
dpnp.atan2
dpnp.degrees
dpnp.radians
dpnp.unwrap
Expand All @@ -37,8 +41,11 @@ Hyperbolic functions
dpnp.cosh
dpnp.tanh
dpnp.arcsinh
dpnp.asinh
dpnp.arccosh
dpnp.acosh
dpnp.arctanh
dpnp.atanh


Rounding
Expand All @@ -48,8 +55,8 @@ Rounding
:toctree: generated/
:nosignatures:

dpnp.around
dpnp.round
dpnp.around
dpnp.rint
dpnp.fix
dpnp.floor
Expand All @@ -68,15 +75,17 @@ Sums, products, differences
dpnp.sum
dpnp.nanprod
dpnp.nansum
dpnp.cumulative_sum
dpnp.cumulative_prod
dpnp.cumprod
dpnp.cumsum
dpnp.nancumprod
dpnp.nancumsum
dpnp.diff
dpnp.ediff1d
dpnp.gradient
dpnp.trapz
dpnp.cross
dpnp.trapezoid


Exponents and logarithms
Expand Down Expand Up @@ -127,6 +136,7 @@ Floating point routines

Rational routines
-----------------

.. autosummary::
:toctree: generated/
:nosignatures:
Expand All @@ -144,15 +154,17 @@ Arithmetic operations

dpnp.add
dpnp.reciprocal
dpnp.negative
dpnp.positive
dpnp.negative
dpnp.multiply
dpnp.divide
dpnp.power
dpnp.pow
dpnp.subtract
dpnp.true_divide
dpnp.floor_divide
dpnp.floor_power
dpnp.float_power

dpnp.fmod
dpnp.mod
dpnp.modf
Expand All @@ -175,7 +187,7 @@ Handling complex numbers
dpnp.proj


Extrema Finding
Extrema finding
---------------

.. autosummary::
Expand All @@ -187,6 +199,7 @@ Extrema Finding
dpnp.amax
dpnp.fmax
dpnp.nanmax

dpnp.minimum
dpnp.min
dpnp.amin
Expand All @@ -203,17 +216,21 @@ Miscellaneous

dpnp.convolve
dpnp.clip

dpnp.sqrt
dpnp.cbrt
dpnp.square
dpnp.rsqrt

dpnp.abs
dpnp.absolute
dpnp.fabs
dpnp.sign
dpnp.heaviside

dpnp.nan_to_num
dpnp.bartlett
dpnp.blackman
dpnp.hamming
dpnp.hanning
dpnp.kaiser
dpnp.real_if_close

dpnp.interp

dpnp.bitwise_count
1 change: 0 additions & 1 deletion dpnp/dpnp_algo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

set(dpnp_algo_pyx_deps
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_statistics.pxi
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_trigonometric.pxi
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_sorting.pxi
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_mathematical.pxi
${CMAKE_CURRENT_SOURCE_DIR}/dpnp_algo_indexing.pxi
Expand Down
1 change: 0 additions & 1 deletion dpnp/dpnp_algo/dpnp_algo.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ include "dpnp_algo_mathematical.pxi"
include "dpnp_algo_sorting.pxi"
include "dpnp_algo_special.pxi"
include "dpnp_algo_statistics.pxi"
include "dpnp_algo_trigonometric.pxi"


ctypedef c_dpctl.DPCTLSyclEventRef(*fptr_dpnp_flatten_t)(c_dpctl.DPCTLSyclQueueRef,
Expand Down
63 changes: 0 additions & 63 deletions dpnp/dpnp_algo/dpnp_algo_trigonometric.pxi

This file was deleted.

127 changes: 102 additions & 25 deletions dpnp/dpnp_iface_trigonometric.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,18 @@
"""

# pylint: disable=protected-access
# pylint: disable=c-extension-no-member
# pylint: disable=duplicate-code
# pylint: disable=no-name-in-module


import dpctl.tensor as dpt
import dpctl.tensor._tensor_elementwise_impl as ti
import dpctl.tensor._type_utils as dtu
import numpy

import dpnp
import dpnp.backend.extensions.ufunc._ufunc_impl as ufi
import dpnp.backend.extensions.vm._vm_impl as vmi

from .dpnp_algo import (
dpnp_unwrap,
)
from .dpnp_algo.dpnp_elementwise_common import DPNPBinaryFunc, DPNPUnaryFunc
from .dpnp_utils import call_origin
from .dpnp_utils.dpnp_utils_reduction import dpnp_wrap_reduction_call

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


def unwrap(x1, **kwargs):
"""
Unwrap by changing deltas between values to 2*pi complement.
def unwrap(p, discont=None, axis=-1, *, period=2 * dpnp.pi):
r"""
Unwrap by taking the complement of large deltas with respect to the period.

This unwraps a signal `p` by changing elements which have an absolute
difference from their predecessor of more than ``max(discont, period / 2)``
to their `period`-complementary values.

For the default case where `period` is :math:`2\pi` and `discont` is
:math:`\pi`, this unwraps a radian phase `p` such that adjacent differences
are never greater than :math:`\pi` by adding :math:`2k\pi` for some integer
:math:`k`.

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

Limitations
-----------
Input array is supported as :class:`dpnp.ndarray`.
Input array data types are limited by supported DPNP :ref:`Data types`.
Parameters
----------
p : {dpnp.ndarray, usm_ndarray}
Input array.
discont : {float, None}, optional
Maximum discontinuity between values, default is ``period / 2``. Values
below ``period / 2`` are treated as if they were ``period / 2``. To
have an effect different from the default, `discont` should be larger
than ``period / 2``.
Default: ``None``.
axis : int, optional
Axis along which unwrap will operate, default is the last axis.
Default: ``-1``.
period : float, optional
Size of the range over which the input wraps.
Default: ``2 * pi``.

Returns
-------
out : dpnp.ndarray
Output array.

See Also
--------
:obj:`dpnp.rad2deg` : Convert angles from radians to degrees.
:obj:`dpnp.deg2rad` : Convert angles from degrees to radians.

Notes
-----
If the discontinuity in `p` is smaller than ``period / 2``, but larger than
`discont`, no unwrapping is done because taking the complement would only
make the discontinuity larger.

Examples
--------
>>> import dpnp as np
>>> phase = np.linspace(0, np.pi, num=5)
>>> for i in range(3, 5):
>>> phase[i] += np.pi
>>> out = np.unwrap(phase)
>>> [i for i in out]
[0.0, 0.78539816, 1.57079633, 5.49778714, 6.28318531]
>>> phase[3:] += np.pi
>>> phase
array([0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531])
>>> np.unwrap(phase)
array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ])

>>> phase = np.array([0, 1, 2, -1, 0])
>>> np.unwrap(phase, period=4)
array([0, 1, 2, 3, 4])

>>> phase = np.array([1, 2, 3, 4, 5, 6, 1, 2, 3])
>>> np.unwrap(phase, period=6)
array([1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> phase = np.array([2, 3, 4, 5, 2, 3, 4, 5])
>>> np.unwrap(phase, period=4)
array([2, 3, 4, 5, 6, 7, 8, 9])

>>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180
>>> np.unwrap(phase_deg, period=360)
array([-180., -140., -100., -60., -20., 20., 60., 100., 140.,
180., 220., 260., 300., 340., 380., 420., 460., 500.,
540.])

"""

x1_desc = dpnp.get_dpnp_descriptor(x1, copy_when_nondefault_queue=False)
if kwargs:
pass
elif x1_desc:
return dpnp_unwrap(x1_desc).get_pyobj()
dpnp.check_supported_arrays_type(p)

return call_origin(numpy.unwrap, x1, **kwargs)
p_nd = p.ndim
p_diff = dpnp.diff(p, axis=axis)

if discont is None:
discont = period / 2

# full slices
slice1 = [slice(None, None)] * p_nd
slice1[axis] = slice(1, None)
slice1 = tuple(slice1)

dt = dpnp.result_type(p_diff, period)
if dpnp.issubdtype(dt, dpnp.integer):
interval_high, rem = divmod(period, 2)
boundary_ambiguous = rem == 0
else:
interval_high = period / 2
boundary_ambiguous = True
interval_low = -interval_high

ddmod = p_diff - interval_low
ddmod = dpnp.remainder(ddmod, period, out=ddmod)
ddmod += interval_low

if boundary_ambiguous:
mask = ddmod == interval_low
mask &= p_diff > 0
ddmod = dpnp.where(mask, interval_high, ddmod, out=ddmod)

ph_correct = dpnp.subtract(ddmod, p_diff, out=ddmod)
abs_p_diff = dpnp.abs(p_diff, out=p_diff)
ph_correct = dpnp.where(abs_p_diff < discont, 0, ph_correct, out=ph_correct)

up = dpnp.astype(p, dtype=dt, copy=True)
up[slice1] = p[slice1]
# TODO: replace, once dpctl-1757 resolved
# up[slice1] += ph_correct.cumsum(axis=axis)
up[slice1] += ph_correct.cumsum(axis=axis, dtype=dt)
return up
9 changes: 0 additions & 9 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,6 @@ tests/third_party/cupy/math_tests/test_misc.py::TestMisc::test_heaviside_nan_inf

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

tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_period
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_1dim_with_discont_and_period
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_axis
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_discont
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_without_axis
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_period
tests/third_party/cupy/math_tests/test_trigonometric.py::TestUnwrap::test_unwrap_2dim_with_discont_and_period

tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_0_{a_shape=(), b_shape=(), shape=(4, 3, 2)}::test_beta
tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_1_{a_shape=(), b_shape=(), shape=(3, 2)}::test_beta
tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsBeta_param_2_{a_shape=(), b_shape=(3, 2), shape=(4, 3, 2)}::test_beta
Expand Down
Loading
Loading