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