mirror of
https://github.com/drewcassidy/vector-victor.git
synced 2024-09-01 14:58:35 +00:00
Consolidate Matrix class
This commit is contained in:
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> {}
|
26
src/index.rs
Normal file
26
src/index.rs
Normal file
@ -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;
|
||||
|
1
src/macros/mod.rs
Normal file
1
src/macros/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod ops;
|
226
src/macros/ops.rs
Normal file
226
src/macros/ops.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
235
src/matrix.rs
235
src/matrix.rs
@ -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;
|
||||
|
||||
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>;
|
||||
}
|
||||
|
||||
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 GenericMatrix<D: Get2DSized<M, N>, const M: usize, const N: usize> {
|
||||
data: D,
|
||||
struct Matrix<T, const M: usize, const N: usize>
|
||||
where
|
||||
T: Scalar,
|
||||
{
|
||||
data: [[T; N]; M],
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
);
|
||||
|
||||
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: Get2DSized<M, N> + Copy, const M: usize, const N: usize> Default for GenericMatrix<D, M, N>
|
||||
// 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]),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// default constructor
|
||||
impl<T, const M: usize, const N: usize> Default for Matrix<T, M, N>
|
||||
where
|
||||
D: Default,
|
||||
[[T; N]; M]: Default,
|
||||
T: Scalar,
|
||||
{
|
||||
fn default() -> Self {
|
||||
GenericMatrix { data: D::default() }
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
|
||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Scalar> {
|
||||
self.data.get(i)
|
||||
Matrix {
|
||||
data: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
// 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>, I: Index2D, const M: usize, const N: usize> Index<I>
|
||||
for GenericMatrix<D, M, N>
|
||||
{
|
||||
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
|
||||
))
|
||||
// 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]
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
))
|
||||
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<D: Get2DSized<M, N>, const M: usize, const N: usize> Get2DSized<M, N>
|
||||
for GenericMatrix<D, M, N>
|
||||
{
|
||||
}
|
||||
|
||||
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_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…
Reference in New Issue
Block a user