use std::error;
use std::fmt;
use std::ops;
use std::slice;
#[derive(Debug)]
pub struct MatrixVec<T> {
items: Vec<T>,
size: Size,
}
impl<T> MatrixVec<T> {
#[inline]
pub fn new(items: Vec<T>, size: Size) -> Result<MatrixVec<T>, Error> {
if items.len() == size.width * size.height {
Ok(MatrixVec { items, size })
} else {
Err(Error::InvalidSize)
}
}
#[inline]
pub fn with_default(size: Size) -> MatrixVec<T>
where
T: Clone + Default,
{
MatrixVec::with(T::default(), size)
}
#[inline]
pub fn with(value: T, size: Size) -> MatrixVec<T>
where
T: Clone,
{
MatrixVec {
items: vec![value; size.width * size.height],
size,
}
}
#[inline]
pub fn from_vec(items: Vec<T>, size: Size) -> Result<MatrixVec<T>, Error> {
MatrixVec::new(items, size)
}
#[inline]
pub(crate) fn swap_size(&mut self) {
self.size = Size {
width: self.size.height,
height: self.size.width,
};
}
}
impl<T> Matrix for MatrixVec<T> {
type Item = T;
#[inline]
fn as_slice(&self) -> &[T] {
&self.items
}
#[inline]
fn size(&self) -> Size {
self.size
}
#[inline]
fn width(&self) -> usize {
self.size.width
}
#[inline]
fn height(&self) -> usize {
self.size.height
}
#[inline]
fn stride(&self) -> usize {
self.size.width
}
}
impl<T> MatrixMut for MatrixVec<T> {
#[inline]
fn as_slice_mut(&mut self) -> &mut [T] {
&mut self.items
}
}
#[derive(Debug)]
pub struct MatrixRef<'a, T> {
items: &'a [T],
size: Size,
stride: usize,
}
impl<'a, T> MatrixRef<'a, T> {
#[inline]
pub fn new(items: &[T], size: Size) -> Result<MatrixRef<T>, Error> {
if items.len() == size.width * size.height {
Ok(MatrixRef {
items,
size,
stride: size.width,
})
} else {
Err(Error::InvalidSize)
}
}
#[inline]
pub fn as_slice(&self) -> &'a [T] {
self.items
}
#[inline]
pub fn as_ref(&self) -> MatrixRef<'a, T> {
MatrixRef {
items: self.items,
size: self.size,
stride: self.stride,
}
}
#[inline]
pub fn get(&self, index: (usize, usize)) -> Option<&'a T> {
let offset = self.offset(index).ok()?;
Some(&self.items[offset])
}
#[inline]
pub fn rows(&self) -> Rows<'a, T> {
Rows::new(self.as_ref())
}
#[inline]
pub fn splits(&self, height: usize) -> Splits<'a, T> {
Splits::new(self.as_ref(), height)
}
#[inline]
pub fn windows(&self, size: Size) -> Windows<'a, T> {
Windows::new(self.as_ref(), size)
}
#[inline]
pub fn window(&self, pos: (usize, usize), size: Size) -> Result<MatrixRef<'a, T>, Error> {
let range = self.window_range(pos, size)?;
Ok(MatrixRef {
items: &self.as_slice()[range],
size,
stride: self.stride(),
})
}
}
impl<'a, T> Matrix for MatrixRef<'a, T> {
type Item = T;
#[inline]
fn as_slice(&self) -> &[T] {
self.items
}
#[inline]
fn size(&self) -> Size {
self.size
}
#[inline]
fn width(&self) -> usize {
self.size.width
}
#[inline]
fn height(&self) -> usize {
self.size.height
}
#[inline]
fn stride(&self) -> usize {
self.stride
}
}
#[derive(Debug)]
pub struct MatrixRefMut<'a, T> {
items: &'a mut [T],
size: Size,
stride: usize,
}
impl<'a, T> MatrixRefMut<'a, T> {
#[inline]
pub fn new(items: &mut [T], size: Size) -> Result<MatrixRefMut<T>, Error> {
if items.len() == size.width * size.height {
Ok(MatrixRefMut {
items,
size,
stride: size.width,
})
} else {
Err(Error::InvalidSize)
}
}
#[inline]
fn into_slice(self) -> &'a mut [T] {
self.items
}
#[inline]
pub fn splits_move(self, height: usize) -> SplitsMut<'a, T> {
SplitsMut::new(self, height)
}
}
impl<'a, T> Matrix for MatrixRefMut<'a, T> {
type Item = T;
#[inline]
fn as_slice(&self) -> &[T] {
self.items
}
#[inline]
fn size(&self) -> Size {
self.size
}
#[inline]
fn width(&self) -> usize {
self.size.width
}
#[inline]
fn height(&self) -> usize {
self.size.height
}
#[inline]
fn stride(&self) -> usize {
self.stride
}
}
impl<'a, T> MatrixMut for MatrixRefMut<'a, T> {
#[inline]
fn as_slice_mut(&mut self) -> &mut [T] {
self.items
}
}
pub trait Matrix: ops::Index<(usize, usize), Output = Self::Item> {
type Item;
fn as_slice(&self) -> &[Self::Item];
fn size(&self) -> Size;
fn width(&self) -> usize;
fn height(&self) -> usize;
fn stride(&self) -> usize;
#[inline]
fn to_owned(&self) -> MatrixVec<Self::Item>
where
Self::Item: Clone,
{
let items = if self.width() * self.height() == self.as_slice().len() {
self.as_slice().to_vec()
} else {
let mut items = Vec::with_capacity(self.width() * self.height());
for row in self.rows() {
items.extend_from_slice(row);
}
items
};
MatrixVec::from_vec(items, self.size()).expect("matrix should have a valid Size")
}
#[inline]
#[deprecated(note = "use `Matrix::to_owned` instead")]
fn promote(&self) -> MatrixVec<Self::Item>
where
Self::Item: Clone,
{
self.to_owned()
}
#[inline]
fn rows(&self) -> Rows<Self::Item> {
Rows::new(self.as_ref())
}
#[inline]
fn splits(&self, height: usize) -> Splits<Self::Item> {
Splits::new(self.as_ref(), height)
}
#[inline]
fn windows(&self, size: Size) -> Windows<Self::Item> {
Windows::new(self.as_ref(), size)
}
#[inline]
fn as_ref(&self) -> MatrixRef<Self::Item> {
MatrixRef {
items: self.as_slice(),
size: self.size(),
stride: self.stride(),
}
}
#[inline]
fn get(&self, index: (usize, usize)) -> Option<&Self::Item> {
let offset = self.offset(index).ok()?;
Some(&self.as_slice()[offset])
}
#[inline]
fn window(&self, pos: (usize, usize), size: Size) -> Result<MatrixRef<Self::Item>, Error> {
self.as_ref().window(pos, size)
}
}
pub trait MatrixMut: Matrix + ops::IndexMut<(usize, usize), Output = Self::Item> {
fn as_slice_mut(&mut self) -> &mut [Self::Item];
#[inline]
fn rows_mut(&mut self) -> RowsMut<Self::Item> {
RowsMut::new(self.as_mut())
}
#[inline]
fn splits_mut(&mut self, height: usize) -> SplitsMut<Self::Item> {
SplitsMut::new(self.as_mut(), height)
}
#[inline]
fn as_mut(&mut self) -> MatrixRefMut<Self::Item> {
MatrixRefMut {
size: self.size(),
stride: self.stride(),
items: self.as_slice_mut(),
}
}
#[inline]
fn get_mut(&mut self, index: (usize, usize)) -> Option<&mut Self::Item> {
let offset = self.offset(index).ok()?;
Some(&mut self.as_slice_mut()[offset])
}
#[inline]
fn get_pair_mut(
&mut self,
index1: (usize, usize),
index2: (usize, usize),
) -> Option<(&mut Self::Item, &mut Self::Item)> {
let index1 = self.offset(index1).ok()?;
let index2 = self.offset(index2).ok()?;
get_pair_mut(self.as_slice_mut(), index1, index2)
}
#[inline]
fn window_mut(
&mut self,
pos: (usize, usize),
size: Size,
) -> Result<MatrixRefMut<Self::Item>, Error> {
let range = self.window_range(pos, size)?;
Ok(MatrixRefMut {
stride: self.stride(),
items: &mut self.as_slice_mut()[range],
size,
})
}
}
macro_rules! impl_index {
($Self:ty) => {
impl<'a, T> ops::Index<(usize, usize)> for $Self {
type Output = T;
#[inline]
fn index(&self, index: (usize, usize)) -> &Self::Output {
self.get(index).expect("indices should be in bounds")
}
}
};
}
macro_rules! impl_index_mut {
($Self:ty) => {
impl<'a, T> ops::IndexMut<(usize, usize)> for $Self {
#[inline]
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
self.get_mut(index).expect("indices should be in bounds")
}
}
};
}
impl_index!(MatrixVec<T>);
impl_index!(MatrixRef<'_, T>);
impl_index!(MatrixRefMut<'_, T>);
impl_index_mut!(MatrixVec<T>);
impl_index_mut!(MatrixRefMut<'_, T>);
macro_rules! impl_partial_eq {
($Self:ty) => {
impl<'a, T, M> PartialEq<M> for $Self
where
M: Matrix<Item = T>,
T: PartialEq,
{
#[inline]
fn eq(&self, other: &M) -> bool {
self.size() == other.size() && self.rows().eq(other.rows())
}
}
};
}
impl_partial_eq!(MatrixVec<T>);
impl_partial_eq!(MatrixRef<'_, T>);
impl_partial_eq!(MatrixRefMut<'_, T>);
impl<T, const W: usize, const H: usize> From<[[T; W]; H]> for MatrixVec<T>
where
T: Clone,
{
#[inline]
fn from(arr: [[T; W]; H]) -> MatrixVec<T> {
let size = Size {
width: W,
height: H,
};
let mut items = Vec::new();
for row in arr {
for t in row {
items.push(t.clone());
}
}
MatrixVec { items, size }
}
}
impl<'a, T, const W: usize, const H: usize> From<&'a [[T; W]; H]> for MatrixRef<'a, T> {
#[inline]
fn from(arr: &'a [[T; W]; H]) -> MatrixRef<'a, T> {
let size = Size {
width: W,
height: H,
};
MatrixRef {
items: arr.as_flattened(),
size,
stride: W,
}
}
}
impl<'a, T, const W: usize, const H: usize> From<&'a mut [[T; W]; H]> for MatrixRefMut<'a, T> {
#[inline]
fn from(arr: &'a mut [[T; W]; H]) -> MatrixRefMut<'a, T> {
let size = Size {
width: W,
height: H,
};
MatrixRefMut {
items: arr.as_flattened_mut(),
size,
stride: W,
}
}
}
#[derive(Debug, PartialEq)]
pub enum Error {
OutOfBounds,
InvalidSize,
}
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Error::InvalidSize => write!(f, "slice's length does not match the `Size`"),
Error::OutOfBounds => write!(f, "indices are out of bounds"),
}
}
}
impl error::Error for Error {}
#[derive(Clone, Copy, Default, Debug, PartialEq)]
pub struct Size {
pub width: usize,
pub height: usize,
}
impl From<(usize, usize)> for Size {
#[inline]
fn from((width, height): (usize, usize)) -> Size {
Size { width, height }
}
}
impl From<Size> for (usize, usize) {
#[inline]
fn from(size: Size) -> (usize, usize) {
(size.width, size.height)
}
}
#[inline]
fn get_pair_mut<T>(slice: &mut [T], i: usize, j: usize) -> Option<(&mut T, &mut T)> {
if i == j {
return None;
}
let low = std::cmp::min(i, j);
let high = std::cmp::max(i, j);
if high >= slice.len() {
return None;
}
let [x, .., y] = &mut slice[low..=high] else {
return None;
};
let pair = if i < j { (x, y) } else { (y, x) };
Some(pair)
}
trait MatrixBounds: Matrix {
#[inline]
fn offset(&self, index: (usize, usize)) -> Result<usize, Error> {
if index.0 < self.width() && index.1 < self.height() {
Ok(index.1 * self.stride() + index.0)
} else {
Err(Error::OutOfBounds)
}
}
#[inline]
fn is_aligned(&self) -> bool {
is_aligned(self.as_slice(), self.size(), self.stride())
}
#[inline]
fn window_range(
&self,
(left, top): (usize, usize),
size: Size,
) -> Result<std::ops::Range<usize>, Error> {
let right = left + size.width;
let bottom = top + size.height;
if size.width == 0 || size.height == 0 {
Ok(0..0)
} else if left >= self.width() || top >= self.height() {
Err(Error::OutOfBounds)
} else if right > self.width() || bottom > self.height() {
Err(Error::InvalidSize)
} else {
let start = self.stride() * top + left;
let end = self.stride() * (bottom - 1) + right;
Ok(start..end)
}
}
}
impl<M: ?Sized> MatrixBounds for M where M: Matrix {}
#[inline]
fn is_aligned<T>(slice: &[T], size: Size, stride: usize) -> bool {
slice.len() == matrix_slice_len(size, stride)
}
#[inline]
fn matrix_slice_len(size: Size, stride: usize) -> usize {
if size.height == 0 || size.width == 0 {
0
} else {
stride * (size.height - 1) + size.width
}
}
pub struct Rows<'a, T> {
width: usize,
chunks: slice::Chunks<'a, T>,
}
impl<'a, T> Rows<'a, T> {
#[inline]
fn new(matrix: MatrixRef<'a, T>) -> Self {
let chunks = if matrix.width() == 0 || matrix.height() == 0 {
[].chunks(1)
} else {
matrix.as_slice().chunks(matrix.stride())
};
Rows {
width: matrix.width(),
chunks,
}
}
}
impl<'a, T> Iterator for Rows<'a, T> {
type Item = &'a [T];
#[inline]
fn next(&mut self) -> Option<&'a [T]> {
let slice = self.chunks.next()?;
slice.get(..self.width)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.chunks.size_hint()
}
}
impl<'a, T> DoubleEndedIterator for Rows<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a [T]> {
let slice = self.chunks.next_back()?;
slice.get(..self.width)
}
}
impl<'a, T> ExactSizeIterator for Rows<'a, T> {}
impl<'a, T> std::iter::FusedIterator for Rows<'a, T> {}
pub struct RowsMut<'a, T> {
width: usize,
chunks: slice::ChunksMut<'a, T>,
}
impl<'a, T> RowsMut<'a, T> {
#[inline]
fn new(matrix: MatrixRefMut<'a, T>) -> Self {
let width = matrix.width();
let chunks = if width == 0 || matrix.height() == 0 {
[].chunks_mut(1)
} else {
let stride = matrix.stride();
matrix.into_slice().chunks_mut(stride)
};
RowsMut { width, chunks }
}
}
impl<'a, T> Iterator for RowsMut<'a, T> {
type Item = &'a mut [T];
#[inline]
fn next(&mut self) -> Option<&'a mut [T]> {
let slice = self.chunks.next()?;
slice.get_mut(..self.width)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.chunks.size_hint()
}
}
impl<'a, T> DoubleEndedIterator for RowsMut<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<&'a mut [T]> {
let slice = self.chunks.next_back()?;
slice.get_mut(..self.width)
}
}
impl<'a, T> ExactSizeIterator for RowsMut<'a, T> {}
impl<'a, T> std::iter::FusedIterator for RowsMut<'a, T> {}
pub struct Splits<'a, T> {
chunks: slice::Chunks<'a, T>,
slice_size: usize,
size: Size,
stride: usize,
}
impl<'a, T> Splits<'a, T> {
#[inline]
fn new(matrix: MatrixRef<'a, T>, height: usize) -> Self {
debug_assert!(matrix.is_aligned(), "matrix slice should be well aligned");
let size = (matrix.width(), height).into();
let stride = matrix.stride();
let chunks = if stride == 0 || height == 0 {
[].chunks(1)
} else {
matrix.as_slice().chunks(stride * height)
};
Splits {
chunks,
slice_size: matrix_slice_len(size, stride),
size,
stride,
}
}
}
impl<'a, T> Iterator for Splits<'a, T> {
type Item = MatrixRef<'a, T>;
#[inline]
fn next(&mut self) -> Option<MatrixRef<'a, T>> {
let mut chunk = self.chunks.next()?;
let mut size = self.size;
if self.slice_size <= chunk.len() {
chunk = &chunk[..self.slice_size];
} else {
size.height = (chunk.len() + (self.stride - 1)) / self.stride;
};
debug_assert!(is_aligned(chunk, size, self.stride));
Some(MatrixRef {
items: chunk,
size,
stride: self.stride,
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.chunks.size_hint()
}
}
impl<'a, T> ExactSizeIterator for Splits<'a, T> {}
pub struct SplitsMut<'a, T> {
chunks: slice::ChunksMut<'a, T>,
slice_size: usize,
size: Size,
stride: usize,
}
impl<'a, T> SplitsMut<'a, T> {
#[inline]
fn new(matrix: MatrixRefMut<'a, T>, height: usize) -> Self {
debug_assert!(matrix.is_aligned(), "matrix slice should be well aligned");
let size = (matrix.width(), height).into();
let stride = matrix.stride();
let chunks = if stride == 0 || height == 0 {
[].chunks_mut(1)
} else {
matrix.into_slice().chunks_mut(stride * height)
};
SplitsMut {
chunks,
slice_size: matrix_slice_len(size, stride),
size,
stride,
}
}
}
impl<'a, T> Iterator for SplitsMut<'a, T> {
type Item = MatrixRefMut<'a, T>;
#[inline]
fn next(&mut self) -> Option<MatrixRefMut<'a, T>> {
let mut chunk = self.chunks.next()?;
let mut size = self.size;
if self.slice_size <= chunk.len() {
chunk = &mut chunk[..self.slice_size];
} else {
size.height = (chunk.len() + (self.stride - 1)) / self.stride;
};
debug_assert!(is_aligned(chunk, size, self.stride));
Some(MatrixRefMut {
items: chunk,
size,
stride: self.stride,
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.chunks.size_hint()
}
}
impl<'a, T> ExactSizeIterator for SplitsMut<'a, T> {}
struct Indices {
pos: (usize, usize),
size: Size,
}
impl Indices {
#[inline]
fn new(mut size: Size) -> Indices {
if size.width == 0 {
size.height = 0
}
Indices { pos: (0, 0), size }
}
}
impl Iterator for Indices {
type Item = (usize, usize);
#[inline]
fn next(&mut self) -> Option<(usize, usize)> {
if self.pos.1 < self.size.height {
let ret = Some(self.pos);
self.pos.0 += 1;
if self.pos.0 >= self.size.width {
self.pos.0 = 0;
self.pos.1 += 1;
}
ret
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let size = self.size.width * (self.size.height - self.pos.1) - self.pos.0;
(size, Some(size))
}
}
impl ExactSizeIterator for Indices {}
impl std::iter::FusedIterator for Indices {}
pub struct Windows<'a, T> {
matrix: MatrixRef<'a, T>,
indices: Indices,
size: Size,
}
impl<'a, T> Windows<'a, T> {
#[inline]
fn new(matrix: MatrixRef<'a, T>, size: Size) -> Self {
let indices = {
let size = if size.width == 0
|| matrix.width() < size.width
|| size.height == 0
|| matrix.height() < size.height
{
(0, 0).into()
} else {
Size {
width: matrix.width() - size.width + 1,
height: matrix.height() - size.height + 1,
}
};
Indices::new(size)
};
Windows {
matrix,
indices,
size,
}
}
}
impl<'a, T> Iterator for Windows<'a, T> {
type Item = MatrixRef<'a, T>;
#[inline]
fn next(&mut self) -> Option<MatrixRef<'a, T>> {
let pos = self.indices.next()?;
self.matrix.window(pos, self.size).ok()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.indices.size_hint()
}
}
impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
impl<'a, T> std::iter::FusedIterator for Windows<'a, T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn indices() {
{
let mut indices = Indices::new(Size {
width: 3,
height: 2,
});
assert_eq!(indices.size_hint(), (6, Some(6)));
assert_eq!(indices.next(), Some((0, 0)));
assert_eq!(indices.size_hint(), (5, Some(5)));
assert_eq!(indices.next(), Some((1, 0)));
assert_eq!(indices.size_hint(), (4, Some(4)));
assert_eq!(indices.next(), Some((2, 0)));
assert_eq!(indices.size_hint(), (3, Some(3)));
assert_eq!(indices.next(), Some((0, 1)));
assert_eq!(indices.size_hint(), (2, Some(2)));
assert_eq!(indices.next(), Some((1, 1)));
assert_eq!(indices.size_hint(), (1, Some(1)));
assert_eq!(indices.next(), Some((2, 1)));
assert_eq!(indices.size_hint(), (0, Some(0)));
assert_eq!(indices.next(), None);
let old_pos = indices.pos;
let old_size = indices.size;
assert_eq!(indices.size_hint(), (0, Some(0)));
assert_eq!(indices.next(), None);
assert_eq!(indices.pos, old_pos);
assert_eq!(indices.size, old_size);
}
{
let mut empty0 = Indices::new(Size {
width: 99,
height: 0,
});
assert_eq!(empty0.size_hint(), (0, Some(0)));
assert_eq!(empty0.next(), None);
assert_eq!(empty0.size_hint(), (0, Some(0)));
}
{
let mut empty1 = Indices::new(Size {
width: 0,
height: 99,
});
assert_eq!(empty1.size_hint(), (0, Some(0)));
assert_eq!(empty1.next(), None);
assert_eq!(empty1.size_hint(), (0, Some(0)));
}
}
#[test]
fn offset() {
let mat = MatrixVec::from([
[00, 01, 02], [03, 04, 05], ]);
assert_eq!(mat.offset((0, 0)), Ok(0));
assert_eq!(mat.offset((1, 0)), Ok(1));
assert_eq!(mat.offset((2, 0)), Ok(2));
assert_eq!(mat.offset((0, 1)), Ok(3));
assert_eq!(mat.offset((1, 1)), Ok(4));
assert_eq!(mat.offset((2, 1)), Ok(5));
assert_eq!(mat.offset((3, 0)), Err(Error::OutOfBounds));
assert_eq!(mat.offset((0, 2)), Err(Error::OutOfBounds));
let mat = MatrixVec::from([
[00, 00, 00, 00, 00], [00, 00, 01, 02, 03], [04, 05, 06, 07, 00], [00, 00, 00, 00, 00], ]);
let win = mat.window((1, 1), (3, 2).into()).unwrap();
assert_eq!(win.offset((0, 0)), Ok(0));
assert_eq!(win.offset((1, 0)), Ok(1));
assert_eq!(win.offset((2, 0)), Ok(2));
assert_eq!(win.offset((0, 1)), Ok(5));
assert_eq!(win.offset((1, 1)), Ok(6));
assert_eq!(win.offset((2, 1)), Ok(7));
assert_eq!(win.offset((3, 0)), Err(Error::OutOfBounds));
assert_eq!(win.offset((0, 2)), Err(Error::OutOfBounds));
}
#[test]
fn window_range() {
let mat = MatrixVec::from([
[00, 01, 02, 03, 04, 05, 06], [07, 08, 09, 10, 11, 12, 13], [14, 15, 16, 17, 18, 19, 20], [21, 22, 23, 24, 25, 26, 27], ]);
assert_eq!(mat.window_range((0, 0), (7, 4).into()), Ok(0..28));
assert_eq!(mat.window_range((1, 0), (6, 4).into()), Ok(1..28));
assert_eq!(mat.window_range((0, 1), (7, 3).into()), Ok(7..28));
assert_eq!(mat.window_range((1, 1), (6, 3).into()), Ok(8..28));
assert_eq!(mat.window_range((0, 0), (6, 4).into()), Ok(0..27));
assert_eq!(mat.window_range((0, 0), (7, 3).into()), Ok(0..21));
assert_eq!(mat.window_range((0, 0), (6, 3).into()), Ok(0..20));
assert_eq!(mat.window_range((1, 1), (5, 3).into()), Ok(8..27));
assert_eq!(mat.window_range((1, 0), (5, 3).into()), Ok(1..20));
assert_eq!(mat.window_range((1, 1), (5, 2).into()), Ok(8..20));
assert_eq!(mat.window_range((0, 1), (7, 2).into()), Ok(7..21));
assert_eq!(mat.window_range((0, 0), (1, 1).into()), Ok(0..1));
assert_eq!(mat.window_range((0, 0), (6, 1).into()), Ok(0..6));
assert_eq!(mat.window_range((1, 0), (6, 1).into()), Ok(1..7));
assert_eq!(mat.window_range((4, 2), (1, 1).into()), Ok(18..19));
assert_eq!(mat.window_range((0, 0), (0, 0).into()), Ok(0..0));
assert_eq!(mat.window_range((7, 4), (0, 0).into()), Ok(0..0));
use Error::OutOfBounds;
assert_eq!(mat.window_range((7, 0), (1, 1).into()), Err(OutOfBounds));
assert_eq!(mat.window_range((0, 4), (1, 1).into()), Err(OutOfBounds));
use Error::InvalidSize;
assert_eq!(mat.window_range((0, 0), (8, 4).into()), Err(InvalidSize));
assert_eq!(mat.window_range((0, 0), (7, 5).into()), Err(InvalidSize));
let mat = MatrixRef::<i32>::new(&[], (0, 0).into()).unwrap();
assert_eq!(mat.window_range((0, 0), (0, 0).into()), Ok(0..0));
let mat_vec = MatrixVec::from([
[00, 00, 00, 00, 00, 00, 00, 00, 00], [00, 00, 01, 02, 03, 04, 05, 06, 07], [08, 09, 10, 11, 12, 13, 14, 15, 16], [17, 18, 19, 20, 21, 22, 23, 24, 25], [26, 27, 28, 29, 30, 31, 32, 33, 00], [00, 00, 00, 00, 00, 00, 00, 00, 00], ]);
let mat = mat_vec.window((1, 1), (7, 4).into()).unwrap();
assert_eq!(mat.window_range((0, 0), (7, 4).into()), Ok(0..34));
assert_eq!(mat.window_range((1, 0), (6, 4).into()), Ok(1..34));
assert_eq!(mat.window_range((0, 1), (7, 3).into()), Ok(9..34));
assert_eq!(mat.window_range((1, 1), (6, 3).into()), Ok(10..34));
assert_eq!(mat.window_range((0, 0), (6, 4).into()), Ok(0..33));
assert_eq!(mat.window_range((0, 0), (7, 3).into()), Ok(0..25));
assert_eq!(mat.window_range((0, 0), (6, 3).into()), Ok(0..24));
assert_eq!(mat.window_range((1, 1), (5, 3).into()), Ok(10..33));
assert_eq!(mat.window_range((1, 0), (5, 3).into()), Ok(1..24));
assert_eq!(mat.window_range((1, 1), (5, 2).into()), Ok(10..24));
assert_eq!(mat.window_range((0, 1), (7, 2).into()), Ok(9..25));
assert_eq!(mat.window_range((0, 0), (1, 1).into()), Ok(0..1));
assert_eq!(mat.window_range((0, 0), (6, 1).into()), Ok(0..6));
assert_eq!(mat.window_range((1, 0), (6, 1).into()), Ok(1..7));
assert_eq!(mat.window_range((4, 2), (1, 1).into()), Ok(22..23));
assert_eq!(mat.window_range((0, 0), (0, 0).into()), Ok(0..0));
assert_eq!(mat.window_range((7, 4), (0, 0).into()), Ok(0..0));
assert_eq!(mat.window_range((7, 0), (1, 1).into()), Err(OutOfBounds));
assert_eq!(mat.window_range((0, 4), (1, 1).into()), Err(OutOfBounds));
assert_eq!(mat.window_range((0, 0), (8, 4).into()), Err(InvalidSize));
assert_eq!(mat.window_range((0, 0), (7, 5).into()), Err(InvalidSize));
}
}