Skip to content

Commit 573a1d2

Browse files
authored
Merge branch 'master' into update-changelog
2 parents dc3a012 + 22b1c73 commit 573a1d2

File tree

6 files changed

+350
-16
lines changed

6 files changed

+350
-16
lines changed

dpnp/dpnp_iface_manipulation.py

Lines changed: 204 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040

4141
import math
42+
import operator
4243

4344
import dpctl.tensor as dpt
4445
import numpy
@@ -77,9 +78,11 @@
7778
"ravel",
7879
"repeat",
7980
"reshape",
81+
"resize",
8082
"result_type",
8183
"roll",
8284
"rollaxis",
85+
"rot90",
8386
"row_stack",
8487
"shape",
8588
"size",
@@ -1522,6 +1525,7 @@ def fliplr(m):
15221525
--------
15231526
:obj:`dpnp.flipud` : Flip an array vertically (axis=0).
15241527
:obj:`dpnp.flip` : Flip array in one or more dimensions.
1528+
:obj:`dpnp.rot90` : Rotate array counterclockwise.
15251529
15261530
Examples
15271531
--------
@@ -1572,6 +1576,7 @@ def flipud(m):
15721576
--------
15731577
:obj:`dpnp.fliplr` : Flip array in the left/right direction.
15741578
:obj:`dpnp.flip` : Flip array in one or more dimensions.
1579+
:obj:`dpnp.rot90` : Rotate array counterclockwise.
15751580
15761581
Examples
15771582
--------
@@ -1985,7 +1990,8 @@ def reshape(a, /, newshape, order="C", copy=None):
19851990
If ``False``, the result array can never be a copy
19861991
and a ValueError exception will be raised in case the copy is necessary.
19871992
If ``None``, the result array will reuse existing memory buffer of `a`
1988-
if possible and copy otherwise. Default: None.
1993+
if possible and copy otherwise.
1994+
Default: ``None``.
19891995
19901996
Returns
19911997
-------
@@ -2004,14 +2010,14 @@ def reshape(a, /, newshape, order="C", copy=None):
20042010
20052011
Examples
20062012
--------
2007-
>>> import dpnp as dp
2008-
>>> a = dp.array([[1, 2, 3], [4, 5, 6]])
2009-
>>> dp.reshape(a, 6)
2013+
>>> import dpnp as np
2014+
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
2015+
>>> np.reshape(a, 6)
20102016
array([1, 2, 3, 4, 5, 6])
2011-
>>> dp.reshape(a, 6, order='F')
2017+
>>> np.reshape(a, 6, order='F')
20122018
array([1, 4, 2, 5, 3, 6])
20132019
2014-
>>> dp.reshape(a, (3, -1)) # the unspecified value is inferred to be 2
2020+
>>> np.reshape(a, (3, -1)) # the unspecified value is inferred to be 2
20152021
array([[1, 2],
20162022
[3, 4],
20172023
[5, 6]])
@@ -2031,6 +2037,91 @@ def reshape(a, /, newshape, order="C", copy=None):
20312037
return dpnp_array._create_from_usm_ndarray(usm_res)
20322038

20332039

