use std::ops::Index;
use rayon::prelude::ParallelSlice;
use rayon::prelude::ParallelSliceMut;
#[derive(Clone, Debug)]
pub struct Matrix<T: Send + Sync> {
n_rows: usize,
n_cols: usize,
values: Vec<T>,
}
impl<T: Send + Sync> Matrix<T> {
pub fn from_raw_parts(values: Vec<T>, n_rows: usize) -> Self {
let n_cols = values.len() / n_rows;
assert_eq!(values.len(), n_rows * n_cols);
Matrix {
n_rows,
n_cols,
values,
}
}
pub fn from_vecs(mut vecs: Vec<Vec<T>>) -> Self {
let n_rows = vecs.len();
let n_cols = vecs[0].len();
let mut values = Vec::with_capacity(n_rows * n_cols);
vecs.drain(..).for_each(|mut row| {
row.drain(..).for_each(|x| values.push(x));
});
Matrix {
n_rows,
n_cols,
values,
}
}
#[inline]
pub fn nelem(&self) -> usize {
self.n_cols * self.n_rows
}
#[inline]
pub fn raw_values(&self) -> &Vec<T> {
&self.values
}
#[inline]
pub fn raw_values_mut(&mut self) -> &mut Vec<T> {
&mut self.values
}
#[inline]
pub fn rows_mut<'a>(&'a mut self) -> std::slice::ChunksExactMut<'a, T> {
self.values.chunks_exact_mut(self.n_cols)
}
#[inline]
pub fn par_rows_mut<'a>(
&'a mut self,
) -> rayon::slice::ChunksExactMut<'a, T> {
self.values.par_chunks_exact_mut(self.n_cols)
}
#[inline]
pub fn rows<'a>(&'a self) -> std::slice::ChunksExact<'a, T> {
self.values.chunks_exact(self.n_cols)
}
#[inline]
pub fn par_rows<'a>(&'a self) -> rayon::slice::ChunksExact<'a, T> {
self.values.par_chunks_exact(self.n_cols)
}
#[inline]
pub fn implicit_transpose(self) -> ImplicitlyTransposedMatrix<T> {
ImplicitlyTransposedMatrix {
n_rows: self.n_cols,
n_cols: self.n_rows,
values: self.values,
}
}
}
impl<T: Send + Sync + Clone> Matrix<T> {
pub fn vtile(col: Vec<T>, n_cols: usize) -> Self {
let n_rows = col.len();
let mut values: Vec<T> = Vec::with_capacity(n_rows * n_cols);
col.iter().for_each(|x| {
(0..n_cols).for_each(|_| values.push(x.clone()));
});
Matrix {
n_rows,
n_cols,
values,
}
}
pub unsafe fn get_unchecked(&self, (i, j): (usize, usize)) -> &T {
self.values.get_unchecked(self.n_cols * i + j)
}
pub unsafe fn get_unchecked_mut(
&mut self,
(i, j): (usize, usize),
) -> &mut T {
self.values.get_unchecked_mut(self.n_cols * i + j)
}
}
impl<T> Index<(usize, usize)> for Matrix<T>
where
T: Send + Sync,
{
type Output = T;
#[inline]
fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
&self.values[self.n_cols * i + j]
}
}
impl<T> Index<(usize, usize)> for &Matrix<T>
where
T: Send + Sync,
{
type Output = T;
#[inline]
fn index(&self, (i, j): (usize, usize)) -> &Self::Output {
&self.values[self.n_cols * i + j]
}
}
#[derive(Clone, Debug)]
pub struct ImplicitlyTransposedMatrix<T: Send + Sync> {
n_rows: usize,
n_cols: usize,
values: Vec<T>,
}
impl<T> Index<(usize, usize)> for ImplicitlyTransposedMatrix<T>
where
T: Send + Sync,
{
type Output = T;
#[inline]
fn index(&self, ix: (usize, usize)) -> &Self::Output {
let (i, j) = ix;
&self.values[self.n_rows * j + i]
}
}
impl<T> Index<(usize, usize)> for &ImplicitlyTransposedMatrix<T>
where
T: Send + Sync,
{
type Output = T;
#[inline]
fn index(&self, ix: (usize, usize)) -> &Self::Output {
let (i, j) = ix;
&self.values[self.n_rows * j + i]
}
}
impl<T: Send + Sync> ImplicitlyTransposedMatrix<T> {
#[inline]
pub fn nelem(&self) -> usize {
self.n_cols * self.n_rows
}
#[inline]
pub fn raw_values(&self) -> &Vec<T> {
&self.values
}
#[inline]
pub fn raw_values_mut(&mut self) -> &mut Vec<T> {
&mut self.values
}
pub fn transpose(self) -> Matrix<T> {
Matrix {
n_rows: self.n_cols,
n_cols: self.n_rows,
values: self.values,
}
}
pub unsafe fn get_unchecked(&self, (i, j): (usize, usize)) -> &T {
self.values.get_unchecked(self.n_rows * j + i)
}
pub unsafe fn get_unchecked_mut(
&mut self,
(i, j): (usize, usize),
) -> &mut T {
self.values.get_unchecked_mut(self.n_rows * j + i)
}
}
pub trait Shape {
fn n_rows(&self) -> usize;
fn n_cols(&self) -> usize;
fn shape(&self) -> (usize, usize) {
(self.n_rows(), self.n_cols())
}
}
impl<T: Send + Sync> Shape for Matrix<T> {
fn n_rows(&self) -> usize {
self.n_rows
}
fn n_cols(&self) -> usize {
self.n_cols
}
}
impl<T: Send + Sync> Shape for &Matrix<T> {
fn n_rows(&self) -> usize {
self.n_rows
}
fn n_cols(&self) -> usize {
self.n_cols
}
}
impl<T: Send + Sync> Shape for ImplicitlyTransposedMatrix<T> {
fn n_rows(&self) -> usize {
self.n_rows
}
fn n_cols(&self) -> usize {
self.n_cols
}
}
impl<T: Send + Sync> Shape for &ImplicitlyTransposedMatrix<T> {
fn n_rows(&self) -> usize {
self.n_rows
}
fn n_cols(&self) -> usize {
self.n_cols
}
}