diff --git a/examples/functions_and_traits.rs b/examples/functions_and_traits.rs index dc8f73da4..56ec1f2e2 100644 --- a/examples/functions_and_traits.rs +++ b/examples/functions_and_traits.rs @@ -139,7 +139,7 @@ fn takes_rawref_mut(arr: &mut RawRef) /// Immutable, take a generic that implements `AsRef` to `RawRef` #[allow(dead_code)] fn takes_rawref_asref(_arr: &T) -where T: AsRef> +where T: AsRef> + ?Sized { takes_layout(_arr.as_ref()); takes_layout_asref(_arr.as_ref()); @@ -148,7 +148,7 @@ where T: AsRef> /// Mutable, take a generic that implements `AsMut` to `RawRef` #[allow(dead_code)] fn takes_rawref_asmut(_arr: &mut T) -where T: AsMut> +where T: AsMut> + ?Sized { takes_layout_mut(_arr.as_mut()); takes_layout_asmut(_arr.as_mut()); @@ -169,10 +169,16 @@ fn takes_layout_mut(_arr: &mut LayoutRef) {} /// Immutable, take a generic that implements `AsRef` to `LayoutRef` #[allow(dead_code)] -fn takes_layout_asref>, A, D>(_arr: &T) {} +fn takes_layout_asref(_arr: &T) +where T: AsRef> + ?Sized +{ +} /// Mutable, take a generic that implements `AsMut` to `LayoutRef` #[allow(dead_code)] -fn takes_layout_asmut>, A, D>(_arr: &mut T) {} +fn takes_layout_asmut(_arr: &mut T) +where T: AsMut> + ?Sized +{ +} fn main() {} diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh index 4135ebeb8..f6c9b27a8 100755 --- a/scripts/all-tests.sh +++ b/scripts/all-tests.sh @@ -30,5 +30,8 @@ fi # Examples cargo nextest run --examples +# Doc tests +cargo test --doc + # Benchmarks ([ "$CHANNEL" != "nightly" ] || cargo bench --no-run --verbose --features "$FEATURES") diff --git a/src/arraytraits.rs b/src/arraytraits.rs index a34b1985e..da87e3a58 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -19,7 +19,6 @@ use std::{iter::FromIterator, slice}; use crate::imp_prelude::*; use crate::Arc; -use crate::LayoutRef; use crate::{ dimension, iter::{Iter, IterMut}, @@ -38,12 +37,14 @@ pub(crate) fn array_out_of_bounds() -> ! } #[inline(always)] -pub fn debug_bounds_check(_a: &LayoutRef, _index: &I) +pub fn debug_bounds_check(_a: &T, _index: &I) where D: Dimension, I: NdIndex, + T: AsRef> + ?Sized, { - debug_bounds_check!(_a, *_index); + let _layout_ref = _a.as_ref(); + debug_bounds_check_ref!(_layout_ref, *_index); } /// Access the element at **index**. @@ -59,11 +60,11 @@ where #[inline] fn index(&self, index: I) -> &Self::Output { - debug_bounds_check!(self, index); + debug_bounds_check_ref!(self, index); unsafe { - &*self.ptr.as_ptr().offset( + &*self._ptr().as_ptr().offset( index - .index_checked(&self.dim, &self.strides) + .index_checked(self._dim(), self._strides()) .unwrap_or_else(|| array_out_of_bounds()), ) } @@ -81,11 +82,11 @@ where #[inline] fn index_mut(&mut self, index: I) -> &mut A { - debug_bounds_check!(self, index); + debug_bounds_check_ref!(self, index); unsafe { &mut *self.as_mut_ptr().offset( index - .index_checked(&self.dim, &self.strides) + .index_checked(self._dim(), self._strides()) .unwrap_or_else(|| array_out_of_bounds()), ) } @@ -581,7 +582,7 @@ where D: Dimension { let data = OwnedArcRepr(Arc::new(arr.data)); // safe because: equivalent unmoved data, ptr and dims remain valid - unsafe { ArrayBase::from_data_ptr(data, arr.layout.ptr).with_strides_dim(arr.layout.strides, arr.layout.dim) } + unsafe { ArrayBase::from_data_ptr(data, arr.parts.ptr).with_strides_dim(arr.parts.strides, arr.parts.dim) } } } diff --git a/src/data_traits.rs b/src/data_traits.rs index 4266e4017..a0b33ea12 100644 --- a/src/data_traits.rs +++ b/src/data_traits.rs @@ -251,7 +251,7 @@ where A: Clone if Arc::get_mut(&mut self_.data.0).is_some() { return; } - if self_.layout.dim.size() <= self_.data.0.len() / 2 { + if self_.parts.dim.size() <= self_.data.0.len() / 2 { // Clone only the visible elements if the current view is less than // half of backing data. *self_ = self_.to_owned().into_shared(); @@ -260,13 +260,13 @@ where A: Clone let rcvec = &mut self_.data.0; let a_size = mem::size_of::() as isize; let our_off = if a_size != 0 { - (self_.layout.ptr.as_ptr() as isize - rcvec.as_ptr() as isize) / a_size + (self_.parts.ptr.as_ptr() as isize - rcvec.as_ptr() as isize) / a_size } else { 0 }; let rvec = Arc::make_mut(rcvec); unsafe { - self_.layout.ptr = rvec.as_nonnull_mut().offset(our_off); + self_.parts.ptr = rvec.as_nonnull_mut().offset(our_off); } } @@ -287,7 +287,7 @@ unsafe impl Data for OwnedArcRepr let data = Arc::try_unwrap(self_.data.0).ok().unwrap(); // safe because data is equivalent unsafe { - ArrayBase::from_data_ptr(data, self_.layout.ptr).with_strides_dim(self_.layout.strides, self_.layout.dim) + ArrayBase::from_data_ptr(data, self_.parts.ptr).with_strides_dim(self_.parts.strides, self_.parts.dim) } } @@ -297,14 +297,14 @@ unsafe impl Data for OwnedArcRepr match Arc::try_unwrap(self_.data.0) { Ok(owned_data) => unsafe { // Safe because the data is equivalent. - Ok(ArrayBase::from_data_ptr(owned_data, self_.layout.ptr) - .with_strides_dim(self_.layout.strides, self_.layout.dim)) + Ok(ArrayBase::from_data_ptr(owned_data, self_.parts.ptr) + .with_strides_dim(self_.parts.strides, self_.parts.dim)) }, Err(arc_data) => unsafe { // Safe because the data is equivalent; we're just // reconstructing `self_`. - Err(ArrayBase::from_data_ptr(OwnedArcRepr(arc_data), self_.layout.ptr) - .with_strides_dim(self_.layout.strides, self_.layout.dim)) + Err(ArrayBase::from_data_ptr(OwnedArcRepr(arc_data), self_.parts.ptr) + .with_strides_dim(self_.parts.strides, self_.parts.dim)) }, } } @@ -603,9 +603,9 @@ where A: Clone CowRepr::View(_) => { let owned = ArrayRef::to_owned(array); array.data = CowRepr::Owned(owned.data); - array.layout.ptr = owned.layout.ptr; - array.layout.dim = owned.layout.dim; - array.layout.strides = owned.layout.strides; + array.parts.ptr = owned.parts.ptr; + array.parts.dim = owned.parts.dim; + array.parts.strides = owned.parts.strides; } CowRepr::Owned(_) => {} } @@ -666,8 +666,7 @@ unsafe impl<'a, A> Data for CowRepr<'a, A> CowRepr::View(_) => self_.to_owned(), CowRepr::Owned(data) => unsafe { // safe because the data is equivalent so ptr, dims remain valid - ArrayBase::from_data_ptr(data, self_.layout.ptr) - .with_strides_dim(self_.layout.strides, self_.layout.dim) + ArrayBase::from_data_ptr(data, self_.parts.ptr).with_strides_dim(self_.parts.strides, self_.parts.dim) }, } } @@ -679,8 +678,8 @@ unsafe impl<'a, A> Data for CowRepr<'a, A> CowRepr::View(_) => Err(self_), CowRepr::Owned(data) => unsafe { // safe because the data is equivalent so ptr, dims remain valid - Ok(ArrayBase::from_data_ptr(data, self_.layout.ptr) - .with_strides_dim(self_.layout.strides, self_.layout.dim)) + Ok(ArrayBase::from_data_ptr(data, self_.parts.ptr) + .with_strides_dim(self_.parts.strides, self_.parts.dim)) }, } } diff --git a/src/free_functions.rs b/src/free_functions.rs index a2ad6137c..4ad69f2c3 100644 --- a/src/free_functions.rs +++ b/src/free_functions.rs @@ -16,7 +16,7 @@ use std::mem::{forget, size_of}; use std::ptr::NonNull; use crate::{dimension, ArcArray1, ArcArray2}; -use crate::{imp_prelude::*, LayoutRef}; +use crate::{imp_prelude::*, ArrayPartsSized}; /// Create an **[`Array`]** with one, two, three, four, five, or six dimensions. /// @@ -109,12 +109,12 @@ pub const fn aview0(x: &A) -> ArrayView0<'_, A> { ArrayBase { data: ViewRepr::new(), - layout: LayoutRef { + parts: ArrayPartsSized::new( // Safe because references are always non-null. - ptr: unsafe { NonNull::new_unchecked(x as *const A as *mut A) }, - dim: Ix0(), - strides: Ix0(), - }, + unsafe { NonNull::new_unchecked(x as *const A as *mut A) }, + Ix0(), + Ix0(), + ), } } @@ -149,12 +149,12 @@ pub const fn aview1(xs: &[A]) -> ArrayView1<'_, A> } ArrayBase { data: ViewRepr::new(), - layout: LayoutRef { + parts: ArrayPartsSized::new( // Safe because references are always non-null. - ptr: unsafe { NonNull::new_unchecked(xs.as_ptr() as *mut A) }, - dim: Ix1(xs.len()), - strides: Ix1(1), - }, + unsafe { NonNull::new_unchecked(xs.as_ptr() as *mut A) }, + Ix1(xs.len()), + Ix1(1), + ), } } @@ -207,7 +207,7 @@ pub const fn aview2(xs: &[[A; N]]) -> ArrayView2<'_, A> }; ArrayBase { data: ViewRepr::new(), - layout: LayoutRef { ptr, dim, strides }, + parts: ArrayPartsSized::new(ptr, dim, strides), } } diff --git a/src/impl_clone.rs b/src/impl_clone.rs index 402437941..bef783bd8 100644 --- a/src/impl_clone.rs +++ b/src/impl_clone.rs @@ -7,7 +7,7 @@ // except according to those terms. use crate::imp_prelude::*; -use crate::LayoutRef; +use crate::ArrayPartsSized; use crate::RawDataClone; impl Clone for ArrayBase @@ -16,14 +16,10 @@ impl Clone for ArrayBase { // safe because `clone_with_ptr` promises to provide equivalent data and ptr unsafe { - let (data, ptr) = self.data.clone_with_ptr(self.layout.ptr); + let (data, ptr) = self.data.clone_with_ptr(self.parts.ptr); ArrayBase { data, - layout: LayoutRef { - ptr, - dim: self.layout.dim.clone(), - strides: self.layout.strides.clone(), - }, + parts: ArrayPartsSized::new(ptr, self.parts.dim.clone(), self.parts.strides.clone()), } } } @@ -34,9 +30,9 @@ impl Clone for ArrayBase fn clone_from(&mut self, other: &Self) { unsafe { - self.layout.ptr = self.data.clone_from_with_ptr(&other.data, other.layout.ptr); - self.layout.dim.clone_from(&other.layout.dim); - self.layout.strides.clone_from(&other.layout.strides); + self.parts.ptr = self.data.clone_from_with_ptr(&other.data, other.parts.ptr); + self.parts.dim.clone_from(&other.parts.dim); + self.parts.strides.clone_from(&other.parts.strides); } } } diff --git a/src/impl_cow.rs b/src/impl_cow.rs index 0ecc3c44b..1a28996d6 100644 --- a/src/impl_cow.rs +++ b/src/impl_cow.rs @@ -34,8 +34,8 @@ where D: Dimension { // safe because equivalent data unsafe { - ArrayBase::from_data_ptr(CowRepr::View(view.data), view.ptr) - .with_strides_dim(view.layout.strides, view.layout.dim) + ArrayBase::from_data_ptr(CowRepr::View(view.data), view.parts.ptr) + .with_strides_dim(view.parts.strides, view.parts.dim) } } } @@ -47,8 +47,8 @@ where D: Dimension { // safe because equivalent data unsafe { - ArrayBase::from_data_ptr(CowRepr::Owned(array.data), array.layout.ptr) - .with_strides_dim(array.layout.strides, array.layout.dim) + ArrayBase::from_data_ptr(CowRepr::Owned(array.data), array.parts.ptr) + .with_strides_dim(array.parts.strides, array.parts.dim) } } } diff --git a/src/impl_dyn.rs b/src/impl_dyn.rs index 409fe991a..404f3d4b6 100644 --- a/src/impl_dyn.rs +++ b/src/impl_dyn.rs @@ -31,8 +31,8 @@ impl LayoutRef pub fn insert_axis_inplace(&mut self, axis: Axis) { assert!(axis.index() <= self.ndim()); - self.dim = self.dim.insert_axis(axis); - self.strides = self.strides.insert_axis(axis); + self.0.dim = self._dim().insert_axis(axis); + self.0.strides = self._strides().insert_axis(axis); } /// Collapses the array to `index` along the axis and removes the axis, @@ -54,8 +54,8 @@ impl LayoutRef pub fn index_axis_inplace(&mut self, axis: Axis, index: usize) { self.collapse_axis(axis, index); - self.dim = self.dim.remove_axis(axis); - self.strides = self.strides.remove_axis(axis); + self.0.dim = self._dim().remove_axis(axis); + self.0.strides = self._strides().remove_axis(axis); } } diff --git a/src/impl_internal_constructors.rs b/src/impl_internal_constructors.rs index 7f95339d5..ef2964fff 100644 --- a/src/impl_internal_constructors.rs +++ b/src/impl_internal_constructors.rs @@ -8,7 +8,7 @@ use std::ptr::NonNull; -use crate::{imp_prelude::*, LayoutRef}; +use crate::{imp_prelude::*, ArrayPartsSized}; // internal "builder-like" methods impl ArrayBase @@ -27,11 +27,7 @@ where S: RawData { let array = ArrayBase { data, - layout: LayoutRef { - ptr, - dim: Ix1(0), - strides: Ix1(1), - }, + parts: ArrayPartsSized::new(ptr, Ix1(0), Ix1(1)), }; debug_assert!(array.pointer_is_inbounds()); array @@ -60,11 +56,7 @@ where debug_assert_eq!(strides.ndim(), dim.ndim()); ArrayBase { data: self.data, - layout: LayoutRef { - ptr: self.layout.ptr, - dim, - strides, - }, + parts: ArrayPartsSized::new(self.parts.ptr, dim, strides), } } } diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 453cc05b3..2170a8d93 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -70,7 +70,7 @@ impl LayoutRef /// Return the total number of elements in the array. pub fn len(&self) -> usize { - self.dim.size() + self._dim().size() } /// Return the length of `axis`. @@ -82,7 +82,7 @@ impl LayoutRef #[track_caller] pub fn len_of(&self, axis: Axis) -> usize { - self.dim[axis.index()] + self._dim()[axis.index()] } /// Return whether the array has any elements @@ -94,7 +94,7 @@ impl LayoutRef /// Return the number of dimensions (axes) in the array pub fn ndim(&self) -> usize { - self.dim.ndim() + self._dim().ndim() } /// Return the shape of the array in its “pattern” form, @@ -102,7 +102,7 @@ impl LayoutRef /// and so on. pub fn dim(&self) -> D::Pattern { - self.dim.clone().into_pattern() + self._dim().clone().into_pattern() } /// Return the shape of the array as it's stored in the array. @@ -121,7 +121,7 @@ impl LayoutRef /// ``` pub fn raw_dim(&self) -> D { - self.dim.clone() + self._dim().clone() } /// Return the shape of the array as a slice. @@ -150,13 +150,13 @@ impl LayoutRef /// ``` pub fn shape(&self) -> &[usize] { - self.dim.slice() + self._dim().slice() } /// Return the strides of the array as a slice. pub fn strides(&self) -> &[isize] { - let s = self.strides.slice(); + let s = self._strides().slice(); // reinterpret unsigned integer as signed unsafe { slice::from_raw_parts(s.as_ptr() as *const _, s.len()) } } @@ -171,7 +171,7 @@ impl LayoutRef pub fn stride_of(&self, axis: Axis) -> isize { // strides are reinterpreted as isize - self.strides[axis.index()] as isize + self._strides()[axis.index()] as isize } } @@ -181,13 +181,13 @@ impl ArrayRef pub fn view(&self) -> ArrayView<'_, A, D> { // debug_assert!(self.pointer_is_inbounds()); - unsafe { ArrayView::new(self.ptr, self.dim.clone(), self.strides.clone()) } + unsafe { ArrayView::new(*self._ptr(), self._dim().clone(), self._strides().clone()) } } /// Return a read-write view of the array pub fn view_mut(&mut self) -> ArrayViewMut<'_, A, D> { - unsafe { ArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) } + unsafe { ArrayViewMut::new(*self._ptr(), self._dim().clone(), self._strides().clone()) } } /// Return a shared view of the array with elements as if they were embedded in cells. @@ -236,7 +236,9 @@ impl ArrayRef where A: Clone { if let Some(slc) = self.as_slice_memory_order() { - unsafe { Array::from_shape_vec_unchecked(self.dim.clone().strides(self.strides.clone()), slc.to_vec()) } + unsafe { + Array::from_shape_vec_unchecked(self._dim().clone().strides(self._strides().clone()), slc.to_vec()) + } } else { self.map(A::clone) } @@ -588,8 +590,8 @@ where // Slice the axis in-place to update the `dim`, `strides`, and `ptr`. self.slice_axis_inplace(Axis(old_axis), Slice { start, end, step }); // Copy the sliced dim and stride to corresponding axis. - new_dim[new_axis] = self.layout.dim[old_axis]; - new_strides[new_axis] = self.layout.strides[old_axis]; + new_dim[new_axis] = self.parts.dim[old_axis]; + new_strides[new_axis] = self.parts.strides[old_axis]; old_axis += 1; new_axis += 1; } @@ -700,10 +702,11 @@ impl LayoutRef #[track_caller] pub fn slice_axis_inplace(&mut self, axis: Axis, indices: Slice) { + let parts = &mut self.0; let offset = - do_slice(&mut self.dim.slice_mut()[axis.index()], &mut self.strides.slice_mut()[axis.index()], indices); + do_slice(&mut parts.dim.slice_mut()[axis.index()], &mut parts.strides.slice_mut()[axis.index()], indices); unsafe { - self.ptr = self.ptr.offset(offset); + self.0.ptr = self._ptr().offset(offset); } // debug_assert!(self.pointer_is_inbounds()); } @@ -779,8 +782,8 @@ impl LayoutRef Axis(ax), f(AxisDescription { axis: Axis(ax), - len: self.dim[ax], - stride: self.strides[ax] as isize, + len: self._dim()[ax], + stride: self._strides()[ax] as isize, }), ) } @@ -832,9 +835,9 @@ impl RawRef pub fn get_ptr(&self, index: I) -> Option<*const A> where I: NdIndex { - let ptr = self.ptr; + let ptr = self._ptr(); index - .index_checked(&self.dim, &self.strides) + .index_checked(self._dim(), self._strides()) .map(move |offset| unsafe { ptr.as_ptr().offset(offset) as *const _ }) } } @@ -876,7 +879,7 @@ impl RawRef // extra code in as_mut_ptr let ptr = self.as_mut_ptr(); index - .index_checked(&self.dim, &self.strides) + .index_checked(self._dim(), self._strides()) .map(move |offset| unsafe { ptr.offset(offset) }) } } @@ -897,8 +900,8 @@ impl ArrayRef where I: NdIndex { arraytraits::debug_bounds_check(self, &index); - let off = index.index_unchecked(&self.strides); - &*self.ptr.as_ptr().offset(off) + let off = index.index_unchecked(self._strides()); + &*self._ptr().as_ptr().offset(off) } /// Perform *unchecked* array indexing. @@ -921,8 +924,8 @@ impl ArrayRef { // debug_assert!(self.data.is_unique()); arraytraits::debug_bounds_check(self, &index); - let off = index.index_unchecked(&self.strides); - &mut *self.ptr.as_ptr().offset(off) + let off = index.index_unchecked(self._strides()); + &mut *self._ptr().as_ptr().offset(off) } /// Swap elements at indices `index1` and `index2`. @@ -935,8 +938,8 @@ impl ArrayRef where I: NdIndex { let ptr = self.as_mut_ptr(); - let offset1 = index1.index_checked(&self.dim, &self.strides); - let offset2 = index2.index_checked(&self.dim, &self.strides); + let offset1 = index1.index_checked(self._dim(), self._strides()); + let offset2 = index2.index_checked(self._dim(), self._strides()); if let Some(offset1) = offset1 { if let Some(offset2) = offset2 { unsafe { @@ -968,9 +971,9 @@ impl ArrayRef // debug_assert!(self.data.is_unique()); arraytraits::debug_bounds_check(self, &index1); arraytraits::debug_bounds_check(self, &index2); - let off1 = index1.index_unchecked(&self.strides); - let off2 = index2.index_unchecked(&self.strides); - std::ptr::swap(self.ptr.as_ptr().offset(off1), self.ptr.as_ptr().offset(off2)); + let off1 = index1.index_unchecked(self._strides()); + let off2 = index2.index_unchecked(self._strides()); + std::ptr::swap(self._ptr().as_ptr().offset(off1), self._ptr().as_ptr().offset(off2)); } // `get` for zero-dimensional arrays @@ -1056,8 +1059,8 @@ where where D: RemoveAxis { self.collapse_axis(axis, index); - let dim = self.layout.dim.remove_axis(axis); - let strides = self.layout.strides.remove_axis(axis); + let dim = self.parts.dim.remove_axis(axis); + let strides = self.parts.strides.remove_axis(axis); // safe because new dimension, strides allow access to a subset of old data unsafe { self.with_strides_dim(strides, dim) } } @@ -1071,8 +1074,9 @@ impl LayoutRef #[track_caller] pub fn collapse_axis(&mut self, axis: Axis, index: usize) { - let offset = dimension::do_collapse_axis(&mut self.dim, &self.strides, axis.index(), index); - self.ptr = unsafe { self.ptr.offset(offset) }; + let parts = &mut self.0; + let offset = dimension::do_collapse_axis(&mut parts.dim, &parts.strides, axis.index(), index); + self.0.ptr = unsafe { self._ptr().offset(offset) }; // debug_assert!(self.pointer_is_inbounds()); } } @@ -1571,7 +1575,7 @@ where fn diag_params(&self) -> (Ix, Ixs) { /* empty shape has len 1 */ - let len = self.layout.dim.slice().iter().cloned().min().unwrap_or(1); + let len = self.parts.dim.slice().iter().cloned().min().unwrap_or(1); let stride = self.strides().iter().sum(); (len, stride) } @@ -1618,13 +1622,13 @@ impl LayoutRef /// contiguous in memory, it has custom strides, etc. pub fn is_standard_layout(&self) -> bool { - dimension::is_layout_c(&self.dim, &self.strides) + dimension::is_layout_c(self._dim(), self._strides()) } /// Return true if the array is known to be contiguous. pub(crate) fn is_contiguous(&self) -> bool { - D::is_contiguous(&self.dim, &self.strides) + D::is_contiguous(self._dim(), self._strides()) } } @@ -1659,7 +1663,7 @@ impl ArrayRef CowArray::from(self.view()) } else { let v = crate::iterators::to_vec_mapped(self.iter(), A::clone); - let dim = self.dim.clone(); + let dim = self._dim().clone(); debug_assert_eq!(v.len(), dim.size()); unsafe { @@ -1685,14 +1689,14 @@ impl RawRef #[inline(always)] pub fn as_ptr(&self) -> *const A { - self.ptr.as_ptr() as *const A + self._ptr().as_ptr() as *const A } /// Return a mutable pointer to the first element in the array reference. #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut A { - self.ptr.as_ptr() + self._ptr().as_ptr() } } @@ -1716,7 +1720,7 @@ where where S: RawDataMut { self.try_ensure_unique(); // for ArcArray - self.layout.ptr.as_ptr() + self.parts.ptr.as_ptr() } } @@ -1726,14 +1730,14 @@ impl RawRef #[inline] pub fn raw_view(&self) -> RawArrayView { - unsafe { RawArrayView::new(self.ptr, self.dim.clone(), self.strides.clone()) } + unsafe { RawArrayView::new(*self._ptr(), self._dim().clone(), self._strides().clone()) } } /// Return a raw mutable view of the array. #[inline] pub fn raw_view_mut(&mut self) -> RawArrayViewMut { - unsafe { RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) } + unsafe { RawArrayViewMut::new(*self._ptr(), self._dim().clone(), self._strides().clone()) } } } @@ -1751,7 +1755,7 @@ where where S: RawDataMut { self.try_ensure_unique(); // for ArcArray - unsafe { RawArrayViewMut::new(self.layout.ptr, self.layout.dim.clone(), self.layout.strides.clone()) } + unsafe { RawArrayViewMut::new(self.parts.ptr, self.parts.dim.clone(), self.parts.strides.clone()) } } /// Return a raw mutable view of the array. @@ -1761,7 +1765,7 @@ where pub(crate) unsafe fn raw_view_mut_unchecked(&mut self) -> RawArrayViewMut where S: DataOwned { - RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) + RawArrayViewMut::new(*self._ptr(), self._dim().clone(), self._strides().clone()) } /// Return the array’s data as a slice, if it is contiguous and in standard order. @@ -1771,7 +1775,7 @@ where { if self.is_standard_layout() { self.ensure_unique(); - unsafe { Some(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) } + unsafe { Some(slice::from_raw_parts_mut(self._ptr().as_ptr(), self.len())) } } else { None } @@ -1796,8 +1800,8 @@ where { if self.is_contiguous() { self.ensure_unique(); - let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides); - unsafe { Ok(slice::from_raw_parts_mut(self.ptr.sub(offset).as_ptr(), self.len())) } + let offset = offset_from_low_addr_ptr_to_logical_ptr(self._dim(), self._strides()); + unsafe { Ok(slice::from_raw_parts_mut(self._ptr().sub(offset).as_ptr(), self.len())) } } else { Err(self) } @@ -1814,7 +1818,7 @@ impl ArrayRef pub fn as_slice(&self) -> Option<&[A]> { if self.is_standard_layout() { - unsafe { Some(slice::from_raw_parts(self.ptr.as_ptr(), self.len())) } + unsafe { Some(slice::from_raw_parts(self._ptr().as_ptr(), self.len())) } } else { None } @@ -1825,7 +1829,7 @@ impl ArrayRef pub fn as_slice_mut(&mut self) -> Option<&mut [A]> { if self.is_standard_layout() { - unsafe { Some(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) } + unsafe { Some(slice::from_raw_parts_mut(self._ptr().as_ptr(), self.len())) } } else { None } @@ -1839,8 +1843,8 @@ impl ArrayRef pub fn as_slice_memory_order(&self) -> Option<&[A]> { if self.is_contiguous() { - let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides); - unsafe { Some(slice::from_raw_parts(self.ptr.sub(offset).as_ptr(), self.len())) } + let offset = offset_from_low_addr_ptr_to_logical_ptr(self._dim(), self._strides()); + unsafe { Some(slice::from_raw_parts(self._ptr().sub(offset).as_ptr(), self.len())) } } else { None } @@ -1862,8 +1866,8 @@ impl ArrayRef pub(crate) fn try_as_slice_memory_order_mut(&mut self) -> Result<&mut [A], &mut Self> { if self.is_contiguous() { - let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides); - unsafe { Ok(slice::from_raw_parts_mut(self.ptr.sub(offset).as_ptr(), self.len())) } + let offset = offset_from_low_addr_ptr_to_logical_ptr(self._dim(), self._strides()); + unsafe { Ok(slice::from_raw_parts_mut(self._ptr().sub(offset).as_ptr(), self.len())) } } else { Err(self) } @@ -1938,9 +1942,9 @@ impl ArrayRef E: Dimension, A: Clone, { - let len = self.dim.size(); + let len = self._dim().size(); if size_of_shape_checked(&shape) != Ok(len) { - return Err(error::incompatible_shapes(&self.dim, &shape)); + return Err(error::incompatible_shapes(self._dim(), &shape)); } // Create a view if the length is 0, safe because the array and new shape is empty. @@ -1951,12 +1955,12 @@ impl ArrayRef } // Try to reshape the array as a view into the existing data - match reshape_dim(&self.dim, &self.strides, &shape, order) { + match reshape_dim(self._dim(), self._strides(), &shape, order) { Ok(to_strides) => unsafe { - return Ok(CowArray::from(ArrayView::new(self.ptr, shape, to_strides))); + return Ok(CowArray::from(ArrayView::new(*self._ptr(), shape, to_strides))); }, Err(err) if err.kind() == ErrorKind::IncompatibleShape => { - return Err(error::incompatible_shapes(&self.dim, &shape)); + return Err(error::incompatible_shapes(self._dim(), &shape)); } _otherwise => {} } @@ -2033,8 +2037,8 @@ where where E: Dimension { let shape = shape.into_dimension(); - if size_of_shape_checked(&shape) != Ok(self.layout.dim.size()) { - return Err(error::incompatible_shapes(&self.layout.dim, &shape)); + if size_of_shape_checked(&shape) != Ok(self.parts.dim.size()) { + return Err(error::incompatible_shapes(&self.parts.dim, &shape)); } // Check if contiguous, then we can change shape @@ -2078,8 +2082,8 @@ where where E: IntoDimension { let shape = shape.into_dimension(); - if size_of_shape_checked(&shape) != Ok(self.layout.dim.size()) { - return Err(error::incompatible_shapes(&self.layout.dim, &shape)); + if size_of_shape_checked(&shape) != Ok(self.parts.dim.size()) { + return Err(error::incompatible_shapes(&self.parts.dim, &shape)); } // Check if contiguous, if not => copy all, else just adapt strides unsafe { @@ -2124,9 +2128,9 @@ where A: Clone, E: Dimension, { - let len = self.dim.size(); + let len = self._dim().size(); if size_of_shape_checked(&shape) != Ok(len) { - return Err(error::incompatible_shapes(&self.dim, &shape)); + return Err(error::incompatible_shapes(self._dim(), &shape)); } // Safe because the array and new shape is empty. @@ -2137,12 +2141,12 @@ where } // Try to reshape the array's current data - match reshape_dim(&self.dim, &self.strides, &shape, order) { + match reshape_dim(self._dim(), self._strides(), &shape, order) { Ok(to_strides) => unsafe { return Ok(self.with_strides_dim(to_strides, shape)); }, Err(err) if err.kind() == ErrorKind::IncompatibleShape => { - return Err(error::incompatible_shapes(&self.dim, &shape)); + return Err(error::incompatible_shapes(self._dim(), &shape)); } _otherwise => {} } @@ -2190,10 +2194,10 @@ where E: IntoDimension, { let shape = shape.into_dimension(); - if size_of_shape_checked(&shape) != Ok(self.dim.size()) { + if size_of_shape_checked(&shape) != Ok(self._dim().size()) { panic!( "ndarray: incompatible shapes in reshape, attempted from: {:?}, to: {:?}", - self.dim.slice(), + self._dim().slice(), shape.slice() ) } @@ -2289,8 +2293,8 @@ where { // safe because new dims equivalent unsafe { - ArrayBase::from_data_ptr(self.data, self.layout.ptr) - .with_strides_dim(self.layout.strides.into_dyn(), self.layout.dim.into_dyn()) + ArrayBase::from_data_ptr(self.data, self.parts.ptr) + .with_strides_dim(self.parts.strides.into_dyn(), self.parts.dim.into_dyn()) } } @@ -2316,14 +2320,14 @@ where unsafe { if D::NDIM == D2::NDIM { // safe because D == D2 - let dim = unlimited_transmute::(self.layout.dim); - let strides = unlimited_transmute::(self.layout.strides); - return Ok(ArrayBase::from_data_ptr(self.data, self.layout.ptr).with_strides_dim(strides, dim)); + let dim = unlimited_transmute::(self.parts.dim); + let strides = unlimited_transmute::(self.parts.strides); + return Ok(ArrayBase::from_data_ptr(self.data, self.parts.ptr).with_strides_dim(strides, dim)); } else if D::NDIM.is_none() || D2::NDIM.is_none() { // one is dynamic dim // safe because dim, strides are equivalent under a different type - if let Some(dim) = D2::from_dimension(&self.layout.dim) { - if let Some(strides) = D2::from_dimension(&self.layout.strides) { + if let Some(dim) = D2::from_dimension(&self.parts.dim) { + if let Some(strides) = D2::from_dimension(&self.parts.strides) { return Ok(self.with_strides_dim(strides, dim)); } } @@ -2421,8 +2425,8 @@ impl ArrayRef let dim = dim.into_dimension(); // Note: zero strides are safe precisely because we return an read-only view - let broadcast_strides = upcast(&dim, &self.dim, &self.strides)?; - unsafe { Some(ArrayView::new(self.ptr, dim, broadcast_strides)) } + let broadcast_strides = upcast(&dim, self._dim(), self._strides())?; + unsafe { Some(ArrayView::new(*self._ptr(), dim, broadcast_strides)) } } /// For two arrays or views, find their common shape if possible and @@ -2437,8 +2441,8 @@ impl ArrayRef D: Dimension + DimMax, E: Dimension, { - let shape = co_broadcast::>::Output>(&self.dim, &other.dim)?; - let view1 = if shape.slice() == self.dim.slice() { + let shape = co_broadcast::>::Output>(self._dim(), other._dim())?; + let view1 = if shape.slice() == self._dim().slice() { self.view() .into_dimensionality::<>::Output>() .unwrap() @@ -2447,7 +2451,7 @@ impl ArrayRef } else { return Err(from_kind(ErrorKind::IncompatibleShape)); }; - let view2 = if shape.slice() == other.dim.slice() { + let view2 = if shape.slice() == other._dim().slice() { other .view() .into_dimensionality::<>::Output>() @@ -2482,8 +2486,8 @@ impl LayoutRef #[track_caller] pub fn swap_axes(&mut self, ax: usize, bx: usize) { - self.dim.slice_mut().swap(ax, bx); - self.strides.slice_mut().swap(ax, bx); + self.0.dim.slice_mut().swap(ax, bx); + self.0.strides.slice_mut().swap(ax, bx); } } @@ -2531,8 +2535,8 @@ where let mut new_dim = usage_counts; // reuse to avoid an allocation let mut new_strides = D::zeros(self.ndim()); { - let dim = self.layout.dim.slice(); - let strides = self.layout.strides.slice(); + let dim = self.parts.dim.slice(); + let strides = self.parts.strides.slice(); for (new_axis, &axis) in axes.slice().iter().enumerate() { new_dim[new_axis] = dim[axis]; new_strides[new_axis] = strides[axis]; @@ -2579,8 +2583,8 @@ where assert_eq!(*count, 1, "each axis must be listed exactly once"); } - let dim = self.layout.dim.slice_mut(); - let strides = self.layout.strides.slice_mut(); + let dim = self.parts.dim.slice_mut(); + let strides = self.parts.strides.slice_mut(); let axes = axes.slice(); // The cycle detection is done using a bitmask to track visited positions. @@ -2614,8 +2618,8 @@ where /// while retaining the same data. pub fn reversed_axes(mut self) -> ArrayBase { - self.layout.dim.slice_mut().reverse(); - self.layout.strides.slice_mut().reverse(); + self.parts.dim.slice_mut().reverse(); + self.parts.strides.slice_mut().reverse(); self } @@ -2625,8 +2629,8 @@ where /// and strides. pub fn reverse_axes(&mut self) { - self.layout.dim.slice_mut().reverse(); - self.layout.strides.slice_mut().reverse(); + self.parts.dim.slice_mut().reverse(); + self.parts.strides.slice_mut().reverse(); } } @@ -2648,13 +2652,13 @@ impl LayoutRef /// Return an iterator over the length and stride of each axis. pub fn axes(&self) -> Axes<'_, D> { - axes_of(&self.dim, &self.strides) + axes_of(self._dim(), self._strides()) } /* /// Return the axis with the least stride (by absolute value) pub fn min_stride_axis(&self) -> Axis { - self.dim.min_stride_axis(&self.strides) + self._dim().min_stride_axis(self._strides()) } */ @@ -2662,7 +2666,7 @@ impl LayoutRef /// preferring axes with len > 1. pub fn max_stride_axis(&self) -> Axis { - self.dim.max_stride_axis(&self.strides) + self._dim().max_stride_axis(self._strides()) } /// Reverse the stride of `axis`. @@ -2672,12 +2676,12 @@ impl LayoutRef pub fn invert_axis(&mut self, axis: Axis) { unsafe { - let s = self.strides.axis(axis) as Ixs; - let m = self.dim.axis(axis); + let s = self._strides().axis(axis) as Ixs; + let m = self._dim().axis(axis); if m != 0 { - self.ptr = self.ptr.offset(stride_offset(m - 1, s as Ix)); + self.0.ptr = self._ptr().offset(stride_offset(m - 1, s as Ix)); } - self.strides.set_axis(axis, (-s) as Ix); + self.0.strides.set_axis(axis, (-s) as Ix); } } @@ -2719,7 +2723,8 @@ impl LayoutRef #[track_caller] pub fn merge_axes(&mut self, take: Axis, into: Axis) -> bool { - merge_axes(&mut self.dim, &mut self.strides, take, into) + let parts = &mut self.0; + merge_axes(&mut parts.dim, &mut parts.strides, take, into) } } @@ -2755,8 +2760,8 @@ where assert!(axis.index() <= self.ndim()); // safe because a new axis of length one does not affect memory layout unsafe { - let strides = self.layout.strides.insert_axis(axis); - let dim = self.layout.dim.insert_axis(axis); + let strides = self.parts.strides.insert_axis(axis); + let dim = self.parts.dim.insert_axis(axis); self.with_strides_dim(strides, dim) } } @@ -2824,7 +2829,10 @@ impl ArrayRef { debug_assert_eq!(self.shape(), rhs.shape()); - if self.dim.strides_equivalent(&self.strides, &rhs.strides) { + if self + ._dim() + .strides_equivalent(self._strides(), rhs._strides()) + { if let Some(self_s) = self.as_slice_memory_order_mut() { if let Some(rhs_s) = rhs.as_slice_memory_order() { for (s, r) in self_s.iter_mut().zip(rhs_s) { @@ -2876,10 +2884,10 @@ impl ArrayRef E: Dimension, F: FnMut(&mut A, &B), { - if rhs.dim.ndim() == 0 { + if rhs._dim().ndim() == 0 { // Skip broadcast from 0-dim array self.zip_mut_with_elem(rhs.get_0d(), f); - } else if self.dim.ndim() == rhs.dim.ndim() && self.shape() == rhs.shape() { + } else if self._dim().ndim() == rhs._dim().ndim() && self.shape() == rhs.shape() { self.zip_mut_with_same_shape(rhs, f); } else { let rhs_broadcast = rhs.broadcast_unwrap(self.raw_dim()); @@ -2900,7 +2908,7 @@ impl ArrayRef slc.iter().fold(init, f) } else { let mut v = self.view(); - move_min_stride_axis_to_last(&mut v.layout.dim, &mut v.layout.strides); + move_min_stride_axis_to_last(&mut v.parts.dim, &mut v.parts.strides); v.into_elements_base().fold(init, f) } } @@ -2931,12 +2939,12 @@ impl ArrayRef unsafe { if let Some(slc) = self.as_slice_memory_order() { ArrayBase::from_shape_trusted_iter_unchecked( - self.dim.clone().strides(self.strides.clone()), + self._dim().clone().strides(self._strides().clone()), slc.iter(), f, ) } else { - ArrayBase::from_shape_trusted_iter_unchecked(self.dim.clone(), self.iter(), f) + ArrayBase::from_shape_trusted_iter_unchecked(self._dim().clone(), self.iter(), f) } } } @@ -2952,9 +2960,9 @@ impl ArrayRef F: FnMut(&'a mut A) -> B, A: 'a, { - let dim = self.dim.clone(); + let dim = self._dim().clone(); if self.is_contiguous() { - let strides = self.strides.clone(); + let strides = self._strides().clone(); let slc = self.as_slice_memory_order_mut().unwrap(); unsafe { ArrayBase::from_shape_trusted_iter_unchecked(dim.strides(strides), slc.iter_mut(), f) } } else { @@ -3064,7 +3072,7 @@ impl ArrayRef Ok(slc) => slc.iter_mut().for_each(f), Err(arr) => { let mut v = arr.view_mut(); - move_min_stride_axis_to_last(&mut v.layout.dim, &mut v.layout.strides); + move_min_stride_axis_to_last(&mut v.parts.dim, &mut v.parts.strides); v.into_elements_base().for_each(f); } } @@ -3148,7 +3156,7 @@ impl ArrayRef A: 'a, { if self.len_of(axis) == 0 { - let new_dim = self.dim.remove_axis(axis); + let new_dim = self._dim().remove_axis(axis); Array::from_shape_simple_fn(new_dim, move || mapping(ArrayView::from(&[]))) } else { Zip::from(self.lanes(axis)).map_collect(mapping) @@ -3173,7 +3181,7 @@ impl ArrayRef A: 'a, { if self.len_of(axis) == 0 { - let new_dim = self.dim.remove_axis(axis); + let new_dim = self._dim().remove_axis(axis); Array::from_shape_simple_fn(new_dim, move || mapping(ArrayViewMut::from(&mut []))) } else { Zip::from(self.lanes_mut(axis)).map_collect(mapping) diff --git a/src/impl_owned_array.rs b/src/impl_owned_array.rs index 023e9ebb4..277b156b8 100644 --- a/src/impl_owned_array.rs +++ b/src/impl_owned_array.rs @@ -45,7 +45,7 @@ impl Array // (This is necessary because the element in the array might not be // the first element in the `Vec`, such as if the array was created // by `array![1, 2, 3, 4].slice_move(s![2])`.) - let first = self.ptr.as_ptr() as usize; + let first = self.parts.ptr.as_ptr() as usize; let base = self.data.as_ptr() as usize; let index = (first - base) / size; debug_assert_eq!((first - base) % size, 0); @@ -69,7 +69,7 @@ where D: Dimension return None; } if std::mem::size_of::() == 0 { - Some(dimension::offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides)) + Some(dimension::offset_from_low_addr_ptr_to_logical_ptr(&self.parts.dim, &self.parts.strides)) } else { let offset = unsafe { self.as_ptr().offset_from(self.data.as_ptr()) }; debug_assert!(offset >= 0); @@ -476,8 +476,8 @@ where D: Dimension } else { dim.slice_mut()[..=growing_axis.index()].rotate_right(1); new_array = Self::uninit(dim); - new_array.dim.slice_mut()[..=growing_axis.index()].rotate_left(1); - new_array.strides.slice_mut()[..=growing_axis.index()].rotate_left(1); + new_array.parts.dim.slice_mut()[..=growing_axis.index()].rotate_left(1); + new_array.parts.strides.slice_mut()[..=growing_axis.index()].rotate_left(1); } // self -> old_self. @@ -631,7 +631,7 @@ where D: Dimension // either the dimension increment is zero, or there is an existing // zero in another axis in self. debug_assert_eq!(self.len(), new_len); - self.dim = res_dim; + self.parts.dim = res_dim; return Ok(()); } @@ -701,11 +701,11 @@ where D: Dimension } } }); - let mut strides = self.strides.clone(); + let mut strides = self.parts.strides.clone(); strides[axis.index()] = new_stride as usize; strides } else { - self.strides.clone() + self.parts.strides.clone() }; // grow backing storage and update head ptr @@ -746,7 +746,7 @@ where D: Dimension sort_axes_in_default_order_tandem(&mut tail_view, &mut array); debug_assert!(tail_view.is_standard_layout(), "not std layout dim: {:?}, strides: {:?}", - tail_view.shape(), tail_view.strides()); + tail_view.shape(), RawArrayViewMut::strides(&tail_view)); } // Keep track of currently filled length of `self.data` and update it @@ -785,8 +785,8 @@ where D: Dimension drop(data_length_guard); // update array dimension - self.strides = strides; - self.dim = res_dim; + self.parts.strides = strides; + self.parts.dim = res_dim; } // multiple assertions after pointer & dimension update debug_assert_eq!(self.data.len(), self.len()); @@ -849,7 +849,7 @@ where D: Dimension 0 }; debug_assert!(data_to_array_offset >= 0); - self.layout.ptr = self + self.parts.ptr = self .data .reserve(len_to_append) .offset(data_to_array_offset); @@ -880,7 +880,7 @@ pub(crate) unsafe fn drop_unreachable_raw( } sort_axes_in_default_order(&mut self_); // with uninverted axes this is now the element with lowest address - let array_memory_head_ptr = self_.layout.ptr; + let array_memory_head_ptr = self_.parts.ptr; let data_end_ptr = data_ptr.add(data_len); debug_assert!(data_ptr <= array_memory_head_ptr); debug_assert!(array_memory_head_ptr <= data_end_ptr); @@ -897,19 +897,19 @@ pub(crate) unsafe fn drop_unreachable_raw( // As an optimization, the innermost axis is removed if it has stride 1, because // we then have a long stretch of contiguous elements we can skip as one. let inner_lane_len; - if self_.ndim() > 1 && self_.layout.strides.last_elem() == 1 { - self_.layout.dim.slice_mut().rotate_right(1); - self_.layout.strides.slice_mut().rotate_right(1); - inner_lane_len = self_.layout.dim[0]; - self_.layout.dim[0] = 1; - self_.layout.strides[0] = 1; + if self_.ndim() > 1 && self_.parts.strides.last_elem() == 1 { + self_.parts.dim.slice_mut().rotate_right(1); + self_.parts.strides.slice_mut().rotate_right(1); + inner_lane_len = self_.parts.dim[0]; + self_.parts.dim[0] = 1; + self_.parts.strides[0] = 1; } else { inner_lane_len = 1; } // iter is a raw pointer iterator traversing the array in memory order now with the // sorted axes. - let mut iter = Baseiter::new(self_.layout.ptr, self_.layout.dim, self_.layout.strides); + let mut iter = Baseiter::new(self_.parts.ptr, self_.parts.dim, self_.parts.strides); let mut dropped_elements = 0; let mut last_ptr = data_ptr; @@ -948,7 +948,7 @@ where if a.ndim() <= 1 { return; } - sort_axes1_impl(&mut a.layout.dim, &mut a.layout.strides); + sort_axes1_impl(&mut a.parts.dim, &mut a.parts.strides); } fn sort_axes1_impl(adim: &mut D, astrides: &mut D) @@ -988,7 +988,7 @@ where if a.ndim() <= 1 { return; } - sort_axes2_impl(&mut a.layout.dim, &mut a.layout.strides, &mut b.layout.dim, &mut b.layout.strides); + sort_axes2_impl(&mut a.parts.dim, &mut a.parts.strides, &mut b.parts.dim, &mut b.parts.strides); } fn sort_axes2_impl(adim: &mut D, astrides: &mut D, bdim: &mut D, bstrides: &mut D) diff --git a/src/impl_raw_views.rs b/src/impl_raw_views.rs index 5bb2a0e42..2423b9343 100644 --- a/src/impl_raw_views.rs +++ b/src/impl_raw_views.rs @@ -98,10 +98,10 @@ where D: Dimension pub unsafe fn deref_into_view<'a>(self) -> ArrayView<'a, A, D> { debug_assert!( - is_aligned(self.layout.ptr.as_ptr()), + is_aligned(self.parts.ptr.as_ptr()), "The pointer must be aligned." ); - ArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) + ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } /// Split the array view along `axis` and return one array pointer strictly @@ -113,23 +113,23 @@ where D: Dimension pub fn split_at(self, axis: Axis, index: Ix) -> (Self, Self) { assert!(index <= self.len_of(axis)); - let left_ptr = self.layout.ptr.as_ptr(); + let left_ptr = self.parts.ptr.as_ptr(); let right_ptr = if index == self.len_of(axis) { - self.layout.ptr.as_ptr() + self.parts.ptr.as_ptr() } else { - let offset = stride_offset(index, self.layout.strides.axis(axis)); + let offset = stride_offset(index, self.parts.strides.axis(axis)); // The `.offset()` is safe due to the guarantees of `RawData`. - unsafe { self.layout.ptr.as_ptr().offset(offset) } + unsafe { self.parts.ptr.as_ptr().offset(offset) } }; - let mut dim_left = self.layout.dim.clone(); + let mut dim_left = self.parts.dim.clone(); dim_left.set_axis(axis, index); - let left = unsafe { Self::new_(left_ptr, dim_left, self.layout.strides.clone()) }; + let left = unsafe { Self::new_(left_ptr, dim_left, self.parts.strides.clone()) }; - let mut dim_right = self.layout.dim; + let mut dim_right = self.parts.dim; let right_len = dim_right.axis(axis) - index; dim_right.set_axis(axis, right_len); - let right = unsafe { Self::new_(right_ptr, dim_right, self.layout.strides) }; + let right = unsafe { Self::new_(right_ptr, dim_right, self.parts.strides) }; (left, right) } @@ -152,8 +152,8 @@ where D: Dimension mem::size_of::(), "size mismatch in raw view cast" ); - let ptr = self.layout.ptr.cast::(); - unsafe { RawArrayView::new(ptr, self.layout.dim, self.layout.strides) } + let ptr = self.parts.ptr.cast::(); + unsafe { RawArrayView::new(ptr, self.parts.dim, self.parts.strides) } } } @@ -172,11 +172,11 @@ where D: Dimension ); assert_eq!(mem::align_of::>(), mem::align_of::()); - let dim = self.layout.dim.clone(); + let dim = self.parts.dim.clone(); // Double the strides. In the zero-sized element case and for axes of // length <= 1, we leave the strides as-is to avoid possible overflow. - let mut strides = self.layout.strides.clone(); + let mut strides = self.parts.strides.clone(); if mem::size_of::() != 0 { for ax in 0..strides.ndim() { if dim[ax] > 1 { @@ -185,7 +185,7 @@ where D: Dimension } } - let ptr_re: *mut T = self.layout.ptr.as_ptr().cast(); + let ptr_re: *mut T = self.parts.ptr.as_ptr().cast(); let ptr_im: *mut T = if self.is_empty() { // In the empty case, we can just reuse the existing pointer since // it won't be dereferenced anyway. It is not safe to offset by @@ -308,7 +308,7 @@ where D: Dimension #[inline] pub(crate) fn into_raw_view(self) -> RawArrayView { - unsafe { RawArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { RawArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } /// Converts to a read-only view of the array. @@ -323,10 +323,10 @@ where D: Dimension pub unsafe fn deref_into_view<'a>(self) -> ArrayView<'a, A, D> { debug_assert!( - is_aligned(self.layout.ptr.as_ptr()), + is_aligned(self.parts.ptr.as_ptr()), "The pointer must be aligned." ); - ArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) + ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } /// Converts to a mutable view of the array. @@ -341,10 +341,10 @@ where D: Dimension pub unsafe fn deref_into_view_mut<'a>(self) -> ArrayViewMut<'a, A, D> { debug_assert!( - is_aligned(self.layout.ptr.as_ptr()), + is_aligned(self.parts.ptr.as_ptr()), "The pointer must be aligned." ); - ArrayViewMut::new(self.layout.ptr, self.layout.dim, self.layout.strides) + ArrayViewMut::new(self.parts.ptr, self.parts.dim, self.parts.strides) } /// Split the array view along `axis` and return one array pointer strictly @@ -358,8 +358,8 @@ where D: Dimension let (left, right) = self.into_raw_view().split_at(axis, index); unsafe { ( - Self::new(left.layout.ptr, left.layout.dim, left.layout.strides), - Self::new(right.layout.ptr, right.layout.dim, right.layout.strides), + Self::new(left.parts.ptr, left.parts.dim, left.parts.strides), + Self::new(right.parts.ptr, right.parts.dim, right.parts.strides), ) } } @@ -382,8 +382,8 @@ where D: Dimension mem::size_of::(), "size mismatch in raw view cast" ); - let ptr = self.layout.ptr.cast::(); - unsafe { RawArrayViewMut::new(ptr, self.layout.dim, self.layout.strides) } + let ptr = self.parts.ptr.cast::(); + unsafe { RawArrayViewMut::new(ptr, self.parts.dim, self.parts.strides) } } } @@ -397,8 +397,8 @@ where D: Dimension let Complex { re, im } = self.into_raw_view().split_complex(); unsafe { Complex { - re: RawArrayViewMut::new(re.layout.ptr, re.layout.dim, re.layout.strides), - im: RawArrayViewMut::new(im.layout.ptr, im.layout.dim, im.layout.strides), + re: RawArrayViewMut::new(re.parts.ptr, re.parts.dim, re.parts.strides), + im: RawArrayViewMut::new(im.parts.ptr, im.parts.dim, im.parts.strides), } } } diff --git a/src/impl_ref_types.rs b/src/impl_ref_types.rs index d93a996bf..bfdfa27f9 100644 --- a/src/impl_ref_types.rs +++ b/src/impl_ref_types.rs @@ -35,7 +35,20 @@ use core::{ ops::{Deref, DerefMut}, }; -use crate::{Array, ArrayBase, ArrayRef, Data, DataMut, Dimension, LayoutRef, RawData, RawDataMut, RawRef}; +use crate::{ + Array, + ArrayBase, + ArrayPartsSized, + ArrayPartsUnsized, + ArrayRef, + Data, + DataMut, + Dimension, + LayoutRef, + RawData, + RawDataMut, + RawRef, +}; // D1: &ArrayBase -> &ArrayRef when data is safe to read impl Deref for ArrayBase @@ -50,7 +63,9 @@ where S: Data // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &*(&self.layout as *const LayoutRef).cast::>() } + let parts: &ArrayPartsUnsized = &self.parts; + let ptr = (parts as *const ArrayPartsUnsized) as *const ArrayRef; + unsafe { &*ptr } } } @@ -68,7 +83,9 @@ where // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &mut *(&mut self.layout as *mut LayoutRef).cast::>() } + let parts: &mut ArrayPartsUnsized = &mut self.parts; + let ptr = (parts as *mut ArrayPartsUnsized) as *mut ArrayRef; + unsafe { &mut *ptr } } } @@ -84,7 +101,7 @@ impl Deref for ArrayRef // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &*(self as *const ArrayRef).cast::>() } + unsafe { &*((self as *const ArrayRef) as *const RawRef) } } } @@ -98,7 +115,7 @@ impl DerefMut for ArrayRef // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &mut *(self as *mut ArrayRef).cast::>() } + unsafe { &mut *((self as *mut ArrayRef) as *mut RawRef) } } } @@ -133,7 +150,9 @@ where S: RawData // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &*(&self.layout as *const LayoutRef).cast::>() } + let parts: &ArrayPartsUnsized = &self.parts; + let ptr = (parts as *const ArrayPartsUnsized) as *const RawRef; + unsafe { &*ptr } } } @@ -148,7 +167,9 @@ where S: RawDataMut // - It is "dereferencable" because it comes from a reference // - For the same reason, it is initialized // - The cast is valid because ArrayRef uses #[repr(transparent)] - unsafe { &mut *(&mut self.layout as *mut LayoutRef).cast::>() } + let parts: &mut ArrayPartsUnsized = &mut self.parts; + let ptr = (parts as *mut ArrayPartsUnsized) as *mut RawRef; + unsafe { &mut *ptr } } } @@ -158,7 +179,9 @@ where S: RawData { fn as_ref(&self) -> &LayoutRef { - &self.layout + let parts: &ArrayPartsUnsized = &self.parts; + let ptr = (parts as *const ArrayPartsUnsized) as *const LayoutRef; + unsafe { &*ptr } } } @@ -168,7 +191,9 @@ where S: RawData { fn as_mut(&mut self) -> &mut LayoutRef { - &mut self.layout + let parts: &mut ArrayPartsUnsized = &mut self.parts; + let ptr = (parts as *mut ArrayPartsUnsized) as *mut LayoutRef; + unsafe { &mut *ptr } } } @@ -269,7 +294,7 @@ impl AsMut> for LayoutRef /// impossible to read the data behind the pointer from a LayoutRef (this /// is a safety invariant that *must* be maintained), and therefore we can /// Clone and Copy as desired. -impl Clone for LayoutRef +impl Clone for ArrayPartsSized { fn clone(&self) -> Self { @@ -277,11 +302,12 @@ impl Clone for LayoutRef dim: self.dim.clone(), strides: self.strides.clone(), ptr: self.ptr, + _dst_control: [0; 0], } } } -impl Copy for LayoutRef {} +impl Copy for ArrayPartsSized {} impl Borrow> for ArrayBase where S: RawData @@ -368,3 +394,17 @@ where S: RawData self.as_mut() } } + +/// Tests that a mem::swap can't compile by putting it into a doctest +/// +/// ```compile_fail +/// let mut x = Array1::from_vec(vec![0, 1, 2]); +/// { +/// let mut y = Array1::from_vec(vec![4, 5, 6]); +/// let x_ref = x.as_layout_ref_mut(); +/// let y_ref = y.as_layout_ref_mut(); +/// core::mem::swap(x_ref, y_ref); +/// } +/// ``` +#[allow(dead_code)] +fn test_no_swap_via_doctests() {} diff --git a/src/impl_special_element_types.rs b/src/impl_special_element_types.rs index 42b524bc2..8b525e314 100644 --- a/src/impl_special_element_types.rs +++ b/src/impl_special_element_types.rs @@ -9,7 +9,7 @@ use std::mem::MaybeUninit; use crate::imp_prelude::*; -use crate::LayoutRef; +use crate::ArrayParts; use crate::RawDataSubst; /// Methods specific to arrays with `MaybeUninit` elements. @@ -36,7 +36,13 @@ where { let ArrayBase { data, - layout: LayoutRef { ptr, dim, strides }, + parts: + ArrayParts { + ptr, + dim, + strides, + _dst_control: [], + }, } = self; // "transmute" from storage of MaybeUninit to storage of A diff --git a/src/impl_views/constructors.rs b/src/impl_views/constructors.rs index 29b7c13d7..dcf6527ec 100644 --- a/src/impl_views/constructors.rs +++ b/src/impl_views/constructors.rs @@ -225,7 +225,7 @@ where D: Dimension pub fn reborrow<'b>(self) -> ArrayViewMut<'b, A, D> where 'a: 'b { - unsafe { ArrayViewMut::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { ArrayViewMut::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } } diff --git a/src/impl_views/conversions.rs b/src/impl_views/conversions.rs index 5bc5f9ad6..54d7ed207 100644 --- a/src/impl_views/conversions.rs +++ b/src/impl_views/conversions.rs @@ -29,7 +29,7 @@ where D: Dimension pub fn reborrow<'b>(self) -> ArrayView<'b, A, D> where 'a: 'b { - unsafe { ArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } /// Return the array’s data as a slice, if it is contiguous and in standard order. @@ -40,7 +40,7 @@ where D: Dimension pub fn to_slice(&self) -> Option<&'a [A]> { if self.is_standard_layout() { - unsafe { Some(slice::from_raw_parts(self.ptr.as_ptr(), self.len())) } + unsafe { Some(slice::from_raw_parts(self.parts.ptr.as_ptr(), self.len())) } } else { None } @@ -55,8 +55,8 @@ where D: Dimension pub fn to_slice_memory_order(&self) -> Option<&'a [A]> { if self.is_contiguous() { - let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides); - unsafe { Some(slice::from_raw_parts(self.ptr.sub(offset).as_ptr(), self.len())) } + let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.parts.dim, &self.parts.strides); + unsafe { Some(slice::from_raw_parts(self.parts.ptr.sub(offset).as_ptr(), self.len())) } } else { None } @@ -66,7 +66,7 @@ where D: Dimension #[inline] pub(crate) fn into_raw_view(self) -> RawArrayView { - unsafe { RawArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { RawArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } } @@ -199,7 +199,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } } @@ -209,7 +209,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } } @@ -220,7 +220,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } #[inline] @@ -276,19 +276,19 @@ where D: Dimension // Convert into a read-only view pub(crate) fn into_view(self) -> ArrayView<'a, A, D> { - unsafe { ArrayView::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { ArrayView::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } /// Converts to a mutable raw array view. pub(crate) fn into_raw_view_mut(self) -> RawArrayViewMut { - unsafe { RawArrayViewMut::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { RawArrayViewMut::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.layout.ptr, self.layout.dim, self.layout.strides) } + unsafe { Baseiter::new(self.parts.ptr, self.parts.dim, self.parts.strides) } } #[inline] @@ -302,7 +302,7 @@ where D: Dimension pub(crate) fn try_into_slice(self) -> Result<&'a mut [A], Self> { if self.is_standard_layout() { - unsafe { Ok(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) } + unsafe { Ok(slice::from_raw_parts_mut(self.parts.ptr.as_ptr(), self.len())) } } else { Err(self) } @@ -313,8 +313,8 @@ where D: Dimension fn try_into_slice_memory_order(self) -> Result<&'a mut [A], Self> { if self.is_contiguous() { - let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides); - unsafe { Ok(slice::from_raw_parts_mut(self.ptr.sub(offset).as_ptr(), self.len())) } + let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.parts.dim, &self.parts.strides); + unsafe { Ok(slice::from_raw_parts_mut(self.parts.ptr.sub(offset).as_ptr(), self.len())) } } else { Err(self) } diff --git a/src/impl_views/indexing.rs b/src/impl_views/indexing.rs index 2879e7416..feadbd296 100644 --- a/src/impl_views/indexing.rs +++ b/src/impl_views/indexing.rs @@ -145,7 +145,9 @@ where unsafe fn uget(self, index: I) -> &'a A { debug_bounds_check!(self, index); - &*self.as_ptr().offset(index.index_unchecked(&self.strides)) + &*self + .as_ptr() + .offset(index.index_unchecked(&self.parts.strides)) } } @@ -213,6 +215,6 @@ where debug_bounds_check!(self, index); &mut *self .as_mut_ptr() - .offset(index.index_unchecked(&self.strides)) + .offset(index.index_unchecked(&self.parts.strides)) } } diff --git a/src/iterators/chunks.rs b/src/iterators/chunks.rs index 4dd99f002..178ead7e0 100644 --- a/src/iterators/chunks.rs +++ b/src/iterators/chunks.rs @@ -59,10 +59,10 @@ impl<'a, A, D: Dimension> ExactChunks<'a, A, D> a.shape() ); for i in 0..a.ndim() { - a.layout.dim[i] /= chunk[i]; + a.parts.dim[i] /= chunk[i]; } - let inner_strides = a.layout.strides.clone(); - a.layout.strides *= &chunk; + let inner_strides = a.parts.strides.clone(); + a.parts.strides *= &chunk; ExactChunks { base: a, @@ -158,10 +158,10 @@ impl<'a, A, D: Dimension> ExactChunksMut<'a, A, D> a.shape() ); for i in 0..a.ndim() { - a.layout.dim[i] /= chunk[i]; + a.parts.dim[i] /= chunk[i]; } - let inner_strides = a.layout.strides.clone(); - a.layout.strides *= &chunk; + let inner_strides = a.parts.strides.clone(); + a.parts.strides *= &chunk; ExactChunksMut { base: a, diff --git a/src/iterators/into_iter.rs b/src/iterators/into_iter.rs index b51315a0f..cacafd2f2 100644 --- a/src/iterators/into_iter.rs +++ b/src/iterators/into_iter.rs @@ -36,12 +36,12 @@ where D: Dimension pub(crate) fn new(array: Array) -> Self { unsafe { - let array_head_ptr = array.ptr; + let array_head_ptr = array.parts.ptr; let mut array_data = array.data; let data_len = array_data.release_all_elements(); - debug_assert!(data_len >= array.layout.dim.size()); - let has_unreachable_elements = array.layout.dim.size() != data_len; - let inner = Baseiter::new(array_head_ptr, array.layout.dim, array.layout.strides); + debug_assert!(data_len >= array.parts.dim.size()); + let has_unreachable_elements = array.parts.dim.size() != data_len; + let inner = Baseiter::new(array_head_ptr, array.parts.dim, array.parts.strides); IntoIter { array_data, diff --git a/src/iterators/lanes.rs b/src/iterators/lanes.rs index 0f9678872..9fd39607b 100644 --- a/src/iterators/lanes.rs +++ b/src/iterators/lanes.rs @@ -46,8 +46,8 @@ impl<'a, A, D: Dimension> Lanes<'a, A, D> v.try_remove_axis(Axis(0)) } else { let i = axis.index(); - len = v.dim[i]; - stride = v.strides[i] as isize; + len = v.parts.dim[i]; + stride = v.parts.strides[i] as isize; v.try_remove_axis(axis) }; Lanes { @@ -115,8 +115,8 @@ impl<'a, A, D: Dimension> LanesMut<'a, A, D> v.try_remove_axis(Axis(0)) } else { let i = axis.index(); - len = v.dim[i]; - stride = v.strides[i] as isize; + len = v.parts.dim[i]; + stride = v.parts.strides[i] as isize; v.try_remove_axis(axis) }; LanesMut { diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 55a9920a8..f7892a8c9 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -880,9 +880,9 @@ impl AxisIterCore index: 0, end: v.len_of(axis), stride: v.stride_of(axis), - inner_dim: v.dim.remove_axis(axis), - inner_strides: v.strides.remove_axis(axis), - ptr: v.ptr.as_ptr(), + inner_dim: v.parts.dim.remove_axis(axis), + inner_strides: v.parts.strides.remove_axis(axis), + ptr: v.parts.ptr.as_ptr(), } } @@ -1366,10 +1366,10 @@ fn chunk_iter_parts(v: ArrayView<'_, A, D>, axis: Axis, size: u }; let axis = axis.index(); - let mut inner_dim = v.dim.clone(); + let mut inner_dim = v.parts.dim.clone(); inner_dim[axis] = size; - let mut partial_chunk_dim = v.layout.dim; + let mut partial_chunk_dim = v.parts.dim; partial_chunk_dim[axis] = chunk_remainder; let partial_chunk_index = n_whole_chunks; @@ -1378,8 +1378,8 @@ fn chunk_iter_parts(v: ArrayView<'_, A, D>, axis: Axis, size: u end: iter_len, stride, inner_dim, - inner_strides: v.layout.strides, - ptr: v.layout.ptr.as_ptr(), + inner_strides: v.parts.strides, + ptr: v.parts.ptr.as_ptr(), }; (iter, partial_chunk_index, partial_chunk_dim) diff --git a/src/iterators/windows.rs b/src/iterators/windows.rs index f3442c0af..e6fccce46 100644 --- a/src/iterators/windows.rs +++ b/src/iterators/windows.rs @@ -39,7 +39,7 @@ impl<'a, A, D: Dimension> Windows<'a, A, D> let window = window_size.into_dimension(); let strides = axis_strides.into_dimension(); - let window_strides = a.strides.clone(); + let window_strides = a.parts.strides.clone(); let base = build_base(a, window.clone(), strides); Windows { @@ -143,7 +143,7 @@ impl<'a, A, D: Dimension> AxisWindows<'a, A, D> { pub(crate) fn new_with_stride(a: ArrayView<'a, A, D>, axis: Axis, window_size: usize, stride_size: usize) -> Self { - let window_strides = a.strides.clone(); + let window_strides = a.parts.strides.clone(); let axis_idx = axis.index(); let mut window = a.raw_dim(); diff --git a/src/lib.rs b/src/lib.rs index e11a8a5ff..9f2c53d79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,12 +131,14 @@ extern crate cblas_sys; #[cfg(docsrs)] pub mod doc; +use alloc::fmt::Debug; #[cfg(target_has_atomic = "ptr")] use alloc::sync::Arc; #[cfg(not(target_has_atomic = "ptr"))] use portable_atomic_util::Arc; +use core::ptr::NonNull; use std::marker::PhantomData; pub use crate::dimension::dim::*; @@ -1299,7 +1301,41 @@ where S: RawData /// buffer; if borrowed, contains the lifetime and mutability.) data: S, /// The dimension, strides, and pointer to inside of `data` - layout: LayoutRef, + parts: ArrayPartsSized, +} + +/// A possibly-unsized container for array parts. +/// +/// This type only exists to enable holding the array parts in a single +/// type, which needs to be sized inside of `ArrayBase` and unsized inside +/// of the reference types. +#[derive(Debug)] +struct ArrayParts +{ + /// A non-null pointer into the buffer held by `data`; may point anywhere + /// in its range. If `S: Data`, this pointer must be aligned. + ptr: NonNull, + /// The lengths of the axes. + dim: D, + /// The element count stride per axis. To be parsed as `isize`. + strides: D, + _dst_control: T, +} + +type ArrayPartsSized = ArrayParts; +type ArrayPartsUnsized = ArrayParts; + +impl ArrayPartsSized +{ + const fn new(ptr: NonNull, dim: D, strides: D) -> ArrayPartsSized + { + Self { + ptr, + dim, + strides, + _dst_control: [], + } + } } /// A reference to the layout of an *n*-dimensional array. @@ -1401,16 +1437,28 @@ where S: RawData // which alter the layout / shape / strides of an array must also // alter the offset of the pointer. This is allowed, as it does not // cause a pointer deref. -#[derive(Debug)] -pub struct LayoutRef +#[repr(transparent)] +pub struct LayoutRef(ArrayPartsUnsized); + +impl LayoutRef { - /// A non-null pointer into the buffer held by `data`; may point anywhere - /// in its range. If `S: Data`, this pointer must be aligned. - ptr: std::ptr::NonNull, - /// The lengths of the axes. - dim: D, - /// The element count stride per axis. To be parsed as `isize`. - strides: D, + /// Get a reference to the data pointer. + fn _ptr(&self) -> &NonNull + { + &self.0.ptr + } + + /// Get a reference to the array's dimension. + fn _dim(&self) -> &D + { + &self.0.dim + } + + /// Get a reference to the array's strides. + fn _strides(&self) -> &D + { + &self.0.strides + } } /// A reference to an *n*-dimensional array whose data is safe to read and write. @@ -1757,7 +1805,7 @@ impl ArrayRef match self.broadcast(dim.clone()) { Some(it) => it, - None => broadcast_panic(&self.dim, &dim), + None => broadcast_panic(self._dim(), &dim), } } @@ -1769,10 +1817,10 @@ impl ArrayRef { let dim = dim.into_dimension(); debug_assert_eq!(self.shape(), dim.slice()); - let ptr = self.ptr; + let ptr = self._ptr(); let mut strides = dim.clone(); - strides.slice_mut().copy_from_slice(self.strides.slice()); - unsafe { ArrayView::new(ptr, dim, strides) } + strides.slice_mut().copy_from_slice(self._strides().slice()); + unsafe { ArrayView::new(*ptr, dim, strides) } } } @@ -1784,8 +1832,8 @@ where /// Remove array axis `axis` and return the result. fn try_remove_axis(self, axis: Axis) -> ArrayBase { - let d = self.layout.dim.try_remove_axis(axis); - let s = self.layout.strides.try_remove_axis(axis); + let d = self.parts.dim.try_remove_axis(axis); + let s = self.parts.strides.try_remove_axis(axis); // safe because new dimension, strides allow access to a subset of old data unsafe { self.with_strides_dim(s, d) } } diff --git a/src/linalg/impl_linalg.rs b/src/linalg/impl_linalg.rs index 1e4eb80ee..14c82ff4d 100644 --- a/src/linalg/impl_linalg.rs +++ b/src/linalg/impl_linalg.rs @@ -65,7 +65,7 @@ impl ArrayRef /// *Note:* If enabled, uses blas `dot` for elements of `f32, f64` when memory /// layout allows. #[track_caller] - pub fn dot(&self, rhs: &Rhs) -> >::Output + pub fn dot(&self, rhs: &Rhs) -> >::Output where Self: Dot { Dot::dot(self, rhs) @@ -110,9 +110,9 @@ impl ArrayRef if blas_compat_1d::<$ty, _>(self) && blas_compat_1d::<$ty, _>(rhs) { unsafe { let (lhs_ptr, n, incx) = - blas_1d_params(self.ptr.as_ptr(), self.len(), self.strides()[0]); + blas_1d_params(self._ptr().as_ptr(), self.len(), self.strides()[0]); let (rhs_ptr, _, incy) = - blas_1d_params(rhs.ptr.as_ptr(), rhs.len(), rhs.strides()[0]); + blas_1d_params(rhs._ptr().as_ptr(), rhs.len(), rhs.strides()[0]); let ret = blas_sys::$func( n, lhs_ptr as *const $ty, @@ -157,7 +157,7 @@ unsafe fn blas_1d_params(ptr: *const A, len: usize, stride: isize) -> (*const /// /// For two-dimensional arrays, the dot method computes the matrix /// multiplication. -pub trait Dot +pub trait Dot { /// The result of the operation. /// @@ -295,7 +295,7 @@ impl ArrayRef /// ); /// ``` #[track_caller] - pub fn dot(&self, rhs: &Rhs) -> >::Output + pub fn dot(&self, rhs: &Rhs) -> >::Output where Self: Dot { Dot::dot(self, rhs) @@ -471,12 +471,12 @@ where A: LinalgScalar n as blas_index, // n, cols of Op(b) k as blas_index, // k, cols of Op(a) gemm_scalar_cast!($ty, alpha), // alpha - a.ptr.as_ptr() as *const _, // a + a._ptr().as_ptr() as *const _, // a lda, // lda - b.ptr.as_ptr() as *const _, // b + b._ptr().as_ptr() as *const _, // b ldb, // ldb gemm_scalar_cast!($ty, beta), // beta - c.ptr.as_ptr() as *mut _, // c + c._ptr().as_ptr() as *mut _, // c ldc, // ldc ); } @@ -694,10 +694,10 @@ unsafe fn general_mat_vec_mul_impl( let cblas_layout = layout.to_cblas_layout(); // Low addr in memory pointers required for x, y - let x_offset = offset_from_low_addr_ptr_to_logical_ptr(&x.dim, &x.strides); - let x_ptr = x.ptr.as_ptr().sub(x_offset); - let y_offset = offset_from_low_addr_ptr_to_logical_ptr(&y.layout.dim, &y.layout.strides); - let y_ptr = y.layout.ptr.as_ptr().sub(y_offset); + let x_offset = offset_from_low_addr_ptr_to_logical_ptr(x._dim(), x._strides()); + let x_ptr = x._ptr().as_ptr().sub(x_offset); + let y_offset = offset_from_low_addr_ptr_to_logical_ptr(&y.parts.dim, &y.parts.strides); + let y_ptr = y.parts.ptr.as_ptr().sub(y_offset); let x_stride = x.strides()[0] as blas_index; let y_stride = y.strides()[0] as blas_index; @@ -708,7 +708,7 @@ unsafe fn general_mat_vec_mul_impl( m as blas_index, // m, rows of Op(a) k as blas_index, // n, cols of Op(a) cast_as(&alpha), // alpha - a.ptr.as_ptr() as *const _, // a + a._ptr().as_ptr() as *const _, // a a_stride, // lda x_ptr as *const _, // x x_stride, @@ -909,9 +909,9 @@ fn is_blas_2d(dim: &Ix2, stride: &Ix2, order: BlasOrder) -> bool #[cfg(feature = "blas")] fn get_blas_compatible_layout(a: &ArrayRef) -> Option { - if is_blas_2d(&a.dim, &a.strides, BlasOrder::C) { + if is_blas_2d(a._dim(), a._strides(), BlasOrder::C) { Some(BlasOrder::C) - } else if is_blas_2d(&a.dim, &a.strides, BlasOrder::F) { + } else if is_blas_2d(a._dim(), a._strides(), BlasOrder::F) { Some(BlasOrder::F) } else { None @@ -952,7 +952,7 @@ where if !same_type::() { return false; } - is_blas_2d(&a.dim, &a.strides, BlasOrder::C) + is_blas_2d(a._dim(), a._strides(), BlasOrder::C) } #[cfg(test)] @@ -965,7 +965,7 @@ where if !same_type::() { return false; } - is_blas_2d(&a.dim, &a.strides, BlasOrder::F) + is_blas_2d(a._dim(), a._strides(), BlasOrder::F) } #[cfg(test)] diff --git a/src/macro_utils.rs b/src/macro_utils.rs index 75360de37..34c700e65 100644 --- a/src/macro_utils.rs +++ b/src/macro_utils.rs @@ -61,7 +61,7 @@ macro_rules! expand_if { #[cfg(debug_assertions)] macro_rules! debug_bounds_check { ($self_:ident, $index:expr) => { - if $index.index_checked(&$self_.dim, &$self_.strides).is_none() { + if $index.index_checked(&$self_._dim(), &$self_._strides()).is_none() { panic!( "ndarray: index {:?} is out of bounds for array of shape {:?}", $index, @@ -75,3 +75,21 @@ macro_rules! debug_bounds_check { macro_rules! debug_bounds_check { ($self_:ident, $index:expr) => {}; } + +#[cfg(debug_assertions)] +macro_rules! debug_bounds_check_ref { + ($self_:ident, $index:expr) => { + if $index.index_checked(&$self_._dim(), &$self_._strides()).is_none() { + panic!( + "ndarray: index {:?} is out of bounds for array of shape {:?}", + $index, + $self_.shape() + ); + } + }; +} + +#[cfg(not(debug_assertions))] +macro_rules! debug_bounds_check_ref { + ($self_:ident, $index:expr) => {}; +} diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index ae82a482a..9709a5254 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -272,7 +272,7 @@ where D: Dimension A: Clone + Zero + Add, D: RemoveAxis, { - let min_stride_axis = self.dim.min_stride_axis(&self.strides); + let min_stride_axis = self._dim().min_stride_axis(self._strides()); if axis == min_stride_axis { crate::Zip::from(self.lanes(axis)).map_collect(|lane| lane.sum()) } else { @@ -309,7 +309,7 @@ where D: Dimension A: Clone + One + Mul, D: RemoveAxis, { - let min_stride_axis = self.dim.min_stride_axis(&self.strides); + let min_stride_axis = self._dim().min_stride_axis(self._strides()); if axis == min_stride_axis { crate::Zip::from(self.lanes(axis)).map_collect(|lane| lane.product()) } else { @@ -414,8 +414,8 @@ where D: Dimension the axis", ); let dof = n - ddof; - let mut mean = Array::::zeros(self.dim.remove_axis(axis)); - let mut sum_sq = Array::::zeros(self.dim.remove_axis(axis)); + let mut mean = Array::::zeros(self._dim().remove_axis(axis)); + let mut sum_sq = Array::::zeros(self._dim().remove_axis(axis)); for (i, subview) in self.axis_iter(axis).enumerate() { let count = A::from_usize(i + 1).expect("Converting index to `A` must not fail."); azip!((mean in &mut mean, sum_sq in &mut sum_sq, &x in &subview) { diff --git a/src/tri.rs b/src/tri.rs index 6e3b90b5b..9f15db71a 100644 --- a/src/tri.rs +++ b/src/tri.rs @@ -59,7 +59,7 @@ where // C-order array check prevents infinite recursion in edge cases like [[1]]. // k-size check prevents underflow when k == isize::MIN let n = self.ndim(); - if is_layout_f(&self.dim, &self.strides) && !is_layout_c(&self.dim, &self.strides) && k > isize::MIN { + if is_layout_f(self._dim(), self._strides()) && !is_layout_c(self._dim(), self._strides()) && k > isize::MIN { let mut x = self.view(); x.swap_axes(n - 2, n - 1); let mut tril = x.tril(-k); @@ -124,7 +124,7 @@ where // C-order array check prevents infinite recursion in edge cases like [[1]]. // k-size check prevents underflow when k == isize::MIN let n = self.ndim(); - if is_layout_f(&self.dim, &self.strides) && !is_layout_c(&self.dim, &self.strides) && k > isize::MIN { + if is_layout_f(self._dim(), self._strides()) && !is_layout_c(self._dim(), self._strides()) && k > isize::MIN { let mut x = self.view(); x.swap_axes(n - 2, n - 1); let mut triu = x.triu(-k); @@ -169,10 +169,10 @@ mod tests { let x = Array2::::ones((3, 3).f()); let res = x.triu(0); - assert!(dimension::is_layout_f(&res.dim, &res.strides)); + assert!(dimension::is_layout_f(&res.parts.dim, &res.parts.strides)); let res = x.tril(0); - assert!(dimension::is_layout_f(&res.dim, &res.strides)); + assert!(dimension::is_layout_f(&res.parts.dim, &res.parts.strides)); } #[test] diff --git a/src/zip/mod.rs b/src/zip/mod.rs index 640a74d1b..668eac093 100644 --- a/src/zip/mod.rs +++ b/src/zip/mod.rs @@ -81,7 +81,7 @@ where D: Dimension { pub(crate) fn layout_impl(&self) -> Layout { - array_layout(&self.dim, &self.strides) + array_layout(self._dim(), self._strides()) } } @@ -95,7 +95,7 @@ where { #[allow(clippy::needless_borrow)] let res: ArrayView<'_, A, E::Dim> = (*self).broadcast_unwrap(shape.into_dimension()); - unsafe { ArrayView::new(res.layout.ptr, res.layout.dim, res.layout.strides) } + unsafe { ArrayView::new(res.parts.ptr, res.parts.dim, res.parts.strides) } } private_impl! {} } diff --git a/src/zip/ndproducer.rs b/src/zip/ndproducer.rs index de9d66979..fe666e81e 100644 --- a/src/zip/ndproducer.rs +++ b/src/zip/ndproducer.rs @@ -274,7 +274,7 @@ impl<'a, A, D: Dimension> NdProducer for ArrayView<'a, A, D> fn equal_dim(&self, dim: &Self::Dim) -> bool { - self.dim.equal(dim) + self._dim().equal(dim) } fn as_ptr(&self) -> *mut A @@ -294,7 +294,9 @@ impl<'a, A, D: Dimension> NdProducer for ArrayView<'a, A, D> unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A { - self.ptr.as_ptr().offset(i.index_unchecked(&self.strides)) + self._ptr() + .as_ptr() + .offset(i.index_unchecked(self._strides())) } fn stride_of(&self, axis: Axis) -> isize @@ -330,7 +332,7 @@ impl<'a, A, D: Dimension> NdProducer for ArrayViewMut<'a, A, D> fn equal_dim(&self, dim: &Self::Dim) -> bool { - self.dim.equal(dim) + self._dim().equal(dim) } fn as_ptr(&self) -> *mut A @@ -350,7 +352,9 @@ impl<'a, A, D: Dimension> NdProducer for ArrayViewMut<'a, A, D> unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A { - self.ptr.as_ptr().offset(i.index_unchecked(&self.strides)) + self._ptr() + .as_ptr() + .offset(i.index_unchecked(self._strides())) } fn stride_of(&self, axis: Axis) -> isize @@ -386,7 +390,7 @@ impl NdProducer for RawArrayView fn equal_dim(&self, dim: &Self::Dim) -> bool { - self.layout.dim.equal(dim) + self.parts.dim.equal(dim) } fn as_ptr(&self) -> *const A @@ -406,10 +410,10 @@ impl NdProducer for RawArrayView unsafe fn uget_ptr(&self, i: &Self::Dim) -> *const A { - self.layout + self.parts .ptr .as_ptr() - .offset(i.index_unchecked(&self.layout.strides)) + .offset(i.index_unchecked(&self.parts.strides)) } fn stride_of(&self, axis: Axis) -> isize @@ -445,7 +449,7 @@ impl NdProducer for RawArrayViewMut fn equal_dim(&self, dim: &Self::Dim) -> bool { - self.layout.dim.equal(dim) + self.parts.dim.equal(dim) } fn as_ptr(&self) -> *mut A @@ -465,10 +469,10 @@ impl NdProducer for RawArrayViewMut unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A { - self.layout + self.parts .ptr .as_ptr() - .offset(i.index_unchecked(&self.layout.strides)) + .offset(i.index_unchecked(&self.parts.strides)) } fn stride_of(&self, axis: Axis) -> isize