use astro_float::{BigFloat, Consts, RoundingMode};
use crate::base::errors::SymplexError;
use crate::base::numeric::Q;
pub(crate) fn even(k: usize) -> Q {
crate::base::bernoulli::even(k)
}
pub(super) fn bernoulli_function(
s: &BigFloat,
prec: usize,
rm: RoundingMode,
cc: &mut Consts,
) -> Result<BigFloat, SymplexError> {
if s.is_nan() || s.is_inf() {
return Err(SymplexError::Unevaluable {
reason: "bernoulli of a non-finite argument".into(),
});
}
if s.is_zero() {
return Ok(BigFloat::from_i32(1, prec));
}
if *s == BigFloat::from_i32(1, 64) {
return Ok(BigFloat::from_i32(-1, prec).div(&BigFloat::from_i32(2, prec), prec, rm));
}
let wp = prec + 32;
let one_minus_s = BigFloat::from_i32(1, 64).sub(s, super::exact_bits(s, wp), rm);
let zeta = super::arb_zeta(&one_minus_s, wp, rm, cc)?;
let r = s.mul(&zeta, wp, rm).neg();
Ok(super::round_to(r, prec, rm))
}
#[cfg(test)]
mod tests {
use super::*;
use num_bigint::BigInt;
use num_rational::Ratio;
#[test]
fn first_values() {
let q = |n: i64, d: i64| Ratio::new(BigInt::from(n), BigInt::from(d));
assert_eq!(even(1), q(1, 6));
assert_eq!(even(2), q(-1, 30));
assert_eq!(even(3), q(1, 42));
assert_eq!(even(6), q(691, -2730));
}
}