Skip to content

Commit ff7d720

Browse files
committed
Remove enum_dispatch dependency
enum_dispatch is somewhat broken, and we need to write manual dispatch code for pyo3 anyway (and have written similar dispatch code for many other things). rust-lang/rust#83527 would make it more convenient to make our manual dispatch code generic.
1 parent 4ae987b commit ff7d720

File tree

4 files changed

+109
-87
lines changed

4 files changed

+109
-87
lines changed

ext/crates/algebra/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@ crate-type = ["cdylib", "rlib"]
1010
[dependencies]
1111
serde_json = { version = "1.0.0", optional = true }
1212
serde = { version = "1.0.0", features = ["derive"], optional = true }
13-
# Cannot upgrade due to https://gitlab.com/antonok/enum_dispatch/-/issues/34
14-
enum_dispatch = "=0.3.2"
1513
itertools = "0.9.0"
1614
lazy_static = "1.2.0"
1715
nom = { version = "5.0.0", default-features = false, features = ["alloc"] }
18-
syn = "=1.0.57"
1916
rustc-hash = "1.1.0"
2017

2118

ext/crates/algebra/src/algebra/algebra_trait.rs

Lines changed: 52 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use fp::prime::ValidPrime;
22
use fp::vector::{Slice, SliceMut};
33

4-
use enum_dispatch::enum_dispatch;
5-
64
/// A graded algebra over F_p, finite dimensional in each degree, equipped with a choice of ordered
75
/// basis in each dimension. Basis elements of the algebra are referred to by their degree and
86
/// index, and general elements are referred to by the degree and an `FpVector` listing the
@@ -17,7 +15,6 @@ use enum_dispatch::enum_dispatch;
1715
/// The algebra should also come with a specified choice of algebra generators, which are
1816
/// necessarily basis elements. It gives us a simpler way of describing finite modules by only
1917
/// specifying the action of the generators.
20-
#[enum_dispatch]
2118
pub trait Algebra: std::fmt::Display + Send + Sync + 'static {
2219
/// Returns the prime the algebra is over.
2320
fn prime(&self) -> ValidPrime;
@@ -155,21 +152,19 @@ pub trait Algebra: std::fmt::Display + Send + Sync + 'static {
155152
}
156153

157154
#[cfg(feature = "json")]
158-
#[enum_dispatch]
159155
pub trait JsonAlgebra: Algebra {
160156
fn prefix(&self) -> &str;
161157

162158
/// Converts a JSON object into a basis element. The way basis elements are represented by JSON
163159
/// objects is to be specified by the algebra itself, and will be used by module
164160
/// specifications.
165-
fn json_to_basis(&self, _json: serde_json::Value) -> error::Result<(i32, usize)>;
161+
fn json_to_basis(&self, json: serde_json::Value) -> error::Result<(i32, usize)>;
166162

167-
fn json_from_basis(&self, _degree: i32, _idx: usize) -> serde_json::Value;
163+
fn json_from_basis(&self, degree: i32, idx: usize) -> serde_json::Value;
168164
}
169165

