binius_field/arch/portable/
m128.rs1use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Shr};
4
5use binius_utils::{
6 DeserializeBytes, SerializationError, SerializeBytes,
7 bytes::{Buf, BufMut},
8 serialization::{assert_enough_data_for, assert_enough_space_for},
9};
10use bytemuck::{Pod, Zeroable};
11use derive_more::{From, Into};
12use rand::{
13 distr::{Distribution, StandardUniform},
14 prelude::*,
15};
16
17use crate::{
18 BinaryField,
19 arch::portable::packed::PackedPrimitiveType,
20 underlier::{
21 Divisible, SmallU, UnderlierType, impl_divisible_bitmask, impl_divisible_memcast,
22 impl_divisible_self,
23 },
24};
25
26#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, From, Into)]
33#[repr(transparent)]
34pub struct M128(u128);
35
36impl M128 {
37 #[inline(always)]
38 pub const fn from_u128(value: u128) -> Self {
39 Self(value)
40 }
41}
42
43impl From<u64> for M128 {
44 #[inline(always)]
45 fn from(value: u64) -> Self {
46 Self(value as u128)
47 }
48}
49impl From<u32> for M128 {
50 #[inline(always)]
51 fn from(value: u32) -> Self {
52 Self(value as u128)
53 }
54}
55impl From<u16> for M128 {
56 #[inline(always)]
57 fn from(value: u16) -> Self {
58 Self(value as u128)
59 }
60}
61impl From<u8> for M128 {
62 #[inline(always)]
63 fn from(value: u8) -> Self {
64 Self(value as u128)
65 }
66}
67
68impl<const N: usize> From<SmallU<N>> for M128 {
69 #[inline(always)]
70 fn from(value: SmallU<N>) -> Self {
71 Self(value.val() as u128)
72 }
73}
74
75impl SerializeBytes for M128 {
76 fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
77 assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
78 write_buf.put_u128_le(self.0);
79 Ok(())
80 }
81}
82
83impl DeserializeBytes for M128 {
84 fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
85 where
86 Self: Sized,
87 {
88 assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
89 Ok(Self(read_buf.get_u128_le()))
90 }
91}
92
93unsafe impl Zeroable for M128 {}
94
95unsafe impl Pod for M128 {}
96
97impl_divisible_memcast!(M128, u128, u64, u32, u16, u8);
98impl_divisible_bitmask!(M128, 1, 2, 4);
99impl_divisible_self!(M128);
100
101impl BitAnd for M128 {
102 type Output = Self;
103
104 #[inline(always)]
105 fn bitand(self, rhs: Self) -> Self::Output {
106 Self(self.0 & rhs.0)
107 }
108}
109
110impl BitAndAssign for M128 {
111 #[inline(always)]
112 fn bitand_assign(&mut self, rhs: Self) {
113 self.0 &= rhs.0;
114 }
115}
116
117impl BitOr for M128 {
118 type Output = Self;
119
120 #[inline(always)]
121 fn bitor(self, rhs: Self) -> Self::Output {
122 Self(self.0 | rhs.0)
123 }
124}
125
126impl BitOrAssign for M128 {
127 #[inline(always)]
128 fn bitor_assign(&mut self, rhs: Self) {
129 self.0 |= rhs.0;
130 }
131}
132
133impl BitXor for M128 {
134 type Output = Self;
135
136 #[inline(always)]
137 fn bitxor(self, rhs: Self) -> Self::Output {
138 Self(self.0 ^ rhs.0)
139 }
140}
141
142impl BitXorAssign for M128 {
143 #[inline(always)]
144 fn bitxor_assign(&mut self, rhs: Self) {
145 self.0 ^= rhs.0;
146 }
147}
148
149impl Not for M128 {
150 type Output = Self;
151
152 #[inline(always)]
153 fn not(self) -> Self::Output {
154 Self(!self.0)
155 }
156}
157
158impl Shl<usize> for M128 {
159 type Output = Self;
160
161 #[inline(always)]
162 fn shl(self, rhs: usize) -> Self::Output {
163 Self(self.0 << rhs)
164 }
165}
166
167impl Shr<usize> for M128 {
168 type Output = Self;
169
170 #[inline(always)]
171 fn shr(self, rhs: usize) -> Self::Output {
172 Self(self.0 >> rhs)
173 }
174}
175
176impl Distribution<M128> for StandardUniform {
177 #[inline]
178 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> M128 {
179 M128(rng.random())
180 }
181}
182
183impl std::fmt::Display for M128 {
184 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
185 write!(f, "{:032X}", self.0)
186 }
187}
188
189impl std::fmt::Debug for M128 {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 write!(f, "M128({self})")
192 }
193}
194
195impl std::fmt::LowerHex for M128 {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 std::fmt::LowerHex::fmt(&self.0, f)
198 }
199}
200
201impl UnderlierType for M128 {
202 const LOG_BITS: usize = 7;
203 const ZERO: Self = Self(0);
204 const ONE: Self = Self(1);
205 const ONES: Self = Self(u128::MAX);
206
207 #[inline(always)]
208 fn interleave(self, other: Self, log_block_len: usize) -> (Self, Self) {
209 let (a, b) = self.0.interleave(other.0, log_block_len);
210 (Self(a), Self(b))
211 }
212}
213
214impl<Scalar: BinaryField> From<u128> for PackedPrimitiveType<M128, Scalar> {
215 #[inline]
216 fn from(value: u128) -> Self {
217 Self::from(M128::from(value))
218 }
219}
220
221impl<Scalar: BinaryField> From<PackedPrimitiveType<M128, Scalar>> for u128 {
222 #[inline]
223 fn from(value: PackedPrimitiveType<M128, Scalar>) -> Self {
224 value.to_underlier().into()
225 }
226}