1use std::{
8 fmt::{Debug, Display, Formatter},
9 iter::{Product, Sum},
10 ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
11};
12
13use binius_utils::{
14 DeserializeBytes, FixedSizeSerializeBytes, SerializationError, SerializeBytes,
15 bytes::{Buf, BufMut},
16 serialization::assert_enough_space_for,
17};
18use bytemuck::{Pod, Zeroable};
19
20use super::{
21 binary_field::{BinaryField, BinaryField1b, binary_field, impl_field_extension},
22 extension::ExtensionField,
23};
24use crate::{
25 AESTowerField8b, Field,
26 arch::M128,
27 mul_by_binary_field_1b,
28 underlier::{U1, WithUnderlier},
29};
30
31binary_field!(
33 pub Ghash128b(M128),
34 M128::from_u128(0x494ef99794d5244f9152df59d87a9186),
35 M128::from_u128(1 << 121)
36);
37
38impl From<u128> for Ghash128b {
42 fn from(value: u128) -> Self {
43 Self(M128::from(value))
44 }
45}
46
47impl From<Ghash128b> for u128 {
48 fn from(value: Ghash128b) -> Self {
49 value.0.into()
50 }
51}
52
53unsafe impl Pod for Ghash128b {}
54
55impl Ghash128b {
56 pub const fn new(value: u128) -> Self {
59 Self(M128::from_u128(value))
60 }
61
62 #[inline]
63 pub fn mul_x(self) -> Self {
64 let val: u128 = self.to_underlier().into();
66 let shifted = val << 1;
67
68 let mask = (val >> 127).wrapping_neg();
72 let result = shifted ^ (0x87 & mask);
73
74 Self::new(result)
75 }
76
77 #[inline]
78 pub fn mul_inv_x(self) -> Self {
79 let val: u128 = self.to_underlier().into();
81 let shifted = val >> 1;
82
83 let mask = (val & 1).wrapping_neg();
89 let result = shifted ^ (((1u128 << 127) | 0x43) & mask);
90
91 Self::new(result)
92 }
93}
94
95impl_field_extension!(BinaryField1b(U1) < @7 => Ghash128b(M128));
96
97mul_by_binary_field_1b!(Ghash128b);
98
99impl SerializeBytes for Ghash128b {
100 fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
101 self.0.serialize(write_buf)
102 }
103
104 fn serialize_slice(
105 slice: &[Self],
106 mut write_buf: impl BufMut,
107 ) -> Result<(), SerializationError> {
108 let bytes: &[u8] = bytemuck::cast_slice(slice);
112 assert_enough_space_for(&write_buf, bytes.len())?;
113 write_buf.put_slice(bytes);
114 Ok(())
115 }
116}
117
118impl DeserializeBytes for Ghash128b {
119 fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError>
120 where
121 Self: Sized,
122 {
123 Ok(Self(DeserializeBytes::deserialize(read_buf)?))
124 }
125}
126
127impl FixedSizeSerializeBytes for Ghash128b {
128 const BYTE_SIZE: usize = 16;
129}
130
131impl From<AESTowerField8b> for Ghash128b {
132 #[inline]
133 fn from(value: AESTowerField8b) -> Self {
134 const LOOKUP_TABLE: [u128; 256] = [
137 0x00000000000000000000000000000000,
138 0x00000000000000000000000000000001,
139 0x0dcb364640a222fe6b8330483c2e9849,
140 0x0dcb364640a222fe6b8330483c2e9848,
141 0x3d5bd35c94646a247573da4a5f7710ed,
142 0x3d5bd35c94646a247573da4a5f7710ec,
143 0x3090e51ad4c648da1ef0ea02635988a4,
144 0x3090e51ad4c648da1ef0ea02635988a5,
145 0x6d58c4e181f9199f41a12db1f974f3ac,
146 0x6d58c4e181f9199f41a12db1f974f3ad,
147 0x6093f2a7c15b3b612a221df9c55a6be5,
148 0x6093f2a7c15b3b612a221df9c55a6be4,
149 0x500317bd159d73bb34d2f7fba603e341,
150 0x500317bd159d73bb34d2f7fba603e340,
151 0x5dc821fb553f51455f51c7b39a2d7b08,
152 0x5dc821fb553f51455f51c7b39a2d7b09,
153 0xa72ec17764d7ced55e2f716f4ede412f,
154 0xa72ec17764d7ced55e2f716f4ede412e,
155 0xaae5f7312475ec2b35ac412772f0d966,
156 0xaae5f7312475ec2b35ac412772f0d967,
157 0x9a75122bf0b3a4f12b5cab2511a951c2,
158 0x9a75122bf0b3a4f12b5cab2511a951c3,
159 0x97be246db011860f40df9b6d2d87c98b,
160 0x97be246db011860f40df9b6d2d87c98a,
161 0xca760596e52ed74a1f8e5cdeb7aab283,
162 0xca760596e52ed74a1f8e5cdeb7aab282,
163 0xc7bd33d0a58cf5b4740d6c968b842aca,
164 0xc7bd33d0a58cf5b4740d6c968b842acb,
165 0xf72dd6ca714abd6e6afd8694e8dda26e,
166 0xf72dd6ca714abd6e6afd8694e8dda26f,
167 0xfae6e08c31e89f90017eb6dcd4f33a27,
168 0xfae6e08c31e89f90017eb6dcd4f33a26,
169 0x4d52354a3a3d8c865cb10fbabcf00118,
170 0x4d52354a3a3d8c865cb10fbabcf00119,
171 0x4099030c7a9fae7837323ff280de9951,
172 0x4099030c7a9fae7837323ff280de9950,
173 0x7009e616ae59e6a229c2d5f0e38711f5,
174 0x7009e616ae59e6a229c2d5f0e38711f4,
175 0x7dc2d050eefbc45c4241e5b8dfa989bc,
176 0x7dc2d050eefbc45c4241e5b8dfa989bd,
177 0x200af1abbbc495191d10220b4584f2b4,
178 0x200af1abbbc495191d10220b4584f2b5,
179 0x2dc1c7edfb66b7e77693124379aa6afd,
180 0x2dc1c7edfb66b7e77693124379aa6afc,
181 0x1d5122f72fa0ff3d6863f8411af3e259,
182 0x1d5122f72fa0ff3d6863f8411af3e258,
183 0x109a14b16f02ddc303e0c80926dd7a10,
184 0x109a14b16f02ddc303e0c80926dd7a11,
185 0xea7cf43d5eea4253029e7ed5f22e4037,
186 0xea7cf43d5eea4253029e7ed5f22e4036,
187 0xe7b7c27b1e4860ad691d4e9dce00d87e,
188 0xe7b7c27b1e4860ad691d4e9dce00d87f,
189 0xd7272761ca8e287777eda49fad5950da,
190 0xd7272761ca8e287777eda49fad5950db,
191 0xdaec11278a2c0a891c6e94d79177c893,
192 0xdaec11278a2c0a891c6e94d79177c892,
193 0x872430dcdf135bcc433f53640b5ab39b,
194 0x872430dcdf135bcc433f53640b5ab39a,
195 0x8aef069a9fb1793228bc632c37742bd2,
196 0x8aef069a9fb1793228bc632c37742bd3,
197 0xba7fe3804b7731e8364c892e542da376,
198 0xba7fe3804b7731e8364c892e542da377,
199 0xb7b4d5c60bd513165dcfb96668033b3f,
200 0xb7b4d5c60bd513165dcfb96668033b3e,
201 0x553e92e8bc0ae9a795ed1f57f3632d4d,
202 0x553e92e8bc0ae9a795ed1f57f3632d4c,
203 0x58f5a4aefca8cb59fe6e2f1fcf4db504,
204 0x58f5a4aefca8cb59fe6e2f1fcf4db505,
205 0x686541b4286e8383e09ec51dac143da0,
206 0x686541b4286e8383e09ec51dac143da1,
207 0x65ae77f268cca17d8b1df555903aa5e9,
208 0x65ae77f268cca17d8b1df555903aa5e8,
209 0x386656093df3f038d44c32e60a17dee1,
210 0x386656093df3f038d44c32e60a17dee0,
211 0x35ad604f7d51d2c6bfcf02ae363946a8,
212 0x35ad604f7d51d2c6bfcf02ae363946a9,
213 0x053d8555a9979a1ca13fe8ac5560ce0c,
214 0x053d8555a9979a1ca13fe8ac5560ce0d,
215 0x08f6b313e935b8e2cabcd8e4694e5645,
216 0x08f6b313e935b8e2cabcd8e4694e5644,
217 0xf210539fd8dd2772cbc26e38bdbd6c62,
218 0xf210539fd8dd2772cbc26e38bdbd6c63,
219 0xffdb65d9987f058ca0415e708193f42b,
220 0xffdb65d9987f058ca0415e708193f42a,
221 0xcf4b80c34cb94d56beb1b472e2ca7c8f,
222 0xcf4b80c34cb94d56beb1b472e2ca7c8e,
223 0xc280b6850c1b6fa8d532843adee4e4c6,
224 0xc280b6850c1b6fa8d532843adee4e4c7,
225 0x9f48977e59243eed8a63438944c99fce,
226 0x9f48977e59243eed8a63438944c99fcf,
227 0x9283a13819861c13e1e073c178e70787,
228 0x9283a13819861c13e1e073c178e70786,
229 0xa2134422cd4054c9ff1099c31bbe8f23,
230 0xa2134422cd4054c9ff1099c31bbe8f22,
231 0xafd872648de276379493a98b2790176a,
232 0xafd872648de276379493a98b2790176b,
233 0x186ca7a286376521c95c10ed4f932c55,
234 0x186ca7a286376521c95c10ed4f932c54,
235 0x15a791e4c69547dfa2df20a573bdb41c,
236 0x15a791e4c69547dfa2df20a573bdb41d,
237 0x253774fe12530f05bc2fcaa710e43cb8,
238 0x253774fe12530f05bc2fcaa710e43cb9,
239 0x28fc42b852f12dfbd7acfaef2ccaa4f1,
240 0x28fc42b852f12dfbd7acfaef2ccaa4f0,
241 0x7534634307ce7cbe88fd3d5cb6e7dff9,
242 0x7534634307ce7cbe88fd3d5cb6e7dff8,
243 0x78ff5505476c5e40e37e0d148ac947b0,
244 0x78ff5505476c5e40e37e0d148ac947b1,
245 0x486fb01f93aa169afd8ee716e990cf14,
246 0x486fb01f93aa169afd8ee716e990cf15,
247 0x45a48659d3083464960dd75ed5be575d,
248 0x45a48659d3083464960dd75ed5be575c,
249 0xbf4266d5e2e0abf497736182014d6d7a,
250 0xbf4266d5e2e0abf497736182014d6d7b,
251 0xb2895093a242890afcf051ca3d63f533,
252 0xb2895093a242890afcf051ca3d63f532,
253 0x8219b5897684c1d0e200bbc85e3a7d97,
254 0x8219b5897684c1d0e200bbc85e3a7d96,
255 0x8fd283cf3626e32e89838b806214e5de,
256 0x8fd283cf3626e32e89838b806214e5df,
257 0xd21aa2346319b26bd6d24c33f8399ed6,
258 0xd21aa2346319b26bd6d24c33f8399ed7,
259 0xdfd1947223bb9095bd517c7bc417069f,
260 0xdfd1947223bb9095bd517c7bc417069e,
261 0xef417168f77dd84fa3a19679a74e8e3b,
262 0xef417168f77dd84fa3a19679a74e8e3a,
263 0xe28a472eb7dffab1c822a6319b601672,
264 0xe28a472eb7dffab1c822a6319b601673,
265 0x93252331bf042b11512625b1f09fa87e,
266 0x93252331bf042b11512625b1f09fa87f,
267 0x9eee1577ffa609ef3aa515f9ccb13037,
268 0x9eee1577ffa609ef3aa515f9ccb13036,
269 0xae7ef06d2b6041352455fffbafe8b893,
270 0xae7ef06d2b6041352455fffbafe8b892,
271 0xa3b5c62b6bc263cb4fd6cfb393c620da,
272 0xa3b5c62b6bc263cb4fd6cfb393c620db,
273 0xfe7de7d03efd328e1087080009eb5bd2,
274 0xfe7de7d03efd328e1087080009eb5bd3,
275 0xf3b6d1967e5f10707b04384835c5c39b,
276 0xf3b6d1967e5f10707b04384835c5c39a,
277 0xc326348caa9958aa65f4d24a569c4b3f,
278 0xc326348caa9958aa65f4d24a569c4b3e,
279 0xceed02caea3b7a540e77e2026ab2d376,
280 0xceed02caea3b7a540e77e2026ab2d377,
281 0x340be246dbd3e5c40f0954debe41e951,
282 0x340be246dbd3e5c40f0954debe41e950,
283 0x39c0d4009b71c73a648a6496826f7118,
284 0x39c0d4009b71c73a648a6496826f7119,
285 0x0950311a4fb78fe07a7a8e94e136f9bc,
286 0x0950311a4fb78fe07a7a8e94e136f9bd,
287 0x049b075c0f15ad1e11f9bedcdd1861f5,
288 0x049b075c0f15ad1e11f9bedcdd1861f4,
289 0x595326a75a2afc5b4ea8796f47351afd,
290 0x595326a75a2afc5b4ea8796f47351afc,
291 0x549810e11a88dea5252b49277b1b82b4,
292 0x549810e11a88dea5252b49277b1b82b5,
293 0x6408f5fbce4e967f3bdba32518420a10,
294 0x6408f5fbce4e967f3bdba32518420a11,
295 0x69c3c3bd8eecb4815058936d246c9259,
296 0x69c3c3bd8eecb4815058936d246c9258,
297 0xde77167b8539a7970d972a0b4c6fa966,
298 0xde77167b8539a7970d972a0b4c6fa967,
299 0xd3bc203dc59b856966141a437041312f,
300 0xd3bc203dc59b856966141a437041312e,
301 0xe32cc527115dcdb378e4f0411318b98b,
302 0xe32cc527115dcdb378e4f0411318b98a,
303 0xeee7f36151ffef4d1367c0092f3621c2,
304 0xeee7f36151ffef4d1367c0092f3621c3,
305 0xb32fd29a04c0be084c3607bab51b5aca,
306 0xb32fd29a04c0be084c3607bab51b5acb,
307 0xbee4e4dc44629cf627b537f28935c283,
308 0xbee4e4dc44629cf627b537f28935c282,
309 0x8e7401c690a4d42c3945ddf0ea6c4a27,
310 0x8e7401c690a4d42c3945ddf0ea6c4a26,
311 0x83bf3780d006f6d252c6edb8d642d26e,
312 0x83bf3780d006f6d252c6edb8d642d26f,
313 0x7959d70ce1ee694253b85b6402b1e849,
314 0x7959d70ce1ee694253b85b6402b1e848,
315 0x7492e14aa14c4bbc383b6b2c3e9f7000,
316 0x7492e14aa14c4bbc383b6b2c3e9f7001,
317 0x44020450758a036626cb812e5dc6f8a4,
318 0x44020450758a036626cb812e5dc6f8a5,
319 0x49c93216352821984d48b16661e860ed,
320 0x49c93216352821984d48b16661e860ec,
321 0x140113ed601770dd121976d5fbc51be5,
322 0x140113ed601770dd121976d5fbc51be4,
323 0x19ca25ab20b55223799a469dc7eb83ac,
324 0x19ca25ab20b55223799a469dc7eb83ad,
325 0x295ac0b1f4731af9676aac9fa4b20b08,
326 0x295ac0b1f4731af9676aac9fa4b20b09,
327 0x2491f6f7b4d138070ce99cd7989c9341,
328 0x2491f6f7b4d138070ce99cd7989c9340,
329 0xc61bb1d9030ec2b6c4cb3ae603fc8533,
330 0xc61bb1d9030ec2b6c4cb3ae603fc8532,
331 0xcbd0879f43ace048af480aae3fd21d7a,
332 0xcbd0879f43ace048af480aae3fd21d7b,
333 0xfb406285976aa892b1b8e0ac5c8b95de,
334 0xfb406285976aa892b1b8e0ac5c8b95df,
335 0xf68b54c3d7c88a6cda3bd0e460a50d97,
336 0xf68b54c3d7c88a6cda3bd0e460a50d96,
337 0xab43753882f7db29856a1757fa88769f,
338 0xab43753882f7db29856a1757fa88769e,
339 0xa688437ec255f9d7eee9271fc6a6eed6,
340 0xa688437ec255f9d7eee9271fc6a6eed7,
341 0x9618a6641693b10df019cd1da5ff6672,
342 0x9618a6641693b10df019cd1da5ff6673,
343 0x9bd39022563193f39b9afd5599d1fe3b,
344 0x9bd39022563193f39b9afd5599d1fe3a,
345 0x613570ae67d90c639ae44b894d22c41c,
346 0x613570ae67d90c639ae44b894d22c41d,
347 0x6cfe46e8277b2e9df1677bc1710c5c55,
348 0x6cfe46e8277b2e9df1677bc1710c5c54,
349 0x5c6ea3f2f3bd6647ef9791c31255d4f1,
350 0x5c6ea3f2f3bd6647ef9791c31255d4f0,
351 0x51a595b4b31f44b98414a18b2e7b4cb8,
352 0x51a595b4b31f44b98414a18b2e7b4cb9,
353 0x0c6db44fe62015fcdb456638b45637b0,
354 0x0c6db44fe62015fcdb456638b45637b1,
355 0x01a68209a6823702b0c656708878aff9,
356 0x01a68209a6823702b0c656708878aff8,
357 0x3136671372447fd8ae36bc72eb21275d,
358 0x3136671372447fd8ae36bc72eb21275c,
359 0x3cfd515532e65d26c5b58c3ad70fbf14,
360 0x3cfd515532e65d26c5b58c3ad70fbf15,
361 0x8b49849339334e30987a355cbf0c842b,
362 0x8b49849339334e30987a355cbf0c842a,
363 0x8682b2d579916ccef3f9051483221c62,
364 0x8682b2d579916ccef3f9051483221c63,
365 0xb61257cfad572414ed09ef16e07b94c6,
366 0xb61257cfad572414ed09ef16e07b94c7,
367 0xbbd96189edf506ea868adf5edc550c8f,
368 0xbbd96189edf506ea868adf5edc550c8e,
369 0xe6114072b8ca57afd9db18ed46787787,
370 0xe6114072b8ca57afd9db18ed46787786,
371 0xebda7634f8687551b25828a57a56efce,
372 0xebda7634f8687551b25828a57a56efcf,
373 0xdb4a932e2cae3d8baca8c2a7190f676a,
374 0xdb4a932e2cae3d8baca8c2a7190f676b,
375 0xd681a5686c0c1f75c72bf2ef2521ff23,
376 0xd681a5686c0c1f75c72bf2ef2521ff22,
377 0x2c6745e45de480e5c6554433f1d2c504,
378 0x2c6745e45de480e5c6554433f1d2c505,
379 0x21ac73a21d46a21badd6747bcdfc5d4d,
380 0x21ac73a21d46a21badd6747bcdfc5d4c,
381 0x113c96b8c980eac1b3269e79aea5d5e9,
382 0x113c96b8c980eac1b3269e79aea5d5e8,
383 0x1cf7a0fe8922c83fd8a5ae31928b4da0,
384 0x1cf7a0fe8922c83fd8a5ae31928b4da1,
385 0x413f8105dc1d997a87f4698208a636a8,
386 0x413f8105dc1d997a87f4698208a636a9,
387 0x4cf4b7439cbfbb84ec7759ca3488aee1,
388 0x4cf4b7439cbfbb84ec7759ca3488aee0,
389 0x7c6452594879f35ef287b3c857d12645,
390 0x7c6452594879f35ef287b3c857d12644,
391 0x71af641f08dbd1a0990483806bffbe0c,
392 0x71af641f08dbd1a0990483806bffbe0d,
393 ];
394
395 Ghash128b::new(LOOKUP_TABLE[value.0 as usize])
396 }
397}
398
399#[cfg(test)]
400mod tests {
401 use proptest::{collection::vec, prelude::any, proptest};
402
403 use super::*;
404 use crate::{
405 WideMul, arithmetic_traits::InvertOrZero,
406 binary_field::tests::is_binary_field_valid_generator,
407 };
408
409 #[test]
410 fn test_ghash_mul() {
411 let a = Ghash128b::new(1u128);
412 let b = Ghash128b::new(1u128);
413 let c = a * b;
414
415 assert_eq!(c, Ghash128b::new(1u128));
416
417 let a = Ghash128b::new(1u128);
418 let b = Ghash128b::new(2u128);
419 let c = a * b;
420
421 assert_eq!(c, Ghash128b::new(2u128));
422
423 let a = Ghash128b::new(1u128);
424 let b = Ghash128b::new(1297182698762987u128);
425 let c = a * b;
426
427 assert_eq!(c, Ghash128b::new(1297182698762987u128));
428
429 let a = Ghash128b::new(2u128);
430 let b = Ghash128b::new(2u128);
431 let c = a * b;
432
433 assert_eq!(c, Ghash128b::new(4u128));
434
435 let a = Ghash128b::new(2u128);
436 let b = Ghash128b::new(3u128);
437 let c = a * b;
438
439 assert_eq!(c, Ghash128b::new(6u128));
440
441 let a = Ghash128b::new(3u128);
442 let b = Ghash128b::new(3u128);
443 let c = a * b;
444
445 assert_eq!(c, Ghash128b::new(5u128));
446
447 let a = Ghash128b::from(1u128 << 127);
448 let b = Ghash128b::new(2u128);
449 let c = a * b;
450
451 assert_eq!(c, Ghash128b::from(0b10000111));
452
453 let a = Ghash128b::from((1u128 << 127) + 1);
454 let b = Ghash128b::new(2u128);
455 let c = a * b;
456
457 assert_eq!(c, Ghash128b::from(0b10000101));
458
459 let a = Ghash128b::from(3u128 << 126);
460 let b = Ghash128b::new(2u128);
461 let c = a * b;
462
463 assert_eq!(c, Ghash128b::from(0b10000111 + (1u128 << 127)));
464
465 let a = Ghash128b::from(1u128 << 127);
466 let b = Ghash128b::new(4u128);
467 let c = a * b;
468
469 assert_eq!(c, Ghash128b::from(0b10000111 << 1));
470
471 let a = Ghash128b::from(1u128 << 127);
472 let b = Ghash128b::from(1u128 << 122);
473 let c = a * b;
474
475 assert_eq!(c, Ghash128b::from((0b00000111 << 121) + 0b10000111));
476 }
477
478 #[test]
479 fn test_multiplicative_generator() {
480 assert!(is_binary_field_valid_generator::<Ghash128b>());
481 }
482
483 #[test]
484 fn test_mul_x() {
485 let test_cases = [
486 0x0, 0x1, 0x2, 0x80000000000000000000000000000000u128, 0x40000000000000000000000000000000u128, 0xffffffffffffffffffffffffffffffffu128, 0x87u128, 0x21ac73a21d46a21badd6747bcdfc5d4d, ];
495
496 for &value in &test_cases {
497 let field_val = Ghash128b::from(value);
498 let mul_x_result = field_val.mul_x();
499 let regular_mul_result = field_val * Ghash128b::new(2u128);
500
501 assert_eq!(
502 mul_x_result, regular_mul_result,
503 "mul_x and regular multiplication by 2 differ for value {:#x}",
504 value
505 );
506 }
507 }
508
509 #[test]
510 fn test_mul_inv_x() {
511 let test_cases = [
512 0x0, 0x1, 0x2, 0x1u128, 0x3u128, 0xffffffffffffffffffffffffffffffffu128, 0x87u128, 0x21ac73a21d46a21badd6747bcdfc5d4d, ];
521
522 for &value in &test_cases {
523 let field_val = Ghash128b::from(value);
524 let mul_inv_x_result = field_val.mul_inv_x();
525 let regular_mul_result = field_val * unsafe { Ghash128b::new(2u128).invert() };
527
528 assert_eq!(
529 mul_inv_x_result, regular_mul_result,
530 "mul_inv_x and regular multiplication by 2 differ for value {:#x}",
531 value
532 );
533 }
534 }
535
536 proptest! {
537 #[test]
538 fn test_conversion_from_aes_consistency(a in any::<u8>(), b in any::<u8>()) {
539 let a_val = AESTowerField8b::new(a);
540 let b_val = AESTowerField8b::new(b);
541 let converted_a = Ghash128b::from(a_val);
542 let converted_b = Ghash128b::from(b_val);
543 assert_eq!(Ghash128b::from(a_val * b_val), converted_a * converted_b);
544 }
545
546 #[test]
547 fn test_wide_mul_correctness(a in any::<u128>(), b in any::<u128>()) {
548 let a = Ghash128b::from(a);
549 let b = Ghash128b::from(b);
550 let reduced = Ghash128b::reduce(Ghash128b::wide_mul(a, b));
551 assert_eq!(reduced, a * b);
552 }
553
554 #[test]
556 fn test_wide_mul_deferred_accumulation(
557 a1 in any::<u128>(), b1 in any::<u128>(),
558 a2 in any::<u128>(), b2 in any::<u128>(),
559 ) {
560 let (a1, b1) = (Ghash128b::from(a1), Ghash128b::from(b1));
561 let (a2, b2) = (Ghash128b::from(a2), Ghash128b::from(b2));
562 let wide =
563 Ghash128b::wide_mul(a1, b1) + Ghash128b::wide_mul(a2, b2);
564 assert_eq!(Ghash128b::reduce(wide), a1 * b1 + a2 * b2);
565 }
566
567 #[test]
573 fn test_ghash_serialize_slice_matches_loop(values in vec(any::<u128>(), 0..300)) {
574 let values: Vec<Ghash128b> =
575 values.into_iter().map(Ghash128b::from).collect();
576
577 let mut expected = Vec::new();
578 for value in &values {
579 value.serialize(&mut expected).unwrap();
580 }
581
582 let mut actual = Vec::new();
583 Ghash128b::serialize_slice(&values, &mut actual).unwrap();
584
585 assert_eq!(actual, expected);
586
587 let mut cursor = actual.as_slice();
591 let deserialized: Vec<Ghash128b> = (0..values.len())
592 .map(|_| Ghash128b::deserialize(&mut cursor).unwrap())
593 .collect();
594 assert_eq!(deserialized, values);
595 assert!(cursor.is_empty());
596 }
597 }
598}