Consolidate Matrix class

master
Andrew Cassidy 2 years ago
parent 6491b7c692
commit 2bb625bdaf

@ -1,180 +0,0 @@
use index::Index2D;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
pub mod index;
pub mod iter;
/// This trait exists to allow structs like Slice2D to require Get2D, without
/// storing the dimensions of the target as part of its own generic parameters
pub trait Get2D {
type Scalar: Sized + Copy;
const HEIGHT: usize;
const WIDTH: usize;
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar>;
}
pub trait Get2DMut: Get2D {
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar>;
}
pub trait Get2DSized<const M: usize, const N: usize>: Get2D {}
/// A 2D owning array of T
#[derive(Debug, Clone, Copy)]
pub struct Array2D<T, const M: usize, const N: usize>
where
T: Copy + 'static,
{
pub data: [[T; N]; M],
}
impl<T, const M: usize, const N: usize> Default for Array2D<T, M, N>
where
T: Default + Copy,
{
fn default() -> Self {
Array2D {
data: [[T::default(); N]; M],
}
}
}
impl<T: Copy, const M: usize, const N: usize> Get2D for Array2D<T, M, N> {
type Scalar = T;
const HEIGHT: usize = M;
const WIDTH: usize = N;
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar> {
let (r, c) = i.to_2d(Self::WIDTH);
self.data.get(r)?.get(c)
}
}
impl<T: Copy, const M: usize, const N: usize> Get2DMut for Array2D<T, M, N> {
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar> {
let (r, c) = i.to_2d(Self::WIDTH);
self.data.get_mut(r)?.get_mut(c)
}
}
impl<T: Copy, const M: usize, const N: usize> Get2DSized<M, N> for Array2D<T, M, N> {}
/// A 2D mutable view into a container
#[derive(Debug, Clone, Copy)]
pub struct Slice2D<'a, R, const M: usize, const N: usize>
where
R: Deref,
R::Target: Get2D + 'a,
{
target: R,
r: usize,
c: usize,
phantom: PhantomData<&'a ()>,
}
impl<'a, R, const M: usize, const N: usize> Slice2D<'a, R, M, N>
where
R: Deref,
R::Target: Get2D + 'a,
{
pub fn new(target: R, r: usize, c: usize) -> Self {
Self {
target,
r,
c,
phantom: PhantomData,
}
}
}
impl<'a, R, D, const M: usize, const N: usize> Get2D for Slice2D<'a, R, M, N>
where
R: Deref<Target = D>,
D: Get2D,
{
type Scalar = <<R as Deref>::Target as Get2D>::Scalar;
const HEIGHT: usize = M;
const WIDTH: usize = N;
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar> {
self.target
.get(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?)
}
}
impl<'a, R, D, const M: usize, const N: usize> Get2DMut for Slice2D<'a, R, M, N>
where
R: Deref<Target = D> + DerefMut,
D: Get2DMut,
{
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar> {
self.target
.get_mut(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?)
}
}
impl<'a, R, D, const M: usize, const N: usize> Get2DSized<M, N> for Slice2D<'a, R, M, N>
where
R: Deref<Target = D>,
D: Get2D,
{
}
// A transposition of a 2D container
#[derive(Debug, Clone, Copy)]
pub struct Transpose<'a, R>
where
R: Deref,
R::Target: Get2D + 'a,
{
target: R,
phantom: std::marker::PhantomData<&'a ()>,
}
impl<'a, R> Transpose<'a, R>
where
R: Deref,
R::Target: Get2D + 'a,
{
fn new(target: R) -> Self {
Self {
target,
phantom: PhantomData,
}
}
}
impl<'a, R, D> Get2D for Transpose<'a, R>
where
R: Deref<Target = D>,
D: Get2D,
{
type Scalar = D::Scalar;
const HEIGHT: usize = D::WIDTH;
const WIDTH: usize = D::HEIGHT;
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar> {
let (r, c) = i.to_2d(Self::WIDTH);
self.target.get((c, r))
}
}
impl<'a, R, D> Get2DMut for Transpose<'a, R>
where
R: DerefMut<Target = D>,
D: Get2DMut,
{
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar> {
let (r, c) = i.to_2d(Self::WIDTH);
self.target.get_mut((c, r))
}
}
impl<'a, R, D, const M: usize, const N: usize> Get2DSized<M, N> for Transpose<'a, R>
where
R: Deref<Target = D>,
D: Get2DSized<N, M>,
{
}

