Skip to main content

binius_field/underlier/
underlier_with_bit_ops.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4#[cfg(test)]
5use std::ops::Shl;
6
7#[cfg(test)]
8use super::underlier_type::UnderlierType;
9#[cfg(test)]
10use crate::Divisible;
11
12#[cfg(test)]
13#[allow(unused)]
14pub(crate) fn single_element_mask_bits<T: UnderlierType + Shl<usize, Output = T>>(
15	bits_count: usize,
16) -> T {
17	use binius_utils::checked_arithmetics::checked_log_2;
18
19	if bits_count == T::BITS {
20		!T::ZERO
21	} else {
22		let mut result = T::ONE;
23		for height in 0..checked_log_2(bits_count) {
24			result |= result << (1usize << height)
25		}
26
27		result
28	}
29}
30
31#[cfg(test)]
32mod tests {
33	use proptest::{arbitrary::any, bits, proptest};
34
35	use super::{
36		super::small_uint::{U1, U2, U4},
37		*,
38	};
39
40	#[test]
41	fn test_from_fn() {
42		assert_eq!(u32::from_fn(|_| U1::new(0)), 0);
43		assert_eq!(u32::from_fn(|i| U1::new((i % 2) as u8)), 0xaaaaaaaa);
44		assert_eq!(u32::from_fn(|_| U1::new(1)), u32::MAX);
45
46		assert_eq!(u32::from_fn(|_| U2::new(0)), 0);
47		assert_eq!(u32::from_fn(|_| U2::new(1)), 0x55555555);
48		assert_eq!(u32::from_fn(|_| U2::new(2)), 0xaaaaaaaa);
49		assert_eq!(u32::from_fn(|_| U2::new(3)), u32::MAX);
50		assert_eq!(u32::from_fn(|i| U2::new((i % 4) as u8)), 0xe4e4e4e4);
51
52		assert_eq!(u32::from_fn(|_| U4::new(0)), 0);
53		assert_eq!(u32::from_fn(|_| U4::new(1)), 0x11111111);
54		assert_eq!(u32::from_fn(|_| U4::new(8)), 0x88888888);
55		assert_eq!(u32::from_fn(|_| U4::new(31)), 0xffffffff);
56		assert_eq!(u32::from_fn(|i| U4::new(i as u8)), 0x76543210);
57
58		assert_eq!(u32::from_fn(|_| 0u8), 0);
59		assert_eq!(u32::from_fn(|_| 0xabu8), 0xabababab);
60		assert_eq!(u32::from_fn(|_| 255u8), 0xffffffff);
61		assert_eq!(u32::from_fn(|i| i as u8), 0x03020100);
62	}
63
64	#[test]
65	fn test_broadcast_subvalue() {
66		assert_eq!(u32::broadcast_subvalue(U1::new(0)), 0);
67		assert_eq!(u32::broadcast_subvalue(U1::new(1)), u32::MAX);
68
69		assert_eq!(u32::broadcast_subvalue(U2::new(0)), 0);
70		assert_eq!(u32::broadcast_subvalue(U2::new(1)), 0x55555555);
71		assert_eq!(u32::broadcast_subvalue(U2::new(2)), 0xaaaaaaaa);
72		assert_eq!(u32::broadcast_subvalue(U2::new(3)), u32::MAX);
73
74		assert_eq!(u32::broadcast_subvalue(U4::new(0)), 0);
75		assert_eq!(u32::broadcast_subvalue(U4::new(1)), 0x11111111);
76		assert_eq!(u32::broadcast_subvalue(U4::new(8)), 0x88888888);
77		assert_eq!(u32::broadcast_subvalue(U4::new(31)), 0xffffffff);
78
79		assert_eq!(u32::broadcast_subvalue(0u8), 0);
80		assert_eq!(u32::broadcast_subvalue(0xabu8), 0xabababab);
81		assert_eq!(u32::broadcast_subvalue(255u8), 0xffffffff);
82	}
83
84	#[test]
85	fn test_divisible_get_u32() {
86		let value = 0xab12cd34u32;
87
88		assert_eq!(Divisible::<U1>::get(&value, 0), U1::new(0));
89		assert_eq!(Divisible::<U1>::get(&value, 1), U1::new(0));
90		assert_eq!(Divisible::<U1>::get(&value, 2), U1::new(1));
91		assert_eq!(Divisible::<U1>::get(&value, 31), U1::new(1));
92
93		assert_eq!(Divisible::<U2>::get(&value, 0), U2::new(0));
94		assert_eq!(Divisible::<U2>::get(&value, 1), U2::new(1));
95		assert_eq!(Divisible::<U2>::get(&value, 2), U2::new(3));
96		assert_eq!(Divisible::<U2>::get(&value, 15), U2::new(2));
97
98		assert_eq!(Divisible::<U4>::get(&value, 0), U4::new(4));
99		assert_eq!(Divisible::<U4>::get(&value, 1), U4::new(3));
100		assert_eq!(Divisible::<U4>::get(&value, 2), U4::new(13));
101		assert_eq!(Divisible::<U4>::get(&value, 7), U4::new(10));
102
103		assert_eq!(Divisible::<u8>::get(&value, 0), 0x34u8);
104		assert_eq!(Divisible::<u8>::get(&value, 1), 0xcdu8);
105		assert_eq!(Divisible::<u8>::get(&value, 2), 0x12u8);
106		assert_eq!(Divisible::<u8>::get(&value, 3), 0xabu8);
107	}
108
109	proptest! {
110		#[test]
111		fn test_divisible_set_1b(mut init_val in any::<u32>(), i in 0usize..31, val in bits::u8::masked(1)) {
112			Divisible::<U1>::set(&mut init_val, i, U1::new(val));
113			assert_eq!(Divisible::<U1>::get(&init_val, i), U1::new(val));
114		}
115
116		#[test]
117		fn test_divisible_set_2b(mut init_val in any::<u32>(), i in 0usize..15, val in bits::u8::masked(3)) {
118			Divisible::<U2>::set(&mut init_val, i, U2::new(val));
119			assert_eq!(Divisible::<U2>::get(&init_val, i), U2::new(val));
120		}
121
122		#[test]
123		fn test_divisible_set_4b(mut init_val in any::<u32>(), i in 0usize..7, val in bits::u8::masked(7)) {
124			Divisible::<U4>::set(&mut init_val, i, U4::new(val));
125			assert_eq!(Divisible::<U4>::get(&init_val, i), U4::new(val));
126		}
127
128		#[test]
129		fn test_divisible_set_8b(mut init_val in any::<u32>(), i in 0usize..3, val in bits::u8::masked(15)) {
130			Divisible::<u8>::set(&mut init_val, i, val);
131			assert_eq!(Divisible::<u8>::get(&init_val, i), val);
132		}
133	}
134}