#[macro_export]
macro_rules! matrix {
( $( $( $x:expr ),+ ) ;+ $(;)? ) => {{
let rows_vec = vec![ $( vec![ $( $x ),+ ] ),+ ];
let n = rows_vec.len();
assert!(rows_vec.iter().all(|r| r.len() == n), "matrix! requires a square n x n list of rows");
let mut data = Vec::with_capacity(n*n);
for r in rows_vec.into_iter() { data.extend(r.into_iter()); }
$crate::linalg::matrix::Matrix::from_vec(n, n, data)
}};
( $( [ $( $x:expr ),* $(,)? ] ),+ $(,)? ) => {{
let rows_vec = vec![ $( vec![ $( $x ),* ] ),+ ];
let n = rows_vec.len();
assert!(rows_vec.iter().all(|r| r.len() == n), "matrix! requires a square n x n list of rows");
let mut data = Vec::with_capacity(n*n);
for r in rows_vec.into_iter() { data.extend(r.into_iter()); }
$crate::linalg::matrix::Matrix::full(n, data)
}};
}
#[macro_export]
macro_rules! banded_matrix {
( $( $k:expr => [ $( $v:expr ),* $(,)? ] ),+ $(,)? ) => {{
let mut n: usize = 0usize;
let mut ml: usize = 0usize;
let mut mu: usize = 0usize;
$( {
let k: isize = $k as isize;
let vals = [ $( $v ),* ];
let len = vals.len();
let kk: usize = if k < 0 { (-k) as usize } else { k as usize };
let candidate = len + kk;
if candidate > n { n = candidate; }
if k < 0 { if kk > mu { mu = kk; } } else { if kk > ml { ml = kk; } }
} )+;
let mut m = $crate::linalg::matrix::Matrix::banded(n, ml, mu);
$( {
let k: isize = $k as isize;
let vals = [ $( $v ),* ];
let len = vals.len();
if k >= 0 {
let kk = k as usize;
assert!(len <= n - kk, "diagonal length {} too long for offset {} with inferred n={}", len, k, n);
for t in 0..len {
let j = t;
let i = t + kk;
m[(i, j)] = vals[t];
}
} else {
let kk = (-k) as usize;
assert!(len <= n - kk, "diagonal length {} too long for offset {} with inferred n={}", len, k, n);
for t in 0..len {
let i = t;
let j = t + kk;
m[(i, j)] = vals[t];
}
}
} )+;
m
}};
}
#[cfg(test)]
mod tests {
use crate::linalg::matrix::Matrix;
#[test]
fn macro_full_matrix() {
let m: Matrix<f64> = matrix![ 1.0, 2.0; 3.0, 4.0 ];
assert_eq!(m.n, 2);
assert_eq!(m[(0, 0)], 1.0);
assert_eq!(m[(0, 1)], 2.0);
assert_eq!(m[(1, 0)], 3.0);
assert_eq!(m[(1, 1)], 4.0);
}
#[test]
fn macro_banded_matrix() {
let b: Matrix<f64> = banded_matrix!( 0 => [1.0,1.0,1.0], 1 => [2.0,2.0], -1 => [3.0,3.0] );
assert_eq!(b[(0, 0)], 1.0);
assert_eq!(b[(1, 1)], 1.0);
assert_eq!(b[(2, 2)], 1.0);
assert_eq!(b[(1, 0)], 2.0);
assert_eq!(b[(2, 1)], 2.0);
assert_eq!(b[(0, 1)], 3.0);
assert_eq!(b[(1, 2)], 3.0);
assert_eq!(b[(0, 2)], 0.0);
}
#[test]
fn macro_banded_by_diagonals() {
let b: Matrix<f64> =
banded_matrix!( 0 => [1.0,1.0,1.0,1.0], 1 => [2.0,2.0,2.0], -1 => [3.0,3.0,3.0] );
assert_eq!(b[(0, 0)], 1.0);
assert_eq!(b[(1, 1)], 1.0);
assert_eq!(b[(2, 2)], 1.0);
assert_eq!(b[(3, 3)], 1.0);
assert_eq!(b[(1, 0)], 2.0);
assert_eq!(b[(2, 1)], 2.0);
assert_eq!(b[(3, 2)], 2.0);
assert_eq!(b[(0, 1)], 3.0);
assert_eq!(b[(1, 2)], 3.0);
assert_eq!(b[(2, 3)], 3.0);
assert_eq!(b[(0, 3)], 0.0);
}
}