@ -1,34 +0,0 @@
pub trait Index2D: Copy {
fn to_1d(&self, width: usize) -> usize {
let (r, c) = self.to_2d(width);
r * width + c
}
fn to_2d(&self, width: usize) -> (usize, usize);
fn to_2d_offset(
&self,
width: usize,
height: usize,
r: usize,
c: usize,
) -> Option<(usize, usize)> {
let (row, col) = self.to_2d(width);
if row >= height || col >= width {
return None;
};
Some((row + r, col + c))
}
}
impl Index2D for usize {
fn to_2d(&self, width: usize) -> (usize, usize) {
(*self / width, *self % width)
}
}
impl Index2D for (usize, usize) {
fn to_2d(&self, _: usize) -> (usize, usize) {
*self
}
}

@ -1,39 +0,0 @@
use super::Get2D;
use std::iter::FusedIterator;
#[derive(Debug, Copy, Clone)]
pub(crate) struct ElementIter<'a, D>
where
D: Get2D,
{
data: &'a D,
index: usize,
}
impl<'a, D: Get2D> ElementIter<'a, D> {
pub(crate) fn new(data: &'a D) -> ElementIter<D> {
ElementIter { data, index: 0 }
}
}
impl<'a, D: Get2D> Iterator for ElementIter<'a, D> {
type Item = &'a D::Scalar;
fn next(&mut self) -> Option<Self::Item> {
let result = self.data.get(self.index);
self.index += 1;
result
}
fn size_hint(&self) -> (usize, Option<usize>) {
let total = D::WIDTH * D::HEIGHT;
(total - self.index, Some(total - self.index))
}
}
impl<'a, D: Get2D> ExactSizeIterator for ElementIter<'a, D> {
fn len(&self) -> usize {
self.index - D::WIDTH * D::HEIGHT
}
}
impl<'a, D: Get2D> FusedIterator for ElementIter<'a, D> {}

@ -0,0 +1,26 @@
pub trait Index2D: Copy {
fn to_1d(self, height: usize, width: usize) -> Option<usize> {
let (r, c) = self.to_2d(height, width)?;
Some(r * width + c)
}
fn to_2d(self, height: usize, width: usize) -> Option<(usize, usize)>;
}
impl Index2D for usize {
fn to_2d(self, height: usize, width: usize) -> Option<(usize, usize)> {
match self < (height * width) {
true => Some((self / width, self % width)),
false => None,
}
}
}
impl Index2D for (usize, usize) {
fn to_2d(self, height: usize, width: usize) -> Option<(usize, usize)> {
match self.0 < height && self.1 < width {
true => Some(self),
false => None,
}
}
}

@ -1,2 +1,3 @@
mod containers;
pub mod index;
mod matrix;
mod macros;

@ -0,0 +1 @@
pub mod ops;

