snarkvm_console_types_field/
arithmetic.rs1use super::*;
17
18impl<E: Environment> Neg for Field<E> {
19 type Output = Field<E>;
20
21 #[inline]
23 fn neg(self) -> Self::Output {
24 Field::new(-self.field)
25 }
26}
27
28impl<E: Environment> Add<Field<E>> for Field<E> {
29 type Output = Field<E>;
30
31 #[inline]
33 fn add(self, other: Field<E>) -> Self::Output {
34 Field::new(self.field + other.field)
35 }
36}
37
38impl<E: Environment> Add<&Field<E>> for Field<E> {
39 type Output = Field<E>;
40
41 #[inline]
43 fn add(self, other: &Field<E>) -> Self::Output {
44 Field::new(self.field + other.field)
45 }
46}
47
48impl<E: Environment> AddAssign<Field<E>> for Field<E> {
49 #[inline]
51 fn add_assign(&mut self, other: Field<E>) {
52 self.field += other.field;
53 }
54}
55
56impl<E: Environment> AddAssign<&Field<E>> for Field<E> {
57 #[inline]
59 fn add_assign(&mut self, other: &Field<E>) {
60 self.field += other.field;
61 }
62}
63
64impl<E: Environment> Sub<Field<E>> for Field<E> {
65 type Output = Field<E>;
66
67 #[inline]
69 fn sub(self, other: Field<E>) -> Self::Output {
70 Field::new(self.field - other.field)
71 }
72}
73
74impl<E: Environment> Sub<&Field<E>> for Field<E> {
75 type Output = Field<E>;
76
77 #[inline]
79 fn sub(self, other: &Field<E>) -> Self::Output {
80 Field::new(self.field - other.field)
81 }
82}
83
84impl<E: Environment> SubAssign<Field<E>> for Field<E> {
85 #[inline]
87 fn sub_assign(&mut self, other: Field<E>) {
88 self.field -= other.field;
89 }
90}
91
92impl<E: Environment> SubAssign<&Field<E>> for Field<E> {
93 #[inline]
95 fn sub_assign(&mut self, other: &Field<E>) {
96 self.field -= other.field;
97 }
98}
99
100impl<E: Environment> Mul<Field<E>> for Field<E> {
101 type Output = Field<E>;
102
103 #[inline]
105 fn mul(self, other: Field<E>) -> Self::Output {
106 Field::new(self.field * other.field)
107 }
108}
109
110impl<E: Environment> Mul<&Field<E>> for Field<E> {
111 type Output = Field<E>;
112
113 #[inline]
115 fn mul(self, other: &Field<E>) -> Self::Output {
116 Field::new(self.field * other.field)
117 }
118}
119
120impl<E: Environment> MulAssign<Field<E>> for Field<E> {
121 #[inline]
123 fn mul_assign(&mut self, other: Field<E>) {
124 self.field *= other.field;
125 }
126}
127
128impl<E: Environment> MulAssign<&Field<E>> for Field<E> {
129 #[inline]
131 fn mul_assign(&mut self, other: &Field<E>) {
132 self.field *= other.field;
133 }
134}
135
136impl<E: Environment> Div<Field<E>> for Field<E> {
137 type Output = Field<E>;
138
139 #[inline]
141 fn div(self, other: Field<E>) -> Self::Output {
142 match other.is_zero() {
143 true => E::halt(format!("Field division by zero: {self} / {other}")),
144 false => Field::new(self.field / other.field),
145 }
146 }
147}
148
149impl<E: Environment> Div<&Field<E>> for Field<E> {
150 type Output = Field<E>;
151
152 #[inline]
154 fn div(self, other: &Field<E>) -> Self::Output {
155 match other.is_zero() {
156 true => E::halt(format!("Field division by zero: {self} / {other}")),
157 false => Field::new(self.field / other.field),
158 }
159 }
160}
161
162impl<E: Environment> DivAssign<Field<E>> for Field<E> {
163 #[inline]
165 fn div_assign(&mut self, other: Field<E>) {
166 match other.is_zero() {
167 true => E::halt(format!("Field division by zero: {self} / {other}")),
168 false => self.field /= other.field,
169 }
170 }
171}
172
173impl<E: Environment> DivAssign<&Field<E>> for Field<E> {
174 #[inline]
176 fn div_assign(&mut self, other: &Field<E>) {
177 match other.is_zero() {
178 true => E::halt(format!("Field division by zero: {self} / {other}")),
179 false => self.field /= other.field,
180 }
181 }
182}
183
184impl<E: Environment> Pow<Field<E>> for Field<E> {
185 type Output = Field<E>;
186
187 #[inline]
189 fn pow(self, other: Field<E>) -> Self::Output {
190 Field::new(self.field.pow(other.field.to_bigint()))
191 }
192}
193
194impl<E: Environment> Pow<&Field<E>> for Field<E> {
195 type Output = Field<E>;
196
197 #[inline]
199 fn pow(self, other: &Field<E>) -> Self::Output {
200 Field::new(self.field.pow(other.field.to_bigint()))
201 }
202}
203
204impl<E: Environment> Double for Field<E> {
205 type Output = Field<E>;
206
207 #[inline]
209 fn double(&self) -> Self::Output {
210 Field::new(self.field.double())
211 }
212}
213
214impl<E: Environment> Inverse for Field<E> {
215 type Output = Field<E>;
216
217 #[inline]
219 fn inverse(&self) -> Result<Self::Output> {
220 match self.field.inverse() {
221 Some(inverse) => Ok(Field::new(inverse)),
222 None => bail!("Failed to invert a field element: {self}"),
223 }
224 }
225}
226
227impl<E: Environment> Square for Field<E> {
228 type Output = Field<E>;
229
230 #[inline]
232 fn square(&self) -> Self::Output {
233 Field::new(self.field.square())
234 }
235}
236
237impl<E: Environment> SquareRoot for Field<E> {
238 type Output = Field<E>;
239
240 #[inline]
243 fn square_root(&self) -> Result<Self::Output> {
244 match self.field.sqrt() {
245 Some(sqrt) => {
246 let sqrt = Field::new(sqrt);
248 let negative_sqrt: Field<E> = -sqrt;
249 match *(sqrt.is_less_than_or_equal(&negative_sqrt)) {
250 true => Ok(sqrt),
251 false => Ok(negative_sqrt),
252 }
253 }
254 None => bail!("Failed to square root a field element: {self}"),
255 }
256 }
257}
258
259impl<E: Environment> Field<E> {
260 #[inline]
262 pub fn even_square_root(&self) -> Result<Self> {
263 match self.field.sqrt() {
264 Some(sqrt) => {
265 let sqrt: Field<E> = Field::new(sqrt);
266 match *sqrt.to_bits_be().last().unwrap() {
269 true => Ok(-sqrt),
271 false => Ok(sqrt),
273 }
274 }
275 None => bail!("Failed to square root a field element: {self}"),
276 }
277 }
278}
279
280impl<E: Environment> Sum<Field<E>> for Field<E> {
281 #[inline]
283 fn sum<I: Iterator<Item = Field<E>>>(iter: I) -> Self {
284 iter.fold(Field::zero(), |a, b| a + b)
285 }
286}
287
288impl<'a, E: Environment> Sum<&'a Field<E>> for Field<E> {
289 #[inline]
291 fn sum<I: Iterator<Item = &'a Field<E>>>(iter: I) -> Self {
292 iter.fold(Field::zero(), |a, b| a + b)
293 }
294}
295
296impl<E: Environment> Product<Field<E>> for Field<E> {
297 #[inline]
299 fn product<I: Iterator<Item = Field<E>>>(iter: I) -> Self {
300 iter.fold(Field::one(), |a, b| a * b)
301 }
302}
303
304impl<'a, E: Environment> Product<&'a Field<E>> for Field<E> {
305 #[inline]
307 fn product<I: Iterator<Item = &'a Field<E>>>(iter: I) -> Self {
308 iter.fold(Field::one(), |a, b| a * b)
309 }
310}
311
312#[cfg(test)]
313mod tests {
314 use super::*;
315 use snarkvm_console_network_environment::Console;
316
317 type CurrentEnvironment = Console;
318
319 #[test]
320 fn test_div_by_zero_fails() {
321 let one = Field::<CurrentEnvironment>::one();
322 let zero = Field::<CurrentEnvironment>::zero();
323
324 let result = std::panic::catch_unwind(|| one / zero);
325 assert!(result.is_err()); }
327}