pub const fn binom(n:usize, k:usize) -> usize {
const LUT: [[usize; 16]; 16] = [
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 4, 6, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 5, 10, 10, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 6, 15, 20, 15, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 7, 21, 35, 35, 21, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 8, 28, 56, 70, 56, 28, 8, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1, 0, 0, 0, 0, 0, 0],
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1, 0, 0, 0, 0, 0],
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1, 0, 0, 0, 0],
[1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1, 0, 0, 0],
[1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1, 0, 0],
[1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1, 0],
[1, 15, 105, 455, 1365, 3003, 5005, 6435, 6435, 5005, 3003, 1365, 455, 105, 15, 1],
];
if n<16 && k<16 { return LUT[n][k]; }
if k>n { return 0; }
if k==0 { return 1; }
(n-k+1) * binom(n, k-1) / k
}
pub const fn even_elements(n:usize) -> usize {
if n==0 { 1 } else { 1 << (n-1) }
}
pub const fn odd_elements(n:usize) -> usize {
if n==0 { 0 } else { 1 << (n-1) }
}
pub const fn multivector_elements(n:usize) -> usize {
1 << n
}
pub const fn grade_index_in_versor(n:usize, g:usize) -> usize {
if g<=1 { return 0; }
binom(n, g-2) + grade_index_in_versor(n, g-2)
}
pub const fn grade_index_in_multivector(n:usize, g:usize) -> usize {
if g==0 { return 0; }
binom(n, g-1) + grade_index_in_multivector(n, g-1)
}
pub fn components_of(n: usize) -> impl std::iter::Iterator<Item=usize> {
let mut binom = 1;
(0..=n).map(
move |g| {
let result = binom;
binom *= n-g;
binom /= g+1;
result
}
)
}
pub fn even_components_of(n: usize) -> impl std::iter::Iterator<Item=usize> {
components_of(n).step_by(2)
}
pub fn odd_components_of(n: usize) -> impl std::iter::Iterator<Item=usize> {
components_of(n).skip(1).step_by(2)
}
#[cfg(test)]
mod tests {
use super::*;
const fn direct_binom(n: usize, k: usize) -> usize {
if k>n { return 0; }
if k==0 { return 1; }
(n-k+1) * direct_binom(n, k-1) / k
}
#[test]
fn test_lut() {
for n in 0..=16 {
for k in 0..=16 {
assert_eq!(binom(n,k), direct_binom(n,k));
}
}
}
}