Skip to main content

oxilean_std/diophantine_geometry/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8/// Simplified Nevanlinna characteristic computation for rational functions.
9///
10/// For a meromorphic function f(z) = p(z)/q(z), the characteristic growth
11/// is determined by max(deg p, deg q).
12#[derive(Debug, Clone)]
13pub struct NevanlinnaData {
14    /// Degree of numerator polynomial.
15    pub numerator_degree: usize,
16    /// Degree of denominator polynomial (pole order at infinity).
17    pub denominator_degree: usize,
18}
19impl NevanlinnaData {
20    /// Create `NevanlinnaData` for a rational function.
21    pub fn new(numerator_degree: usize, denominator_degree: usize) -> Self {
22        NevanlinnaData {
23            numerator_degree,
24            denominator_degree,
25        }
26    }
27    /// The order of growth: max(deg p, deg q) for rational functions.
28    pub fn order_of_growth(&self) -> usize {
29        self.numerator_degree.max(self.denominator_degree)
30    }
31    /// Number of distinct values omitted (Picard: entire functions omit at most 1).
32    pub fn picard_omitted_values(&self) -> usize {
33        if self.denominator_degree == 0 {
34            1
35        } else {
36            0
37        }
38    }
39    /// Deficiency sum bound: ∑ δ(a, f) ≤ 2 (Nevanlinna deficiency relation).
40    pub fn deficiency_sum_bound(&self) -> f64 {
41        2.0
42    }
43}
44/// A smooth projective curve over a number field, tracked by genus.
45#[derive(Debug, Clone)]
46pub struct ProjectiveCurve {
47    /// The geometric genus g ≥ 0.
48    pub genus: usize,
49    /// Description string (for display).
50    pub description: String,
51}
52impl ProjectiveCurve {
53    /// Create a new `ProjectiveCurve` with the given genus.
54    pub fn new(genus: usize, description: &str) -> Self {
55        ProjectiveCurve {
56            genus,
57            description: description.to_string(),
58        }
59    }
60    /// Faltings' theorem: the curve has finitely many rational points iff genus ≥ 2.
61    pub fn has_finitely_many_rational_points(&self) -> bool {
62        self.genus >= 2
63    }
64    /// Whether the curve is rational (genus 0).
65    pub fn is_rational(&self) -> bool {
66        self.genus == 0
67    }
68    /// Whether the curve is elliptic (genus 1).
69    pub fn is_elliptic(&self) -> bool {
70        self.genus == 1
71    }
72    /// Riemann-Roch: dimension of L(D) for a divisor of degree d ≥ g.
73    pub fn riemann_roch_dim(&self, degree: i64) -> i64 {
74        if degree >= self.genus as i64 {
75            degree - self.genus as i64 + 1
76        } else {
77            0
78        }
79    }
80}
81/// Data for Mordell-Weil theorem on abelian varieties.
82#[allow(dead_code)]
83#[derive(Debug, Clone)]
84pub struct MordellWeilData {
85    /// Variety description.
86    pub variety: String,
87    /// Base field.
88    pub field: String,
89    /// Rank of the free part.
90    pub rank: usize,
91    /// Torsion subgroup description.
92    pub torsion: String,
93    /// Generators of the free part.
94    pub generators: Vec<String>,
95}
96#[allow(dead_code)]
97impl MordellWeilData {
98    /// Creates Mordell-Weil data.
99    pub fn new(variety: &str, field: &str) -> Self {
100        MordellWeilData {
101            variety: variety.to_string(),
102            field: field.to_string(),
103            rank: 0,
104            torsion: "trivial".to_string(),
105            generators: Vec::new(),
106        }
107    }
108    /// Sets rank.
109    pub fn with_rank(mut self, r: usize) -> Self {
110        self.rank = r;
111        self
112    }
113    /// Sets torsion.
114    pub fn with_torsion(mut self, t: &str) -> Self {
115        self.torsion = t.to_string();
116        self
117    }
118    /// Adds a generator.
119    pub fn add_generator(&mut self, gen: &str) {
120        self.generators.push(gen.to_string());
121    }
122    /// Returns the structure theorem statement.
123    pub fn structure_theorem(&self) -> String {
124        format!(
125            "{}({}) ≅ Z^{} ⊕ ({})",
126            self.variety, self.field, self.rank, self.torsion
127        )
128    }
129    /// Returns the Mordell-Weil rank.
130    pub fn mw_rank(&self) -> usize {
131        self.rank
132    }
133}
134/// Computes the naive Weil height for a projective point given as integer coords.
135#[derive(Debug, Clone)]
136pub struct NaiveHeightComputer {
137    /// Homogeneous integer coordinates.
138    pub coords: Vec<i64>,
139}
140#[allow(dead_code)]
141impl NaiveHeightComputer {
142    /// Create a new `NaiveHeightComputer` with the given coordinates.
143    pub fn new(coords: Vec<i64>) -> Self {
144        NaiveHeightComputer { coords }
145    }
146    /// Naive height H(P) = max |x_i|.
147    pub fn naive_height(&self) -> i64 {
148        self.coords.iter().map(|x| x.abs()).max().unwrap_or(0)
149    }
150    /// Logarithmic height h(P) = log H(P).
151    pub fn log_height(&self) -> f64 {
152        let h = self.naive_height();
153        if h == 0 {
154            0.0
155        } else {
156            (h as f64).ln()
157        }
158    }
159    /// Number of coordinates.
160    pub fn number_of_coords(&self) -> usize {
161        self.coords.len()
162    }
163    /// Check if all coordinates are zero (degenerate point).
164    pub fn is_zero(&self) -> bool {
165        self.coords.iter().all(|&x| x == 0)
166    }
167}
168/// Represents a height function on algebraic varieties.
169#[allow(dead_code)]
170#[derive(Debug, Clone)]
171pub struct HeightFunction {
172    /// Name of the height function.
173    pub name: String,
174    /// Whether the Northcott property holds (finite points of bounded height and degree).
175    pub northcott: bool,
176    /// Logarithmic Weil height on the base field.
177    pub base_field: String,
178}
179#[allow(dead_code)]
180impl HeightFunction {
181    /// Creates a height function.
182    pub fn new(name: &str, base_field: &str) -> Self {
183        HeightFunction {
184            name: name.to_string(),
185            northcott: false,
186            base_field: base_field.to_string(),
187        }
188    }
189    /// Sets Northcott property.
190    pub fn with_northcott(mut self) -> Self {
191        self.northcott = true;
192        self
193    }
194    /// Weil height of a rational number p/q (in lowest terms): h(p/q) = log(max(|p|, |q|)).
195    pub fn weil_height_rational(p: i64, q: i64) -> f64 {
196        if q == 0 {
197            return f64::INFINITY;
198        }
199        (p.abs().max(q.abs()) as f64).ln()
200    }
201    /// Naive height of (x_0 : ... : x_n) in projective space: max |x_i|.
202    pub fn projective_height(coords: &[i64]) -> f64 {
203        coords.iter().map(|&x| x.unsigned_abs()).max().unwrap_or(0) as f64
204    }
205    /// Logarithmic height.
206    pub fn log_height(coords: &[i64]) -> f64 {
207        Self::projective_height(coords).max(1.0).ln()
208    }
209    /// Checks Northcott's theorem consequence: there are finitely many points h(P) <= B.
210    pub fn northcott_bound(&self, bound: f64) -> String {
211        if self.northcott {
212            format!(
213                "Finitely many points P over {} with h(P) <= {bound:.2}",
214                self.base_field
215            )
216        } else {
217            format!("Northcott property not established for {}", self.name)
218        }
219    }
220}
221/// Represents a line bundle on a smooth projective variety by its numerical data.
222#[derive(Debug, Clone)]
223pub struct LineBundleData {
224    /// Self-intersection number (for surfaces: L²).
225    pub self_intersection: i64,
226    /// Intersection with a curve class (for ampleness checks).
227    pub curve_intersections: Vec<i64>,
228}
229impl LineBundleData {
230    /// Create a `LineBundleData` with given self-intersection and curve intersections.
231    pub fn new(self_intersection: i64, curve_intersections: Vec<i64>) -> Self {
232        LineBundleData {
233            self_intersection,
234            curve_intersections,
235        }
236    }
237    /// Check ampleness via Nakai-Moishezon on a surface: L² > 0 and L·C > 0 for all curves.
238    pub fn is_ample_nakai_moishezon(&self) -> bool {
239        self.self_intersection > 0 && self.curve_intersections.iter().all(|&c| c > 0)
240    }
241    /// Check the nef property: L·C ≥ 0 for all curves.
242    pub fn is_nef(&self) -> bool {
243        self.curve_intersections.iter().all(|&c| c >= 0)
244    }
245    /// Compute the Seshadri constant (simplified: min ratio L·C / mult_x(C)).
246    pub fn seshadri_constant(&self, multiplicities: &[u64]) -> f64 {
247        self.curve_intersections
248            .iter()
249            .zip(multiplicities.iter())
250            .filter(|(_, &m)| m > 0)
251            .map(|(&lc, &m)| lc as f64 / m as f64)
252            .fold(f64::INFINITY, f64::min)
253    }
254}
255/// An abc triple: coprime positive integers a, b, c with a + b = c.
256#[derive(Debug, Clone)]
257pub struct ABCTriple {
258    pub a: u64,
259    pub b: u64,
260    pub c: u64,
261}
262impl ABCTriple {
263    /// Construct an ABCTriple, verifying a + b = c.
264    pub fn new(a: u64, b: u64, c: u64) -> Option<Self> {
265        if a + b == c && gcd(a, b) == 1 && gcd(b, c) == 1 {
266            Some(ABCTriple { a, b, c })
267        } else {
268            None
269        }
270    }
271    /// Compute the radical rad(abc) = product of distinct prime factors.
272    pub fn radical(&self) -> u64 {
273        radical(self.a) / gcd(radical(self.a), 1)
274            * (radical(self.b) / gcd(radical(self.b), 1))
275            * (radical(self.c) / gcd(radical(self.c), 1))
276    }
277    /// Compute the quality q = log(c) / log(rad(abc)).
278    pub fn quality(&self) -> f64 {
279        let r = self.radical();
280        if r <= 1 {
281            return 0.0;
282        }
283        (self.c as f64).ln() / (r as f64).ln()
284    }
285}
286/// Data related to Faltings' theorem (Mordell conjecture).
287#[allow(dead_code)]
288#[derive(Debug, Clone)]
289pub struct FaltingsData {
290    /// Curve description.
291    pub curve: String,
292    /// Genus.
293    pub genus: usize,
294    /// Number of rational points (if finite and known).
295    pub rational_points_count: Option<usize>,
296    /// Whether finitely many rational points are expected (genus >= 2).
297    pub finitely_many: bool,
298}
299#[allow(dead_code)]
300impl FaltingsData {
301    /// Creates Faltings data.
302    pub fn new(curve: &str, genus: usize) -> Self {
303        FaltingsData {
304            curve: curve.to_string(),
305            genus,
306            rational_points_count: None,
307            finitely_many: genus >= 2,
308        }
309    }
310    /// Sets the number of rational points.
311    pub fn with_point_count(mut self, n: usize) -> Self {
312        self.rational_points_count = Some(n);
313        self
314    }
315    /// Returns the Faltings theorem statement.
316    pub fn faltings_statement(&self) -> String {
317        if self.genus >= 2 {
318            format!(
319                "C = {} has only finitely many rational points (Faltings 1983)",
320                self.curve
321            )
322        } else {
323            format!(
324                "C = {} genus {} - Faltings does not apply",
325                self.curve, self.genus
326            )
327        }
328    }
329    /// Checks the genus condition.
330    pub fn applies(&self) -> bool {
331        self.genus >= 2
332    }
333}
334/// Estimates the rank of a Selmer group via a 2-descent-style bound.
335///
336/// In practice, the Selmer rank equals the Mordell-Weil rank plus the
337/// number of independent Sha elements, but here we give an upper bound.
338#[derive(Debug, Clone)]
339pub struct SelmerGroupEstimator {
340    /// Number of bad primes (primes of bad reduction).
341    pub num_bad_primes: usize,
342    /// The 2-rank of the torsion subgroup.
343    pub two_torsion_rank: usize,
344}
345#[allow(dead_code)]
346impl SelmerGroupEstimator {
347    /// Create a new `SelmerGroupEstimator`.
348    pub fn new(num_bad_primes: usize, two_torsion_rank: usize) -> Self {
349        SelmerGroupEstimator {
350            num_bad_primes,
351            two_torsion_rank,
352        }
353    }
354    /// Upper bound on the 2-Selmer rank: 2-torsion rank + num_bad_primes + 1.
355    pub fn rank_upper_bound(&self) -> usize {
356        self.two_torsion_rank + self.num_bad_primes + 1
357    }
358    /// Whether the Selmer group is provably trivial (both params are zero).
359    pub fn is_trivially_trivial(&self) -> bool {
360        self.num_bad_primes == 0 && self.two_torsion_rank == 0
361    }
362    /// A Birch-Swinnerton-Dyer style parity conjecture: if analytic rank is odd,
363    /// the algebraic rank is odd (rank upper bound is at least 1).
364    pub fn parity_conjecture_rank_lower_bound(&self) -> usize {
365        0
366    }
367}
368/// Data for Arakelov geometry on an arithmetic surface.
369#[allow(dead_code)]
370#[derive(Debug, Clone)]
371pub struct ArakelovData {
372    /// Arithmetic surface description.
373    pub surface: String,
374    /// Arithmetic degree of a divisor.
375    pub arithmetic_degree: f64,
376    /// Green's function data (metric on Hermitian line bundle).
377    pub green_function_values: Vec<(f64, f64)>,
378}
379#[allow(dead_code)]
380impl ArakelovData {
381    /// Creates Arakelov data.
382    pub fn new(surface: &str) -> Self {
383        ArakelovData {
384            surface: surface.to_string(),
385            arithmetic_degree: 0.0,
386            green_function_values: Vec::new(),
387        }
388    }
389    /// Sets arithmetic degree.
390    pub fn with_arith_degree(mut self, d: f64) -> Self {
391        self.arithmetic_degree = d;
392        self
393    }
394    /// Adds a Green's function value at (x, y).
395    pub fn add_green_value(&mut self, x: f64, g: f64) {
396        self.green_function_values.push((x, g));
397    }
398    /// Computes the Faltings height from Arakelov data.
399    pub fn faltings_height_estimate(&self) -> f64 {
400        self.arithmetic_degree / 2.0
401    }
402    /// Noether formula: χ(O_X) = (K^2 + e(X))/12, returns description.
403    pub fn noether_formula(&self) -> String {
404        format!(
405            "χ(O_{{{}}}) = (K² + e(X))/12 (Noether formula)",
406            self.surface
407        )
408    }
409}
410/// Represents an elliptic curve E: y^2 = x^3 + ax + b over Q with arithmetic data.
411#[allow(dead_code)]
412#[derive(Debug, Clone)]
413pub struct EllipticCurveArithmetic {
414    /// Coefficient a.
415    pub a: i64,
416    /// Coefficient b.
417    pub b: i64,
418    /// Rational points (x, y) as pairs.
419    pub rational_points: Vec<(i64, i64)>,
420    /// Mordell-Weil rank.
421    pub rank: usize,
422    /// Torsion subgroup order.
423    pub torsion_order: usize,
424    /// Conductor N.
425    pub conductor: Option<u64>,
426}
427#[allow(dead_code)]
428impl EllipticCurveArithmetic {
429    /// Creates an elliptic curve.
430    pub fn new(a: i64, b: i64) -> Self {
431        EllipticCurveArithmetic {
432            a,
433            b,
434            rational_points: Vec::new(),
435            rank: 0,
436            torsion_order: 1,
437            conductor: None,
438        }
439    }
440    /// Adds a rational point.
441    pub fn add_rational_point(&mut self, x: i64, y: i64) {
442        if y * y == x * x * x + self.a * x + self.b {
443            self.rational_points.push((x, y));
444        }
445    }
446    /// Discriminant Δ = -16(4a^3 + 27b^2).
447    pub fn discriminant(&self) -> i64 {
448        -16 * (4 * self.a.pow(3) + 27 * self.b.pow(2))
449    }
450    /// j-invariant: j = 1728 * (4a)^3 / Δ.
451    pub fn j_invariant(&self) -> Option<f64> {
452        let disc = self.discriminant();
453        if disc == 0 {
454            return None;
455        }
456        let num = 1728.0 * (4.0 * self.a as f64).powi(3);
457        Some(num / disc as f64)
458    }
459    /// Returns true if E is a smooth (non-singular) curve.
460    pub fn is_smooth(&self) -> bool {
461        self.discriminant() != 0
462    }
463    /// Checks if a point (x, y) is on the curve.
464    pub fn is_on_curve(&self, x: i64, y: i64) -> bool {
465        y * y == x * x * x + self.a * x + self.b
466    }
467    /// Mordell's theorem: E(Q) is finitely generated.
468    pub fn mordell_theorem(&self) -> String {
469        format!("E(Q) ≅ Z^{} ⊕ Z/{}", self.rank, self.torsion_order)
470    }
471    /// Point doubling formula (for rational points): returns 2P.
472    pub fn double_point(&self, x: i64, y: i64) -> Option<(f64, f64)> {
473        if y == 0 {
474            return None;
475        }
476        let xf = x as f64;
477        let yf = y as f64;
478        let af = self.a as f64;
479        let lambda = (3.0 * xf * xf + af) / (2.0 * yf);
480        let x3 = lambda * lambda - 2.0 * xf;
481        let y3 = lambda * (xf - x3) - yf;
482        Some((x3, y3))
483    }
484}
485/// A simple Thue equation solver for F(x,y) = m where F is a degree-d polynomial.
486///
487/// Stores the polynomial by its coefficient vector: a_0 x^d + a_1 x^{d-1} y + ... + a_d y^d.
488#[derive(Debug, Clone)]
489pub struct ThueSolver {
490    /// Coefficients of the homogeneous polynomial F, from degree d down to 0.
491    pub coeffs: Vec<i64>,
492    /// Right-hand side m.
493    pub rhs: i64,
494}
495#[allow(dead_code)]
496impl ThueSolver {
497    /// Create a new `ThueSolver` for F(x,y) = rhs.
498    pub fn new(coeffs: Vec<i64>, rhs: i64) -> Self {
499        ThueSolver { coeffs, rhs }
500    }
501    /// Degree of the Thue form.
502    pub fn degree(&self) -> usize {
503        self.coeffs.len().saturating_sub(1)
504    }
505    /// Evaluate F(x, y): F = sum_{i=0}^{d} coeffs[i] * x^{d-i} * y^i.
506    pub fn evaluate(&self, x: i64, y: i64) -> i64 {
507        let d = self.degree();
508        let mut result = 0i64;
509        for (i, &c) in self.coeffs.iter().enumerate() {
510            let x_pow = (d - i) as u32;
511            let y_pow = i as u32;
512            let term = c
513                .saturating_mul(x.saturating_pow(x_pow))
514                .saturating_mul(y.saturating_pow(y_pow));
515            result = result.saturating_add(term);
516        }
517        result
518    }
519    /// Search for small solutions (x,y) with |x|,|y| ≤ bound.
520    pub fn small_solutions(&self, bound: i64) -> Vec<(i64, i64)> {
521        let mut solutions = Vec::new();
522        for x in -bound..=bound {
523            for y in -bound..=bound {
524                if self.evaluate(x, y) == self.rhs {
525                    solutions.push((x, y));
526                }
527            }
528        }
529        solutions
530    }
531}
532/// A Weil height function on projective space P^n(Q).
533///
534/// For P = [x₀ : x₁ : ... : xₙ] with integer coordinates (no common factor),
535/// the naive height is H(P) = max |xᵢ|, and the logarithmic height is h(P) = log H(P).
536#[derive(Debug, Clone)]
537pub struct WeilHeight {
538    /// Coordinates of the projective point (as integers).
539    pub coords: Vec<i64>,
540}
541impl WeilHeight {
542    /// Create a new `WeilHeight` for a projective point with given coordinates.
543    pub fn new(coords: Vec<i64>) -> Self {
544        WeilHeight { coords }
545    }
546    /// Compute the naive Weil height H(P) = max |xᵢ|.
547    pub fn naive_height(&self) -> i64 {
548        self.coords.iter().map(|x| x.abs()).max().unwrap_or(0)
549    }
550    /// Compute the logarithmic Weil height h(P) = log H(P).
551    pub fn logarithmic_height(&self) -> f64 {
552        let h = self.naive_height();
553        if h == 0 {
554            0.0
555        } else {
556            (h as f64).ln()
557        }
558    }
559    /// Check the Northcott property: are there finitely many points with bounded height?
560    ///
561    /// Returns `true` (the Northcott property holds for standard Weil heights).
562    pub fn northcott_property_holds(&self) -> bool {
563        true
564    }
565}
566/// A simplified model of the Mordell-Weil group of an elliptic curve.
567///
568/// We store only the rank and the orders of torsion generators (for illustration).
569#[derive(Debug, Clone)]
570pub struct MordellWeilGroup {
571    /// The rank r of the free part Z^r.
572    pub rank: usize,
573    /// Orders of cyclic factors in the torsion subgroup (e.g., [2, 6] for Z/2 × Z/6).
574    pub torsion_orders: Vec<u32>,
575}
576impl MordellWeilGroup {
577    /// Create a new `MordellWeilGroup` with given rank and torsion.
578    pub fn new(rank: usize, torsion_orders: Vec<u32>) -> Self {
579        MordellWeilGroup {
580            rank,
581            torsion_orders,
582        }
583    }
584    /// The total size of the torsion subgroup.
585    pub fn torsion_size(&self) -> u64 {
586        self.torsion_orders.iter().map(|&n| n as u64).product()
587    }
588    /// Check if the Mordell-Weil group is finite (rank = 0).
589    pub fn is_finite(&self) -> bool {
590        self.rank == 0
591    }
592    /// The minimum number of generators needed.
593    pub fn num_generators(&self) -> usize {
594        self.rank + self.torsion_orders.len()
595    }
596}
597/// Implements the Chabauty-Coleman bound on rational points of a curve.
598///
599/// For a curve C of genus g over Q with Mordell-Weil rank r < g,
600/// the Coleman bound gives |C(Q)| ≤ 2g - 2 + (p - 1) for good prime p > 2g.
601#[derive(Debug, Clone)]
602pub struct ChabautyBound {
603    /// Genus of the curve.
604    pub genus: usize,
605    /// Mordell-Weil rank (must be < genus for applicability).
606    pub rank: usize,
607    /// Prime p used for p-adic integration (p > 2g, p good reduction).
608    pub prime: u64,
609}
610#[allow(dead_code)]
611impl ChabautyBound {
612    /// Create a new `ChabautyBound`.
613    pub fn new(genus: usize, rank: usize, prime: u64) -> Self {
614        ChabautyBound { genus, rank, prime }
615    }
616    /// The Chabauty method applies when rank < genus.
617    pub fn is_applicable(&self) -> bool {
618        self.rank < self.genus
619    }
620    /// The Coleman bound: |C(Q)| ≤ 2g - 2 + (p - 1) for p > 2g good prime.
621    pub fn point_bound(&self) -> u64 {
622        if !self.is_applicable() {
623            return u64::MAX;
624        }
625        let g = self.genus as u64;
626        let p = self.prime;
627        if p == 0 {
628            return 2 * g;
629        }
630        2 * g - 2 + (p - 1)
631    }
632    /// Improved bound from Stoll: accounts for p-adic residue disks.
633    pub fn stoll_bound(&self) -> u64 {
634        if !self.is_applicable() {
635            return u64::MAX;
636        }
637        let g = self.genus as u64;
638        2 * g - 2 + (self.prime - 1) / 2
639    }
640}