170166
/// An algebra with a specified list of generators and generating relations. This data can be used
171167
/// to specify modules by specifying the actions of the generators.
172-
#[enum_dispatch]
173168
pub trait GeneratedAlgebra: Algebra {
174169
/// Given a degree `degree`, the function returns a list of algebra generators in that degree.
175170
/// This return value is the list of indices of the basis elements that are generators. The
@@ -220,75 +215,62 @@ pub trait GeneratedAlgebra: Algebra {
220215

221216
#[macro_export]
222217
macro_rules! dispatch_algebra {
223-
($dispatch_macro : ident) => {
224-
fn prime(&self) -> fp::prime::ValidPrime {
225-
$dispatch_macro!(prime, self,)
226-
}
227-
228-
fn compute_basis(&self, degree: i32) {
229-
$dispatch_macro!(compute_basis, self, degree)
230-
}
231-
232-
fn dimension(&self, degree: i32, excess: i32) -> usize {
233-
$dispatch_macro!(dimension, self, degree, excess)
234-
}
235-
236-
fn multiply_basis_elements(
237-
&self,
238-
result: &mut FpVector,
239-
coeff: u32,
240-
r_deg: i32,
241-
r_idx: usize,
242-
s_deg: i32,
243-
s_idx: usize,
244-
excess: i32,
245-
) {
246-
$dispatch_macro!(
247-
multiply_basis_elements,
248-
self,
249-
result,
250-
coeff,
251-
r_deg,
252-
r_idx,
253-
s_deg,
254-
s_idx,
255-
excess
256-
)
257-
}
218+
($struct:ty, $dispatch_macro: ident) => {
219+
impl Algebra for $struct {
220+
$dispatch_macro! {
221+
fn prime(&self) -> ValidPrime;
222+
fn compute_basis(&self, degree: i32);
223+
fn dimension(&self, degree: i32, excess: i32) -> usize;
224+
fn multiply_basis_elements(
225+
&self,
226+
result: SliceMut,
227+
coeff: u32,
228+
r_degree: i32,
229+
r_idx: usize,
230+
s_degree: i32,
231+
s_idx: usize,
232+
excess: i32,
233+
);
258234

259-
fn json_to_basis(&self, json: serde_json::Value) -> error::Result<(i32, usize)> {
260-
$dispatch_macro!(json_to_basis, self, json)
261-
}
235+
fn multiply_basis_element_by_element(
236+
&self,
237+
result: SliceMut,
238+
coeff: u32,
239+
r_degree: i32,
240+
r_idx: usize,
241+
s_degree: i32,
242+
s: Slice,
243+
excess: i32,
244+
);
262245

263-
fn json_from_basis(&self, degree: i32, idx: usize) -> serde_json::Value {
264-
$dispatch_macro!(json_from_basis, self, degree, idx)
265-
}
246+
fn multiply_element_by_basis_element(
247+
&self,
248+
result: SliceMut,
249+
coeff: u32,
250+
r_degree: i32,
251+
r: Slice,
252+
s_degree: i32,
253+
s_idx: usize,
254+
excess: i32,
255+
);
266256

267-
fn basis_element_to_string(&self, degree: i32, idx: usize) -> String {
268-
$dispatch_macro!(basis_element_to_string, self, degree, idx)
269-
}
257+
fn multiply_element_by_element(
258+
&self,
259+
result: SliceMut,
260+
coeff: u32,
261+
r_degree: i32,
262+
r: Slice,
263+
s_degree: i32,
264+
s: Slice,
265+
excess: i32,
266+
);
270267

271-
fn generators(&self, degree: i32) -> Vec<usize> {
272-
$dispatch_macro!(generators, self, degree)
273-
}
268+
fn default_filtration_one_products(&self) -> Vec<(String, i32, usize)>;
274269

275-
fn string_to_generator<'a, 'b>(
276-
&'a self,
277-
input: &'b str,
278-
) -> nom::IResult<&'b str, (i32, usize)> {
279-
$dispatch_macro!(string_to_generator, self, input)
280-
}
281-
282-
fn decompose_basis_element(
283-
&self,
284-
degree: i32,
285-
idx: usize,
286-
) -> Vec<(u32, (i32, usize), (i32, usize))> {
287-
$dispatch_macro!(decompose_basis_element, self, degree, idx)
288-
}
270+
fn basis_element_to_string(&self, degree: i32, idx: usize) -> String;
289271

290-
fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, (i32, usize), (i32, usize))>> {
291-
$dispatch_macro!(generating_relations, self, degree)
272+
fn element_to_string(&self, degree: i32, element: Slice) -> String;
273+
}
292274
}
293275
};
294276
}

ext/crates/algebra/src/algebra/steenrod_algebra.rs

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use crate::algebra::JsonAlgebra;
33
use crate::algebra::{
44
AdemAlgebra, AdemAlgebraT, Algebra, Bialgebra, GeneratedAlgebra, MilnorAlgebra, MilnorAlgebraT,
55
};
6+
use crate::dispatch_algebra;
67
use fp::prime::ValidPrime;
78
use fp::vector::{Slice, SliceMut};
89

9-
use enum_dispatch::enum_dispatch;
1010
#[cfg(feature = "json")]
1111
use {serde::Deserialize, serde_json::Value};
1212

13-
// This is here so that the Python bindings can use modules defined for SteenrodAlgebraT with their own algebra enum.
13+
// This is here so that the Python bindings can use modules defined aor SteenrodAlgebraT with their own algebra enum.
1414
// In order for things to work SteenrodAlgebraT cannot implement Algebra.
1515
// Otherwise, the algebra enum for our bindings will see an implementation clash.
1616
pub trait SteenrodAlgebraT: Send + Sync + 'static + Algebra {
@@ -22,18 +22,21 @@ pub enum SteenrodAlgebraBorrow<'a> {
2222
BorrowMilnor(&'a MilnorAlgebra),
2323
}
2424

25-
#[cfg(feature = "json")]
26-
#[enum_dispatch(Algebra, GeneratedAlgebra, JsonAlgebra)]
2725
pub enum SteenrodAlgebra {
28-
AdemAlgebra,
29-
MilnorAlgebra,
26+
AdemAlgebra(AdemAlgebra),
27+
MilnorAlgebra(MilnorAlgebra),
3028
}
3129

32-
#[cfg(not(feature = "json"))]
33-
#[enum_dispatch(Algebra, GeneratedAlgebra)]
34-
pub enum SteenrodAlgebra {
35-
AdemAlgebra,
36-
MilnorAlgebra,
30+
impl From<AdemAlgebra> for SteenrodAlgebra {
31+
fn from(adem: AdemAlgebra) -> SteenrodAlgebra {
32+
SteenrodAlgebra::AdemAlgebra(adem)
33+
}
34+
}
35+
36+
impl From<MilnorAlgebra> for SteenrodAlgebra {
37+
fn from(milnor: MilnorAlgebra) -> SteenrodAlgebra {
38+
SteenrodAlgebra::MilnorAlgebra(milnor)
39+
}
3740
}
3841

3942
impl std::fmt::Display for SteenrodAlgebra {
@@ -197,3 +200,45 @@ impl std::error::Error for InvalidAlgebraError {
197200
"Invalid algebra supplied"
198201
}
199202
}
203+
204+
macro_rules! dispatch_steenrod {
205+
() => {};
206+
($vis:vis fn $method:ident$(<$($lt:lifetime),+>)?(&$($lt2:lifetime)?self$(, $arg:ident: $ty:ty )*$(,)?) $(-> $ret:ty)?; $($tail:tt)*) => {
207+
$vis fn $method$(<$($lt),+>)?(&$($lt2)?self, $($arg: $ty),* ) $(-> $ret)* {
208+
match self {
209+
SteenrodAlgebra::AdemAlgebra(a) => a.$method($($arg),*),
210+
SteenrodAlgebra::MilnorAlgebra(a) => a.$method($($arg),*),
211+
}
212+
}
213+
dispatch_steenrod!{$($tail)*}
214+
};
215+
}
216+
217+
dispatch_algebra!(SteenrodAlgebra, dispatch_steenrod);
218+
219+
#[cfg(feature = "json")]
220+
impl JsonAlgebra for SteenrodAlgebra {
221+
dispatch_steenrod! {
222+
fn prefix(&self) -> &str;
223+
fn json_to_basis(&self, json: serde_json::Value) -> error::Result<(i32, usize)>;
224+
fn json_from_basis(&self, degree: i32, idx: usize) -> serde_json::Value;
225+
}
226+
}
227+
228+
/// An algebra with a specified list of generators and generating relations. This data can be used
229+
/// to specify modules by specifying the actions of the generators.
230+
impl GeneratedAlgebra for SteenrodAlgebra {
231+
dispatch_steenrod! {
232+
fn generators(&self, degree: i32) -> Vec<usize>;
233+
fn generator_to_string(&self, degree: i32, idx: usize) -> String;
234+
fn string_to_generator<'a, 'b>(&'a self, input: &'b str) -> nom::IResult<&'b str, (i32, usize)>;
235+
236+
fn decompose_basis_element(
237+
&self,
238+
degree: i32,
239+
idx: usize,
240+
) -> Vec<(u32, (i32, usize), (i32, usize))>;
241+
242+
fn generating_relations(&self, degree: i32) -> Vec<Vec<(u32, (i32, usize), (i32, usize))>>;
243+
}
244+
}

python_ext/pyo3/python_algebra/src/algebra/algebra_rust.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@ macro_rules! because_enum_dispatch_doesnt_work_for_me {
8585
};
8686
}
8787

88-
impl algebra::Algebra for AlgebraRust {
89-
algebra::dispatch_algebra!{because_enum_dispatch_doesnt_work_for_me}
90-
}
88+
algebra::dispatch_algebra!{AlgebraRust, because_enum_dispatch_doesnt_work_for_me}
9189

9290

9391
// #[derive(Debug)]

0 commit comments

Comments
 (0)