Skip to content

Commit 7d61342

Browse files
committed
shape: Add .into_shape_clone()
1 parent 0504347 commit 7d61342

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/impl_methods.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,74 @@ where
19221922
}
19231923
}
19241924

1925+
/// Transform the array into `shape`; any shape with the same number of
1926+
/// elements is accepted. Array elements are reordered in place if
1927+
/// possible, otherwise they are copied to create a new array.
1928+
///
1929+
/// If an index ordering is not specified, the default is `RowMajor`.
1930+
/// The operation will only succeed if the array's memory layout is compatible with
1931+
/// the index ordering, so that the array elements can be rearranged in place.
1932+
///
1933+
/// # `.to_shape` vs `.into_shape_clone`
1934+
///
1935+
/// - `to_shape` supports views and outputting views
1936+
/// - `to_shape` borrows the original array, `into_shape_clone` consumes the original
1937+
/// - `into_shape_clone` preserves array type (Array vs ArcArray), but does not support views.
1938+
///
1939+
/// **Errors** if the shapes don't have the same number of elements.<br>
1940+
pub fn into_shape_clone<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
1941+
where
1942+
S: DataOwned,
1943+
A: Clone,
1944+
E: ShapeArg,
1945+
{
1946+
let (shape, order) = shape.into_shape_and_order();
1947+
let order = order.unwrap_or(Order::RowMajor);
1948+
self.into_shape_clone_order(shape, order)
1949+
}
1950+
1951+
pub fn into_shape_clone_order<E>(self, shape: E, order: Order)
1952+
-> Result<ArrayBase<S, E>, ShapeError>
1953+
where
1954+
S: DataOwned,
1955+
A: Clone,
1956+
E: Dimension,
1957+
{
1958+
let len = self.dim.size();
1959+
if size_of_shape_checked(&shape) != Ok(len) {
1960+
return Err(error::incompatible_shapes(&self.dim, &shape));
1961+
}
1962+
1963+
// Safe because the array and new shape is empty.
1964+
if len == 0 {
1965+
unsafe {
1966+
return Ok(self.with_strides_dim(shape.default_strides(), shape));
1967+
}
1968+
}
1969+
1970+
// Try to reshape the array's current data
1971+
match reshape_dim(&self.dim, &self.strides, &shape, order) {
1972+
Ok(to_strides) => unsafe {
1973+
return Ok(self.with_strides_dim(to_strides, shape));
1974+
}
1975+
Err(err) if err.kind() == ErrorKind::IncompatibleShape => {
1976+
return Err(error::incompatible_shapes(&self.dim, &shape));
1977+
}
1978+
_otherwise => { }
1979+
}
1980+
1981+
// otherwise, clone and allocate a new array
1982+
unsafe {
1983+
let (shape, view) = match order {
1984+
Order::RowMajor => (shape.set_f(false), self.view()),
1985+
Order::ColumnMajor => (shape.set_f(true), self.t()),
1986+
};
1987+
1988+
Ok(ArrayBase::from_shape_trusted_iter_unchecked(
1989+
shape, view.into_iter(), A::clone))
1990+
}
1991+
}
1992+
19251993
/// *Note: Reshape is for `ArcArray` only. Use `.into_shape()` for
19261994
/// other arrays and array views.*
19271995
///
@@ -1952,6 +2020,7 @@ where
19522020
A: Clone,
19532021
E: IntoDimension,
19542022
{
2023+
return self.clone().into_shape_clone(shape).unwrap();
19552024
let shape = shape.into_dimension();
19562025
if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
19572026
panic!(

0 commit comments

Comments
 (0)