Skip to content

Commit cfd84e2

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 62db054 commit cfd84e2

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
@@ -1884,10 +1884,84 @@ where
18841884
}
18851885
}
18861886

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

1935-
pub fn into_shape_clone_order<E>(self, shape: E, order: Order)
2010+
fn into_shape_clone_order<E>(self, shape: E, order: Order)
19362011
-> Result<ArrayBase<S, E>, ShapeError>
19372012
where
19382013
S: DataOwned,
@@ -2004,7 +2079,7 @@ where
20042079
A: Clone,
20052080
E: IntoDimension,
20062081
{
2007-
return self.clone().into_shape_clone(shape).unwrap();
2082+
//return self.clone().into_shape_clone(shape).unwrap();
20082083
let shape = shape.into_dimension();
20092084
if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
20102085
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)