use oxilean_kernel::{Declaration, Environment, Expr, Name};
use std::f64::consts::PI;
use super::types::{
AdditiveSet, ArithmeticProgression, DirichletCharacter, DirichletLFunction, DirichletSeries,
EllipticCurveLFunction, ExponentialSumBound, GaussSum, GaussSumComputer, GoldbachConjecture,
GrandRiemannHypothesis, KloostermanSum, LFunction, LFunctionZeroChecker, ModularForm,
ModularWeight, PrimeCountingFunction, PrimeGap, RiemannHypothesis, SieveEstimator,
WaringCircleMethod, ZetaFunction,
};
pub fn riemann_hypothesis_statement() -> &'static str {
"All non-trivial zeros of the Riemann zeta function ζ(s) \
have real part equal to 1/2."
}
pub fn riemann_zeta_at_even_positive(n: u32) -> f64 {
let bernoulli_abs: [f64; 7] = [
1.0,
1.0 / 6.0,
1.0 / 30.0,
1.0 / 42.0,
1.0 / 30.0,
5.0 / 66.0,
691.0 / 2730.0,
];
if n == 0 || n as usize >= bernoulli_abs.len() {
return f64::NAN;
}
let two_n = 2 * n;
let pi_pow = PI.powi(two_n as i32);
let b = bernoulli_abs[n as usize];
let fact: f64 = (1..=(two_n as u64)).map(|k| k as f64).product();
pi_pow * b / (2.0 * fact) * (2.0_f64.powi(two_n as i32 - 1))
}
pub fn prime_number_theorem_statement() -> &'static str {
"π(x) ~ x / ln(x) as x → ∞, i.e., lim_{x→∞} π(x) · ln(x) / x = 1."
}
pub fn von_mangoldt_function(n: u64) -> f64 {
if n <= 1 {
return 0.0;
}
let p = smallest_prime_factor(n);
let mut m = n;
while m % p == 0 {
m /= p;
}
if m == 1 {
(p as f64).ln()
} else {
0.0
}
}
pub fn chebyshev_psi(x: f64) -> f64 {
if x < 2.0 {
return 0.0;
}
let limit = x as u64;
(2..=limit).map(von_mangoldt_function).sum()
}
pub fn euler_totient(n: u64) -> u64 {
if n == 0 {
return 0;
}
let mut result = n;
let mut m = n;
let mut p = 2u64;
while p * p <= m {
if m % p == 0 {
while m % p == 0 {
m /= p;
}
result -= result / p;
}
p += 1;
}
if m > 1 {
result -= result / m;
}
result
}
pub fn mobius_function(n: u64) -> i32 {
if n == 0 {
return 0;
}
if n == 1 {
return 1;
}
let mut m = n;
let mut factor_count = 0i32;
let mut p = 2u64;
while p * p <= m {
if m % p == 0 {
factor_count += 1;
m /= p;
if m % p == 0 {
return 0;
}
}
p += 1;
}
if m > 1 {
factor_count += 1;
}
if factor_count % 2 == 0 {
1
} else {
-1
}
}
pub fn liouville_function(n: u64) -> i32 {
if n == 0 {
return 0;
}
let mut m = n;
let mut omega = 0u32;
let mut p = 2u64;
while p * p <= m {
while m % p == 0 {
omega += 1;
m /= p;
}
p += 1;
}
if m > 1 {
omega += 1;
}
if omega % 2 == 0 {
1
} else {
-1
}
}
pub fn divisor_sigma(n: u64, k: u32) -> u64 {
if n == 0 {
return 0;
}
(1..=n).filter(|&d| n % d == 0).map(|d| d.pow(k)).sum()
}
pub fn mobius_inversion_theorem() -> &'static str {
"If g(n) = Σ_{d|n} f(d), then f(n) = Σ_{d|n} μ(d) g(n/d). \
Equivalently, f = μ * g in the Dirichlet convolution ring."
}
pub fn selberg_sieve_statement() -> &'static str {
"Selberg's sieve provides upper bounds for the number of integers in a set \
avoiding a given set of residue classes. It gives a sharp upper bound \
π(x) - π(√x) + 1 ≤ 2 x / ln(x)."
}
pub fn chen_theorem_statement() -> &'static str {
"Chen's theorem (1973): Every sufficiently large even integer N can be \
written as N = p + P₂, where p is prime and P₂ is either prime or a \
semiprime (product of exactly two primes)."
}
pub fn gcd(a: u64, b: u64) -> u64 {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
pub fn smallest_prime_factor(n: u64) -> u64 {
let mut p = 2u64;
while p * p <= n {
if n % p == 0 {
return p;
}
p += 1;
}
n
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(oxilean_kernel::Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(oxilean_kernel::Level::succ(oxilean_kernel::Level::zero()))
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
Expr::Pi(
oxilean_kernel::BinderInfo::Default,
Name::str("_"),
Box::new(a),
Box::new(b),
)
}
pub fn zeta_function_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn riemann_hypothesis_ty() -> Expr {
prop()
}
pub fn dirichlet_series_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn dirichlet_character_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn dirichlet_l_function_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn prime_counting_function_ty() -> Expr {
arrow(real_ty(), nat_ty())
}
pub fn von_mangoldt_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn chebyshev_psi_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn euler_totient_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn mobius_function_ty() -> Expr {
arrow(nat_ty(), cst("Int"))
}
pub fn liouville_function_ty() -> Expr {
arrow(nat_ty(), cst("Int"))
}
pub fn divisor_sigma_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), nat_ty()))
}
pub fn gauss_sum_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn kloosterman_sum_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), arrow(nat_ty(), real_ty())))
}
pub fn l_function_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn grand_riemann_hypothesis_ty() -> Expr {
prop()
}
pub fn birch_swinnerton_dyer_ty() -> Expr {
prop()
}
pub fn prime_gap_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), nat_ty()))
}
pub fn brun_constant_ty() -> Expr {
real_ty()
}
pub fn mobius_inversion_ty() -> Expr {
prop()
}
pub fn chebotarev_density_an_ty() -> Expr {
prop()
}
pub fn prime_number_theorem_ty() -> Expr {
prop()
}
pub fn chen_theorem_ty() -> Expr {
prop()
}
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn pi_impl(name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(
oxilean_kernel::BinderInfo::Implicit,
Name::str(name),
Box::new(dom),
Box::new(body),
)
}
pub fn weyl_inequality_ty() -> Expr {
pi_impl(
"f",
arrow(nat_ty(), real_ty()),
pi_impl("n", nat_ty(), prop()),
)
}
pub fn van_der_corput_b_process_ty() -> Expr {
prop()
}
pub fn exponent_pairs_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), prop()))
}
pub fn exp_sum_bound_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn major_arc_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), arrow(real_ty(), prop())))
}
pub fn minor_arc_ty() -> Expr {
arrow(real_ty(), prop())
}
pub fn waring_problem_bound_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), prop()))
}
pub fn goldbach_circle_method_ty() -> Expr {
prop()
}
pub fn vinogradov_three_primes_ty() -> Expr {
prop()
}
pub fn large_sieve_inequality_ty() -> Expr {
prop()
}
pub fn bombieri_vinogradov_ty() -> Expr {
prop()
}
pub fn barban_davenport_halberstam_ty() -> Expr {
prop()
}
pub fn selberg_upper_bound_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn l_functional_equation_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn convexity_bound_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn lindelof_hypothesis_ty() -> Expr {
prop()
}
pub fn subconvexity_bound_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn de_la_vallee_poussin_region_ty() -> Expr {
prop()
}
pub fn siegel_zero_ty() -> Expr {
arrow(real_ty(), prop())
}
pub fn effective_chebotarev_ty() -> Expr {
prop()
}
pub fn zero_free_bound_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), prop()))
}
pub fn cramer_conjecture_ty() -> Expr {
prop()
}
pub fn green_tao_theorem_ty() -> Expr {
prop()
}
pub fn bounded_gaps_ty() -> Expr {
prop()
}
pub fn prime_gap_distribution_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn chebyshev_theta_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn explicit_von_mangoldt_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn primes_in_ap_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn dirichlet_theorem_ap_ty() -> Expr {
prop()
}
pub fn character_sum_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn gauss_sum_primitive_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn jacobi_sum_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn ramanujan_sum_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn sum_product_theorem_ty() -> Expr {
prop()
}
pub fn szemeredi_trotter_ty() -> Expr {
prop()
}
pub fn additive_energy_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn freiman_theorem_ty() -> Expr {
prop()
}
pub fn euler_product_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn zero_density_estimate_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn moments_of_zeta_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn critical_line_res_ty() -> Expr {
prop()
}
pub fn primitive_character_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn orthogonality_relation_ty() -> Expr {
prop()
}
pub fn l_one_chi_nonzero_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn conductor_discriminant_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn modular_form_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn ramanujan_petersson_ty() -> Expr {
prop()
}
pub fn rankin_selberg_ty() -> Expr {
prop()
}
pub fn hecke_eigenvalue_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn register_analytic_number_theory(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("ZetaFunction", zeta_function_ty()),
("RiemannHypothesis", riemann_hypothesis_ty()),
("DirichletSeries", dirichlet_series_ty()),
("DirichletCharacter", dirichlet_character_ty()),
("DirichletLFunction", dirichlet_l_function_ty()),
("PrimeCountingFunction", prime_counting_function_ty()),
("VonMangoldt", von_mangoldt_ty()),
("ChebyshevPsi", chebyshev_psi_ty()),
("EulerTotient", euler_totient_ty()),
("MobiusFunction", mobius_function_ty()),
("LiouvilleFunction", liouville_function_ty()),
("DivisorSigma", divisor_sigma_ty()),
("GaussSum", gauss_sum_ty()),
("KloostermanSum", kloosterman_sum_ty()),
("LFunction", l_function_ty()),
("GrandRiemannHypothesis", grand_riemann_hypothesis_ty()),
("BirchSwinnertonDyer", birch_swinnerton_dyer_ty()),
("PrimeGap", prime_gap_ty()),
("BrunConstant", brun_constant_ty()),
("MobiusInversion", mobius_inversion_ty()),
("ChebotarevDensityAn", chebotarev_density_an_ty()),
("PrimeNumberTheorem", prime_number_theorem_ty()),
("ChenTheorem", chen_theorem_ty()),
("WeylInequality", weyl_inequality_ty()),
("VanDerCorputBProcess", van_der_corput_b_process_ty()),
("ExponentPairs", exponent_pairs_ty()),
("ExpSumBound", exp_sum_bound_ty()),
("MajorArc", major_arc_ty()),
("MinorArc", minor_arc_ty()),
("WaringProblemBound", waring_problem_bound_ty()),
("GoldbachCircleMethod", goldbach_circle_method_ty()),
("VinogradovThreePrimes", vinogradov_three_primes_ty()),
("LargeSieveInequality", large_sieve_inequality_ty()),
("BombieriVinogradov", bombieri_vinogradov_ty()),
(
"BarbanDavenportHalberstam",
barban_davenport_halberstam_ty(),
),
("SelbergUpperBound", selberg_upper_bound_ty()),
("LFunctionalEquation", l_functional_equation_ty()),
("ConvexityBound", convexity_bound_ty()),
("LindelofHypothesis", lindelof_hypothesis_ty()),
("SubconvexityBound", subconvexity_bound_ty()),
("DeLaValleePoussinRegion", de_la_vallee_poussin_region_ty()),
("SiegelZero", siegel_zero_ty()),
("EffectiveChebotarev", effective_chebotarev_ty()),
("ZeroFreeBound", zero_free_bound_ty()),
("CramerConjecture", cramer_conjecture_ty()),
("GreenTaoTheorem", green_tao_theorem_ty()),
("BoundedGaps", bounded_gaps_ty()),
("PrimeGapDistribution", prime_gap_distribution_ty()),
("ChebyshevTheta", chebyshev_theta_ty()),
("ExplicitVonMangoldt", explicit_von_mangoldt_ty()),
("PrimesInAP", primes_in_ap_ty()),
("DirichletTheoremAP", dirichlet_theorem_ap_ty()),
("CharacterSum", character_sum_ty()),
("GaussSumPrimitive", gauss_sum_primitive_ty()),
("JacobiSum", jacobi_sum_ty()),
("RamanujanSum", ramanujan_sum_ty()),
("SumProductTheorem", sum_product_theorem_ty()),
("SzemerediTrotter", szemeredi_trotter_ty()),
("AdditiveEnergy", additive_energy_ty()),
("FreimanTheorem", freiman_theorem_ty()),
("EulerProduct", euler_product_ty()),
("ZeroDensityEstimate", zero_density_estimate_ty()),
("MomentsOfZeta", moments_of_zeta_ty()),
("CriticalLineRes", critical_line_res_ty()),
("PrimitiveCharacter", primitive_character_ty()),
("OrthogonalityRelation", orthogonality_relation_ty()),
("LOneChiNonzero", l_one_chi_nonzero_ty()),
("ConductorDiscriminant", conductor_discriminant_ty()),
("ModularForm", modular_form_ty()),
("RamanujanPetersson", ramanujan_petersson_ty()),
("RankinSelberg", rankin_selberg_ty()),
("HeckeEigenvalue", hecke_eigenvalue_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
pub fn goldbach_conjecture() -> GoldbachConjecture {
GoldbachConjecture::new(
false,
"Chen's theorem (1973): every sufficiently large even integer is p + q \
where p is prime and q has at most two prime factors."
.to_string(),
)
}
pub fn build_env() -> oxilean_kernel::Environment {
use oxilean_kernel::Environment;
let mut env = Environment::new();
register_analytic_number_theory(&mut env);
env
}
pub fn mod_inverse(a: u64, m: u64) -> Option<u64> {
if m == 0 {
return None;
}
let (mut old_r, mut r) = (a as i64, m as i64);
let (mut old_s, mut s) = (1i64, 0i64);
while r != 0 {
let q = old_r / r;
let tmp = r;
r = old_r - q * r;
old_r = tmp;
let tmp = s;
s = old_s - q * s;
old_s = tmp;
}
if old_r != 1 {
None
} else {
Some(((old_s % m as i64 + m as i64) % m as i64) as u64)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_register_analytic_number_theory() {
let env = build_env();
assert!(env.get(&Name::str("ZetaFunction")).is_some());
assert!(env.get(&Name::str("RiemannHypothesis")).is_some());
assert!(env.get(&Name::str("PrimeNumberTheorem")).is_some());
}
#[test]
fn test_extended_axioms_registered() {
let env = build_env();
assert!(env.get(&Name::str("WeylInequality")).is_some());
assert!(env.get(&Name::str("ExponentPairs")).is_some());
assert!(env.get(&Name::str("VinogradovThreePrimes")).is_some());
assert!(env.get(&Name::str("WaringProblemBound")).is_some());
assert!(env.get(&Name::str("BombieriVinogradov")).is_some());
assert!(env.get(&Name::str("LargeSieveInequality")).is_some());
assert!(env.get(&Name::str("LindelofHypothesis")).is_some());
assert!(env.get(&Name::str("SubconvexityBound")).is_some());
assert!(env.get(&Name::str("DeLaValleePoussinRegion")).is_some());
assert!(env.get(&Name::str("SiegelZero")).is_some());
assert!(env.get(&Name::str("GreenTaoTheorem")).is_some());
assert!(env.get(&Name::str("BoundedGaps")).is_some());
assert!(env.get(&Name::str("DirichletTheoremAP")).is_some());
assert!(env.get(&Name::str("ExplicitVonMangoldt")).is_some());
assert!(env.get(&Name::str("JacobiSum")).is_some());
assert!(env.get(&Name::str("RamanujanSum")).is_some());
assert!(env.get(&Name::str("SumProductTheorem")).is_some());
assert!(env.get(&Name::str("FreimanTheorem")).is_some());
assert!(env.get(&Name::str("ZeroDensityEstimate")).is_some());
assert!(env.get(&Name::str("MomentsOfZeta")).is_some());
assert!(env.get(&Name::str("OrthogonalityRelation")).is_some());
assert!(env.get(&Name::str("LOneChiNonzero")).is_some());
assert!(env.get(&Name::str("RamanujanPetersson")).is_some());
assert!(env.get(&Name::str("RankinSelberg")).is_some());
}
#[test]
fn test_gauss_sum_computer_principal() {
let g = GaussSumComputer::new(5);
let (re, im) = g.principal_gauss_sum();
assert!(re.abs() < 2.0);
assert!(im.abs() < 1e-10);
}
#[test]
fn test_gauss_sum_magnitude_squared() {
let g = GaussSumComputer::new(7);
assert_eq!(g.magnitude_squared_primitive(), 7.0);
}
#[test]
fn test_gauss_sum_weil_bound() {
let g = GaussSumComputer::new(7);
assert!((g.weil_bound() - 2.0 * 7f64.sqrt()).abs() < 1e-10);
}
#[test]
fn test_ramanujan_sum_at_1() {
let g = GaussSumComputer::new(5);
let c = g.ramanujan_sum(1);
assert!((c - (-1.0)).abs() < 1e-8);
}
#[test]
fn test_ramanujan_sum_at_0() {
let g = GaussSumComputer::new(5);
let c = g.ramanujan_sum(0);
assert!((c - 4.0).abs() < 1e-8);
}
#[test]
fn test_kloosterman_weil_bound() {
let g = GaussSumComputer::new(11);
let (re, im) = g.kloosterman_sum(1, 1);
let magnitude = (re * re + im * im).sqrt();
assert!(magnitude <= g.weil_bound() + 1e-8);
}
#[test]
fn test_mod_inverse() {
assert_eq!(mod_inverse(3, 7), Some(5));
assert_eq!(mod_inverse(2, 6), None);
}
#[test]
fn test_l_function_zero_checker_riemann() {
let checker = LFunctionZeroChecker::riemann_zeta();
assert!(checker.all_zeros_on_critical_line());
assert!(checker.in_critical_strip(0.5));
assert!(!checker.in_critical_strip(1.5));
}
#[test]
fn test_l_function_zero_free_bound() {
let checker = LFunctionZeroChecker::riemann_zeta();
let bound = checker.zero_free_bound(1000.0);
assert!(bound > 0.9 && bound < 1.0);
}
#[test]
fn test_l_function_zero_count_estimate() {
let checker = LFunctionZeroChecker::riemann_zeta();
let count = checker.zero_count_estimate(100.0);
assert!(count > 0.0);
}
#[test]
fn test_l_function_siegel_zero() {
let checker = LFunctionZeroChecker::riemann_zeta();
assert!(!checker.siegel_zero_possible());
let checker2 = LFunctionZeroChecker::dirichlet(2000);
assert!(checker2.siegel_zero_possible());
}
#[test]
fn test_sieve_estimator_large_sieve() {
let s = SieveEstimator::new(1_000_000, 1000);
let factor = s.large_sieve_factor();
assert_eq!(factor, 1_000_000.0 + 1_000_000.0);
}
#[test]
fn test_sieve_estimator_selberg() {
let s = SieveEstimator::new(1_000_000, 100);
let bound = s.selberg_upper_bound();
assert!(bound > 200_000.0 && bound < 250_000.0);
}
#[test]
fn test_sieve_estimator_bombieri_vinogradov() {
let s = SieveEstimator::new(10_000, 100);
let q = s.bombieri_vinogradov_q();
assert!(q > 0.0);
}
#[test]
fn test_sieve_estimator_brun_titchmarsh() {
let s = SieveEstimator::new(1000, 10);
let bound = s.brun_titchmarsh_bound(1);
assert!(bound > 0.0);
}
#[test]
fn test_sieve_prime_count_estimate() {
let s = SieveEstimator::new(1000, 30);
let count = s.sieve_prime_count_estimate();
assert!(count > 50 && count < 200);
}
#[test]
fn test_exp_sum_trivial_bound() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
assert_eq!(e.trivial_bound(), 1000.0);
}
#[test]
fn test_exp_sum_weyl_bound() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
let w2 = e.weyl_bound(2);
assert!((w2 - 1000f64.powf(0.5)).abs() < 1e-8);
}
#[test]
fn test_exp_sum_van_der_corput_a() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
let bound = e.van_der_corput_a();
assert!(bound > 0.0 && bound <= 1000.0);
}
#[test]
fn test_exp_sum_van_der_corput_b() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
let bound = e.van_der_corput_b();
assert!(bound > 0.0 && bound <= 1000.0);
}
#[test]
fn test_exp_sum_exponent_pair() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
let bound = e.exponent_pair_bound(1.0 / 6.0, 2.0 / 3.0);
assert!(bound > 0.0 && bound <= 1000.0);
}
#[test]
fn test_exp_sum_best_bound() {
let e = ExponentialSumBound::new(1000, 0.01, 0.001);
let best = e.best_bound(3);
assert!(best > 0.0 && best <= 1000.0);
assert!(best <= e.trivial_bound());
}
}
#[allow(dead_code)]
pub fn gcd_u64(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let t = b;
b = a % b;
a = t;
}
a
}
#[allow(dead_code)]
pub fn euler_totient_f64(q: u64) -> f64 {
if q == 0 {
return 0.0;
}
let mut result = q as f64;
let mut n = q;
let mut p = 2u64;
while p * p <= n {
if n % p == 0 {
while n % p == 0 {
n /= p;
}
result *= 1.0 - 1.0 / (p as f64);
}
p += 1;
}
if n > 1 {
result *= 1.0 - 1.0 / (n as f64);
}
result
}
#[cfg(test)]
mod tests_extended {
use super::*;
#[test]
fn test_modular_form_dimension() {
let mf = ModularForm::new(11, ModularWeight::Integer(12), true, true);
let dim = mf.cusp_form_dimension_approx();
assert!(dim > 0.0);
}
#[test]
fn test_modular_form_ramanujan_bound() {
let mf = ModularForm::new(1, ModularWeight::Integer(12), true, true);
let bound = mf.ramanujan_bound(2);
assert!(bound > 0.0);
}
#[test]
fn test_circle_method_partition() {
let p_approx = WaringCircleMethod::partition_asymptotic(100);
assert!(p_approx > 1.0e8);
}
#[test]
fn test_circle_method_waring() {
let cm = WaringCircleMethod::new(1000, 9, 3);
assert_eq!(cm.waring_g(), Some(9));
}
#[test]
fn test_arithmetic_progression_validity() {
let ap = ArithmeticProgression::new(1, 4);
assert!(ap.is_valid());
let ap2 = ArithmeticProgression::new(2, 4);
assert!(!ap2.is_valid());
}
#[test]
fn test_siegel_walfisz_main_term() {
let ap = ArithmeticProgression::new(1, 4);
let mt = ap.siegel_walfisz_main_term(1_000_000.0);
assert!(mt > 0.0);
}
#[test]
fn test_elliptic_curve_discriminant() {
let ec = EllipticCurveLFunction::new(-1, 0, 0, 0);
let d = ec.discriminant();
assert_eq!(d, 64);
assert!(ec.is_non_singular());
}
#[test]
fn test_bsd_weak() {
let ec = EllipticCurveLFunction::new(-1, 0, 1, 1);
assert!(ec.bsd_weak_holds());
}
#[test]
fn test_additive_set_sumset() {
let a = AdditiveSet::new(vec![0, 1, 2, 3]);
let s = a.sumset();
assert_eq!(s.size(), 7);
}
#[test]
fn test_additive_energy() {
let a = AdditiveSet::new(vec![0, 1, 2]);
let e = a.additive_energy();
assert!(e >= 9);
}
#[test]
fn test_doubling_constant() {
let a = AdditiveSet::new(vec![0, 1, 2, 3, 4]);
let dc = a.doubling_constant();
assert!((dc - 1.8).abs() < 0.01);
}
}