secret_cosmwasm_std/math/
uint512.rs

1use forward_ref::{forward_ref_binop, forward_ref_op_assign};
2use schemars::JsonSchema;
3use serde::{de, ser, Deserialize, Deserializer, Serialize};
4use std::fmt;
5use std::ops::{
6    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shr, ShrAssign, Sub, SubAssign,
7};
8use std::str::FromStr;
9
10use crate::errors::{
11    ConversionOverflowError, DivideByZeroError, OverflowError, OverflowOperation, StdError,
12};
13use crate::{Uint128, Uint256, Uint64};
14
15/// This module is purely a workaround that lets us ignore lints for all the code
16/// the `construct_uint!` macro generates.
17#[allow(clippy::all)]
18mod uints {
19    uint::construct_uint! {
20        pub struct U512(8);
21    }
22}
23
24/// Used internally - we don't want to leak this type since we might change
25/// the implementation in the future.
26use uints::U512;
27
28/// An implementation of u512 that is using strings for JSON encoding/decoding,
29/// such that the full u512 range can be used for clients that convert JSON numbers to floats,
30/// like JavaScript and jq.
31///
32/// # Examples
33///
34/// Use `from` to create instances out of primitive uint types or `new` to provide big
35/// endian bytes:
36///
37/// ```
38/// # use secret_cosmwasm_std::Uint512;
39/// let a = Uint512::from(258u128);
40/// let b = Uint512::new([
41///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
42///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
43///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
44///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
45///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
46///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
47///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
48///     0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8,
49/// ]);
50/// assert_eq!(a, b);
51/// ```
52#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
53pub struct Uint512(#[schemars(with = "String")] U512);
54
55impl Uint512 {
56    pub const MAX: Uint512 = Uint512(U512::MAX);
57    pub const MIN: Uint512 = Uint512(U512::zero());
58
59    /// Creates a Uint512(value) from a big endian representation. It's just an alias for
60    /// `from_big_endian`.
61    pub const fn new(value: [u8; 64]) -> Self {
62        Self::from_be_bytes(value)
63    }
64
65    /// Creates a Uint512(0)
66    #[inline]
67    pub const fn zero() -> Self {
68        Uint512(U512::zero())
69    }
70
71    /// Creates a Uint512(1)
72    #[inline]
73    pub const fn one() -> Self {
74        Self::from_be_bytes([
75            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,
76            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,
77            0, 0, 0, 0, 0, 1,
78        ])
79    }
80
81    pub const fn from_be_bytes(data: [u8; 64]) -> Self {
82        let words: [u64; 8] = [
83            u64::from_le_bytes([
84                data[63], data[62], data[61], data[60], data[59], data[58], data[57], data[56],
85            ]),
86            u64::from_le_bytes([
87                data[55], data[54], data[53], data[52], data[51], data[50], data[49], data[48],
88            ]),
89            u64::from_le_bytes([
90                data[47], data[46], data[45], data[44], data[43], data[42], data[41], data[40],
91            ]),
92            u64::from_le_bytes([
93                data[39], data[38], data[37], data[36], data[35], data[34], data[33], data[32],
94            ]),
95            u64::from_le_bytes([
96                data[31], data[30], data[29], data[28], data[27], data[26], data[25], data[24],
97            ]),
98            u64::from_le_bytes([
99                data[23], data[22], data[21], data[20], data[19], data[18], data[17], data[16],
100            ]),
101            u64::from_le_bytes([
102                data[15], data[14], data[13], data[12], data[11], data[10], data[9], data[8],
103            ]),
104            u64::from_le_bytes([
105                data[7], data[6], data[5], data[4], data[3], data[2], data[1], data[0],
106            ]),
107        ];
108        Self(U512(words))
109    }
110
111    pub const fn from_le_bytes(data: [u8; 64]) -> Self {
112        let words: [u64; 8] = [
113            u64::from_le_bytes([
114                data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
115            ]),
116            u64::from_le_bytes([
117                data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15],
118            ]),
119            u64::from_le_bytes([
120                data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23],
121            ]),
122            u64::from_le_bytes([
123                data[24], data[25], data[26], data[27], data[28], data[29], data[30], data[31],
124            ]),
125            u64::from_le_bytes([
126                data[32], data[33], data[34], data[35], data[36], data[37], data[38], data[39],
127            ]),
128            u64::from_le_bytes([
129                data[40], data[41], data[42], data[43], data[44], data[45], data[46], data[47],
130            ]),
131            u64::from_le_bytes([
132                data[48], data[49], data[50], data[51], data[52], data[53], data[54], data[55],
133            ]),
134            u64::from_le_bytes([
135                data[56], data[57], data[58], data[59], data[60], data[61], data[62], data[63],
136            ]),
137        ];
138        Self(U512(words))
139    }
140
141    /// A conversion from `Uint256` that, unlike the one provided by the `From` trait,
142    /// can be used in a `const` context.
143    pub const fn from_uint256(num: Uint256) -> Self {
144        let bytes = num.to_le_bytes();
145        Self::from_le_bytes([
146            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
147            bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
148            bytes[16], bytes[17], bytes[18], bytes[19], bytes[20], bytes[21], bytes[22], bytes[23],
149            bytes[24], bytes[25], bytes[26], bytes[27], bytes[28], bytes[29], bytes[30], bytes[31],
150            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,
151            0, 0, 0,
152        ])
153    }
154
155    /// Returns a copy of the number as big endian bytes.
156    pub const fn to_be_bytes(self) -> [u8; 64] {
157        let words = [
158            (self.0).0[7].to_be_bytes(),
159            (self.0).0[6].to_be_bytes(),
160            (self.0).0[5].to_be_bytes(),
161            (self.0).0[4].to_be_bytes(),
162            (self.0).0[3].to_be_bytes(),
163            (self.0).0[2].to_be_bytes(),
164            (self.0).0[1].to_be_bytes(),
165            (self.0).0[0].to_be_bytes(),
166        ];
167        unsafe { std::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
168    }
169
170    /// Returns a copy of the number as little endian bytes.
171    pub const fn to_le_bytes(self) -> [u8; 64] {
172        let words = [
173            (self.0).0[0].to_le_bytes(),
174            (self.0).0[1].to_le_bytes(),
175            (self.0).0[2].to_le_bytes(),
176            (self.0).0[3].to_le_bytes(),
177            (self.0).0[4].to_le_bytes(),
178            (self.0).0[5].to_le_bytes(),
179            (self.0).0[6].to_le_bytes(),
180            (self.0).0[7].to_le_bytes(),
181        ];
182        unsafe { std::mem::transmute::<[[u8; 8]; 8], [u8; 64]>(words) }
183    }
184
185    pub const fn is_zero(&self) -> bool {
186        let words = (self.0).0;
187        words[0] == 0
188            && words[1] == 0
189            && words[2] == 0
190            && words[3] == 0
191            && words[4] == 0
192            && words[5] == 0
193            && words[6] == 0
194            && words[7] == 0
195    }
196
197    pub fn pow(self, exp: u32) -> Self {
198        let res = self.0.pow(exp.into());
199        Self(res)
200    }
201
202    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
203        self.0
204            .checked_add(other.0)
205            .map(Self)
206            .ok_or_else(|| OverflowError::new(OverflowOperation::Add, self, other))
207    }
208
209    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
210        self.0
211            .checked_sub(other.0)
212            .map(Self)
213            .ok_or_else(|| OverflowError::new(OverflowOperation::Sub, self, other))
214    }
215
216    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
217        self.0
218            .checked_mul(other.0)
219            .map(Self)
220            .ok_or_else(|| OverflowError::new(OverflowOperation::Mul, self, other))
221    }
222
223    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
224        self.0
225            .checked_pow(exp.into())
226            .map(Self)
227            .ok_or_else(|| OverflowError::new(OverflowOperation::Pow, self, exp))
228    }
229
230    pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
231        self.0
232            .checked_div(other.0)
233            .map(Self)
234            .ok_or_else(|| DivideByZeroError::new(self))
235    }
236
237    pub fn checked_div_euclid(self, other: Self) -> Result<Self, DivideByZeroError> {
238        self.checked_div(other)
239    }
240
241    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
242        self.0
243            .checked_rem(other.0)
244            .map(Self)
245            .ok_or_else(|| DivideByZeroError::new(self))
246    }
247
248    pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
249        if other >= 512 {
250            return Err(OverflowError::new(OverflowOperation::Shr, self, other));
251        }
252
253        Ok(Self(self.0.shr(other)))
254    }
255
256    #[inline]
257    pub fn wrapping_add(self, other: Self) -> Self {
258        let (value, _did_overflow) = self.0.overflowing_add(other.0);
259        Self(value)
260    }
261
262    #[inline]
263    pub fn wrapping_sub(self, other: Self) -> Self {
264        let (value, _did_overflow) = self.0.overflowing_sub(other.0);
265        Self(value)
266    }
267
268    #[inline]
269    pub fn wrapping_mul(self, other: Self) -> Self {
270        let (value, _did_overflow) = self.0.overflowing_mul(other.0);
271        Self(value)
272    }
273
274    #[inline]
275    pub fn wrapping_pow(self, other: u32) -> Self {
276        let (value, _did_overflow) = self.0.overflowing_pow(other.into());
277        Self(value)
278    }
279
280    pub fn saturating_add(self, other: Self) -> Self {
281        Self(self.0.saturating_add(other.0))
282    }
283
284    pub fn saturating_sub(self, other: Self) -> Self {
285        Self(self.0.saturating_sub(other.0))
286    }
287
288    pub fn saturating_mul(self, other: Self) -> Self {
289        Self(self.0.saturating_mul(other.0))
290    }
291
292    pub fn saturating_pow(self, exp: u32) -> Self {
293        match self.checked_pow(exp) {
294            Ok(value) => value,
295            Err(_) => Self::MAX,
296        }
297    }
298
299    pub fn abs_diff(self, other: Self) -> Self {
300        if self < other {
301            other - self
302        } else {
303            self - other
304        }
305    }
306}
307
308impl From<Uint256> for Uint512 {
309    fn from(val: Uint256) -> Self {
310        let bytes = [[0u8; 32], val.to_be_bytes()].concat();
311
312        Self::from_be_bytes(bytes.try_into().unwrap())
313    }
314}
315
316impl From<Uint128> for Uint512 {
317    fn from(val: Uint128) -> Self {
318        val.u128().into()
319    }
320}
321
322impl From<Uint64> for Uint512 {
323    fn from(val: Uint64) -> Self {
324        val.u64().into()
325    }
326}
327
328impl From<u128> for Uint512 {
329    fn from(val: u128) -> Self {
330        Uint512(val.into())
331    }
332}
333
334impl From<u64> for Uint512 {
335    fn from(val: u64) -> Self {
336        Uint512(val.into())
337    }
338}
339
340impl From<u32> for Uint512 {
341    fn from(val: u32) -> Self {
342        Uint512(val.into())
343    }
344}
345
346impl From<u16> for Uint512 {
347    fn from(val: u16) -> Self {
348        Uint512(val.into())
349    }
350}
351
352impl From<u8> for Uint512 {
353    fn from(val: u8) -> Self {
354        Uint512(val.into())
355    }
356}
357
358impl TryFrom<Uint512> for Uint256 {
359    type Error = ConversionOverflowError;
360
361    fn try_from(value: Uint512) -> Result<Self, Self::Error> {
362        let bytes = value.to_be_bytes();
363        let (first_bytes, last_bytes) = bytes.split_at(32);
364
365        if first_bytes != [0u8; 32] {
366            return Err(ConversionOverflowError::new(
367                "Uint512",
368                "Uint256",
369                value.to_string(),
370            ));
371        }
372
373        Ok(Self::from_be_bytes(last_bytes.try_into().unwrap()))
374    }
375}
376
377impl TryFrom<Uint512> for Uint128 {
378    type Error = ConversionOverflowError;
379
380    fn try_from(value: Uint512) -> Result<Self, Self::Error> {
381        Ok(Uint128::new(value.0.try_into().map_err(|_| {
382            ConversionOverflowError::new("Uint512", "Uint128", value.to_string())
383        })?))
384    }
385}
386
387impl TryFrom<&str> for Uint512 {
388    type Error = StdError;
389
390    fn try_from(val: &str) -> Result<Self, Self::Error> {
391        Self::from_str(val)
392    }
393}
394
395impl FromStr for Uint512 {
396    type Err = StdError;
397
398    fn from_str(s: &str) -> Result<Self, Self::Err> {
399        match U512::from_dec_str(s) {
400            Ok(u) => Ok(Self(u)),
401            Err(e) => Err(StdError::generic_err(format!("Parsing u512: {}", e))),
402        }
403    }
404}
405
406impl From<Uint512> for String {
407    fn from(original: Uint512) -> Self {
408        original.to_string()
409    }
410}
411
412impl fmt::Display for Uint512 {
413    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414        // The inner type doesn't work as expected with padding, so we
415        // work around that.
416        let unpadded = self.0.to_string();
417
418        f.pad_integral(true, "", &unpadded)
419    }
420}
421
422impl Add<Uint512> for Uint512 {
423    type Output = Self;
424
425    fn add(self, rhs: Self) -> Self {
426        Uint512(self.0.checked_add(rhs.0).unwrap())
427    }
428}
429
430impl<'a> Add<&'a Uint512> for Uint512 {
431    type Output = Self;
432
433    fn add(self, rhs: &'a Uint512) -> Self {
434        Uint512(self.0.checked_add(rhs.0).unwrap())
435    }
436}
437
438impl Sub<Uint512> for Uint512 {
439    type Output = Self;
440
441    fn sub(self, rhs: Self) -> Self {
442        Uint512(self.0.checked_sub(rhs.0).unwrap())
443    }
444}
445forward_ref_binop!(impl Sub, sub for Uint512, Uint512);
446
447impl SubAssign<Uint512> for Uint512 {
448    fn sub_assign(&mut self, rhs: Uint512) {
449        self.0 = self.0.checked_sub(rhs.0).unwrap();
450    }
451}
452forward_ref_op_assign!(impl SubAssign, sub_assign for Uint512, Uint512);
453
454impl Div<Uint512> for Uint512 {
455    type Output = Self;
456
457    fn div(self, rhs: Self) -> Self::Output {
458        Self(self.0.checked_div(rhs.0).unwrap())
459    }
460}
461
462impl<'a> Div<&'a Uint512> for Uint512 {
463    type Output = Self;
464
465    fn div(self, rhs: &'a Uint512) -> Self::Output {
466        Self(self.0.checked_div(rhs.0).unwrap())
467    }
468}
469
470impl Rem for Uint512 {
471    type Output = Self;
472
473    /// # Panics
474    ///
475    /// This operation will panic if `rhs` is zero.
476    #[inline]
477    fn rem(self, rhs: Self) -> Self {
478        Self(self.0.rem(rhs.0))
479    }
480}
481forward_ref_binop!(impl Rem, rem for Uint512, Uint512);
482
483impl RemAssign<Uint512> for Uint512 {
484    fn rem_assign(&mut self, rhs: Uint512) {
485        *self = *self % rhs;
486    }
487}
488forward_ref_op_assign!(impl RemAssign, rem_assign for Uint512, Uint512);
489
490impl Mul<Uint512> for Uint512 {
491    type Output = Self;
492
493    fn mul(self, rhs: Self) -> Self::Output {
494        Self(self.0.checked_mul(rhs.0).unwrap())
495    }
496}
497forward_ref_binop!(impl Mul, mul for Uint512, Uint512);
498
499impl MulAssign<Uint512> for Uint512 {
500    fn mul_assign(&mut self, rhs: Self) {
501        self.0 = self.0.checked_mul(rhs.0).unwrap();
502    }
503}
504forward_ref_op_assign!(impl MulAssign, mul_assign for Uint512, Uint512);
505
506impl Shr<u32> for Uint512 {
507    type Output = Self;
508
509    fn shr(self, rhs: u32) -> Self::Output {
510        self.checked_shr(rhs).unwrap_or_else(|_| {
511            panic!(
512                "right shift error: {} is larger or equal than the number of bits in Uint512",
513                rhs,
514            )
515        })
516    }
517}
518
519impl<'a> Shr<&'a u32> for Uint512 {
520    type Output = Self;
521
522    fn shr(self, rhs: &'a u32) -> Self::Output {
523        Shr::<u32>::shr(self, *rhs)
524    }
525}
526
527impl AddAssign<Uint512> for Uint512 {
528    fn add_assign(&mut self, rhs: Uint512) {
529        self.0 = self.0.checked_add(rhs.0).unwrap();
530    }
531}
532
533impl<'a> AddAssign<&'a Uint512> for Uint512 {
534    fn add_assign(&mut self, rhs: &'a Uint512) {
535        self.0 = self.0.checked_add(rhs.0).unwrap();
536    }
537}
538
539impl DivAssign<Uint512> for Uint512 {
540    fn div_assign(&mut self, rhs: Self) {
541        self.0 = self.0.checked_div(rhs.0).unwrap();
542    }
543}
544
545impl<'a> DivAssign<&'a Uint512> for Uint512 {
546    fn div_assign(&mut self, rhs: &'a Uint512) {
547        self.0 = self.0.checked_div(rhs.0).unwrap();
548    }
549}
550
551impl ShrAssign<u32> for Uint512 {
552    fn shr_assign(&mut self, rhs: u32) {
553        *self = Shr::<u32>::shr(*self, rhs);
554    }
555}
556
557impl<'a> ShrAssign<&'a u32> for Uint512 {
558    fn shr_assign(&mut self, rhs: &'a u32) {
559        *self = Shr::<u32>::shr(*self, *rhs);
560    }
561}
562
563impl Serialize for Uint512 {
564    /// Serializes as an integer string using base 10
565    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
566    where
567        S: ser::Serializer,
568    {
569        serializer.serialize_str(&self.to_string())
570    }
571}
572
573impl<'de> Deserialize<'de> for Uint512 {
574    /// Deserialized from an integer string using base 10
575    fn deserialize<D>(deserializer: D) -> Result<Uint512, D::Error>
576    where
577        D: Deserializer<'de>,
578    {
579        deserializer.deserialize_str(Uint512Visitor)
580    }
581}
582
583struct Uint512Visitor;
584
585impl<'de> de::Visitor<'de> for Uint512Visitor {
586    type Value = Uint512;
587
588    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
589        formatter.write_str("string-encoded integer")
590    }
591
592    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
593    where
594        E: de::Error,
595    {
596        Uint512::try_from(v).map_err(|e| E::custom(format!("invalid Uint512 '{}' - {}", v, e)))
597    }
598}
599
600impl<A> std::iter::Sum<A> for Uint512
601where
602    Self: Add<A, Output = Self>,
603{
604    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
605        iter.fold(Self::zero(), Add::add)
606    }
607}
608
609impl PartialEq<&Uint512> for Uint512 {
610    fn eq(&self, rhs: &&Uint512) -> bool {
611        self == *rhs
612    }
613}
614
615impl PartialEq<Uint512> for &Uint512 {
616    fn eq(&self, rhs: &Uint512) -> bool {
617        *self == rhs
618    }
619}
620
621#[cfg(test)]
622mod tests {
623    use super::*;
624    use crate::{from_slice, to_vec};
625
626    #[test]
627    fn uint512_new_works() {
628        let num = Uint512::new([1; 64]);
629        let a: [u8; 64] = num.to_be_bytes();
630        assert_eq!(a, [1; 64]);
631
632        let be_bytes = [
633            0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
634            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
635            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
636            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
637        ];
638        let num = Uint512::new(be_bytes);
639        let resulting_bytes: [u8; 64] = num.to_be_bytes();
640        assert_eq!(be_bytes, resulting_bytes);
641    }
642
643    #[test]
644    fn uint512_zero_works() {
645        let zero = Uint512::zero();
646        assert_eq!(
647            zero.to_be_bytes(),
648            [
649                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,
650                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,
651                0, 0, 0, 0, 0, 0, 0, 0
652            ]
653        );
654    }
655
656    #[test]
657    fn uin512_one_works() {
658        let one = Uint512::one();
659        assert_eq!(
660            one.to_be_bytes(),
661            [
662                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,
663                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,
664                0, 0, 0, 0, 0, 0, 0, 1
665            ]
666        );
667    }
668
669    #[test]
670    fn uint512_endianness() {
671        let be_bytes = [
672            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
673            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
674            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
675            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
676        ];
677        let le_bytes = [
678            3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
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,
682        ];
683
684        // These should all be the same.
685        let num1 = Uint512::new(be_bytes);
686        let num2 = Uint512::from_be_bytes(be_bytes);
687        let num3 = Uint512::from_le_bytes(le_bytes);
688        assert_eq!(num1, Uint512::from(65536u32 + 512 + 3));
689        assert_eq!(num1, num2);
690        assert_eq!(num1, num3);
691    }
692
693    #[test]
694    fn uint512_convert_from() {
695        let a = Uint512::from(5u128);
696        assert_eq!(a.0, U512::from(5));
697
698        let a = Uint512::from(5u64);
699        assert_eq!(a.0, U512::from(5));
700
701        let a = Uint512::from(5u32);
702        assert_eq!(a.0, U512::from(5));
703
704        let a = Uint512::from(5u16);
705        assert_eq!(a.0, U512::from(5));
706
707        let a = Uint512::from(5u8);
708        assert_eq!(a.0, U512::from(5));
709
710        let result = Uint512::try_from("34567");
711        assert_eq!(result.unwrap().0, U512::from_dec_str("34567").unwrap());
712
713        let result = Uint512::try_from("1.23");
714        assert!(result.is_err());
715    }
716
717    #[test]
718    fn uint512_convert_to_uint128() {
719        let source = Uint512::from(42u128);
720        let target = Uint128::try_from(source);
721        assert_eq!(target, Ok(Uint128::new(42u128)));
722
723        let source = Uint512::MAX;
724        let target = Uint128::try_from(source);
725        assert_eq!(
726            target,
727            Err(ConversionOverflowError::new(
728                "Uint512",
729                "Uint128",
730                Uint512::MAX.to_string()
731            ))
732        );
733    }
734
735    #[test]
736    fn uint512_from_uint256() {
737        assert_eq!(
738            Uint512::from_uint256(Uint256::from_str("123").unwrap()),
739            Uint512::from_str("123").unwrap()
740        );
741
742        assert_eq!(
743            Uint512::from_uint256(Uint256::from_str("9785746283745").unwrap()),
744            Uint512::from_str("9785746283745").unwrap()
745        );
746
747        assert_eq!(
748            Uint512::from_uint256(
749                Uint256::from_str(
750                    "97857462837575757832978493758398593853985452378423874623874628736482736487236"
751                )
752                .unwrap()
753            ),
754            Uint512::from_str(
755                "97857462837575757832978493758398593853985452378423874623874628736482736487236"
756            )
757            .unwrap()
758        );
759    }
760
761    #[test]
762    fn uint512_implements_display() {
763        let a = Uint512::from(12345u32);
764        assert_eq!(format!("Embedded: {}", a), "Embedded: 12345");
765        assert_eq!(a.to_string(), "12345");
766
767        let a = Uint512::zero();
768        assert_eq!(format!("Embedded: {}", a), "Embedded: 0");
769        assert_eq!(a.to_string(), "0");
770    }
771
772    #[test]
773    fn uint512_display_padding_works() {
774        let a = Uint512::from(123u64);
775        assert_eq!(format!("Embedded: {:05}", a), "Embedded: 00123");
776    }
777
778    #[test]
779    fn uint512_to_be_bytes_works() {
780        assert_eq!(
781            Uint512::zero().to_be_bytes(),
782            [
783                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,
784                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,
785                0, 0, 0, 0, 0, 0, 0, 0,
786            ]
787        );
788        assert_eq!(
789            Uint512::MAX.to_be_bytes(),
790            [
791                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
792                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
793                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
794                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
795                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
796            ]
797        );
798        assert_eq!(
799            Uint512::from(1u128).to_be_bytes(),
800            [
801                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,
802                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,
803                0, 0, 0, 0, 0, 0, 0, 1
804            ]
805        );
806        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(64, "big")]`
807        assert_eq!(
808            Uint512::from(240282366920938463463374607431768124608u128).to_be_bytes(),
809            [
810                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,
811                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,
812                121, 59, 133, 246, 117, 221, 191, 255, 254, 172, 192
813            ]
814        );
815        assert_eq!(
816            Uint512::from_be_bytes([
817                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
818                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
819                238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
820                252, 96, 230, 187, 38, 29
821            ])
822            .to_be_bytes(),
823            [
824                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
825                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
826                238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
827                252, 96, 230, 187, 38, 29
828            ]
829        );
830    }
831
832    #[test]
833    fn uint512_to_le_bytes_works() {
834        assert_eq!(
835            Uint512::zero().to_le_bytes(),
836            [
837                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,
838                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,
839                0, 0, 0, 0, 0, 0, 0, 0
840            ]
841        );
842        assert_eq!(
843            Uint512::MAX.to_le_bytes(),
844            [
845                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
846                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
847                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
848                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
849                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
850            ]
851        );
852        assert_eq!(
853            Uint512::from(1u128).to_le_bytes(),
854            [
855                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,
856                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,
857                0, 0, 0, 0, 0, 0, 0, 0
858            ]
859        );
860        // Python: `[b for b in (240282366920938463463374607431768124608).to_bytes(64, "little")]`
861        assert_eq!(
862            Uint512::from(240282366920938463463374607431768124608u128).to_le_bytes(),
863            [
864                192, 172, 254, 255, 191, 221, 117, 246, 133, 59, 121, 165, 87, 179, 196, 180, 0, 0,
865                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,
866                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
867            ]
868        );
869        assert_eq!(
870            Uint512::from_be_bytes([
871                17, 4, 23, 32, 87, 67, 123, 200, 58, 91, 0, 38, 33, 21, 67, 78, 87, 76, 65, 54,
872                211, 201, 192, 7, 42, 233, 2, 240, 200, 115, 150, 240, 218, 88, 106, 45, 208, 134,
873                238, 119, 85, 22, 14, 88, 166, 195, 154, 73, 64, 10, 44, 59, 13, 22, 47, 12, 99, 8,
874                252, 96, 230, 187, 38, 29
875            ])
876            .to_le_bytes(),
877            [
878                29, 38, 187, 230, 96, 252, 8, 99, 12, 47, 22, 13, 59, 44, 10, 64, 73, 154, 195,
879                166, 88, 14, 22, 85, 119, 238, 134, 208, 45, 106, 88, 218, 240, 150, 115, 200, 240,
880                2, 233, 42, 7, 192, 201, 211, 54, 65, 76, 87, 78, 67, 21, 33, 38, 0, 91, 58, 200,
881                123, 67, 87, 32, 23, 4, 17
882            ]
883        );
884    }
885
886    #[test]
887    fn uint512_is_zero_works() {
888        assert!(Uint512::zero().is_zero());
889        assert!(Uint512(U512::from(0)).is_zero());
890
891        assert!(!Uint512::from(1u32).is_zero());
892        assert!(!Uint512::from(123u32).is_zero());
893    }
894
895    #[test]
896    fn uint512_wrapping_methods() {
897        // wrapping_add
898        assert_eq!(
899            Uint512::from(2u32).wrapping_add(Uint512::from(2u32)),
900            Uint512::from(4u32)
901        ); // non-wrapping
902        assert_eq!(
903            Uint512::MAX.wrapping_add(Uint512::from(1u32)),
904            Uint512::from(0u32)
905        ); // wrapping
906
907        // wrapping_sub
908        assert_eq!(
909            Uint512::from(7u32).wrapping_sub(Uint512::from(5u32)),
910            Uint512::from(2u32)
911        ); // non-wrapping
912        assert_eq!(
913            Uint512::from(0u32).wrapping_sub(Uint512::from(1u32)),
914            Uint512::MAX
915        ); // wrapping
916
917        // wrapping_mul
918        assert_eq!(
919            Uint512::from(3u32).wrapping_mul(Uint512::from(2u32)),
920            Uint512::from(6u32)
921        ); // non-wrapping
922        assert_eq!(
923            Uint512::MAX.wrapping_mul(Uint512::from(2u32)),
924            Uint512::MAX - Uint512::one()
925        ); // wrapping
926
927        // wrapping_pow
928        assert_eq!(Uint512::from(2u32).wrapping_pow(3), Uint512::from(8u32)); // non-wrapping
929        assert_eq!(Uint512::MAX.wrapping_pow(2), Uint512::from(1u32)); // wrapping
930    }
931
932    #[test]
933    fn uint512_json() {
934        let orig = Uint512::from(1234567890987654321u128);
935        let serialized = to_vec(&orig).unwrap();
936        assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
937        let parsed: Uint512 = from_slice(&serialized).unwrap();
938        assert_eq!(parsed, orig);
939    }
940
941    #[test]
942    fn uint512_compare() {
943        let a = Uint512::from(12345u32);
944        let b = Uint512::from(23456u32);
945
946        assert!(a < b);
947        assert!(b > a);
948        assert_eq!(a, Uint512::from(12345u32));
949    }
950
951    #[test]
952    #[allow(clippy::op_ref)]
953    fn uint512_math() {
954        let a = Uint512::from(12345u32);
955        let b = Uint512::from(23456u32);
956
957        // test + with owned and reference right hand side
958        assert_eq!(a + b, Uint512::from(35801u32));
959        assert_eq!(a + &b, Uint512::from(35801u32));
960
961        // test - with owned and reference right hand side
962        assert_eq!(b - a, Uint512::from(11111u32));
963        assert_eq!(b - &a, Uint512::from(11111u32));
964
965        // test += with owned and reference right hand side
966        let mut c = Uint512::from(300000u32);
967        c += b;
968        assert_eq!(c, Uint512::from(323456u32));
969        let mut d = Uint512::from(300000u32);
970        d += &b;
971        assert_eq!(d, Uint512::from(323456u32));
972
973        // test -= with owned and reference right hand side
974        let mut c = Uint512::from(300000u32);
975        c -= b;
976        assert_eq!(c, Uint512::from(276544u32));
977        let mut d = Uint512::from(300000u32);
978        d -= &b;
979        assert_eq!(d, Uint512::from(276544u32));
980
981        // error result on underflow (- would produce negative result)
982        let underflow_result = a.checked_sub(b);
983        let OverflowError {
984            operand1, operand2, ..
985        } = underflow_result.unwrap_err();
986        assert_eq!((operand1, operand2), (a.to_string(), b.to_string()));
987    }
988
989    #[test]
990    #[should_panic]
991    fn uint512_add_overflow_panics() {
992        let max = Uint512::new([255u8; 64]);
993        let _ = max + Uint512::from(12u32);
994    }
995
996    #[test]
997    #[allow(clippy::op_ref)]
998    fn uint512_sub_works() {
999        assert_eq!(
1000            Uint512::from(2u32) - Uint512::from(1u32),
1001            Uint512::from(1u32)
1002        );
1003        assert_eq!(
1004            Uint512::from(2u32) - Uint512::from(0u32),
1005            Uint512::from(2u32)
1006        );
1007        assert_eq!(
1008            Uint512::from(2u32) - Uint512::from(2u32),
1009            Uint512::from(0u32)
1010        );
1011
1012        // works for refs
1013        let a = Uint512::from(10u32);
1014        let b = Uint512::from(3u32);
1015        let expected = Uint512::from(7u32);
1016        assert_eq!(a - b, expected);
1017        assert_eq!(a - &b, expected);
1018        assert_eq!(&a - b, expected);
1019        assert_eq!(&a - &b, expected);
1020    }
1021
1022    #[test]
1023    #[should_panic]
1024    fn uint512_sub_overflow_panics() {
1025        let _ = Uint512::from(1u32) - Uint512::from(2u32);
1026    }
1027
1028    #[test]
1029    fn uint512_sub_assign_works() {
1030        let mut a = Uint512::from(14u32);
1031        a -= Uint512::from(2u32);
1032        assert_eq!(a, Uint512::from(12u32));
1033
1034        // works for refs
1035        let mut a = Uint512::from(10u32);
1036        let b = Uint512::from(3u32);
1037        let expected = Uint512::from(7u32);
1038        a -= &b;
1039        assert_eq!(a, expected);
1040    }
1041
1042    #[test]
1043    #[allow(clippy::op_ref)]
1044    fn uint512_mul_works() {
1045        assert_eq!(
1046            Uint512::from(2u32) * Uint512::from(3u32),
1047            Uint512::from(6u32)
1048        );
1049        assert_eq!(Uint512::from(2u32) * Uint512::zero(), Uint512::zero());
1050
1051        // works for refs
1052        let a = Uint512::from(11u32);
1053        let b = Uint512::from(3u32);
1054        let expected = Uint512::from(33u32);
1055        assert_eq!(a * b, expected);
1056        assert_eq!(a * &b, expected);
1057        assert_eq!(&a * b, expected);
1058        assert_eq!(&a * &b, expected);
1059    }
1060
1061    #[test]
1062    fn uint512_mul_assign_works() {
1063        let mut a = Uint512::from(14u32);
1064        a *= Uint512::from(2u32);
1065        assert_eq!(a, Uint512::from(28u32));
1066
1067        // works for refs
1068        let mut a = Uint512::from(10u32);
1069        let b = Uint512::from(3u32);
1070        a *= &b;
1071        assert_eq!(a, Uint512::from(30u32));
1072    }
1073
1074    #[test]
1075    fn uint512_pow_works() {
1076        assert_eq!(Uint512::from(2u32).pow(2), Uint512::from(4u32));
1077        assert_eq!(Uint512::from(2u32).pow(10), Uint512::from(1024u32));
1078    }
1079
1080    #[test]
1081    #[should_panic]
1082    fn uint512_pow_overflow_panics() {
1083        Uint512::MAX.pow(2u32);
1084    }
1085
1086    #[test]
1087    fn uint512_shr_works() {
1088        let original = Uint512::new([
1089            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1090            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1091            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1092            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
1093        ]);
1094
1095        let shifted = Uint512::new([
1096            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1097            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1098            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
1099            0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
1100        ]);
1101
1102        assert_eq!(original >> 2u32, shifted);
1103    }
1104
1105    #[test]
1106    #[should_panic]
1107    fn uint512_shr_overflow_panics() {
1108        let _ = Uint512::from(1u32) >> 512u32;
1109    }
1110
1111    #[test]
1112    fn sum_works() {
1113        let nums = vec![
1114            Uint512::from(17u32),
1115            Uint512::from(123u32),
1116            Uint512::from(540u32),
1117            Uint512::from(82u32),
1118        ];
1119        let expected = Uint512::from(762u32);
1120
1121        let sum_as_ref: Uint512 = nums.iter().sum();
1122        assert_eq!(expected, sum_as_ref);
1123
1124        let sum_as_owned: Uint512 = nums.into_iter().sum();
1125        assert_eq!(expected, sum_as_owned);
1126    }
1127
1128    #[test]
1129    fn uint512_methods() {
1130        // checked_*
1131        assert!(matches!(
1132            Uint512::MAX.checked_add(Uint512::from(1u32)),
1133            Err(OverflowError { .. })
1134        ));
1135        assert_eq!(
1136            Uint512::from(1u32).checked_add(Uint512::from(1u32)),
1137            Ok(Uint512::from(2u32)),
1138        );
1139        assert!(matches!(
1140            Uint512::from(0u32).checked_sub(Uint512::from(1u32)),
1141            Err(OverflowError { .. })
1142        ));
1143        assert_eq!(
1144            Uint512::from(2u32).checked_sub(Uint512::from(1u32)),
1145            Ok(Uint512::from(1u32)),
1146        );
1147        assert!(matches!(
1148            Uint512::MAX.checked_mul(Uint512::from(2u32)),
1149            Err(OverflowError { .. })
1150        ));
1151        assert_eq!(
1152            Uint512::from(2u32).checked_mul(Uint512::from(2u32)),
1153            Ok(Uint512::from(4u32)),
1154        );
1155        assert!(matches!(
1156            Uint512::MAX.checked_pow(2u32),
1157            Err(OverflowError { .. })
1158        ));
1159        assert_eq!(
1160            Uint512::from(2u32).checked_pow(3u32),
1161            Ok(Uint512::from(8u32)),
1162        );
1163        assert!(matches!(
1164            Uint512::MAX.checked_div(Uint512::from(0u32)),
1165            Err(DivideByZeroError { .. })
1166        ));
1167        assert_eq!(
1168            Uint512::from(6u32).checked_div(Uint512::from(2u32)),
1169            Ok(Uint512::from(3u32)),
1170        );
1171        assert!(matches!(
1172            Uint512::MAX.checked_div_euclid(Uint512::from(0u32)),
1173            Err(DivideByZeroError { .. })
1174        ));
1175        assert_eq!(
1176            Uint512::from(6u32).checked_div_euclid(Uint512::from(2u32)),
1177            Ok(Uint512::from(3u32)),
1178        );
1179        assert_eq!(
1180            Uint512::from(7u32).checked_div_euclid(Uint512::from(2u32)),
1181            Ok(Uint512::from(3u32)),
1182        );
1183        assert!(matches!(
1184            Uint512::MAX.checked_rem(Uint512::from(0u32)),
1185            Err(DivideByZeroError { .. })
1186        ));
1187
1188        // saturating_*
1189        assert_eq!(
1190            Uint512::MAX.saturating_add(Uint512::from(1u32)),
1191            Uint512::MAX
1192        );
1193        assert_eq!(
1194            Uint512::from(0u32).saturating_sub(Uint512::from(1u32)),
1195            Uint512::from(0u32)
1196        );
1197        assert_eq!(
1198            Uint512::MAX.saturating_mul(Uint512::from(2u32)),
1199            Uint512::MAX
1200        );
1201        assert_eq!(
1202            Uint512::from(4u32).saturating_pow(2u32),
1203            Uint512::from(16u32)
1204        );
1205        assert_eq!(Uint512::MAX.saturating_pow(2u32), Uint512::MAX);
1206    }
1207
1208    #[test]
1209    #[allow(clippy::op_ref)]
1210    fn uint512_implements_rem() {
1211        let a = Uint512::from(10u32);
1212        assert_eq!(a % Uint512::from(10u32), Uint512::zero());
1213        assert_eq!(a % Uint512::from(2u32), Uint512::zero());
1214        assert_eq!(a % Uint512::from(1u32), Uint512::zero());
1215        assert_eq!(a % Uint512::from(3u32), Uint512::from(1u32));
1216        assert_eq!(a % Uint512::from(4u32), Uint512::from(2u32));
1217
1218        // works for refs
1219        let a = Uint512::from(10u32);
1220        let b = Uint512::from(3u32);
1221        let expected = Uint512::from(1u32);
1222        assert_eq!(a % b, expected);
1223        assert_eq!(a % &b, expected);
1224        assert_eq!(&a % b, expected);
1225        assert_eq!(&a % &b, expected);
1226    }
1227
1228    #[test]
1229    #[should_panic(expected = "division by zero")]
1230    fn uint512_rem_panics_for_zero() {
1231        let _ = Uint512::from(10u32) % Uint512::zero();
1232    }
1233
1234    #[test]
1235    #[allow(clippy::op_ref)]
1236    fn uint512_rem_works() {
1237        assert_eq!(
1238            Uint512::from(12u32) % Uint512::from(10u32),
1239            Uint512::from(2u32)
1240        );
1241        assert_eq!(Uint512::from(50u32) % Uint512::from(5u32), Uint512::zero());
1242
1243        // works for refs
1244        let a = Uint512::from(42u32);
1245        let b = Uint512::from(5u32);
1246        let expected = Uint512::from(2u32);
1247        assert_eq!(a % b, expected);
1248        assert_eq!(a % &b, expected);
1249        assert_eq!(&a % b, expected);
1250        assert_eq!(&a % &b, expected);
1251    }
1252
1253    #[test]
1254    fn uint512_rem_assign_works() {
1255        let mut a = Uint512::from(30u32);
1256        a %= Uint512::from(4u32);
1257        assert_eq!(a, Uint512::from(2u32));
1258
1259        // works for refs
1260        let mut a = Uint512::from(25u32);
1261        let b = Uint512::from(6u32);
1262        a %= &b;
1263        assert_eq!(a, Uint512::from(1u32));
1264    }
1265
1266    #[test]
1267    fn uint512_abs_diff_works() {
1268        let a = Uint512::from(42u32);
1269        let b = Uint512::from(5u32);
1270        let expected = Uint512::from(37u32);
1271        assert_eq!(a.abs_diff(b), expected);
1272        assert_eq!(b.abs_diff(a), expected);
1273    }
1274
1275    #[test]
1276    fn uint512_partial_eq() {
1277        let test_cases = [(1, 1, true), (42, 42, true), (42, 24, false), (0, 0, true)]
1278            .into_iter()
1279            .map(|(lhs, rhs, expected): (u64, u64, bool)| {
1280                (Uint512::from(lhs), Uint512::from(rhs), expected)
1281            });
1282
1283        #[allow(clippy::op_ref)]
1284        for (lhs, rhs, expected) in test_cases {
1285            assert_eq!(lhs == rhs, expected);
1286            assert_eq!(&lhs == rhs, expected);
1287            assert_eq!(lhs == &rhs, expected);
1288            assert_eq!(&lhs == &rhs, expected);
1289        }
1290    }
1291}