1use std::{
4 any::TypeId,
5 fmt::{Debug, Display, Formatter},
6 iter::{Product, Sum},
7 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
8};
9
10use binius_utils::{
11 DeserializeBytes, SerializationError, SerializationMode, SerializeBytes,
12 bytes::{Buf, BufMut},
13};
14use bytemuck::{Pod, Zeroable};
15use rand::RngCore;
16use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
17
18use super::{
19 binary_field_arithmetic::TowerFieldArithmetic, error::Error, extension::ExtensionField,
20};
21use crate::{
22 Field,
23 underlier::{U1, U2, U4},
24};
25
26pub trait BinaryField: ExtensionField<BinaryField1b> {
28 const N_BITS: usize = Self::DEGREE;
29 const MULTIPLICATIVE_GENERATOR: Self;
30}
31
32pub trait TowerField: BinaryField + From<Self::Canonical>
40where
41 Self::Canonical: From<Self>,
42{
43 const TOWER_LEVEL: usize = Self::N_BITS.ilog2() as usize;
45
46 type Canonical: TowerField + SerializeBytes + DeserializeBytes;
50
51 fn min_tower_level(self) -> usize;
57
58 fn basis(iota: usize, i: usize) -> Result<Self, Error> {
61 if iota > Self::TOWER_LEVEL {
62 return Err(Error::ExtensionDegreeTooHigh);
63 }
64 let n_basis_elts = 1 << (Self::TOWER_LEVEL - iota);
65 if i >= n_basis_elts {
66 return Err(Error::IndexOutOfRange {
67 index: i,
68 max: n_basis_elts,
69 });
70 }
71 <Self as ExtensionField<BinaryField1b>>::basis_checked(i << iota)
72 }
73
74 fn mul_primitive(self, iota: usize) -> Result<Self, Error> {
85 Ok(self * <Self as ExtensionField<BinaryField1b>>::basis_checked(1 << iota)?)
86 }
87}
88
89#[inline]
97pub fn ext_basis<FExt, FSub>(i: usize) -> FExt
98where
99 FSub: Field,
100 FExt: ExtensionField<FSub>,
101{
102 <FExt as ExtensionField<FSub>>::basis(i)
103}
104
105pub(super) trait TowerExtensionField:
106 TowerField
107 + ExtensionField<Self::DirectSubfield>
108 + From<(Self::DirectSubfield, Self::DirectSubfield)>
109 + Into<(Self::DirectSubfield, Self::DirectSubfield)>
110{
111 type DirectSubfield: TowerField;
112}
113
114macro_rules! binary_field {
116 ($vis:vis $name:ident($typ:ty), $gen:expr) => {
117 #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Zeroable, bytemuck::TransparentWrapper)]
118 #[repr(transparent)]
119 $vis struct $name(pub(crate) $typ);
120
121 impl $name {
122 pub const fn new(value: $typ) -> Self {
123 Self(value)
124 }
125
126 pub const fn val(self) -> $typ {
127 self.0
128 }
129 }
130
131 unsafe impl $crate::underlier::WithUnderlier for $name {
132 type Underlier = $typ;
133
134 fn to_underlier(self) -> Self::Underlier {
135 ::bytemuck::TransparentWrapper::peel(self)
136 }
137
138 fn to_underlier_ref(&self) -> &Self::Underlier {
139 ::bytemuck::TransparentWrapper::peel_ref(self)
140 }
141
142 fn to_underlier_ref_mut(&mut self) -> &mut Self::Underlier {
143 ::bytemuck::TransparentWrapper::peel_mut(self)
144 }
145
146 fn to_underliers_ref(val: &[Self]) -> &[Self::Underlier] {
147 ::bytemuck::TransparentWrapper::peel_slice(val)
148 }
149
150 fn to_underliers_ref_mut(val: &mut [Self]) -> &mut [Self::Underlier] {
151 ::bytemuck::TransparentWrapper::peel_slice_mut(val)
152 }
153
154 fn from_underlier(val: Self::Underlier) -> Self {
155 ::bytemuck::TransparentWrapper::wrap(val)
156 }
157
158 fn from_underlier_ref(val: &Self::Underlier) -> &Self {
159 ::bytemuck::TransparentWrapper::wrap_ref(val)
160 }
161
162 fn from_underlier_ref_mut(val: &mut Self::Underlier) -> &mut Self {
163 ::bytemuck::TransparentWrapper::wrap_mut(val)
164 }
165
166 fn from_underliers_ref(val: &[Self::Underlier]) -> &[Self] {
167 ::bytemuck::TransparentWrapper::wrap_slice(val)
168 }
169
170 fn from_underliers_ref_mut(val: &mut [Self::Underlier]) -> &mut [Self] {
171 ::bytemuck::TransparentWrapper::wrap_slice_mut(val)
172 }
173 }
174
175 impl Neg for $name {
176 type Output = Self;
177
178 fn neg(self) -> Self::Output {
179 self
180 }
181 }
182
183 impl Add<Self> for $name {
184 type Output = Self;
185
186 #[allow(clippy::suspicious_arithmetic_impl)]
187 fn add(self, rhs: Self) -> Self::Output {
188 $name(self.0 ^ rhs.0)
189 }
190 }
191
192 impl Add<&Self> for $name {
193 type Output = Self;
194
195 #[allow(clippy::suspicious_arithmetic_impl)]
196 fn add(self, rhs: &Self) -> Self::Output {
197 $name(self.0 ^ rhs.0)
198 }
199 }
200
201 impl Sub<Self> for $name {
202 type Output = Self;
203
204 #[allow(clippy::suspicious_arithmetic_impl)]
205 fn sub(self, rhs: Self) -> Self::Output {
206 $name(self.0 ^ rhs.0)
207 }
208 }
209
210 impl Sub<&Self> for $name {
211 type Output = Self;
212
213 #[allow(clippy::suspicious_arithmetic_impl)]
214 fn sub(self, rhs: &Self) -> Self::Output {
215 $name(self.0 ^ rhs.0)
216 }
217 }
218
219 impl Mul<Self> for $name {
220 type Output = Self;
221
222 fn mul(self, rhs: Self) -> Self::Output {
223 $crate::tracing::trace_multiplication!($name);
224
225 TowerFieldArithmetic::multiply(self, rhs)
226 }
227 }
228
229 impl Mul<&Self> for $name {
230 type Output = Self;
231
232 fn mul(self, rhs: &Self) -> Self::Output {
233 self * *rhs
234 }
235 }
236
237 impl AddAssign<Self> for $name {
238 fn add_assign(&mut self, rhs: Self) {
239 *self = *self + rhs;
240 }
241 }
242
243 impl AddAssign<&Self> for $name {
244 fn add_assign(&mut self, rhs: &Self) {
245 *self = *self + *rhs;
246 }
247 }
248
249 impl SubAssign<Self> for $name {
250 fn sub_assign(&mut self, rhs: Self) {
251 *self = *self - rhs;
252 }
253 }
254
255 impl SubAssign<&Self> for $name {
256 fn sub_assign(&mut self, rhs: &Self) {
257 *self = *self - *rhs;
258 }
259 }
260
261 impl MulAssign<Self> for $name {
262 fn mul_assign(&mut self, rhs: Self) {
263 *self = *self * rhs;
264 }
265 }
266
267 impl MulAssign<&Self> for $name {
268 fn mul_assign(&mut self, rhs: &Self) {
269 *self = *self * rhs;
270 }
271 }
272
273 impl Sum<Self> for $name {
274 fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
275 iter.fold(Self::ZERO, |acc, x| acc + x)
276 }
277 }
278
279 impl<'a> Sum<&'a Self> for $name {
280 fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
281 iter.fold(Self::ZERO, |acc, x| acc + x)
282 }
283 }
284
285 impl Product<Self> for $name {
286 fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
287 iter.fold(Self::ONE, |acc, x| acc * x)
288 }
289 }
290
291 impl<'a> Product<&'a Self> for $name {
292 fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
293 iter.fold(Self::ONE, |acc, x| acc * x)
294 }
295 }
296
297 impl ConstantTimeEq for $name {
298 fn ct_eq(&self, other: &Self) -> Choice {
299 self.0.ct_eq(&other.0)
300 }
301 }
302
303 impl ConditionallySelectable for $name {
304 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
305 Self(ConditionallySelectable::conditional_select(&a.0, &b.0, choice))
306 }
307 }
308
309 impl crate::arithmetic_traits::Square for $name {
310 fn square(self) -> Self {
311 TowerFieldArithmetic::square(self)
312 }
313 }
314
315 impl Field for $name {
316 const ZERO: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ZERO);
317 const ONE: Self = $name::new(<$typ as $crate::underlier::UnderlierWithBitOps>::ONE);
318 const CHARACTERISTIC: usize = 2;
319
320 fn random(mut rng: impl RngCore) -> Self {
321 Self(<$typ as $crate::underlier::Random>::random(&mut rng))
322 }
323
324 fn double(&self) -> Self {
325 Self::ZERO
326 }
327 }
328
329 impl Display for $name {
330 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
331 write!(f, "0x{repr:0>width$x}", repr=self.val(), width=Self::N_BITS.max(4) / 4)
332 }
333 }
334
335 impl Debug for $name {
336 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
337 let structure_name = std::any::type_name::<$name>().split("::").last().expect("exist");
338
339 write!(f, "{}({})",structure_name, self)
340 }
341 }
342
343 impl BinaryField for $name {
344 const MULTIPLICATIVE_GENERATOR: $name = $name($gen);
345 }
346
347 impl From<$typ> for $name {
348 fn from(val: $typ) -> Self {
349 return Self(val)
350 }
351 }
352
353 impl From<$name> for $typ {
354 fn from(val: $name) -> Self {
355 return val.0
356 }
357 }
358 }
359}
360
361pub(crate) use binary_field;
362
363macro_rules! binary_subfield_mul_packed_128b {
364 ($subfield_name:ident, $field_name:ident, $subfield_packed:ident) => {
365 cfg_if::cfg_if! {
366 if #[cfg(all(target_arch = "x86_64", target_feature = "gfni", target_feature = "sse2"))] {
369 impl Mul<$subfield_name> for $field_name {
370 type Output = Self;
371
372 fn mul(self, rhs: $subfield_name) -> Self::Output {
373 use bytemuck::must_cast;
374 use crate::$subfield_packed;
375
376 let a = must_cast::<_, $subfield_packed>(self);
377 must_cast(a * rhs)
378 }
379 }
380 } else {
381 impl Mul<$subfield_name> for $field_name {
382 type Output = Self;
383
384 fn mul(self, rhs: $subfield_name) -> Self::Output {
385 $crate::tracing::trace_multiplication!($field_name, $subfield_name);
386
387 let (a, b) = self.into();
388 (a * rhs, b * rhs).into()
389 }
390 }
391 }
392 }
393 };
394}
395
396pub(crate) use binary_subfield_mul_packed_128b;
397
398macro_rules! mul_by_binary_field_1b {
399 ($name:ident) => {
400 impl Mul<BinaryField1b> for $name {
401 type Output = Self;
402
403 #[inline]
404 #[allow(clippy::suspicious_arithmetic_impl)]
405 fn mul(self, rhs: BinaryField1b) -> Self::Output {
406 use $crate::underlier::{UnderlierWithBitOps, WithUnderlier};
407
408 $crate::tracing::trace_multiplication!(BinaryField128b, BinaryField1b);
409
410 Self(self.0 & <$name as WithUnderlier>::Underlier::fill_with_bit(u8::from(rhs.0)))
411 }
412 }
413 };
414}
415
416pub(crate) use mul_by_binary_field_1b;
417
418macro_rules! binary_tower_subfield_mul {
419 (BinaryField1b, $name:ident) => {
421 mul_by_binary_field_1b!($name);
422 };
423 (BinaryField8b, BinaryField128b) => {
425 $crate::binary_field::binary_subfield_mul_packed_128b!(
426 BinaryField8b,
427 BinaryField128b,
428 PackedBinaryField16x8b
429 );
430 };
431 (BinaryField16b, BinaryField128b) => {
433 $crate::binary_field::binary_subfield_mul_packed_128b!(
434 BinaryField16b,
435 BinaryField128b,
436 PackedBinaryField8x16b
437 );
438 };
439 (BinaryField32b, BinaryField128b) => {
441 $crate::binary_field::binary_subfield_mul_packed_128b!(
442 BinaryField32b,
443 BinaryField128b,
444 PackedBinaryField4x32b
445 );
446 };
447 (BinaryField64b, BinaryField128b) => {
449 $crate::binary_field::binary_subfield_mul_packed_128b!(
450 BinaryField64b,
451 BinaryField128b,
452 PackedBinaryField2x64b
453 );
454 };
455 (AESTowerField8b, AESTowerField128b) => {
457 $crate::binary_field::binary_subfield_mul_packed_128b!(
458 AESTowerField8b,
459 AESTowerField128b,
460 PackedAESBinaryField16x8b
461 );
462 };
463 (BinaryField16b, AESTowerField128b) => {
465 $crate::binary_field::binary_subfield_mul_packed_128b!(
466 AESTowerField16b,
467 AESTowerField128b,
468 PackedAESBinaryField8x16b
469 );
470 };
471 (BinaryField32b, AESTowerField128b) => {
473 $crate::binary_field::binary_subfield_mul_packed_128b!(
474 AESTowerField32b,
475 AESTowerField128b,
476 PackedAESBinaryField4x32b
477 );
478 };
479 (BinaryField64b, AESTowerField128b) => {
481 $crate::binary_field::binary_subfield_mul_packed_128b!(
482 AESTowerField64b,
483 AESTowerField128b,
484 PackedAESBinaryField2x64b
485 );
486 };
487 ($subfield_name:ident, $name:ident) => {
488 impl Mul<$subfield_name> for $name {
489 type Output = Self;
490
491 fn mul(self, rhs: $subfield_name) -> Self::Output {
492 $crate::tracing::trace_multiplication!($name, $subfield_name);
493
494 let (a, b) = self.into();
495 (a * rhs, b * rhs).into()
496 }
497 }
498 };
499}
500
501pub(crate) use binary_tower_subfield_mul;
502
503macro_rules! impl_field_extension {
504 ($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
505 impl TryFrom<$name> for $subfield_name {
506 type Error = ();
507
508 #[inline]
509 fn try_from(elem: $name) -> Result<Self, Self::Error> {
510 use $crate::underlier::NumCast;
511
512 if elem.0 >> $subfield_name::N_BITS
513 == <$typ as $crate::underlier::UnderlierWithBitOps>::ZERO
514 {
515 Ok($subfield_name::new(<$subfield_typ>::num_cast_from(elem.val())))
516 } else {
517 Err(())
518 }
519 }
520 }
521
522 impl From<$subfield_name> for $name {
523 #[inline]
524 fn from(elem: $subfield_name) -> Self {
525 $name::new(<$typ>::from(elem.val()))
526 }
527 }
528
529 impl Add<$subfield_name> for $name {
530 type Output = Self;
531
532 #[inline]
533 fn add(self, rhs: $subfield_name) -> Self::Output {
534 self + Self::from(rhs)
535 }
536 }
537
538 impl Sub<$subfield_name> for $name {
539 type Output = Self;
540
541 #[inline]
542 fn sub(self, rhs: $subfield_name) -> Self::Output {
543 self - Self::from(rhs)
544 }
545 }
546
547 impl AddAssign<$subfield_name> for $name {
548 #[inline]
549 fn add_assign(&mut self, rhs: $subfield_name) {
550 *self = *self + rhs;
551 }
552 }
553
554 impl SubAssign<$subfield_name> for $name {
555 #[inline]
556 fn sub_assign(&mut self, rhs: $subfield_name) {
557 *self = *self - rhs;
558 }
559 }
560
561 impl MulAssign<$subfield_name> for $name {
562 #[inline]
563 fn mul_assign(&mut self, rhs: $subfield_name) {
564 *self = *self * rhs;
565 }
566 }
567
568 impl Add<$name> for $subfield_name {
569 type Output = $name;
570
571 #[inline]
572 fn add(self, rhs: $name) -> Self::Output {
573 rhs + self
574 }
575 }
576
577 impl Sub<$name> for $subfield_name {
578 type Output = $name;
579
580 #[allow(clippy::suspicious_arithmetic_impl)]
581 #[inline]
582 fn sub(self, rhs: $name) -> Self::Output {
583 rhs + self
584 }
585 }
586
587 impl Mul<$name> for $subfield_name {
588 type Output = $name;
589
590 #[inline]
591 fn mul(self, rhs: $name) -> Self::Output {
592 rhs * self
593 }
594 }
595
596 impl ExtensionField<$subfield_name> for $name {
597 const LOG_DEGREE: usize = $log_degree;
598
599 #[inline]
600 fn basis_checked(i: usize) -> Result<Self, Error> {
601 use $crate::underlier::UnderlierWithBitOps;
602
603 if i >= 1 << $log_degree {
604 return Err(Error::ExtensionDegreeMismatch);
605 }
606 Ok(Self::new(<$typ>::ONE << (i * $subfield_name::N_BITS)))
607 }
608
609 #[inline]
610 fn from_bases_sparse(
611 base_elems: impl IntoIterator<Item = $subfield_name>,
612 log_stride: usize,
613 ) -> Result<Self, Error> {
614 use $crate::underlier::UnderlierWithBitOps;
615
616 debug_assert!($name::N_BITS.is_power_of_two());
617 let shift_step = ($subfield_name::N_BITS << log_stride) & ($name::N_BITS - 1);
618 let mut value = <$typ>::ZERO;
619 let mut shift = 0;
620
621 for elem in base_elems.into_iter() {
622 if shift >= $name::N_BITS {
623 return Err(Error::ExtensionDegreeMismatch);
624 }
625 value |= <$typ>::from(elem.val()) << shift;
626 shift += shift_step;
627 }
628
629 Ok(Self::new(value))
630 }
631
632 #[inline]
633 fn iter_bases(&self) -> impl Iterator<Item = $subfield_name> {
634 use $crate::underlier::{WithUnderlier, IterationMethods, IterationStrategy};
635 use binius_utils::iter::IterExtensions;
636
637 IterationMethods::<<$subfield_name as WithUnderlier>::Underlier, Self::Underlier>::ref_iter(&self.0)
638 .map_skippable($subfield_name::from)
639 }
640
641 #[inline]
642 fn into_iter_bases(self) -> impl Iterator<Item = $subfield_name> {
643 use $crate::underlier::{WithUnderlier, IterationMethods, IterationStrategy};
644 use binius_utils::iter::IterExtensions;
645
646 IterationMethods::<<$subfield_name as WithUnderlier>::Underlier, Self::Underlier>::value_iter(self.0)
647 .map_skippable($subfield_name::from)
648 }
649
650 #[inline]
651 unsafe fn get_base_unchecked(&self, i: usize) -> $subfield_name {
652 use $crate::underlier::{WithUnderlier, UnderlierWithBitOps};
653 unsafe {
654 $subfield_name::from_underlier(self.to_underlier().get_subvalue(i))
655 }
656 }
657 }
658 };
659}
660
661pub(crate) use impl_field_extension;
662
663pub(super) trait MulPrimitive: Sized {
666 fn mul_primitive(self, iota: usize) -> Result<Self, Error>;
667}
668
669#[macro_export]
670macro_rules! binary_tower {
671 (BinaryField1b($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
672 binary_tower!([BinaryField1b::TOWER_LEVEL]; BinaryField1b($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
673 };
674 ($subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
675 binary_tower!([BinaryField1b::TOWER_LEVEL, $subfield_name::TOWER_LEVEL]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
676 };
677 ([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty)) => {
678 binary_tower!([$($valid_tower_levels)*]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ, $name));
679 };
680 ([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty, $canonical:ident)) => {
681 impl From<$name> for ($subfield_name, $subfield_name) {
682 #[inline]
683 fn from(src: $name) -> ($subfield_name, $subfield_name) {
684 use $crate::underlier::NumCast;
685
686 let lo = <$subfield_typ>::num_cast_from(src.0);
687 let hi = <$subfield_typ>::num_cast_from(src.0 >> $subfield_name::N_BITS);
688 ($subfield_name::new(lo), $subfield_name::new(hi))
689 }
690 }
691
692 impl From<($subfield_name, $subfield_name)> for $name {
693 #[inline]
694 fn from((a, b): ($subfield_name, $subfield_name)) -> Self {
695 $name(<$typ>::from(a.val()) | (<$typ>::from(b.val()) << $subfield_name::N_BITS))
696 }
697 }
698
699 impl TowerField for $name {
700 const TOWER_LEVEL: usize = { $subfield_name::TOWER_LEVEL + 1 };
701
702 type Canonical = $canonical;
703
704 fn min_tower_level(self) -> usize {
705 let zero = <$typ as $crate::underlier::UnderlierWithBitOps>::ZERO;
706 for level in [$($valid_tower_levels)*] {
707 if self.0 >> (1 << level) == zero {
708 return level;
709 }
710 }
711 Self::TOWER_LEVEL
712 }
713
714 fn mul_primitive(self, iota: usize) -> Result<Self, Error> {
715 <Self as $crate::binary_field::MulPrimitive>::mul_primitive(self, iota)
716 }
717 }
718
719 impl $crate::TowerExtensionField for $name {
720 type DirectSubfield = $subfield_name;
721 }
722
723 binary_tower!($subfield_name($subfield_typ) < @1 => $name($typ));
724 };
725 ([$($valid_tower_levels:tt)*]; $subfield_name:ident($subfield_typ:ty $(, $canonical_subfield:ident)?) < $name:ident($typ:ty $(, $canonical:ident)?) $(< $extfield_name:ident($extfield_typ:ty $(, $canonical_ext:ident)?))+) => {
726 binary_tower!([$($valid_tower_levels)*]; $subfield_name($subfield_typ $(, $canonical_subfield)?) < $name($typ $(, $canonical)?));
727 binary_tower!([$($valid_tower_levels)*, $name::TOWER_LEVEL]; $name($typ $(, $canonical)?) $(< $extfield_name($extfield_typ $(, $canonical_ext)?))+);
728 binary_tower!($subfield_name($subfield_typ) < @2 => $($extfield_name($extfield_typ))<+);
729 };
730 ($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty)) => {
731 $crate::binary_field::impl_field_extension!($subfield_name($subfield_typ) < @$log_degree => $name($typ));
732 $crate::binary_field::binary_tower_subfield_mul!($subfield_name, $name);
733 };
734 ($subfield_name:ident($subfield_typ:ty) < @$log_degree:expr => $name:ident($typ:ty) $(< $extfield_name:ident($extfield_typ:ty))+) => {
735 binary_tower!($subfield_name($subfield_typ) < @$log_degree => $name($typ));
736 binary_tower!($subfield_name($subfield_typ) < @$log_degree+1 => $($extfield_name($extfield_typ))<+);
737 };
738}
739
740binary_field!(pub BinaryField1b(U1), U1::new(0x1));
741binary_field!(pub BinaryField2b(U2), U2::new(0x2));
742binary_field!(pub BinaryField4b(U4), U4::new(0x5));
743binary_field!(pub BinaryField8b(u8), 0x2D);
744binary_field!(pub BinaryField16b(u16), 0xE2DE);
745binary_field!(pub BinaryField32b(u32), 0x03E21CEA);
746binary_field!(pub BinaryField64b(u64), 0x070F870DCD9C1D88);
747binary_field!(pub BinaryField128b(u128), 0x2E895399AF449ACE499596F6E5FCCAFAu128);
748
749unsafe impl Pod for BinaryField8b {}
750unsafe impl Pod for BinaryField16b {}
751unsafe impl Pod for BinaryField32b {}
752unsafe impl Pod for BinaryField64b {}
753unsafe impl Pod for BinaryField128b {}
754
755binary_tower!(
756 BinaryField1b(U1)
757 < BinaryField2b(U2)
758 < BinaryField4b(U4)
759 < BinaryField8b(u8)
760 < BinaryField16b(u16)
761 < BinaryField32b(u32)
762 < BinaryField64b(u64)
763 < BinaryField128b(u128)
764);
765
766#[inline(always)]
767pub fn is_canonical_tower<F: TowerField>() -> bool {
768 TypeId::of::<F::Canonical>() == TypeId::of::<F>()
769}
770
771macro_rules! serialize_deserialize {
772 ($bin_type:ty) => {
773 impl SerializeBytes for $bin_type {
774 fn serialize(
775 &self,
776 write_buf: impl BufMut,
777 mode: SerializationMode,
778 ) -> Result<(), SerializationError> {
779 self.0.serialize(write_buf, mode)
780 }
781 }
782
783 impl DeserializeBytes for $bin_type {
784 fn deserialize(
785 read_buf: impl Buf,
786 mode: SerializationMode,
787 ) -> Result<Self, SerializationError> {
788 Ok(Self(DeserializeBytes::deserialize(read_buf, mode)?))
789 }
790 }
791 };
792}
793
794serialize_deserialize!(BinaryField1b);
795serialize_deserialize!(BinaryField2b);
796serialize_deserialize!(BinaryField4b);
797serialize_deserialize!(BinaryField8b);
798serialize_deserialize!(BinaryField16b);
799serialize_deserialize!(BinaryField32b);
800serialize_deserialize!(BinaryField64b);
801serialize_deserialize!(BinaryField128b);
802
803impl From<BinaryField1b> for Choice {
804 fn from(val: BinaryField1b) -> Self {
805 Self::from(val.val().val())
806 }
807}
808
809impl BinaryField1b {
810 #[inline]
815 pub unsafe fn new_unchecked(val: u8) -> Self {
816 debug_assert!(val < 2);
817
818 Self::new(U1::new_unchecked(val))
819 }
820}
821
822impl From<u8> for BinaryField1b {
823 #[inline]
824 fn from(val: u8) -> Self {
825 Self::new(U1::new(val))
826 }
827}
828
829impl From<BinaryField1b> for u8 {
830 #[inline]
831 fn from(value: BinaryField1b) -> Self {
832 value.val().into()
833 }
834}
835
836impl From<bool> for BinaryField1b {
837 #[inline]
838 fn from(value: bool) -> Self {
839 Self::from(U1::new_unchecked(value.into()))
840 }
841}
842
843impl BinaryField2b {
844 #[inline]
849 pub unsafe fn new_unchecked(val: u8) -> Self {
850 debug_assert!(val < 4);
851
852 Self::new(U2::new_unchecked(val))
853 }
854}
855
856impl From<u8> for BinaryField2b {
857 #[inline]
858 fn from(val: u8) -> Self {
859 Self::new(U2::new(val))
860 }
861}
862
863impl From<BinaryField2b> for u8 {
864 #[inline]
865 fn from(value: BinaryField2b) -> Self {
866 value.val().into()
867 }
868}
869
870impl BinaryField4b {
871 #[inline]
876 pub unsafe fn new_unchecked(val: u8) -> Self {
877 debug_assert!(val < 16);
878
879 Self::new(U4::new_unchecked(val))
880 }
881}
882
883impl From<u8> for BinaryField4b {
884 #[inline]
885 fn from(val: u8) -> Self {
886 Self::new(U4::new(val))
887 }
888}
889
890impl From<BinaryField4b> for u8 {
891 #[inline]
892 fn from(value: BinaryField4b) -> Self {
893 value.val().into()
894 }
895}
896
897#[cfg(test)]
898pub(crate) mod tests {
899 use binius_utils::{SerializationMode, bytes::BytesMut};
900 use proptest::prelude::*;
901
902 use super::{
903 BinaryField1b as BF1, BinaryField2b as BF2, BinaryField4b as BF4, BinaryField8b as BF8,
904 BinaryField16b as BF16, BinaryField64b as BF64, *,
905 };
906
907 #[test]
908 fn test_gf2_add() {
909 assert_eq!(BF1::from(0) + BF1::from(0), BF1::from(0));
910 assert_eq!(BF1::from(0) + BF1::from(1), BF1::from(1));
911 assert_eq!(BF1::from(1) + BF1::from(0), BF1::from(1));
912 assert_eq!(BF1::from(1) + BF1::from(1), BF1::from(0));
913 }
914
915 #[test]
916 fn test_gf2_sub() {
917 assert_eq!(BF1::from(0) - BF1::from(0), BF1::from(0));
918 assert_eq!(BF1::from(0) - BF1::from(1), BF1::from(1));
919 assert_eq!(BF1::from(1) - BF1::from(0), BF1::from(1));
920 assert_eq!(BF1::from(1) - BF1::from(1), BF1::from(0));
921 }
922
923 #[test]
924 fn test_gf2_mul() {
925 assert_eq!(BF1::from(0) * BF1::from(0), BF1::from(0));
926 assert_eq!(BF1::from(0) * BF1::from(1), BF1::from(0));
927 assert_eq!(BF1::from(1) * BF1::from(0), BF1::from(0));
928 assert_eq!(BF1::from(1) * BF1::from(1), BF1::from(1));
929 }
930
931 #[test]
932 fn test_bin2b_mul() {
933 assert_eq!(BF2::from(0x1) * BF2::from(0x0), BF2::from(0x0));
934 assert_eq!(BF2::from(0x1) * BF2::from(0x1), BF2::from(0x1));
935 assert_eq!(BF2::from(0x0) * BF2::from(0x3), BF2::from(0x0));
936 assert_eq!(BF2::from(0x1) * BF2::from(0x2), BF2::from(0x2));
937 assert_eq!(BF2::from(0x0) * BF2::from(0x1), BF2::from(0x0));
938 assert_eq!(BF2::from(0x0) * BF2::from(0x2), BF2::from(0x0));
939 assert_eq!(BF2::from(0x1) * BF2::from(0x3), BF2::from(0x3));
940 assert_eq!(BF2::from(0x3) * BF2::from(0x0), BF2::from(0x0));
941 assert_eq!(BF2::from(0x2) * BF2::from(0x0), BF2::from(0x0));
942 assert_eq!(BF2::from(0x2) * BF2::from(0x2), BF2::from(0x3));
943 }
944
945 #[test]
946 fn test_bin4b_mul() {
947 assert_eq!(BF4::from(0x0) * BF4::from(0x0), BF4::from(0x0));
948 assert_eq!(BF4::from(0x9) * BF4::from(0x0), BF4::from(0x0));
949 assert_eq!(BF4::from(0x9) * BF4::from(0x4), BF4::from(0xa));
950 assert_eq!(BF4::from(0x6) * BF4::from(0x0), BF4::from(0x0));
951 assert_eq!(BF4::from(0x6) * BF4::from(0x7), BF4::from(0xc));
952 assert_eq!(BF4::from(0x2) * BF4::from(0x0), BF4::from(0x0));
953 assert_eq!(BF4::from(0x2) * BF4::from(0xa), BF4::from(0xf));
954 assert_eq!(BF4::from(0x1) * BF4::from(0x0), BF4::from(0x0));
955 assert_eq!(BF4::from(0x1) * BF4::from(0x8), BF4::from(0x8));
956 assert_eq!(BF4::from(0x9) * BF4::from(0xb), BF4::from(0x8));
957 }
958
959 #[test]
960 fn test_bin8b_mul() {
961 assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
962 assert_eq!(BF8::new(0x1b) * BF8::new(0xa8), BF8::new(0x09));
963 assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
964 assert_eq!(BF8::new(0x76) * BF8::new(0x51), BF8::new(0x84));
965 assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
966 assert_eq!(BF8::new(0xe4) * BF8::new(0x8f), BF8::new(0x0e));
967 assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
968 assert_eq!(BF8::new(0x42) * BF8::new(0x66), BF8::new(0xea));
969 assert_eq!(BF8::new(0x00) * BF8::new(0x00), BF8::new(0x00));
970 assert_eq!(BF8::new(0x68) * BF8::new(0xd0), BF8::new(0xc5));
971 }
972
973 #[test]
974 fn test_bin16b_mul() {
975 assert_eq!(BF16::new(0x0000) * BF16::new(0x0000), BF16::new(0x0000));
976 assert_eq!(BF16::new(0x48a8) * BF16::new(0xf8a4), BF16::new(0x3656));
977 assert_eq!(BF16::new(0xf8a4) * BF16::new(0xf8a4), BF16::new(0xe7e6));
978 assert_eq!(BF16::new(0xf8a4) * BF16::new(0xf8a4), BF16::new(0xe7e6));
979 assert_eq!(BF16::new(0x448b) * BF16::new(0x0585), BF16::new(0x47d3));
980 assert_eq!(BF16::new(0x0585) * BF16::new(0x0585), BF16::new(0x8057));
981 assert_eq!(BF16::new(0x0001) * BF16::new(0x6a57), BF16::new(0x6a57));
982 assert_eq!(BF16::new(0x0001) * BF16::new(0x0001), BF16::new(0x0001));
983 assert_eq!(BF16::new(0xf62c) * BF16::new(0x0dbd), BF16::new(0xa9da));
984 assert_eq!(BF16::new(0xf62c) * BF16::new(0xf62c), BF16::new(0x37bb));
985 }
986
987 #[test]
988 fn test_bin64b_mul() {
989 assert_eq!(
990 BF64::new(0x0000000000000000) * BF64::new(0x0000000000000000),
991 BF64::new(0x0000000000000000)
992 );
993 assert_eq!(
994 BF64::new(0xc84d619110831cef) * BF64::new(0x000000000000a14f),
995 BF64::new(0x3565086d6b9ef595)
996 );
997 assert_eq!(
998 BF64::new(0xa14f580107030300) * BF64::new(0x000000000000f404),
999 BF64::new(0x83e7239eb819a6ac)
1000 );
1001 assert_eq!(
1002 BF64::new(0xf404210706070403) * BF64::new(0x0000000000006b44),
1003 BF64::new(0x790541c54ffa2ede)
1004 );
1005 assert_eq!(
1006 BF64::new(0x6b44000404006b44) * BF64::new(0x0000000000000013),
1007 BF64::new(0x7018004c4c007018)
1008 );
1009 assert_eq!(
1010 BF64::new(0x6b44000404006b44) * BF64::new(0x0000000000000013),
1011 BF64::new(0x7018004c4c007018)
1012 );
1013 assert_eq!(
1014 BF64::new(0x6b44000404006b44) * BF64::new(0x6b44000404006b44),
1015 BF64::new(0xc59751e6f1769000)
1016 );
1017 assert_eq!(
1018 BF64::new(0x6b44000404006b44) * BF64::new(0x6b44000404006b44),
1019 BF64::new(0xc59751e6f1769000)
1020 );
1021 assert_eq!(
1022 BF64::new(0x00000000000000eb) * BF64::new(0x000000000000fba1),
1023 BF64::new(0x0000000000007689)
1024 );
1025 assert_eq!(
1026 BF64::new(0x00000000000000eb) * BF64::new(0x000000000000fba1),
1027 BF64::new(0x0000000000007689)
1028 );
1029 }
1030
1031 pub(crate) fn is_binary_field_valid_generator<F: BinaryField>() -> bool {
1032 let mut order = if F::N_BITS == 128 {
1034 u128::MAX
1035 } else {
1036 (1 << F::N_BITS) - 1
1037 };
1038
1039 let mut factorization = Vec::new();
1041
1042 let mut prime = 2;
1043 while prime * prime <= order {
1044 while order % prime == 0 {
1045 order /= prime;
1046 factorization.push(prime);
1047 }
1048
1049 prime += if prime > 2 { 2 } else { 1 };
1050 }
1051
1052 if order > 1 {
1053 factorization.push(order);
1054 }
1055
1056 for mask in 0..(1 << factorization.len()) {
1058 let mut divisor = 1;
1059
1060 for (bit_index, &prime) in factorization.iter().enumerate() {
1061 if (1 << bit_index) & mask != 0 {
1062 divisor *= prime;
1063 }
1064 }
1065
1066 divisor = divisor.reverse_bits();
1068
1069 let mut pow_divisor = F::ONE;
1070 while divisor > 0 {
1071 pow_divisor *= pow_divisor;
1072
1073 if divisor & 1 != 0 {
1074 pow_divisor *= F::MULTIPLICATIVE_GENERATOR;
1075 }
1076
1077 divisor >>= 1;
1078 }
1079
1080 let is_root_of_unity = pow_divisor == F::ONE;
1082 let is_full_group = mask + 1 == 1 << factorization.len();
1083
1084 if is_root_of_unity && !is_full_group || !is_root_of_unity && is_full_group {
1085 return false;
1086 }
1087 }
1088
1089 true
1090 }
1091
1092 #[test]
1093 fn test_multiplicative_generators() {
1094 assert!(is_binary_field_valid_generator::<BF1>());
1095 assert!(is_binary_field_valid_generator::<BF2>());
1096 assert!(is_binary_field_valid_generator::<BF4>());
1097 assert!(is_binary_field_valid_generator::<BF8>());
1098 assert!(is_binary_field_valid_generator::<BF16>());
1099 assert!(is_binary_field_valid_generator::<BinaryField32b>());
1100 assert!(is_binary_field_valid_generator::<BF64>());
1101 assert!(is_binary_field_valid_generator::<BinaryField128b>());
1102 }
1103
1104 proptest! {
1105 #[test]
1106 fn test_add_sub_subfields_is_commutative(a_val in any::<u8>(), b_val in any::<u64>()) {
1107 let (a, b) = (BinaryField8b::new(a_val), BinaryField16b::new(b_val as u16));
1108 assert_eq!(a + b, b + a);
1109 assert_eq!(a - b, -(b - a));
1110
1111 let (a, b) = (BinaryField8b::new(a_val), BinaryField64b::new(b_val));
1112 assert_eq!(a + b, b + a);
1113 assert_eq!(a - b, -(b - a));
1114 }
1115
1116 #[test]
1117 fn test_mul_subfields_is_commutative(a_val in any::<u8>(), b_val in any::<u64>()) {
1118 let (a, b) = (BinaryField8b::new(a_val), BinaryField16b::new(b_val as u16));
1119 assert_eq!(a * b, b * a);
1120
1121 let (a, b) = (BinaryField8b::new(a_val), BinaryField64b::new(b_val));
1122 assert_eq!(a * b, b * a);
1123 }
1124
1125 #[test]
1126 fn test_square_equals_mul(a_val in any::<u64>()) {
1127 let a = BinaryField64b::new(a_val);
1128 assert_eq!(a.square(), a * a);
1129 }
1130 }
1131
1132 #[test]
1133 fn test_field_degrees() {
1134 assert_eq!(BinaryField1b::N_BITS, 1);
1135 assert_eq!(BinaryField2b::N_BITS, 2);
1136 assert_eq!(BinaryField4b::N_BITS, 4);
1137 assert_eq!(<BinaryField4b as ExtensionField<BinaryField2b>>::DEGREE, 2);
1138 assert_eq!(BinaryField8b::N_BITS, 8);
1139 assert_eq!(BinaryField128b::N_BITS, 128);
1140
1141 assert_eq!(<BinaryField8b as ExtensionField<BinaryField2b>>::DEGREE, 4);
1142 assert_eq!(<BinaryField128b as ExtensionField<BinaryField2b>>::DEGREE, 64);
1143 assert_eq!(<BinaryField128b as ExtensionField<BinaryField8b>>::DEGREE, 16);
1144 }
1145
1146 #[test]
1147 fn test_field_formatting() {
1148 assert_eq!(format!("{}", BinaryField4b::from(3)), "0x3");
1149 assert_eq!(format!("{}", BinaryField8b::from(3)), "0x03");
1150 assert_eq!(format!("{}", BinaryField32b::from(5)), "0x00000005");
1151 assert_eq!(format!("{}", BinaryField64b::from(5)), "0x0000000000000005");
1152 }
1153
1154 #[test]
1155 fn test_extension_from_bases() {
1156 let a = BinaryField8b(0x01);
1157 let b = BinaryField8b(0x02);
1158 let c = BinaryField8b(0x03);
1159 let d = BinaryField8b(0x04);
1160 assert_eq!(
1161 <BinaryField32b as ExtensionField<BinaryField8b>>::from_bases([]).unwrap(),
1162 BinaryField32b(0)
1163 );
1164 assert_eq!(BinaryField32b::from_bases([a]).unwrap(), BinaryField32b(0x00000001));
1165 assert_eq!(BinaryField32b::from_bases([a, b]).unwrap(), BinaryField32b(0x00000201));
1166 assert_eq!(BinaryField32b::from_bases([a, b, c]).unwrap(), BinaryField32b(0x00030201));
1167 assert_eq!(BinaryField32b::from_bases([a, b, c, d]).unwrap(), BinaryField32b(0x04030201));
1168 assert!(BinaryField32b::from_bases([a, b, c, d, d]).is_err());
1169 }
1170
1171 #[test]
1172 fn test_inverse_on_zero() {
1173 assert!(BinaryField1b::ZERO.invert().is_none());
1174 assert!(BinaryField2b::ZERO.invert().is_none());
1175 assert!(BinaryField4b::ZERO.invert().is_none());
1176 assert!(BinaryField8b::ZERO.invert().is_none());
1177 assert!(BinaryField16b::ZERO.invert().is_none());
1178 assert!(BinaryField32b::ZERO.invert().is_none());
1179 assert!(BinaryField64b::ZERO.invert().is_none());
1180 assert!(BinaryField128b::ZERO.invert().is_none());
1181 }
1182
1183 proptest! {
1184 #[test]
1185 fn test_inverse_8b(val in 1u8..) {
1186 let x = BinaryField8b(val);
1187 let x_inverse = x.invert().unwrap();
1188 assert_eq!(x * x_inverse, BinaryField8b::ONE);
1189 }
1190
1191 #[test]
1192 fn test_inverse_32b(val in 1u32..) {
1193 let x = BinaryField32b(val);
1194 let x_inverse = x.invert().unwrap();
1195 assert_eq!(x * x_inverse, BinaryField32b::ONE);
1196 }
1197
1198 #[test]
1199 fn test_inverse_128b(val in 1u128..) {
1200 let x = BinaryField128b(val);
1201 let x_inverse = x.invert().unwrap();
1202 assert_eq!(x * x_inverse, BinaryField128b::ONE);
1203 }
1204 }
1205
1206 fn test_mul_primitive<F: TowerField>(val: F, iota: usize) {
1207 let result = val.mul_primitive(iota);
1208 let expected =
1209 <F as ExtensionField<BinaryField1b>>::basis_checked(1 << iota).map(|b| val * b);
1210 assert_eq!(result.is_ok(), expected.is_ok());
1211 if result.is_ok() {
1212 assert_eq!(result.unwrap(), expected.unwrap());
1213 } else {
1214 assert!(matches!(result.unwrap_err(), Error::ExtensionDegreeMismatch));
1215 }
1216 }
1217
1218 proptest! {
1219 #[test]
1220 fn test_mul_primitive_1b(val in 0u8..2u8, iota in 0usize..8) {
1221 test_mul_primitive::<BinaryField1b>(val.into(), iota)
1222 }
1223
1224 #[test]
1225 fn test_mul_primitive_2b(val in 0u8..4u8, iota in 0usize..8) {
1226 test_mul_primitive::<BinaryField2b>(val.into(), iota)
1227 }
1228
1229 #[test]
1230 fn test_mul_primitive_4b(val in 0u8..16u8, iota in 0usize..8) {
1231 test_mul_primitive::<BinaryField4b>(val.into(), iota)
1232 }
1233
1234 #[test]
1235 fn test_mul_primitive_8b(val in 0u8.., iota in 0usize..8) {
1236 test_mul_primitive::<BinaryField8b>(val.into(), iota)
1237 }
1238
1239 #[test]
1240 fn test_mul_primitive_16b(val in 0u16.., iota in 0usize..8) {
1241 test_mul_primitive::<BinaryField16b>(val.into(), iota)
1242 }
1243
1244 #[test]
1245 fn test_mul_primitive_32b(val in 0u32.., iota in 0usize..8) {
1246 test_mul_primitive::<BinaryField32b>(val.into(), iota)
1247 }
1248
1249 #[test]
1250 fn test_mul_primitive_64b(val in 0u64.., iota in 0usize..8) {
1251 test_mul_primitive::<BinaryField64b>(val.into(), iota)
1252 }
1253
1254 #[test]
1255 fn test_mul_primitive_128b(val in 0u128.., iota in 0usize..8) {
1256 test_mul_primitive::<BinaryField128b>(val.into(), iota)
1257 }
1258 }
1259
1260 #[test]
1261 fn test_1b_to_choice() {
1262 for i in 0..2 {
1263 assert_eq!(Choice::from(BinaryField1b::from(i)).unwrap_u8(), i);
1264 }
1265 }
1266
1267 #[test]
1268 fn test_serialization() {
1269 let mode = SerializationMode::CanonicalTower;
1270 let mut buffer = BytesMut::new();
1271 let b1 = BinaryField1b::from(0x1);
1272 let b8 = BinaryField8b::new(0x12);
1273 let b2 = BinaryField2b::from(0x2);
1274 let b16 = BinaryField16b::new(0x3456);
1275 let b32 = BinaryField32b::new(0x789ABCDE);
1276 let b4 = BinaryField4b::from(0xa);
1277 let b64 = BinaryField64b::new(0x13579BDF02468ACE);
1278 let b128 = BinaryField128b::new(0x147AD0369CF258BE8899AABBCCDDEEFF);
1279
1280 b1.serialize(&mut buffer, mode).unwrap();
1281 b8.serialize(&mut buffer, mode).unwrap();
1282 b2.serialize(&mut buffer, mode).unwrap();
1283 b16.serialize(&mut buffer, mode).unwrap();
1284 b32.serialize(&mut buffer, mode).unwrap();
1285 b4.serialize(&mut buffer, mode).unwrap();
1286 b64.serialize(&mut buffer, mode).unwrap();
1287 b128.serialize(&mut buffer, mode).unwrap();
1288
1289 let mut read_buffer = buffer.freeze();
1290
1291 assert_eq!(BinaryField1b::deserialize(&mut read_buffer, mode).unwrap(), b1);
1292 assert_eq!(BinaryField8b::deserialize(&mut read_buffer, mode).unwrap(), b8);
1293 assert_eq!(BinaryField2b::deserialize(&mut read_buffer, mode).unwrap(), b2);
1294 assert_eq!(BinaryField16b::deserialize(&mut read_buffer, mode).unwrap(), b16);
1295 assert_eq!(BinaryField32b::deserialize(&mut read_buffer, mode).unwrap(), b32);
1296 assert_eq!(BinaryField4b::deserialize(&mut read_buffer, mode).unwrap(), b4);
1297 assert_eq!(BinaryField64b::deserialize(&mut read_buffer, mode).unwrap(), b64);
1298 assert_eq!(BinaryField128b::deserialize(&mut read_buffer, mode).unwrap(), b128);
1299 }
1300
1301 #[test]
1302 fn test_gf2_new_unchecked() {
1303 for i in 0..2 {
1304 assert_eq!(unsafe { BF1::new_unchecked(i) }, BF1::from(i));
1305 }
1306 let result = std::panic::catch_unwind(|| unsafe { BF1::new_unchecked(2) });
1308 assert!(result.is_err(), "Expected a panic for value > 1, but no panic occurred");
1309 }
1310
1311 #[test]
1312 fn test_bin2b_new_unchecked() {
1313 for i in 0..4 {
1314 assert_eq!(unsafe { BF2::new_unchecked(i) }, BF2::from(i));
1315 }
1316 let result = std::panic::catch_unwind(|| unsafe { BF2::new_unchecked(4) });
1318 assert!(result.is_err(), "Expected a panic for value > 3, but no panic occurred");
1319 }
1320
1321 #[test]
1322 fn test_bin4b_new_unchecked() {
1323 for i in 0..16 {
1324 assert_eq!(unsafe { BF4::new_unchecked(i) }, BF4::from(i));
1325 }
1326 let result = std::panic::catch_unwind(|| unsafe { BF4::new_unchecked(16) });
1328 assert!(result.is_err(), "Expected a panic for value > 15, but no panic occurred");
1329 }
1330}