Skip to content

Commit 8501d7b

Browse files
committed
shape: Deprecate into_shape, add into_shape_with_order
into_shape_with_order: If an index ordering is not specified, the default is `RowMajor`. The operation will only succeed if the array's memory layout is compatible with the index ordering. into_shape: `.into_shape()` "moves" elements differently depending on if the input array is C-contig or F-contig, it follows the index order that corresponds to the memory order. Because of this, the method is deprecated. That reshapes depend on memory order is not intuitive.
1 parent 3f02ac2 commit 8501d7b

File tree

2 files changed

+115
-2
lines changed

2 files changed

+115
-2
lines changed

src/impl_methods.rs

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,10 +1885,84 @@ where
18851885
}
18861886
}
18871887

1888+
/// Transform the array into `shape`; any shape with the same number of
1889+
/// elements is accepted, but the source array must be contiguous.
1890+
///
1891+
/// If an index ordering is not specified, the default is `RowMajor`.
1892+
/// The operation will only succeed if the array's memory layout is compatible with
1893+
/// the index ordering.
1894+
///
1895+
/// Use `.to_shape()` instead for more flexible reshaping of arrays, which
1896+
/// allows copying elements if required.
1897+
///
1898+
/// **Errors** if the shapes don't have the same number of elements.<br>
1899+
/// **Errors** if order RowMajor is given but input is not c-contiguous.
1900+
/// **Errors** if order ColumnMajor is given but input is not f-contiguous.
1901+
///
1902+
/// If shape is not given: use memory layout of incoming array. Row major arrays are
1903+
/// reshaped using row major index ordering, column major arrays with column major index
1904+
/// ordering.
1905+
///
1906+
/// ```
1907+
/// use ndarray::{aview1, aview2};
1908+
/// use ndarray::Order;
1909+
///
1910+
/// assert!(
1911+
/// aview1(&[1., 2., 3., 4.]).into_shape_with_order((2, 2)).unwrap()
1912+
/// == aview2(&[[1., 2.],
1913+
/// [3., 4.]])
1914+
/// );
1915+
///
1916+
/// assert!(
1917+
/// aview1(&[1., 2., 3., 4.]).into_shape_with_order(((2, 2), Order::ColumnMajor)).unwrap()
1918+
/// == aview2(&[[1., 3.],
1919+
/// [2., 4.]])
1920+
/// );
1921+
/// ```
1922+
pub fn into_shape_with_order<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
1923+
where
1924+
E: ShapeArg,
1925+
{
1926+
let (shape, order) = shape.into_shape_and_order();
1927+
self.into_shape_with_order_impl(shape, order.unwrap_or(Order::RowMajor))
1928+
}
1929+
1930+
fn into_shape_with_order_impl<E>(self, shape: E, order: Order)
1931+
-> Result<ArrayBase<S, E>, ShapeError>
1932+
where
1933+
E: Dimension,
1934+
{
1935+
let shape = shape.into_dimension();
1936+
if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
1937+
return Err(error::incompatible_shapes(&self.dim, &shape));
1938+
}
1939+
1940+
// Check if contiguous, then we can change shape
1941+
unsafe {
1942+
// safe because arrays are contiguous and len is unchanged
1943+
match order {
1944+
Order::RowMajor if self.is_standard_layout() => {
1945+
Ok(self.with_strides_dim(shape.default_strides(), shape))
1946+
}
1947+
Order::ColumnMajor if self.raw_view().reversed_axes().is_standard_layout() => {
1948+
Ok(self.with_strides_dim(shape.fortran_strides(), shape))
1949+
}
1950+
_otherwise => Err(error::from_kind(error::ErrorKind::IncompatibleLayout))
1951+
}
1952+
}
1953+
}
1954+
18881955
/// Transform the array into `shape`; any shape with the same number of
18891956
/// elements is accepted, but the source array or view must be in standard
18901957
/// or column-major (Fortran) layout.
18911958
///
1959+
/// **Note** that `.into_shape()` "moves" elements differently depending on if the input array
1960+
/// is C-contig or F-contig, it follows the index order that corresponds to the memory order.
1961+
/// Prefer to use `.to_shape()` or `.into_shape_with_order()`.
1962+
///
1963+
/// Because of this, the method is deprecated. That reshapes depend on memory order is not
1964+
/// intuitive.
1965+
///
18921966
/// **Errors** if the shapes don't have the same number of elements.<br>
18931967
/// **Errors** if the input array is not c- or f-contiguous.
18941968
///
@@ -1901,6 +1975,7 @@ where
19011975
/// [3., 4.]])
19021976
/// );
19031977
/// ```
1978+
#[deprecated = "Use `.into_shape_with_order()` or `.to_shape()`"]
19041979
pub fn into_shape<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
19051980
where
19061981
E: IntoDimension,
@@ -1948,7 +2023,7 @@ where
19482023
self.into_shape_clone_order(shape, order)
19492024
}
19502025

1951-
pub fn into_shape_clone_order<E>(self, shape: E, order: Order)
2026+
fn into_shape_clone_order<E>(self, shape: E, order: Order)
19522027
-> Result<ArrayBase<S, E>, ShapeError>
19532028
where
19542029
S: DataOwned,
@@ -2020,7 +2095,7 @@ where
20202095
A: Clone,
20212096
E: IntoDimension,
20222097
{
2023-
return self.clone().into_shape_clone(shape).unwrap();
2098+
//return self.clone().into_shape_clone(shape).unwrap();
20242099
let shape = shape.into_dimension();
20252100
if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
20262101
panic!(

tests/reshape.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,41 @@ fn to_shape_broadcast() {
230230
}
231231
}
232232
}
233+
234+
235+
#[test]
236+
fn into_shape_with_order() {
237+
// 1D -> C -> C
238+
let data = [1, 2, 3, 4, 5, 6, 7, 8];
239+
let v = aview1(&data);
240+
let u = v.into_shape_with_order(((3, 3), Order::RowMajor));
241+
assert!(u.is_err());
242+
243+
let u = v.into_shape_with_order(((2, 2, 2), Order::C));
244+
assert!(u.is_ok());
245+
246+
let u = u.unwrap();
247+
assert_eq!(u.shape(), &[2, 2, 2]);
248+
assert_eq!(u, array![[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
249+
250+
let s = u.into_shape_with_order((4, 2)).unwrap();
251+
assert_eq!(s.shape(), &[4, 2]);
252+
assert_eq!(s, aview2(&[[1, 2], [3, 4], [5, 6], [7, 8]]));
253+
254+
// 1D -> F -> F
255+
let data = [1, 2, 3, 4, 5, 6, 7, 8];
256+
let v = aview1(&data);
257+
let u = v.into_shape_with_order(((3, 3), Order::ColumnMajor));
258+
assert!(u.is_err());
259+
260+
let u = v.into_shape_with_order(((2, 2, 2), Order::ColumnMajor));
261+
assert!(u.is_ok());
262+
263+
let u = u.unwrap();
264+
assert_eq!(u.shape(), &[2, 2, 2]);
265+
assert_eq!(u, array![[[1, 5], [3, 7]], [[2, 6], [4, 8]]]);
266+
267+
let s = u.into_shape_with_order(((4, 2), Order::ColumnMajor)).unwrap();
268+
assert_eq!(s.shape(), &[4, 2]);
269+
assert_eq!(s, array![[1, 5], [2, 6], [3, 7], [4, 8]]);
270+
}

0 commit comments

Comments
 (0)