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};
11
12use crate::{
13 Random,
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 + Random
52 + WithUnderlier<Underlier: PackScalar<Self>>
54 + SerializeBytes
55 + DeserializeBytes
56{
57 const ZERO: Self;
59
60 const ONE: Self;
62
63 const CHARACTERISTIC: usize;
65
66 fn is_zero(&self) -> bool {
68 *self == Self::ZERO
69 }
70
71 #[must_use]
73 fn double(&self) -> Self;
74
75 fn invert(&self) -> Option<Self> {
78 let inv = self.invert_or_zero();
79 (!inv.is_zero()).then_some(inv)
80 }
81
82 fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
91 let mut res = Self::ONE;
92 for e in exp.as_ref().iter().rev() {
93 for i in (0..64).rev() {
94 res = res.square();
95 let mut tmp = res;
96 tmp *= self;
97 if ((*e >> i) & 1) != 0 {
98 res = tmp;
99 }
100 }
101 }
102 res
103 }
104
105 fn pow_vartime<S: AsRef<[u64]>>(&self, exp: S) -> Self {
114 let mut res = Self::ONE;
115 for e in exp.as_ref().iter().rev() {
116 for i in (0..64).rev() {
117 res = res.square();
118
119 if ((*e >> i) & 1) == 1 {
120 res.mul_assign(self);
121 }
122 }
123 }
124
125 res
126 }
127}