Skip to content

Commit

Permalink
Merge pull request #932 from rust-ndarray/append-row-column
Browse files Browse the repository at this point in the history
append, append_row, append_column: methods for appending an array or single rows and columns
  • Loading branch information
bluss authored Apr 13, 2021
2 parents fc3f836 + d946360 commit 77c6286
Show file tree
Hide file tree
Showing 13 changed files with 1,447 additions and 93 deletions.
35 changes: 35 additions & 0 deletions benches/append.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#![feature(test)]

extern crate test;
use test::Bencher;

use ndarray::prelude::*;

#[bench]
fn select_axis0(bench: &mut Bencher) {
let a = Array::<f32, _>::zeros((256, 256));
let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1];
bench.iter(|| {
a.select(Axis(0), &selectable)
});
}

#[bench]
fn select_axis1(bench: &mut Bencher) {
let a = Array::<f32, _>::zeros((256, 256));
let selectable = vec![0, 1, 2, 0, 1, 3, 0, 4, 16, 32, 128, 147, 149, 220, 221, 255, 221, 0, 1];
bench.iter(|| {
a.select(Axis(1), &selectable)
});
}

#[bench]
fn select_1d(bench: &mut Bencher) {
let a = Array::<f32, _>::zeros(1024);
let mut selectable = (0..a.len()).step_by(17).collect::<Vec<_>>();
selectable.extend(selectable.clone().iter().rev());

bench.iter(|| {
a.select(Axis(0), &selectable)
});
}
38 changes: 38 additions & 0 deletions src/data_repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use alloc::borrow::ToOwned;
use alloc::vec::Vec;
use crate::extension::nonnull;

use rawpointer::PointerExt;

/// Array's representation.
///
/// *Don’t use this type directly—use the type alias
Expand Down Expand Up @@ -55,6 +57,37 @@ impl<A> OwnedRepr<A> {
self.ptr
}

/// Return end pointer
pub(crate) fn as_end_nonnull(&self) -> NonNull<A> {
unsafe {
self.ptr.add(self.len)
}
}

/// Reserve `additional` elements; return the new pointer
///
/// ## Safety
///
/// Note that existing pointers into the data are invalidated
#[must_use = "must use new pointer to update existing pointers"]
pub(crate) fn reserve(&mut self, additional: usize) -> NonNull<A> {
self.modify_as_vec(|mut v| {
v.reserve(additional);
v
});
self.as_nonnull_mut()
}

/// Set the valid length of the data
///
/// ## Safety
///
/// The first `new_len` elements of the data should be valid.
pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(new_len <= self.capacity);
self.len = new_len;
}

/// Cast self into equivalent repr of other element type
///
/// ## Safety
Expand All @@ -72,6 +105,11 @@ impl<A> OwnedRepr<A> {
}
}

fn modify_as_vec(&mut self, f: impl FnOnce(Vec<A>) -> Vec<A>) {
let v = self.take_as_vec();
*self = Self::from(f(v));
}

fn take_as_vec(&mut self) -> Vec<A> {
let capacity = self.capacity;
let len = self.len;
Expand Down
39 changes: 29 additions & 10 deletions src/impl_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -873,20 +873,39 @@ where
/// ```
pub fn select(&self, axis: Axis, indices: &[Ix]) -> Array<A, D>
where
A: Copy,
A: Clone,
S: Data,
D: RemoveAxis,
{
let mut subs = vec![self.view(); indices.len()];
for (&i, sub) in zip(indices, &mut subs[..]) {
sub.collapse_axis(axis, i);
}
if subs.is_empty() {
let mut dim = self.raw_dim();
dim.set_axis(axis, 0);
unsafe { Array::from_shape_vec_unchecked(dim, vec![]) }
if self.ndim() == 1 {
// using .len_of(axis) means that we check if `axis` is in bounds too.
let axis_len = self.len_of(axis);
// bounds check the indices first
if let Some(max_index) = indices.iter().cloned().max() {
if max_index >= axis_len {
panic!("ndarray: index {} is out of bounds in array of len {}",
max_index, self.len_of(axis));
}
} // else: indices empty is ok
let view = self.view().into_dimensionality::<Ix1>().unwrap();
Array::from_iter(indices.iter().map(move |&index| {
// Safety: bounds checked indexes
unsafe {
view.uget(index).clone()
}
})).into_dimensionality::<D>().unwrap()
} else {
concatenate(axis, &subs).unwrap()
let mut subs = vec![self.view(); indices.len()];
for (&i, sub) in zip(indices, &mut subs[..]) {
sub.collapse_axis(axis, i);
}
if subs.is_empty() {
let mut dim = self.raw_dim();
dim.set_axis(axis, 0);
unsafe { Array::from_shape_vec_unchecked(dim, vec![]) }
} else {
concatenate(axis, &subs).unwrap()
}
}
}

Expand Down
Loading

0 comments on commit 77c6286

Please sign in to comment.