Skip to content

Commit c80764c

Browse files
committed
FEAT: Make methods .append(axis, array), .append_row/column()
Without the tricky memory layout failure mode, these methods can just have names without try_ prefix. It's expected that they work successfully as long as the user matches up array sizes correctly.
1 parent 769bd77 commit c80764c

File tree

3 files changed

+100
-84
lines changed

3 files changed

+100
-84
lines changed

src/impl_owned_array.rs

+49-33
Original file line numberDiff line numberDiff line change
@@ -74,66 +74,78 @@ where
7474
///
7575
/// [`ArrayBase`]: struct.ArrayBase.html
7676
impl<A> Array<A, Ix2> {
77-
/// Append a row to an array with row major memory layout.
77+
/// Append a row to an array
7878
///
79-
/// ***Errors*** with a layout error if the array is not in standard order or
80-
/// if it has holes, even exterior holes (from slicing). <br>
8179
/// ***Errors*** with shape error if the length of the input row does not match
8280
/// the length of the rows in the array. <br>
8381
///
84-
/// The memory layout matters, since it determines in which direction the array can easily
85-
/// grow. Notice that an empty array is compatible both ways. The amortized average
86-
/// complexity of the append is O(m) where *m* is the length of the row.
82+
/// The memory layout of the `self` array matters for ensuring that the append is efficient.
83+
/// Appending automatically changes memory layout of the array so that it is appended to
84+
/// along the "growing axis".
85+
///
86+
/// Ensure appending is efficient by for example starting appending an empty array and
87+
/// always appending along the same axis. For rows, ndarray's default layout is efficient for
88+
/// appending.
89+
///
90+
/// Notice that an empty array (where it has an axis of length zero) is the simplest starting
91+
/// point. The amortized average complexity of the append is O(m) where *m* is the length of
92+
/// the row.
8793
///
8894
/// ```rust
8995
/// use ndarray::{Array, ArrayView, array};
9096
///
9197
/// // create an empty array and append
9298
/// let mut a = Array::zeros((0, 4));
93-
/// a.try_append_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
94-
/// a.try_append_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
99+
/// a.append_row(ArrayView::from(&[ 1., 2., 3., 4.])).unwrap();
100+
/// a.append_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
95101
///
96102
/// assert_eq!(
97103
/// a,
98104
/// array![[ 1., 2., 3., 4.],
99105
/// [-1., -2., -3., -4.]]);
100106
/// ```
101-
pub fn try_append_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
107+
pub fn append_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
102108
where
103109
A: Clone,
104110
{
105-
self.try_append_array(Axis(0), row.insert_axis(Axis(0)))
111+
self.append(Axis(0), row.insert_axis(Axis(0)))
106112
}
107113

108-
/// Append a column to an array with column major memory layout.
114+
/// Append a column to an array
109115
///
110-
/// ***Errors*** with a layout error if the array is not in column major order or
111-
/// if it has holes, even exterior holes (from slicing). <br>
112116
/// ***Errors*** with shape error if the length of the input column does not match
113117
/// the length of the columns in the array.<br>
114118
///
115-
/// The memory layout matters, since it determines in which direction the array can easily
116-
/// grow. Notice that an empty array is compatible both ways. The amortized average
117-
/// complexity of the append is O(m) where *m* is the length of the column.
119+
/// The memory layout of the `self` array matters for ensuring that the append is efficient.
120+
/// Appending automatically changes memory layout of the array so that it is appended to
121+
/// along the "growing axis".
122+
///
123+
/// Ensure appending is efficient by for example starting appending an empty array and
124+
/// always appending along the same axis. For columns, column major ("F") memory layout is
125+
/// efficient for appending.
126+
///
127+
/// Notice that an empty array (where it has an axis of length zero) is the simplest starting
128+
/// point. The amortized average complexity of the append is O(m) where *m* is the length of
129+
/// the row.
118130
///
119131
/// ```rust
120132
/// use ndarray::{Array, ArrayView, array};
121133
///
122134
/// // create an empty array and append
123135
/// let mut a = Array::zeros((2, 0));
124-
/// a.try_append_column(ArrayView::from(&[1., 2.])).unwrap();
125-
/// a.try_append_column(ArrayView::from(&[-1., -2.])).unwrap();
136+
/// a.append_column(ArrayView::from(&[1., 2.])).unwrap();
137+
/// a.append_column(ArrayView::from(&[-1., -2.])).unwrap();
126138
///
127139
/// assert_eq!(
128140
/// a,
129141
/// array![[1., -1.],
130142
/// [2., -2.]]);
131143
/// ```
132-
pub fn try_append_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
144+
pub fn append_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
133145
where
134146
A: Clone,
135147
{
136-
self.try_append_array(Axis(1), column.insert_axis(Axis(1)))
148+
self.append(Axis(1), column.insert_axis(Axis(1)))
137149
}
138150
}
139151

