use super::functions::*;
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
#[derive(Debug, Clone)]
pub struct NevanlinnaData {
pub numerator_degree: usize,
pub denominator_degree: usize,
}
impl NevanlinnaData {
pub fn new(numerator_degree: usize, denominator_degree: usize) -> Self {
NevanlinnaData {
numerator_degree,
denominator_degree,
}
}
pub fn order_of_growth(&self) -> usize {
self.numerator_degree.max(self.denominator_degree)
}
pub fn picard_omitted_values(&self) -> usize {
if self.denominator_degree == 0 {
1
} else {
0
}
}
pub fn deficiency_sum_bound(&self) -> f64 {
2.0
}
}
#[derive(Debug, Clone)]
pub struct ProjectiveCurve {
pub genus: usize,
pub description: String,
}
impl ProjectiveCurve {
pub fn new(genus: usize, description: &str) -> Self {
ProjectiveCurve {
genus,
description: description.to_string(),
}
}
pub fn has_finitely_many_rational_points(&self) -> bool {
self.genus >= 2
}
pub fn is_rational(&self) -> bool {
self.genus == 0
}
pub fn is_elliptic(&self) -> bool {
self.genus == 1
}
pub fn riemann_roch_dim(&self, degree: i64) -> i64 {
if degree >= self.genus as i64 {
degree - self.genus as i64 + 1
} else {
0
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MordellWeilData {
pub variety: String,
pub field: String,
pub rank: usize,
pub torsion: String,
pub generators: Vec<String>,
}
#[allow(dead_code)]
impl MordellWeilData {
pub fn new(variety: &str, field: &str) -> Self {
MordellWeilData {
variety: variety.to_string(),
field: field.to_string(),
rank: 0,
torsion: "trivial".to_string(),
generators: Vec::new(),
}
}
pub fn with_rank(mut self, r: usize) -> Self {
self.rank = r;
self
}
pub fn with_torsion(mut self, t: &str) -> Self {
self.torsion = t.to_string();
self
}
pub fn add_generator(&mut self, gen: &str) {
self.generators.push(gen.to_string());
}
pub fn structure_theorem(&self) -> String {
format!(
"{}({}) ≅ Z^{} ⊕ ({})",
self.variety, self.field, self.rank, self.torsion
)
}
pub fn mw_rank(&self) -> usize {
self.rank
}
}
#[derive(Debug, Clone)]
pub struct NaiveHeightComputer {
pub coords: Vec<i64>,
}
#[allow(dead_code)]
impl NaiveHeightComputer {
pub fn new(coords: Vec<i64>) -> Self {
NaiveHeightComputer { coords }
}
pub fn naive_height(&self) -> i64 {
self.coords.iter().map(|x| x.abs()).max().unwrap_or(0)
}
pub fn log_height(&self) -> f64 {
let h = self.naive_height();
if h == 0 {
0.0
} else {
(h as f64).ln()
}
}
pub fn number_of_coords(&self) -> usize {
self.coords.len()
}
pub fn is_zero(&self) -> bool {
self.coords.iter().all(|&x| x == 0)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct HeightFunction {
pub name: String,
pub northcott: bool,
pub base_field: String,
}
#[allow(dead_code)]
impl HeightFunction {
pub fn new(name: &str, base_field: &str) -> Self {
HeightFunction {
name: name.to_string(),
northcott: false,
base_field: base_field.to_string(),
}
}
pub fn with_northcott(mut self) -> Self {
self.northcott = true;
self
}
pub fn weil_height_rational(p: i64, q: i64) -> f64 {
if q == 0 {
return f64::INFINITY;
}
(p.abs().max(q.abs()) as f64).ln()
}
pub fn projective_height(coords: &[i64]) -> f64 {
coords.iter().map(|&x| x.unsigned_abs()).max().unwrap_or(0) as f64
}
pub fn log_height(coords: &[i64]) -> f64 {
Self::projective_height(coords).max(1.0).ln()
}
pub fn northcott_bound(&self, bound: f64) -> String {
if self.northcott {
format!(
"Finitely many points P over {} with h(P) <= {bound:.2}",
self.base_field
)
} else {
format!("Northcott property not established for {}", self.name)
}
}
}
#[derive(Debug, Clone)]
pub struct LineBundleData {
pub self_intersection: i64,
pub curve_intersections: Vec<i64>,
}
impl LineBundleData {
pub fn new(self_intersection: i64, curve_intersections: Vec<i64>) -> Self {
LineBundleData {
self_intersection,
curve_intersections,
}
}
pub fn is_ample_nakai_moishezon(&self) -> bool {
self.self_intersection > 0 && self.curve_intersections.iter().all(|&c| c > 0)
}
pub fn is_nef(&self) -> bool {
self.curve_intersections.iter().all(|&c| c >= 0)
}
pub fn seshadri_constant(&self, multiplicities: &[u64]) -> f64 {
self.curve_intersections
.iter()
.zip(multiplicities.iter())
.filter(|(_, &m)| m > 0)
.map(|(&lc, &m)| lc as f64 / m as f64)
.fold(f64::INFINITY, f64::min)
}
}
#[derive(Debug, Clone)]
pub struct ABCTriple {
pub a: u64,
pub b: u64,
pub c: u64,
}
impl ABCTriple {
pub fn new(a: u64, b: u64, c: u64) -> Option<Self> {
if a + b == c && gcd(a, b) == 1 && gcd(b, c) == 1 {
Some(ABCTriple { a, b, c })
} else {
None
}
}
pub fn radical(&self) -> u64 {
radical(self.a) / gcd(radical(self.a), 1)
* (radical(self.b) / gcd(radical(self.b), 1))
* (radical(self.c) / gcd(radical(self.c), 1))
}
pub fn quality(&self) -> f64 {
let r = self.radical();
if r <= 1 {
return 0.0;
}
(self.c as f64).ln() / (r as f64).ln()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FaltingsData {
pub curve: String,
pub genus: usize,
pub rational_points_count: Option<usize>,
pub finitely_many: bool,
}
#[allow(dead_code)]
impl FaltingsData {
pub fn new(curve: &str, genus: usize) -> Self {
FaltingsData {
curve: curve.to_string(),
genus,
rational_points_count: None,
finitely_many: genus >= 2,
}
}
pub fn with_point_count(mut self, n: usize) -> Self {
self.rational_points_count = Some(n);
self
}
pub fn faltings_statement(&self) -> String {
if self.genus >= 2 {
format!(
"C = {} has only finitely many rational points (Faltings 1983)",
self.curve
)
} else {
format!(
"C = {} genus {} - Faltings does not apply",
self.curve, self.genus
)
}
}
pub fn applies(&self) -> bool {
self.genus >= 2
}
}
#[derive(Debug, Clone)]
pub struct SelmerGroupEstimator {
pub num_bad_primes: usize,
pub two_torsion_rank: usize,
}
#[allow(dead_code)]
impl SelmerGroupEstimator {
pub fn new(num_bad_primes: usize, two_torsion_rank: usize) -> Self {
SelmerGroupEstimator {
num_bad_primes,
two_torsion_rank,
}
}
pub fn rank_upper_bound(&self) -> usize {
self.two_torsion_rank + self.num_bad_primes + 1
}
pub fn is_trivially_trivial(&self) -> bool {
self.num_bad_primes == 0 && self.two_torsion_rank == 0
}
pub fn parity_conjecture_rank_lower_bound(&self) -> usize {
0
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ArakelovData {
pub surface: String,
pub arithmetic_degree: f64,
pub green_function_values: Vec<(f64, f64)>,
}
#[allow(dead_code)]
impl ArakelovData {
pub fn new(surface: &str) -> Self {
ArakelovData {
surface: surface.to_string(),
arithmetic_degree: 0.0,
green_function_values: Vec::new(),
}
}
pub fn with_arith_degree(mut self, d: f64) -> Self {
self.arithmetic_degree = d;
self
}
pub fn add_green_value(&mut self, x: f64, g: f64) {
self.green_function_values.push((x, g));
}
pub fn faltings_height_estimate(&self) -> f64 {
self.arithmetic_degree / 2.0
}
pub fn noether_formula(&self) -> String {
format!(
"χ(O_{{{}}}) = (K² + e(X))/12 (Noether formula)",
self.surface
)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct EllipticCurveArithmetic {
pub a: i64,
pub b: i64,
pub rational_points: Vec<(i64, i64)>,
pub rank: usize,
pub torsion_order: usize,
pub conductor: Option<u64>,
}
#[allow(dead_code)]
impl EllipticCurveArithmetic {
pub fn new(a: i64, b: i64) -> Self {
EllipticCurveArithmetic {
a,
b,
rational_points: Vec::new(),
rank: 0,
torsion_order: 1,
conductor: None,
}
}
pub fn add_rational_point(&mut self, x: i64, y: i64) {
if y * y == x * x * x + self.a * x + self.b {
self.rational_points.push((x, y));
}
}
pub fn discriminant(&self) -> i64 {
-16 * (4 * self.a.pow(3) + 27 * self.b.pow(2))
}
pub fn j_invariant(&self) -> Option<f64> {
let disc = self.discriminant();
if disc == 0 {
return None;
}
let num = 1728.0 * (4.0 * self.a as f64).powi(3);
Some(num / disc as f64)
}
pub fn is_smooth(&self) -> bool {
self.discriminant() != 0
}
pub fn is_on_curve(&self, x: i64, y: i64) -> bool {
y * y == x * x * x + self.a * x + self.b
}
pub fn mordell_theorem(&self) -> String {
format!("E(Q) ≅ Z^{} ⊕ Z/{}", self.rank, self.torsion_order)
}
pub fn double_point(&self, x: i64, y: i64) -> Option<(f64, f64)> {
if y == 0 {
return None;
}
let xf = x as f64;
let yf = y as f64;
let af = self.a as f64;
let lambda = (3.0 * xf * xf + af) / (2.0 * yf);
let x3 = lambda * lambda - 2.0 * xf;
let y3 = lambda * (xf - x3) - yf;
Some((x3, y3))
}
}
#[derive(Debug, Clone)]
pub struct ThueSolver {
pub coeffs: Vec<i64>,
pub rhs: i64,
}
#[allow(dead_code)]
impl ThueSolver {
pub fn new(coeffs: Vec<i64>, rhs: i64) -> Self {
ThueSolver { coeffs, rhs }
}
pub fn degree(&self) -> usize {
self.coeffs.len().saturating_sub(1)
}
pub fn evaluate(&self, x: i64, y: i64) -> i64 {
let d = self.degree();
let mut result = 0i64;
for (i, &c) in self.coeffs.iter().enumerate() {
let x_pow = (d - i) as u32;
let y_pow = i as u32;
let term = c
.saturating_mul(x.saturating_pow(x_pow))
.saturating_mul(y.saturating_pow(y_pow));
result = result.saturating_add(term);
}
result
}
pub fn small_solutions(&self, bound: i64) -> Vec<(i64, i64)> {
let mut solutions = Vec::new();
for x in -bound..=bound {
for y in -bound..=bound {
if self.evaluate(x, y) == self.rhs {
solutions.push((x, y));
}
}
}
solutions
}
}
#[derive(Debug, Clone)]
pub struct WeilHeight {
pub coords: Vec<i64>,
}
impl WeilHeight {
pub fn new(coords: Vec<i64>) -> Self {
WeilHeight { coords }
}
pub fn naive_height(&self) -> i64 {
self.coords.iter().map(|x| x.abs()).max().unwrap_or(0)
}
pub fn logarithmic_height(&self) -> f64 {
let h = self.naive_height();
if h == 0 {
0.0
} else {
(h as f64).ln()
}
}
pub fn northcott_property_holds(&self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct MordellWeilGroup {
pub rank: usize,
pub torsion_orders: Vec<u32>,
}
impl MordellWeilGroup {
pub fn new(rank: usize, torsion_orders: Vec<u32>) -> Self {
MordellWeilGroup {
rank,
torsion_orders,
}
}
pub fn torsion_size(&self) -> u64 {
self.torsion_orders.iter().map(|&n| n as u64).product()
}
pub fn is_finite(&self) -> bool {
self.rank == 0
}
pub fn num_generators(&self) -> usize {
self.rank + self.torsion_orders.len()
}
}
#[derive(Debug, Clone)]
pub struct ChabautyBound {
pub genus: usize,
pub rank: usize,
pub prime: u64,
}
#[allow(dead_code)]
impl ChabautyBound {
pub fn new(genus: usize, rank: usize, prime: u64) -> Self {
ChabautyBound { genus, rank, prime }
}
pub fn is_applicable(&self) -> bool {
self.rank < self.genus
}
pub fn point_bound(&self) -> u64 {
if !self.is_applicable() {
return u64::MAX;
}
let g = self.genus as u64;
let p = self.prime;
if p == 0 {
return 2 * g;
}
2 * g - 2 + (p - 1)
}
pub fn stoll_bound(&self) -> u64 {
if !self.is_applicable() {
return u64::MAX;
}
let g = self.genus as u64;
2 * g - 2 + (self.prime - 1) / 2
}
}