diff --git a/examples/bounds_check_elim.rs b/examples/bounds_check_elim.rs new file mode 100644 index 000000000..dc9e1e22a --- /dev/null +++ b/examples/bounds_check_elim.rs @@ -0,0 +1,103 @@ +#![crate_type="lib"] + +// Test cases for bounds check elimination + +extern crate ndarray; + +use ndarray::prelude::*; + +/* +pub fn testslice(a: &[f64]) -> f64 { + let mut sum = 0.; + for i in 0..a.len() { + sum += a[i]; + } + sum +} + +pub fn testvec(a: &Vec) -> f64 { + let mut sum = 0.; + for i in 0..a.len() { + sum += a[i]; + } + sum +} + +pub fn testvec_as_slice(a: &Vec) -> f64 { + let a = a.as_slice(); + let mut sum = 0.; + for i in 0..a.len() { + sum += a[i]; + } + sum +} +*/ + +#[no_mangle] +pub fn test1d_single(a: &Array1, i: usize) -> f64 { + if i < a.len() { a[i] } else { 0. } +} + +#[no_mangle] +pub fn test1d_single_mut(a: &mut Array1, i: usize) -> f64 { + if i < a.len() { *&mut a[i] } else { 0. } +} + +#[no_mangle] +pub fn test1d_len_of(a: &Array1) -> f64 { + let a = &*a; + let mut sum = 0.; + for i in 0..a.len_of(Axis(0)) { + sum += a[i]; + } + sum +} + +#[no_mangle] +pub fn test1d_range(a: &Array1) -> f64 { + let mut sum = 0.; + for i in 0..a.len() { + sum += a[i]; + } + sum +} + +#[no_mangle] +pub fn test1d_while(a: &Array1) -> f64 { + let mut sum = 0.; + let mut i = 0; + while i < a.len() { + sum += a[i]; + i += 1; + } + sum +} + +#[no_mangle] +pub fn test2d_ranges(a: &Array2) -> f64 { + let mut sum = 0.; + for i in 0..a.rows() { + for j in 0..a.cols() { + sum += a[[i, j]]; + } + } + sum +} + +#[no_mangle] +pub fn test2d_whiles(a: &Array2) -> f64 { + let mut sum = 0.; + let mut i = 0; + while i < a.rows() { + let mut j = 0; + while j < a.cols() { + sum += a[[i, j]]; + j += 1; + } + i += 1; + } + sum +} + +fn main() { +} diff --git a/src/arraytraits.rs b/src/arraytraits.rs index 4a8d209cb..d7f5710c0 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -69,7 +69,10 @@ impl Index for ArrayBase #[inline] fn index(&self, index: I) -> &S::Elem { debug_bounds_check!(self, index); - self.get(index).unwrap_or_else(|| array_out_of_bounds()) + unsafe { + &*self.ptr.offset(index.index_checked(&self.dim, &self.strides) + .unwrap_or_else(|| array_out_of_bounds())) + } } } @@ -84,7 +87,10 @@ impl IndexMut for ArrayBase #[inline] fn index_mut(&mut self, index: I) -> &mut S::Elem { debug_bounds_check!(self, index); - self.get_mut(index).unwrap_or_else(|| array_out_of_bounds()) + unsafe { + &mut *self.as_mut_ptr().offset(index.index_checked(&self.dim, &self.strides) + .unwrap_or_else(|| array_out_of_bounds())) + } } } diff --git a/tests/array.rs b/tests/array.rs index 85bae74b1..1b1981a8c 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -219,6 +219,41 @@ fn test_cow() assert_eq!(before[3], 1); } +#[test] +fn test_cow_shrink() +{ + // A test for clone-on-write in the case that + // mutation shrinks the array and gives it different strides + // + let mut mat = RcArray::zeros((2, 3)); + //mat.islice(s![.., ..;2]); + mat[[0, 0]] = 1; + let n = mat.clone(); + mat[[0, 1]] = 2; + mat[[0, 2]] = 3; + mat[[1, 0]] = 4; + mat[[1, 1]] = 5; + mat[[1, 2]] = 6; + assert_eq!(mat[[0, 0]], 1); + assert_eq!(mat[[0, 1]], 2); + assert_eq!(n[[0, 0]], 1); + assert_eq!(n[[0, 1]], 0); + assert_eq!(n.get((0, 1)), Some(&0)); + // small has non-C strides this way + let mut small = mat.reshape(6); + small.islice(s![4..;-1]); + assert_eq!(small[0], 6); + assert_eq!(small[1], 5); + let before = small.clone(); + // mutation + // small gets back C strides in CoW. + small[1] = 9; + assert_eq!(small[0], 6); + assert_eq!(small[1], 9); + assert_eq!(before[0], 6); + assert_eq!(before[1], 5); +} + #[test] fn test_sub() {