1use std::{
4 fmt::{Debug, Display},
5 hash::Hash,
6 iter::{Product, Sum},
7 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
8};
9
10use binius_utils::{DeserializeBytes, SerializeBytes};
11use rand::RngCore;
12
13use crate::{
14 arithmetic_traits::{InvertOrZero, Square},
15 as_packed_field::PackScalar,
16 underlier::WithUnderlier,
17};
18
19pub trait Field:
21 Sized
22 + Eq
23 + Copy
24 + Clone
25 + Default
26 + Send
27 + Sync
28 + Debug
29 + Display
30 + Hash
31 + 'static
32 + Neg<Output = Self>
33 + Add<Output = Self>
34 + Sub<Output = Self>
35 + Mul<Output = Self>
36 + Sum
37 + Product
38 + for<'a> Add<&'a Self, Output = Self>
39 + for<'a> Sub<&'a Self, Output = Self>
40 + for<'a> Mul<&'a Self, Output = Self>
41 + for<'a> Sum<&'a Self>
42 + for<'a> Product<&'a Self>
43 + AddAssign
44 + SubAssign
45 + MulAssign
46 + for<'a> AddAssign<&'a Self>
47 + for<'a> SubAssign<&'a Self>
48 + for<'a> MulAssign<&'a Self>
49 + Square
50 + InvertOrZero
51 + WithUnderlier<Underlier: PackScalar<Self>>
53 + SerializeBytes
54 + DeserializeBytes
55{
56 const ZERO: Self;
58
59 const ONE: Self;
61
62 const CHARACTERISTIC: usize;
64
65 fn random(rng: impl RngCore) -> Self;
67
68 fn is_zero(&self) -> bool {
70 *self == Self::ZERO
71 }
72
73 #[must_use]
75 fn double(&self) -> Self;
76
77 fn invert(&self) -> Option<Self> {
80 let inv = self.invert_or_zero();
81 (!inv.is_zero()).then_some(inv)
82 }
83
84 fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
93 let mut res = Self::ONE;
94 for e in exp.as_ref().iter().rev() {
95 for i in (0..64).rev() {
96 res = res.square();
97 let mut tmp = res;
98 tmp *= self;
99 if ((*e >> i) & 1) != 0 {
100 res = tmp;
101 }
102 }
103 }
104 res
105 }
106
107 fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
116 let mut res = Self::ONE;
117 for e in exp.as_ref().iter().rev() {
118 for i in (0..64).rev() {
119 res = res.square();
120
121 if ((*e >> i) & 1) == 1 {
122 res.mul_assign(self);
123 }
124 }
125 }
126
127 res
128 }
129}