use crate::natural::Natural;
use alloc::vec;
use alloc::vec::Vec;
use malachite_base::num::arithmetic::traits::{
BellNumber, ModAddAssign, ModInverse, ModMulPrecomputed, ModPowPrecomputed, ModSquare,
ModSubAssign, Parity,
};
use malachite_base::num::basic::traits::One;
use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
use malachite_base::num::factorization::traits::IsPrime;
const BELL_TAB: [u64; 26] = [
1,
1,
2,
5,
15,
52,
203,
877,
4140,
21147,
115975,
678570,
4213597,
27644437,
190899322,
1382958545,
10480142147,
82864869804,
682076806159,
5832742205057,
51724158235372,
474869816156751,
4506715738447323,
44152005855084346,
445958869294805289,
4638590332229999353,
];
const MAX_N_1: usize = 25;
const MAX_N_2: usize = 42;
const MAX_N_3: usize = 58;
fn bell_number_triangle(n: u64) -> Natural {
let un = usize::exact_from(n);
let mut t1 = [0u64; MAX_N_1];
t1[0] = 1;
let limit_1 = un.min(MAX_N_1);
for i in 1..limit_1 {
t1[i] = t1[0];
for k in (1..=i).rev() {
let t = t1[k];
t1[k - 1] += t;
}
}
if limit_1 == un {
return Natural::from(t1[0]);
}
let mut t2 = [0u128; MAX_N_2];
for (x, y) in t2.iter_mut().zip(t1.iter()) {
*x = u128::from(*y);
}
let limit_2 = un.min(MAX_N_2);
for i in limit_1..limit_2 {
t2[i] = t2[0];
for k in (1..=i).rev() {
let t = t2[k];
t2[k - 1] += t;
}
}
if limit_2 == un {
return Natural::from(t2[0]);
}
let mut t3 = [(0u128, 0u64); MAX_N_3];
for (x, y) in t3.iter_mut().zip(t2.iter()) {
*x = (*y, 0);
}
for i in limit_2..un {
t3[i] = t3[0];
for k in (1..=i).rev() {
let (lo, carry) = t3[k - 1].0.overflowing_add(t3[k].0);
t3[k - 1] = (lo, t3[k - 1].1 + t3[k].1 + u64::from(carry));
}
}
let (lo, hi) = t3[0];
(Natural::from(hi) << 128u32) | Natural::from(lo)
}
fn bell_number_size(n: u64) -> u64 {
if n <= 1 {
return 0;
}
let l = libm::log(n as f64);
let ll = libm::log(l);
let u = 1.0 / l;
(core::f64::consts::LOG2_E
* n as f64
* (l - ll - 1.0 + ll * u + u + 0.5 * (ll * u) * (ll * u) + 0.25 * ll * u * u)
+ 2.0) as u64
}
fn divisor_table(len: usize) -> Vec<(u32, u32)> {
let mut tab: Vec<(u32, u32)> = (0..len).map(|i| (1, i as u32)).collect();
for i in 2..len {
let mut j = 2;
while j <= i && i * j < len {
tab[i * j] = (j as u32, i as u32);
j += 1;
}
}
tab
}
fn bell_number_mod(n: u64, p: u64, divtab: &[(u32, u32)]) -> u64 {
let un = usize::exact_from(n);
let mul_data = u64::precompute_mod_mul_data(&p);
let pow_data = u64::precompute_mod_pow_data(&p);
let mut facs = vec![0u64; un + 1];
facs[un] = 1;
for i in (0..un).rev() {
facs[i] = facs[i + 1].mod_mul_precomputed(i as u64 + 1, p, &mul_data);
}
let mut pows = vec![0u64; un + 1];
pows[1] = 1;
for i in 2..=un {
let (a, b) = divtab[i];
pows[i] = if a == 1 {
(i as u64).mod_pow_precomputed(n, p, &pow_data)
} else {
pows[a as usize].mod_mul_precomputed(pows[b as usize], p, &mul_data)
};
}
let mut s_lo = 0u128;
let mut s_hi = 0u64;
let mut t = 0u64;
for i in 0..=un {
if i.even() {
t.mod_add_assign(facs[i], p);
} else {
t.mod_sub_assign(facs[i], p);
}
let u = pows[un - i].mod_mul_precomputed(facs[un - i], p, &mul_data);
let prod = u128::from(u) * u128::from(t);
let (lo, carry) = s_lo.overflowing_add(prod);
s_lo = lo;
s_hi += u64::from(carry);
}
let r64 = ((1u128 << 64) % u128::from(p)) as u64;
let r128 = r64.mod_square(p);
let lo_low = (s_lo % u128::from(p)) as u64;
let mut s = (s_hi % p).mod_mul_precomputed(r128, p, &mul_data);
s.mod_add_assign(lo_low, p);
let inv = facs[0].mod_inverse(p).unwrap();
s.mod_mul_precomputed(inv, p, &mul_data)
.mod_mul_precomputed(inv, p, &mul_data)
}
fn bell_number_multi_mod(n: u64) -> Natural {
let size = bell_number_size(n) + 1;
let prime_bits = 61;
let num_primes = usize::exact_from(size.div_ceil(prime_bits));
let divtab = divisor_table(usize::exact_from(n) + 1);
let mut primes = Vec::with_capacity(num_primes);
let mut p = 1u64 << prime_bits;
for _ in 0..num_primes {
p += 1;
while !p.is_prime() {
p += 1;
}
primes.push(p);
}
let residues: Vec<Natural> = primes
.iter()
.map(|&p| Natural::from(bell_number_mod(n, p, &divtab)))
.collect();
let moduli: Vec<Natural> = primes.iter().map(|&p| Natural::from(p)).collect();
Natural::multi_crt(&moduli, &residues).unwrap()
}
#[derive(Clone, Debug)]
pub struct BellNumbers {
row: Vec<Natural>,
next_index: u64,
}
impl Iterator for BellNumbers {
type Item = Natural;
fn next(&mut self) -> Option<Natural> {
let out = match self.next_index {
0 => Natural::ONE,
1 => {
self.row.push(Natural::ONE);
Natural::ONE
}
_ => {
self.row.push(self.row[0].clone());
for k in (1..self.row.len()).rev() {
let t = self.row[k].clone();
self.row[k - 1] += t;
}
self.row[0].clone()
}
};
self.next_index += 1;
Some(out)
}
}
pub const fn exhaustive_bell_numbers() -> BellNumbers {
BellNumbers {
row: Vec::new(),
next_index: 0,
}
}
fn bell_numbers_mod(len: usize, p: u64) -> Vec<u64> {
let mut b = vec![0u64; len];
b[0] = 1;
if len >= 2 {
b[1] = 1;
}
if len >= 3 {
let mut t = vec![0u64; len - 1];
t[0] = 1;
for i in 1..len - 1 {
t[i] = t[0];
for k in (1..=i).rev() {
let x = t[k];
t[k - 1].mod_add_assign(x, p);
}
b[i + 1] = t[0];
}
}
b
}
crate_test_fn! {bell_numbers_prefix_multi_mod(len: usize) -> Vec<Natural> {
let size = bell_number_size(u64::exact_from(len)) + 1;
let prime_bits = 61;
let num_primes = usize::exact_from(size.div_ceil(prime_bits));
let mut primes = Vec::with_capacity(num_primes);
let mut p = 1u64 << prime_bits;
for _ in 0..num_primes {
p += 1;
while !p.is_prime() {
p += 1;
}
primes.push(p);
}
let residue_vecs: Vec<Vec<u64>> = primes.iter().map(|&p| bell_numbers_mod(len, p)).collect();
let moduli: Vec<Natural> = primes.iter().map(|&p| Natural::from(p)).collect();
(0..len)
.map(|k| {
let num_primes_k =
usize::exact_from((bell_number_size(u64::exact_from(k)) + 1).div_ceil(prime_bits))
.max(1);
let residues: Vec<Natural> = residue_vecs[..num_primes_k]
.iter()
.map(|v| Natural::from(v[k]))
.collect();
Natural::multi_crt(&moduli[..num_primes_k], &residues).unwrap()
})
.collect()
}}
const PREFIX_MULTI_MOD_THRESHOLD: u64 = 5000;
pub fn bell_numbers_prefix(len: u64) -> Vec<Natural> {
if len < PREFIX_MULTI_MOD_THRESHOLD {
exhaustive_bell_numbers()
.take(usize::exact_from(len))
.collect()
} else {
bell_numbers_prefix_multi_mod(usize::exact_from(len))
}
}
impl BellNumber for Natural {
fn bell_number(n: u64) -> Self {
if n < 26 {
Self::from(BELL_TAB[usize::wrapping_from(n)])
} else if n <= const { MAX_N_3 as u64 } {
bell_number_triangle(n)
} else {
bell_number_multi_mod(n)
}
}
}