use crate::error::MatrixError;
use crate::matrix::Matrix;
use crate::number::Number;
#[cfg(feature = "rayon_mat")]
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
pub fn points<T, R>(
mut f: impl FnMut(usize, usize) -> (T, R),
row: usize,
col: usize,
) -> Vec<(T, R)> {
let mut ps = Vec::with_capacity(row * col);
for r in 1..=row {
for c in 1..=col {
ps.push(f(r, c))
}
}
ps
}
pub fn horizontal_concat<T, const ROW: usize, const COL: usize, const RCOL: usize>(
mat: &Matrix<T, ROW, COL>,
rhs: &Matrix<T, ROW, RCOL>,
) -> Result<Matrix<T, ROW, { COL + RCOL }>, MatrixError>
where
T: Clone + Default + std::marker::Send + std::marker::Sync,
{
let mut hmat = Matrix::zeros()?;
for r in 1..=ROW {
for c1 in 1..=COL {
hmat.set_element(r, c1, mat.get_element(r, c1)?.to_owned())?;
}
for c2 in 1..=RCOL {
hmat.set_element(r, COL + c2, rhs.get_element(r, c2)?.to_owned())?;
}
}
Ok(hmat)
}
pub fn vertical_concat<T, const ROW: usize, const COL: usize, const RROW: usize>(
mat: &Matrix<T, ROW, COL>,
rhs: &Matrix<T, RROW, COL>,
) -> Result<Matrix<T, { ROW + RROW }, COL>, MatrixError>
where
T: Clone + std::marker::Send + std::marker::Sync,
{
Matrix::create([&mat.inner[..], &rhs.inner[..]].concat())
}
pub fn linear_solve<T, const ROW: usize, const COL: usize, const EDGE: usize>(
mat: Matrix<T, ROW, COL>,
b: Matrix<T, ROW, EDGE>,
) -> Result<Matrix<T, ROW, EDGE>, MatrixError>
where
T: Number,
{
if mat.rank()? > COL {
Err(MatrixError::NoSolution(ROW, COL))
} else {
mat.row_reduce()?.1.times(b)
}
}
pub fn lu_decomposition<T, const ROW: usize, const COL: usize>(
mat: Matrix<T, ROW, COL>,
) -> Result<(Matrix<T, ROW, ROW>, Matrix<T, ROW, COL>), MatrixError>
where
T: Number,
{
let eliminates = mat.row_eliminate()?;
Ok((eliminates.1.inverse()?, eliminates.0))
}
pub fn qr_decomposition() {
todo!()
}
pub fn eigen_system() {
todo!()
}
pub fn is_sqaure_matrix<T, const ROW: usize, const COL: usize>(_: &Matrix<T, ROW, COL>) -> bool {
ROW == COL
}
pub fn is_upper_triangle_matrix<T, const ROW: usize, const COL: usize>(
m: &Matrix<T, ROW, COL>,
) -> Result<bool, MatrixError>
where
T: Number,
{
#[cfg(feature = "rayon_mat")]
let predicate = points(|r, c| (r, c), ROW, COL)
.par_iter()
.filter(|(r, c)| r > c)
.all(|(r, c)| {
m.get_element(r.to_owned(), c.to_owned())
.is_ok_and(|e| e.is_zero())
});
#[cfg(not(feature = "rayon_mat"))]
let predicate = points(|r, c| (r, c), ROW, COL)
.iter()
.filter(|(r, c)| r > c)
.all(|(r, c)| {
m.get_element(r.to_owned(), c.to_owned())
.is_ok_and(|e| e.is_zero())
});
Ok(predicate)
}