Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 104 additions & 133 deletions ext/crates/algebra/src/algebra/adem_algebra.rs

Large diffs are not rendered by default.

416 changes: 272 additions & 144 deletions ext/crates/algebra/src/algebra/algebra_trait.rs

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions ext/crates/algebra/src/algebra/bialgebra_trait.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::algebra::Algebra;
use crate::algebra::BasisElem;

pub trait Bialgebra: Algebra {
/// This function decomposes an element of the algebra as a product of elements, each of whose
Expand All @@ -9,9 +10,9 @@ pub trait Bialgebra: Algebra {
/// This structure is motivated by the fact that in the admissible basis for the Adem algebra,
/// an element naturally decomposes into a product of Steenrod squares, each of which has an
/// easy coproduct formula.
fn decompose(&self, op_deg: i32, op_idx: usize) -> Vec<(i32, usize)>;
fn decompose(&self, BasisElem<Self>) -> Vec<BasisElem<Self>>;

/// Expresses Delta(x) as sum_j (A_{ij} (x) B_{ij}). Here x must be one of the elements
/// returned by `decompose`.
fn coproduct(&self, op_deg: i32, op_idx: usize) -> Vec<(i32, usize, i32, usize)>;
fn coproduct(&self, BasisElem<Self>) -> Vec<(BasisElem<Self>, BasisElem<Self>)>;
}
30 changes: 14 additions & 16 deletions ext/crates/algebra/src/algebra/field.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::algebra::{Algebra, Bialgebra};
use crate::algebra::{Algebra, Bialgebra, BasisElem, Elem};
use fp::prime::ValidPrime;
use fp::vector::{Slice, SliceMut};

Expand Down Expand Up @@ -39,36 +39,34 @@ impl Algebra for Field {
&self,
mut result: SliceMut,
coeff: u32,
_r_degree: i32,
_r_idx: usize,
_s_degree: i32,
_s_idx: usize,
_excess: i32,
_r: BasisElem<Self>,
_s: BasisElem<Self>,
) {
result.add_basis_element(0, coeff)
}

fn default_filtration_one_products(&self) -> Vec<(String, i32, usize)> {
fn default_filtration_one_products(&self) -> Vec<(String, BasisElem<Self>)> {
vec![]
}

/// Converts a basis element into a string for display.
fn basis_element_to_string(&self, degree: i32, _idx: usize) -> String {
assert!(degree == 0);
fn basis_element_to_string(&self, b: BasisElem<Self>) -> String {
assert!(b.degree() == 0);
"1".to_string()
}

fn element_to_string(&self, degree: i32, element: Slice) -> String {
assert!(degree == 0);
format!("{}", element.entry(0))
fn element_to_string(&self, x: impl Into<Elem<Self, Slice>>) -> String {
let x = x.into()
assert!(x.degree() == 0);
format!("{}", x.coeffs().entry(0))
}
}

impl Bialgebra for Field {
fn coproduct(&self, _op_deg: i32, _op_idx: usize) -> Vec<(i32, usize, i32, usize)> {
vec![(1, 0, 1, 0)]
fn coproduct(&self, _x: BasisElem<Self>) -> Vec<(BasisElem<Self>, BasisElem<Self>)> {
vec![(BasisElem::new(1, 0), BasisElem::new(1, 0))]
}
fn decompose(&self, _op_deg: i32, _op_idx: usize) -> Vec<(i32, usize)> {
vec![(1, 0)]
fn decompose(&self, _x: BasisElem<Self>) -> Vec<BasisElem<Self>> {
vec![(BasisElem::new(1, 0))]
}
}
92 changes: 42 additions & 50 deletions ext/crates/algebra/src/algebra/milnor_algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use rustc_hash::FxHashMap as HashMap;
use std::sync::Mutex;

use crate::algebra::combinatorics;
use crate::algebra::{Algebra, Bialgebra, GeneratedAlgebra};
use crate::algebra::{Algebra, BasisElem, Elem, VectorElem,Bialgebra, GeneratedAlgebra};
use fp::prime::{integer_power, Binomial, BitflagIterator, ValidPrime};
use fp::vector::{FpVector, Slice, SliceMut};
use once::OnceVec;
Expand Down Expand Up @@ -190,17 +190,17 @@ impl MilnorAlgebra {
}
}

pub fn basis_element_from_index(&self, degree: i32, idx: usize) -> &MilnorBasisElement {
&self.basis_table[degree as usize][idx]
pub fn basis_element_from_index(&self, b: BasisElem<Self>) -> &MilnorBasisElement {
&self.basis_table[b.degree() as usize][b.index()]
}

pub fn try_basis_element_to_index(&self, elt: &MilnorBasisElement) -> Option<usize> {
pub fn try_basis_element_to_index(&self, elt: &MilnorBasisElement) -> Option<BasisElem<Self>> {
self.basis_element_to_index_map[elt.degree as usize]
.get(elt)
.copied()
.map(|&i| BasisElem::new(elt.degree, i))
}

pub fn basis_element_to_index(&self, elt: &MilnorBasisElement) -> usize {
pub fn basis_element_to_index(&self, elt: &MilnorBasisElement) -> BasisElem<Self> {
self.try_basis_element_to_index(elt)
.unwrap_or_else(|| panic!("Didn't find element: {:?}", elt))
}
Expand All @@ -211,7 +211,7 @@ impl Algebra for MilnorAlgebra {
self.p
}

fn default_filtration_one_products(&self) -> Vec<(String, i32, usize)> {
fn default_filtration_one_products(&self) -> Vec<(String, BasisElem<Self>)> {
let mut products = Vec::with_capacity(4);
let max_degree;
if self.generic() {
Expand Down Expand Up @@ -262,7 +262,7 @@ impl Algebra for MilnorAlgebra {

products
.into_iter()
.map(|(name, b)| (name, b.degree, self.basis_element_to_index(&b)))
.map(|(name, b)| (name, self.basis_element_to_index(&b)))
.collect()
}

Expand Down Expand Up @@ -339,17 +339,15 @@ impl Algebra for MilnorAlgebra {
&self,
result: SliceMut,
coef: u32,
r_degree: i32,
r_idx: usize,
s_degree: i32,
s_idx: usize,
r: BasisElem<Self>,
s: BasisElem<Self>,
_excess: i32,
) {
self.multiply(
result,
coef,
&self.basis_table[r_degree as usize][r_idx],
&self.basis_table[s_degree as usize][s_idx],
&self.basis_table[r.degree() as usize][r.index()],
&self.basis_table[s.degree() as usize][s.index()],
);
}

Expand All @@ -358,21 +356,20 @@ impl Algebra for MilnorAlgebra {
&self,
result: SliceMut,
coef: u32,
r_degree: i32,
r_idx: usize,
s_degree: i32,
s_idx: usize,
r: BasisElem<Self>,
s: BasisElem<Self>,
_excess: i32,
) {
result.shift_add(
&self.multiplication_table[r_degree as usize][s_degree as usize][r_idx][s_idx]
&self.multiplication_table[r.degree() as usize][s.degree() as usize][r.index()][s.index()]
.as_slice(),
coef,
);
}

fn basis_element_to_string(&self, degree: i32, idx: usize) -> String {
format!("{}", self.basis_table[degree as usize][idx])
fn basis_element_to_string(&self,
x: BasisElem<Self>,) -> String {
format!("{}", self.basis_table[x.degree() as usize][x.index()])
}
}

Expand All @@ -382,7 +379,7 @@ impl JsonAlgebra for MilnorAlgebra {
"milnor"
}

fn json_to_basis(&self, json: &Value) -> anyhow::Result<(i32, usize)> {
fn json_to_basis(&self, json: &Value) -> anyhow::Result<BasisElem<Self>> {
let xi_degrees = combinatorics::xi_degrees(self.prime());
let tau_degrees = combinatorics::tau_degrees(self.prime());

Expand Down Expand Up @@ -414,11 +411,11 @@ impl JsonAlgebra for MilnorAlgebra {
p_part,
degree,
};
Ok((degree, self.basis_element_to_index(&m)))
Ok(self.basis_element_to_index(&m))
}

fn json_from_basis(&self, degree: i32, index: usize) -> Value {
let b = self.basis_element_from_index(degree, index);
fn json_from_basis(&self, b: BasisElem<Self>) -> Value {
let b = self.basis_element_from_index(b);
if self.generic() {
let mut q_part = b.q_part;
let mut q_list = Vec::with_capacity(q_part.count_ones() as usize);
Expand All @@ -436,7 +433,7 @@ impl JsonAlgebra for MilnorAlgebra {

impl GeneratedAlgebra for MilnorAlgebra {
// Same implementation as AdemAlgebra
fn string_to_generator<'a, 'b>(&'a self, input: &'b str) -> IResult<&'b str, (i32, usize)> {
fn string_to_generator<'a, 'b>(&'a self, input: &'b str) -> IResult<&'b str, BasisElem<Self>> {
let first = map(
alt((
delimited(char('P'), digit1, space1),
Expand All @@ -448,24 +445,24 @@ impl GeneratedAlgebra for MilnorAlgebra {
},
);

let second = map(pair(char('b'), space1), |_| (1, 0));
let second = map(pair(char('b'), space1), |_| BasisElem::new(1, 0));

alt((first, second))(input)
}

fn generator_to_string(&self, degree: i32, _idx: usize) -> String {
fn generator_to_string(&self, b: BasisElem<Self>) -> String {
if self.generic() {
if degree == 1 {
if b.degree() == 1 {
"b".to_string()
} else {
format!("P{}", degree as u32 / (2 * (*self.prime()) - 2))
format!("P{}", b.degree() as u32 / (2 * (*self.prime()) - 2))
}
} else {
format!("Sq{}", degree)
format!("Sq{}", b.degree())
}
}

fn generators(&self, degree: i32) -> Vec<usize> {
fn generators(&self, degree: i32) -> Vec<BasisElem<Self>> {
if degree == 0 {
return vec![];
}
Expand Down Expand Up @@ -498,14 +495,13 @@ impl GeneratedAlgebra for MilnorAlgebra {
q_part: 0,
p_part: vec![(degree as u32 / q) as PPartEntry],
});
return vec![idx];
return vec![BasisElem::new(degree, idx)];
}

fn decompose_basis_element(
&self,
degree: i32,
idx: usize,
) -> Vec<(u32, (i32, usize), (i32, usize))> {
b: BasisElem<Self>,
) -> Vec<(u32, BasisElem<Self>, BasisElem<Self>)> {
let basis = &self.basis_table[degree as usize][idx];
// If qpart = 0, return self
if basis.q_part == 0 {
Expand All @@ -515,10 +511,10 @@ impl GeneratedAlgebra for MilnorAlgebra {
}
}

fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, (i32, usize), (i32, usize))>> {
fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, BasisElem<Self>, BasisElem<Self>)>> {
if self.generic() && degree == 2 {
// beta^2 = 0 is an edge case
return vec![vec![(1, (1, 0), (1, 0))]];
return vec![vec![(1, BasisElem::new(1, 0), BasisElem::new(1, 0))]];
}
let p = self.prime();
let inadmissible_pairs = combinatorics::inadmissible_pairs(p, self.generic(), degree);
Expand All @@ -527,12 +523,10 @@ impl GeneratedAlgebra for MilnorAlgebra {
let mut relation = Vec::new();
// Adem relation. Sometimes these don't exist because of profiles. Then just ignore it.
(|| {
let (first_degree, first_index) = self.try_beps_pn(0, x as PPartEntry)?;
let (second_degree, second_index) = self.try_beps_pn(b, y as PPartEntry)?;
relation.push((
*p - 1,
(first_degree, first_index),
(second_degree, second_index),
self.try_beps_pn(0, x as PPartEntry)?,
self.try_beps_pn(b, y as PPartEntry)?,
));
for e1 in 0..=b {
let e2 = b - e1;
Expand All @@ -549,7 +543,7 @@ impl GeneratedAlgebra for MilnorAlgebra {
relation.push((
c,
self.try_beps_pn(e1, (x + y) as PPartEntry)?,
(e2 as i32, 0),
BasisElem::new(e2 as i32, 0),
));
continue;
}
Expand Down Expand Up @@ -721,18 +715,17 @@ impl MilnorAlgebra {

// Multiplication logic
impl MilnorAlgebra {
fn try_beps_pn(&self, e: u32, x: PPartEntry) -> Option<(i32, usize)> {
fn try_beps_pn(&self, e: u32, x: PPartEntry) -> Option<BasisElem<Self>> {
let q = self.q() as u32;
let degree = (q * x as u32 + e) as i32;
self.try_basis_element_to_index(&MilnorBasisElement {
degree,
q_part: e,
p_part: vec![x as PPartEntry],
})
.map(|index| (degree, index))
}

fn beps_pn(&self, e: u32, x: PPartEntry) -> (i32, usize) {
fn beps_pn(&self, e: u32, x: PPartEntry) -> BasisElem<Self> {
self.try_beps_pn(e, x).unwrap()
}

Expand Down Expand Up @@ -856,16 +849,15 @@ impl MilnorAlgebra {
&self,
mut res: SliceMut,
coef: u32,
r_deg: i32,
r: Slice,
r: VectorElem<Self, Slice>,
m2: &MilnorBasisElement,
mut allocation: PPartAllocation,
) -> PPartAllocation {
for (i, c) in r.iter_nonzero() {
for (i, c) in r.coeffs().iter_nonzero() {
allocation = self.multiply_with_allocation(
res.copy(),
coef * c,
self.basis_element_from_index(r_deg, i),
self.basis_element_from_index(BasisElem::new(r.degree(), i)),
m2,
allocation,
);
Expand Down
8 changes: 4 additions & 4 deletions ext/crates/algebra/src/algebra/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ mod algebra_trait;
mod bialgebra_trait;
pub mod field;
pub mod milnor_algebra;
mod polynomial_algebra;
//mod polynomial_algebra;
mod steenrod_algebra;

pub use adem_algebra::{AdemAlgebra, AdemAlgebraT};
#[cfg(feature = "json")]
pub use algebra_trait::JsonAlgebra;
pub use algebra_trait::{Algebra, GeneratedAlgebra};
pub use algebra_trait::{BasisElem, VectorElem, Elem, Algebra, GeneratedAlgebra};
pub use bialgebra_trait::Bialgebra;
pub use field::Field;
pub use milnor_algebra::{MilnorAlgebra, MilnorAlgebraT};
pub use polynomial_algebra::{
/*pub use polynomial_algebra::{
PolynomialAlgebra, PolynomialAlgebraMonomial, PolynomialAlgebraTableEntry,
};
};*/
pub use steenrod_algebra::{AlgebraType, SteenrodAlgebra, SteenrodAlgebraBorrow, SteenrodAlgebraT};
13 changes: 7 additions & 6 deletions ext/crates/algebra/src/algebra/steenrod_algebra.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#[cfg(feature = "json")]
use crate::algebra::JsonAlgebra;
use crate::algebra::{
BasisElem, VectorElem, Elem,
AdemAlgebra, AdemAlgebraT, Algebra, Bialgebra, GeneratedAlgebra, MilnorAlgebra, MilnorAlgebraT,
};
use crate::dispatch_algebra;
Expand Down Expand Up @@ -241,8 +242,8 @@ dispatch_algebra!(SteenrodAlgebra, dispatch_steenrod);
impl JsonAlgebra for SteenrodAlgebra {
dispatch_steenrod! {
fn prefix(&self) -> &str;
fn json_to_basis(&self, json: &serde_json::Value) -> anyhow::Result<(i32, usize)>;
fn json_from_basis(&self, degree: i32, idx: usize) -> serde_json::Value;
fn json_to_basis(&self, json: &serde_json::Value) -> anyhow::Result<BasisElem<Self>>;
fn json_from_basis(&self, b: BasisElem<Self>) -> serde_json::Value;
}
}

Expand All @@ -251,15 +252,15 @@ impl JsonAlgebra for SteenrodAlgebra {
impl GeneratedAlgebra for SteenrodAlgebra {
dispatch_steenrod! {
fn generators(&self, degree: i32) -> Vec<usize>;
fn generator_to_string(&self, degree: i32, idx: usize) -> String;
fn string_to_generator<'a, 'b>(&'a self, input: &'b str) -> nom::IResult<&'b str, (i32, usize)>;
fn generator_to_string(&self, b: BasisElem<Self>) -> String;
fn string_to_generator<'a, 'b>(&'a self, input: &'b str) -> nom::IResult<&'b str, BasisElem<Self>>;

fn decompose_basis_element(
&self,
degree: i32,
idx: usize,
) -> Vec<(u32, (i32, usize), (i32, usize))>;
) -> Vec<(u32, BasisElem<Self>, BasisElem<Self>)>;

fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, (i32, usize), (i32, usize))>>;
fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, BasisElem<Self>, BasisElem<Self>)>>;
}
}
Loading