1use alloc::string::{String, ToString};
2use core::fmt;
3use core::ops::{
4 Add, AddAssign, Div, DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr,
5 ShrAssign, Sub, SubAssign,
6};
7use core::str::FromStr;
8
9use crate::errors::{
10 ConversionOverflowError, DivideByZeroError, OverflowError, OverflowOperation, StdError,
11};
12use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
13use crate::{
14 Int128, Int256, Int512, Int64, Uint128, Uint256, Uint64, __internal::forward_ref_partial_eq,
15};
16
17use bnum::types::U512;
20
21use super::conversion::{forward_try_from, primitive_to_wrapped_int, try_from_int_to_uint};
22use super::impl_int_serde;
23use super::num_consts::NumConsts;
24
25#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
52pub struct Uint512(#[schemars(with = "String")] pub(crate) U512);
53
54impl_int_serde!(Uint512);
55forward_ref_partial_eq!(Uint512, Uint512);
56
57impl Uint512 {
58 pub const MAX: Uint512 = Uint512(U512::MAX);
59 pub const MIN: Uint512 = Uint512(U512::ZERO);
60
61 #[must_use]
70 pub const fn new(value: u128) -> Self {
71 let b = value.to_be_bytes();
72 Self::from_be_bytes([
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, b[0], b[1], b[2], b[3], b[4],
75 b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15],
76 ])
77 }
78
79 #[inline]
81 pub const fn zero() -> Self {
82 Uint512(U512::ZERO)
83 }
84
85 #[inline]
87 pub const fn one() -> Self {
88 Self(U512::ONE)
89 }
90
91 #[must_use]
92 pub const fn from_be_bytes(data: [u8; 64]) -> Self {
93 let words: [u64; 8] = [
94 u64::from_le_bytes([
95 data[63], data[62], data[61], data[60], data[59], data[58], data[57], data[56],
96 ]),
97 u64::from_le_bytes([
98 data[55], data[54], data[53], data[52], data[51], data[50], data[49], data[48],
99 ]),
100 u64::from_le_bytes([
101 data[47], data[46], data[45], data[44], data[43], data[42], data[41], data[40],
102 ]),
103 u64::from_le_bytes([
104 data[39], data[38], data[37], data[36], data[35], data[34], data[33], data[32],
105 ]),
106 u64::from_le_bytes([
107 data[31], data[30], data[29], data[28], data[27], data[26], data[25], data[24],
108 ]),
109 u64::from_le_bytes([
110 data[23], data[22], data[21], data[20], data[19], data[18], data[17], data[16],
111 ]),
112 u64::from_le_bytes([
113 data[15], data[14], data[13], data[12], data[11], data[10], data[9], data[8],
114 ]),
115 u64::from_le_bytes([
116 data[7], data[6], data[5], data[4], data[3], data[2], data[1], data[0],
117 ]),
118 ];
119 Self(U512::from_digits(words))
120 }
121
122 #[must_use]
123 pub const fn from_le_bytes(data: [u8; 64]) -> Self {
124 let words: [u64; 8] = [
125 u64::from_le_bytes([
126 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
127 ]),
128 u64::from_le_bytes([
129 data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
130 ]),
131 u64::from_le_bytes([
132 data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],
133 ]),
134 u64::from_le_bytes([
135 data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31],
136 ]),
137 u64::from_le_bytes([
138 data[32], data[33], data[34], data[35], data[36], data[37], data[38], data[39],
139 ]),
140 u64::from_le_bytes([
141 data[40], data[41], data[42], data[43], data[44], data[45], data[46], data[47],
142 ]),
143 u64::from_le_bytes([
144 data[48], data[49], data[50], data[51], data[52], data[53], data[54], data[55],
145 ]),
146 u64::from_le_bytes([
147 data[56], data[57], data[58], data[59], data[60], data[61], data[62], data[63],
148 ]),
149 ];
150 Self(U512::from_digits(words))
151 }
152
153 #[must_use]
156 pub const fn from_uint256(num: Uint256) -> Self {
157 let bytes = num.to_le_bytes();
158 Self::from_le_bytes([
159 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
160 bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
161 bytes[16], bytes[17], bytes[18], bytes[19], bytes[20], bytes[21], bytes[22], bytes[23],
162 bytes[24], bytes[25], bytes[26], bytes[27], bytes[28], bytes[29], bytes[30], bytes[31],
163 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
164 0, 0, 0,
165 ])
166 }
167
168 #[must_use = "this returns the result of the operation, without modifying the original"]
170 pub const fn to_be_bytes(self) -> [u8; 64] {
171 let words = self.0.digits();
172 let words = [
173 words[7].to_be_bytes(),
174 words[6].to_be_bytes(),
175 words[5].to_be_bytes(),
176 words[4].to_be_bytes(),
177 words[3].to_be_bytes(),
178 words[2].to_be_bytes(),
179 words[1].to_be_bytes(),
180 words[0].to_be_bytes(),
181 ];
182 unsafe { core::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
183 }
184
185 #[must_use = "this returns the result of the operation, without modifying the original"]
187 pub const fn to_le_bytes(self) -> [u8; 64] {
188 let words = self.0.digits();
189 let words = [
190 words[0].to_le_bytes(),
191 words[1].to_le_bytes(),
192 words[2].to_le_bytes(),
193 words[3].to_le_bytes(),
194 words[4].to_le_bytes(),
195 words[5].to_le_bytes(),
196 words[6].to_le_bytes(),
197 words[7].to_le_bytes(),
198 ];
199 unsafe { core::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
200 }
201
202 #[must_use]
203 pub const fn is_zero(&self) -> bool {
204 self.0.is_zero()
205 }
206
207 #[must_use = "this returns the result of the operation, without modifying the original"]
208 pub const fn pow(self, exp: u32) -> Self {
209 match self.0.checked_pow(exp) {
210 Some(val) => Self(val),
211 None => panic!("attempt to exponentiate with overflow"),
212 }
213 }
214
215 #[must_use = "this returns the result of the operation, without modifying the original"]
221 pub fn ilog2(self) -> u32 {
222 self.0.checked_ilog2().unwrap()
223 }
224
225 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
226 self.0
227 .checked_add(other.0)
228 .map(Self)
229 .ok_or_else(|| OverflowError::new(OverflowOperation::Add))
230 }
231
232 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
233 self.0
234 .checked_sub(other.0)
235 .map(Self)
236 .ok_or_else(|| OverflowError::new(OverflowOperation::Sub))
237 }
238
239 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
240 self.0
241 .checked_mul(other.0)
242 .map(Self)
243 .ok_or_else(|| OverflowError::new(OverflowOperation::Mul))
244 }
245
246 pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
247 self.0
248 .checked_pow(exp)
249 .map(Self)
250 .ok_or_else(|| OverflowError::new(OverflowOperation::Pow))
251 }
252
253 pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
254 self.0
255 .checked_div(other.0)
256 .map(Self)
257 .ok_or(DivideByZeroError)
258 }
259
260 pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivideByZeroError> {
261 self.checked_div(other)
262 }
263
264 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
265 self.0
266 .checked_rem(other.0)
267 .map(Self)
268 .ok_or(DivideByZeroError)
269 }
270
271 pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
272 self.0
273 .checked_shr(other)
274 .map(Self)
275 .ok_or_else(|| OverflowError::new(OverflowOperation::Shr))
276 }
277
278 pub fn checked_shl(self, other: u32) -> Result<Self, OverflowError> {
279 if other >= 512 {
280 return Err(OverflowError::new(OverflowOperation::Shl));
281 }
282
283 Ok(Self(self.0.shl(other)))
284 }
285
286 #[must_use = "this returns the result of the operation, without modifying the original"]
287 #[inline]
288 pub fn wrapping_add(self, other: Self) -> Self {
289 Self(self.0.wrapping_add(other.0))
290 }
291
292 #[must_use = "this returns the result of the operation, without modifying the original"]
293 #[inline]
294 pub fn wrapping_sub(self, other: Self) -> Self {
295 Self(self.0.wrapping_sub(other.0))
296 }
297
298 #[must_use = "this returns the result of the operation, without modifying the original"]
299 #[inline]
300 pub fn wrapping_mul(self, other: Self) -> Self {
301 Self(self.0.wrapping_mul(other.0))
302 }
303
304 #[must_use = "this returns the result of the operation, without modifying the original"]
305 #[inline]
306 pub fn wrapping_pow(self, other: u32) -> Self {
307 Self(self.0.wrapping_pow(other))
308 }
309
310 #[must_use = "this returns the result of the operation, without modifying the original"]
311 pub fn saturating_add(self, other: Self) -> Self {
312 Self(self.0.saturating_add(other.0))
313 }
314
315 #[must_use = "this returns the result of the operation, without modifying the original"]
316 pub fn saturating_sub(self, other: Self) -> Self {
317 Self(self.0.saturating_sub(other.0))
318 }
319
320 #[must_use = "this returns the result of the operation, without modifying the original"]
321 pub fn saturating_mul(self, other: Self) -> Self {
322 Self(self.0.saturating_mul(other.0))
323 }
324
325 #[must_use = "this returns the result of the operation, without modifying the original"]
326 pub fn saturating_pow(self, exp: u32) -> Self {
327 Self(self.0.saturating_pow(exp))
328 }
329
330 #[must_use = "this returns the result of the operation, without modifying the original"]
334 pub const fn strict_add(self, rhs: Self) -> Self {
335 match self.0.checked_add(rhs.0) {
336 None => panic!("attempt to add with overflow"),
337 Some(sum) => Self(sum),
338 }
339 }
340
341 #[must_use = "this returns the result of the operation, without modifying the original"]
345 pub const fn strict_sub(self, other: Self) -> Self {
346 match self.0.checked_sub(other.0) {
347 None => panic!("attempt to subtract with overflow"),
348 Some(diff) => Self(diff),
349 }
350 }
351
352 #[must_use = "this returns the result of the operation, without modifying the original"]
353 pub const fn abs_diff(self, other: Self) -> Self {
354 Self(self.0.abs_diff(other.0))
355 }
356}
357
358impl NumConsts for Uint512 {
359 const ZERO: Self = Self::zero();
360 const ONE: Self = Self::one();
361 const MAX: Self = Self::MAX;
362 const MIN: Self = Self::MIN;
363}
364
365primitive_to_wrapped_int!(u8, Uint512);
367primitive_to_wrapped_int!(u16, Uint512);
368primitive_to_wrapped_int!(u32, Uint512);
369primitive_to_wrapped_int!(u64, Uint512);
370primitive_to_wrapped_int!(u128, Uint512);
371
372impl From<Uint256> for Uint512 {
373 fn from(val: Uint256) -> Self {
374 let mut bytes = [0u8; 64];
375 bytes[32..].copy_from_slice(&val.to_be_bytes());
376
377 Self::from_be_bytes(bytes)
378 }
379}
380
381impl From<Uint128> for Uint512 {
382 fn from(val: Uint128) -> Self {
383 val.u128().into()
384 }
385}
386
387impl From<Uint64> for Uint512 {
388 fn from(val: Uint64) -> Self {
389 val.u64().into()
390 }
391}
392
393impl TryFrom<Uint512> for Uint256 {
394 type Error = ConversionOverflowError;
395
396 fn try_from(value: Uint512) -> Result<Self, Self::Error> {
397 let bytes = value.to_be_bytes();
398 let (first_bytes, last_bytes) = bytes.split_at(32);
399
400 if first_bytes != [0u8; 32] {
401 return Err(ConversionOverflowError::new("Uint512", "Uint256"));
402 }
403
404 Ok(Self::from_be_bytes(last_bytes.try_into().unwrap()))
405 }
406}
407
408forward_try_from!(Uint512, Uint128);
409forward_try_from!(Uint512, Uint64);
410
411try_from_int_to_uint!(Int64, Uint512);
413try_from_int_to_uint!(Int128, Uint512);
414try_from_int_to_uint!(Int256, Uint512);
415try_from_int_to_uint!(Int512, Uint512);
416
417impl TryFrom<&str> for Uint512 {
418 type Error = StdError;
419
420 fn try_from(val: &str) -> Result<Self, Self::Error> {
421 Self::from_str(val)
422 }
423}
424
425impl FromStr for Uint512 {
426 type Err = StdError;
427
428 fn from_str(s: &str) -> Result<Self, Self::Err> {
429 match U512::from_str_radix(s, 10) {
430 Ok(u) => Ok(Self(u)),
431 Err(e) => Err(StdError::generic_err(format!("Parsing u512: {e}"))),
432 }
433 }
434}
435
436impl From<Uint512> for String {
437 fn from(original: Uint512) -> Self {
438 original.to_string()
439 }
440}
441
442impl fmt::Display for Uint512 {
443 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444 self.0.fmt(f)
445 }
446}
447
448impl Add<Uint512> for Uint512 {
449 type Output = Self;
450
451 fn add(self, rhs: Self) -> Self {
452 self.strict_add(rhs)
453 }
454}
455forward_ref_binop!(impl Add, add for Uint512, Uint512);
456
457impl Sub<Uint512> for Uint512 {
458 type Output = Self;
459
460 fn sub(self, rhs: Self) -> Self {
461 self.strict_sub(rhs)
462 }
463}
464forward_ref_binop!(impl Sub, sub for Uint512, Uint512);
465
466impl SubAssign<Uint512> for Uint512 {
467 fn sub_assign(&mut self, rhs: Uint512) {
468 self.0 = self.0.checked_sub(rhs.0).unwrap();
469 }
470}
471forward_ref_op_assign!(impl SubAssign, sub_assign for Uint512, Uint512);
472
473impl Div<Uint512> for Uint512 {
474 type Output = Self;
475
476 fn div(self, rhs: Self) -> Self::Output {
477 Self(self.0.checked_div(rhs.0).unwrap())
478 }
479}
480
481impl<'a> Div<&'a Uint512> for Uint512 {
482 type Output = Self;
483
484 fn div(self, rhs: &'a Uint512) -> Self::Output {
485 Self(self.0.checked_div(rhs.0).unwrap())
486 }
487}
488
489impl Rem for Uint512 {
490 type Output = Self;
491
492 #[inline]
496 fn rem(self, rhs: Self) -> Self {
497 Self(self.0.rem(rhs.0))
498 }
499}
500forward_ref_binop!(impl Rem, rem for Uint512, Uint512);
501
502impl Not for Uint512 {
503 type Output = Self;
504
505 fn not(self) -> Self::Output {
506 Self(!self.0)
507 }
508}
509
510impl RemAssign<Uint512> for Uint512 {
511 fn rem_assign(&mut self, rhs: Uint512) {
512 *self = *self % rhs;
513 }
514}
515forward_ref_op_assign!(impl RemAssign, rem_assign for Uint512, Uint512);
516
517impl Mul<Uint512> for Uint512 {
518 type Output = Self;
519
520 fn mul(self, rhs: Self) -> Self::Output {
521 Self(self.0.checked_mul(rhs.0).unwrap())
522 }
523}
524forward_ref_binop!(impl Mul, mul for Uint512, Uint512);
525
526impl MulAssign<Uint512> for Uint512 {
527 fn mul_assign(&mut self, rhs: Self) {
528 self.0 = self.0.checked_mul(rhs.0).unwrap();
529 }
530}
531forward_ref_op_assign!(impl MulAssign, mul_assign for Uint512, Uint512);
532
533impl Shr<u32> for Uint512 {
534 type Output = Self;
535
536 fn shr(self, rhs: u32) -> Self::Output {
537 self.checked_shr(rhs).unwrap_or_else(|_| {
538 panic!(
539 "right shift error: {rhs} is larger or equal than the number of bits in Uint512",
540 )
541 })
542 }
543}
544
545impl<'a> Shr<&'a u32> for Uint512 {
546 type Output = Self;
547
548 fn shr(self, rhs: &'a u32) -> Self::Output {
549 Shr::<u32>::shr(self, *rhs)
550 }
551}
552
553impl Shl<u32> for Uint512 {
554 type Output = Self;
555
556 fn shl(self, rhs: u32) -> Self::Output {
557 self.checked_shl(rhs)
558 .expect("attempt to shift left with overflow")
559 }
560}
561
562impl<'a> Shl<&'a u32> for Uint512 {
563 type Output = Self;
564
565 fn shl(self, rhs: &'a u32) -> Self::Output {
566 self.shl(*rhs)
567 }
568}
569
570impl AddAssign<Uint512> for Uint512 {
571 fn add_assign(&mut self, rhs: Uint512) {
572 self.0 = self.0.checked_add(rhs.0).unwrap();
573 }
574}
575
576impl<'a> AddAssign<&'a Uint512> for Uint512 {
577 fn add_assign(&mut self, rhs: &'a Uint512) {
578 self.0 = self.0.checked_add(rhs.0).unwrap();
579 }
580}
581
582impl DivAssign<Uint512> for Uint512 {
583 fn div_assign(&mut self, rhs: Self) {
584 self.0 = self.0.checked_div(rhs.0).unwrap();
585 }
586}
587
588impl<'a> DivAssign<&'a Uint512> for Uint512 {
589 fn div_assign(&mut self, rhs: &'a Uint512) {
590 self.0 = self.0.checked_div(rhs.0).unwrap();
591 }
592}
593
594impl ShrAssign<u32> for Uint512 {
595 fn shr_assign(&mut self, rhs: u32) {
596 *self = Shr::<u32>::shr(*self, rhs);
597 }
598}
599
600impl<'a> ShrAssign<&'a u32> for Uint512 {
601 fn shr_assign(&mut self, rhs: &'a u32) {
602 *self = Shr::<u32>::shr(*self, *rhs);
603 }
604}
605
606impl ShlAssign<u32> for Uint512 {
607 fn shl_assign(&mut self, rhs: u32) {
608 *self = self.shl(rhs);
609 }
610}
611
612impl<'a> ShlAssign<&'a u32> for Uint512 {
613 fn shl_assign(&mut self, rhs: &'a u32) {
614 *self = self.shl(*rhs);
615 }
616}
617
618impl<A> core::iter::Sum<A> for Uint512
619where
620 Self: Add<A, Output = Self>,
621{
622 fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
623 iter.fold(Self::zero(), Add::add)
624 }
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630 use crate::math::conversion::test_try_from_int_to_uint;
631
632 #[test]
633 fn size_of_works() {
634 assert_eq!(core::mem::size_of::<Uint512>(), 64);
635 }
636
637 #[test]
638 fn uint512_new_works() {
639 let num = Uint512::new(1);
640 assert_eq!(
641 num.to_be_bytes(),
642 [
643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
645 0, 0, 0, 0, 0, 0, 0, 1
646 ]
647 );
648
649 for v in [0, 1, 18, 875786576, u128::MAX] {
650 let uut = Uint512::new(v);
652 assert_eq!(uut, Uint512::from(v));
653 }
654 }
655
656 #[test]
657 fn uint512_from_be_bytes_works() {
658 let num = Uint512::from_be_bytes([1; 64]);
659 let a: [u8; 64] = num.to_be_bytes();
660 assert_eq!(a, [1; 64]);
661
662 let be_bytes = [
663 0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
664 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
665 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
666 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
667 ];
668 let num = Uint512::from_be_bytes(be_bytes);
669 let resulting_bytes: [u8; 64] = num.to_be_bytes();
670 assert_eq!(be_bytes, resulting_bytes);
671 }
672
673 #[test]
674 fn uint512_not_works() {
675 let num = Uint512::from_be_bytes([1; 64]);
676 let a = (!num).to_be_bytes();
677 assert_eq!(a, [254; 64]);
678
679 assert_eq!(!Uint512::MAX, Uint512::MIN);
680 assert_eq!(!Uint512::MIN, Uint512::MAX);
681 }
682
683 #[test]
684 fn uint512_zero_works() {
685 let zero = Uint512::zero();
686 assert_eq!(
687 zero.to_be_bytes(),
688 [
689 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
690 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
691 0, 0, 0, 0, 0, 0, 0, 0
692 ]
693 );
694 }
695
696 #[test]
697 fn uin512_one_works() {
698 let one = Uint512::one();
699 assert_eq!(
700 one.to_be_bytes(),
701 [
702 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
703 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
704 0, 0, 0, 0, 0, 0, 0, 1
705 ]
706 );
707 }
708
709 #[test]
710 fn uint512_endianness() {
711 let be_bytes = [
712 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
713 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
714 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
715 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
716 ];
717 let le_bytes = [
718 3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
719 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
720 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
721 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
722 ];
723
724 let a = Uint512::from_be_bytes(be_bytes);
726 let b = Uint512::from_le_bytes(le_bytes);
727 assert_eq!(a, Uint512::from(65536u32 + 512 + 3));
728 assert_eq!(a, b);
729 }
730
731 #[test]
732 fn uint512_convert_from() {
733 let a = Uint512::from(5u128);
734 assert_eq!(a.0, U512::from(5u32));
735
736 let a = Uint512::from(5u64);
737 assert_eq!(a.0, U512::from(5u32));
738
739 let a = Uint512::from(5u32);
740 assert_eq!(a.0, U512::from(5u32));
741
742 let a = Uint512::from(5u16);
743 assert_eq!(a.0, U512::from(5u32));
744
745 let a = Uint512::from(5u8);
746 assert_eq!(a.0, U512::from(5u32));
747
748 let result = Uint512::try_from("34567");
749 assert_eq!(
750 result.unwrap().0,
751 U512::from_str_radix("34567", 10).unwrap()
752 );
753
754 let result = Uint512::try_from("1.23");
755 assert!(result.is_err());
756 }
757
758 #[test]
759 fn uint512_try_from_signed_works() {
760 test_try_from_int_to_uint::<Int64, Uint512>("Int64", "Uint512");
761 test_try_from_int_to_uint::<Int128, Uint512>("Int128", "Uint512");
762 test_try_from_int_to_uint::<Int256, Uint512>("Int256", "Uint512");
763 test_try_from_int_to_uint::<Int512, Uint512>("Int512", "Uint512");
764 }
765
766 #[test]
767 fn uint512_try_into() {
768 assert!(Uint64::try_from(Uint512::MAX).is_err());
769 assert!(Uint128::try_from(Uint512::MAX).is_err());
770 assert!(Uint256::try_from(Uint512::MAX).is_err());
771
772 assert_eq!(Uint64::try_from(Uint512::zero()), Ok(Uint64::zero()));
773 assert_eq!(Uint128::try_from(Uint512::zero()), Ok(Uint128::zero()));
774 assert_eq!(Uint256::try_from(Uint512::zero()), Ok(Uint256::zero()));
775
776 assert_eq!(
777 Uint64::try_from(Uint512::from(42u64)),
778 Ok(Uint64::from(42u64))
779 );
780 assert_eq!(
781 Uint128::try_from(Uint512::from(42u128)),
782 Ok(Uint128::from(42u128))
783 );
784 assert_eq!(
785 Uint256::try_from(Uint512::from(42u128)),
786 Ok(Uint256::from(42u128))
787 );
788 }
789
790 #[test]
791 fn uint512_convert_to_uint128() {
792 let source = Uint512::from(42u128);
793 let target = Uint128::try_from(source);
794 assert_eq!(target, Ok(Uint128::new(42u128)));
795
796 let source = Uint512::MAX;
797 let target = Uint128::try_from(source);
798 assert_eq!(
799 target,
800 Err(ConversionOverflowError::new("Uint512", "Uint128"))
801 );
802 }
803
804 #[test]
805 fn uint512_from_uint256() {
806 assert_eq!(
807 Uint512::from_uint256(Uint256::from_str("123").unwrap()),
808 Uint512::from_str("123").unwrap()
809 );
810
811 assert_eq!(
812 Uint512::from_uint256(Uint256::from_str("9785746283745").unwrap()),
813 Uint512::from_str("9785746283745").unwrap()
814 );
815
816 assert_eq!(
817 Uint512::from_uint256(
818 Uint256::from_str(
819 "97857462837575757832978493758398593853985452378423874623874628736482736487236"
820 )
821 .unwrap()
822 ),
823 Uint512::from_str(
824 "97857462837575757832978493758398593853985452378423874623874628736482736487236"
825 )
826 .unwrap()
827 );
828 }
829
830 #[test]
831 fn uint512_implements_display() {
832 let a = Uint512::from(12345u32);
833 assert_eq!(format!("Embedded: {a}"), "Embedded: 12345");
834 assert_eq!(a.to_string(), "12345");
835
836 let a = Uint512::zero();
837 assert_eq!(format!("Embedded: {a}"), "Embedded: 0");
838 assert_eq!(a.to_string(), "0");
839 }
840
841 #[test]
842 fn uint512_display_padding_works() {
843 let a = Uint512::from(123u64);
845 assert_eq!(format!("Embedded: {a:05}"), "Embedded: 00123");
846
847 let a = Uint512::from(123u64);
849 assert_eq!(format!("Embedded: {a:02}"), "Embedded: 123");
850 }
851
852 #[test]
853 fn uint512_to_be_bytes_works() {
854 assert_eq!(
855 Uint512::zero().to_be_bytes(),
856 [
857 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
859 0, 0, 0, 0, 0, 0, 0, 0,
860 ]
861 );
862 assert_eq!(
863 Uint512::MAX.to_be_bytes(),
864 [
865 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
866 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
867 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
868 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
869 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
870 ]
871 );
872 assert_eq!(
873 Uint512::from(1u128).to_be_bytes(),
874 [
875 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
876 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
877 0, 0, 0, 0, 0, 0, 0, 1
878 ]
879 );
880 assert_eq!(
882 Uint512::from(240282366920938463463374607431768124608u128).to_be_bytes(),
883 [
884 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
885 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 196, 179, 87, 165,
886 121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192
887 ]
888 );
889 assert_eq!(
890 Uint512::from_be_bytes([
891 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
892 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
893 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
894 252, 96, 230, 187, 38, 29
895 ])
896 .to_be_bytes(),
897 [
898 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
899 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
900 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
901 252, 96, 230, 187, 38, 29
902 ]
903 );
904 }
905
906 #[test]
907 fn uint512_to_le_bytes_works() {
908 assert_eq!(
909 Uint512::zero().to_le_bytes(),
910 [
911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
913 0, 0, 0, 0, 0, 0, 0, 0
914 ]
915 );
916 assert_eq!(
917 Uint512::MAX.to_le_bytes(),
918 [
919 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
920 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
921 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
922 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
923 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
924 ]
925 );
926 assert_eq!(
927 Uint512::from(1u128).to_le_bytes(),
928 [
929 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
931 0, 0, 0, 0, 0, 0, 0, 0
932 ]
933 );
934 assert_eq!(
936 Uint512::from(240282366920938463463374607431768124608u128).to_le_bytes(),
937 [
938 192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180, 0, 0,
939 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
940 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
941 ]
942 );
943 assert_eq!(
944 Uint512::from_be_bytes([
945 17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
946 211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
947 238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
948 252, 96, 230, 187, 38, 29
949 ])
950 .to_le_bytes(),
951 [
952 29, 38, 187, 230, 96, 252, 8, 99, 12, 47, 22, 13, 59, 44, 10, 64, 73, 154, 195,
953 166, 88, 14, 22, 85, 119, 238, 134, 208, 45, 106, 88, 218, 240, 150, 115, 200, 240,
954 2, 233, 42, 7, 192, 201, 211, 54, 65, 76, 87, 78, 67, 21, 33, 38, 0, 91, 58, 200,
955 123, 67, 87, 32, 23, 4, 17
956 ]
957 );
958 }
959
960 #[test]
961 fn uint512_is_zero_works() {
962 assert!(Uint512::zero().is_zero());
963 assert!(Uint512(U512::from(0u32)).is_zero());
964
965 assert!(!Uint512::from(1u32).is_zero());
966 assert!(!Uint512::from(123u32).is_zero());
967 }
968
969 #[test]
970 fn uint512_wrapping_methods() {
971 assert_eq!(
973 Uint512::from(2u32).wrapping_add(Uint512::from(2u32)),
974 Uint512::from(4u32)
975 ); assert_eq!(
977 Uint512::MAX.wrapping_add(Uint512::from(1u32)),
978 Uint512::from(0u32)
979 ); assert_eq!(
983 Uint512::from(7u32).wrapping_sub(Uint512::from(5u32)),
984 Uint512::from(2u32)
985 ); assert_eq!(
987 Uint512::from(0u32).wrapping_sub(Uint512::from(1u32)),
988 Uint512::MAX
989 ); assert_eq!(
993 Uint512::from(3u32).wrapping_mul(Uint512::from(2u32)),
994 Uint512::from(6u32)
995 ); assert_eq!(
997 Uint512::MAX.wrapping_mul(Uint512::from(2u32)),
998 Uint512::MAX - Uint512::one()
999 ); assert_eq!(Uint512::from(2u32).wrapping_pow(3), Uint512::from(8u32)); assert_eq!(Uint512::MAX.wrapping_pow(2), Uint512::from(1u32)); }
1005
1006 #[test]
1007 fn uint512_json() {
1008 let orig = Uint512::from(1234567890987654321u128);
1009 let serialized = serde_json::to_vec(&orig).unwrap();
1010 assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
1011 let parsed: Uint512 = serde_json::from_slice(&serialized).unwrap();
1012 assert_eq!(parsed, orig);
1013 }
1014
1015 #[test]
1016 fn uint512_compare() {
1017 let a = Uint512::from(12345u32);
1018 let b = Uint512::from(23456u32);
1019
1020 assert!(a < b);
1021 assert!(b > a);
1022 assert_eq!(a, Uint512::from(12345u32));
1023 }
1024
1025 #[test]
1026 #[allow(clippy::op_ref)]
1027 fn uint512_math() {
1028 let a = Uint512::from(12345u32);
1029 let b = Uint512::from(23456u32);
1030
1031 let mut c = Uint512::from(300000u32);
1033 c += b;
1034 assert_eq!(c, Uint512::from(323456u32));
1035 let mut d = Uint512::from(300000u32);
1036 d += &b;
1037 assert_eq!(d, Uint512::from(323456u32));
1038
1039 let mut c = Uint512::from(300000u32);
1041 c -= b;
1042 assert_eq!(c, Uint512::from(276544u32));
1043 let mut d = Uint512::from(300000u32);
1044 d -= &b;
1045 assert_eq!(d, Uint512::from(276544u32));
1046
1047 let underflow_result = a.checked_sub(b);
1049 let OverflowError { operation } = underflow_result.unwrap_err();
1050 assert_eq!(operation, OverflowOperation::Sub);
1051 }
1052
1053 #[test]
1054 #[allow(clippy::op_ref)]
1055 fn uint512_add_works() {
1056 assert_eq!(
1057 Uint512::from(2u32) + Uint512::from(1u32),
1058 Uint512::from(3u32)
1059 );
1060 assert_eq!(
1061 Uint512::from(2u32) + Uint512::from(0u32),
1062 Uint512::from(2u32)
1063 );
1064
1065 let a = Uint512::from(10u32);
1067 let b = Uint512::from(3u32);
1068 let expected = Uint512::from(13u32);
1069 assert_eq!(a + b, expected);
1070 assert_eq!(a + &b, expected);
1071 assert_eq!(&a + b, expected);
1072 assert_eq!(&a + &b, expected);
1073 }
1074
1075 #[test]
1076 #[should_panic(expected = "attempt to add with overflow")]
1077 fn uint512_add_overflow_panics() {
1078 let max = Uint512::MAX;
1079 let _ = max + Uint512::from(12u32);
1080 }
1081
1082 #[test]
1083 #[allow(clippy::op_ref)]
1084 fn uint512_sub_works() {
1085 assert_eq!(
1086 Uint512::from(2u32) - Uint512::from(1u32),
1087 Uint512::from(1u32)
1088 );
1089 assert_eq!(
1090 Uint512::from(2u32) - Uint512::from(0u32),
1091 Uint512::from(2u32)
1092 );
1093 assert_eq!(
1094 Uint512::from(2u32) - Uint512::from(2u32),
1095 Uint512::from(0u32)
1096 );
1097
1098 let a = Uint512::from(10u32);
1100 let b = Uint512::from(3u32);
1101 let expected = Uint512::from(7u32);
1102 assert_eq!(a - b, expected);
1103 assert_eq!(a - &b, expected);
1104 assert_eq!(&a - b, expected);
1105 assert_eq!(&a - &b, expected);
1106 }
1107
1108 #[test]
1109 #[should_panic]
1110 fn uint512_sub_overflow_panics() {
1111 let _ = Uint512::from(1u32) - Uint512::from(2u32);
1112 }
1113
1114 #[test]
1115 fn uint512_sub_assign_works() {
1116 let mut a = Uint512::from(14u32);
1117 a -= Uint512::from(2u32);
1118 assert_eq!(a, Uint512::from(12u32));
1119
1120 let mut a = Uint512::from(10u32);
1122 let b = Uint512::from(3u32);
1123 let expected = Uint512::from(7u32);
1124 a -= &b;
1125 assert_eq!(a, expected);
1126 }
1127
1128 #[test]
1129 #[allow(clippy::op_ref)]
1130 fn uint512_mul_works() {
1131 assert_eq!(
1132 Uint512::from(2u32) * Uint512::from(3u32),
1133 Uint512::from(6u32)
1134 );
1135 assert_eq!(Uint512::from(2u32) * Uint512::zero(), Uint512::zero());
1136
1137 let a = Uint512::from(11u32);
1139 let b = Uint512::from(3u32);
1140 let expected = Uint512::from(33u32);
1141 assert_eq!(a * b, expected);
1142 assert_eq!(a * &b, expected);
1143 assert_eq!(&a * b, expected);
1144 assert_eq!(&a * &b, expected);
1145 }
1146
1147 #[test]
1148 fn uint512_mul_assign_works() {
1149 let mut a = Uint512::from(14u32);
1150 a *= Uint512::from(2u32);
1151 assert_eq!(a, Uint512::from(28u32));
1152
1153 let mut a = Uint512::from(10u32);
1155 let b = Uint512::from(3u32);
1156 a *= &b;
1157 assert_eq!(a, Uint512::from(30u32));
1158 }
1159
1160 #[test]
1161 fn uint512_pow_works() {
1162 assert_eq!(Uint512::from(2u32).pow(2), Uint512::from(4u32));
1163 assert_eq!(Uint512::from(2u32).pow(10), Uint512::from(1024u32));
1164 }
1165
1166 #[test]
1167 #[should_panic]
1168 fn uint512_pow_overflow_panics() {
1169 _ = Uint512::MAX.pow(2u32);
1170 }
1171
1172 #[test]
1173 fn uint512_shr_works() {
1174 let original = Uint512::from_be_bytes([
1175 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1176 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1177 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1178 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1179 ]);
1180
1181 let shifted = Uint512::from_be_bytes([
1182 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1183 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1184 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1185 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1186 ]);
1187
1188 assert_eq!(original >> 2u32, shifted);
1189 }
1190
1191 #[test]
1192 #[should_panic]
1193 fn uint512_shr_overflow_panics() {
1194 let _ = Uint512::from(1u32) >> 512u32;
1195 }
1196
1197 #[test]
1198 fn uint512_shl_works() {
1199 let original = Uint512::from_be_bytes([
1200 64u8, 128u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1201 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1202 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1203 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1204 ]);
1205
1206 let shifted = Uint512::from_be_bytes([
1207 2u8, 0u8, 4u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1208 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1209 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1210 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1211 ]);
1212
1213 assert_eq!(original << 2u32, shifted);
1214 }
1215
1216 #[test]
1217 #[should_panic]
1218 fn uint512_shl_overflow_panics() {
1219 let _ = Uint512::from(1u32) << 512u32;
1220 }
1221
1222 #[test]
1223 fn sum_works() {
1224 let nums = vec![
1225 Uint512::from(17u32),
1226 Uint512::from(123u32),
1227 Uint512::from(540u32),
1228 Uint512::from(82u32),
1229 ];
1230 let expected = Uint512::from(762u32);
1231
1232 let sum_as_ref: Uint512 = nums.iter().sum();
1233 assert_eq!(expected, sum_as_ref);
1234
1235 let sum_as_owned: Uint512 = nums.into_iter().sum();
1236 assert_eq!(expected, sum_as_owned);
1237 }
1238
1239 #[test]
1240 fn uint512_methods() {
1241 assert!(matches!(
1243 Uint512::MAX.checked_add(Uint512::from(1u32)),
1244 Err(OverflowError { .. })
1245 ));
1246 assert_eq!(
1247 Uint512::from(1u32).checked_add(Uint512::from(1u32)),
1248 Ok(Uint512::from(2u32)),
1249 );
1250 assert!(matches!(
1251 Uint512::from(0u32).checked_sub(Uint512::from(1u32)),
1252 Err(OverflowError { .. })
1253 ));
1254 assert_eq!(
1255 Uint512::from(2u32).checked_sub(Uint512::from(1u32)),
1256 Ok(Uint512::from(1u32)),
1257 );
1258 assert!(matches!(
1259 Uint512::MAX.checked_mul(Uint512::from(2u32)),
1260 Err(OverflowError { .. })
1261 ));
1262 assert_eq!(
1263 Uint512::from(2u32).checked_mul(Uint512::from(2u32)),
1264 Ok(Uint512::from(4u32)),
1265 );
1266 assert!(matches!(
1267 Uint512::MAX.checked_pow(2u32),
1268 Err(OverflowError { .. })
1269 ));
1270 assert_eq!(
1271 Uint512::from(2u32).checked_pow(3u32),
1272 Ok(Uint512::from(8u32)),
1273 );
1274 assert!(matches!(
1275 Uint512::MAX.checked_div(Uint512::from(0u32)),
1276 Err(DivideByZeroError { .. })
1277 ));
1278 assert_eq!(
1279 Uint512::from(6u32).checked_div(Uint512::from(2u32)),
1280 Ok(Uint512::from(3u32)),
1281 );
1282 assert!(matches!(
1283 Uint512::MAX.checked_div_euclid(Uint512::from(0u32)),
1284 Err(DivideByZeroError { .. })
1285 ));
1286 assert_eq!(
1287 Uint512::from(6u32).checked_div_euclid(Uint512::from(2u32)),
1288 Ok(Uint512::from(3u32)),
1289 );
1290 assert_eq!(
1291 Uint512::from(7u32).checked_div_euclid(Uint512::from(2u32)),
1292 Ok(Uint512::from(3u32)),
1293 );
1294 assert!(matches!(
1295 Uint512::MAX.checked_rem(Uint512::from(0u32)),
1296 Err(DivideByZeroError { .. })
1297 ));
1298
1299 assert_eq!(
1301 Uint512::MAX.saturating_add(Uint512::from(1u32)),
1302 Uint512::MAX
1303 );
1304 assert_eq!(
1305 Uint512::from(0u32).saturating_sub(Uint512::from(1u32)),
1306 Uint512::from(0u32)
1307 );
1308 assert_eq!(
1309 Uint512::MAX.saturating_mul(Uint512::from(2u32)),
1310 Uint512::MAX
1311 );
1312 assert_eq!(
1313 Uint512::from(4u32).saturating_pow(2u32),
1314 Uint512::from(16u32)
1315 );
1316 assert_eq!(Uint512::MAX.saturating_pow(2u32), Uint512::MAX);
1317 }
1318
1319 #[test]
1320 #[allow(clippy::op_ref)]
1321 fn uint512_implements_rem() {
1322 let a = Uint512::from(10u32);
1323 assert_eq!(a % Uint512::from(10u32), Uint512::zero());
1324 assert_eq!(a % Uint512::from(2u32), Uint512::zero());
1325 assert_eq!(a % Uint512::from(1u32), Uint512::zero());
1326 assert_eq!(a % Uint512::from(3u32), Uint512::from(1u32));
1327 assert_eq!(a % Uint512::from(4u32), Uint512::from(2u32));
1328
1329 let a = Uint512::from(10u32);
1331 let b = Uint512::from(3u32);
1332 let expected = Uint512::from(1u32);
1333 assert_eq!(a % b, expected);
1334 assert_eq!(a % &b, expected);
1335 assert_eq!(&a % b, expected);
1336 assert_eq!(&a % &b, expected);
1337 }
1338
1339 #[test]
1340 #[should_panic(expected = "divisor of zero")]
1341 fn uint512_rem_panics_for_zero() {
1342 let _ = Uint512::from(10u32) % Uint512::zero();
1343 }
1344
1345 #[test]
1346 #[allow(clippy::op_ref)]
1347 fn uint512_rem_works() {
1348 assert_eq!(
1349 Uint512::from(12u32) % Uint512::from(10u32),
1350 Uint512::from(2u32)
1351 );
1352 assert_eq!(Uint512::from(50u32) % Uint512::from(5u32), Uint512::zero());
1353
1354 let a = Uint512::from(42u32);
1356 let b = Uint512::from(5u32);
1357 let expected = Uint512::from(2u32);
1358 assert_eq!(a % b, expected);
1359 assert_eq!(a % &b, expected);
1360 assert_eq!(&a % b, expected);
1361 assert_eq!(&a % &b, expected);
1362 }
1363
1364 #[test]
1365 fn uint512_rem_assign_works() {
1366 let mut a = Uint512::from(30u32);
1367 a %= Uint512::from(4u32);
1368 assert_eq!(a, Uint512::from(2u32));
1369
1370 let mut a = Uint512::from(25u32);
1372 let b = Uint512::from(6u32);
1373 a %= &b;
1374 assert_eq!(a, Uint512::from(1u32));
1375 }
1376
1377 #[test]
1378 fn uint512_strict_add_works() {
1379 let a = Uint512::from(5u32);
1380 let b = Uint512::from(3u32);
1381 assert_eq!(a.strict_add(b), Uint512::from(8u32));
1382 assert_eq!(b.strict_add(a), Uint512::from(8u32));
1383 }
1384
1385 #[test]
1386 #[should_panic(expected = "attempt to add with overflow")]
1387 fn uint512_strict_add_panics_on_overflow() {
1388 let a = Uint512::MAX;
1389 let b = Uint512::ONE;
1390 let _ = a.strict_add(b);
1391 }
1392
1393 #[test]
1394 fn uint512_strict_sub_works() {
1395 let a = Uint512::from(5u32);
1396 let b = Uint512::from(3u32);
1397 assert_eq!(a.strict_sub(b), Uint512::from(2u32));
1398 }
1399
1400 #[test]
1401 #[should_panic(expected = "attempt to subtract with overflow")]
1402 fn uint512_strict_sub_panics_on_overflow() {
1403 let a = Uint512::ZERO;
1404 let b = Uint512::ONE;
1405 let _ = a.strict_sub(b);
1406 }
1407
1408 #[test]
1409 fn uint512_abs_diff_works() {
1410 let a = Uint512::from(42u32);
1411 let b = Uint512::from(5u32);
1412 let expected = Uint512::from(37u32);
1413 assert_eq!(a.abs_diff(b), expected);
1414 assert_eq!(b.abs_diff(a), expected);
1415 }
1416
1417 #[test]
1418 fn uint512_partial_eq() {
1419 let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1420 .into_iter()
1421 .map(|(lhs, rhs, expected): (u64, u64, bool)| {
1422 (Uint512::from(lhs), Uint512::from(rhs), expected)
1423 });
1424
1425 #[allow(clippy::op_ref)]
1426 for (lhs, rhs, expected) in test_cases {
1427 assert_eq!(lhs == rhs, expected);
1428 assert_eq!(&lhs == rhs, expected);
1429 assert_eq!(lhs == &rhs, expected);
1430 assert_eq!(&lhs == &rhs, expected);
1431 }
1432 }
1433}