@@ -1336,8 +1336,45 @@ impl<T: Element, D> PyArray<T, D> {
1336
1336
self . as_borrowed ( ) . cast ( is_fortran) . map ( Bound :: into_gil_ref)
1337
1337
}
1338
1338
1339
+ /// A view of `self` with a different order of axes determined by `axes`.
1340
+ ///
1341
+ /// If `axes` is `None`, the order of axes is reversed which corresponds to the standard matrix transpose.
1342
+ ///
1343
+ /// See also [`numpy.transpose`][numpy-transpose] and [`PyArray_Transpose`][PyArray_Transpose].
1344
+ ///
1345
+ /// # Example
1346
+ ///
1347
+ /// ```
1348
+ /// use numpy::prelude::*;
1349
+ /// use numpy::PyArray;
1350
+ /// use pyo3::Python;
1351
+ /// use ndarray::array;
1352
+ ///
1353
+ /// Python::with_gil(|py| {
1354
+ /// let array = array![[0, 1, 2], [3, 4, 5]].into_pyarray(py);
1355
+ ///
1356
+ /// let array = array.permute(Some([1, 0])).unwrap();
1357
+ ///
1358
+ /// assert_eq!(array.readonly().as_array(), array![[0, 3], [1, 4], [2, 5]]);
1359
+ /// });
1360
+ /// ```
1361
+ ///
1362
+ /// [numpy-transpose]: https://numpy.org/doc/stable/reference/generated/numpy.transpose.html
1363
+ /// [PyArray_Transpose]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Transpose
1364
+ pub fn permute < ' py , ID : IntoDimension > (
1365
+ & ' py self ,
1366
+ axes : Option < ID > ,
1367
+ ) -> PyResult < & ' py PyArray < T , D > > {
1368
+ self . as_borrowed ( ) . permute ( axes) . map ( Bound :: into_gil_ref)
1369
+ }
1370
+
1371
+ /// Special case of [`permute`][Self::permute] which reverses the order the axes.
1372
+ pub fn transpose < ' py > ( & ' py self ) -> PyResult < & ' py PyArray < T , D > > {
1373
+ self . as_borrowed ( ) . transpose ( ) . map ( Bound :: into_gil_ref)
1374
+ }
1375
+
1339
1376
/// Construct a new array which has same values as self,
1340
- /// but has different dimensions specified by `dims `
1377
+ /// but has different dimensions specified by `shape `
1341
1378
/// and a possibly different memory order specified by `order`.
1342
1379
///
1343
1380
/// See also [`numpy.reshape`][numpy-reshape] and [`PyArray_Newshape`][PyArray_Newshape].
@@ -1365,21 +1402,21 @@ impl<T: Element, D> PyArray<T, D> {
1365
1402
/// [PyArray_Newshape]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Newshape
1366
1403
pub fn reshape_with_order < ' py , ID : IntoDimension > (
1367
1404
& ' py self ,
1368
- dims : ID ,
1405
+ shape : ID ,
1369
1406
order : NPY_ORDER ,
1370
1407
) -> PyResult < & ' py PyArray < T , ID :: Dim > > {
1371
1408
self . as_borrowed ( )
1372
- . reshape_with_order ( dims , order)
1409
+ . reshape_with_order ( shape , order)
1373
1410
. map ( Bound :: into_gil_ref)
1374
1411
}
1375
1412
1376
1413
/// Special case of [`reshape_with_order`][Self::reshape_with_order] which keeps the memory order the same.
1377
1414
#[ inline( always) ]
1378
1415
pub fn reshape < ' py , ID : IntoDimension > (
1379
1416
& ' py self ,
1380
- dims : ID ,
1417
+ shape : ID ,
1381
1418
) -> PyResult < & ' py PyArray < T , ID :: Dim > > {
1382
- self . as_borrowed ( ) . reshape ( dims ) . map ( Bound :: into_gil_ref)
1419
+ self . as_borrowed ( ) . reshape ( shape ) . map ( Bound :: into_gil_ref)
1383
1420
}
1384
1421
1385
1422
/// Extends or truncates the dimensions of an array.
@@ -1414,8 +1451,8 @@ impl<T: Element, D> PyArray<T, D> {
1414
1451
///
1415
1452
/// [ndarray-resize]: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.resize.html
1416
1453
/// [PyArray_Resize]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Resize
1417
- pub unsafe fn resize < ID : IntoDimension > ( & self , dims : ID ) -> PyResult < ( ) > {
1418
- self . as_borrowed ( ) . resize ( dims )
1454
+ pub unsafe fn resize < ID : IntoDimension > ( & self , newshape : ID ) -> PyResult < ( ) > {
1455
+ self . as_borrowed ( ) . resize ( newshape )
1419
1456
}
1420
1457
}
1421
1458
@@ -1879,8 +1916,45 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> {
1879
1916
where
1880
1917
T : Element ;
1881
1918
1882
- /// Construct a new array which has same values as self,
1883
- /// but has different dimensions specified by `dims`
1919
+ /// A view of `self` with a different order of axes determined by `axes`.
1920
+ ///
1921
+ /// If `axes` is `None`, the order of axes is reversed which corresponds to the standard matrix transpose.
1922
+ ///
1923
+ /// See also [`numpy.transpose`][numpy-transpose] and [`PyArray_Transpose`][PyArray_Transpose].
1924
+ ///
1925
+ /// # Example
1926
+ ///
1927
+ /// ```
1928
+ /// use numpy::prelude::*;
1929
+ /// use numpy::PyArray;
1930
+ /// use pyo3::Python;
1931
+ /// use ndarray::array;
1932
+ ///
1933
+ /// Python::with_gil(|py| {
1934
+ /// let array = array![[0, 1, 2], [3, 4, 5]].into_pyarray_bound(py);
1935
+ ///
1936
+ /// let array = array.permute(Some([1, 0])).unwrap();
1937
+ ///
1938
+ /// assert_eq!(array.readonly().as_array(), array![[0, 3], [1, 4], [2, 5]]);
1939
+ /// });
1940
+ /// ```
1941
+ ///
1942
+ /// [numpy-transpose]: https://numpy.org/doc/stable/reference/generated/numpy.transpose.html
1943
+ /// [PyArray_Transpose]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Transpose
1944
+ fn permute < ID : IntoDimension > ( & self , axes : Option < ID > ) -> PyResult < Bound < ' py , PyArray < T , D > > >
1945
+ where
1946
+ T : Element ;
1947
+
1948
+ /// Special case of [`permute`][Self::permute] which reverses the order the axes.
1949
+ fn transpose ( & self ) -> PyResult < Bound < ' py , PyArray < T , D > > >
1950
+ where
1951
+ T : Element ,
1952
+ {
1953
+ self . permute :: < ( ) > ( None )
1954
+ }
1955
+
1956
+ /// Construct a new array which has same values as `self`,
1957
+ /// but has different dimensions specified by `shape`
1884
1958
/// and a possibly different memory order specified by `order`.
1885
1959
///
1886
1960
/// See also [`numpy.reshape`][numpy-reshape] and [`PyArray_Newshape`][PyArray_Newshape].
@@ -1908,19 +1982,19 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> {
1908
1982
/// [PyArray_Newshape]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Newshape
1909
1983
fn reshape_with_order < ID : IntoDimension > (
1910
1984
& self ,
1911
- dims : ID ,
1985
+ shape : ID ,
1912
1986
order : NPY_ORDER ,
1913
1987
) -> PyResult < Bound < ' py , PyArray < T , ID :: Dim > > >
1914
1988
where
1915
1989
T : Element ;
1916
1990
1917
1991
/// Special case of [`reshape_with_order`][Self::reshape_with_order] which keeps the memory order the same.
1918
1992
#[ inline( always) ]
1919
- fn reshape < ID : IntoDimension > ( & self , dims : ID ) -> PyResult < Bound < ' py , PyArray < T , ID :: Dim > > >
1993
+ fn reshape < ID : IntoDimension > ( & self , shape : ID ) -> PyResult < Bound < ' py , PyArray < T , ID :: Dim > > >
1920
1994
where
1921
1995
T : Element ,
1922
1996
{
1923
- self . reshape_with_order ( dims , NPY_ORDER :: NPY_ANYORDER )
1997
+ self . reshape_with_order ( shape , NPY_ORDER :: NPY_ANYORDER )
1924
1998
}
1925
1999
1926
2000
/// Extends or truncates the dimensions of an array.
@@ -1955,7 +2029,7 @@ pub trait PyArrayMethods<'py, T, D>: PyUntypedArrayMethods<'py> {
1955
2029
///
1956
2030
/// [ndarray-resize]: https://numpy.org/doc/stable/reference/generated/numpy.ndarray.resize.html
1957
2031
/// [PyArray_Resize]: https://numpy.org/doc/stable/reference/c-api/array.html#c.PyArray_Resize
1958
- unsafe fn resize < ID : IntoDimension > ( & self , dims : ID ) -> PyResult < ( ) >
2032
+ unsafe fn resize < ID : IntoDimension > ( & self , newshape : ID ) -> PyResult < ( ) >
1959
2033
where
1960
2034
T : Element ;
1961
2035
@@ -2249,55 +2323,66 @@ impl<'py, T, D> PyArrayMethods<'py, T, D> for Bound<'py, PyArray<T, D>> {
2249
2323
if is_fortran { -1 } else { 0 } ,
2250
2324
)
2251
2325
} ;
2252
- if !ptr. is_null ( ) {
2253
- Ok ( unsafe { Bound :: from_owned_ptr ( self . py ( ) , ptr) . downcast_into_unchecked ( ) } )
2254
- } else {
2255
- Err ( PyErr :: fetch ( self . py ( ) ) )
2326
+ unsafe {
2327
+ Bound :: from_owned_ptr_or_err ( self . py ( ) , ptr) . map ( |ob| ob. downcast_into_unchecked ( ) )
2256
2328
}
2257
2329
}
2258
2330
2331
+ fn permute < ID : IntoDimension > ( & self , axes : Option < ID > ) -> PyResult < Bound < ' py , PyArray < T , D > > > {
2332
+ let mut axes = axes. map ( |axes| axes. into_dimension ( ) ) ;
2333
+ let mut axes = axes. as_mut ( ) . map ( |axes| axes. to_npy_dims ( ) ) ;
2334
+ let axes = axes
2335
+ . as_mut ( )
2336
+ . map_or_else ( ptr:: null_mut, |axes| axes as * mut npyffi:: PyArray_Dims ) ;
2337
+
2338
+ let py = self . py ( ) ;
2339
+ let ptr = unsafe { PY_ARRAY_API . PyArray_Transpose ( py, self . as_array_ptr ( ) , axes) } ;
2340
+ unsafe { Bound :: from_owned_ptr_or_err ( py, ptr) . map ( |ob| ob. downcast_into_unchecked ( ) ) }
2341
+ }
2342
+
2259
2343
fn reshape_with_order < ID : IntoDimension > (
2260
2344
& self ,
2261
- dims : ID ,
2345
+ shape : ID ,
2262
2346
order : NPY_ORDER ,
2263
2347
) -> PyResult < Bound < ' py , PyArray < T , ID :: Dim > > >
2264
2348
where
2265
2349
T : Element ,
2266
2350
{
2267
- let mut dims = dims. into_dimension ( ) ;
2268
- let mut dims = dims. to_npy_dims ( ) ;
2351
+ let mut shape = shape. into_dimension ( ) ;
2352
+ let mut shape = shape. to_npy_dims ( ) ;
2353
+
2354
+ let py = self . py ( ) ;
2269
2355
let ptr = unsafe {
2270
2356
PY_ARRAY_API . PyArray_Newshape (
2271
- self . py ( ) ,
2357
+ py ,
2272
2358
self . as_array_ptr ( ) ,
2273
- & mut dims as * mut npyffi:: PyArray_Dims ,
2359
+ & mut shape as * mut npyffi:: PyArray_Dims ,
2274
2360
order,
2275
2361
)
2276
2362
} ;
2277
- if !ptr. is_null ( ) {
2278
- Ok ( unsafe { Bound :: from_owned_ptr ( self . py ( ) , ptr) . downcast_into_unchecked ( ) } )
2279
- } else {
2280
- Err ( PyErr :: fetch ( self . py ( ) ) )
2281
- }
2363
+ unsafe { Bound :: from_owned_ptr_or_err ( py, ptr) . map ( |ob| ob. downcast_into_unchecked ( ) ) }
2282
2364
}
2283
2365
2284
- unsafe fn resize < ID : IntoDimension > ( & self , dims : ID ) -> PyResult < ( ) >
2366
+ unsafe fn resize < ID : IntoDimension > ( & self , newshape : ID ) -> PyResult < ( ) >
2285
2367
where
2286
2368
T : Element ,
2287
2369
{
2288
- let mut dims = dims. into_dimension ( ) ;
2289
- let mut dims = dims. to_npy_dims ( ) ;
2370
+ let mut newshape = newshape. into_dimension ( ) ;
2371
+ let mut newshape = newshape. to_npy_dims ( ) ;
2372
+
2373
+ let py = self . py ( ) ;
2290
2374
let res = PY_ARRAY_API . PyArray_Resize (
2291
- self . py ( ) ,
2375
+ py ,
2292
2376
self . as_array_ptr ( ) ,
2293
- & mut dims as * mut npyffi:: PyArray_Dims ,
2377
+ & mut newshape as * mut npyffi:: PyArray_Dims ,
2294
2378
1 ,
2295
2379
NPY_ORDER :: NPY_ANYORDER ,
2296
2380
) ;
2381
+
2297
2382
if !res. is_null ( ) {
2298
2383
Ok ( ( ) )
2299
2384
} else {
2300
- Err ( PyErr :: fetch ( self . py ( ) ) )
2385
+ Err ( PyErr :: fetch ( py ) )
2301
2386
}
2302
2387
}
2303
2388
0 commit comments