use std::ops::{Deref, Range};
use std::marker::PhantomData;
use std::ptr::{addr_of_mut, NonNull};
#[cfg(feature = "ndarray")]
use ndarray::{ArrayBase, DataMut, Ix2};
use crate::seq::SwappableVectorViewMut;
use crate::seq::{VectorView, VectorViewMut};
pub unsafe trait AsPointerToSlice<T> {
unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T>;
}
unsafe impl<T> AsPointerToSlice<T> for Vec<T> {
unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> {
unsafe {
NonNull::new((*self_.as_ptr()).as_mut_ptr()).unwrap()
}
}
}
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct DerefArray<T, const SIZE: usize> {
pub data: [T; SIZE]
}
impl<T: std::fmt::Debug, const SIZE: usize> std::fmt::Debug for DerefArray<T, SIZE> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.data.fmt(f)
}
}
impl<T, const SIZE: usize> From<[T; SIZE]> for DerefArray<T, SIZE> {
fn from(value: [T; SIZE]) -> Self {
Self { data: value }
}
}
impl<'a, T, const SIZE: usize> From<&'a [T; SIZE]> for &'a DerefArray<T, SIZE> {
fn from(value: &'a [T; SIZE]) -> Self {
unsafe { std::mem::transmute(value) }
}
}
impl<'a, T, const SIZE: usize> From<&'a mut [T; SIZE]> for &'a mut DerefArray<T, SIZE> {
fn from(value: &'a mut [T; SIZE]) -> Self {
unsafe { std::mem::transmute(value) }
}
}
impl<T, const SIZE: usize> Deref for DerefArray<T, SIZE> {
type Target = [T];
fn deref(&self) -> &Self::Target {
&self.data[..]
}
}
unsafe impl<T, const SIZE: usize> AsPointerToSlice<T> for DerefArray<T, SIZE> {
unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> {
unsafe {
let self_ptr = self_.as_ptr();
let data_ptr = addr_of_mut!((*self_ptr).data);
NonNull::new((*data_ptr).as_mut_ptr()).unwrap()
}
}
}
#[repr(transparent)]
pub struct AsFirstElement<T>(T);
unsafe impl<'a, T> AsPointerToSlice<T> for AsFirstElement<T> {
unsafe fn get_pointer(self_: NonNull<Self>) -> NonNull<T> {
std::mem::transmute(self_)
}
}
#[stability::unstable(feature = "enable")]
pub struct SubmatrixRaw<V, T>
where V: AsPointerToSlice<T>
{
entry: PhantomData<*mut T>,
rows: NonNull<V>,
row_count: usize,
row_step: isize,
col_start: usize,
col_count: usize
}
unsafe impl<V, T> Send for SubmatrixRaw<V, T>
where V: AsPointerToSlice<T> + Sync, T: Sync
{}
unsafe impl<V, T> Sync for SubmatrixRaw<V, T>
where V: AsPointerToSlice<T> + Sync, T: Sync
{}
impl<V, T> Clone for SubmatrixRaw<V, T>
where V: AsPointerToSlice<T>
{
fn clone(&self) -> Self {
*self
}
}
impl<V, T> Copy for SubmatrixRaw<V, T>
where V: AsPointerToSlice<T>
{}
impl<V, T> SubmatrixRaw<V, T>
where V: AsPointerToSlice<T>
{
#[stability::unstable(feature = "enable")]
pub unsafe fn new(rows: NonNull<V>, row_count: usize, row_step: isize, cols_start: usize, col_count: usize) -> Self {
Self {
entry: PhantomData,
row_count: row_count,
row_step: row_step,
rows: rows,
col_start: cols_start,
col_count
}
}
#[stability::unstable(feature = "enable")]
pub fn restrict_rows(mut self, rows: Range<usize>) -> Self {
assert!(rows.start <= rows.end);
assert!(rows.end <= self.row_count);
unsafe {
self.row_count = rows.end - rows.start;
self.rows = self.rows.offset(rows.start as isize * self.row_step);
}
self
}
#[stability::unstable(feature = "enable")]
pub fn restrict_cols(mut self, cols: Range<usize>) -> Self {
assert!(cols.end <= self.col_count);
self.col_count = cols.end - cols.start;
self.col_start += cols.start;
self
}
#[stability::unstable(feature = "enable")]
pub fn row_at(&self, row: usize) -> NonNull<[T]> {
assert!(row < self.row_count);
let row_ref = unsafe {
V::get_pointer(self.rows.offset(row as isize * self.row_step))
};
unsafe {
NonNull::slice_from_raw_parts(row_ref.offset(self.col_start as isize), self.col_count)
}
}
#[stability::unstable(feature = "enable")]
pub fn entry_at(&self, row: usize, col: usize) -> NonNull<T> {
assert!(row < self.row_count);
assert!(col < self.col_count);
let row_ref = unsafe {
V::get_pointer(self.rows.offset(row as isize * self.row_step))
};
unsafe {
row_ref.offset(self.col_start as isize + col as isize)
}
}
}
pub struct Column<'a, V, T>
where V: AsPointerToSlice<T>
{
entry: PhantomData<&'a T>,
raw_data: SubmatrixRaw<V, T>
}
impl<'a, V, T> Column<'a, V, T>
where V: AsPointerToSlice<T>
{
unsafe fn new(raw_data: SubmatrixRaw<V, T>) -> Self {
assert!(raw_data.col_count == 1);
Self {
entry: PhantomData,
raw_data: raw_data
}
}
}
impl<'a, V, T> Clone for Column<'a, V, T>
where V: AsPointerToSlice<T>
{
fn clone(&self) -> Self {
*self
}
}
impl<'a, V, T> Copy for Column<'a, V, T>
where V: AsPointerToSlice<T>
{}
impl<'a, V, T> VectorView<T> for Column<'a, V, T>
where V: AsPointerToSlice<T>
{
fn len(&self) -> usize {
self.raw_data.row_count
}
fn at(&self, i: usize) -> &T {
unsafe {
self.raw_data.entry_at(i, 0).as_ref()
}
}
}
pub struct ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
entry: PhantomData<&'a mut T>,
raw_data: SubmatrixRaw<V, T>
}
impl<'a, V, T> ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
unsafe fn new(raw_data: SubmatrixRaw<V, T>) -> Self {
assert!(raw_data.col_count == 1);
Self {
entry: PhantomData,
raw_data: raw_data
}
}
pub fn reborrow<'b>(&'b mut self) -> ColumnMut<'b, V, T> {
ColumnMut {
entry: PhantomData,
raw_data: self.raw_data
}
}
pub fn two_entries<'b>(&'b mut self, i: usize, j: usize) -> (&'b mut T, &'b mut T) {
assert!(i != j);
unsafe {
(self.raw_data.entry_at(i, 0).as_mut(), self.raw_data.entry_at(j, 0).as_mut())
}
}
pub fn as_const<'b>(&'b self) -> Column<'b, V, T> {
Column {
entry: PhantomData,
raw_data: self.raw_data
}
}
}
unsafe impl<'a, V, T> Send for ColumnMut<'a, V, T>
where V: AsPointerToSlice<T> + Sync, T: Send
{}
impl<'a, V, T> VectorView<T> for ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
fn len(&self) -> usize {
self.raw_data.row_count
}
fn at(&self, i: usize) -> &T {
unsafe {
self.raw_data.entry_at(i, 0).as_ref()
}
}
}
pub struct ColumnMutIter<'a, V, T>
where V: AsPointerToSlice<T>
{
column_mut: ColumnMut<'a, V, T>
}
impl<'a, V, T> Iterator for ColumnMutIter<'a, V, T>
where V: AsPointerToSlice<T>
{
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.column_mut.raw_data.row_count > 0 {
let mut result = self.column_mut.raw_data.entry_at(0, 0);
self.column_mut.raw_data = self.column_mut.raw_data.restrict_rows(1..self.column_mut.raw_data.row_count);
unsafe {
Some(result.as_mut())
}
} else {
None
}
}
}
impl<'a, V, T> IntoIterator for ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
type Item = &'a mut T;
type IntoIter = ColumnMutIter<'a, V, T>;
fn into_iter(self) -> ColumnMutIter<'a, V, T> {
ColumnMutIter { column_mut: self }
}
}
impl<'a, V, T> VectorViewMut<T> for ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
fn at_mut<'b>(&'b mut self, i: usize) -> &'b mut T {
unsafe {
self.raw_data.entry_at(i, 0).as_mut()
}
}
}
impl<'a, V, T> SwappableVectorViewMut<T> for ColumnMut<'a, V, T>
where V: AsPointerToSlice<T>
{
fn swap(&mut self, i: usize, j: usize) {
if i != j {
unsafe {
std::mem::swap(self.raw_data.entry_at(i, 0).as_mut(), self.raw_data.entry_at(j, 0).as_mut());
}
}
}
}
pub struct Submatrix<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{
entry: PhantomData<&'a T>,
raw_data: SubmatrixRaw<V, T>
}
impl<'a, V, T> Submatrix<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{
pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
self.restrict_rows(rows).restrict_cols(cols)
}
pub fn restrict_rows(self, rows: Range<usize>) -> Self {
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_rows(rows)
}
}
pub fn into_at(self, i: usize, j: usize) -> &'a T {
&self.into_row_at(i)[j]
}
pub fn at<'b>(&'b self, i: usize, j: usize) -> &'b T {
&self.row_at(i)[j]
}
pub fn restrict_cols(self, cols: Range<usize>) -> Self {
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_cols(cols)
}
}
pub fn row_iter(self) -> impl 'a + Clone + ExactSizeIterator<Item = &'a [T]> {
(0..self.raw_data.row_count).map(move |i|
unsafe {
self.raw_data.row_at(i).as_ref()
})
}
pub fn col_iter(self) -> impl 'a + Clone + ExactSizeIterator<Item = Column<'a, V, T>> {
(0..self.raw_data.col_count).map(move |j| {
debug_assert!(j < self.raw_data.col_count);
let mut result_raw = self.raw_data;
result_raw.col_start += j;
result_raw.col_count = 1;
unsafe {
return Column::new(result_raw);
}
})
}
pub fn into_row_at(self, i: usize) -> &'a [T] {
unsafe {
self.raw_data.row_at(i).as_ref()
}
}
pub fn row_at<'b>(&'b self, i: usize) -> &'b [T] {
unsafe {
self.raw_data.row_at(i).as_ref()
}
}
pub fn into_col_at(self, j: usize) -> Column<'a, V, T> {
assert!(j < self.raw_data.col_count);
let mut result_raw = self.raw_data;
result_raw.col_start += j;
result_raw.col_count = 1;
unsafe {
return Column::new(result_raw);
}
}
pub fn col_at<'b>(&'b self, j: usize) -> Column<'b, V, T> {
assert!(j < self.raw_data.col_count);
let mut result_raw = self.raw_data;
result_raw.col_start += j;
result_raw.col_count = 1;
unsafe {
return Column::new(result_raw);
}
}
pub fn col_count(&self) -> usize {
self.raw_data.col_count
}
pub fn row_count(&self) -> usize {
self.raw_data.row_count
}
}
impl<'a, V, T> Clone for Submatrix<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{
fn clone(&self) -> Self {
*self
}
}
impl<'a, V, T> Copy for Submatrix<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{}
pub struct SubmatrixMut<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{
entry: PhantomData<&'a mut T>,
raw_data: SubmatrixRaw<V, T>
}
impl<'a, V, T> SubmatrixMut<'a, V, T>
where V: 'a + AsPointerToSlice<T>
{
pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
self.restrict_rows(rows).restrict_cols(cols)
}
pub fn restrict_rows(self, rows: Range<usize>) -> Self {
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_rows(rows)
}
}
pub fn restrict_cols(self, cols: Range<usize>) -> Self {
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_cols(cols)
}
}
pub fn split_rows(self, fst_rows: Range<usize>, snd_rows: Range<usize>) -> (Self, Self) {
assert!(fst_rows.end <= snd_rows.start || snd_rows.end <= fst_rows.start);
(
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_rows(fst_rows)
},
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_rows(snd_rows)
},
)
}
pub fn split_cols(self, fst_cols: Range<usize>, snd_cols: Range<usize>) -> (Self, Self) {
assert!(fst_cols.end <= snd_cols.start || snd_cols.end <= fst_cols.start);
(
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_cols(fst_cols)
},
Self {
entry: PhantomData,
raw_data: self.raw_data.restrict_cols(snd_cols)
},
)
}
pub fn row_iter(self) -> impl 'a + ExactSizeIterator<Item = &'a mut [T]> {
(0..self.raw_data.row_count).map(move |i|
unsafe {
self.raw_data.row_at(i).as_mut()
})
}
pub fn col_iter(self) -> impl 'a + ExactSizeIterator<Item = ColumnMut<'a, V, T>> {
(0..self.raw_data.col_count).map(move |j| {
let mut result_raw = self.raw_data;
result_raw.col_start += j;
result_raw.col_count = 1;
unsafe {
return ColumnMut::new(result_raw);
}
})
}
#[stability::unstable(feature = "enable")]
pub fn into_at_mut(self, i: usize, j: usize) -> &'a mut T {
&mut self.into_row_mut_at(i)[j]
}
pub fn at_mut<'b>(&'b mut self, i: usize, j: usize) -> &'b mut T {
&mut self.row_mut_at(i)[j]
}
pub fn at<'b>(&'b self, i: usize, j: usize) -> &'b T {
self.as_const().into_at(i, j)
}
pub fn row_at<'b>(&'b self, i: usize) -> &'b [T] {
self.as_const().into_row_at(i)
}
#[stability::unstable(feature = "enable")]
pub fn into_row_mut_at(self, i: usize) -> &'a mut [T] {
unsafe {
self.raw_data.row_at(i).as_mut()
}
}
pub fn row_mut_at<'b>(&'b mut self, i: usize) -> &'b mut [T] {
self.reborrow().into_row_mut_at(i)
}
pub fn col_at<'b>(&'b self, j: usize) -> Column<'b, V, T> {
self.as_const().into_col_at(j)
}
pub fn col_mut_at<'b>(&'b mut self, j: usize) -> ColumnMut<'b, V, T> {
assert!(j < self.raw_data.col_count);
let mut result_raw = self.raw_data;
result_raw.col_start += j;
result_raw.col_count = 1;
unsafe {
return ColumnMut::new(result_raw);
}
}
pub fn reborrow<'b>(&'b mut self) -> SubmatrixMut<'b, V, T> {
SubmatrixMut {
entry: PhantomData,
raw_data: self.raw_data
}
}
pub fn as_const<'b>(&'b self) -> Submatrix<'b, V, T> {
Submatrix {
entry: PhantomData,
raw_data: self.raw_data
}
}
pub fn col_count(&self) -> usize {
self.raw_data.col_count
}
pub fn row_count(&self) -> usize {
self.raw_data.row_count
}
}
impl<'a, V, T> SubmatrixMut<'a, V, T>
where V: 'a + Sync + AsPointerToSlice<T>,
T: Send
{
#[cfg(not(feature = "parallel"))]
pub fn concurrent_row_iter(self) -> impl 'a + ExactSizeIterator<Item = &'a mut [T]> {
self.row_iter()
}
#[cfg(not(feature = "parallel"))]
pub fn concurrent_col_iter(self) -> impl 'a + ExactSizeIterator<Item = ColumnMut<'a, V, T>> {
self.col_iter()
}
#[cfg(feature = "parallel")]
pub fn concurrent_row_iter(self) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = &'a mut [T]> {
struct AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
entry: PhantomData<&'a ()>,
raw_data: SubmatrixRaw<V, T>
}
unsafe impl<'a, V, T> Sync for AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{}
unsafe impl<'a, V, T> Send for AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{}
impl<'a, V, T> FnOnce<(usize,)> for AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
type Output = &'a mut [T];
extern "rust-call" fn call_once(self, args: (usize,)) -> Self::Output {
self.call(args)
}
}
impl<'a, V, T> FnMut<(usize,)> for AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
extern "rust-call" fn call_mut(&mut self, args: (usize,)) -> Self::Output {
self.call(args)
}
}
impl<'a, V, T> Fn<(usize,)> for AccessIthRow<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
extern "rust-call" fn call(&self, args: (usize,)) -> Self::Output {
unsafe {
self.raw_data.row_at(args.0).as_mut()
}
}
}
rayon::iter::ParallelIterator::map(
rayon::iter::IntoParallelIterator::into_par_iter(0..self.row_count()),
AccessIthRow { entry: PhantomData, raw_data: self.raw_data }
)
}
#[cfg(feature = "parallel")]
pub fn concurrent_col_iter(self) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = ColumnMut<'a, V, T>> {
struct AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
entry: PhantomData<&'a ()>,
raw_data: SubmatrixRaw<V, T>
}
unsafe impl<'a, V, T> Sync for AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{}
unsafe impl<'a, V, T> Send for AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{}
impl<'a, V, T> FnOnce<(usize,)> for AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
type Output = ColumnMut<'a, V, T>;
extern "rust-call" fn call_once(self, args: (usize,)) -> Self::Output {
self.call(args)
}
}
impl<'a, V, T> FnMut<(usize,)> for AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
extern "rust-call" fn call_mut(&mut self, args: (usize,)) -> Self::Output {
self.call(args)
}
}
impl<'a, V, T> Fn<(usize,)> for AccessIthCol<'a, V, T>
where V: Sync + AsPointerToSlice<T>, T: 'a + Send
{
extern "rust-call" fn call(&self, args: (usize,)) -> Self::Output {
let mut result_raw = self.raw_data;
result_raw.col_start += args.0;
result_raw.col_count = 1;
unsafe {
return ColumnMut::new(result_raw);
}
}
}
rayon::iter::ParallelIterator::map(
rayon::iter::IntoParallelIterator::into_par_iter(0..self.col_count()),
AccessIthCol { entry: PhantomData, raw_data: self.raw_data }
)
}
}
impl<'a, V, T> Submatrix<'a, V, T>
where V: 'a + Sync + AsPointerToSlice<T>,
T: Sync
{
#[cfg(not(feature = "parallel"))]
pub fn concurrent_row_iter(self) -> impl 'a + ExactSizeIterator<Item = &'a [T]> {
self.row_iter()
}
#[cfg(feature = "parallel")]
pub fn concurrent_row_iter(self) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = &'a [T]> {
rayon::iter::ParallelIterator::map(
rayon::iter::IntoParallelIterator::into_par_iter(0..self.row_count()),
move |i| unsafe { self.raw_data.row_at(i).as_ref() }
)
}
}
impl<'a, T> SubmatrixMut<'a, AsFirstElement<T>, T> {
pub fn new(data: &'a mut [T], row_count: usize, col_count: usize) -> Self {
assert_eq!(row_count * col_count, data.len());
unsafe {
Self {
entry: PhantomData,
raw_data: SubmatrixRaw::new(std::mem::transmute(NonNull::new(data.as_mut_ptr()).unwrap_unchecked()), row_count, col_count as isize, 0, col_count)
}
}
}
#[cfg(feature = "ndarray")]
pub fn from_ndarray<S>(data: &'a mut ArrayBase<S, Ix2>) -> Self
where S: DataMut<Elem = T>
{
assert!(data.is_standard_layout());
let (nrows, ncols) = (data.nrows(), data.ncols());
return Self::new(data.as_slice_mut().unwrap(), nrows, ncols);
}
}
impl<'a, V: AsPointerToSlice<T> + Deref<Target = [T]>, T> SubmatrixMut<'a, V, T> {
pub fn new(data: &'a mut [V]) -> Self {
assert!(data.len() > 0);
let row_count = data.len();
let col_count = data[0].len();
for row in data.iter() {
assert_eq!(col_count, row.len());
}
unsafe {
Self {
entry: PhantomData,
raw_data: SubmatrixRaw::new(NonNull::new(data.as_mut_ptr() as *mut _).unwrap_unchecked(), row_count, 1, 0, col_count)
}
}
}
}
impl<'a, T> Submatrix<'a, AsFirstElement<T>, T> {
pub fn new(data: &'a [T], row_count: usize, col_count: usize) -> Self {
assert_eq!(row_count * col_count, data.len());
unsafe {
Self {
entry: PhantomData,
raw_data: SubmatrixRaw::new(std::mem::transmute(NonNull::new(data.as_ptr() as *mut T).unwrap_unchecked()), row_count, col_count as isize, 0, col_count)
}
}
}
#[cfg(feature = "ndarray")]
pub fn from_ndarray<S>(data: &'a ArrayBase<S, Ix2>) -> Self
where S: DataMut<Elem = T>
{
let (nrows, ncols) = (data.nrows(), data.ncols());
return Self::new(data.as_slice().unwrap(), nrows, ncols);
}
}
impl<'a, V: AsPointerToSlice<T> + Deref<Target = [T]>, T> Submatrix<'a, V, T> {
pub fn new(data: &'a [V]) -> Self {
assert!(data.len() > 0);
let row_count = data.len();
let col_count = data[0].len();
for row in data.iter() {
assert_eq!(col_count, row.len());
}
unsafe {
Self {
entry: PhantomData,
raw_data: SubmatrixRaw::new(NonNull::new(data.as_ptr() as *mut _).unwrap_unchecked(), row_count, 1, 0, col_count)
}
}
}
}
#[cfg(test)]
use std::fmt::Debug;
#[cfg(test)]
fn assert_submatrix_eq<V: AsPointerToSlice<T>, T: PartialEq + Debug, const N: usize, const M: usize>(expected: [[T; M]; N], actual: &mut SubmatrixMut<V, T>) {
assert_eq!(N, actual.row_count());
assert_eq!(M, actual.col_count());
for i in 0..N {
for j in 0..M {
assert_eq!(&expected[i][j], actual.at(i, j));
assert_eq!(&expected[i][j], actual.as_const().at(i, j));
}
}
}
#[cfg(test)]
fn with_testmatrix_vec<F>(f: F)
where F: FnOnce(SubmatrixMut<Vec<i64>, i64>)
{
let mut data = vec![
vec![1, 2, 3, 4, 5],
vec![6, 7, 8, 9, 10],
vec![11, 12, 13, 14, 15]
];
let matrix = SubmatrixMut::<Vec<_>, _>::new(&mut data[..]);
f(matrix)
}
#[cfg(test)]
fn with_testmatrix_array<F>(f: F)
where F: FnOnce(SubmatrixMut<DerefArray<i64, 5>, i64>)
{
let mut data = vec![
DerefArray::from([1, 2, 3, 4, 5]),
DerefArray::from([6, 7, 8, 9, 10]),
DerefArray::from([11, 12, 13, 14, 15])
];
let matrix = SubmatrixMut::<DerefArray<_, 5>, _>::new(&mut data[..]);
f(matrix)
}
#[cfg(test)]
fn with_testmatrix_linmem<F>(f: F)
where F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>)
{
let mut data = vec![
1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15
];
let matrix = SubmatrixMut::<AsFirstElement<_>, _>::new(&mut data[..], 3, 5);
f(matrix)
}
#[cfg(feature = "ndarray")]
#[cfg(test)]
fn with_testmatrix_ndarray<F>(f: F)
where F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>)
{
use ndarray::array;
let mut data = array![
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
];
let matrix = SubmatrixMut::<AsFirstElement<_>, _>::from_ndarray(&mut data);
f(matrix)
}
#[cfg(not(feature = "ndarray"))]
#[cfg(test)]
fn with_testmatrix_ndarray<F>(_: F)
where F: FnOnce(SubmatrixMut<AsFirstElement<i64>, i64>)
{
}
#[cfg(test)]
fn test_submatrix<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
assert_submatrix_eq([[2, 3], [7, 8]], &mut matrix.reborrow().submatrix(0..2, 1..3));
assert_submatrix_eq([[8, 9, 10]], &mut matrix.reborrow().submatrix(1..2, 2..5));
assert_submatrix_eq([[8, 9, 10], [13, 14, 15]], &mut matrix.reborrow().submatrix(1..3, 2..5));
let (mut left, mut right) = matrix.split_cols(0..3, 3..5);
assert_submatrix_eq([[1, 2, 3], [6, 7, 8], [11, 12, 13]], &mut left);
assert_submatrix_eq([[4, 5], [9, 10], [14, 15]], &mut right);
}
#[test]
fn test_submatrix_wrapper() {
with_testmatrix_vec(test_submatrix);
with_testmatrix_array(test_submatrix);
with_testmatrix_linmem(test_submatrix);
with_testmatrix_ndarray(test_submatrix);
}
#[cfg(test)]
fn test_submatrix_mutate<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
let (mut left, mut right) = matrix.split_cols(0..3, 3..5);
assert_submatrix_eq([[1, 2, 3], [6, 7, 8], [11, 12, 13]], &mut left);
assert_submatrix_eq([[4, 5], [9, 10], [14, 15]], &mut right);
*left.at_mut(1, 1) += 1;
*right.at_mut(0, 0) += 1;
*right.at_mut(2, 1) += 1;
assert_submatrix_eq([[1, 2, 3], [6, 8, 8], [11, 12, 13]], &mut left);
assert_submatrix_eq([[5, 5], [9, 10], [14, 16]], &mut right);
let (mut top, mut bottom) = left.split_rows(0..1, 1..3);
assert_submatrix_eq([[1, 2, 3]], &mut top);
assert_submatrix_eq([[6, 8, 8], [11, 12, 13]], &mut bottom);
*top.at_mut(0, 0) -= 1;
*top.at_mut(0, 2) += 3;
*bottom.at_mut(0, 2) -= 1;
*bottom.at_mut(1, 0) += 3;
assert_submatrix_eq([[0, 2, 6]], &mut top);
assert_submatrix_eq([[6, 8, 7], [14, 12, 13]], &mut bottom);
}
#[test]
fn test_submatrix_mutate_wrapper() {
with_testmatrix_vec(test_submatrix_mutate);
with_testmatrix_array(test_submatrix_mutate);
with_testmatrix_linmem(test_submatrix_mutate);
with_testmatrix_ndarray(test_submatrix_mutate);
}
#[cfg(test)]
fn test_submatrix_col_iter<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
{
let mut it = matrix.reborrow().col_iter();
assert_eq!(vec![2, 7, 12], it.by_ref().skip(1).next().unwrap().into_iter().map(|x| *x).collect::<Vec<_>>());
assert_eq!(vec![4, 9, 14], it.by_ref().skip(1).next().unwrap().into_iter().map(|x| *x).collect::<Vec<_>>());
let mut last_col = it.next().unwrap();
for x in last_col.reborrow() {
*x *= 2;
}
assert_eq!(vec![10, 20, 30], last_col.into_iter().map(|x| *x).collect::<Vec<_>>());
}
assert_submatrix_eq([
[1, 2, 3, 4, 10],
[6, 7, 8, 9, 20],
[11, 12, 13, 14, 30]],
&mut matrix
);
let (left, _right) = matrix.reborrow().split_cols(0..2, 3..4);
{
let mut it = left.col_iter();
let mut col1 = it.next().unwrap();
let mut col2 = it.next().unwrap();
assert!(it.next().is_none());
assert_eq!(vec![1, 6, 11], col1.as_iter().map(|x| *x).collect::<Vec<_>>());
assert_eq!(vec![2, 7, 12], col2.as_iter().map(|x| *x).collect::<Vec<_>>());
assert_eq!(vec![1, 6, 11], col1.reborrow().into_iter().map(|x| *x).collect::<Vec<_>>());
assert_eq!(vec![2, 7, 12], col2.reborrow().into_iter().map(|x| *x).collect::<Vec<_>>());
*col1.into_iter().skip(1).next().unwrap() += 5;
}
assert_submatrix_eq([
[1, 2, 3, 4, 10],
[11, 7, 8, 9, 20],
[11, 12, 13, 14, 30]],
&mut matrix
);
let (_left, right) = matrix.reborrow().split_cols(0..2, 3..4);
{
let mut it = right.col_iter();
let mut col = it.next().unwrap();
assert!(it.next().is_none());
assert_eq!(vec![4, 9, 14], col.reborrow().as_iter().map(|x| *x).collect::<Vec<_>>());
*col.into_iter().next().unwrap() += 3;
}
assert_submatrix_eq([
[1, 2, 3, 7, 10],
[11, 7, 8, 9, 20],
[11, 12, 13, 14, 30]],
&mut matrix
);
}
#[test]
fn test_submatrix_col_iter_wrapper() {
with_testmatrix_vec(test_submatrix_col_iter);
with_testmatrix_array(test_submatrix_col_iter);
with_testmatrix_linmem(test_submatrix_col_iter);
with_testmatrix_ndarray(test_submatrix_col_iter);
}
#[cfg(test)]
fn test_submatrix_row_iter<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
{
let mut it = matrix.reborrow().row_iter();
assert_eq!(&[6, 7, 8, 9, 10], it.by_ref().skip(1).next().unwrap());
let row = it.next().unwrap();
assert!(it.next().is_none());
row[1] += 6;
row[4] *= 2;
}
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 18, 13, 14, 30]],
&mut matrix
);
let (mut left, mut right) = matrix.reborrow().split_cols(0..2, 3..4);
{
let mut it = left.reborrow().row_iter();
let row1 = it.next().unwrap();
let row2 = it.next().unwrap();
assert!(it.next().is_some());
assert!(it.next().is_none());
assert_eq!(&[1, 2], row1);
assert_eq!(&[6, 7], row2);
}
{
let mut it = left.reborrow().row_iter();
let row1 = it.next().unwrap();
let row2 = it.next().unwrap();
assert!(it.next().is_some());
assert!(it.next().is_none());
assert_eq!(&[1, 2], row1);
assert_eq!(&[6, 7], row2);
row2[1] += 1;
}
assert_submatrix_eq([[1, 2], [6, 8], [11, 18]], &mut left);
{
right = right.submatrix(1..3, 0..1);
let mut it = right.reborrow().row_iter();
let row1 = it.next().unwrap();
let row2 = it.next().unwrap();
assert_eq!(&[9], row1);
assert_eq!(&[14], row2);
row1[0] += 1;
}
assert_submatrix_eq([[10], [14]], &mut right);
}
#[test]
fn test_submatrix_row_iter_wrapper() {
with_testmatrix_vec(test_submatrix_row_iter);
with_testmatrix_array(test_submatrix_row_iter);
with_testmatrix_linmem(test_submatrix_row_iter);
with_testmatrix_ndarray(test_submatrix_row_iter);
}
#[cfg(test)]
fn test_submatrix_col_at<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
assert_eq!(&[2, 7, 12], &matrix.col_at(1).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[2, 7, 12], &matrix.as_const().col_at(1).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5, 10, 15], &matrix.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5, 10, 15], &matrix.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
{
let (mut top, mut bottom) = matrix.reborrow().restrict_rows(0..2).split_rows(0..1, 1..2);
assert_eq!(&[1], &top.col_mut_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[1], &top.as_const().col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[1], &top.col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5], &top.col_mut_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5], &top.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5], &top.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[6], &bottom.col_mut_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[6], &bottom.as_const().col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[6], &bottom.col_at(0).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[10], &bottom.col_mut_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[10], &bottom.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[10], &bottom.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
}
}
#[test]
fn test_submatrix_col_at_wrapper() {
with_testmatrix_vec(test_submatrix_col_at);
with_testmatrix_array(test_submatrix_col_at);
with_testmatrix_linmem(test_submatrix_col_at);
with_testmatrix_ndarray(test_submatrix_col_at);
}
#[cfg(test)]
fn test_submatrix_row_at<V: AsPointerToSlice<i64>>(mut matrix: SubmatrixMut<V, i64>) {
assert_submatrix_eq([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15]
], &mut matrix);
assert_eq!(&[2, 7, 12], &matrix.col_at(1).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[2, 7, 12], &matrix.as_const().col_at(1).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5, 10, 15], &matrix.col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
assert_eq!(&[5, 10, 15], &matrix.as_const().col_at(4).as_iter().copied().collect::<Vec<_>>()[..]);
{
let (mut left, mut right) = matrix.reborrow().restrict_cols(1..5).split_cols(0..2, 2..4);
assert_eq!(&[2, 3], left.row_mut_at(0));
assert_eq!(&[4, 5], right.row_mut_at(0));
assert_eq!(&[2, 3], left.as_const().row_at(0));
assert_eq!(&[4, 5], right.as_const().row_at(0));
assert_eq!(&[2, 3], left.row_at(0));
assert_eq!(&[4, 5], right.row_at(0));
assert_eq!(&[7, 8], left.row_mut_at(1));
assert_eq!(&[9, 10], right.row_mut_at(1));
assert_eq!(&[7, 8], left.as_const().row_at(1));
assert_eq!(&[9, 10], right.as_const().row_at(1));
assert_eq!(&[7, 8], left.row_at(1));
assert_eq!(&[9, 10], right.row_at(1));
}
}
#[test]
fn test_submatrix_row_at_wrapper() {
with_testmatrix_vec(test_submatrix_row_at);
with_testmatrix_array(test_submatrix_row_at);
with_testmatrix_linmem(test_submatrix_row_at);
with_testmatrix_ndarray(test_submatrix_row_at);
}