Skip to content

Commit 702de70

Browse files
authored
Merge pull request #990 from rust-ndarray/push-append
Rename append_row/column to push_row/column; add method push
2 parents 9f868f7 + 68c5be0 commit 702de70

File tree

2 files changed

+145
-61
lines changed

2 files changed

+145
-61
lines changed

src/impl_owned_array.rs

+72-13
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ impl<A> Array<A, Ix2> {
9999
///
100100
/// // create an empty array and append
101101
/// let mut a = Array::zeros((0, 4));
102-
/// a.append_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
103-
/// a.append_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
102+
/// a.push_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
103+
/// a.push_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
104104
///
105105
/// assert_eq!(
106106
/// a,
107107
/// array![[ 1., 2., 3., 4.],
108108
/// [-1., -2., -3., -4.]]);
109109
/// ```
110-
pub fn append_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
110+
pub fn push_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
111111
where
112112
A: Clone,
113113
{
@@ -136,15 +136,15 @@ impl<A> Array<A, Ix2> {
136136
///
137137
/// // create an empty array and append
138138
/// let mut a = Array::zeros((2, 0));
139-
/// a.append_column(ArrayView::from(&[1., 2.])).unwrap();
140-
/// a.append_column(ArrayView::from(&[-1., -2.])).unwrap();
139+
/// a.push_column(ArrayView::from(&[1., 2.])).unwrap();
140+
/// a.push_column(ArrayView::from(&[-1., -2.])).unwrap();
141141
///
142142
/// assert_eq!(
143143
/// a,
144144
/// array![[1., -1.],
145145
/// [2., -2.]]);
146146
/// ```
147-
pub fn append_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
147+
pub fn push_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
148148
where
149149
A: Clone,
150150
{
@@ -278,8 +278,66 @@ impl<A, D> Array<A, D>
278278
}
279279
}
280280

281+
/// Append an array to the array along an axis
282+
///
283+
/// Where the item to push to the array has one dimension less than the `self` array. This
284+
/// method is equivalent to `self.append(axis, array.insert_axis(axis))`.
285+
///
286+
/// The axis-to-append-to `axis` must be the array's "growing axis" for this operation
287+
/// to succeed. The growing axis is the outermost or last-visited when elements are visited in
288+
/// memory order:
289+
///
290+
/// `axis` must be the growing axis of the current array, an axis with length 0 or 1.
291+
///
292+
/// - This is the 0th axis for standard layout arrays
293+
/// - This is the *n*-1 th axis for fortran layout arrays
294+
/// - If the array is empty (the axis or any other has length 0) or if `axis`
295+
/// has length 1, then the array can always be appended.
296+
///
297+
/// ***Errors*** with a shape error if the shape of self does not match the array-to-append;
298+
/// all axes *except* the axis along which it being appended matter for this check.
299+
///
300+
/// The memory layout of the `self` array matters for ensuring that the append is efficient.
301+
/// Appending automatically changes memory layout of the array so that it is appended to
302+
/// along the "growing axis".
303+
///
304+
/// Ensure appending is efficient by for example starting from an empty array and/or always
305+
/// appending to an array along the same axis.
306+
///
307+
/// The amortized average complexity of the append, when appending along its growing axis, is
308+
/// O(*m*) where *m* is the length of the row.
309+
///
310+
/// The memory layout of the argument `array` does not matter to the same extent.
311+
///
312+
/// ```rust
313+
/// use ndarray::{Array, ArrayView, array, Axis};
314+
///
315+
/// // create an empty array and push rows to it
316+
/// let mut a = Array::zeros((0, 4));
317+
/// let ones = ArrayView::from(&[1.; 4]);
318+
/// let zeros = ArrayView::from(&[0.; 4]);
319+
/// a.push(Axis(0), ones).unwrap();
320+
/// a.push(Axis(0), zeros).unwrap();
321+
/// a.push(Axis(0), ones).unwrap();
322+
///
323+
/// assert_eq!(
324+
/// a,
325+
/// array![[1., 1., 1., 1.],
326+
/// [0., 0., 0., 0.],
327+
/// [1., 1., 1., 1.]]);
328+
/// ```
329+
pub fn push(&mut self, axis: Axis, array: ArrayView<A, D::Smaller>)
330+
-> Result<(), ShapeError>
331+
where
332+
A: Clone,
333+
D: RemoveAxis,
334+
{
335+
// same-dimensionality conversion
336+
self.append(axis, array.insert_axis(axis).into_dimensionality::<D>().unwrap())
337+
}
338+
281339

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

340398
let current_axis_len = self.len_of(axis);
341-
let remaining_shape = self.raw_dim().remove_axis(axis);
342-
let array_rem_shape = array.raw_dim().remove_axis(axis);
399+
let self_dim = self.raw_dim();
400+
let array_dim = array.raw_dim();
401+
let remaining_shape = self_dim.remove_axis(axis);
402+
let array_rem_shape = array_dim.remove_axis(axis);
343403

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

348408
let len_to_append = array.len();
349409

350-
let array_shape = array.raw_dim();
351-
let mut res_dim = self.raw_dim();
352-
res_dim[axis.index()] += array_shape[axis.index()];
410+
let mut res_dim = self_dim;
411+
res_dim[axis.index()] += array_dim[axis.index()];
353412
let new_len = dimension::size_of_shape_checked(&res_dim)?;
354413

355414
if len_to_append == 0 {
@@ -468,7 +527,7 @@ impl<A, D> Array<A, D>
468527

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

473532
if tail_view.ndim() > 1 {
474533
sort_axes_in_default_order_tandem(&mut tail_view, &mut array);

0 commit comments

Comments
 (0)