Skip to main content

slop_algebra/
pure.rs

1//! Abstract algebraic traits and constructions
2
3use std::{
4    fmt::Debug,
5    iter::{Product, Sum},
6    ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
7};
8
9use p3_field::{AbstractField, Field};
10use serde::{Deserialize, Serialize};
11
12pub trait Module<R>:
13    Clone + Add<R, Output = Self> + Sub<R, Output = Self> + Mul<R, Output = Self> + Neg<Output = Self>
14{
15}
16
17impl<R, E> Module<R> for E
18where
19    R: AbstractField,
20    E: Clone + Add<R, Output = E> + Sub<R, Output = E> + Mul<R, Output = E> + Neg<Output = E>,
21{
22}
23
24/// An abstract algebra over a field.
25pub trait Algebra<R>: AbstractField + Module<R> {}
26
27impl<R, E> Algebra<R> for E where E: AbstractField + Module<R> {}
28
29/// A struct representing the `Dorroh extension` of a module.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
31pub enum Dorroh<F, E> {
32    Constant(F),
33    Element(E),
34}
35
36impl<F, E> From<F> for Dorroh<F, E> {
37    fn from(value: F) -> Self {
38        Self::Constant(value)
39    }
40}
41
42impl<F: Default, E> Default for Dorroh<F, E> {
43    fn default() -> Self {
44        Self::Constant(F::default())
45    }
46}
47
48impl<F, E> Add for Dorroh<F, E>
49where
50    F: Field,
51    E: Module<F> + Add<Output = E>,
52{
53    type Output = Self;
54
55    fn add(self, rhs: Self) -> Self {
56        match (self, rhs) {
57            (Self::Constant(a), Self::Constant(b)) => Self::Constant(a + b),
58            (Self::Element(a), Self::Element(b)) => Self::Element(a + b),
59            (Self::Constant(a), Self::Element(b)) => Self::Element(b + a),
60            (Self::Element(a), Self::Constant(b)) => Self::Element(a + b),
61        }
62    }
63}
64
65impl<F, E> AddAssign for Dorroh<F, E>
66where
67    F: Field,
68    E: Module<F> + Add<Output = E>,
69{
70    fn add_assign(&mut self, rhs: Self) {
71        *self = self.clone() + rhs;
72    }
73}
74
75impl<F, E> Sub for Dorroh<F, E>
76where
77    F: Field,
78    E: Module<F> + Sub<Output = E>,
79{
80    type Output = Self;
81
82    fn sub(self, rhs: Self) -> Self {
83        match (self, rhs) {
84            (Self::Constant(a), Self::Constant(b)) => Self::Constant(a - b),
85            (Self::Element(a), Self::Element(b)) => Self::Element(a - b),
86            (Self::Constant(a), Self::Element(b)) => Self::Element(-b + a),
87            (Self::Element(a), Self::Constant(b)) => Self::Element(a - b),
88        }
89    }
90}
91
92impl<F, E> SubAssign for Dorroh<F, E>
93where
94    F: Field,
95    E: Module<F> + Sub<Output = E>,
96{
97    fn sub_assign(&mut self, rhs: Self) {
98        *self = self.clone() - rhs;
99    }
100}
101
102impl<F, E> Neg for Dorroh<F, E>
103where
104    F: Field,
105    E: Module<F>,
106{
107    type Output = Self;
108
109    fn neg(self) -> Self {
110        match self {
111            Self::Constant(a) => Self::Constant(-a),
112            Self::Element(a) => Self::Element(-a),
113        }
114    }
115}
116
117impl<F, E> Mul for Dorroh<F, E>
118where
119    F: Field,
120    E: Module<F> + Mul<Output = E>,
121{
122    type Output = Self;
123
124    fn mul(self, rhs: Self) -> Self {
125        match (self, rhs) {
126            (Self::Constant(a), Self::Constant(b)) => Self::Constant(a * b),
127            (Self::Element(a), Self::Element(b)) => Self::Element(a * b),
128            (Self::Constant(a), Self::Element(b)) => Self::Element(b * a),
129            (Self::Element(a), Self::Constant(b)) => Self::Element(a * b),
130        }
131    }
132}
133
134impl<F, E> MulAssign for Dorroh<F, E>
135where
136    F: Field,
137    E: Module<F> + Mul<Output = E>,
138{
139    fn mul_assign(&mut self, rhs: Self) {
140        *self = self.clone() * rhs;
141    }
142}
143
144impl<F, E> Sum for Dorroh<F, E>
145where
146    F: Field,
147    E: Module<F> + Mul<Output = E> + Add<Output = E> + Sub<Output = E> + Debug,
148{
149    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
150        iter.fold(Self::zero(), |acc, x| acc + x)
151    }
152}
153
154impl<F, E> Product for Dorroh<F, E>
155where
156    F: Field,
157    E: Module<F> + Mul<Output = E> + Add<Output = E> + Sub<Output = E> + Debug,
158{
159    fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
160        iter.fold(Self::one(), |acc, x| acc * x)
161    }
162}
163
164impl<F, E> Add<F> for Dorroh<F, E>
165where
166    F: Field,
167    E: Module<F>,
168{
169    type Output = Self;
170
171    fn add(self, rhs: F) -> Self {
172        match self {
173            Self::Constant(a) => Self::Constant(a + rhs),
174            Self::Element(a) => Self::Element(a + rhs),
175        }
176    }
177}
178
179impl<F, E> Sub<F> for Dorroh<F, E>
180where
181    F: Field,
182    E: Module<F>,
183{
184    type Output = Self;
185
186    fn sub(self, rhs: F) -> Self {
187        match self {
188            Self::Constant(a) => Self::Constant(a - rhs),
189            Self::Element(a) => Self::Element(a - rhs),
190        }
191    }
192}
193
194impl<F, E> Mul<F> for Dorroh<F, E>
195where
196    F: Field,
197    E: Module<F>,
198{
199    type Output = Self;
200
201    fn mul(self, rhs: F) -> Self {
202        match self {
203            Self::Constant(a) => Self::Constant(a * rhs),
204            Self::Element(a) => Self::Element(a * rhs),
205        }
206    }
207}
208
209impl<F, E> AbstractField for Dorroh<F, E>
210where
211    F: Field,
212    E: Module<F> + Mul<Output = E> + Add<Output = E> + Sub<Output = E> + Debug,
213{
214    type F = F;
215
216    fn zero() -> Self {
217        Self::Constant(F::zero())
218    }
219
220    fn one() -> Self {
221        Self::Constant(F::one())
222    }
223
224    fn two() -> Self {
225        Self::Constant(F::two())
226    }
227
228    fn neg_one() -> Self {
229        Self::Constant(F::neg_one())
230    }
231
232    fn from_f(f: Self::F) -> Self {
233        Self::Constant(f)
234    }
235
236    fn from_bool(b: bool) -> Self {
237        Self::Constant(F::from_bool(b))
238    }
239
240    fn from_canonical_u8(n: u8) -> Self {
241        Self::Constant(F::from_canonical_u8(n))
242    }
243
244    fn from_canonical_u16(n: u16) -> Self {
245        Self::Constant(F::from_canonical_u16(n))
246    }
247
248    fn from_canonical_u32(n: u32) -> Self {
249        Self::Constant(F::from_canonical_u32(n))
250    }
251
252    fn from_canonical_u64(n: u64) -> Self {
253        Self::Constant(F::from_canonical_u64(n))
254    }
255
256    fn from_canonical_usize(n: usize) -> Self {
257        Self::Constant(F::from_canonical_usize(n))
258    }
259
260    fn from_wrapped_u32(n: u32) -> Self {
261        Self::Constant(F::from_wrapped_u32(n))
262    }
263
264    fn from_wrapped_u64(n: u64) -> Self {
265        Self::Constant(F::from_wrapped_u64(n))
266    }
267
268    fn generator() -> Self {
269        Self::Constant(F::generator())
270    }
271}