#[macro_export]
macro_rules! static_assert {
($cond:expr) => {
const _: () = assert!($cond);
};
($cond:expr, $msg:literal) => {
const _: () = assert!($cond, $msg);
};
}
pub const fn rank_eq(rank: usize, expected: usize) -> bool {
rank == expected
}
pub const fn rank_at_least(rank: usize, min: usize) -> bool {
rank >= min
}
pub const fn shape_elements<const N: usize>(dims: [usize; N]) -> usize {
let mut total = 1usize;
let mut i = 0;
while i < N {
total *= dims[i];
i += 1;
}
total
}
pub const fn broadcastable<const N: usize>(lhs: [usize; N], rhs: [usize; N]) -> bool {
let mut i = 0;
while i < N {
let l = lhs[i];
let r = rhs[i];
if !(l == r || l == 1 || r == 1) {
return false;
}
i += 1;
}
true
}
pub const fn matmul_compat(lhs_m: usize, lhs_k: usize, rhs_k: usize, rhs_n: usize) -> bool {
let _ = lhs_m;
let _ = rhs_n;
lhs_k == rhs_k
}
#[cfg(test)]
mod tests {
use super::*;
static_assert!(rank_eq(2, 2));
static_assert!(rank_at_least(3, 2));
static_assert!(shape_elements([2, 3, 4]) == 24);
static_assert!(broadcastable([4, 1, 8], [4, 6, 1]));
static_assert!(!broadcastable([4, 5], [3, 5]));
static_assert!(matmul_compat(8, 16, 16, 32));
static_assert!(!matmul_compat(8, 16, 32, 16));
#[test]
fn const_helpers_at_runtime() {
assert!(rank_eq(2, 2));
assert!(!rank_eq(2, 3));
assert_eq!(shape_elements([2, 3, 4]), 24);
assert!(broadcastable([4, 1, 8], [4, 6, 1]));
assert!(matmul_compat(8, 16, 16, 32));
}
}