diff --git a/src/impl_owned_array.rs b/src/impl_owned_array.rs
index 8d8963c1a..63af63917 100644
--- a/src/impl_owned_array.rs
+++ b/src/impl_owned_array.rs
@@ -99,15 +99,15 @@ impl Array {
///
/// // 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) -> Result<(), ShapeError>
+ pub fn push_row(&mut self, row: ArrayView) -> Result<(), ShapeError>
where
A: Clone,
{
@@ -136,15 +136,15 @@ impl Array {
///
/// // 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) -> Result<(), ShapeError>
+ pub fn push_column(&mut self, column: ArrayView) -> Result<(), ShapeError>
where
A: Clone,
{
@@ -278,8 +278,66 @@ impl Array
}
}
+ /// 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)
+ -> Result<(), ShapeError>
+ where
+ A: Clone,
+ D: RemoveAxis,
+ {
+ // same-dimensionality conversion
+ self.append(axis, array.insert_axis(axis).into_dimensionality::().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
@@ -338,8 +396,10 @@ impl Array
}
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));
@@ -347,9 +407,8 @@ impl Array
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 {
@@ -468,7 +527,7 @@ impl Array
// 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);
diff --git a/tests/append.rs b/tests/append.rs
index 6306b2ecf..dcebcf50e 100644
--- a/tests/append.rs
+++ b/tests/append.rs
@@ -3,21 +3,21 @@ use ndarray::prelude::*;
use ndarray::{ShapeError, ErrorKind};
#[test]
-fn append_row() {
+fn push_row() {
let mut a = Array::zeros((0, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[2, 4]);
assert_eq!(a,
array![[0., 1., 2., 3.],
[4., 5., 6., 7.]]);
- assert_eq!(a.append_row(aview1(&[1.])),
+ assert_eq!(a.push_row(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1.])),
+ assert_eq!(a.push_column(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1., 2.])),
+ assert_eq!(a.push_column(aview1(&[1., 2.])),
Ok(()));
assert_eq!(a,
array![[0., 1., 2., 3., 1.],
@@ -25,10 +25,10 @@ fn append_row() {
}
#[test]
-fn append_row_wrong_layout() {
+fn push_row_wrong_layout() {
let mut a = Array::zeros((0, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[2, 4]);
assert_eq!(a,
@@ -38,7 +38,7 @@ fn append_row_wrong_layout() {
// Changing the memory layout to fit the next append
let mut a2 = a.clone();
- a2.append_column(aview1(&[1., 2.])).unwrap();
+ a2.push_column(aview1(&[1., 2.])).unwrap();
assert_eq!(a2,
array![[0., 1., 2., 3., 1.],
[4., 5., 6., 7., 2.]]);
@@ -51,17 +51,17 @@ fn append_row_wrong_layout() {
dim[1] = 0;
let mut b = Array::zeros(dim);
b.append(Axis(1), a.view()).unwrap();
- assert_eq!(b.append_column(aview1(&[1., 2.])), Ok(()));
+ assert_eq!(b.push_column(aview1(&[1., 2.])), Ok(()));
assert_eq!(b,
array![[0., 1., 2., 3., 1.],
[4., 5., 6., 7., 2.]]);
}
#[test]
-fn append_row_neg_stride_1() {
+fn push_row_neg_stride_1() {
let mut a = Array::zeros((0, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[2, 4]);
assert_eq!(a,
@@ -75,7 +75,7 @@ fn append_row_neg_stride_1() {
let mut a2 = a.clone();
println!("a = {:?}", a);
println!("a2 = {:?}", a2);
- a2.append_column(aview1(&[1., 2.])).unwrap();
+ a2.push_column(aview1(&[1., 2.])).unwrap();
assert_eq!(a2,
array![[4., 5., 6., 7., 1.],
[0., 1., 2., 3., 2.]]);
@@ -83,7 +83,7 @@ fn append_row_neg_stride_1() {
a.invert_axis(Axis(1));
let mut a3 = a.clone();
- a3.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a3.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a3,
array![[7., 6., 5., 4.],
[3., 2., 1., 0.],
@@ -92,7 +92,7 @@ fn append_row_neg_stride_1() {
a.invert_axis(Axis(0));
let mut a4 = a.clone();
- a4.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a4.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a4,
array![[3., 2., 1., 0.],
[7., 6., 5., 4.],
@@ -101,10 +101,10 @@ fn append_row_neg_stride_1() {
}
#[test]
-fn append_row_neg_stride_2() {
+fn push_row_neg_stride_2() {
let mut a = Array::zeros((0, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[2, 4]);
assert_eq!(a,
@@ -118,7 +118,7 @@ fn append_row_neg_stride_2() {
let mut a2 = a.clone();
println!("a = {:?}", a);
println!("a2 = {:?}", a2);
- a2.append_column(aview1(&[1., 2.])).unwrap();
+ a2.push_column(aview1(&[1., 2.])).unwrap();
assert_eq!(a2,
array![[3., 2., 1., 0., 1.],
[7., 6., 5., 4., 2.]]);
@@ -126,7 +126,7 @@ fn append_row_neg_stride_2() {
a.invert_axis(Axis(0));
let mut a3 = a.clone();
- a3.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a3.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a3,
array![[7., 6., 5., 4.],
[3., 2., 1., 0.],
@@ -135,7 +135,7 @@ fn append_row_neg_stride_2() {
a.invert_axis(Axis(1));
let mut a4 = a.clone();
- a4.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a4.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a4,
array![[4., 5., 6., 7.],
[0., 1., 2., 3.],
@@ -144,14 +144,14 @@ fn append_row_neg_stride_2() {
}
#[test]
-fn append_row_error() {
+fn push_row_error() {
let mut a = Array::zeros((3, 4));
- assert_eq!(a.append_row(aview1(&[1.])),
+ assert_eq!(a.push_row(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1.])),
+ assert_eq!(a.push_column(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1., 2., 3.])),
+ assert_eq!(a.push_column(aview1(&[1., 2., 3.])),
Ok(()));
assert_eq!(a.t(),
array![[0., 0., 0.],
@@ -162,10 +162,10 @@ fn append_row_error() {
}
#[test]
-fn append_row_existing() {
+fn push_row_existing() {
let mut a = Array::zeros((1, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[3, 4]);
assert_eq!(a,
@@ -173,11 +173,11 @@ fn append_row_existing() {
[0., 1., 2., 3.],
[4., 5., 6., 7.]]);
- assert_eq!(a.append_row(aview1(&[1.])),
+ assert_eq!(a.push_row(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1.])),
+ assert_eq!(a.push_column(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- assert_eq!(a.append_column(aview1(&[1., 2., 3.])),
+ assert_eq!(a.push_column(aview1(&[1., 2., 3.])),
Ok(()));
assert_eq!(a,
array![[0., 0., 0., 0., 1.],
@@ -186,15 +186,15 @@ fn append_row_existing() {
}
#[test]
-fn append_row_col_len_1() {
+fn push_row_col_len_1() {
// Test appending 1 row and then cols from shape 1 x 1
let mut a = Array::zeros((1, 1));
- a.append_row(aview1(&[1.])).unwrap(); // shape 2 x 1
- a.append_column(aview1(&[2., 3.])).unwrap(); // shape 2 x 2
- assert_eq!(a.append_row(aview1(&[1.])),
+ a.push_row(aview1(&[1.])).unwrap(); // shape 2 x 1
+ a.push_column(aview1(&[2., 3.])).unwrap(); // shape 2 x 2
+ assert_eq!(a.push_row(aview1(&[1.])),
Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)));
- //assert_eq!(a.append_row(aview1(&[1., 2.])), Err(ShapeError::from_kind(ErrorKind::IncompatibleLayout)));
- a.append_column(aview1(&[4., 5.])).unwrap(); // shape 2 x 3
+ //assert_eq!(a.push_row(aview1(&[1., 2.])), Err(ShapeError::from_kind(ErrorKind::IncompatibleLayout)));
+ a.push_column(aview1(&[4., 5.])).unwrap(); // shape 2 x 3
assert_eq!(a.shape(), &[2, 3]);
assert_eq!(a,
@@ -203,10 +203,10 @@ fn append_row_col_len_1() {
}
#[test]
-fn append_column() {
+fn push_column() {
let mut a = Array::zeros((4, 0));
- a.append_column(aview1(&[0., 1., 2., 3.])).unwrap();
- a.append_column(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_column(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_column(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[4, 2]);
assert_eq!(a.t(),
@@ -221,7 +221,7 @@ fn append_array1() {
println!("{:?}", a);
a.append(Axis(0), aview2(&[[4., 5., 6., 7.]])).unwrap();
println!("{:?}", a);
- //a.append_column(aview1(&[4., 5., 6., 7.])).unwrap();
+ //a.push_column(aview1(&[4., 5., 6., 7.])).unwrap();
//assert_eq!(a.shape(), &[4, 2]);
assert_eq!(a,
@@ -347,18 +347,18 @@ fn test_append_zero_size() {
}
#[test]
-fn append_row_neg_stride_3() {
+fn push_row_neg_stride_3() {
let mut a = Array::zeros((0, 4));
- a.append_row(aview1(&[0., 1., 2., 3.])).unwrap();
+ a.push_row(aview1(&[0., 1., 2., 3.])).unwrap();
a.invert_axis(Axis(1));
- a.append_row(aview1(&[4., 5., 6., 7.])).unwrap();
+ a.push_row(aview1(&[4., 5., 6., 7.])).unwrap();
assert_eq!(a.shape(), &[2, 4]);
assert_eq!(a, array![[3., 2., 1., 0.], [4., 5., 6., 7.]]);
assert_eq!(a.strides(), &[4, -1]);
}
#[test]
-fn append_row_ignore_strides_length_one_axes() {
+fn push_row_ignore_strides_length_one_axes() {
let strides = &[0, 1, 10, 20];
for invert in &[vec![], vec![0], vec![1], vec![0, 1]] {
for &stride0 in strides {
@@ -368,7 +368,7 @@ fn append_row_ignore_strides_length_one_axes() {
for &ax in invert {
a.invert_axis(Axis(ax));
}
- a.append_row(aview1(&[1.])).unwrap();
+ a.push_row(aview1(&[1.])).unwrap();
assert_eq!(a.shape(), &[2, 1]);
assert_eq!(a, array![[0.], [1.]]);
assert_eq!(a.stride_of(Axis(0)), 1);
@@ -376,3 +376,28 @@ fn append_row_ignore_strides_length_one_axes() {
}
}
}
+
+#[test]
+#[should_panic(expected = "IncompatibleShape")]
+fn zero_dimensional_error1() {
+ let mut a = Array::zeros(()).into_dyn();
+ a.append(Axis(0), arr0(0).into_dyn().view()).unwrap();
+}
+
+#[test]
+#[should_panic(expected = "IncompatibleShape")]
+fn zero_dimensional_error2() {
+ let mut a = Array::zeros(()).into_dyn();
+ a.push(Axis(0), arr0(0).into_dyn().view()).unwrap();
+}
+
+#[test]
+fn zero_dimensional_ok() {
+ let mut a = Array::zeros(0);
+ let one = aview0(&1);
+ let two = aview0(&2);
+ a.push(Axis(0), two).unwrap();
+ a.push(Axis(0), one).unwrap();
+ a.push(Axis(0), one).unwrap();
+ assert_eq!(a, array![2, 1, 1]);
+}