use algebra_kit::algebra::*;
#[macro_export]
macro_rules! index {
($m: expr, $n: expr, $r: expr, $c: expr) => {
$c * $m + $r
};
}
pub fn vec_dot_prod_ptr<R: Ring>(m: usize, n: usize, x: &[R], r: usize, y: &[R], out: &mut R) {
*out = R::zero();
for i in 0..n {
*out += x[index!(m, n, r, i)].clone() * y[i].clone()
}
}
pub fn mat_vec_mul_ptr<R: Ring>(m: usize, n: usize, a: &[R], vec: &[R], to_vec: &mut [R]) {
for r in 0..m {
vec_dot_prod_ptr(m, n, a, r, vec, &mut to_vec[r]);
}
}
pub fn mat_add<R: Ring>(m: usize, n: usize, a: &[R], b: &[R], out: &mut [R]) {
for i in 0..(m * n) {
out[i] = a[i].clone() + b[i].clone();
}
}
pub fn mat_add_assign<R: Ring>(m: usize, n: usize, a: &mut [R], b: &[R]) {
for i in 0..(m * n) {
a[i] += a[i].clone() + b[i].clone();
}
}
pub fn mat_sub<R: Ring>(m: usize, n: usize, a: &[R], b: &[R], out: &mut [R]) {
for i in 0..(m * n) {
out[i] = a[i].clone() - b[i].clone();
}
}
pub fn mat_sub_assign<R: Ring>(m: usize, n: usize, a: &mut [R], b: &[R]) {
for i in 0..(m * n) {
a[i] -= b[i].clone();
}
}
pub fn scalar_mul<R: Ring>(n: usize, k: R, v: &[R], out: &mut [R]) {
for i in 0..n {
out[i] = k.clone() * v[i].clone();
}
}
pub fn scalar_mul_assign<R: Ring>(n: usize, k: R, v: &mut [R]) {
for i in 0..n {
v[i] *= k.clone();
}
}
pub fn scalar_div<F: Field>(n: usize, k: F, v: &[F], out: &mut [F]) {
for i in 0..n {
out[i] = v[i].clone() / k.clone();
}
}
pub fn scalar_div_assign<F: Field>(n: usize, k: F, v: &mut [F]) {
for i in 0..n {
v[i] /= k.clone();
}
}
pub fn mat_mul_ptrs<R: Ring>(m: usize, k: usize, n: usize, a: &[R], b: &[R], out: &mut [R]) {
for c in 0..n {
mat_vec_mul_ptr::<R>(m, k, a,
&b[index!(k, n, 0, c)..index!(k, n, k, c)],
&mut out[index!(m, n, 0, c)..index!(m, n, m, c)]
);
}
}
pub fn mat_mul_ptrs_assign<R: Ring>(n: usize, a: &mut [R], b: &[R]) {
let mut out = vec![R::zero() ; n * n];
mat_mul_ptrs(n, n, n, a, b, &mut out);
for i in 0..(n * n) {
a[i] = out[i].clone();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mat_vec_mul_ptr() {
let identity = [1, 0, 0, 1];
let simple_vector = [3, 7];
let mut out_vector = [0 ; 2];
mat_vec_mul_ptr(2, 2, &identity, &simple_vector, &mut out_vector);
assert_eq!(out_vector, simple_vector);
let mat = [3, 1, 2, 7, 5, 0];
let vec = [1, 4, 9];
let mut out = [0 ; 2];
mat_vec_mul_ptr(2, 3, &mat, &vec, &mut out);
assert_eq!(out, [56, 29]);
}
#[test]
fn test_full_mat_mul() {
let a = [4, 6, 10, 8, 5, 2, 5, 9, 1, 5, 1, 0];
let b = [1, 8, 1, 0, 2, 3, 4, 7];
let mut prod = [0 ; 3 * 2];
mat_mul_ptrs(3, 4, 2, &a, &b, &mut prod);
assert_eq!(prod, [73, 55, 27, 87, 70, 30]);
}
}