1use super::functions::*;
5
6#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub struct ChowGroup {
10 pub variety: String,
12 pub codimension: usize,
14 pub generators: Vec<String>,
16}
17#[allow(dead_code)]
18impl ChowGroup {
19 pub fn new(variety: impl Into<String>, codimension: usize) -> Self {
21 Self {
22 variety: variety.into(),
23 codimension,
24 generators: Vec::new(),
25 }
26 }
27 pub fn ch0(variety: impl Into<String>) -> Self {
29 let mut g = Self::new(variety, 0);
30 g.generators.push("[X]".to_string());
31 g
32 }
33 pub fn pic(variety: impl Into<String>) -> Self {
35 let mut g = Self::new(variety, 1);
36 g.generators.push("Pic".to_string());
37 g
38 }
39 pub fn add_generator(&mut self, gen: impl Into<String>) {
41 self.generators.push(gen.into());
42 }
43 pub fn intersect(&self, other: &Self) -> Self {
45 Self {
46 variety: self.variety.clone(),
47 codimension: self.codimension + other.codimension,
48 generators: vec![format!(
49 "{} · {}",
50 self.generators.first().map(|s| s.as_str()).unwrap_or("?"),
51 other.generators.first().map(|s| s.as_str()).unwrap_or("?")
52 )],
53 }
54 }
55 pub fn rank(&self) -> usize {
57 self.generators.len()
58 }
59}
60#[allow(dead_code)]
62#[derive(Debug, Clone)]
63pub struct BerkovichSpace {
64 pub algebra: String,
66 pub base_field: String,
68 pub dimension: usize,
70 pub is_smooth: bool,
72}
73#[allow(dead_code)]
74impl BerkovichSpace {
75 pub fn new(algebra: impl Into<String>, base_field: impl Into<String>, dim: usize) -> Self {
77 Self {
78 algebra: algebra.into(),
79 base_field: base_field.into(),
80 dimension: dim,
81 is_smooth: false,
82 }
83 }
84 pub fn unit_disc(base_field: impl Into<String>) -> Self {
86 Self {
87 algebra: "K{T}".to_string(),
88 base_field: base_field.into(),
89 dimension: 1,
90 is_smooth: true,
91 }
92 }
93 pub fn affine_n_space(base_field: impl Into<String>, n: usize) -> Self {
95 let gens = (1..=n)
96 .map(|i| format!("T_{}", i))
97 .collect::<Vec<_>>()
98 .join(", ");
99 Self {
100 algebra: format!("K{{{}}}", gens),
101 base_field: base_field.into(),
102 dimension: n,
103 is_smooth: true,
104 }
105 }
106 pub fn gauss_point_description(&self) -> String {
108 format!(
109 "Gauss point of M({}) over {}: seminorm |·|_1",
110 self.algebra, self.base_field
111 )
112 }
113 pub fn smooth(mut self) -> Self {
115 self.is_smooth = true;
116 self
117 }
118 pub fn skeleton_description(&self) -> String {
120 format!("Skeleton of M({}) (dim ≤ {})", self.algebra, self.dimension)
121 }
122}
123#[derive(Debug, Clone)]
125pub struct AbsoluteHeight {
126 pub point_description: String,
128 pub value: f64,
130}
131impl AbsoluteHeight {
132 pub fn of_rational(p: i64, q: u64) -> Self {
136 let value = (p.unsigned_abs()).max(q) as f64;
137 Self {
138 point_description: format!("{}/{}", p, q),
139 value,
140 }
141 }
142 pub fn of_minimal_poly(coeffs: &[i64]) -> Self {
144 let max_coeff = coeffs.iter().map(|c| c.unsigned_abs()).max().unwrap_or(0);
145 Self {
146 point_description: format!("root of poly with coeffs {:?}", coeffs),
147 value: max_coeff as f64,
148 }
149 }
150 pub fn value(&self) -> f64 {
152 self.value
153 }
154}
155#[derive(Debug, Clone)]
157pub struct LanglandsCorrespondence {
158 pub galois_rep: GaloisRepresentation,
160 pub automorphic_rep: AutomorphicRepresentation,
162 pub correspondence_type: LanglandsType,
164}
165impl LanglandsCorrespondence {
166 pub fn new(
168 gal: GaloisRepresentation,
169 aut: AutomorphicRepresentation,
170 kind: LanglandsType,
171 ) -> Self {
172 Self {
173 galois_rep: gal,
174 automorphic_rep: aut,
175 correspondence_type: kind,
176 }
177 }
178}
179#[derive(Debug, Clone)]
181pub struct NorthcottProperty {
182 pub space: String,
184 pub absolute: bool,
186}
187impl NorthcottProperty {
188 pub fn projective_space(n: usize) -> Self {
190 Self {
191 space: format!("P^{}", n),
192 absolute: true,
193 }
194 }
195 pub fn count_estimate_p1_rational(bound: f64) -> usize {
199 if bound < 1.0 {
200 return 0;
201 }
202 ((12.0 / std::f64::consts::PI.powi(2)) * bound * bound).round() as usize
203 }
204}
205#[derive(Debug, Clone, PartialEq, Eq)]
207pub struct AbelianVariety {
208 pub field: String,
210 pub dimension: usize,
212 pub is_simple: bool,
214 pub name: String,
216}
217impl AbelianVariety {
218 pub fn new(field: impl Into<String>, dimension: usize) -> Self {
220 Self {
221 field: field.into(),
222 dimension,
223 is_simple: false,
224 name: String::new(),
225 }
226 }
227 pub fn named(field: impl Into<String>, dimension: usize, name: impl Into<String>) -> Self {
229 Self {
230 field: field.into(),
231 dimension,
232 is_simple: false,
233 name: name.into(),
234 }
235 }
236 pub fn dimension(&self) -> usize {
238 self.dimension
239 }
240 pub fn tate_module_rank(&self) -> usize {
242 2 * self.dimension
243 }
244 pub fn trace_of_frobenius(&self, _prime: u64) -> i64 {
246 0
247 }
248 pub fn endomorphism_ring(&self) -> String {
250 if self.is_simple {
251 "Division algebra".to_string()
252 } else {
253 "Matrix algebra".to_string()
254 }
255 }
256 pub fn simple(mut self) -> Self {
258 self.is_simple = true;
259 self
260 }
261}
262#[derive(Debug, Clone)]
264pub struct AutomorphicRepresentation {
265 pub group: String,
267 pub field: String,
269 pub weight: Vec<i32>,
271 pub is_cuspidal: bool,
273}
274impl AutomorphicRepresentation {
275 pub fn new(group: impl Into<String>, field: impl Into<String>) -> Self {
277 Self {
278 group: group.into(),
279 field: field.into(),
280 weight: Vec::new(),
281 is_cuspidal: false,
282 }
283 }
284 pub fn modular_form_gl2(weight: i32, field: impl Into<String>) -> Self {
286 Self {
287 group: "GL_2".to_string(),
288 field: field.into(),
289 weight: vec![weight],
290 is_cuspidal: true,
291 }
292 }
293 pub fn local_components(&self) -> String {
295 format!("⊗_v π_v of {} over {}", self.group, self.field)
296 }
297}
298#[derive(Debug, Clone, PartialEq, Eq)]
300pub enum LanglandsType {
301 LocalGLn,
303 GlobalGL2,
305 Functoriality,
307 Geometric,
309}
310#[derive(Debug, Clone)]
312pub struct LogarithmicHeight {
313 pub absolute: AbsoluteHeight,
315}
316impl LogarithmicHeight {
317 pub fn from_absolute(h: AbsoluteHeight) -> Self {
319 Self { absolute: h }
320 }
321 pub fn of_rational(p: i64, q: u64) -> Self {
323 Self::from_absolute(AbsoluteHeight::of_rational(p, q))
324 }
325 pub fn value(&self) -> f64 {
327 self.absolute.value.ln()
328 }
329}
330#[allow(dead_code)]
332#[derive(Debug, Clone)]
333pub struct CondensedAbelianGroup {
334 pub label: String,
336 pub is_solid: bool,
338 pub is_discrete: bool,
340}
341#[allow(dead_code)]
342impl CondensedAbelianGroup {
343 pub fn discrete(label: impl Into<String>) -> Self {
345 Self {
346 label: label.into(),
347 is_solid: false,
348 is_discrete: true,
349 }
350 }
351 pub fn solid_free(profinite_set: impl Into<String>) -> Self {
353 Self {
354 label: format!("Z[{}]^solid", profinite_set.into()),
355 is_solid: true,
356 is_discrete: false,
357 }
358 }
359 pub fn solidify(mut self) -> Self {
361 self.is_solid = true;
362 self
363 }
364 pub fn solid_tensor_product(&self, other: &Self) -> String {
366 format!("{} ⊗_solid {}", self.label, other.label)
367 }
368 pub fn is_p_liquid(&self, p: f64) -> bool {
370 self.is_solid && p > 0.0 && p <= 1.0
371 }
372}
373#[allow(dead_code)]
375#[derive(Debug, Clone)]
376pub struct NeronModel {
377 pub variety: String,
379 pub dvr: String,
381 pub fraction_field: String,
383 pub reduction_type: NeronReductionType,
385 pub component_group_order: Option<u64>,
387}
388#[allow(dead_code)]
389impl NeronModel {
390 pub fn new(
392 variety: impl Into<String>,
393 dvr: impl Into<String>,
394 fraction_field: impl Into<String>,
395 reduction_type: NeronReductionType,
396 ) -> Self {
397 Self {
398 variety: variety.into(),
399 dvr: dvr.into(),
400 fraction_field: fraction_field.into(),
401 reduction_type,
402 component_group_order: None,
403 }
404 }
405 pub fn good_reduction(
407 variety: impl Into<String>,
408 dvr: impl Into<String>,
409 frac: impl Into<String>,
410 ) -> Self {
411 Self::new(variety, dvr, frac, NeronReductionType::Good)
412 }
413 pub fn semi_stable(
415 variety: impl Into<String>,
416 dvr: impl Into<String>,
417 frac: impl Into<String>,
418 ) -> Self {
419 Self::new(variety, dvr, frac, NeronReductionType::SemiStable)
420 }
421 pub fn with_component_group(mut self, order: u64) -> Self {
423 self.component_group_order = Some(order);
424 self
425 }
426 pub fn has_good_reduction(&self) -> bool {
428 self.reduction_type == NeronReductionType::Good
429 }
430 pub fn is_semi_stable(&self) -> bool {
432 matches!(
433 self.reduction_type,
434 NeronReductionType::Good
435 | NeronReductionType::SemiStable
436 | NeronReductionType::PurelyToric
437 )
438 }
439 pub fn tamagawa_number(&self) -> u64 {
441 self.component_group_order.unwrap_or(1)
442 }
443}
444#[allow(dead_code)]
446#[derive(Debug, Clone, PartialEq, Eq)]
447pub enum NeronReductionType {
448 Good,
450 SemiStable,
452 PurelyToric,
454 Additive,
456}
457#[derive(Debug, Clone)]
459pub struct EllipticCurve {
460 pub field: String,
462 pub a: i64,
464 pub b: i64,
466}
467impl EllipticCurve {
468 pub fn new(field: impl Into<String>, a: i64, b: i64) -> Self {
470 Self {
471 field: field.into(),
472 a,
473 b,
474 }
475 }
476 pub fn discriminant(&self) -> i64 {
478 -16 * (4 * self.a.pow(3) + 27 * self.b.pow(2))
479 }
480 pub fn is_non_singular(&self) -> bool {
482 self.discriminant() != 0
483 }
484 pub fn j_invariant(&self) -> Option<f64> {
486 let delta = self.discriminant();
487 if delta == 0 {
488 return None;
489 }
490 let numerator = -1728.0 * (4.0 * (self.a as f64)).powi(3);
491 Some(numerator / (delta as f64))
492 }
493 pub fn j_class(&self) -> String {
495 match self.j_invariant() {
496 Some(j) => format!("j = {:.4}", j),
497 None => "Singular (not an elliptic curve)".to_string(),
498 }
499 }
500}
501#[derive(Debug, Clone, PartialEq, Eq)]
503pub struct TateModule {
504 pub variety: String,
506 pub prime: u64,
508 pub rank: usize,
510}
511impl TateModule {
512 pub fn new(variety: impl Into<String>, prime: u64, dimension: usize) -> Self {
514 Self {
515 variety: variety.into(),
516 prime,
517 rank: 2 * dimension,
518 }
519 }
520}
521#[derive(Debug, Clone)]
523pub struct ShimuraDatum {
524 pub group: String,
526 pub domain: String,
528 pub reflex_field: String,
530}
531impl ShimuraDatum {
532 pub fn new(
534 group: impl Into<String>,
535 domain: impl Into<String>,
536 reflex_field: impl Into<String>,
537 ) -> Self {
538 Self {
539 group: group.into(),
540 domain: domain.into(),
541 reflex_field: reflex_field.into(),
542 }
543 }
544 pub fn gl2_upper_half_plane() -> Self {
546 Self::new("GL_2", "H (upper half-plane)", "Q")
547 }
548 pub fn siegel(g: usize) -> Self {
550 Self::new(
551 format!("GSp_{{2{}}}", g),
552 format!("H_{} (Siegel half-space)", g),
553 "Q",
554 )
555 }
556}
557#[derive(Debug, Clone)]
559pub struct CanonicalModel {
560 pub shimura_variety: ShimuraVariety,
562 pub reflex_field: String,
564}
565impl CanonicalModel {
566 pub fn new(variety: ShimuraVariety, reflex_field: impl Into<String>) -> Self {
568 Self {
569 shimura_variety: variety,
570 reflex_field: reflex_field.into(),
571 }
572 }
573}
574#[derive(Debug, Clone)]
576pub struct NearlyOrdinaryRepresentation {
577 pub rep: GaloisRepresentation,
579 pub prime: u64,
581}
582impl NearlyOrdinaryRepresentation {
583 pub fn new(rep: GaloisRepresentation, prime: u64) -> Self {
585 Self { rep, prime }
586 }
587}
588#[derive(Debug, Clone)]
590pub struct HeightFunction {
591 pub curve: String,
593 pub field: String,
595}
596impl HeightFunction {
597 pub fn neron_tate(curve: impl Into<String>, field: impl Into<String>) -> Self {
599 Self {
600 curve: curve.into(),
601 field: field.into(),
602 }
603 }
604 pub fn naive_height(x_num: i64, x_den: u64) -> f64 {
608 if x_den == 0 {
609 return 0.0;
610 }
611 0.5 * ((x_num.unsigned_abs()).max(x_den) as f64).ln()
612 }
613}
614#[allow(dead_code)]
616#[derive(Debug, Clone)]
617pub struct PerfectoidField {
618 pub name: String,
620 pub residue_char: u64,
622 pub is_alg_closed: bool,
624 pub tilt_name: String,
626}
627#[allow(dead_code)]
628impl PerfectoidField {
629 pub fn new(name: impl Into<String>, residue_char: u64, tilt_name: impl Into<String>) -> Self {
631 Self {
632 name: name.into(),
633 residue_char,
634 is_alg_closed: false,
635 tilt_name: tilt_name.into(),
636 }
637 }
638 pub fn c_p(p: u64) -> Self {
640 Self {
641 name: format!("C_{}", p),
642 residue_char: p,
643 is_alg_closed: true,
644 tilt_name: format!("C_{}^flat", p),
645 }
646 }
647 pub fn q_p_cyclotomic(p: u64) -> Self {
649 Self {
650 name: format!("Q_{}(zeta_{{p^inf}})", p),
651 residue_char: p,
652 is_alg_closed: false,
653 tilt_name: format!("F_{}((t^{{1/p^inf}}))", p),
654 }
655 }
656 pub fn residue_characteristic(&self) -> u64 {
658 self.residue_char
659 }
660 pub fn tilt_characteristic(&self) -> u64 {
662 self.residue_char
663 }
664 pub fn hodge_tate_description(&self, dim: usize) -> String {
666 format!(
667 "H^{{}} decomposes over {} as direct sum of dim {} C_p-spaces with Hodge-Tate weights",
668 self.name, dim
669 )
670 }
671}
672#[derive(Debug, Clone)]
674pub struct Isogeny {
675 pub source: String,
677 pub target: String,
679 pub degree: u64,
681}
682impl Isogeny {
683 pub fn new(source: impl Into<String>, target: impl Into<String>, degree: u64) -> Self {
685 Self {
686 source: source.into(),
687 target: target.into(),
688 degree,
689 }
690 }
691 pub fn multiplication_by_n(curve: impl Into<String>, n: u64) -> Self {
693 let c = curve.into();
694 Self {
695 source: c.clone(),
696 target: c,
697 degree: n * n,
698 }
699 }
700 pub fn is_endomorphism(&self) -> bool {
702 self.source == self.target
703 }
704}
705#[derive(Debug, Clone)]
707pub struct DualAbelianVariety {
708 pub variety: AbelianVariety,
710}
711impl DualAbelianVariety {
712 pub fn of(variety: AbelianVariety) -> Self {
714 Self { variety }
715 }
716 pub fn dimension(&self) -> usize {
718 self.variety.dimension
719 }
720}
721#[derive(Debug, Clone)]
723pub struct PolarizedAbelianVariety {
724 pub variety: AbelianVariety,
726 pub polarization_degree: u64,
728 pub is_principal: bool,
730}
731impl PolarizedAbelianVariety {
732 pub fn principally_polarized(variety: AbelianVariety) -> Self {
734 Self {
735 variety,
736 polarization_degree: 1,
737 is_principal: true,
738 }
739 }
740 pub fn polarized(variety: AbelianVariety, degree: u64) -> Self {
742 Self {
743 variety,
744 polarization_degree: degree,
745 is_principal: degree == 1,
746 }
747 }
748}
749#[derive(Debug, Clone)]
751pub struct BirchSwinnertonDyerData {
752 pub curve: String,
754 pub rank: usize,
756 pub regulator: f64,
758 pub sha_order: Option<u64>,
760 pub bsd_rank_verified: bool,
762}
763impl BirchSwinnertonDyerData {
764 pub fn new(curve: impl Into<String>, rank: usize, regulator: f64) -> Self {
766 Self {
767 curve: curve.into(),
768 rank,
769 regulator,
770 sha_order: None,
771 bsd_rank_verified: false,
772 }
773 }
774 pub fn leading_coefficient_prediction(&self) -> f64 {
779 let sha = self.sha_order.unwrap_or(1) as f64;
780 sha * self.regulator
781 }
782}
783#[derive(Debug, Clone)]
785pub struct ShimuraVariety {
786 pub datum: ShimuraDatum,
788 pub level: String,
790 pub complex_dimension: usize,
792}
793impl ShimuraVariety {
794 pub fn new(datum: ShimuraDatum, level: impl Into<String>, dim: usize) -> Self {
796 Self {
797 datum,
798 level: level.into(),
799 complex_dimension: dim,
800 }
801 }
802 pub fn modular_curve_y(n: usize) -> Self {
804 Self::new(ShimuraDatum::gl2_upper_half_plane(), format!("Γ({})", n), 1)
805 }
806}
807#[derive(Debug, Clone)]
809pub struct GaloisRepresentation {
810 pub galois_group: String,
812 pub dimension: usize,
814 pub coefficient_ring: String,
816 pub is_irreducible: bool,
818 pub is_geometric: bool,
820}
821impl GaloisRepresentation {
822 pub fn new(gal_group: impl Into<String>, dim: usize, ring: impl Into<String>) -> Self {
824 Self {
825 galois_group: gal_group.into(),
826 dimension: dim,
827 coefficient_ring: ring.into(),
828 is_irreducible: false,
829 is_geometric: false,
830 }
831 }
832 pub fn cyclotomic(ell: u64) -> Self {
834 let mut r = Self::new("G_Q", 1, format!("Z_{}", ell));
835 r.is_irreducible = true;
836 r.is_geometric = true;
837 r
838 }
839 pub fn from_elliptic_curve(curve: &str, ell: u64) -> Self {
841 let mut r = Self::new("G_Q", 2, format!("Z_{}", ell));
842 r.galois_group = format!("G_Q (from {})", curve);
843 r.is_geometric = true;
844 r
845 }
846 pub fn irreducible(mut self) -> Self {
848 self.is_irreducible = true;
849 self
850 }
851}
852#[derive(Debug, Clone)]
854pub struct TolimaniConjecture {
855 pub proved: bool,
857 pub proof_method: String,
859}
860impl TolimaniConjecture {
861 pub fn proved() -> Self {
863 Self {
864 proved: true,
865 proof_method: "o-minimality (Pila-Wilkie) + height bounds".to_string(),
866 }
867 }
868}
869#[derive(Debug, Clone, PartialEq, Eq)]
871pub struct TorsionPoint {
872 pub curve: String,
874 pub n: u64,
876 pub is_full_n_torsion: bool,
878}
879impl TorsionPoint {
880 pub fn full(curve: impl Into<String>, n: u64) -> Self {
882 Self {
883 curve: curve.into(),
884 n,
885 is_full_n_torsion: true,
886 }
887 }
888 pub fn size(&self) -> u64 {
890 if self.is_full_n_torsion {
891 self.n * self.n
892 } else {
893 self.n
894 }
895 }
896}
897#[derive(Debug, Clone)]
899pub struct FaltingsThm {
900 pub curve: String,
902 pub genus: usize,
904 pub field: String,
906 pub known_rational_points: Vec<String>,
908}
909impl FaltingsThm {
910 pub fn for_curve(curve: impl Into<String>, genus: usize, field: impl Into<String>) -> Self {
912 Self {
913 curve: curve.into(),
914 genus,
915 field: field.into(),
916 known_rational_points: Vec::new(),
917 }
918 }
919 pub fn finiteness_guaranteed(&self) -> bool {
921 self.genus >= 2
922 }
923 pub fn add_rational_point(&mut self, point: impl Into<String>) {
925 self.known_rational_points.push(point.into());
926 }
927 pub fn fermat_curve(n: usize, field: impl Into<String>) -> Self {
929 let genus = if n >= 3 { (n - 1) * (n - 2) / 2 } else { 0 };
930 Self::for_curve(format!("x^{} + y^{} = 1", n, n), genus, field)
931 }
932}