use num_bigint::BigInt;
use num_traits::Zero;
pub fn integer_bits(n: &BigInt) -> u64 {
n.bits()
}
pub fn product_bits(values: &[BigInt]) -> u64 {
values.iter().map(|v| v.bits()).sum::<u64>() + 1
}
fn inf_norm_bits(coeffs: &[BigInt]) -> u64 {
coeffs.iter().map(|c| c.bits()).max().unwrap_or(0)
}
fn two_norm_log2_upper(coeffs: &[BigInt]) -> f64 {
let n = coeffs.iter().filter(|c| !c.is_zero()).count().max(1);
let inf = inf_norm_bits(coeffs) as f64;
0.5 * (n as f64 + 1.0).log2() + inf
}
pub fn resultant_bits(f: &[BigInt], g: &[BigInt]) -> u64 {
let deg_f = f.len().saturating_sub(1) as f64;
let deg_g = g.len().saturating_sub(1) as f64;
let log_f = two_norm_log2_upper(f);
let log_g = two_norm_log2_upper(g);
let bits = deg_g * log_f + deg_f * log_g;
bits.ceil() as u64 + 4
}
pub fn determinant_bits(rows: &[Vec<BigInt>]) -> u64 {
let mut total = 0.0f64;
for row in rows {
total += two_norm_log2_upper(row);
}
total.ceil() as u64 + 2
}
pub fn mignotte_bits(f: &[BigInt]) -> u64 {
let deg = f.len().saturating_sub(1) as u64;
let log_f2 = two_norm_log2_upper(f).ceil() as u64;
deg + log_f2 + 2
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn product_is_sum_of_bits() {
let vals = vec![BigInt::from(255), BigInt::from(255)];
assert!(product_bits(&vals) >= 16);
}
#[test]
fn resultant_bound_is_positive() {
let f = vec![BigInt::from(1), BigInt::from(0), BigInt::from(-2)]; let g = vec![BigInt::from(1), BigInt::from(0), BigInt::from(-3)]; assert!(resultant_bits(&f, &g) > 0);
}
}