@ -0,0 +1,226 @@
// borrowed from the auto_ops crate
#[doc(hidden)]
#[macro_export]
macro_rules! impl_matrix_op {
(neg, $f:expr) => {
$crate::_impl_op_m_internal_ex!(Neg, neg, $f);
};
(!, $f:expr) => {
$crate::_impl_op_m_internal_ex!(Not, not, $f);
};
(+, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(Add, add, $f);
$crate::_impl_opassign_mm_internal_ex!(Add, AddAssign, add_assign, $f);
};
(-, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(Sub, sub, $f);
$crate::_impl_opassign_mm_internal_ex!(Sub, SubAssign, sub_assign, $f);
};
(*, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(Mul, mul, $f);
$crate::_impl_op_ms_internal_ex!(Mul, mul, $f);
$crate::_impl_opassign_mm_internal_ex!(Mul, MulAssign, mul_assign, $f);
$crate::_impl_opassign_ms_internal_ex!(Mul, MulAssign, mul_assign, $f);
};
(/, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(Div, div, $f);
$crate::_impl_op_ms_internal_ex!(Div, div, $f);
$crate::_impl_opassign_mm_internal_ex!(Div, DivAssign, div_assign, $f);
$crate::_impl_opassign_ms_internal_ex!(Div, DivAssign, div_assign, $f);
};
(%, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(Rem, rem, $f);
$crate::_impl_op_ms_internal_ex!(Rem, rem, $f);
$crate::_impl_opassign_mm_internal_ex!(Rem, RemAssign, rem_assign, $f);
$crate::_impl_opassign_ms_internal_ex!(Rem, RemAssign, rem_assign, $f);
};
(&, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(BitAnd, bitand, $f);
$crate::_impl_opassign_mm_internal_ex!(BitAnd, BitAndAssign, bitand_assign, $f);
};
(|, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(BitOr, bitor, $f);
$crate::_impl_opassign_mm_internal_ex!(BitOr, BitOrAssign, bitor_assign, $f);
};
(^, $f:expr) => {
$crate::_impl_op_mm_internal_ex!(BitXor, bitxor, $f);
$crate::_impl_opassign_mm_internal_ex!(BitXor, BitXorAssign, bitxor_assign, $f);
};
(<<, $f:expr) => {
$crate::_impl_op_ms_internal_ex!(Shl, shl, $f);
$crate::_impl_opassign_mm_internal_ex!(Shl, ShlAssign, shl_assign, $f);
};
(>>, $f:expr) => {
$crate::_impl_op_ms_internal_ex!(Shr, shr, $f);
$crate::_impl_opassign_mm_internal_ex!(Shr, ShrAssign, shr_assign, $f);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! impl_op_ms {
(*, $f:expr) => {
_impl_op_ms_internal!(Mul, mul, $f);
};
(/, $f:expr) => {
_impl_op_ms_internal!(Div, div, $f);
};
(%, $f:expr) => {
_impl_op_ms_internal!(Rem, rem, $f);
};
(<<, $f:expr) => {
_impl_op_ms_internal!(Shl, shl, $f);
};
(>>, $f:expr) => {
_impl_op_ms_internal!(Shr, shr, $d);
};
}
#[macro_export]
macro_rules! _impl_op_m_internal_ex {
($ops_trait:ident, $ops_fn:ident, $f:expr) => {
$crate::_impl_op_m_internal!($ops_trait, $ops_fn, Matrix<L,M,N>, Matrix<L,M,N>, $f);
$crate::_impl_op_m_internal!($ops_trait, $ops_fn, &Matrix<L,M,N>, Matrix<L,M,N>, $f);
}
}
#[macro_export]
macro_rules! _impl_op_mm_internal_ex {
($ops_trait:ident, $ops_fn:ident, $f:expr) => {
$crate::_impl_op_mm_internal!($ops_trait, $ops_fn, Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>, $f);
$crate::_impl_op_mm_internal!($ops_trait, $ops_fn, &Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>, $f);
$crate::_impl_op_mm_internal!($ops_trait, $ops_fn, Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>, $f);
$crate::_impl_op_mm_internal!($ops_trait, $ops_fn, &Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>, $f);
}
}
#[macro_export]
macro_rules! _impl_opassign_mm_internal_ex {
($ops_super:ident, $ops_trait:ident, $ops_fn:ident, $f:expr) => {
$crate::_impl_opassign_mm_internal!($ops_super, $ops_trait, $ops_fn, Matrix<L,M,N>, Matrix<R,M,N>, Matrix<L,M,N>, $f);
$crate::_impl_opassign_mm_internal!($ops_super, $ops_trait, $ops_fn, Matrix<L,M,N>, &Matrix<R,M,N>, Matrix<L,M,N>, $f);
}
}
#[macro_export]
macro_rules! _impl_op_ms_internal_ex {
($ops_trait:ident, $ops_fn:ident, $f:expr) => {
$crate::_impl_op_ms_internal!($ops_trait, $ops_fn, Matrix<L,M,N>, R, Matrix<L,M,N>, $f);
$crate::_impl_op_ms_internal!($ops_trait, $ops_fn, &Matrix<L,M,N>, R, Matrix<L,M,N>, $f);
}
}
#[macro_export]
macro_rules! _impl_opassign_ms_internal_ex {
($ops_super:ident, $ops_trait:ident, $ops_fn:ident, $f:expr) => {
$crate::_impl_opassign_ms_internal!($ops_super, $ops_trait, $ops_fn, Matrix<L,M,N>, R, Matrix<L,M,N>, $f);
}
}
#[macro_export]
macro_rules! _impl_op_mm_internal {
($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $f:expr) => {
impl<L, R, const M: usize, const N: usize> ::std::ops::$ops_trait<$rhs> for $lhs
where
L: ::std::ops::$ops_trait<R, Output = L>,
L: Scalar,
R: Scalar,
{
type Output = $out;
fn $ops_fn(self, rhs_i: $rhs) -> Self::Output {
let mut result = self.clone();
let op = $f;
for (l, r) in zip(result.elements_mut(), rhs_i.elements()) {
*l = op(*l, *r);
}
result
}
}
};
}
#[macro_export]
macro_rules! _impl_opassign_mm_internal {
($ops_super:ident, $ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $f:expr) => {
impl<L, R, const M: usize, const N: usize> ::std::ops::$ops_trait<$rhs> for $lhs
where
L: ::std::ops::$ops_trait<R>,
L: ::std::ops::$ops_super<R, Output = L>,
L: Scalar,
R: Scalar,
{
fn $ops_fn(&mut self, rhs_i: $rhs) {
let op = $f;
for (l, r) in zip(self.elements_mut(), rhs_i.elements()) {
*l = op(*l, *r);
}
}
}
};
}
#[macro_export]
macro_rules! _impl_op_m_internal {
($ops_trait:ident, $ops_fn:ident, $lhs:ty, $out:ty, $f:expr) => {
impl<L, const M: usize, const N: usize> ::std::ops::$ops_trait for $lhs
where
L: ::std::ops::$ops_trait<Output = L>,
L: Scalar,
{
type Output = $out;
fn $ops_fn(self) -> Self::Output {
let mut result = self.clone();
let op = $f;
for l in result.elements_mut() {
*l = op(*l);
}
result
}
}
};
}
#[macro_export]
macro_rules! _impl_op_ms_internal {
($ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $f:expr) => {
impl<L, R, const M: usize, const N: usize> ::std::ops::$ops_trait<$rhs> for $lhs
where
L: ::std::ops::$ops_trait<R, Output = L>,
L: Scalar,
R: Scalar,
{
type Output = $out;
fn $ops_fn(self, r: $rhs) -> Self::Output {
let mut result = self.clone();
let op = $f;
for l in result.elements_mut() {
*l = op(*l, r);
}
result
}
}
};
}
#[macro_export]
macro_rules! _impl_opassign_ms_internal {
($ops_super:ident, $ops_trait:ident, $ops_fn:ident, $lhs:ty, $rhs:ty, $out:ty, $f:expr) => {
impl<L, R, const M: usize, const N: usize> ::std::ops::$ops_trait<$rhs> for $lhs
where
L: ::std::ops::$ops_trait<R>,
L: ::std::ops::$ops_super<R, Output = L>,
L: Scalar,
R: Scalar,
{
fn $ops_fn(&mut self, r: $rhs) {
let op = $f;
for l in self.elements_mut() {
*l = op(*l, r);
}
}
}
};
}

@ -1,90 +1,191 @@
use crate::containers::index::Index2D;
use crate::containers::iter::ElementIter;
use crate::containers::{Array2D, Get2D, Get2DMut, Get2DSized, Slice2D};
use std::ops::{Add, Index, IndexMut};
use crate::impl_matrix_op;
use crate::index::Index2D;
use std::iter::{zip, Enumerate, Flatten};
use std::ops::{Add, Deref, DerefMut, Index, IndexMut, Range};
use std::option::IntoIter;
type Matrix<T: Copy, const M: usize, const N: usize> = GenericMatrix<Array2D<T, M, N>, M, N>;
pub trait Get2D {
type Scalar: Sized + Copy;
const HEIGHT: usize;
const WIDTH: usize;
#[derive(Debug, Copy, Clone)]
struct GenericMatrix<D: Get2DSized<M, N>, const M: usize, const N: usize> {
data: D,
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar>;
}
impl<D: Get2DSized<M, N>, const M: usize, const N: usize> GenericMatrix<D, M, N> {
fn elements(&self) -> ElementIter<GenericMatrix<D, M, N>> {
ElementIter::new(self)
}
pub trait Get2DMut: Get2D {
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar>;
}
impl<D: Get2DSized<M, N> + Copy, const M: usize, const N: usize> Default for GenericMatrix<D, M, N>
trait Scalar: Copy + 'static {}
macro_rules! multi_impl { ($name:ident for $($t:ty),*) => ($( impl $name for $t {} )*) }
multi_impl!(Scalar for i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64);
impl<T> Scalar for &'static T where T: Scalar {}
#[derive(Debug, Copy, Clone)]
struct Matrix<T, const M: usize, const N: usize>
where
D: Default,
T: Scalar,
{
fn default() -> Self {
GenericMatrix { data: D::default() }
}
data: [[T; N]; M],
}
// impl<D: Get2D + Copy, const M: usize, const N: usize> Matrix<D, M, N>
// where
// D::Scalar: Default,
// {
// fn new(data: &[&[D::Scalar]]) -> Result<Self, &'static str> {}
// }
impl<D: Get2DSized<M, N>, const M: usize, const N: usize> Get2D for GenericMatrix<D, M, N> {
type Scalar = D::Scalar;
const HEIGHT: usize = D::HEIGHT;
const WIDTH: usize = D::WIDTH;
type Vector<T, const N: usize> = Matrix<T, N, 1>;
impl<T: Scalar, const M: usize, const N: usize> Matrix<T, M, N> {
fn new(data: [[T; N]; M]) -> Self {
return Matrix::<T, M, N> { data };
}
fn from_rows<I>(iter: &I) -> Self
where
Self: Default,
I: Iterator<Item = Vector<T, N>> + Copy,
{
let mut result = Self::default();
for (m, row) in iter.enumerate().filter(|(m, _)| *m <= M) {
result.set_row(m, &row)
}
result
}
fn from_cols<I>(iter: &I) -> Self
where
Self: Default,
I: Iterator<Item = Vector<T, M>> + Copy,
{
let mut result = Self::default();
for (n, col) in iter.enumerate().filter(|(n, _)| *n <= N) {
result.set_col(n, &col)
}
result
}
fn elements<'a>(&'a self) -> impl Iterator<Item = &T> + 'a {
self.data.iter().flatten()
}
fn elements_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut T> + 'a {
self.data.iter_mut().flatten()
}
fn get(&self, index: impl Index2D) -> Option<&T> {
let (m, n) = index.to_2d(M, N)?;
Some(&self.data[m][n])
}
fn get_mut(&mut self, index: impl Index2D) -> Option<&mut T> {
let (m, n) = index.to_2d(M, N)?;
Some(&mut self.data[m][n])
}
fn row(&self, m: usize) -> Option<Vector<T, N>> {
if m < M {
Some(Vector::<T, N>::new_vector(self.data[m]))
} else {
None
}
}
fn set_row(&mut self, m: usize, val: &Vector<T, N>) {
assert!(
m < M,
"Row index {} out of bounds for {}x{} matrix",
m,
M,
N
);
for (n, v) in val.elements().enumerate() {
self.data[m][n] = *v;
}
}
fn col(&self, n: usize) -> Option<Vector<T, M>> {
if n < N {
Some(Vector::<T, M>::new_vector(self.data.map(|r| r[n])))
} else {
None
}
}
fn set_col(&mut self, n: usize, val: &Vector<T, M>) {
assert!(
n < N,
"Column index {} out of bounds for {}x{} matrix",
n,
M,
N
);
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar> {
self.data.get(i)
for (m, v) in val.elements().enumerate() {
self.data[m][n] = *v;
}
}
fn rows<'a>(&'a self) -> impl Iterator<Item = Vector<T, N>> + 'a {
(0..M).map(|m| self.row(m).expect("invalid row reached while iterating"))
}
fn cols<'a>(&'a self) -> impl Iterator<Item = Vector<T, M>> + 'a {
(0..N).map(|n| self.col(n).expect("invalid column reached while iterating"))
}
}
impl<D: Get2DMut + Get2DSized<M, N>, const M: usize, const N: usize> Get2DMut
for GenericMatrix<D, M, N>
{
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Scalar> {
self.data.get_mut(i)
// constructor for column vectors
impl<T: Scalar, const N: usize> Vector<T, N> {
fn new_vector(data: [T; N]) -> Self {
return Vector::<T, N> {
data: data.map(|e| [e]),
};
}
}
impl<D: Get2DSized<M, N>, I: Index2D, const M: usize, const N: usize> Index<I>
for GenericMatrix<D, M, N>
// default constructor
impl<T, const M: usize, const N: usize> Default for Matrix<T, M, N>
where
[[T; N]; M]: Default,
T: Scalar,
{
type Output = D::Scalar;
fn index(&self, index: I) -> &Self::Output {
self.get(index).expect(&*format!(
"Index {:?} out of range for {} x {} matrix",
index.to_2d(D::WIDTH),
D::HEIGHT,
D::WIDTH
))
fn default() -> Self {
Matrix {
data: Default::default(),
}
}
}
impl<D: Get2DMut + Get2DSized<M, N>, I: Index2D, const M: usize, const N: usize> IndexMut<I>
for GenericMatrix<D, M, N>
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.get_mut(index).expect(&*format!(
"Index {:?} out of range for {} x {} matrix",
index.to_2d(D::WIDTH),
D::HEIGHT,
D::WIDTH
))
// deref 1x1 matrices to a scalar automatically
impl<T: Scalar> Deref for Matrix<T, 1, 1> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data[0][0]
}
}
impl<D: Get2DSized<M, N>, const M: usize, const N: usize> Get2DSized<M, N>
for GenericMatrix<D, M, N>
{
// deref 1x1 matrices to a mutable scalar automatically
impl<T: Scalar> DerefMut for Matrix<T, 1, 1> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data[0][0]
}
}
fn foo() {
let mut a: Matrix<i32, 5, 5> = Default::default();
let c = Slice2D::<&Matrix<i32, 5, 5>, 3, 3>::new(&a, 2, 2);
let b = Slice2D::<&mut Matrix<i32, 5, 5>, 3, 3>::new(&mut a, 1, 1);
println!("{:?} {:?}", b, c)
impl<T: Scalar, const M: usize, const N: usize> IntoIterator for Matrix<T, M, N> {
type Item = T;
type IntoIter = Flatten<std::array::IntoIter<[T; N], M>>;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter().flatten()
}
}
impl_matrix_op!(neg, |l: L| { -l });
impl_matrix_op!(!, |l: L| { !l });
impl_matrix_op!(+, |l,r| {l + r});
impl_matrix_op!(-, |l,r| {l - r});
impl_matrix_op!(*, |l,r| {l * r});
impl_matrix_op!(/, |l,r| {l / r});
impl_matrix_op!(%, |l,r| {l % r});
impl_matrix_op!(&, |l,r| {l & r});
impl_matrix_op!(|, |l,r| {l | r});
impl_matrix_op!(^, |l,r| {l ^ r});
impl_matrix_op!(<<, |l,r| {l << r});
impl_matrix_op!(>>, |l,r| {l >> r});

Loading…
Cancel
Save