pub trait Zero: Sized + std::ops::Add<Self, Output = Self> {
fn zero() -> Self;
fn is_zero(&self) -> bool;
}
macro_rules! zero_impl {
($t:ty, $v:expr) => {
impl Zero for $t {
#[inline]
fn zero() -> $t {
$v
}
#[inline]
fn is_zero(&self) -> bool {
*self == $v
}
}
};
}
zero_impl!(usize, 0usize);
zero_impl!(u32, 0u32);
zero_impl!(u64, 0u64);
zero_impl!(isize, 0isize);
zero_impl!(i32, 0i32);
zero_impl!(i64, 0i64);
zero_impl!(f32, 0.0f32);
zero_impl!(f64, 0.0f64);
pub trait Num:
Zero
+ std::ops::Add
+ std::ops::AddAssign
+ std::ops::Sub
+ std::ops::SubAssign
+ std::ops::Mul
+ std::ops::MulAssign
+ Copy
+ std::fmt::Debug
{
}
impl Num for usize {}
impl Num for u32 {}
impl Num for u64 {}
impl Num for isize {}
impl Num for i32 {}
impl Num for i64 {}
impl Num for f32 {}
impl Num for f64 {}
pub fn scpmat<T: Num>(scalar: T, mat: &[Vec<T>]) -> Vec<Vec<T>> {
let rows = mat.len();
let columns = mat[0].len();
let mut r = vec![vec![T::zero(); columns]; rows];
for i in 0..mat.len() {
for j in 0..mat[0].len() {
r[i][j] = mat[i][j] + scalar;
}
}
r
}
pub fn scxmat<T: Num + std::ops::Mul<Output = T>>(scalar: T, mat: &[Vec<T>]) -> Vec<Vec<T>> {
let rows = mat.len();
let columns = mat[0].len();
let mut r = vec![vec![T::zero(); columns]; rows];
for i in 0..mat.len() {
for j in 0..mat[0].len() {
r[i][j] = mat[i][j] * scalar;
}
}
r
}
pub fn scpvec<T: Num>(scalar: T, v: &[T]) -> Vec<T> {
let mut r = vec![T::zero(); v.len()];
for i in 0..v.len() {
r[i] = v[i] + scalar;
}
r
}
pub fn scxvec<T: Num + std::ops::Mul<Output = T>>(scalar: T, v: &[T]) -> Vec<T> {
let mut r = vec![T::zero(); v.len()];
for i in 0..v.len() {
r[i] = v[i] * scalar;
}
r
}
pub fn add_vec<T: Num>(a: &[T], b: &[T], alpha: T, beta: T) -> Vec<T>
where
<T as std::ops::Mul>::Output: std::ops::Add<Output = T>,
{
let len = a.len();
if len != b.len() {
panic!("Vector dimensions do not match.");
}
let mut c = Vec::with_capacity(len);
for i in 0..len {
c.push(alpha * a[i] + beta * b[i]);
}
c
}
pub fn mul_vec<T: Num + std::ops::Mul<Output = T>>(a: &[T], b: &[T]) -> Vec<T> {
let len = a.len();
if len != b.len() {
panic!("Vector dimensions do not match.");
}
let mut c = Vec::with_capacity(len);
for i in 0..len {
c.push(a[i] * b[i]);
}
c
}
pub fn dot_prod<T: Num + std::ops::Mul<Output = T>>(a: &[T], b: &[T]) -> T {
let len = a.len();
if len != b.len() {
panic!("Vector dimensions do not match.");
}
let mut c = T::zero();
for i in 0..len {
c += a[i] * b[i];
}
c
}
pub fn cross_prod_3d<T: Num + std::ops::Mul<Output = T> + std::ops::Sub<Output = T>>(
a: &[T],
b: &[T],
) -> Vec<T> {
let len = a.len();
if len != b.len() {
panic!("Vector dimensions do not match.");
}
if len != 3 {
panic!("Vector dimension must be 3. {} given", len);
}
vec![
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
}
pub fn add_mat<T: Num + std::ops::Add<Output = T>>(
a: &[Vec<T>],
b: &[Vec<T>],
alpha: T,
beta: T,
) -> Vec<Vec<T>>
where
<T as std::ops::Mul>::Output: std::ops::Add<Output = T>,
{
let len_i = a.len();
let len_j = a[0].len();
if len_i != b.len() || len_j != b[0].len() {
panic!("Matrix dimensions do not match.");
}
let mut o = Vec::new();
for i in 0..len_i {
let mut row = Vec::new();
for j in 0..len_j {
row.push(alpha * a[i][j] + beta * b[i][j]);
}
o.push(row);
}
o
}
pub fn mul_mat<T: Num + std::ops::AddAssign<<T as std::ops::Mul>::Output>>(
a: &[Vec<T>],
b: &[Vec<T>],
) -> Vec<Vec<T>> {
let rows_a = a.len();
let columns_a = a[0].len();
let rows_b = b.len();
let columns_b = b[0].len();
if columns_a != rows_b {
panic!("Matrix dimensions do not match.")
}
let mut r = vec![vec![T::zero(); columns_b]; rows_a];
for i in 0..rows_a {
for j in 0..columns_b {
for k in 0..rows_b {
r[i][j] += a[i][k] * b[k][j];
}
}
}
r
}
pub fn transpose<T: Num>(a: &[Vec<T>]) -> Vec<Vec<T>> {
let rows = a.len();
let columns = a[0].len();
let mut r = vec![vec![T::zero(); rows]; columns];
for i in 0..rows {
for j in 0..columns {
r[j][i] = a[i][j];
}
}
r
}