Skip to content

Commit 77c6286

Browse files
authored
Merge pull request #932 from rust-ndarray/append-row-column
append, append_row, append_column: methods for appending an array or single rows and columns
2 parents fc3f836 + d946360 commit 77c6286

13 files changed

+1447
-93
lines changed

benches/append.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#![feature(test)]
2+
3+
extern crate test;
4+
use test::Bencher;
5+
6+
use ndarray::prelude::*;
7+
8+
#[bench]
9+
fn select_axis0(bench: &mut Bencher) {
10+
let a = Array::<f32, _>::zeros((256, 256));
11+
let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1];
12+
bench.iter(|| {
13+
a.select(Axis(0), &selectable)
14+
});
15+
}
16+
17+
#[bench]
18+
fn select_axis1(bench: &mut Bencher) {
19+
let a = Array::<f32, _>::zeros((256, 256));
20+
let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1];
21+
bench.iter(|| {
22+
a.select(Axis(1), &selectable)
23+
});
24+
}
25+
26+
#[bench]
27+
fn select_1d(bench: &mut Bencher) {
28+
let a = Array::<f32, _>::zeros(1024);
29+
let mut selectable = (0..a.len()).step_by(17).collect::<Vec<_>>();
30+
selectable.extend(selectable.clone().iter().rev());
31+
32+
bench.iter(|| {
33+
a.select(Axis(0), &selectable)
34+
});
35+
}

src/data_repr.rs

+38
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use alloc::borrow::ToOwned;
66
use alloc::vec::Vec;
77
use crate::extension::nonnull;
88

9+
use rawpointer::PointerExt;
10+
911
/// Array's representation.
1012
///
1113
/// *Don’t use this type directly—use the type alias
@@ -55,6 +57,37 @@ impl<A> OwnedRepr<A> {
5557
self.ptr
5658
}
5759

60+
/// Return end pointer
61+
pub(crate) fn as_end_nonnull(&self) -> NonNull<A> {
62+
unsafe {
63+
self.ptr.add(self.len)
64+
}
65+
}
66+
67+
/// Reserve `additional` elements; return the new pointer
68+
///
69+
/// ## Safety
70+
///
71+
/// Note that existing pointers into the data are invalidated
72+
#[must_use = "must use new pointer to update existing pointers"]
73+
pub(crate) fn reserve(&mut self, additional: usize) -> NonNull<A> {
74+
self.modify_as_vec(|mut v| {
75+
v.reserve(additional);
76+
v
77+
});
78+
self.as_nonnull_mut()
79+
}
80+
81+
/// Set the valid length of the data
82+
///
83+
/// ## Safety
84+
///
85+
/// The first `new_len` elements of the data should be valid.
86+
pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
87+
debug_assert!(new_len <= self.capacity);
88+
self.len = new_len;
89+
}
90+
5891
/// Cast self into equivalent repr of other element type
5992
///
6093
/// ## Safety
@@ -72,6 +105,11 @@ impl<A> OwnedRepr<A> {
72105
}
73106
}
74107

108+
fn modify_as_vec(&mut self, f: impl FnOnce(Vec<A>) -> Vec<A>) {
109+
let v = self.take_as_vec();
110+
*self = Self::from(f(v));
111+
}
112+
75113
fn take_as_vec(&mut self) -> Vec<A> {
76114
let capacity = self.capacity;
77115
let len = self.len;

src/impl_methods.rs

+29-10
Original file line numberDiff line numberDiff line change
@@ -873,20 +873,39 @@ where
873873
/// ```
874874
pub fn select(&self, axis: Axis, indices: &[Ix]) -> Array<A, D>
875875
where
876-
A: Copy,
876+
A: Clone,
877877
S: Data,
878878
D: RemoveAxis,
879879
{
880-
let mut subs = vec![self.view(); indices.len()];
881-
for (&i, sub) in zip(indices, &mut subs[..]) {
882-
sub.collapse_axis(axis, i);
883-
}
884-
if subs.is_empty() {
885-
let mut dim = self.raw_dim();
886-
dim.set_axis(axis, 0);
887-
unsafe { Array::from_shape_vec_unchecked(dim, vec![]) }
880+
if self.ndim() == 1 {
881+
// using .len_of(axis) means that we check if `axis` is in bounds too.
882+
let axis_len = self.len_of(axis);
883+
// bounds check the indices first
884+
if let Some(max_index) = indices.iter().cloned().max() {
885+
if max_index >= axis_len {
886+
panic!("ndarray: index {} is out of bounds in array of len {}",
887+
max_index, self.len_of(axis));
888+
}
889+
} // else: indices empty is ok
890+
let view = self.view().into_dimensionality::<Ix1>().unwrap();
891+
Array::from_iter(indices.iter().map(move |&index| {
892+
// Safety: bounds checked indexes
893+
unsafe {
894+
view.uget(index).clone()
895+
}
896+
})).into_dimensionality::<D>().unwrap()
888897
} else {
889-
concatenate(axis, &subs).unwrap()
898+
let mut subs = vec![self.view(); indices.len()];
899+
for (&i, sub) in zip(indices, &mut subs[..]) {
900+
sub.collapse_axis(axis, i);
901+
}
902+
if subs.is_empty() {
903+
let mut dim = self.raw_dim();
904+
dim.set_axis(axis, 0);
905+
unsafe { Array::from_shape_vec_unchecked(dim, vec![]) }
906+
} else {
907+
concatenate(axis, &subs).unwrap()
908+
}
890909
}
891910
}
892911

0 commit comments

Comments
 (0)