1use 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
24pub trait Algebra<R>: AbstractField + Module<R> {}
26
27impl<R, E> Algebra<R> for E where E: AbstractField + Module<R> {}
28
29#[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}