1use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::functions::*;
8use std::collections::HashMap;
9
10pub struct BousfieldLocalization {
14 pub homology_theory: String,
16 pub spectrum: String,
18 pub localized: String,
20}
21pub struct PeriodicityThm {
23 pub height: usize,
25 pub prime: u64,
27 pub periodicity_period: u64,
29}
30impl PeriodicityThm {
31 pub fn new(height: usize, prime: u64) -> Self {
33 let periodicity_period = 2 * (prime.pow(height as u32) - 1);
34 PeriodicityThm {
35 height,
36 prime,
37 periodicity_period,
38 }
39 }
40 pub fn vn_degree(&self) -> u64 {
42 self.periodicity_period
43 }
44}
45pub struct MoravaKTheory {
47 pub height: usize,
49 pub prime: u64,
51}
52impl MoravaKTheory {
53 pub fn new(height: usize, prime: u64) -> Self {
55 MoravaKTheory { height, prime }
56 }
57 pub fn periodicity(&self) -> u64 {
59 2 * (self.prime.pow(self.height as u32) - 1)
60 }
61 pub fn is_field_spectrum(&self) -> bool {
63 true
64 }
65}
66pub struct MoravaKGroup {
68 pub height: usize,
70 pub prime: u64,
72 pub spectrum: String,
74 pub graded_ranks: Vec<usize>,
76}
77impl MoravaKGroup {
78 pub fn new(height: usize, prime: u64, spectrum: impl Into<String>) -> Self {
80 MoravaKGroup {
81 height,
82 prime,
83 spectrum: spectrum.into(),
84 graded_ranks: Vec::new(),
85 }
86 }
87 pub fn set_rank(&mut self, degree: usize, rank: usize) {
89 if degree >= self.graded_ranks.len() {
90 self.graded_ranks.resize(degree + 1, 0);
91 }
92 self.graded_ranks[degree] = rank;
93 }
94 pub fn rank_in_degree(&self, degree: usize) -> usize {
96 self.graded_ranks.get(degree).copied().unwrap_or(0)
97 }
98 pub fn euler_characteristic(&self) -> i64 {
100 self.graded_ranks
101 .iter()
102 .enumerate()
103 .map(|(i, &r)| if i % 2 == 0 { r as i64 } else { -(r as i64) })
104 .sum()
105 }
106 pub fn is_acyclic(&self) -> bool {
108 self.graded_ranks.iter().all(|&r| r == 0)
109 }
110}
111pub struct AdamsSpectralSequence {
113 pub prime: u64,
115 pub spectrum: String,
117 pub e2_data: Vec<(usize, usize, usize)>,
119}
120impl AdamsSpectralSequence {
121 pub fn new(spectrum: impl Into<String>, prime: u64) -> Self {
123 AdamsSpectralSequence {
124 prime,
125 spectrum: spectrum.into(),
126 e2_data: Vec::new(),
127 }
128 }
129 pub fn add_e2_group(&mut self, s: usize, stem: usize, rank: usize) {
131 self.e2_data.push((s, stem, rank));
132 }
133 pub fn total_rank_in_stem(&self, stem: usize) -> usize {
135 self.e2_data
136 .iter()
137 .filter(|&&(_, st, _)| st == stem)
138 .map(|&(_, _, r)| r)
139 .sum()
140 }
141 pub fn rank_at(&self, s: usize, stem: usize) -> usize {
143 self.e2_data
144 .iter()
145 .find(|&&(si, st, _)| si == s && st == stem)
146 .map(|&(_, _, r)| r)
147 .unwrap_or(0)
148 }
149 pub fn sphere_at_2() -> Self {
151 let mut ss = AdamsSpectralSequence::new("S^0", 2);
152 ss.add_e2_group(0, 0, 1);
153 ss.add_e2_group(1, 1, 1);
154 ss.add_e2_group(2, 2, 1);
155 ss.add_e2_group(1, 3, 1);
156 ss.add_e2_group(3, 3, 1);
157 ss.add_e2_group(1, 7, 1);
158 ss
159 }
160}
161pub struct EllipticCurveOverRing {
163 pub ring: String,
165 pub a: i64,
167 pub b: i64,
169}
170impl EllipticCurveOverRing {
171 pub fn is_nonsingular(&self) -> bool {
173 4 * self.a.pow(3) + 27 * self.b.pow(2) != 0
174 }
175 pub fn j_invariant_numerator(&self) -> i64 {
177 -1728 * (4 * self.a).pow(3)
178 }
179}
180pub struct EllipticCohomologyTheory {
182 pub name: String,
184 pub elliptic_curve: EllipticCurveOverRing,
186 pub is_e_infty: bool,
188}
189#[allow(dead_code)]
191#[derive(Debug, Clone)]
192pub struct SpectralScheme {
193 pub name: String,
195 pub classical_truncation: String,
197 pub cotangent_dim: Option<usize>,
199 pub is_dci: bool,
201}
202#[allow(dead_code)]
203impl SpectralScheme {
204 pub fn new(name: &str, classical: &str) -> Self {
206 SpectralScheme {
207 name: name.to_string(),
208 classical_truncation: classical.to_string(),
209 cotangent_dim: None,
210 is_dci: false,
211 }
212 }
213 pub fn with_cotangent_dim(mut self, d: usize) -> Self {
215 self.cotangent_dim = Some(d);
216 self
217 }
218 pub fn as_dci(mut self) -> Self {
220 self.is_dci = true;
221 self
222 }
223 pub fn tor_amplitude(&self) -> String {
225 match self.cotangent_dim {
226 Some(d) => format!("[0, {}]", d),
227 None => "unknown".to_string(),
228 }
229 }
230 pub fn is_spectral_dm_stack(&self) -> bool {
232 matches!(self.cotangent_dim, Some(0))
233 }
234 pub fn spectrum_description(&self) -> String {
236 format!("Spec({}) as E_β-ring scheme", self.name)
237 }
238}
239#[allow(dead_code)]
241#[derive(Debug, Clone)]
242pub struct ChromaticTowerLevel {
243 pub height: usize,
245 pub prime: usize,
247 pub ln_sphere_known: bool,
249 pub pi_low: Vec<(i32, String)>,
251}
252#[allow(dead_code)]
253impl ChromaticTowerLevel {
254 pub fn new(height: usize, prime: usize) -> Self {
256 ChromaticTowerLevel {
257 height,
258 prime,
259 ln_sphere_known: height <= 2,
260 pi_low: Vec::new(),
261 }
262 }
263 pub fn add_homotopy_group(&mut self, degree: i32, description: String) {
265 self.pi_low.push((degree, description));
266 }
267 pub fn bousfield_class(&self) -> String {
269 format!("<E({},{})>", self.prime, self.height)
270 }
271 pub fn monochromatic_nontrivial(&self) -> bool {
273 self.height >= 1
274 }
275 pub fn periodicity_element(&self) -> String {
277 if self.height == 0 {
278 "1 (no periodicity)".to_string()
279 } else {
280 format!("v_{}", self.height)
281 }
282 }
283 pub fn periodicity_degree(&self) -> Option<usize> {
285 if self.prime < 2 {
286 return None;
287 }
288 Some(2 * (self.prime.pow(self.height as u32) - 1))
289 }
290}
291pub struct BPAdamsSpectralSequence {
295 pub spectrum: String,
297 pub prime: u64,
299 pub converges: bool,
301}
302impl BPAdamsSpectralSequence {
303 pub fn new(spectrum: impl Into<String>, prime: u64) -> Self {
305 BPAdamsSpectralSequence {
306 spectrum: spectrum.into(),
307 prime,
308 converges: true,
309 }
310 }
311}
312pub struct ChromaticConvergence {
314 pub spectrum: String,
316 pub verified: bool,
318}
319pub struct AdamsNovikovSS {
323 pub spectrum: String,
325 pub prime: u64,
327 pub e2_page: Vec<(usize, usize, usize)>,
329}
330impl AdamsNovikovSS {
331 pub fn e2_rank(&self, s: usize, t: usize) -> usize {
333 self.e2_page
334 .iter()
335 .find(|&&(si, ti, _)| si == s && ti == t)
336 .map(|&(_, _, r)| r)
337 .unwrap_or(0)
338 }
339 pub fn stem(&self, t: usize, s: usize) -> Option<i64> {
341 if t >= s {
342 Some((t - s) as i64)
343 } else {
344 None
345 }
346 }
347}
348pub struct TopologicalCyclicHomologyData {
350 pub ring_spectrum: String,
352 pub prime: u64,
354 pub uses_bokstedt_periodicity: bool,
356}
357impl TopologicalCyclicHomologyData {
358 pub fn new(ring_spectrum: impl Into<String>, prime: u64) -> Self {
360 TopologicalCyclicHomologyData {
361 ring_spectrum: ring_spectrum.into(),
362 prime,
363 uses_bokstedt_periodicity: false,
364 }
365 }
366 pub fn cyclotomic_trace_exists(&self) -> bool {
368 true
369 }
370}
371pub struct LandweberExactFunctor {
376 pub ring: String,
378 pub is_exact: bool,
380 pub regularity_depth: usize,
382}
383impl LandweberExactFunctor {
384 pub fn new(ring: impl Into<String>, depth: usize) -> Self {
386 LandweberExactFunctor {
387 ring: ring.into(),
388 is_exact: depth > 0,
389 regularity_depth: depth,
390 }
391 }
392 pub fn produces_cohomology_theory(&self) -> bool {
394 self.is_exact
395 }
396}
397pub struct LubinTateSpaceData {
399 pub height: usize,
401 pub prime: u64,
403 pub e_theory_computed: bool,
405}
406impl LubinTateSpaceData {
407 pub fn new(height: usize, prime: u64) -> Self {
409 LubinTateSpaceData {
410 height,
411 prime,
412 e_theory_computed: false,
413 }
414 }
415 pub fn num_deformation_params(&self) -> usize {
417 if self.height > 0 {
418 self.height - 1
419 } else {
420 0
421 }
422 }
423}
424pub struct BrownPetersonBP {
428 pub prime: u64,
430 pub max_height: usize,
432}
433impl BrownPetersonBP {
434 pub fn new(prime: u64, max_height: usize) -> Self {
436 BrownPetersonBP { prime, max_height }
437 }
438 pub fn vn_degree(&self, n: usize) -> u64 {
440 2 * (self.prime.pow(n as u32) - 1)
441 }
442 pub fn generators(&self) -> Vec<(String, u64)> {
444 (1..=self.max_height)
445 .map(|n| (format!("v_{n}"), self.vn_degree(n)))
446 .collect()
447 }
448}
449pub struct WittVectorRing {
453 pub base_ring: String,
455 pub prime: u64,
457 pub length: usize,
459}
460impl WittVectorRing {
461 pub fn new(base_ring: impl Into<String>, prime: u64, length: usize) -> Self {
463 WittVectorRing {
464 base_ring: base_ring.into(),
465 prime,
466 length,
467 }
468 }
469 pub fn add(&self, a: &[i64], b: &[i64]) -> Vec<i64> {
471 let len = self.length.min(a.len()).min(b.len());
472 let p = self.prime as i64;
473 let mut result = vec![0i64; len];
474 let mut carry = 0i64;
475 for i in 0..len {
476 let sum = a[i] + b[i] + carry;
477 result[i] = sum % p;
478 carry = sum / p;
479 }
480 result
481 }
482 pub fn frobenius_shift(components: &[i64]) -> Vec<i64> {
484 if components.is_empty() {
485 vec![]
486 } else {
487 components[1..].to_vec()
488 }
489 }
490 pub fn verschiebung(components: &[i64]) -> Vec<i64> {
492 let mut result = vec![0i64];
493 result.extend_from_slice(components);
494 result
495 }
496}
497pub struct FormalGroupLaw {
502 pub coefficients: Vec<Vec<i64>>,
504 pub truncation: usize,
506}
507impl FormalGroupLaw {
508 pub fn additive(truncation: usize) -> Self {
510 let mut coefficients = vec![vec![0i64; truncation + 1]; truncation + 1];
511 if truncation >= 1 {
512 coefficients[1][0] = 1;
513 coefficients[0][1] = 1;
514 }
515 FormalGroupLaw {
516 coefficients,
517 truncation,
518 }
519 }
520 pub fn multiplicative(truncation: usize) -> Self {
522 let mut coefficients = vec![vec![0i64; truncation + 1]; truncation + 1];
523 if truncation >= 1 {
524 coefficients[1][0] = 1;
525 coefficients[0][1] = 1;
526 }
527 if truncation >= 2 {
528 coefficients[1][1] = 1;
529 }
530 FormalGroupLaw {
531 coefficients,
532 truncation,
533 }
534 }
535 pub fn satisfies_identity(&self) -> bool {
537 self.truncation >= 1 && self.coefficients[1][0] == 1
538 }
539 pub fn height_at_prime(&self, _p: u64) -> Option<usize> {
541 if self.truncation >= 2 && self.coefficients[1][1] != 0 {
542 Some(1)
543 } else {
544 None
545 }
546 }
547}
548pub struct TopologicalHochschildHomologyData {
550 pub ring_spectrum: String,
552 pub is_e_infty: bool,
554 pub homotopy_groups: Vec<(usize, usize)>,
556}
557impl TopologicalHochschildHomologyData {
558 pub fn new(ring_spectrum: impl Into<String>, is_e_infty: bool) -> Self {
560 TopologicalHochschildHomologyData {
561 ring_spectrum: ring_spectrum.into(),
562 is_e_infty,
563 homotopy_groups: Vec::new(),
564 }
565 }
566 pub fn add_homotopy_group(&mut self, degree: usize, rank: usize) {
568 self.homotopy_groups.push((degree, rank));
569 }
570 pub fn pi_rank(&self, d: usize) -> usize {
572 self.homotopy_groups
573 .iter()
574 .find(|&&(deg, _)| deg == d)
575 .map(|&(_, r)| r)
576 .unwrap_or(0)
577 }
578}
579pub struct VnSelfMapData {
583 pub height: usize,
585 pub prime: u64,
587 pub period: u64,
589 pub multiplicity: u64,
591}
592impl VnSelfMapData {
593 pub fn new(height: usize, prime: u64, multiplicity: u64) -> Self {
595 let base_period = 2 * (prime.pow(height as u32) - 1);
596 VnSelfMapData {
597 height,
598 prime,
599 period: base_period * multiplicity,
600 multiplicity,
601 }
602 }
603 pub fn telescope_name(&self, spectrum: &str) -> String {
605 format!("v_{}^{{-1}} {}", self.height, spectrum)
606 }
607}
608pub struct LevelStructure {
610 pub level: usize,
612 pub structure_type: String,
614}
615impl LevelStructure {
616 pub fn gamma_0(n: usize) -> Self {
618 LevelStructure {
619 level: n,
620 structure_type: "Gamma_0".to_string(),
621 }
622 }
623 pub fn gamma_1(n: usize) -> Self {
625 LevelStructure {
626 level: n,
627 structure_type: "Gamma_1".to_string(),
628 }
629 }
630}
631#[allow(dead_code)]
633#[derive(Debug, Clone)]
634pub struct MoravaKData {
635 pub height: usize,
637 pub prime: usize,
639 pub coeff_ring: String,
641}
642#[allow(dead_code)]
643impl MoravaKData {
644 pub fn new(height: usize, prime: usize) -> Self {
646 let coeff_ring = if height == 0 {
647 format!("F_{}", prime)
648 } else {
649 format!("F_{}[v_{}, v_{}^(-1)]", prime, height, height)
650 };
651 MoravaKData {
652 height,
653 prime,
654 coeff_ring,
655 }
656 }
657 pub fn vn_degree(&self) -> usize {
659 2 * (self.prime.pow(self.height as u32) - 1)
660 }
661 pub fn coeff_of_point_is_fp(&self) -> bool {
663 self.height >= 1
664 }
665 pub fn satisfies_kunneth(&self) -> bool {
667 true
668 }
669 pub fn bcp_dimension(&self) -> usize {
672 if self.height == 0 {
673 0
674 } else {
675 2 * self.prime.pow((self.height - 1) as u32)
676 }
677 }
678 pub fn associated_e_theory(&self) -> String {
680 format!(
681 "E({},{}) (Morava E-theory, formal group over W(F_{}^{})",
682 self.prime, self.height, self.prime, self.height
683 )
684 }
685}
686pub struct ChromaticComplexityData {
690 pub spectrum: String,
692 pub acyclic_below: Vec<bool>,
694}
695impl ChromaticComplexityData {
696 pub fn new(spectrum: impl Into<String>) -> Self {
698 ChromaticComplexityData {
699 spectrum: spectrum.into(),
700 acyclic_below: Vec::new(),
701 }
702 }
703 pub fn set_acyclic_at(&mut self, n: usize) {
705 if n >= self.acyclic_below.len() {
706 self.acyclic_below.resize(n + 1, false);
707 }
708 self.acyclic_below[n] = true;
709 }
710 pub fn type_estimate(&self) -> Option<usize> {
713 for (n, &acyclic) in self.acyclic_below.iter().enumerate() {
714 if !acyclic {
715 return Some(n);
716 }
717 }
718 if self.acyclic_below.is_empty() {
719 None
720 } else {
721 Some(self.acyclic_below.len())
722 }
723 }
724 pub fn complexity(&self) -> usize {
726 self.type_estimate().unwrap_or(0)
727 }
728}
729pub struct ModularFormSpectrum {
731 pub weight: usize,
733 pub level: usize,
735 pub is_cusp_form: bool,
737}
738impl ModularFormSpectrum {
739 pub fn cusp_forms(&self) -> bool {
741 self.is_cusp_form
742 }
743 pub fn degree(&self) -> usize {
745 2 * self.weight
746 }
747 pub fn weight(&self) -> usize {
749 self.weight
750 }
751}
752pub struct LazardRing {
756 pub generators: Vec<(usize, String)>,
758}
759impl LazardRing {
760 pub fn new(max_degree: usize) -> Self {
762 let generators = (1..=max_degree / 2)
763 .map(|i| (2 * i, format!("a_{i}")))
764 .collect();
765 LazardRing { generators }
766 }
767 pub fn generators_of_degree(&self, d: usize) -> Vec<&str> {
769 self.generators
770 .iter()
771 .filter(|(deg, _)| *deg == d)
772 .map(|(_, name)| name.as_str())
773 .collect()
774 }
775}
776#[allow(dead_code)]
778#[derive(Debug, Clone)]
779pub struct BPCohomologyData {
780 pub prime: usize,
782 pub vn_generators: Vec<(usize, usize)>,
784 pub bp_ranks: Vec<(i32, usize)>,
786}
787#[allow(dead_code)]
788impl BPCohomologyData {
789 pub fn new(prime: usize, max_n: usize) -> Self {
791 let vn_generators = (0..=max_n)
792 .map(|i| {
793 let deg = if i == 0 {
794 2
795 } else {
796 2 * (prime.pow(i as u32) - 1)
797 };
798 (i, deg)
799 })
800 .collect();
801 BPCohomologyData {
802 prime,
803 vn_generators,
804 bp_ranks: Vec::new(),
805 }
806 }
807 pub fn vn_degree(&self, n: usize) -> Option<usize> {
809 self.vn_generators
810 .iter()
811 .find(|&&(i, _)| i == n)
812 .map(|&(_, d)| d)
813 }
814 pub fn add_bp_rank(&mut self, degree: i32, rank: usize) {
816 self.bp_ranks.push((degree, rank));
817 }
818 pub fn rank_in_degree(&self, d: i32) -> usize {
820 self.bp_ranks
821 .iter()
822 .filter(|&&(deg, _)| deg == d)
823 .map(|&(_, r)| r)
824 .sum()
825 }
826 pub fn coefficient_ring(&self) -> String {
828 let gens: Vec<String> = self
829 .vn_generators
830 .iter()
831 .map(|&(i, _)| format!("v_{}", i))
832 .collect();
833 format!("Z_({})[{}]", self.prime, gens.join(", "))
834 }
835}
836pub struct LocalSpectra {
838 pub homology_theory: String,
840 pub local_spectra: Vec<String>,
842}
843impl LocalSpectra {
844 pub fn is_local(&self, name: &str) -> bool {
846 self.local_spectra.iter().any(|s| s == name)
847 }
848}
849pub struct ChromaticFiltration {
853 pub spectrum: String,
855 pub layers: Vec<String>,
857 pub prime: u64,
859}
860impl ChromaticFiltration {
861 pub fn layer(&self, n: usize) -> Option<&str> {
863 self.layers.get(n).map(String::as_str)
864 }
865 pub fn converges_at(&self, max_n: usize) -> bool {
867 self.layers.len() > max_n
868 }
869}
870pub struct AcyclicMorphism {
872 pub source: String,
874 pub target: String,
876 pub acyclic: bool,
878}
879pub struct MoravaStabilizerGroupData {
881 pub height: usize,
883 pub prime: u64,
885 pub center_order_mod: u64,
887}
888impl MoravaStabilizerGroupData {
889 pub fn new(height: usize, prime: u64) -> Self {
891 let center_order_mod = prime.pow(height as u32) - 1;
892 MoravaStabilizerGroupData {
893 height,
894 prime,
895 center_order_mod,
896 }
897 }
898 pub fn center_index(&self) -> u64 {
900 self.center_order_mod
901 }
902}
903pub struct TopologicalModularForms {
907 pub is_connective: bool,
909 pub is_compactified: bool,
911}
912impl TopologicalModularForms {
913 pub fn connective() -> Self {
915 TopologicalModularForms {
916 is_connective: true,
917 is_compactified: false,
918 }
919 }
920 pub fn periodic() -> Self {
922 TopologicalModularForms {
923 is_connective: false,
924 is_compactified: false,
925 }
926 }
927}
928pub struct OrientationData {
930 pub theory: String,
932 pub first_chern_class: i64,
934}
935#[allow(dead_code)]
937#[derive(Debug, Clone)]
938pub struct LambdaRingElement {
939 pub adams_ops: Vec<f64>,
941 pub value: f64,
943}
944#[allow(dead_code)]
945impl LambdaRingElement {
946 pub fn new(value: f64, degree: usize) -> Self {
948 let adams_ops = (1..=degree).map(|k| (k as f64) * value).collect();
949 LambdaRingElement { adams_ops, value }
950 }
951 pub fn adams_op(&self, k: usize) -> Option<f64> {
953 if k == 0 || k > self.adams_ops.len() {
954 None
955 } else {
956 Some(self.adams_ops[k - 1])
957 }
958 }
959 pub fn add(&self, other: &LambdaRingElement) -> LambdaRingElement {
961 let degree = self.adams_ops.len().min(other.adams_ops.len());
962 let adams_ops = (0..degree)
963 .map(|i| self.adams_ops[i] + other.adams_ops[i])
964 .collect();
965 LambdaRingElement {
966 adams_ops,
967 value: self.value + other.value,
968 }
969 }
970 pub fn tensor(&self, other: &LambdaRingElement) -> LambdaRingElement {
972 let degree = self.adams_ops.len().min(other.adams_ops.len());
973 let adams_ops = (0..degree)
974 .map(|i| self.adams_ops[i] * other.adams_ops[i])
975 .collect();
976 LambdaRingElement {
977 adams_ops,
978 value: self.value * other.value,
979 }
980 }
981 pub fn check_composition(&self, m: usize, n: usize) -> bool {
983 let mn = m * n;
984 if mn > self.adams_ops.len() || m > self.adams_ops.len() || n > self.adams_ops.len() {
985 return true;
986 }
987 let psi_mn_direct = mn as f64 * self.value;
988 let psi_mn_via_comp = m as f64 * (n as f64 * self.value);
989 (psi_mn_direct - psi_mn_via_comp).abs() < 1e-10
990 }
991}
992pub struct DescentData {
996 pub spectrum: String,
998 pub group: String,
1000 pub hfp_computed: bool,
1002}
1003pub struct MoravaETheory {
1005 pub height: usize,
1007 pub prime: u64,
1009 pub formal_group_name: String,
1011 pub is_e_infty_ring: bool,
1013}
1014impl MoravaETheory {
1015 pub fn new(height: usize, prime: u64) -> Self {
1017 MoravaETheory {
1018 height,
1019 prime,
1020 formal_group_name: format!("Gamma_{height}"),
1021 is_e_infty_ring: true,
1022 }
1023 }
1024 pub fn periodicity(&self) -> u64 {
1026 2 * (self.prime.pow(self.height as u32) - 1)
1027 }
1028}
1029pub struct HondaFormalGroup {
1033 pub height: usize,
1035 pub prime: u64,
1037}
1038impl HondaFormalGroup {
1039 pub fn new(height: usize, prime: u64) -> Self {
1041 HondaFormalGroup { height, prime }
1042 }
1043 pub fn p_series_degree(&self) -> u64 {
1045 self.prime.pow(self.height as u32)
1046 }
1047 pub fn isomorphic_to(&self, other: &HondaFormalGroup) -> bool {
1049 self.height == other.height && self.prime == other.prime
1050 }
1051}
1052#[allow(dead_code)]
1054#[derive(Debug, Clone)]
1055pub struct FormalGroupDeformation {
1056 pub height: usize,
1058 pub lt_parameters: Vec<f64>,
1060 pub char_p: usize,
1062}
1063#[allow(dead_code)]
1064impl FormalGroupDeformation {
1065 pub fn universal(height: usize, char_p: usize) -> Self {
1067 let lt_parameters = vec![0.0; height.saturating_sub(1)];
1068 FormalGroupDeformation {
1069 height,
1070 lt_parameters,
1071 char_p,
1072 }
1073 }
1074 pub fn deformation_ring_dim(&self) -> usize {
1076 self.height.saturating_sub(1)
1077 }
1078 pub fn set_lt_param(&mut self, i: usize, val: f64) {
1080 if i < self.lt_parameters.len() {
1081 self.lt_parameters[i] = val;
1082 }
1083 }
1084 pub fn is_lubin_tate(&self) -> bool {
1086 self.height >= 1 && self.char_p >= 2
1087 }
1088 pub fn morava_stabilizer_group(&self) -> String {
1090 format!(
1091 "S_{} = Aut(Ξ_{}^{{1}}) over F_{}",
1092 self.height, self.height, self.char_p
1093 )
1094 }
1095 pub fn hasse_invariant_vanishes(&self) -> bool {
1097 self.height >= 2
1098 }
1099}
1100pub struct LocalizationUnit {
1102 pub constructed: bool,
1104 pub is_e_local_equiv: bool,
1106}
1107#[allow(dead_code)]
1110#[derive(Debug, Clone)]
1111pub struct FglArithmetic {
1112 pub coeffs: std::collections::HashMap<(usize, usize), f64>,
1114 pub max_deg: usize,
1116 pub name: String,
1118}
1119#[allow(dead_code)]
1120impl FglArithmetic {
1121 pub fn additive(max_deg: usize) -> Self {
1123 let mut coeffs = std::collections::HashMap::new();
1124 coeffs.insert((1, 0), 1.0);
1125 coeffs.insert((0, 1), 1.0);
1126 FglArithmetic {
1127 coeffs,
1128 max_deg,
1129 name: "Additive".to_string(),
1130 }
1131 }
1132 pub fn multiplicative(max_deg: usize) -> Self {
1134 let mut coeffs = std::collections::HashMap::new();
1135 coeffs.insert((1, 0), 1.0);
1136 coeffs.insert((0, 1), 1.0);
1137 coeffs.insert((1, 1), 1.0);
1138 FglArithmetic {
1139 coeffs,
1140 max_deg,
1141 name: "Multiplicative".to_string(),
1142 }
1143 }
1144 pub fn evaluate(&self, x: f64, y: f64) -> f64 {
1146 let mut result = 0.0;
1147 for (&(i, j), &a) in &self.coeffs {
1148 if i + j <= self.max_deg {
1149 result += a * x.powi(i as i32) * y.powi(j as i32);
1150 }
1151 }
1152 result
1153 }
1154 pub fn is_commutative_approx(&self, tol: f64) -> bool {
1156 let samples = [(0.1, 0.2), (0.3, 0.4), (0.05, 0.15)];
1157 for &(x, y) in &samples {
1158 let fxy = self.evaluate(x, y);
1159 let fyx = self.evaluate(y, x);
1160 if (fxy - fyx).abs() > tol {
1161 return false;
1162 }
1163 }
1164 true
1165 }
1166 pub fn coeff(&self, i: usize, j: usize) -> f64 {
1168 *self.coeffs.get(&(i, j)).unwrap_or(&0.0)
1169 }
1170 pub fn set_coeff(&mut self, i: usize, j: usize, val: f64) {
1172 if i + j <= self.max_deg {
1173 self.coeffs.insert((i, j), val);
1174 }
1175 }
1176 pub fn p_series(&self, p: usize, x: f64) -> f64 {
1178 if p == 0 {
1179 return 0.0;
1180 }
1181 let mut acc = x;
1182 for _ in 1..p {
1183 acc = self.evaluate(acc, x);
1184 }
1185 acc
1186 }
1187 pub fn is_height_one_approx(&self) -> bool {
1189 let x = 0.01f64;
1190 let two_series = self.p_series(2, x);
1191 two_series.abs() < 0.001
1192 }
1193}
1194#[allow(dead_code)]
1196#[derive(Debug, Clone)]
1197pub struct NilpotenceData {
1198 pub element: String,
1200 pub is_nilpotent: bool,
1202 pub nilpotency_exponent: Option<usize>,
1204 pub prime: usize,
1206}
1207#[allow(dead_code)]
1208impl NilpotenceData {
1209 pub fn new(element: &str, prime: usize) -> Self {
1211 NilpotenceData {
1212 element: element.to_string(),
1213 is_nilpotent: false,
1214 nilpotency_exponent: None,
1215 prime,
1216 }
1217 }
1218 pub fn set_nilpotent(&mut self, exp: usize) {
1220 self.is_nilpotent = true;
1221 self.nilpotency_exponent = Some(exp);
1222 }
1223 pub fn satisfies_nishida(&self) -> bool {
1225 self.is_nilpotent
1226 }
1227 pub fn detecting_filtration(&self) -> String {
1229 if self.is_nilpotent {
1230 format!("Detected in Adams filtration (prime {})", self.prime)
1231 } else {
1232 "Not nilpotent or unknown".to_string()
1233 }
1234 }
1235}
1236pub struct ChromaticSS {
1240 pub spectrum: String,
1242 pub prime: u64,
1244 pub monochromatic_layers: Vec<Vec<usize>>,
1246}
1247impl ChromaticSS {
1248 pub fn e1_rank(&self, n: usize, d: usize) -> usize {
1250 self.monochromatic_layers
1251 .get(n)
1252 .and_then(|layer| layer.get(d))
1253 .copied()
1254 .unwrap_or(0)
1255 }
1256}
1257pub struct ThickSubcategoryData {
1261 pub index: usize,
1263 pub prime: u64,
1265 pub members: Vec<String>,
1267}
1268impl ThickSubcategoryData {
1269 pub fn new(index: usize, prime: u64) -> Self {
1271 ThickSubcategoryData {
1272 index,
1273 prime,
1274 members: Vec::new(),
1275 }
1276 }
1277 pub fn add_member(&mut self, name: impl Into<String>) {
1279 self.members.push(name.into());
1280 }
1281 pub fn contains(&self, name: &str) -> bool {
1283 self.members.iter().any(|m| m == name)
1284 }
1285}