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