o1_utils/
foreign_field.rs1use crate::field_helpers::FieldHelpers;
7use ark_ff::{Field, PrimeField};
8use num_bigint::BigUint;
9use std::{
10 fmt::{Debug, Formatter},
11 ops::{Index, IndexMut},
12};
13
14#[derive(Clone, PartialEq, Eq)]
16pub struct ForeignElement<F: Field, const B: usize, const N: usize> {
18 pub limbs: [F; N],
20 len: usize,
22}
23
24impl<F: Field, const B: usize, const N: usize> ForeignElement<F, B, N> {
25 pub fn new(limbs: [F; N]) -> Self {
27 Self { limbs, len: N }
28 }
29
30 pub fn zero() -> Self {
32 Self {
33 limbs: [F::zero(); N],
34 len: N,
35 }
36 }
37
38 pub fn from_biguint(big: BigUint) -> Self {
41 let vec = ForeignElement::<F, B, N>::big_to_vec(big);
42
43 if vec.len() > N {
47 panic!("BigUint element is too large for N limbs");
48 }
49
50 let mut limbs = [F::zero(); N];
51 for (i, term) in vec.iter().enumerate() {
52 limbs[i] = *term;
53 }
54
55 Self {
56 limbs,
57 len: limbs.len(),
58 }
59 }
60
61 pub fn neg(&self, modulus: &BigUint) -> Self {
66 let big = self.to_biguint();
67 let ok = big % modulus;
68 let neg = modulus - ok;
69 Self::from_biguint(neg)
70 }
71
72 pub fn from_be(bytes: &[u8]) -> Self {
74 Self::from_biguint(BigUint::from_bytes_be(bytes))
75 }
76
77 pub fn to_biguint(&self) -> BigUint {
79 let mut bytes = vec![];
80 if B % 8 == 0 {
81 for limb in self.limbs {
83 let crumb = &limb.to_bytes()[0..B / 8];
84 bytes.extend_from_slice(crumb);
85 }
86 } else {
87 let mut bits: Vec<bool> = vec![];
88 for limb in self.limbs {
89 let f_bits_lower: Vec<bool> = limb.to_bits().into_iter().take(B).collect();
91 bits.extend(&f_bits_lower);
92 }
93
94 let bytes_len = if (B * N) % 8 == 0 {
95 (B * N) / 8
96 } else {
97 ((B * N) / 8) + 1
98 };
99 bytes = vec![0u8; bytes_len];
100 for i in 0..bits.len() {
101 bytes[i / 8] |= u8::from(bits[i]) << (i % 8);
102 }
103 }
104 BigUint::from_bytes_le(&bytes)
105 }
106
107 fn big_to_vec(fe: BigUint) -> Vec<F> {
111 if B % 8 == 0 {
112 let bytes = fe.to_bytes_le();
113 let chunks: Vec<&[u8]> = bytes.chunks(B / 8).collect();
114 chunks
115 .iter()
116 .map(|chunk| F::from_random_bytes(chunk).expect("failed to deserialize"))
117 .collect()
118 } else {
119 let mut bits = vec![]; assert!(
122 fe.bits() <= (B * N) as u64,
123 "BigUint too big to be represented in B*N elements"
124 );
125 for i in 0..B * N {
126 bits.push(fe.bit(i as u64));
127 }
128 let chunks: Vec<_> = bits.chunks(B).collect();
129 chunks
130 .into_iter()
131 .map(|chunk| F::from_bits(chunk).expect("failed to deserialize"))
132 .collect()
133 }
134 }
135}
136
137impl<F: PrimeField, const B: usize, const N: usize> ForeignElement<F, B, N> {
138 pub fn from_field(field: F) -> Self {
140 Self::from_biguint(field.into())
141 }
142}
143
144impl<F: Field, const B: usize, const N: usize> Index<usize> for ForeignElement<F, B, N> {
145 type Output = F;
146 fn index(&self, idx: usize) -> &Self::Output {
147 &self.limbs[idx]
148 }
149}
150
151impl<F: Field, const B: usize, const N: usize> IndexMut<usize> for ForeignElement<F, B, N> {
152 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
153 &mut self.limbs[idx]
154 }
155}
156
157impl<F: Field, const B: usize, const N: usize> Debug for ForeignElement<F, B, N> {
158 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
159 write!(f, "ForeignElement(")?;
160 for i in 0..self.len {
161 write!(f, "{:?}", self.limbs[i].to_hex())?;
162 if i != self.len - 1 {
163 write!(f, ", ")?;
164 }
165 }
166 write!(f, ")")
167 }
168}
169
170pub trait ForeignFieldHelpers<F, const B: usize> {
172 fn two_to_limb() -> F;
174
175 fn two_to_2limb() -> F;
177
178 fn two_to_3limb() -> F;
180}
181
182impl<F: Field, const B: usize, const N: usize> ForeignFieldHelpers<F, B>
183 for ForeignElement<F, B, N>
184{
185 fn two_to_limb() -> F {
186 F::from(2u64).pow([B as u64])
187 }
188
189 fn two_to_2limb() -> F {
190 F::from(2u64).pow([2 * B as u64])
191 }
192
193 fn two_to_3limb() -> F {
194 F::from(2u64).pow([3 * B as u64])
196 }
197}