Skip to content

Commit

Permalink
Merge pull request #990 from rust-ndarray/push-append
Browse files Browse the repository at this point in the history
Rename append_row/column to push_row/column; add method push
  • Loading branch information
bluss committed May 1, 2021
2 parents 9f868f7 + 68c5be0 commit 702de70
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 61 deletions.
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

0 comments on commit 702de70

Please sign in to comment.