#[inline]
pub fn getRSSvalue<const S: usize>(widths: &[u32; S], maxWidth: u32, noNarrow: bool) -> u32 {
let elements = S as u32;
let mut n = widths.iter().sum::<u32>();
let mut val = 0;
let mut narrowMask = 0;
for bar in 0..(elements - 1) {
let mut elmWidth = 1;
narrowMask |= 1 << bar;
while elmWidth < widths[bar as usize] {
let mut subVal = combins_pre(n - elmWidth - 1, elements - bar - 2);
if noNarrow
&& (narrowMask == 0)
&& (n - elmWidth - (elements - bar - 1) >= elements - bar - 1)
{
subVal -= combins_pre(n - elmWidth - (elements - bar), elements - bar - 2);
}
if elements - bar - 1 > 1 {
let mut lessVal = 0;
let mut mxwElement = n - elmWidth - (elements - bar - 2);
while mxwElement > maxWidth {
lessVal += combins_pre(n - elmWidth - mxwElement - 1, elements - bar - 3);
mxwElement -= 1;
}
subVal -= lessVal * (elements - 1 - bar);
} else if n - elmWidth > maxWidth {
subVal -= 1;
}
val += subVal;
elmWidth += 1;
narrowMask &= !(1 << bar)
}
n -= elmWidth;
}
val
}
#[inline(always)]
const fn combins(n: u32, r: u32) -> u32 {
if n as usize <= N_MAX && r as usize <= R_MAX {
return combins_pre(n, r);
}
let maxDenom;
let minDenom;
if n.checked_sub(r).is_none() {
minDenom = r;
maxDenom = n - r;
} else {
minDenom = n - r;
maxDenom = r;
}
let mut val = 1;
let mut j = 1;
let mut i = n;
while i > maxDenom {
val *= i;
if j <= minDenom {
val /= j;
j += 1;
}
i -= 1;
}
while j <= minDenom {
val /= j;
j += 1;
}
val
}
const N_MAX: usize = 34;
const R_MAX: usize = N_MAX;
const fn build_pascal() -> [[u32; R_MAX + 1]; N_MAX + 1] {
let mut table = [[0u32; R_MAX + 1]; N_MAX + 1];
let mut i = 0;
while i <= N_MAX {
let mut j = 0;
while j <= i {
table[i][j] = if j == 0 || j == i {
1
} else {
table[i - 1][j - 1] + table[i - 1][j]
};
j += 1;
}
i += 1;
}
table
}
const COMBIN_TABLE: [[u32; R_MAX + 1]; N_MAX + 1] = build_pascal();
#[inline(always)]
pub const fn combins_pre(n: u32, r: u32) -> u32 {
let ni = n as usize;
let ri = r as usize;
if ni > N_MAX || ri > R_MAX {
return combins(n, r);
}
COMBIN_TABLE[ni][ri]
}