@@ -311,17 +323,21 @@ impl<A, D> Array<A, D>
311323
/// - If the array is empty (the axis or any other has length 0) or if `axis`
312324
/// has length 1, then the array can always be appended.
313325
///
314-
/// ***Errors*** with a layout error if the array is not in standard order or
315-
/// if it has holes, even exterior holes (from slicing). <br>
316-
/// ***Errors*** with shape error if the length of the input row does not match
317-
/// the length of the rows in the array. <br>
326+
/// ***Errors*** with shape error if the shape of self does not match the array-to-append;
327+
/// all axes *except* the axis along which it being appended matter for this check.
328+
///
329+
/// The memory layout of the `self` array matters for ensuring that the append is efficient.
330+
/// Appending automatically changes memory layout of the array so that it is appended to
331+
/// along the "growing axis".
332+
///
333+
/// Ensure appending is efficient by for example starting appending an empty array and
334+
/// always appending along the same axis.
318335
///
319-
/// The memory layout of the `self` array matters, since it determines in which direction the
320-
/// array can easily grow. Notice that an empty array is compatible both ways. The amortized
321-
/// average complexity of the append is O(m) where *m* is the number of elements in the
322-
/// array-to-append (equivalent to how `Vec::extend` works).
336+
/// Notice that an empty array (where it has an axis of length zero) is the simplest starting
337+
/// point. The amortized average complexity of the append is O(m) where *m* is the length of
338+
/// the row.
323339
///
324-
/// The memory layout of the argument `array` does not matter.
340+
/// The memory layout of the argument `array` does not matter to the same extent.
325341
///
326342
/// ```rust
327343
/// use ndarray::{Array, ArrayView, array, Axis};
@@ -330,9 +346,9 @@ impl<A, D> Array<A, D>
330346
/// let mut a = Array::zeros((0, 4));
331347
/// let ones = ArrayView::from(&[1.; 8]).into_shape((2, 4)).unwrap();
332348
/// let zeros = ArrayView::from(&[0.; 8]).into_shape((2, 4)).unwrap();
333-
/// a.try_append_array(Axis(0), ones).unwrap();
334-
/// a.try_append_array(Axis(0), zeros).unwrap();
335-
/// a.try_append_array(Axis(0), ones).unwrap();
349+
/// a.append(Axis(0), ones).unwrap();
350+
/// a.append(Axis(0), zeros).unwrap();
351+
/// a.append(Axis(0), ones).unwrap();
336352
///
337353
/// assert_eq!(
338354
/// a,
@@ -343,7 +359,7 @@ impl<A, D> Array<A, D>
343359
/// [1., 1., 1., 1.],
344360
/// [1., 1., 1., 1.]]);
345361
/// ```
346-
pub fn try_append_array(&mut self, axis: Axis, mut array: ArrayView<A, D>)
362+
pub fn append(&mut self, axis: Axis, mut array: ArrayView<A, D>)
347363
-> Result<(), ShapeError>
348364
where
349365
A: Clone,

src/stacking.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,15 +94,15 @@ where
9494
let new_len = dimension::size_of_shape_checked(&res_dim)?;
9595

9696
// start with empty array with precomputed capacity
97-
// try_append_array's handling of empty arrays makes sure `axis` is ok for appending
97+
// append's handling of empty arrays makes sure `axis` is ok for appending
9898
res_dim.set_axis(axis, 0);
9999
let mut res = unsafe {
100100
// Safety: dimension is size 0 and vec is empty
101101
Array::from_shape_vec_unchecked(res_dim, Vec::with_capacity(new_len))
102102
};
103103

104104
for array in arrays {
105-
res.try_append_array(axis, array.clone())?;
105+
res.append(axis, array.clone())?;
106106
}
107107
debug_assert_eq!(res.len_of(axis), stacked_dim);
108108
Ok(res)
@@ -161,15 +161,15 @@ where
161161
let new_len = dimension::size_of_shape_checked(&res_dim)?;
162162

163163
// start with empty array with precomputed capacity
164-
// try_append_array's handling of empty arrays makes sure `axis` is ok for appending
164+
// append's handling of empty arrays makes sure `axis` is ok for appending
165165
res_dim.set_axis(axis, 0);
166166
let mut res = unsafe {
167167
// Safety: dimension is size 0 and vec is empty
168168
Array::from_shape_vec_unchecked(res_dim, Vec::with_capacity(new_len))
169169
};
170170

171171
for array in arrays {
172-
res.try_append_array(axis, array.clone().insert_axis(axis))?;
172+
res.append(axis, array.clone().insert_axis(axis))?;
173173
}
174174

175175
debug_assert_eq!(res.len_of(axis), arrays.len());

0 commit comments

Comments
 (0)