#[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; use std::ops::Deref; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; use base::allocator::Allocator; use base::default_allocator::DefaultAllocator; use base::dimension::{Dim, DimName, Dynamic, U1}; use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; use base::{Scalar, Vector}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; /* * * Storage. * */ /// A Vec-based matrix data storage. It may be dynamically-sized. #[repr(C)] #[derive(Eq, Debug, Clone, PartialEq)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] pub struct MatrixVec { data: Vec, nrows: R, ncols: C, } impl MatrixVec { /// Creates a new dynamic matrix data storage from the given vector and shape. #[inline] pub fn new(nrows: R, ncols: C, data: Vec) -> MatrixVec { assert!( nrows.value() * ncols.value() == data.len(), "Data storage buffer dimension mismatch." ); MatrixVec { data: data, nrows: nrows, ncols: ncols, } } /// The underlying data storage. #[inline] pub fn data(&self) -> &Vec { &self.data } /// The underlying mutable data storage. /// /// This is unsafe because this may cause UB if the vector is modified by the user. #[inline] pub unsafe fn data_mut(&mut self) -> &mut Vec { &mut self.data } /// Resizes the underlying mutable data storage and unwraps it. /// /// If `sz` is larger than the current size, additional elements are uninitialized. /// If `sz` is smaller than the current size, additional elements are truncated. #[inline] pub unsafe fn resize(mut self, sz: usize) -> Vec { let len = self.len(); if sz < len { self.data.set_len(sz); self.data.shrink_to_fit(); } else { self.data.reserve_exact(sz - len); self.data.set_len(sz); } self.data } } impl Deref for MatrixVec { type Target = Vec; #[inline] fn deref(&self) -> &Self::Target { &self.data } } /* * * Dynamic − Static * Dynamic − Dynamic * */ unsafe impl Storage for MatrixVec where DefaultAllocator: Allocator { type RStride = U1; type CStride = Dynamic; #[inline] fn ptr(&self) -> *const N { self.data.as_ptr() } #[inline] fn shape(&self) -> (Dynamic, C) { (self.nrows, self.ncols) } #[inline] fn strides(&self) -> (Self::RStride, Self::CStride) { (Self::RStride::name(), self.nrows) } #[inline] fn is_contiguous(&self) -> bool { true } #[inline] fn into_owned(self) -> Owned where DefaultAllocator: Allocator { self } #[inline] fn clone_owned(&self) -> Owned where DefaultAllocator: Allocator { self.clone() } #[inline] fn as_slice(&self) -> &[N] { &self[..] } } unsafe impl Storage for MatrixVec where DefaultAllocator: Allocator { type RStride = U1; type CStride = R; #[inline] fn ptr(&self) -> *const N { self.data.as_ptr() } #[inline] fn shape(&self) -> (R, Dynamic) { (self.nrows, self.ncols) } #[inline] fn strides(&self) -> (Self::RStride, Self::CStride) { (Self::RStride::name(), self.nrows) } #[inline] fn is_contiguous(&self) -> bool { true } #[inline] fn into_owned(self) -> Owned where DefaultAllocator: Allocator { self } #[inline] fn clone_owned(&self) -> Owned where DefaultAllocator: Allocator { self.clone() } #[inline] fn as_slice(&self) -> &[N] { &self[..] } } /* * * StorageMut, ContiguousStorage. * */ unsafe impl StorageMut for MatrixVec where DefaultAllocator: Allocator { #[inline] fn ptr_mut(&mut self) -> *mut N { self.data.as_mut_ptr() } #[inline] fn as_mut_slice(&mut self) -> &mut [N] { &mut self.data[..] } } unsafe impl ContiguousStorage for MatrixVec where DefaultAllocator: Allocator {} unsafe impl ContiguousStorageMut for MatrixVec where DefaultAllocator: Allocator {} unsafe impl StorageMut for MatrixVec where DefaultAllocator: Allocator { #[inline] fn ptr_mut(&mut self) -> *mut N { self.data.as_mut_ptr() } #[inline] fn as_mut_slice(&mut self) -> &mut [N] { &mut self.data[..] } } #[cfg(feature = "abomonation-serialize")] impl Abomonation for MatrixVec { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { self.data.entomb(writer) } unsafe fn exhume<'a, 'b>(&'a mut self, bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { self.data.exhume(bytes) } fn extent(&self) -> usize { self.data.extent() } } unsafe impl ContiguousStorage for MatrixVec where DefaultAllocator: Allocator {} unsafe impl ContiguousStorageMut for MatrixVec where DefaultAllocator: Allocator {} impl Extend for MatrixVec { /// Extends the number of columns of the `MatrixVec` with elements /// from the given iterator. /// /// # Panics /// This function panics if the number of elements yielded by the /// given iterator is not a multiple of the number of rows of the /// `MatrixVec`. fn extend>(&mut self, iter: I) { self.data.extend(iter); self.ncols = Dynamic::new(self.data.len() / self.nrows.value()); assert!(self.data.len() % self.nrows.value() == 0, "The number of elements produced by the given iterator was not a multiple of the number of rows."); } } impl Extend> for MatrixVec where N: Scalar, R: Dim, RV: Dim, SV: Storage { /// Extends the number of columns of the `MatrixVec` with vectors /// from the given iterator. /// /// # Panics /// This function panics if the number of rows of each `Vector` /// yielded by the iterator is not equal to the number of rows /// of this `MatrixVec`. fn extend>>(&mut self, iter: I) { let nrows = self.nrows.value(); let iter = iter.into_iter(); let (lower, _upper) = iter.size_hint(); self.data.reserve(nrows * lower); for vector in iter { assert_eq!(nrows, vector.shape().0); self.data.extend(vector.iter()); } self.ncols = Dynamic::new(self.data.len() / nrows); } } impl Extend for MatrixVec { /// Extends the number of rows of the `MatrixVec` with elements /// from the given iterator. fn extend>(&mut self, iter: I) { self.data.extend(iter); self.nrows = Dynamic::new(self.data.len()); } }