use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::functions::*;
use std::collections::HashMap;
pub struct BousfieldLocalization {
pub homology_theory: String,
pub spectrum: String,
pub localized: String,
}
pub struct PeriodicityThm {
pub height: usize,
pub prime: u64,
pub periodicity_period: u64,
}
impl PeriodicityThm {
pub fn new(height: usize, prime: u64) -> Self {
let periodicity_period = 2 * (prime.pow(height as u32) - 1);
PeriodicityThm {
height,
prime,
periodicity_period,
}
}
pub fn vn_degree(&self) -> u64 {
self.periodicity_period
}
}
pub struct MoravaKTheory {
pub height: usize,
pub prime: u64,
}
impl MoravaKTheory {
pub fn new(height: usize, prime: u64) -> Self {
MoravaKTheory { height, prime }
}
pub fn periodicity(&self) -> u64 {
2 * (self.prime.pow(self.height as u32) - 1)
}
pub fn is_field_spectrum(&self) -> bool {
true
}
}
pub struct MoravaKGroup {
pub height: usize,
pub prime: u64,
pub spectrum: String,
pub graded_ranks: Vec<usize>,
}
impl MoravaKGroup {
pub fn new(height: usize, prime: u64, spectrum: impl Into<String>) -> Self {
MoravaKGroup {
height,
prime,
spectrum: spectrum.into(),
graded_ranks: Vec::new(),
}
}
pub fn set_rank(&mut self, degree: usize, rank: usize) {
if degree >= self.graded_ranks.len() {
self.graded_ranks.resize(degree + 1, 0);
}
self.graded_ranks[degree] = rank;
}
pub fn rank_in_degree(&self, degree: usize) -> usize {
self.graded_ranks.get(degree).copied().unwrap_or(0)
}
pub fn euler_characteristic(&self) -> i64 {
self.graded_ranks
.iter()
.enumerate()
.map(|(i, &r)| if i % 2 == 0 { r as i64 } else { -(r as i64) })
.sum()
}
pub fn is_acyclic(&self) -> bool {
self.graded_ranks.iter().all(|&r| r == 0)
}
}
pub struct AdamsSpectralSequence {
pub prime: u64,
pub spectrum: String,
pub e2_data: Vec<(usize, usize, usize)>,
}
impl AdamsSpectralSequence {
pub fn new(spectrum: impl Into<String>, prime: u64) -> Self {
AdamsSpectralSequence {
prime,
spectrum: spectrum.into(),
e2_data: Vec::new(),
}
}
pub fn add_e2_group(&mut self, s: usize, stem: usize, rank: usize) {
self.e2_data.push((s, stem, rank));
}
pub fn total_rank_in_stem(&self, stem: usize) -> usize {
self.e2_data
.iter()
.filter(|&&(_, st, _)| st == stem)
.map(|&(_, _, r)| r)
.sum()
}
pub fn rank_at(&self, s: usize, stem: usize) -> usize {
self.e2_data
.iter()
.find(|&&(si, st, _)| si == s && st == stem)
.map(|&(_, _, r)| r)
.unwrap_or(0)
}
pub fn sphere_at_2() -> Self {
let mut ss = AdamsSpectralSequence::new("S^0", 2);
ss.add_e2_group(0, 0, 1);
ss.add_e2_group(1, 1, 1);
ss.add_e2_group(2, 2, 1);
ss.add_e2_group(1, 3, 1);
ss.add_e2_group(3, 3, 1);
ss.add_e2_group(1, 7, 1);
ss
}
}
pub struct EllipticCurveOverRing {
pub ring: String,
pub a: i64,
pub b: i64,
}
impl EllipticCurveOverRing {
pub fn is_nonsingular(&self) -> bool {
4 * self.a.pow(3) + 27 * self.b.pow(2) != 0
}
pub fn j_invariant_numerator(&self) -> i64 {
-1728 * (4 * self.a).pow(3)
}
}
pub struct EllipticCohomologyTheory {
pub name: String,
pub elliptic_curve: EllipticCurveOverRing,
pub is_e_infty: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct SpectralScheme {
pub name: String,
pub classical_truncation: String,
pub cotangent_dim: Option<usize>,
pub is_dci: bool,
}
#[allow(dead_code)]
impl SpectralScheme {
pub fn new(name: &str, classical: &str) -> Self {
SpectralScheme {
name: name.to_string(),
classical_truncation: classical.to_string(),
cotangent_dim: None,
is_dci: false,
}
}
pub fn with_cotangent_dim(mut self, d: usize) -> Self {
self.cotangent_dim = Some(d);
self
}
pub fn as_dci(mut self) -> Self {
self.is_dci = true;
self
}
pub fn tor_amplitude(&self) -> String {
match self.cotangent_dim {
Some(d) => format!("[0, {}]", d),
None => "unknown".to_string(),
}
}
pub fn is_spectral_dm_stack(&self) -> bool {
matches!(self.cotangent_dim, Some(0))
}
pub fn spectrum_description(&self) -> String {
format!("Spec({}) as E_∞-ring scheme", self.name)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ChromaticTowerLevel {
pub height: usize,
pub prime: usize,
pub ln_sphere_known: bool,
pub pi_low: Vec<(i32, String)>,
}
#[allow(dead_code)]
impl ChromaticTowerLevel {
pub fn new(height: usize, prime: usize) -> Self {
ChromaticTowerLevel {
height,
prime,
ln_sphere_known: height <= 2,
pi_low: Vec::new(),
}
}
pub fn add_homotopy_group(&mut self, degree: i32, description: String) {
self.pi_low.push((degree, description));
}
pub fn bousfield_class(&self) -> String {
format!("<E({},{})>", self.prime, self.height)
}
pub fn monochromatic_nontrivial(&self) -> bool {
self.height >= 1
}
pub fn periodicity_element(&self) -> String {
if self.height == 0 {
"1 (no periodicity)".to_string()
} else {
format!("v_{}", self.height)
}
}
pub fn periodicity_degree(&self) -> Option<usize> {
if self.prime < 2 {
return None;
}
Some(2 * (self.prime.pow(self.height as u32) - 1))
}
}
pub struct BPAdamsSpectralSequence {
pub spectrum: String,
pub prime: u64,
pub converges: bool,
}
impl BPAdamsSpectralSequence {
pub fn new(spectrum: impl Into<String>, prime: u64) -> Self {
BPAdamsSpectralSequence {
spectrum: spectrum.into(),
prime,
converges: true,
}
}
}
pub struct ChromaticConvergence {
pub spectrum: String,
pub verified: bool,
}
pub struct AdamsNovikovSS {
pub spectrum: String,
pub prime: u64,
pub e2_page: Vec<(usize, usize, usize)>,
}
impl AdamsNovikovSS {
pub fn e2_rank(&self, s: usize, t: usize) -> usize {
self.e2_page
.iter()
.find(|&&(si, ti, _)| si == s && ti == t)
.map(|&(_, _, r)| r)
.unwrap_or(0)
}
pub fn stem(&self, t: usize, s: usize) -> Option<i64> {
if t >= s {
Some((t - s) as i64)
} else {
None
}
}
}
pub struct TopologicalCyclicHomologyData {
pub ring_spectrum: String,
pub prime: u64,
pub uses_bokstedt_periodicity: bool,
}
impl TopologicalCyclicHomologyData {
pub fn new(ring_spectrum: impl Into<String>, prime: u64) -> Self {
TopologicalCyclicHomologyData {
ring_spectrum: ring_spectrum.into(),
prime,
uses_bokstedt_periodicity: false,
}
}
pub fn cyclotomic_trace_exists(&self) -> bool {
true
}
}
pub struct LandweberExactFunctor {
pub ring: String,
pub is_exact: bool,
pub regularity_depth: usize,
}
impl LandweberExactFunctor {
pub fn new(ring: impl Into<String>, depth: usize) -> Self {
LandweberExactFunctor {
ring: ring.into(),
is_exact: depth > 0,
regularity_depth: depth,
}
}
pub fn produces_cohomology_theory(&self) -> bool {
self.is_exact
}
}
pub struct LubinTateSpaceData {
pub height: usize,
pub prime: u64,
pub e_theory_computed: bool,
}
impl LubinTateSpaceData {
pub fn new(height: usize, prime: u64) -> Self {
LubinTateSpaceData {
height,
prime,
e_theory_computed: false,
}
}
pub fn num_deformation_params(&self) -> usize {
if self.height > 0 {
self.height - 1
} else {
0
}
}
}
pub struct BrownPetersonBP {
pub prime: u64,
pub max_height: usize,
}
impl BrownPetersonBP {
pub fn new(prime: u64, max_height: usize) -> Self {
BrownPetersonBP { prime, max_height }
}
pub fn vn_degree(&self, n: usize) -> u64 {
2 * (self.prime.pow(n as u32) - 1)
}
pub fn generators(&self) -> Vec<(String, u64)> {
(1..=self.max_height)
.map(|n| (format!("v_{n}"), self.vn_degree(n)))
.collect()
}
}
pub struct WittVectorRing {
pub base_ring: String,
pub prime: u64,
pub length: usize,
}
impl WittVectorRing {
pub fn new(base_ring: impl Into<String>, prime: u64, length: usize) -> Self {
WittVectorRing {
base_ring: base_ring.into(),
prime,
length,
}
}
pub fn add(&self, a: &[i64], b: &[i64]) -> Vec<i64> {
let len = self.length.min(a.len()).min(b.len());
let p = self.prime as i64;
let mut result = vec![0i64; len];
let mut carry = 0i64;
for i in 0..len {
let sum = a[i] + b[i] + carry;
result[i] = sum % p;
carry = sum / p;
}
result
}
pub fn frobenius_shift(components: &[i64]) -> Vec<i64> {
if components.is_empty() {
vec![]
} else {
components[1..].to_vec()
}
}
pub fn verschiebung(components: &[i64]) -> Vec<i64> {
let mut result = vec![0i64];
result.extend_from_slice(components);
result
}
}
pub struct FormalGroupLaw {
pub coefficients: Vec<Vec<i64>>,
pub truncation: usize,
}
impl FormalGroupLaw {
pub fn additive(truncation: usize) -> Self {
let mut coefficients = vec![vec![0i64; truncation + 1]; truncation + 1];
if truncation >= 1 {
coefficients[1][0] = 1;
coefficients[0][1] = 1;
}
FormalGroupLaw {
coefficients,
truncation,
}
}
pub fn multiplicative(truncation: usize) -> Self {
let mut coefficients = vec![vec![0i64; truncation + 1]; truncation + 1];
if truncation >= 1 {
coefficients[1][0] = 1;
coefficients[0][1] = 1;
}
if truncation >= 2 {
coefficients[1][1] = 1;
}
FormalGroupLaw {
coefficients,
truncation,
}
}
pub fn satisfies_identity(&self) -> bool {
self.truncation >= 1 && self.coefficients[1][0] == 1
}
pub fn height_at_prime(&self, _p: u64) -> Option<usize> {
if self.truncation >= 2 && self.coefficients[1][1] != 0 {
Some(1)
} else {
None
}
}
}
pub struct TopologicalHochschildHomologyData {
pub ring_spectrum: String,
pub is_e_infty: bool,
pub homotopy_groups: Vec<(usize, usize)>,
}
impl TopologicalHochschildHomologyData {
pub fn new(ring_spectrum: impl Into<String>, is_e_infty: bool) -> Self {
TopologicalHochschildHomologyData {
ring_spectrum: ring_spectrum.into(),
is_e_infty,
homotopy_groups: Vec::new(),
}
}
pub fn add_homotopy_group(&mut self, degree: usize, rank: usize) {
self.homotopy_groups.push((degree, rank));
}
pub fn pi_rank(&self, d: usize) -> usize {
self.homotopy_groups
.iter()
.find(|&&(deg, _)| deg == d)
.map(|&(_, r)| r)
.unwrap_or(0)
}
}
pub struct VnSelfMapData {
pub height: usize,
pub prime: u64,
pub period: u64,
pub multiplicity: u64,
}
impl VnSelfMapData {
pub fn new(height: usize, prime: u64, multiplicity: u64) -> Self {
let base_period = 2 * (prime.pow(height as u32) - 1);
VnSelfMapData {
height,
prime,
period: base_period * multiplicity,
multiplicity,
}
}
pub fn telescope_name(&self, spectrum: &str) -> String {
format!("v_{}^{{-1}} {}", self.height, spectrum)
}
}
pub struct LevelStructure {
pub level: usize,
pub structure_type: String,
}
impl LevelStructure {
pub fn gamma_0(n: usize) -> Self {
LevelStructure {
level: n,
structure_type: "Gamma_0".to_string(),
}
}
pub fn gamma_1(n: usize) -> Self {
LevelStructure {
level: n,
structure_type: "Gamma_1".to_string(),
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MoravaKData {
pub height: usize,
pub prime: usize,
pub coeff_ring: String,
}
#[allow(dead_code)]
impl MoravaKData {
pub fn new(height: usize, prime: usize) -> Self {
let coeff_ring = if height == 0 {
format!("F_{}", prime)
} else {
format!("F_{}[v_{}, v_{}^(-1)]", prime, height, height)
};
MoravaKData {
height,
prime,
coeff_ring,
}
}
pub fn vn_degree(&self) -> usize {
2 * (self.prime.pow(self.height as u32) - 1)
}
pub fn coeff_of_point_is_fp(&self) -> bool {
self.height >= 1
}
pub fn satisfies_kunneth(&self) -> bool {
true
}
pub fn bcp_dimension(&self) -> usize {
if self.height == 0 {
0
} else {
2 * self.prime.pow((self.height - 1) as u32)
}
}
pub fn associated_e_theory(&self) -> String {
format!(
"E({},{}) (Morava E-theory, formal group over W(F_{}^{})",
self.prime, self.height, self.prime, self.height
)
}
}
pub struct ChromaticComplexityData {
pub spectrum: String,
pub acyclic_below: Vec<bool>,
}
impl ChromaticComplexityData {
pub fn new(spectrum: impl Into<String>) -> Self {
ChromaticComplexityData {
spectrum: spectrum.into(),
acyclic_below: Vec::new(),
}
}
pub fn set_acyclic_at(&mut self, n: usize) {
if n >= self.acyclic_below.len() {
self.acyclic_below.resize(n + 1, false);
}
self.acyclic_below[n] = true;
}
pub fn type_estimate(&self) -> Option<usize> {
for (n, &acyclic) in self.acyclic_below.iter().enumerate() {
if !acyclic {
return Some(n);
}
}
if self.acyclic_below.is_empty() {
None
} else {
Some(self.acyclic_below.len())
}
}
pub fn complexity(&self) -> usize {
self.type_estimate().unwrap_or(0)
}
}
pub struct ModularFormSpectrum {
pub weight: usize,
pub level: usize,
pub is_cusp_form: bool,
}
impl ModularFormSpectrum {
pub fn cusp_forms(&self) -> bool {
self.is_cusp_form
}
pub fn degree(&self) -> usize {
2 * self.weight
}
pub fn weight(&self) -> usize {
self.weight
}
}
pub struct LazardRing {
pub generators: Vec<(usize, String)>,
}
impl LazardRing {
pub fn new(max_degree: usize) -> Self {
let generators = (1..=max_degree / 2)
.map(|i| (2 * i, format!("a_{i}")))
.collect();
LazardRing { generators }
}
pub fn generators_of_degree(&self, d: usize) -> Vec<&str> {
self.generators
.iter()
.filter(|(deg, _)| *deg == d)
.map(|(_, name)| name.as_str())
.collect()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct BPCohomologyData {
pub prime: usize,
pub vn_generators: Vec<(usize, usize)>,
pub bp_ranks: Vec<(i32, usize)>,
}
#[allow(dead_code)]
impl BPCohomologyData {
pub fn new(prime: usize, max_n: usize) -> Self {
let vn_generators = (0..=max_n)
.map(|i| {
let deg = if i == 0 {
2
} else {
2 * (prime.pow(i as u32) - 1)
};
(i, deg)
})
.collect();
BPCohomologyData {
prime,
vn_generators,
bp_ranks: Vec::new(),
}
}
pub fn vn_degree(&self, n: usize) -> Option<usize> {
self.vn_generators
.iter()
.find(|&&(i, _)| i == n)
.map(|&(_, d)| d)
}
pub fn add_bp_rank(&mut self, degree: i32, rank: usize) {
self.bp_ranks.push((degree, rank));
}
pub fn rank_in_degree(&self, d: i32) -> usize {
self.bp_ranks
.iter()
.filter(|&&(deg, _)| deg == d)
.map(|&(_, r)| r)
.sum()
}
pub fn coefficient_ring(&self) -> String {
let gens: Vec<String> = self
.vn_generators
.iter()
.map(|&(i, _)| format!("v_{}", i))
.collect();
format!("Z_({})[{}]", self.prime, gens.join(", "))
}
}
pub struct LocalSpectra {
pub homology_theory: String,
pub local_spectra: Vec<String>,
}
impl LocalSpectra {
pub fn is_local(&self, name: &str) -> bool {
self.local_spectra.iter().any(|s| s == name)
}
}
pub struct ChromaticFiltration {
pub spectrum: String,
pub layers: Vec<String>,
pub prime: u64,
}
impl ChromaticFiltration {
pub fn layer(&self, n: usize) -> Option<&str> {
self.layers.get(n).map(String::as_str)
}
pub fn converges_at(&self, max_n: usize) -> bool {
self.layers.len() > max_n
}
}
pub struct AcyclicMorphism {
pub source: String,
pub target: String,
pub acyclic: bool,
}
pub struct MoravaStabilizerGroupData {
pub height: usize,
pub prime: u64,
pub center_order_mod: u64,
}
impl MoravaStabilizerGroupData {
pub fn new(height: usize, prime: u64) -> Self {
let center_order_mod = prime.pow(height as u32) - 1;
MoravaStabilizerGroupData {
height,
prime,
center_order_mod,
}
}
pub fn center_index(&self) -> u64 {
self.center_order_mod
}
}
pub struct TopologicalModularForms {
pub is_connective: bool,
pub is_compactified: bool,
}
impl TopologicalModularForms {
pub fn connective() -> Self {
TopologicalModularForms {
is_connective: true,
is_compactified: false,
}
}
pub fn periodic() -> Self {
TopologicalModularForms {
is_connective: false,
is_compactified: false,
}
}
}
pub struct OrientationData {
pub theory: String,
pub first_chern_class: i64,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct LambdaRingElement {
pub adams_ops: Vec<f64>,
pub value: f64,
}
#[allow(dead_code)]
impl LambdaRingElement {
pub fn new(value: f64, degree: usize) -> Self {
let adams_ops = (1..=degree).map(|k| (k as f64) * value).collect();
LambdaRingElement { adams_ops, value }
}
pub fn adams_op(&self, k: usize) -> Option<f64> {
if k == 0 || k > self.adams_ops.len() {
None
} else {
Some(self.adams_ops[k - 1])
}
}
pub fn add(&self, other: &LambdaRingElement) -> LambdaRingElement {
let degree = self.adams_ops.len().min(other.adams_ops.len());
let adams_ops = (0..degree)
.map(|i| self.adams_ops[i] + other.adams_ops[i])
.collect();
LambdaRingElement {
adams_ops,
value: self.value + other.value,
}
}
pub fn tensor(&self, other: &LambdaRingElement) -> LambdaRingElement {
let degree = self.adams_ops.len().min(other.adams_ops.len());
let adams_ops = (0..degree)
.map(|i| self.adams_ops[i] * other.adams_ops[i])
.collect();
LambdaRingElement {
adams_ops,
value: self.value * other.value,
}
}
pub fn check_composition(&self, m: usize, n: usize) -> bool {
let mn = m * n;
if mn > self.adams_ops.len() || m > self.adams_ops.len() || n > self.adams_ops.len() {
return true;
}
let psi_mn_direct = mn as f64 * self.value;
let psi_mn_via_comp = m as f64 * (n as f64 * self.value);
(psi_mn_direct - psi_mn_via_comp).abs() < 1e-10
}
}
pub struct DescentData {
pub spectrum: String,
pub group: String,
pub hfp_computed: bool,
}
pub struct MoravaETheory {
pub height: usize,
pub prime: u64,
pub formal_group_name: String,
pub is_e_infty_ring: bool,
}
impl MoravaETheory {
pub fn new(height: usize, prime: u64) -> Self {
MoravaETheory {
height,
prime,
formal_group_name: format!("Gamma_{height}"),
is_e_infty_ring: true,
}
}
pub fn periodicity(&self) -> u64 {
2 * (self.prime.pow(self.height as u32) - 1)
}
}
pub struct HondaFormalGroup {
pub height: usize,
pub prime: u64,
}
impl HondaFormalGroup {
pub fn new(height: usize, prime: u64) -> Self {
HondaFormalGroup { height, prime }
}
pub fn p_series_degree(&self) -> u64 {
self.prime.pow(self.height as u32)
}
pub fn isomorphic_to(&self, other: &HondaFormalGroup) -> bool {
self.height == other.height && self.prime == other.prime
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FormalGroupDeformation {
pub height: usize,
pub lt_parameters: Vec<f64>,
pub char_p: usize,
}
#[allow(dead_code)]
impl FormalGroupDeformation {
pub fn universal(height: usize, char_p: usize) -> Self {
let lt_parameters = vec![0.0; height.saturating_sub(1)];
FormalGroupDeformation {
height,
lt_parameters,
char_p,
}
}
pub fn deformation_ring_dim(&self) -> usize {
self.height.saturating_sub(1)
}
pub fn set_lt_param(&mut self, i: usize, val: f64) {
if i < self.lt_parameters.len() {
self.lt_parameters[i] = val;
}
}
pub fn is_lubin_tate(&self) -> bool {
self.height >= 1 && self.char_p >= 2
}
pub fn morava_stabilizer_group(&self) -> String {
format!(
"S_{} = Aut(Γ_{}^{{1}}) over F_{}",
self.height, self.height, self.char_p
)
}
pub fn hasse_invariant_vanishes(&self) -> bool {
self.height >= 2
}
}
pub struct LocalizationUnit {
pub constructed: bool,
pub is_e_local_equiv: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct FglArithmetic {
pub coeffs: std::collections::HashMap<(usize, usize), f64>,
pub max_deg: usize,
pub name: String,
}
#[allow(dead_code)]
impl FglArithmetic {
pub fn additive(max_deg: usize) -> Self {
let mut coeffs = std::collections::HashMap::new();
coeffs.insert((1, 0), 1.0);
coeffs.insert((0, 1), 1.0);
FglArithmetic {
coeffs,
max_deg,
name: "Additive".to_string(),
}
}
pub fn multiplicative(max_deg: usize) -> Self {
let mut coeffs = std::collections::HashMap::new();
coeffs.insert((1, 0), 1.0);
coeffs.insert((0, 1), 1.0);
coeffs.insert((1, 1), 1.0);
FglArithmetic {
coeffs,
max_deg,
name: "Multiplicative".to_string(),
}
}
pub fn evaluate(&self, x: f64, y: f64) -> f64 {
let mut result = 0.0;
for (&(i, j), &a) in &self.coeffs {
if i + j <= self.max_deg {
result += a * x.powi(i as i32) * y.powi(j as i32);
}
}
result
}
pub fn is_commutative_approx(&self, tol: f64) -> bool {
let samples = [(0.1, 0.2), (0.3, 0.4), (0.05, 0.15)];
for &(x, y) in &samples {
let fxy = self.evaluate(x, y);
let fyx = self.evaluate(y, x);
if (fxy - fyx).abs() > tol {
return false;
}
}
true
}
pub fn coeff(&self, i: usize, j: usize) -> f64 {
*self.coeffs.get(&(i, j)).unwrap_or(&0.0)
}
pub fn set_coeff(&mut self, i: usize, j: usize, val: f64) {
if i + j <= self.max_deg {
self.coeffs.insert((i, j), val);
}
}
pub fn p_series(&self, p: usize, x: f64) -> f64 {
if p == 0 {
return 0.0;
}
let mut acc = x;
for _ in 1..p {
acc = self.evaluate(acc, x);
}
acc
}
pub fn is_height_one_approx(&self) -> bool {
let x = 0.01f64;
let two_series = self.p_series(2, x);
two_series.abs() < 0.001
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct NilpotenceData {
pub element: String,
pub is_nilpotent: bool,
pub nilpotency_exponent: Option<usize>,
pub prime: usize,
}
#[allow(dead_code)]
impl NilpotenceData {
pub fn new(element: &str, prime: usize) -> Self {
NilpotenceData {
element: element.to_string(),
is_nilpotent: false,
nilpotency_exponent: None,
prime,
}
}
pub fn set_nilpotent(&mut self, exp: usize) {
self.is_nilpotent = true;
self.nilpotency_exponent = Some(exp);
}
pub fn satisfies_nishida(&self) -> bool {
self.is_nilpotent
}
pub fn detecting_filtration(&self) -> String {
if self.is_nilpotent {
format!("Detected in Adams filtration (prime {})", self.prime)
} else {
"Not nilpotent or unknown".to_string()
}
}
}
pub struct ChromaticSS {
pub spectrum: String,
pub prime: u64,
pub monochromatic_layers: Vec<Vec<usize>>,
}
impl ChromaticSS {
pub fn e1_rank(&self, n: usize, d: usize) -> usize {
self.monochromatic_layers
.get(n)
.and_then(|layer| layer.get(d))
.copied()
.unwrap_or(0)
}
}
pub struct ThickSubcategoryData {
pub index: usize,
pub prime: u64,
pub members: Vec<String>,
}
impl ThickSubcategoryData {
pub fn new(index: usize, prime: u64) -> Self {
ThickSubcategoryData {
index,
prime,
members: Vec::new(),
}
}
pub fn add_member(&mut self, name: impl Into<String>) {
self.members.push(name.into());
}
pub fn contains(&self, name: &str) -> bool {
self.members.iter().any(|m| m == name)
}
}