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