diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 4b5b1919a..d1e8c2fbb 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -1929,28 +1929,48 @@ where { let (shape, order) = shape.into_shape_and_order(); let order = order.unwrap_or(Order::RowMajor); + self.into_shape_clone_order(shape, order) + } - if size_of_shape_checked(&shape) != Ok(self.dim.size()) { + pub fn into_shape_clone_order(self, shape: E, order: Order) + -> Result, ShapeError> + where + S: DataOwned, + A: Clone, + E: Dimension, + { + let len = self.dim.size(); + if size_of_shape_checked(&shape) != Ok(len) { return Err(error::incompatible_shapes(&self.dim, &shape)); } - let layout = self.layout_impl(); - unsafe { - if layout.is(Layout::CORDER) && order == Order::RowMajor { - // safe because arrays are contiguous and len is unchanged - Ok(self.with_strides_dim(shape.default_strides(), shape)) - } else if layout.is(Layout::FORDER) && order == Order::ColumnMajor { - // safe because arrays are contiguous and len is unchanged - Ok(self.with_strides_dim(shape.fortran_strides(), shape)) - } else { - let (shape, view) = match order { - Order::RowMajor => (shape.set_f(false), self.view()), - Order::ColumnMajor => (shape.set_f(true), self.t()), - }; + // Safe because the array and new shape is empty. + if len == 0 { + unsafe { + return Ok(self.with_strides_dim(shape.default_strides(), shape)); + } + } - Ok(ArrayBase::from_shape_trusted_iter_unchecked( - shape, view.into_iter(), A::clone)) + // Try to reshape the array's current data + match reshape_dim(&self.dim, &self.strides, &shape, order) { + Ok(to_strides) => unsafe { + return Ok(self.with_strides_dim(to_strides, shape)); + } + Err(err) if err.kind() == ErrorKind::IncompatibleShape => { + return Err(error::incompatible_shapes(&self.dim, &shape)); } + _otherwise => { } + } + + // otherwise, clone and allocate a new array + unsafe { + let (shape, view) = match order { + Order::RowMajor => (shape.set_f(false), self.view()), + Order::ColumnMajor => (shape.set_f(true), self.t()), + }; + + Ok(ArrayBase::from_shape_trusted_iter_unchecked( + shape, view.into_iter(), A::clone)) } } @@ -1984,6 +2004,7 @@ where A: Clone, E: IntoDimension, { + return self.clone().into_shape_clone(shape).unwrap(); let shape = shape.into_dimension(); if size_of_shape_checked(&shape) != Ok(self.dim.size()) { panic!(