#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
extern crate generic_array;
pub mod traits;
use core::marker::PhantomData;
use core::{fmt, ops};
pub use generic_array::typenum::consts;
use generic_array::typenum::consts::U1;
pub use generic_array::typenum::Quot as __Quot;
use generic_array::typenum::{Prod, Unsigned};
use generic_array::{ArrayLength, GenericArray};
use traits::{Matrix, UnsafeGet, Zero};
#[macro_export]
macro_rules! mat {
($ty:ty, [$([$($e:expr),*],)+]) => ({
extern crate core;
type NROWS = __nrows!($crate::consts::U0; [ $([ $($e),* ],)* ] );
type NELEMS = __nelems!($crate::consts::U0; [ $( $($e),* ,)* ]);
type NCOLS = $crate::__Quot<NELEMS, NROWS>;
unsafe {
core::mem::transmute::<_, $crate::Mat<$ty, NROWS, NCOLS>>(
[ $( $({ let e: $ty = $e; e }),* ),* ]
)
}
})
}
#[doc(hidden)]
#[macro_export]
macro_rules! __nrows {
($i:ty; []) => {
$i
};
($i:ty; [ [$($head:expr),*], $( [$($tail:expr),*] ,)*]) => {
__nrows!($crate::__Inc<$i>; [$( [$($tail),*] ,)*])
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __nelems {
($i:ty; []) => {
$i
};
($i:ty; [$head:expr, $($tail:expr,)*]) => {
__nelems!($crate::__Inc<$i>; [ $($tail,)* ])
};
}
#[doc(hidden)]
pub type __Inc<T> = generic_array::typenum::Sum<T, U1>;
pub struct Row<T, NCOLS>
where
NCOLS: ArrayLength<T>,
{
buffer: GenericArray<T, NCOLS>,
}
impl<T, NCOLS> ops::Index<usize> for Row<T, NCOLS>
where
NCOLS: ArrayLength<T>,
{
type Output = T;
fn index(&self, c: usize) -> &T {
assert!(c < NCOLS::to_usize());
unsafe { self.buffer.get_unchecked(c) }
}
}
impl<T, NCOLS> ops::IndexMut<usize> for Row<T, NCOLS>
where
NCOLS: ArrayLength<T>,
{
fn index_mut(&mut self, c: usize) -> &mut T {
assert!(c < NCOLS::to_usize());
unsafe { self.buffer.get_unchecked_mut(c) }
}
}
#[derive(Clone)]
pub struct Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS>,
Prod<NROWS, NCOLS>: ArrayLength<T>,
{
buffer: GenericArray<T, Prod<NROWS, NCOLS>>,
_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, NROWS, NCOLS> fmt::Debug for Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS>,
NCOLS: Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
.entries(self.buffer.chunks(NCOLS::to_usize()))
.finish()
}
}
impl<'a, T, NROWS, NCOLS> Matrix for &'a Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS> + Unsigned,
NCOLS: Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
T: Copy,
{
type NROWS = NROWS;
type NCOLS = NCOLS;
}
impl<'a, T, NROWS, NCOLS> UnsafeGet for &'a Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS> + Unsigned,
NCOLS: Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
T: Copy,
{
type Elem = T;
unsafe fn unsafe_get(self, r: usize, c: usize) -> T {
*self.buffer.get_unchecked(r * NCOLS::to_usize() + c)
}
}
impl<T, NROWS, NCOLS> ops::Index<usize> for Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS> + Unsigned,
NCOLS: ArrayLength<T> + Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
{
type Output = Row<T, NCOLS>;
fn index(&self, r: usize) -> &Row<T, NCOLS> {
assert!(r < NROWS::to_usize());
unsafe {
&*(self.buffer.get_unchecked(r * NCOLS::to_usize()) as *const _ as *const Row<_, _>)
}
}
}
impl<T, NROWS, NCOLS> ops::IndexMut<usize> for Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS> + Unsigned,
NCOLS: ArrayLength<T> + Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
{
fn index_mut(&mut self, r: usize) -> &mut Row<T, NCOLS> {
assert!(r < NROWS::to_usize());
unsafe {
&mut *(self.buffer.get_unchecked_mut(r * NCOLS::to_usize()) as *mut _ as *mut Row<_, _>)
}
}
}
impl<'a, T, NROWS, NCOLS, R> ops::Mul<R> for &'a Mat<T, NROWS, NCOLS>
where
NROWS: ops::Mul<NCOLS>,
NCOLS: Unsigned,
Prod<NROWS, NCOLS>: ArrayLength<T>,
R: Matrix<NROWS = NCOLS>,
{
type Output = Product<&'a Mat<T, 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)
}
}