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};
8use crate::arch::{interleave_mask_even, interleave_with_mask};
9
10macro_rules! impl_underlier_type {
11	($name:ty) => {
12		impl UnderlierType for $name {
13			const LOG_BITS: usize =
14				binius_utils::checked_arithmetics::checked_log_2(Self::BITS as _);
15		}
16	};
17	() => {};
18	($name:ty, $($tail:ty),+) => {
19		impl_underlier_type!($name);
20		impl_underlier_type!($($tail),+);
21	}
22}
23
24impl_underlier_type!(u8, u16, u32, u64, u128);
25
26impl UnderlierWithBitOps for u8 {
27	const ZERO: Self = 0;
28	const ONE: Self = 1;
29	const ONES: Self = Self::MAX;
30
31	fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
32		const MASKS: &[u8] = &[
33			interleave_mask_even!(u8, 0),
34			interleave_mask_even!(u8, 1),
35			interleave_mask_even!(u8, 2),
36		];
37		interleave_with_mask(self, other, log_block_len, MASKS)
38	}
39}
40
41impl UnderlierWithBitOps for u16 {
42	const ZERO: Self = 0;
43	const ONE: Self = 1;
44	const ONES: Self = Self::MAX;
45
46	fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
47		const MASKS: &[u16] = &[
48			interleave_mask_even!(u16, 0),
49			interleave_mask_even!(u16, 1),
50			interleave_mask_even!(u16, 2),
51			interleave_mask_even!(u16, 3),
52		];
53		interleave_with_mask(self, other, log_block_len, MASKS)
54	}
55}
56
57impl UnderlierWithBitOps for u32 {
58	const ZERO: Self = 0;
59	const ONE: Self = 1;
60	const ONES: Self = Self::MAX;
61
62	fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
63		const MASKS: &[u32] = &[
64			interleave_mask_even!(u32, 0),
65			interleave_mask_even!(u32, 1),
66			interleave_mask_even!(u32, 2),
67			interleave_mask_even!(u32, 3),
68			interleave_mask_even!(u32, 4),
69		];
70		interleave_with_mask(self, other, log_block_len, MASKS)
71	}
72}
73
74impl UnderlierWithBitOps for u64 {
75	const ZERO: Self = 0;
76	const ONE: Self = 1;
77	const ONES: Self = Self::MAX;
78
79	fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
80		const MASKS: &[u64] = &[
81			interleave_mask_even!(u64, 0),
82			interleave_mask_even!(u64, 1),
83			interleave_mask_even!(u64, 2),
84			interleave_mask_even!(u64, 3),
85			interleave_mask_even!(u64, 4),
86			interleave_mask_even!(u64, 5),
87		];
88		interleave_with_mask(self, other, log_block_len, MASKS)
89	}
90}
91
92impl UnderlierWithBitOps for u128 {
93	const ZERO: Self = 0;
94	const ONE: Self = 1;
95	const ONES: Self = Self::MAX;
96
97	fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
98		const MASKS: &[u128] = &[
99			interleave_mask_even!(u128, 0),
100			interleave_mask_even!(u128, 1),
101			interleave_mask_even!(u128, 2),
102			interleave_mask_even!(u128, 3),
103			interleave_mask_even!(u128, 4),
104			interleave_mask_even!(u128, 5),
105			interleave_mask_even!(u128, 6),
106		];
107		interleave_with_mask(self, other, log_block_len, MASKS)
108	}
109}
110
111macro_rules! impl_num_cast {
112	(@pair U1, U2) => {impl_num_cast!(@small_u_from_small_u U1, U2);};
113	(@pair U1, U4) => {impl_num_cast!(@small_u_from_small_u U1, U4);};
114	(@pair U2, U4) => {impl_num_cast!(@small_u_from_small_u U2, U4);};
115	(@pair U1, $bigger:ty) => {impl_num_cast!(@small_u_from_u U1, $bigger);};
116	(@pair U2, $bigger:ty) => {impl_num_cast!(@small_u_from_u U2, $bigger);};
117	(@pair U4, $bigger:ty) => {impl_num_cast!(@small_u_from_u U4, $bigger);};
118	(@pair $smaller:ident, $bigger:ident) => {
119		impl NumCast<$bigger> for $smaller {
120			#[inline(always)]
121			fn num_cast_from(val: $bigger) -> Self {
122				val as _
123			}
124		}
125
126		impl NumCast<$smaller> for $bigger {
127			#[inline(always)]
128			fn num_cast_from(val: $smaller) -> Self {
129				val as _
130			}
131		}
132	};
133	(@small_u_from_small_u $smaller:ty, $bigger:ty) => {
134		impl NumCast<$bigger> for $smaller {
135			#[inline(always)]
136			fn num_cast_from(val: $bigger) -> Self {
137				Self::new(val.val()) & Self::ONES
138			}
139		}
140
141		impl NumCast<$smaller> for $bigger {
142			#[inline(always)]
143			fn num_cast_from(val: $smaller) -> Self {
144				Self::new(val.val())
145			}
146		}
147	};
148	(@small_u_from_u $smaller:ty, $bigger:ty) => {
149		impl NumCast<$bigger> for $smaller {
150			#[inline(always)]
151			fn num_cast_from(val: $bigger) -> Self {
152				Self::new(val as u8) & Self::ONES
153			}
154		}
155
156		impl NumCast<$smaller> for $bigger {
157			#[inline(always)]
158			fn num_cast_from(val: $smaller) -> Self {
159				val.val() as _
160			}
161		}
162	};
163	($_:ty,) => {};
164	(,) => {};
165	(all_pairs) => {};
166	(all_pairs $_:ty) => {};
167	(all_pairs $_:ty,) => {};
168	(all_pairs $smaller:ident, $head:ident, $($tail:ident,)*) => {
169		impl_num_cast!(@pair $smaller, $head);
170		impl_num_cast!(all_pairs $smaller, $($tail,)*);
171	};
172	($smaller:ident, $($tail:ident,)+) => {
173		impl_num_cast!(all_pairs $smaller, $($tail,)+);
174		impl_num_cast!($($tail,)+);
175	};
176}
177
178impl_num_cast!(U1, U2, U4, u8, u16, u32, u64, u128,);