2040+
def resize(a, new_shape):
2041+
"""
2042+
Return a new array with the specified shape.
2043+
2044+
If the new array is larger than the original array, then the new array is
2045+
filled with repeated copies of `a`. Note that this behavior is different
2046+
from ``a.resize(new_shape)`` which fills with zeros instead of repeated
2047+
copies of `a`.
2048+
2049+
For full documentation refer to :obj:`numpy.resize`.
2050+
2051+
Parameters
2052+
----------
2053+
a : {dpnp.ndarray, usm_ndarray}
2054+
Array to be resized.
2055+
new_shape : {int, tuple or list of ints}
2056+
Shape of resized array.
2057+
2058+
Returns
2059+
-------
2060+
out : dpnp.ndarray
2061+
The new array is formed from the data in the old array, repeated
2062+
if necessary to fill out the required number of elements. The
2063+
data are repeated iterating over the array in C-order.
2064+
2065+
See Also
2066+
--------
2067+
:obj:`dpnp.ndarray.resize` : Resize an array in-place.
2068+
:obj:`dpnp.reshape` : Reshape an array without changing the total size.
2069+
:obj:`dpnp.pad` : Enlarge and pad an array.
2070+
:obj:`dpnp.repeat` : Repeat elements of an array.
2071+
2072+
Notes
2073+
-----
2074+
When the total size of the array does not change :obj:`dpnp.reshape` should
2075+
be used. In most other cases either indexing (to reduce the size) or
2076+
padding (to increase the size) may be a more appropriate solution.
2077+
2078+
Warning: This functionality does **not** consider axes separately,
2079+
i.e. it does not apply interpolation/extrapolation.
2080+
It fills the return array with the required number of elements, iterating
2081+
over `a` in C-order, disregarding axes (and cycling back from the start if
2082+
the new shape is larger). This functionality is therefore not suitable to
2083+
resize images, or data where each axis represents a separate and distinct
2084+
entity.
2085+
2086+
Examples
2087+
--------
2088+
>>> import dpnp as np
2089+
>>> a = np.array([[0, 1], [2, 3]])
2090+
>>> np.resize(a, (2, 3))
2091+
array([[0, 1, 2],
2092+
[3, 0, 1]])
2093+
>>> np.resize(a, (1, 4))
2094+
array([[0, 1, 2, 3]])
2095+
>>> np.resize(a, (2, 4))
2096+
array([[0, 1, 2, 3],
2097+
[0, 1, 2, 3]])
2098+
2099+
"""
2100+
2101+
dpnp.check_supported_arrays_type(a)
2102+
if a.ndim == 0:
2103+
return dpnp.full_like(a, a, shape=new_shape)
2104+
2105+
if isinstance(new_shape, (int, numpy.integer)):
2106+
new_shape = (new_shape,)
2107+
2108+
new_size = 1
2109+
for dim_length in new_shape:
2110+
if dim_length < 0:
2111+
raise ValueError("all elements of `new_shape` must be non-negative")
2112+
new_size *= dim_length
2113+
2114+
a_size = a.size
2115+
if a_size == 0 or new_size == 0:
2116+
# First case must zero fill. The second would have repeats == 0.
2117+
return dpnp.zeros_like(a, shape=new_shape)
2118+
2119+
repeats = -(-new_size // a_size) # ceil division
2120+
a = dpnp.concatenate((dpnp.ravel(a),) * repeats)[:new_size]
2121+
2122+
return a.reshape(new_shape)
2123+
2124+
20342125
def result_type(*arrays_and_dtypes):
20352126
"""
20362127
result_type(*arrays_and_dtypes)
@@ -2052,16 +2143,16 @@ def result_type(*arrays_and_dtypes):
20522143
20532144
Examples
20542145
--------
2055-
>>> import dpnp as dp
2056-
>>> a = dp.arange(3, dtype=dp.int64)
2057-
>>> b = dp.arange(7, dtype=dp.int32)
2058-
>>> dp.result_type(a, b)
2146+
>>> import dpnp as np
2147+
>>> a = np.arange(3, dtype=np.int64)
2148+
>>> b = np.arange(7, dtype=np.int32)
2149+
>>> np.result_type(a, b)
20592150
dtype('int64')
20602151
2061-
>>> dp.result_type(dp.int64, dp.complex128)
2152+
>>> np.result_type(np.int64, np.complex128)
20622153
dtype('complex128')
20632154
2064-
>>> dp.result_type(dp.ones(10, dtype=dp.float32), dp.float64)
2155+
>>> np.result_type(np.ones(10, dtype=np.float32), np.float64)
20652156
dtype('float64')
20662157
20672158
"""
@@ -2200,6 +2291,107 @@ def rollaxis(x, axis, start=0):
22002291
return dpnp.moveaxis(usm_array, source=axis, destination=start)
22012292

22022293

2294+
def rot90(m, k=1, axes=(0, 1)):
2295+
"""
2296+
Rotate an array by 90 degrees in the plane specified by axes.
2297+
2298+
Rotation direction is from the first towards the second axis.
2299+
This means for a 2D array with the default `k` and `axes`, the
2300+
rotation will be counterclockwise.
2301+
2302+
For full documentation refer to :obj:`numpy.rot90`.
2303+
2304+
Parameters
2305+
----------
2306+
m : {dpnp.ndarray, usm_ndarray}
2307+
Array of two or more dimensions.
2308+
k : integer, optional
2309+
Number of times the array is rotated by 90 degrees.
2310+
Default: ``1``.
2311+
axes : (2,) array_like of ints, optional
2312+
The array is rotated in the plane defined by the axes.
2313+
Axes must be different.
2314+
Default: ``(0, 1)``.
2315+
2316+
Returns
2317+
-------
2318+
out : dpnp.ndarray
2319+
A rotated view of `m`.
2320+
2321+
See Also
2322+
--------
2323+
:obj:`dpnp.flip` : Reverse the order of elements in an array along
2324+
the given axis.
2325+
:obj:`dpnp.fliplr` : Flip an array horizontally.
2326+
:obj:`dpnp.flipud` : Flip an array vertically.
2327+
2328+
Notes
2329+
-----
2330+
``rot90(m, k=1, axes=(1,0))`` is the reverse of
2331+
``rot90(m, k=1, axes=(0,1))``.
2332+
2333+
``rot90(m, k=1, axes=(1,0))`` is equivalent to
2334+
``rot90(m, k=-1, axes=(0,1))``.
2335+
2336+
Examples
2337+
--------
2338+
>>> import dpnp as np
2339+
>>> m = np.array([[1, 2], [3, 4]])
2340+
>>> m
2341+
array([[1, 2],
2342+
[3, 4]])
2343+
>>> np.rot90(m)
2344+
array([[2, 4],
2345+
[1, 3]])
2346+
>>> np.rot90(m, 2)
2347+
array([[4, 3],
2348+
[2, 1]])
2349+
>>> m = np.arange(8).reshape((2, 2, 2))
2350+
>>> np.rot90(m, 1, (1, 2))
2351+
array([[[1, 3],
2352+
[0, 2]],
2353+
[[5, 7],
2354+
[4, 6]]])
2355+
2356+
"""
2357+
2358+
dpnp.check_supported_arrays_type(m)
2359+
k = operator.index(k)
2360+
2361+
m_ndim = m.ndim
2362+
if m_ndim < 2:
2363+
raise ValueError("Input must be at least 2-d.")
2364+
2365+
if len(axes) != 2:
2366+
raise ValueError("len(axes) must be 2.")
2367+
2368+
if axes[0] == axes[1] or abs(axes[0] - axes[1]) == m_ndim:
2369+
raise ValueError("Axes must be different.")
2370+
2371+
if not (-m_ndim <= axes[0] < m_ndim and -m_ndim <= axes[1] < m_ndim):
2372+
raise ValueError(
2373+
f"Axes={axes} out of range for array of ndim={m_ndim}."
2374+
)
2375+
2376+
k %= 4
2377+
if k == 0:
2378+
return m[:]
2379+
if k == 2:
2380+
return dpnp.flip(dpnp.flip(m, axes[0]), axes[1])
2381+
2382+
axes_list = list(range(0, m_ndim))
2383+
(axes_list[axes[0]], axes_list[axes[1]]) = (
2384+
axes_list[axes[1]],
2385+
axes_list[axes[0]],
2386+
)
2387+
2388+
if k == 1:
2389+
return dpnp.transpose(dpnp.flip(m, axes[1]), axes_list)
2390+
2391+
# k == 3
2392+
return dpnp.flip(dpnp.transpose(m, axes_list), axes[1])
2393+
2394+
22032395
def shape(a):
22042396
"""
22052397
Return the shape of an array.

0 commit comments

Comments
 (0)