Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename append_row/column to push_row/column; add method push #990

Merged
merged 3 commits into from
May 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 72 additions & 13 deletions src/impl_owned_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ impl<A> Array<A, Ix2> {
///
/// // create an empty array and append
/// let mut a = Array::zeros((0, 4));
/// a.append_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
/// a.append_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
/// a.push_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
/// a.push_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
///
/// assert_eq!(
/// a,
/// array![[ 1., 2., 3., 4.],
/// [-1., -2., -3., -4.]]);
/// ```
pub fn append_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
pub fn push_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
where
A: Clone,
{
Expand Down Expand Up @@ -136,15 +136,15 @@ impl<A> Array<A, Ix2> {
///
/// // create an empty array and append
/// let mut a = Array::zeros((2, 0));
/// a.append_column(ArrayView::from(&[1., 2.])).unwrap();
/// a.append_column(ArrayView::from(&[-1., -2.])).unwrap();
/// a.push_column(ArrayView::from(&[1., 2.])).unwrap();
/// a.push_column(ArrayView::from(&[-1., -2.])).unwrap();
///
/// assert_eq!(
/// a,
/// array![[1., -1.],
/// [2., -2.]]);
/// ```
pub fn append_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
pub fn push_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
where
A: Clone,
{
Expand Down Expand Up @@ -278,8 +278,66 @@ impl<A, D> Array<A, D>
}
}

/// Append an array to the array along an axis
///
/// Where the item to push to the array has one dimension less than the `self` array. This
/// method is equivalent to `self.append(axis, array.insert_axis(axis))`.
///
/// The axis-to-append-to `axis` must be the array's "growing axis" for this operation
/// to succeed. The growing axis is the outermost or last-visited when elements are visited in
/// memory order:
///
/// `axis` must be the growing axis of the current array, an axis with length 0 or 1.
///
/// - This is the 0th axis for standard layout arrays
/// - This is the *n*-1 th axis for fortran layout arrays
/// - If the array is empty (the axis or any other has length 0) or if `axis`
/// has length 1, then the array can always be appended.
///
/// ***Errors*** with a shape error if the shape of self does not match the array-to-append;
/// all axes *except* the axis along which it being appended matter for this check.
///
/// The memory layout of the `self` array matters for ensuring that the append is efficient.
/// Appending automatically changes memory layout of the array so that it is appended to
/// along the "growing axis".
///
/// Ensure appending is efficient by for example starting from an empty array and/or always
/// appending to an array along the same axis.
///
/// The amortized average complexity of the append, when appending along its growing axis, is
/// O(*m*) where *m* is the length of the row.
///
/// The memory layout of the argument `array` does not matter to the same extent.
///
/// ```rust
/// use ndarray::{Array, ArrayView, array, Axis};
///
/// // create an empty array and push rows to it
/// let mut a = Array::zeros((0, 4));
/// let ones = ArrayView::from(&[1.; 4]);
/// let zeros = ArrayView::from(&[0.; 4]);
/// a.push(Axis(0), ones).unwrap();
/// a.push(Axis(0), zeros).unwrap();
/// a.push(Axis(0), ones).unwrap();
///
/// assert_eq!(
/// a,
/// array![[1., 1., 1., 1.],
/// [0., 0., 0., 0.],
/// [1., 1., 1., 1.]]);
/// ```
pub fn push(&mut self, axis: Axis, array: ArrayView<A, D::Smaller>)
-> Result<(), ShapeError>
where
A: Clone,
D: RemoveAxis,
{
// same-dimensionality conversion
self.append(axis, array.insert_axis(axis).into_dimensionality::<D>().unwrap())
}


/// Append an array to the array
/// Append an array to the array along an axis
///
/// The axis-to-append-to `axis` must be the array's "growing axis" for this operation
/// to succeed. The growing axis is the outermost or last-visited when elements are visited in
Expand Down Expand Up @@ -338,18 +396,19 @@ impl<A, D> Array<A, D>
}

let current_axis_len = self.len_of(axis);
let remaining_shape = self.raw_dim().remove_axis(axis);
let array_rem_shape = array.raw_dim().remove_axis(axis);
let self_dim = self.raw_dim();
let array_dim = array.raw_dim();
let remaining_shape = self_dim.remove_axis(axis);
let array_rem_shape = array_dim.remove_axis(axis);

if remaining_shape != array_rem_shape {
return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape));
}

let len_to_append = array.len();

let array_shape = array.raw_dim();
let mut res_dim = self.raw_dim();
res_dim[axis.index()] += array_shape[axis.index()];
let mut res_dim = self_dim;
res_dim[axis.index()] += array_dim[axis.index()];
let new_len = dimension::size_of_shape_checked(&res_dim)?;

if len_to_append == 0 {
Expand Down Expand Up @@ -468,7 +527,7 @@ impl<A, D> Array<A, D>

// With > 0 strides, the current end of data is the correct base pointer for tail_view
let tail_ptr = self.data.as_end_nonnull();
let mut tail_view = RawArrayViewMut::new(tail_ptr, array_shape, tail_strides);
let mut tail_view = RawArrayViewMut::new(tail_ptr, array_dim, tail_strides);

if tail_view.ndim() > 1 {
sort_axes_in_default_order_tandem(&mut tail_view, &mut array);
Expand Down