binius_field/underlier/
underlier_impls.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use super::{
4	small_uint::{U1, U2, U4},
5	underlier_type::{NumCast, UnderlierType},
6	underlier_with_bit_ops::UnderlierWithBitOps,
7};
8
9macro_rules! impl_underlier_type {
10	($name:ty) => {
11		impl UnderlierType for $name {
12			const LOG_BITS: usize =
13				binius_utils::checked_arithmetics::checked_log_2(Self::BITS as _);
14		}
15
16        impl UnderlierWithBitOps for $name {
17			const ZERO: Self = 0;
18			const ONE: Self = 1;
19			const ONES: Self = <$name>::MAX;
20
21			#[inline(always)]
22			fn fill_with_bit(val: u8) -> Self {
23				debug_assert!(val == 0 || val == 1);
24				(val as Self).wrapping_neg()
25			}
26
27			#[inline(always)]
28			fn shl_128b_lanes(self, rhs: usize) -> Self {
29				self << rhs
30			}
31
32			#[inline(always)]
33			fn shr_128b_lanes(self, rhs: usize) -> Self {
34				self >> rhs
35			}
36		}
37	};
38	() => {};
39	($name:ty, $($tail:ty),+) => {
40		impl_underlier_type!($name);
41		impl_underlier_type!($($tail),+);
42	}
43}
44
45impl_underlier_type!(u8, u16, u32, u64, u128);
46
47macro_rules! impl_num_cast {
48	(@pair U1, U2) => {impl_num_cast!(@small_u_from_small_u U1, U2);};
49	(@pair U1, U4) => {impl_num_cast!(@small_u_from_small_u U1, U4);};
50	(@pair U2, U4) => {impl_num_cast!(@small_u_from_small_u U2, U4);};
51	(@pair U1, $bigger:ty) => {impl_num_cast!(@small_u_from_u U1, $bigger);};
52	(@pair U2, $bigger:ty) => {impl_num_cast!(@small_u_from_u U2, $bigger);};
53	(@pair U4, $bigger:ty) => {impl_num_cast!(@small_u_from_u U4, $bigger);};
54	(@pair $smaller:ident, $bigger:ident) => {
55		impl NumCast<$bigger> for $smaller {
56			#[inline(always)]
57			fn num_cast_from(val: $bigger) -> Self {
58				val as _
59			}
60		}
61
62		impl NumCast<$smaller> for $bigger {
63			#[inline(always)]
64			fn num_cast_from(val: $smaller) -> Self {
65				val as _
66			}
67		}
68	};
69	(@small_u_from_small_u $smaller:ty, $bigger:ty) => {
70		impl NumCast<$bigger> for $smaller {
71			#[inline(always)]
72			fn num_cast_from(val: $bigger) -> Self {
73				Self::new(val.val()) & Self::ONES
74			}
75		}
76
77		impl NumCast<$smaller> for $bigger {
78			#[inline(always)]
79			fn num_cast_from(val: $smaller) -> Self {
80				Self::new(val.val())
81			}
82		}
83	};
84	(@small_u_from_u $smaller:ty, $bigger:ty) => {
85		impl NumCast<$bigger> for $smaller {
86			#[inline(always)]
87			fn num_cast_from(val: $bigger) -> Self {
88				Self::new(val as u8) & Self::ONES
89			}
90		}
91
92		impl NumCast<$smaller> for $bigger {
93			#[inline(always)]
94			fn num_cast_from(val: $smaller) -> Self {
95				val.val() as _
96			}
97		}
98	};
99	($_:ty,) => {};
100	(,) => {};
101	(all_pairs) => {};
102	(all_pairs $_:ty) => {};
103	(all_pairs $_:ty,) => {};
104	(all_pairs $smaller:ident, $head:ident, $($tail:ident,)*) => {
105		impl_num_cast!(@pair $smaller, $head);
106		impl_num_cast!(all_pairs $smaller, $($tail,)*);
107	};
108	($smaller:ident, $($tail:ident,)+) => {
109		impl_num_cast!(all_pairs $smaller, $($tail,)+);
110		impl_num_cast!($($tail,)+);
111	};
112}
113
114impl_num_cast!(U1, U2, U4, u8, u16, u32, u64, u128,);