More messing around

This commit is contained in:
Andrew Cassidy 2022-07-28 18:49:48 -07:00
parent 96482fb0d1
commit 6491b7c692
7 changed files with 345 additions and 129 deletions

View File

@ -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))
}
}

View File

@ -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
View 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
View 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
View 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> {}

View File

@ -1,2 +1,2 @@
mod Container2D;
mod Index2D;
mod containers;
mod matrix;

90
src/matrix.rs Normal file
View 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)
}