#![deny(missing_docs)]
#![deny(warnings)]
#![feature(proc_macro)]
#![feature(unsize)]
#![no_std]
extern crate mat_macros;
#[doc(hidden)]
pub extern crate typenum;
use core::ops;
use core::marker::{PhantomData, Unsize};
use core::fmt;
pub use mat_macros::mat;
use typenum::Unsigned;
pub mod traits;
use traits::{Matrix, UnsafeGet, Zero};
#[derive(Clone)]
pub struct Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NCOLS: Unsigned,
NROWS: Unsigned,
T: Copy,
{
buffer: BUFFER,
ty: PhantomData<[T; 0]>,
nrows: PhantomData<NROWS>,
ncols: PhantomData<NCOLS>,
}
#[derive(Clone, Copy)]
pub struct Product<L, R> {
l: L,
r: R,
}
#[derive(Clone, Copy)]
pub struct Sum<L, R> {
l: L,
r: R,
}
#[derive(Clone, Copy)]
pub struct Transpose<M> {
m: M,
}
impl<T, BUFFER, NROWS, NCOLS> Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NROWS: Unsigned,
NCOLS: Unsigned,
T: Copy,
{
#[doc(hidden)]
pub unsafe fn new(buffer: BUFFER) -> Self {
Mat {
buffer,
ty: PhantomData,
nrows: PhantomData,
ncols: PhantomData,
}
}
}
impl<T, BUFFER, NROWS, NCOLS> fmt::Debug for Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NROWS: Unsigned,
NCOLS: Unsigned,
T: Copy + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut is_first = true;
let slice: &[T] = &self.buffer;
f.write_str("[")?;
for row in slice.chunks(NCOLS::to_usize()) {
if is_first {
is_first = false;
} else {
f.write_str(", ")?;
}
write!(f, "{:?}", row)?;
}
f.write_str("]")
}
}
impl<'a, T, BUFFER, NROWS, NCOLS> Matrix for &'a Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NROWS: Unsigned,
NCOLS: Unsigned,
T: Copy,
{
type NROWS = NROWS;
type NCOLS = NCOLS;
}
impl<'a, T, BUFFER, NROWS, NCOLS> UnsafeGet for &'a Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NROWS: Unsigned,
NCOLS: Unsigned,
T: Copy,
{
type Elem = T;
unsafe fn unsafe_get(self, r: usize, c: usize) -> T {
let slice: &[T] = &self.buffer;
*slice.get_unchecked(r * NCOLS::to_usize() + c)
}
}
impl<'a, T, BUFFER, NROWS, NCOLS, R> ops::Mul<R> for &'a Mat<T, BUFFER, NROWS, NCOLS>
where
BUFFER: Unsize<[T]>,
NROWS: Unsigned,
NCOLS: Unsigned,
T: Copy,
R: Matrix<NROWS = NCOLS>,
{
type Output = Product<&'a Mat<T, BUFFER, NROWS, NCOLS>, R>;
fn mul(self, rhs: R) -> Self::Output {
Product { l: self, r: rhs }
}
}
impl<M> traits::Transpose for M
where
M: Matrix,
{
}
impl<M> Matrix for Transpose<M>
where
M: Matrix,
{
type NROWS = M::NCOLS;
type NCOLS = M::NROWS;
}
impl<M> UnsafeGet for Transpose<M>
where
M: Matrix,
{
type Elem = M::Elem;
unsafe fn unsafe_get(self, r: usize, c: usize) -> M::Elem {
self.m.unsafe_get(c, r)
}
}
impl<L, R> ops::Mul<R> for Transpose<L>
where
L: Matrix,
R: Matrix<NROWS = L::NROWS>,
{
type Output = Product<Transpose<L>, R>;
fn mul(self, rhs: R) -> Self::Output {
Product { l: self, r: rhs }
}
}
impl<L, R, T> Matrix for Product<L, R>
where
L: Matrix<Elem = T>,
R: Matrix<Elem = T>,
T: ops::Add<T, Output = T> + ops::Mul<T, Output = T> + Copy + Zero,
{
type NROWS = L::NROWS;
type NCOLS = R::NCOLS;
}
impl<T, L, R> UnsafeGet for Product<L, R>
where
L: Matrix<Elem = T>,
R: Matrix<Elem = T>,
T: ops::Add<T, Output = T> + ops::Mul<T, Output = T> + Copy + Zero,
{
type Elem = T;
unsafe fn unsafe_get(self, r: usize, c: usize) -> T {
let mut sum = T::zero();
for i in 0..self.l.ncols() {
sum = sum + self.l.unsafe_get(r, i) * self.r.unsafe_get(i, c);
}
sum
}
}
impl<L, R, RHS> ops::Add<RHS> for Product<L, R>
where
L: Matrix,
R: Matrix,
RHS: Matrix<NROWS = L::NROWS, NCOLS = R::NCOLS>,
{
type Output = Sum<Product<L, R>, RHS>;
fn add(self, rhs: RHS) -> Self::Output {
Sum { l: self, r: rhs }
}
}
impl<T, L, R> Matrix for Sum<L, R>
where
L: Matrix<Elem = T>,
R: Matrix<Elem = T>,
T: ops::Add<T, Output = T> + Copy,
{
type NROWS = L::NROWS;
type NCOLS = L::NCOLS;
}
impl<T, L, R> UnsafeGet for Sum<L, R>
where
L: Matrix<Elem = T>,
R: Matrix<Elem = T>,
T: ops::Add<T, Output = T> + Copy,
{
type Elem = T;
unsafe fn unsafe_get(self, r: usize, c: usize) -> T {
self.l.unsafe_get(r, c) + self.r.unsafe_get(r, c)
}
}