ligerito_binary_fields/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
6
7mod elem;
8mod poly;
9pub mod simd;
10
11pub use elem::{BinaryElem16, BinaryElem32, BinaryElem64, BinaryElem128};
12pub use poly::{BinaryPoly16, BinaryPoly32, BinaryPoly64, BinaryPoly128, BinaryPoly256};
13pub use simd::{batch_mul_gf128, batch_add_gf128};
14
15#[cfg(feature = "std")]
17pub trait BinaryFieldElement: Send + Sync +
18 Sized + Copy + Clone + Default + PartialEq + Eq + core::fmt::Debug
19{
20 type Poly: BinaryPolynomial;
21
22 fn zero() -> Self;
23 fn one() -> Self;
24 fn from_poly(poly: Self::Poly) -> Self;
25 fn poly(&self) -> Self::Poly;
26 fn add(&self, other: &Self) -> Self;
27 fn mul(&self, other: &Self) -> Self;
28 fn inv(&self) -> Self;
29 fn pow(&self, exp: u64) -> Self;
30
31 fn from_bits(bits: u64) -> Self {
32 let mut result = Self::zero();
33 let mut power = Self::one();
34 let generator = Self::from_poly(Self::Poly::from_value(2));
35
36 for i in 0..64 {
37 if (bits >> i) & 1 == 1 {
38 result = result.add(&power);
39 }
40 if i < 63 {
41 power = power.mul(&generator);
42 }
43 }
44 result
45 }
46}
47
48#[cfg(not(feature = "std"))]
49pub trait BinaryFieldElement:
50 Sized + Copy + Clone + Default + PartialEq + Eq + core::fmt::Debug
51{
52 type Poly: BinaryPolynomial;
53
54 fn zero() -> Self;
55 fn one() -> Self;
56 fn from_poly(poly: Self::Poly) -> Self;
57 fn poly(&self) -> Self::Poly;
58 fn add(&self, other: &Self) -> Self;
59 fn mul(&self, other: &Self) -> Self;
60 fn inv(&self) -> Self;
61 fn pow(&self, exp: u64) -> Self;
62
63 fn from_bits(bits: u64) -> Self {
64 let mut result = Self::zero();
65 let mut power = Self::one();
66 let generator = Self::from_poly(Self::Poly::from_value(2));
67
68 for i in 0..64 {
69 if (bits >> i) & 1 == 1 {
70 result = result.add(&power);
71 }
72 if i < 63 {
73 power = power.mul(&generator);
74 }
75 }
76 result
77 }
78}
79
80pub trait BinaryPolynomial:
81 Sized + Copy + Clone + Default + PartialEq + Eq + core::fmt::Debug
82{
83 type Value: Copy + Clone + core::fmt::Debug;
84
85 fn zero() -> Self;
86 fn one() -> Self;
87 fn from_value(val: u64) -> Self;
88 fn value(&self) -> Self::Value;
89 fn add(&self, other: &Self) -> Self;
90 fn mul(&self, other: &Self) -> Self;
91 fn div_rem(&self, other: &Self) -> (Self, Self);
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_poly_operations() {
100 let a = BinaryPoly16::from_value(0x1234);
102 let b = BinaryPoly16::from_value(0x5678);
103 assert_eq!(a.add(&b).value(), 0x1234 ^ 0x5678);
104 assert_eq!(a.add(&a), BinaryPoly16::zero());
105
106 let a = BinaryPoly16::from_value(0x2);
108 let b = BinaryPoly16::from_value(0x3);
109 assert_eq!(a.mul(&b).value(), 0x6);
110 assert_eq!(a.mul(&BinaryPoly16::one()), a);
111
112 let a = BinaryPoly16::from_value(0x15); let b = BinaryPoly16::from_value(0x3); let (q, r) = a.div_rem(&b);
116 assert_eq!(a, q.mul(&b).add(&r));
117 }
118
119 #[test]
120 fn test_field_axioms() {
121 macro_rules! test_field {
123 ($elem:ty, $val1:expr, $val2:expr, $val3:expr) => {
124 let a = <$elem>::from_value($val1);
125 let b = <$elem>::from_value($val2);
126 let c = <$elem>::from_value($val3);
127
128 assert_eq!(a.add(&b.add(&c)), a.add(&b).add(&c));
130 assert_eq!(a.mul(&b.mul(&c)), a.mul(&b).mul(&c));
131
132 assert_eq!(a.add(&b), b.add(&a));
134 assert_eq!(a.mul(&b), b.mul(&a));
135
136 assert_eq!(a.mul(&b.add(&c)), a.mul(&b).add(&a.mul(&c)));
138
139 assert_eq!(a.add(&<$elem>::zero()), a);
141 assert_eq!(a.mul(&<$elem>::one()), a);
142
143 assert_eq!(a.add(&a), <$elem>::zero());
145 if a != <$elem>::zero() {
146 assert_eq!(a.mul(&a.inv()), <$elem>::one());
147 }
148 };
149 }
150
151 test_field!(BinaryElem16, 0x1234, 0x5678, 0x9ABC);
152 test_field!(BinaryElem32, 0x12345678, 0x9ABCDEF0, 0x11111111);
153 test_field!(BinaryElem128, 0x123456789ABCDEF0123456789ABCDEF0,
154 0xFEDCBA9876543210FEDCBA9876543210, 0x1111111111111111111111111111111);
155 }
156
157 #[test]
158 fn test_fermat_little_theorem() {
159 let a = BinaryElem16::from_value(0x1234);
161 assert_eq!(a.pow(65535), BinaryElem16::one()); assert_eq!(a.pow(65536), a);
165 }
166
167 #[test]
168 #[should_panic(expected = "Cannot invert zero")]
169 fn test_zero_inverse_panics() {
170 let _ = BinaryElem16::zero().inv();
171 }
172
173 #[test]
174 fn test_from_bits() {
175 let elem = BinaryElem16::from_bits(0b11);
177 let expected = BinaryElem16::from_value(1).add(&BinaryElem16::from_value(2));
178 assert_eq!(elem, expected);
179
180 let elem = BinaryElem16::from_bits(0b10101);
182 let x = BinaryElem16::from_value(2);
183 let expected = x.pow(4).add(&x.pow(2)).add(&BinaryElem16::one());
184 assert_eq!(elem, expected);
185 }
186}
187
188#[cfg(test)]
189mod julia_compatibility_tests {
190 use super::*;
191
192 #[test]
193 fn test_julia_sage_vectors() {
194 let v_values: Vec<u128> = vec![
196 48843935073701397021918627474152975110,
197 257371465678647658219914792930422930533,
198 197874898248752057839214693713406247745,
199 86301329031543269357031453671330949739,
200 245592208151890074913079678553060805151,
201 191477208903117015546989222243599496680,
202 92830719409229016308089219817617750833,
203 264528954340572454088312978462893134650,
204 158998607558664949362678439274836957424,
205 187448928532932960560649099299315170550,
206 177534835847791156274472818404289166039,
207 307322189246381679156077507151623179879,
208 117208864575585467966316847685913785498,
209 332422437295611968587046799211069213610,
210 109428368893056851194159753059340120844,
211 197947890894953343492199130314470631788,
212 ];
213
214 let v: Vec<BinaryElem128> = v_values.iter()
215 .map(|&val| BinaryElem128::from_value(val))
216 .collect();
217
218 for (i, &val) in v_values.iter().enumerate() {
219 assert_eq!(v[i].poly().value(), val);
220 }
221 }
222
223 #[test]
224 fn test_julia_betas() {
225 let beta16 = BinaryElem128::from_value(44320122245670141922313918651005395719);
227 let _beta32 = BinaryElem128::from_value(23246355947528323030879441634950214446);
228
229 let mut bs16 = vec![BinaryElem128::one()];
231 for i in 1..16 {
232 bs16.push(bs16[i-1].mul(&beta16));
233 }
234
235 for i in 0..16 {
236 for j in (i+1)..16 {
237 assert_ne!(bs16[i], bs16[j]);
238 }
239 }
240 }
241
242 #[test]
243 fn test_large_multiplication() {
244 let cases = vec![
246 (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0u128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0u128),
247 (u128::MAX, u128::MAX),
248 (0x8000000000000000_0000000000000000u128, 0x8000000000000000_0000000000000000u128),
249 ];
250
251 for (a_val, b_val) in cases {
252 let a = BinaryElem128::from(a_val);
253 let b = BinaryElem128::from(b_val);
254
255 let _c = a.mul(&b);
256
257 if a != BinaryElem128::zero() {
259 let a_inv = a.inv();
260 assert_eq!(a.mul(&a_inv), BinaryElem128::one());
261 }
262 }
263 }
264
265 #[test]
266 fn test_field_embedding() {
267 let elem16 = BinaryElem16::from_value(0x1234);
269 let elem32: BinaryElem32 = elem16.into();
270 let elem64: BinaryElem64 = elem16.into();
271 let elem128: BinaryElem128 = elem16.into();
272
273 assert_eq!(elem32.poly().value() & 0xFFFF, 0x1234);
274 assert_eq!(elem64.poly().value() & 0xFFFF, 0x1234);
275 assert_eq!(elem128.poly().value() & 0xFFFF, 0x1234);
276 }
277}