use oxilean_kernel::{Declaration, Environment, Expr, Level, Name};
use super::types::{
AtkinLehnerInvolution, AutomorphicRepresentation, DirichletCharacter, EisensteinSeries,
HeckeLFunction, HeckeOperator, HeckeOperatorDataMatrix, Mat2x2, ModularCurve, ModularCurveType,
ModularForm, ModularFormCusp, ModularSymbol, MoonshineDatum, NewformDecomposition,
PeterssonInnerProduct, QExpansion, RamanujanTau, RamanujanTauFunction,
RankinSelbergConvolution, ShimuraVariety, SiegelModularForm,
};
pub type HeckeOperatorMatrix = HeckeOperatorDataMatrix;
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn int_ty() -> Expr {
cst("Int")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn complex_ty() -> Expr {
cst("Complex")
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
Expr::Pi(
oxilean_kernel::BinderInfo::Default,
Name::str("_"),
Box::new(a),
Box::new(b),
)
}
pub fn arrow3(a: Expr, b: Expr, c: Expr) -> Expr {
arrow(a, arrow(b, c))
}
pub fn arrow4(a: Expr, b: Expr, c: Expr, d: Expr) -> Expr {
arrow(a, arrow3(b, c, d))
}
pub fn arrow5(a: Expr, b: Expr, c: Expr, d: Expr, e: Expr) -> Expr {
arrow(a, arrow4(b, c, d, e))
}
pub fn sigma_k_minus_1(n: u64, k: u32) -> u64 {
if n == 0 {
return 0;
}
let mut result = 0u64;
let exp = k.saturating_sub(1);
for d in 1..=n {
if n % d == 0 {
result = result.saturating_add(d.saturating_pow(exp));
}
}
result
}
pub fn eisenstein_fourier_coeff(n: u64, k: u32) -> u64 {
if n == 0 {
1
} else {
sigma_k_minus_1(n, k)
}
}
pub fn ramanujan_tau_up_to(n_max: usize) -> Vec<i64> {
let mut coeffs = vec![0i64; n_max + 1];
let size = n_max + 1;
let mut prod = vec![0i64; size];
prod[0] = 1;
for m in 1..size {
for _ in 0..24 {
for j in (m..size).rev() {
prod[j] -= prod[j - m];
}
}
}
for n in 1..=n_max {
if n >= 1 {
coeffs[n] = *prod.get(n - 1).unwrap_or(&0);
}
}
coeffs[0] = 0;
coeffs
}
pub fn check_ramanujan_congruence(n_max: usize) -> bool {
let taus = ramanujan_tau_up_to(n_max);
for n in 1..=n_max {
let tau_n = taus[n].rem_euclid(691) as u64;
let sigma11_n = sigma_k_minus_1(n as u64, 12) % 691;
if tau_n != sigma11_n {
return false;
}
}
true
}
pub fn r2(n: u64) -> u64 {
if n == 0 {
return 1;
}
let mut count = 0u64;
let bound = (n as f64).sqrt() as i64 + 1;
for a in -bound..=bound {
let b2 = n as i64 - a * a;
if b2 < 0 {
continue;
}
let b = (b2 as f64).sqrt() as i64;
if b * b == b2 {
count += 1;
if b > 0 {
count += 1;
}
}
}
count
}
pub fn hecke_tp_coefficients(a: &[i64], p: u64, k: u32) -> Vec<i64> {
let n_max = a.len();
let mut b = vec![0i64; n_max];
let pk1 = (p as i64).pow(k.saturating_sub(1));
for n in 0..n_max {
let pn = (n as u64).saturating_mul(p) as usize;
b[n] = if pn < n_max { a[pn] } else { 0 };
if n as u64 % p == 0 {
let np = (n as u64 / p) as usize;
b[n] += pk1 * a[np];
}
}
b
}
pub fn modular_group_ty() -> Expr {
type0()
}
pub fn psl2z_ty() -> Expr {
type0()
}
pub fn generator_s_ty() -> Expr {
cst("ModularGroup")
}
pub fn generator_t_ty() -> Expr {
cst("ModularGroup")
}
pub fn fundamental_domain_ty() -> Expr {
type0()
}
pub fn congruence_subgroup_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn gamma0_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn gamma1_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn subgroup_index_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn subgroup_level_ty() -> Expr {
arrow(cst("CongruenceSubgroup"), nat_ty())
}
pub fn modular_form_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), type0())
}
pub fn cusp_form_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), type0())
}
pub fn eisenstein_series_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn g_function_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn fourier_coefficient_ty() -> Expr {
arrow3(cst("ModularForm"), nat_ty(), complex_ty())
}
pub fn modular_form_weight_ty() -> Expr {
arrow(cst("ModularForm"), nat_ty())
}
pub fn holomorphic_at_cusps_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn vanishes_at_cusps_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn petersson_inner_product_ty() -> Expr {
arrow3(cst("CuspForm"), cst("CuspForm"), complex_ty())
}
pub fn petersson_norm_ty() -> Expr {
arrow(cst("CuspForm"), real_ty())
}
pub fn hecke_operator_ty() -> Expr {
arrow4(nat_ty(), nat_ty(), cst("CongruenceSubgroup"), type0())
}
pub fn hecke_algebra_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), type0())
}
pub fn diamond_operator_ty() -> Expr {
arrow4(nat_ty(), nat_ty(), cst("ModularForm"), cst("ModularForm"))
}
pub fn hecke_eigenform_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn hecke_eigenvalue_ty() -> Expr {
arrow3(cst("ModularForm"), nat_ty(), complex_ty())
}
pub fn hecke_multiplicativity_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), prop())
}
pub fn l_function_mf_ty() -> Expr {
arrow3(cst("ModularForm"), complex_ty(), complex_ty())
}
pub fn completed_l_function_ty() -> Expr {
arrow3(cst("ModularForm"), complex_ty(), complex_ty())
}
pub fn functional_equation_mf_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn root_number_ty() -> Expr {
arrow(cst("ModularForm"), int_ty())
}
pub fn euler_product_mf_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn ramanujan_tau_ty() -> Expr {
arrow(nat_ty(), int_ty())
}
pub fn delta_form_ty() -> Expr {
type0()
}
pub fn ramanujan_conjecture_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn ramanujan_congruence_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn theta_series_ty() -> Expr {
arrow(type0(), type0())
}
pub fn theta_series_lattice_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn jacobi_theta_function_ty() -> Expr {
arrow3(complex_ty(), complex_ty(), complex_ty())
}
pub fn modular_symbol_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), type0())
}
pub fn manin_symbol_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn eichler_shimura_pairing_ty() -> Expr {
arrow3(cst("ModularForm"), cst("ModularSymbol"), complex_ty())
}
pub fn eichler_shimura_relation_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn modular_curve_ty() -> Expr {
arrow(cst("CongruenceSubgroup"), type0())
}
pub fn cusp_ty() -> Expr {
arrow(cst("CongruenceSubgroup"), type0())
}
pub fn jacobian_of_modular_curve_ty() -> Expr {
arrow(cst("CongruenceSubgroup"), type0())
}
pub fn newform_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn oldform_space_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn newform_decomposition_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), prop())
}
pub fn strong_multiplicity_one_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), prop())
}
pub fn atkin_lehner_involution_ty() -> Expr {
arrow3(nat_ty(), cst("ModularForm"), cst("ModularForm"))
}
pub fn atkin_lehner_eigenvalue_ty() -> Expr {
arrow3(nat_ty(), cst("Newform"), int_ty())
}
pub fn gross_zagier_formula_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn tate_twist_mf_ty() -> Expr {
arrow3(cst("ModularForm"), nat_ty(), cst("ModularForm"))
}
pub fn galois_conjugate_mf_ty() -> Expr {
arrow(cst("Newform"), type0())
}
pub fn modular_form_dimension_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), nat_ty())
}
pub fn cusp_form_dimension_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), nat_ty())
}
pub fn poincare_series_ty() -> Expr {
arrow4(nat_ty(), nat_ty(), complex_ty(), complex_ty())
}
pub fn siegel_modular_form_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn hilbert_modular_form_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn modular_form_lift_ty() -> Expr {
arrow3(cst("Newform"), nat_ty(), prop())
}
pub fn sato_tate_conjecture_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), prop())
}
pub fn langlands_correspondence_gl2_ty() -> Expr {
arrow(cst("Newform"), type0())
}
pub fn modular_form_conductor_ty() -> Expr {
arrow(cst("Newform"), nat_ty())
}
pub fn nebentypus_character_ty() -> Expr {
arrow(cst("Newform"), type0())
}
pub fn hecke_tn_matrix_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn hecke_commutative_ty() -> Expr {
arrow3(nat_ty(), cst("CongruenceSubgroup"), prop())
}
pub fn hecke_normal_operator_ty() -> Expr {
arrow(cst("ModularForm"), prop())
}
pub fn newform_eigen_system_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn maass_form_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn laplace_beltrami_eigenvalue_ty() -> Expr {
arrow(cst("MaassForm"), real_ty())
}
pub fn maass_l_function_ty() -> Expr {
arrow3(cst("MaassForm"), complex_ty(), complex_ty())
}
pub fn selberg_eigenvalue_conjecture_ty() -> Expr {
prop()
}
pub fn weyl_law_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn half_integer_weight_form_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn shimura_correspondence_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn waldspurger_formula_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn kohnen_variance_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), real_ty())
}
pub fn galois_representation_mf_ty() -> Expr {
arrow3(cst("Newform"), nat_ty(), type0())
}
pub fn eichler_shimura_construction_ty() -> Expr {
arrow(cst("Newform"), prop())
}
pub fn l_adic_representation_ty() -> Expr {
arrow3(cst("Newform"), nat_ty(), prop())
}
pub fn deligne_semisimplicity_ty() -> Expr {
arrow(cst("Newform"), prop())
}
pub fn overconvergent_modular_form_ty() -> Expr {
arrow3(nat_ty(), real_ty(), type0())
}
pub fn coleman_family_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn p_adic_l_function_mf_ty() -> Expr {
arrow4(cst("Newform"), nat_ty(), complex_ty(), complex_ty())
}
pub fn hida_family_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn eigencurve_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn x0n_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn x1n_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn cusp_resolution_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn modular_unit_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn siegel_unit_ty() -> Expr {
arrow3(nat_ty(), complex_ty(), complex_ty())
}
pub fn cm_point_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn shimura_reciprocity_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn cm_theory_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn heegner_point_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn gross_zagier_heegner_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn sato_tate_measure_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn sato_tate_equidistribution_ty() -> Expr {
arrow(cst("Newform"), prop())
}
pub fn sato_tate_l_function_ty() -> Expr {
arrow3(cst("Newform"), nat_ty(), complex_ty())
}
pub fn modularity_lifting_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn residual_representation_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn deformation_ring_ty() -> Expr {
arrow(nat_ty(), type0())
}
pub fn taylor_wiles_method_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn fermat_last_theorem_via_modularity_ty() -> Expr {
prop()
}
pub fn siegel_theta_series_ty() -> Expr {
arrow3(nat_ty(), nat_ty(), type0())
}
pub fn jacobi_four_squares_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn build_modular_forms_env() -> Environment {
let mut env = Environment::new();
register_modular_forms(&mut env);
env
}
pub fn register_modular_forms(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("ModularGroup", modular_group_ty()),
("PSL2Z", psl2z_ty()),
("GeneratorS", generator_s_ty()),
("GeneratorT", generator_t_ty()),
("FundamentalDomain", fundamental_domain_ty()),
("CongruenceSubgroup", congruence_subgroup_ty()),
("Gamma0", gamma0_ty()),
("Gamma1", gamma1_ty()),
("SubgroupIndex", subgroup_index_ty()),
("SubgroupLevel", subgroup_level_ty()),
("ModularForm", modular_form_ty()),
("CuspForm", cusp_form_ty()),
("EisensteinSeries", eisenstein_series_ty()),
("GFunction", g_function_ty()),
("FourierCoefficient", fourier_coefficient_ty()),
("ModularFormWeight", modular_form_weight_ty()),
("HolomorphicAtCusps", holomorphic_at_cusps_ty()),
("VanishesAtCusps", vanishes_at_cusps_ty()),
("PeterssonInnerProduct", petersson_inner_product_ty()),
("PeterssonNorm", petersson_norm_ty()),
("HeckeOperator", hecke_operator_ty()),
("HeckeAlgebra", hecke_algebra_ty()),
("DiamondOperator", diamond_operator_ty()),
("HeckeEigenform", hecke_eigenform_ty()),
("HeckeEigenvalue", hecke_eigenvalue_ty()),
("HeckeMultiplicativity", hecke_multiplicativity_ty()),
("LFunction_MF", l_function_mf_ty()),
("CompletedLFunction", completed_l_function_ty()),
("FunctionalEquation_MF", functional_equation_mf_ty()),
("RootNumber", root_number_ty()),
("EulerProduct_MF", euler_product_mf_ty()),
("RamanujanTau", ramanujan_tau_ty()),
("DeltaForm", delta_form_ty()),
("RamanujanConjecture", ramanujan_conjecture_ty()),
("RamanujanCongruence", ramanujan_congruence_ty()),
("ThetaSeries", theta_series_ty()),
("ThetaSeriesLattice", theta_series_lattice_ty()),
("JacobiThetaFunction", jacobi_theta_function_ty()),
("ModularSymbol", modular_symbol_ty()),
("ManinSymbol", manin_symbol_ty()),
("EichlerShimuraPairing", eichler_shimura_pairing_ty()),
("EichlerShimuraRelation", eichler_shimura_relation_ty()),
("ModularCurve", modular_curve_ty()),
("Cusp", cusp_ty()),
("JacobianOfModularCurve", jacobian_of_modular_curve_ty()),
("Newform", newform_ty()),
("OldformSpace", oldform_space_ty()),
("NewformDecomposition", newform_decomposition_ty()),
("StrongMultiplicityOne", strong_multiplicity_one_ty()),
("AtkinLehnerInvolution", atkin_lehner_involution_ty()),
("AtkinLehnerEigenvalue", atkin_lehner_eigenvalue_ty()),
("GrossZagierFormula", gross_zagier_formula_ty()),
("TateTwist_MF", tate_twist_mf_ty()),
("GaloisConjugate_MF", galois_conjugate_mf_ty()),
("ModularFormDimension", modular_form_dimension_ty()),
("CuspFormDimension", cusp_form_dimension_ty()),
("PoincareSeries", poincare_series_ty()),
("SiegelModularForm", siegel_modular_form_ty()),
("HilbertModularForm", hilbert_modular_form_ty()),
("ModularFormLift", modular_form_lift_ty()),
("SatoTateConjecture", sato_tate_conjecture_ty()),
(
"LanglandsCorrespondence_GL2",
langlands_correspondence_gl2_ty(),
),
("ModularFormConductor", modular_form_conductor_ty()),
("NebentypusCharacter", nebentypus_character_ty()),
("HeckeTnMatrix", hecke_tn_matrix_ty()),
("HeckeCommutative", hecke_commutative_ty()),
("HeckeNormalOperator", hecke_normal_operator_ty()),
("NewformEigenSystem", newform_eigen_system_ty()),
("MaassForm", maass_form_ty()),
(
"LaplaceBeltramiEigenvalue",
laplace_beltrami_eigenvalue_ty(),
),
("MaassLFunction", maass_l_function_ty()),
(
"SelvergEigenvalueConjecture",
selberg_eigenvalue_conjecture_ty(),
),
("WeylLaw", weyl_law_ty()),
("HalfIntegerWeightForm", half_integer_weight_form_ty()),
("ShimuraCorrespondence", shimura_correspondence_ty()),
("WaldspurgerFormula", waldspurger_formula_ty()),
("KohnenVariance", kohnen_variance_ty()),
("GaloisRepresentation_MF", galois_representation_mf_ty()),
(
"EichlerShimuraConstruction",
eichler_shimura_construction_ty(),
),
("LAdic_Representation", l_adic_representation_ty()),
("DeligneSemiSimplicity", deligne_semisimplicity_ty()),
(
"OverconvergentModularForm",
overconvergent_modular_form_ty(),
),
("ColemanFamily", coleman_family_ty()),
("PAdicLFunction_MF", p_adic_l_function_mf_ty()),
("HidaFamily", hida_family_ty()),
("EigenvarietyCurve", eigencurve_ty()),
("X0N", x0n_ty()),
("X1N", x1n_ty()),
("CuspResolution", cusp_resolution_ty()),
("ModularUnit", modular_unit_ty()),
("SiegelUnit", siegel_unit_ty()),
("CMPoint", cm_point_ty()),
("ShimuraReciprocity", shimura_reciprocity_ty()),
("CMTheory", cm_theory_ty()),
("HeegnerPoint", heegner_point_ty()),
("GrossZagierHeegner", gross_zagier_heegner_ty()),
("SatoTateMeasure", sato_tate_measure_ty()),
("SatoTateEquidistribution", sato_tate_equidistribution_ty()),
("SatoTateLFunction", sato_tate_l_function_ty()),
("ModularityLifting", modularity_lifting_ty()),
("ResidualRepresentation", residual_representation_ty()),
("DeformationRing", deformation_ring_ty()),
("TaylorWilesMethod", taylor_wiles_method_ty()),
(
"FermatLastTheoremViaModularity",
fermat_last_theorem_via_modularity_ty(),
),
("SiegelThetaSeries", siegel_theta_series_ty()),
("JacobiFourSquares", jacobi_four_squares_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_build_modular_forms_env() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("ModularGroup")).is_some());
assert!(env.get(&Name::str("PSL2Z")).is_some());
assert!(env.get(&Name::str("FundamentalDomain")).is_some());
}
#[test]
fn test_congruence_subgroups() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("CongruenceSubgroup")).is_some());
assert!(env.get(&Name::str("Gamma0")).is_some());
assert!(env.get(&Name::str("Gamma1")).is_some());
assert!(env.get(&Name::str("SubgroupIndex")).is_some());
}
#[test]
fn test_forms_and_operators() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("ModularForm")).is_some());
assert!(env.get(&Name::str("CuspForm")).is_some());
assert!(env.get(&Name::str("EisensteinSeries")).is_some());
assert!(env.get(&Name::str("HeckeOperator")).is_some());
assert!(env.get(&Name::str("HeckeAlgebra")).is_some());
assert!(env.get(&Name::str("DiamondOperator")).is_some());
assert!(env.get(&Name::str("HeckeEigenform")).is_some());
}
#[test]
fn test_l_functions() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("LFunction_MF")).is_some());
assert!(env.get(&Name::str("CompletedLFunction")).is_some());
assert!(env.get(&Name::str("FunctionalEquation_MF")).is_some());
assert!(env.get(&Name::str("RootNumber")).is_some());
assert!(env.get(&Name::str("EulerProduct_MF")).is_some());
}
#[test]
fn test_ramanujan_and_theta() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("RamanujanTau")).is_some());
assert!(env.get(&Name::str("DeltaForm")).is_some());
assert!(env.get(&Name::str("RamanujanConjecture")).is_some());
assert!(env.get(&Name::str("RamanujanCongruence")).is_some());
assert!(env.get(&Name::str("ThetaSeries")).is_some());
assert!(env.get(&Name::str("JacobiThetaFunction")).is_some());
}
#[test]
fn test_newforms_and_atkin_lehner() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("Newform")).is_some());
assert!(env.get(&Name::str("NewformDecomposition")).is_some());
assert!(env.get(&Name::str("StrongMultiplicityOne")).is_some());
assert!(env.get(&Name::str("AtkinLehnerInvolution")).is_some());
assert!(env.get(&Name::str("AtkinLehnerEigenvalue")).is_some());
}
#[test]
fn test_eichler_shimura_and_curves() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("ModularSymbol")).is_some());
assert!(env.get(&Name::str("EichlerShimuraPairing")).is_some());
assert!(env.get(&Name::str("EichlerShimuraRelation")).is_some());
assert!(env.get(&Name::str("ModularCurve")).is_some());
assert!(env.get(&Name::str("JacobianOfModularCurve")).is_some());
}
#[test]
fn test_sl2z_generators_rust() {
let s = Mat2x2::generator_s();
let t = Mat2x2::generator_t();
assert!(s.is_sl2z());
assert!(t.is_sl2z());
let s2 = s.mul(&s);
assert_eq!(
s2,
Mat2x2 {
a: -1,
b: 0,
c: 0,
d: -1
}
);
assert!(t.mul(&t).is_sl2z());
}
#[test]
fn test_eisenstein_and_ramanujan_tau_rust() {
assert_eq!(sigma_k_minus_1(6, 2), 12);
assert_eq!(sigma_k_minus_1(6, 1), 4);
let taus = ramanujan_tau_up_to(5);
assert_eq!(taus[1], 1, "τ(1) should be 1");
assert_eq!(taus[2], -24, "τ(2) should be -24");
assert_eq!(r2(1), 4);
assert_eq!(r2(5), 8);
}
#[test]
fn test_hecke_operator_rust() {
let coeffs: Vec<i64> = (0..10).map(|n| sigma_k_minus_1(n, 4) as i64).collect();
let b = hecke_tp_coefficients(&coeffs, 2, 4);
assert_eq!(b.len(), coeffs.len());
}
#[test]
fn test_extended_hecke_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("HeckeTnMatrix")).is_some());
assert!(env.get(&Name::str("HeckeCommutative")).is_some());
assert!(env.get(&Name::str("HeckeNormalOperator")).is_some());
assert!(env.get(&Name::str("NewformEigenSystem")).is_some());
}
#[test]
fn test_maass_forms_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("MaassForm")).is_some());
assert!(env.get(&Name::str("LaplaceBeltramiEigenvalue")).is_some());
assert!(env.get(&Name::str("MaassLFunction")).is_some());
assert!(env.get(&Name::str("SelvergEigenvalueConjecture")).is_some());
assert!(env.get(&Name::str("WeylLaw")).is_some());
}
#[test]
fn test_half_integer_weight_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("HalfIntegerWeightForm")).is_some());
assert!(env.get(&Name::str("ShimuraCorrespondence")).is_some());
assert!(env.get(&Name::str("WaldspurgerFormula")).is_some());
assert!(env.get(&Name::str("KohnenVariance")).is_some());
}
#[test]
fn test_galois_representation_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("GaloisRepresentation_MF")).is_some());
assert!(env.get(&Name::str("EichlerShimuraConstruction")).is_some());
assert!(env.get(&Name::str("LAdic_Representation")).is_some());
assert!(env.get(&Name::str("DeligneSemiSimplicity")).is_some());
}
#[test]
fn test_padic_overconvergent_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("OverconvergentModularForm")).is_some());
assert!(env.get(&Name::str("ColemanFamily")).is_some());
assert!(env.get(&Name::str("PAdicLFunction_MF")).is_some());
assert!(env.get(&Name::str("HidaFamily")).is_some());
assert!(env.get(&Name::str("EigenvarietyCurve")).is_some());
}
#[test]
fn test_modular_curves_units_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("X0N")).is_some());
assert!(env.get(&Name::str("X1N")).is_some());
assert!(env.get(&Name::str("CuspResolution")).is_some());
assert!(env.get(&Name::str("ModularUnit")).is_some());
assert!(env.get(&Name::str("SiegelUnit")).is_some());
}
#[test]
fn test_cm_and_heegner_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("CMPoint")).is_some());
assert!(env.get(&Name::str("ShimuraReciprocity")).is_some());
assert!(env.get(&Name::str("CMTheory")).is_some());
assert!(env.get(&Name::str("HeegnerPoint")).is_some());
assert!(env.get(&Name::str("GrossZagierHeegner")).is_some());
}
#[test]
fn test_sato_tate_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("SatoTateMeasure")).is_some());
assert!(env.get(&Name::str("SatoTateEquidistribution")).is_some());
assert!(env.get(&Name::str("SatoTateLFunction")).is_some());
}
#[test]
fn test_modularity_lifting_axioms() {
let env = build_modular_forms_env();
assert!(env.get(&Name::str("ModularityLifting")).is_some());
assert!(env.get(&Name::str("ResidualRepresentation")).is_some());
assert!(env.get(&Name::str("DeformationRing")).is_some());
assert!(env.get(&Name::str("TaylorWilesMethod")).is_some());
assert!(env
.get(&Name::str("FermatLastTheoremViaModularity"))
.is_some());
assert!(env.get(&Name::str("SiegelThetaSeries")).is_some());
assert!(env.get(&Name::str("JacobiFourSquares")).is_some());
}
#[test]
fn test_hecke_operator_matrix_rust() {
let m = HeckeOperatorMatrix::eigenvalue_matrix(6, 12);
assert!(m.is_diagonal());
let expected = sigma_k_minus_1(6, 12) as i64;
assert_eq!(m.trace(), expected);
}
#[test]
fn test_q_expansion_delta() {
let qe = QExpansion::delta(6);
assert!((qe.coeffs[1] - 1.0).abs() < 1e-9);
assert!((qe.coeffs[2] - (-24.0)).abs() < 1e-9);
assert_eq!(qe.valuation(), Some(1));
}
#[test]
fn test_q_expansion_eisenstein() {
let qe = QExpansion::eisenstein(4, 5);
assert!((qe.coeffs[0] - 1.0).abs() < 1e-9);
assert!((qe.coeffs[1] - 1.0).abs() < 1e-9);
assert!((qe.coeffs[2] - 9.0).abs() < 1e-9);
}
#[test]
fn test_ramanujan_tau_function_rust() {
let rtf = RamanujanTauFunction::new(20);
assert_eq!(rtf.tau(1), 1);
assert_eq!(rtf.tau(2), -24);
assert!(rtf.check_multiplicativity(2, 3));
assert!(rtf.verify_congruence_691());
}
#[test]
fn test_modular_form_cusp_rust() {
let inf = ModularFormCusp::infinity(11);
let zero = ModularFormCusp::zero(11);
assert!(inf.is_infinity());
assert!(!zero.is_infinity());
assert_eq!(inf.width(), 1);
assert_eq!(ModularFormCusp::cusp_count(11), 2);
assert_eq!(ModularFormCusp::cusp_count(1), 1);
}
}
pub fn gcd_u64(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let t = b;
b = a % b;
a = t;
}
a
}
pub fn build_env() -> Environment {
build_modular_forms_env()
}
#[allow(dead_code)]
pub fn famous_modular_forms() -> Vec<(&'static str, u32, u64, &'static str)> {
vec![
(
"Delta",
12,
1,
"Ramanujan's Delta function, generates S_12(SL2Z)",
),
(
"E4",
4,
1,
"Eisenstein series, E4 = 1 + 240 sum tau3(n) q^n",
),
(
"E6",
6,
1,
"Eisenstein series, E6 = 1 - 504 sum tau5(n) q^n",
),
(
"E2*",
2,
1,
"Quasi-modular; weight 2 Eisenstein (non-holomorphic)",
),
(
"j-function",
0,
1,
"j = E4^3/Delta, modular function (weight 0)",
),
(
"eta",
0,
1,
"Dedekind eta = q^(1/24) prod (1-q^n), weight 1/2",
),
(
"theta series",
0,
4,
"theta(z) = sum q^(n^2), weight 1/2 automorphic",
),
(
"CM newform f_37",
2,
37,
"Associated to elliptic curve y^2=x^3-x",
),
(
"Ramanujan tau-function",
12,
1,
"tau(n): tau(p) = a_p for Delta",
),
(
"Mock theta f(q)",
0,
1,
"Ramanujan's third-order mock theta function",
),
]
}
#[allow(dead_code)]
pub fn monstrous_moonshine_data() -> Vec<MoonshineDatum> {
vec![
MoonshineDatum::new("1A", "J(q) = q^-1 + 196884q + ...", true),
MoonshineDatum::new("2A", "T_{2A}(q)", true),
MoonshineDatum::new("3A", "T_{3A}(q)", true),
MoonshineDatum::new("5A", "T_{5A}(q)", true),
]
}
#[cfg(test)]
mod modular_forms_ext_tests {
use super::*;
#[test]
fn test_dirichlet_character() {
let chi = DirichletCharacter::legendre_symbol(5);
assert_eq!(chi.order, 2);
assert!(chi.is_primitive);
}
#[test]
fn test_hecke_l_function() {
let l = HeckeLFunction::new("11a1", 2, 11);
assert!(!l.euler_product_description().is_empty());
}
#[test]
fn test_shimura_variety() {
let x0 = ShimuraVariety::modular_curve(37);
assert_eq!(x0.dimension, 1);
assert!(x0.has_canonical_model());
}
#[test]
fn test_modular_curve_genus() {
let x0_11 = ModularCurveType::X0(11);
assert!(x0_11.genus() <= 2);
}
#[test]
fn test_famous_forms_nonempty() {
let forms = famous_modular_forms();
assert!(!forms.is_empty());
}
#[test]
fn test_moonshine_data() {
let md = monstrous_moonshine_data();
assert!(!md.is_empty());
assert!(md[0].hauptmodul);
}
}
#[allow(dead_code)]
pub fn dimension_s_k(k: u32, level: u64) -> u64 {
if k < 2 || k % 2 != 0 {
return 0;
}
let mu = level;
if k == 2 {
if level <= 10 {
0
} else {
mu / 12
}
} else {
((k - 1) as u64) * mu / 12
}
}
#[cfg(test)]
mod modular_forms_extra_tests {
use super::*;
#[test]
fn test_petersson_ip() {
let ip = PeterssonInnerProduct::new(2, 11);
assert!(ip.hecke_operators_self_adjoint());
assert!(ip.newforms_orthogonal());
}
#[test]
fn test_automorphic_rep() {
let pi = AutomorphicRepresentation::classical_newform(37, 2);
assert!(pi.is_cuspidal);
assert!(pi.is_tempered);
}
#[test]
fn test_dimension_formula() {
let d = dimension_s_k(12, 1);
assert_eq!(d, 0);
let d2 = dimension_s_k(2, 37);
assert!(d2 <= 4);
}
#[test]
fn test_rankin_selberg() {
let rs = RankinSelbergConvolution::new("f", "f");
assert!(rs.nonvanishing_at_s1());
assert!(rs.analytic_continuation_entire());
}
}