mirror of
https://github.com/drewcassidy/vector-victor.git
synced 2024-09-01 14:58:35 +00:00
More messing around
This commit is contained in:
parent
96482fb0d1
commit
6491b7c692
@ -1,99 +0,0 @@
|
|||||||
use crate::Index2D::Index2D;
|
|
||||||
|
|
||||||
pub trait Container2D {
|
|
||||||
type Output;
|
|
||||||
const HEIGHT: u32;
|
|
||||||
const WIDTH: u32;
|
|
||||||
|
|
||||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Output>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Container2DMut: Container2D {
|
|
||||||
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Output>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A 2D owning array of T
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Array2D<T, const M: u32, const N: u32> {
|
|
||||||
pub data: [[T; N as usize]; M as usize],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, const M: u32, const N: u32> Container2D for Array2D<T, M, N> {
|
|
||||||
type Output = T;
|
|
||||||
const HEIGHT: u32 = M;
|
|
||||||
const WIDTH: u32 = N;
|
|
||||||
|
|
||||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Output> {
|
|
||||||
let (r, c) = i.to_2d(Self::WIDTH);
|
|
||||||
self.data.get(r)?.get(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, const M: u32, const N: u32> Container2DMut for Array2D<T, M, N> {
|
|
||||||
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Output> {
|
|
||||||
let (r, c) = i.to_2d(Self::WIDTH);
|
|
||||||
self.data.get_mut(r)?.get_mut(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A 2D immutable view into a Container2D
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct View2D<'a, D: Container2D, const M: u32, const N: u32> {
|
|
||||||
r: u32,
|
|
||||||
c: u32,
|
|
||||||
data: &'a D,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, D: Container2D, const M: u32, const N: u32> Container2D for View2D<'a, D, M, N> {
|
|
||||||
type Output = D::Output;
|
|
||||||
const HEIGHT: u32 = M;
|
|
||||||
const WIDTH: u32 = N;
|
|
||||||
|
|
||||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Output> {
|
|
||||||
self.data
|
|
||||||
.get(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, D: Container2DMut, const M: u32, const N: u32> Container2D for Slice2D<'a, D, M, N> {
|
|
||||||
type Output = D::Output;
|
|
||||||
const HEIGHT: u32 = M;
|
|
||||||
const WIDTH: u32 = N;
|
|
||||||
|
|
||||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Output> {
|
|
||||||
self.data
|
|
||||||
.get(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A 2D mutable view into a Container2D
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Slice2D<'a, D: Container2DMut, const M: u32, const N: u32> {
|
|
||||||
r: u32,
|
|
||||||
c: u32,
|
|
||||||
data: &'a mut D,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, D: Container2DMut, const M: u32, const N: u32> Container2DMut for Slice2D<'a, D, M, N> {
|
|
||||||
fn get_mut<I: Index2D>(&mut self, i: I) -> Option<&mut Self::Output> {
|
|
||||||
self.data
|
|
||||||
.get_mut(i.to_2d_offset(Self::WIDTH, Self::HEIGHT, self.r, self.c)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// An immutable transposition of a Container2D
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Transpose<'a, D: Container2D> {
|
|
||||||
pub data: &'a D,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, D: Container2D> Container2D for Transpose<'a, D> {
|
|
||||||
type Output = D::Output;
|
|
||||||
const HEIGHT: u32 = D::WIDTH;
|
|
||||||
const WIDTH: u32 = D::HEIGHT;
|
|
||||||
|
|
||||||
fn get<I: Index2D>(&self, i: I) -> Option<&Self::Output> {
|
|
||||||
let (r, c) = i.to_2d(Self::WIDTH);
|
|
||||||
self.data.get((c, r))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
pub trait Index2D {
|
|
||||||
fn to_1d(&self, width: u32) -> u32 {
|
|
||||||
let (r, c) = self.to_2d(width);
|
|
||||||
r * width + c
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_2d(&self, width: u32) -> (u32, u32);
|
|
||||||
|
|
||||||
fn to_2d_offset(&self, width: u32, height: u32, r: u32, c: u32) -> Option<(u32, u32)> {
|
|
||||||
let (row, col) = self.to_2d(width);
|
|
||||||
if row >= height || col >= width {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some((row + r, col + c))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Index2D for u32 {
|
|
||||||
fn to_2d(&self, width: u32) -> (u32, u32) {
|
|
||||||
(*self / width, *self % width)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Index2D for (u32, u32) {
|
|
||||||
fn to_2d(&self, _: u32) -> (u32, u32) {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
}
|
|
180
src/containers.rs
Normal file
180
src/containers.rs
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
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>,
|
||||||
|
{
|
||||||
|
}
|
34
src/containers/index.rs
Normal file
34
src/containers/index.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
39
src/containers/iter.rs
Normal file
39
src/containers/iter.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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> {}
|
@ -1,2 +1,2 @@
|
|||||||
mod Container2D;
|
mod containers;
|
||||||
mod Index2D;
|
mod matrix;
|
||||||
|
90
src/matrix.rs
Normal file
90
src/matrix.rs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
use crate::containers::index::Index2D;
|
||||||
|
use crate::containers::iter::ElementIter;
|
||||||
|
use crate::containers::{Array2D, Get2D, Get2DMut, Get2DSized, Slice2D};
|
||||||
|
use std::ops::{Add, Index, IndexMut};
|
||||||
|
|
||||||
|
type Matrix<T: Copy, const M: usize, const N: usize> = GenericMatrix<Array2D<T, M, N>, M, N>;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
struct GenericMatrix<D: Get2DSized<M, N>, const M: usize, const N: usize> {
|
||||||
|
data: D,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Get2DSized<M, N> + Copy, const M: usize, const N: usize> Default for GenericMatrix<D, M, N>
|
||||||
|
where
|
||||||
|
D: Default,
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user