tycho_types/num/
varuint248.rs

1use std::mem::MaybeUninit;
2use std::str::FromStr;
3
4use crate::cell::{CellBuilder, CellContext, CellSlice, ExactSize, Load, Size, Store};
5use crate::error::Error;
6use crate::util::unlikely;
7
8/// Variable-length 248-bit integer.
9///
10/// Stored as 5 bits of `len` (`0..=31`), followed by `len` bytes.
11#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
12#[repr(transparent)]
13pub struct VarUint248([u128; 2]);
14
15impl VarUint248 {
16    /// The additive identity for this integer type, i.e. `0`.
17    pub const ZERO: Self = Self([0, 0]);
18
19    /// The multiplicative identity for this integer type, i.e. `1`.
20    pub const ONE: Self = Self([1, 0]);
21
22    /// The smallest value that can be represented by this integer type.
23    pub const MIN: Self = Self::new(1);
24
25    /// The largest value that can be represented by this integer type.
26    pub const MAX: Self = Self::from_words(u128::MAX >> 8, u128::MAX);
27
28    /// The number of data bits that the length occupies.
29    pub const LEN_BITS: u16 = 5;
30
31    /// The maximum number of data bits that this struct occupies.
32    pub const MAX_BITS: u16 = Self::LEN_BITS + 31 * 8;
33
34    /// Creates a new integer value from a primitive integer.
35    #[inline]
36    pub const fn new(value: u128) -> Self {
37        Self::from_words(0, value)
38    }
39
40    /// Constructs self from a pair of high and low underlying integers.
41    #[inline]
42    pub const fn from_words(hi: u128, lo: u128) -> Self {
43        #[cfg(target_endian = "little")]
44        {
45            Self([lo, hi])
46        }
47        #[cfg(target_endian = "big")]
48        {
49            Self([hi, lo])
50        }
51    }
52
53    /// Returns a tuple of high and low underlying integers.
54    #[inline]
55    pub const fn into_words(self) -> (u128, u128) {
56        #[cfg(target_endian = "little")]
57        {
58            (self.0[1], self.0[0])
59        }
60        #[cfg(target_endian = "big")]
61        {
62            (self.0[0], self.0[1])
63        }
64    }
65
66    /// Converts a string slice in a given base to an integer.
67    pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, std::num::ParseIntError> {
68        from_str_radix(src, radix, None)
69    }
70
71    /// Returns `true` if an underlying primitive integer is zero.
72    #[inline]
73    pub const fn is_zero(&self) -> bool {
74        self.0[0] == 0 && self.0[1] == 0
75    }
76
77    /// Returns `true` if an underlying primitive integer fits into the repr.
78    #[inline]
79    pub const fn is_valid(&self) -> bool {
80        *self.high() <= (u128::MAX >> 8)
81    }
82
83    /// Returns number of data bits that this struct occupies.
84    /// Returns `None` if an underlying primitive integer is too large.
85    pub const fn bit_len(&self) -> Option<u16> {
86        let bytes = (32 - self.leading_zeros() / 8) as u8;
87        if unlikely(bytes > 31) {
88            None
89        } else {
90            Some(Self::LEN_BITS + bytes as u16 * 8)
91        }
92    }
93
94    /// Returns the number of leading zeros in the binary representation of self.
95    pub const fn leading_zeros(&self) -> u32 {
96        let (hi, lo) = self.into_words();
97        if hi == 0 {
98            128 + lo.leading_zeros()
99        } else {
100            hi.leading_zeros()
101        }
102    }
103
104    /// Saturating integer addition. Computes `self + rhs`,
105    /// saturating at the numeric bounds instead of overflowing.
106    #[must_use]
107    pub const fn saturating_add(self, rhs: &Self) -> Self {
108        match self.checked_add(rhs) {
109            Some(value) => value,
110            None => Self::MAX,
111        }
112    }
113
114    /// Saturating integer addition. Computes `self - rhs`,
115    /// saturating at the numeric bounds instead of overflowing.
116    #[must_use]
117    pub const fn saturating_sub(self, rhs: &Self) -> Self {
118        let (lo, carry_lo) = self.low().overflowing_sub(*rhs.low());
119        let (hi, carry_c) = self.high().overflowing_sub(carry_lo as _);
120        let (hi, carry_hi) = hi.overflowing_sub(*rhs.high());
121
122        if carry_c || carry_hi {
123            return Self::ZERO;
124        }
125
126        let res = Self::from_words(hi, lo);
127        if res.is_valid() { res } else { Self::MAX }
128    }
129
130    /// Saturating integer multiplication. Computes `self * rhs`,
131    /// returning `None` if overflow occurred.
132    #[must_use]
133    pub fn saturating_mul(self, rhs: &Self) -> Self {
134        match self.checked_mul(rhs) {
135            Some(value) => value,
136            None => Self::MAX,
137        }
138    }
139
140    /// Checked integer addition. Computes `self + rhs`,
141    /// returning `None` if overflow occurred.
142    #[must_use]
143    pub const fn checked_add(&self, rhs: &Self) -> Option<Self> {
144        let (lo, carry_lo) = self.low().overflowing_add(*rhs.low());
145        let (hi, carry_c) = self.high().overflowing_add(carry_lo as _);
146        let (hi, carry_hi) = hi.overflowing_add(*rhs.high());
147
148        if carry_c || carry_hi {
149            return None;
150        }
151
152        let res = Self::from_words(hi, lo);
153        if res.is_valid() { Some(res) } else { None }
154    }
155
156    /// Checked integer subtraction. Computes `self - rhs`,
157    /// returning `None` if overflow occurred.
158    #[must_use]
159    pub const fn checked_sub(&self, rhs: &Self) -> Option<Self> {
160        let (lo, carry_lo) = self.low().overflowing_sub(*rhs.low());
161        let (hi, carry_c) = self.high().overflowing_sub(carry_lo as _);
162        let (hi, carry_hi) = hi.overflowing_sub(*rhs.high());
163
164        if carry_c || carry_hi {
165            return None;
166        }
167
168        let res = Self::from_words(hi, lo);
169        if res.is_valid() { Some(res) } else { None }
170    }
171
172    /// Checked integer multiplication. Computes `self * rhs`,
173    /// returning `None` if overflow occurred.
174    #[must_use]
175    pub fn checked_mul(&self, rhs: &Self) -> Option<Self> {
176        let mut res = umulddi3(self.low(), rhs.low());
177
178        let (hi_lo, overflow_hi_lo) = self.high().overflowing_mul(*rhs.low());
179        let (lo_hi, overflow_lo_hi) = self.low().overflowing_mul(*rhs.high());
180        let (hi, overflow_hi) = hi_lo.overflowing_add(lo_hi);
181        let (high, overflow_high) = res.high().overflowing_add(hi);
182        *res.high_mut() = high;
183
184        let overflow_hi_hi = (*self.high() != 0) & (*rhs.high() != 0);
185
186        if overflow_hi_lo
187            || overflow_lo_hi
188            || overflow_hi
189            || overflow_high
190            || overflow_hi_hi
191            || !self.is_valid()
192        {
193            None
194        } else {
195            Some(res)
196        }
197    }
198
199    /// The lower part of the integer.
200    pub const fn low(&self) -> &u128 {
201        &self.0[0]
202    }
203
204    /// The higher part of the integer.
205    pub const fn high(&self) -> &u128 {
206        &self.0[1]
207    }
208
209    /// A mutable reference to the lower part of the integer.
210    pub fn low_mut(&mut self) -> &mut u128 {
211        &mut self.0[0]
212    }
213
214    /// A mutable reference to the higher part of the integer.
215    pub fn high_mut(&mut self) -> &mut u128 {
216        &mut self.0[1]
217    }
218
219    /// Cast to a primitive `isize`.
220    #[inline]
221    pub const fn as_isize(self) -> isize {
222        let (_, lo) = self.into_words();
223        lo as _
224    }
225
226    /// Cast to a primitive `usize`.
227    #[inline]
228    pub const fn as_usize(self) -> usize {
229        let (_, lo) = self.into_words();
230        lo as _
231    }
232}
233
234macro_rules! impl_from {
235    ($($ty:ty),*$(,)?) => {
236        $(impl From<$ty> for VarUint248 {
237            #[inline]
238            fn from(value: $ty) -> Self {
239                Self::new(value as _)
240            }
241        })*
242    };
243}
244
245impl_from! { u8, u16, u32, u64, u128, usize }
246
247#[cfg(feature = "bigint")]
248impl From<VarUint248> for num_bigint::BigInt {
249    #[inline]
250    fn from(value: VarUint248) -> Self {
251        num_bigint::BigUint::from(value).into()
252    }
253}
254
255#[cfg(feature = "bigint")]
256impl From<VarUint248> for num_bigint::BigUint {
257    fn from(value: VarUint248) -> Self {
258        let (high, low) = value.into_words();
259        if high == 0 {
260            return Self::from(low);
261        }
262
263        let mut res = Self::from(high);
264        res <<= 128;
265        res += low;
266        res
267    }
268}
269
270impl ExactSize for VarUint248 {
271    #[inline]
272    fn exact_size(&self) -> Size {
273        Size {
274            bits: self.bit_len().unwrap_or_default(),
275            refs: 0,
276        }
277    }
278}
279
280impl PartialEq<u128> for VarUint248 {
281    fn eq(&self, other: &u128) -> bool {
282        self.into_words() == (0, *other)
283    }
284}
285
286impl Ord for VarUint248 {
287    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
288        self.into_words().cmp(&other.into_words())
289    }
290}
291
292impl PartialOrd for VarUint248 {
293    #[inline]
294    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
295        Some(self.cmp(other))
296    }
297}
298
299impl PartialOrd<u128> for VarUint248 {
300    #[inline]
301    fn partial_cmp(&self, other: &u128) -> Option<std::cmp::Ordering> {
302        Some(self.into_words().cmp(&(0, *other)))
303    }
304}
305
306impl Store for VarUint248 {
307    fn store_into(&self, builder: &mut CellBuilder, _: &dyn CellContext) -> Result<(), Error> {
308        let bytes = (32 - self.leading_zeros() / 8) as u8;
309        let mut bits = bytes as u16 * 8;
310
311        if unlikely(bytes > 31 || !builder.has_capacity(Self::LEN_BITS + bits, 0)) {
312            return Err(Error::CellOverflow);
313        }
314
315        ok!(builder.store_small_uint(bytes, Self::LEN_BITS));
316
317        let (hi, lo) = self.into_words();
318        if let Some(high_bits) = bits.checked_sub(128) {
319            ok!(super::store_u128(builder, hi, high_bits));
320            bits -= high_bits;
321        }
322        super::store_u128(builder, lo, bits)
323    }
324}
325
326impl<'a> Load<'a> for VarUint248 {
327    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
328        let mut bytes = ok!(slice.load_small_uint(Self::LEN_BITS));
329
330        let mut hi: u128 = 0;
331        if let Some(high_bytes) = bytes.checked_sub(16)
332            && high_bytes > 0
333        {
334            hi = ok!(super::load_u128(slice, high_bytes));
335            bytes -= high_bytes;
336        }
337
338        match super::load_u128(slice, bytes) {
339            Ok(lo) => Ok(Self::from_words(hi, lo)),
340            Err(e) => Err(e),
341        }
342    }
343}
344
345#[cfg(feature = "serde")]
346impl serde::Serialize for VarUint248 {
347    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
348    where
349        S: serde::Serializer,
350    {
351        if serializer.is_human_readable() {
352            serializer.collect_str(self)
353        } else {
354            self.0.serialize(serializer)
355        }
356    }
357}
358
359#[cfg(feature = "serde")]
360impl<'de> serde::Deserialize<'de> for VarUint248 {
361    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
362    where
363        D: serde::Deserializer<'de>,
364    {
365        use serde::de::{Error, Unexpected, Visitor};
366
367        struct VarUint248Visitor;
368
369        impl Visitor<'_> for VarUint248Visitor {
370            type Value = VarUint248;
371
372            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
373                f.write_str("a formatted 248-bit integer")
374            }
375
376            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
377            where
378                E: Error,
379            {
380                from_str_radix(v, 10, None).map_err(Error::custom)
381            }
382
383            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
384            where
385                E: Error,
386            {
387                let Ok(string) = std::str::from_utf8(v) else {
388                    return Err(Error::invalid_value(Unexpected::Bytes(v), &self));
389                };
390                self.visit_str(string)
391            }
392        }
393
394        if deserializer.is_human_readable() {
395            deserializer.deserialize_str(VarUint248Visitor)
396        } else {
397            <_>::deserialize(deserializer).map(Self)
398        }
399    }
400}
401
402#[cfg(feature = "arbitrary")]
403impl<'a> arbitrary::Arbitrary<'a> for VarUint248 {
404    #[inline]
405    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
406        Ok(Self::from_words(
407            u.int_in_range(0..=(u128::MAX >> 8))?,
408            u.arbitrary()?,
409        ))
410    }
411
412    #[inline]
413    fn size_hint(_: usize) -> (usize, Option<usize>) {
414        (32, Some(32))
415    }
416}
417
418impl std::ops::Add<u128> for VarUint248 {
419    type Output = Self;
420
421    #[inline]
422    fn add(mut self, rhs: u128) -> Self::Output {
423        self += Self::new(rhs);
424        self
425    }
426}
427
428impl std::ops::Add for VarUint248 {
429    type Output = Self;
430
431    #[inline]
432    fn add(mut self, rhs: Self) -> Self::Output {
433        self += &rhs;
434        self
435    }
436}
437
438impl std::ops::Add<&Self> for VarUint248 {
439    type Output = Self;
440
441    #[inline]
442    fn add(mut self, rhs: &Self) -> Self::Output {
443        self += rhs;
444        self
445    }
446}
447
448impl std::ops::AddAssign<u128> for VarUint248 {
449    fn add_assign(&mut self, rhs: u128) {
450        std::ops::AddAssign::<&Self>::add_assign(self, &Self::new(rhs))
451    }
452}
453
454impl std::ops::AddAssign for VarUint248 {
455    fn add_assign(&mut self, rhs: Self) {
456        std::ops::AddAssign::<&Self>::add_assign(self, &rhs)
457    }
458}
459
460impl std::ops::AddAssign<&Self> for VarUint248 {
461    fn add_assign(&mut self, rhs: &Self) {
462        let (lo, carry) = self.low().overflowing_add(*rhs.low());
463        *self.low_mut() = lo;
464        *self.high_mut() = rhs
465            .high()
466            .wrapping_add(carry as _)
467            .wrapping_add(*rhs.high());
468    }
469}
470
471impl std::ops::Sub<u128> for VarUint248 {
472    type Output = Self;
473
474    #[inline]
475    fn sub(mut self, rhs: u128) -> Self::Output {
476        self -= &Self::new(rhs);
477        self
478    }
479}
480
481impl std::ops::Sub for VarUint248 {
482    type Output = Self;
483
484    #[inline]
485    fn sub(mut self, rhs: Self) -> Self::Output {
486        self -= &rhs;
487        self
488    }
489}
490
491impl std::ops::Sub<&Self> for VarUint248 {
492    type Output = Self;
493
494    #[inline]
495    fn sub(mut self, rhs: &Self) -> Self::Output {
496        self -= rhs;
497        self
498    }
499}
500
501impl std::ops::SubAssign<u128> for VarUint248 {
502    fn sub_assign(&mut self, rhs: u128) {
503        std::ops::SubAssign::<&Self>::sub_assign(self, &Self::new(rhs))
504    }
505}
506
507impl std::ops::SubAssign for VarUint248 {
508    #[inline]
509    fn sub_assign(&mut self, rhs: Self) {
510        std::ops::SubAssign::<&Self>::sub_assign(self, &rhs)
511    }
512}
513
514impl std::ops::SubAssign<&Self> for VarUint248 {
515    fn sub_assign(&mut self, rhs: &Self) {
516        let (lo, carry) = self.low().overflowing_sub(*rhs.low());
517        *self.low_mut() = lo;
518        *self.high_mut() = self
519            .high()
520            .wrapping_sub(carry as _)
521            .wrapping_sub(*rhs.high());
522    }
523}
524
525impl std::ops::Shr<i32> for VarUint248 {
526    type Output = Self;
527
528    #[inline]
529    fn shr(mut self, rhs: i32) -> Self::Output {
530        self >>= rhs as usize;
531        self
532    }
533}
534
535impl std::ops::Shr<u32> for VarUint248 {
536    type Output = Self;
537
538    #[inline]
539    fn shr(mut self, rhs: u32) -> Self::Output {
540        self >>= rhs as usize;
541        self
542    }
543}
544
545impl std::ops::Shr<usize> for VarUint248 {
546    type Output = Self;
547
548    #[inline]
549    fn shr(mut self, rhs: usize) -> Self::Output {
550        self >>= rhs;
551        self
552    }
553}
554
555impl std::ops::ShrAssign<usize> for VarUint248 {
556    fn shr_assign(&mut self, n: usize) {
557        debug_assert!(n < 256, "shr overflow");
558
559        match n {
560            0 => {}
561            1..=127 => {
562                let hi = *self.high();
563                *self.high_mut() >>= n;
564                *self.low_mut() >>= n;
565                *self.low_mut() |= hi << (128 - n);
566            }
567            _ => {
568                let hi = *self.high();
569                *self.high_mut() = 0;
570                *self.low_mut() = hi >> (n & 127);
571            }
572        }
573    }
574}
575
576impl std::ops::Shl<i32> for VarUint248 {
577    type Output = Self;
578
579    #[inline]
580    fn shl(mut self, rhs: i32) -> Self::Output {
581        self <<= rhs as usize;
582        self
583    }
584}
585
586impl std::ops::Shl<u32> for VarUint248 {
587    type Output = Self;
588
589    #[inline]
590    fn shl(mut self, rhs: u32) -> Self::Output {
591        self <<= rhs as usize;
592        self
593    }
594}
595
596impl std::ops::Shl<usize> for VarUint248 {
597    type Output = Self;
598
599    fn shl(mut self, rhs: usize) -> Self::Output {
600        self <<= rhs;
601        self
602    }
603}
604
605impl std::ops::ShlAssign<usize> for VarUint248 {
606    fn shl_assign(&mut self, n: usize) {
607        debug_assert!(n < 256, "shl overflow");
608
609        match n {
610            0 => {}
611            1..=127 => {
612                let lo = *self.low();
613                *self.low_mut() <<= n;
614                *self.high_mut() <<= n;
615                *self.high_mut() |= lo >> (128 - n);
616            }
617            _ => {
618                let lo = *self.low();
619                *self.low_mut() = 0;
620                *self.high_mut() = lo << (n & 127);
621            }
622        }
623    }
624}
625
626impl std::ops::Mul<u128> for VarUint248 {
627    type Output = Self;
628
629    #[inline]
630    fn mul(mut self, rhs: u128) -> Self::Output {
631        self *= rhs;
632        self
633    }
634}
635
636impl std::ops::Mul for VarUint248 {
637    type Output = Self;
638
639    #[inline]
640    fn mul(mut self, rhs: Self) -> Self::Output {
641        self *= rhs;
642        self
643    }
644}
645
646impl std::ops::Mul<&Self> for VarUint248 {
647    type Output = Self;
648
649    #[inline]
650    fn mul(mut self, rhs: &Self) -> Self::Output {
651        self *= rhs;
652        self
653    }
654}
655
656impl std::ops::MulAssign<u128> for VarUint248 {
657    #[inline]
658    fn mul_assign(&mut self, rhs: u128) {
659        std::ops::MulAssign::<&Self>::mul_assign(self, &Self::new(rhs))
660    }
661}
662
663impl std::ops::MulAssign for VarUint248 {
664    #[inline]
665    fn mul_assign(&mut self, rhs: Self) {
666        std::ops::MulAssign::<&Self>::mul_assign(self, &rhs)
667    }
668}
669
670impl std::ops::MulAssign<&Self> for VarUint248 {
671    fn mul_assign(&mut self, rhs: &Self) {
672        // See https://github.com/nlordell/ethnum-rs/blob/main/src/intrinsics/native/mul.rs
673
674        let mut r = umulddi3(self.low(), rhs.low());
675        let a_hi_mul_b_lo = self.high().wrapping_mul(*rhs.low());
676        let a_lo_mul_b_hi = self.low().wrapping_mul(*rhs.high());
677        *r.high_mut() = r
678            .high()
679            .wrapping_add(a_hi_mul_b_lo.wrapping_add(a_lo_mul_b_hi));
680
681        *self = r;
682    }
683}
684
685impl std::ops::Div<u128> for VarUint248 {
686    type Output = Self;
687
688    #[inline]
689    fn div(mut self, rhs: u128) -> Self::Output {
690        self /= VarUint248::new(rhs);
691        self
692    }
693}
694
695impl std::ops::Div for VarUint248 {
696    type Output = Self;
697
698    #[inline]
699    fn div(mut self, rhs: Self) -> Self::Output {
700        self /= rhs;
701        self
702    }
703}
704
705impl std::ops::Div<&Self> for VarUint248 {
706    type Output = Self;
707
708    #[inline]
709    fn div(mut self, rhs: &Self) -> Self::Output {
710        self /= rhs;
711        self
712    }
713}
714
715impl std::ops::DivAssign<u128> for VarUint248 {
716    #[inline]
717    fn div_assign(&mut self, rhs: u128) {
718        std::ops::DivAssign::<&Self>::div_assign(self, &VarUint248::new(rhs))
719    }
720}
721
722impl std::ops::DivAssign for VarUint248 {
723    #[inline]
724    fn div_assign(&mut self, rhs: Self) {
725        std::ops::DivAssign::<&Self>::div_assign(self, &rhs)
726    }
727}
728
729impl std::ops::DivAssign<&Self> for VarUint248 {
730    fn div_assign(&mut self, rhs: &Self) {
731        let (a, b) = (*self, rhs);
732
733        // SAFETY: `udivmod` does not write `MaybeUninit::uninit()` to `res` and
734        // `VarUint248` does not implement `Drop`.
735        let res = unsafe { &mut *(self as *mut Self).cast() };
736        udivmod(res, &a, b, None);
737    }
738}
739
740impl std::ops::Rem<u128> for VarUint248 {
741    type Output = Self;
742
743    #[inline]
744    fn rem(mut self, rhs: u128) -> Self::Output {
745        self %= VarUint248::new(rhs);
746        self
747    }
748}
749
750impl std::ops::Rem for VarUint248 {
751    type Output = Self;
752
753    #[inline]
754    fn rem(mut self, rhs: Self) -> Self::Output {
755        self %= rhs;
756        self
757    }
758}
759
760impl std::ops::Rem<&Self> for VarUint248 {
761    type Output = Self;
762
763    #[inline]
764    fn rem(mut self, rhs: &Self) -> Self::Output {
765        self %= rhs;
766        self
767    }
768}
769
770impl std::ops::RemAssign<u128> for VarUint248 {
771    fn rem_assign(&mut self, rhs: u128) {
772        std::ops::RemAssign::<&Self>::rem_assign(self, &VarUint248::new(rhs))
773    }
774}
775
776impl std::ops::RemAssign for VarUint248 {
777    #[inline]
778    fn rem_assign(&mut self, rhs: Self) {
779        std::ops::RemAssign::<&Self>::rem_assign(self, &rhs)
780    }
781}
782
783impl std::ops::RemAssign<&Self> for VarUint248 {
784    fn rem_assign(&mut self, rhs: &Self) {
785        let mut res = MaybeUninit::uninit();
786        let (a, b) = (*self, rhs);
787
788        // SAFETY: `udivmod` does not write `MaybeUninit::uninit()` to `rem` and
789        // `VarUint248` does not implement `Drop`.
790        let r = unsafe { &mut *(self as *mut Self).cast() };
791        udivmod(&mut res, &a, b, Some(r));
792    }
793}
794
795#[inline]
796pub fn umulddi3(a: &u128, b: &u128) -> VarUint248 {
797    const BITS_IN_DWORD_2: u32 = 64;
798    const LOWER_MASK: u128 = u128::MAX >> BITS_IN_DWORD_2;
799
800    let mut low = (a & LOWER_MASK) * (b & LOWER_MASK);
801    let mut t = low >> BITS_IN_DWORD_2;
802    low &= LOWER_MASK;
803    t += (a >> BITS_IN_DWORD_2) * (b & LOWER_MASK);
804    low += (t & LOWER_MASK) << BITS_IN_DWORD_2;
805    let mut high = t >> BITS_IN_DWORD_2;
806    t = low >> BITS_IN_DWORD_2;
807    low &= LOWER_MASK;
808    t += (b >> BITS_IN_DWORD_2) * (a & LOWER_MASK);
809    low += (t & LOWER_MASK) << BITS_IN_DWORD_2;
810    high += t >> BITS_IN_DWORD_2;
811    high += (a >> BITS_IN_DWORD_2) * (b >> BITS_IN_DWORD_2);
812
813    VarUint248::from_words(high, low)
814}
815
816fn udivmod(
817    res: &mut MaybeUninit<VarUint248>,
818    a: &VarUint248,
819    b: &VarUint248,
820    rem: Option<&mut MaybeUninit<VarUint248>>,
821) {
822    // See https://github.com/nlordell/ethnum-rs/blob/main/src/intrinsics/native/divmod.rs
823
824    if a.high() | b.high() == 0 {
825        if let Some(rem) = rem {
826            rem.write(VarUint248::from_words(0, a.low() % b.low()));
827        }
828        res.write(VarUint248::from_words(0, a.low() / b.low()));
829        return;
830    }
831
832    let dividend = *a;
833    let divisor = *b;
834    let quotient: VarUint248;
835    let mut remainder: VarUint248;
836
837    if divisor > dividend {
838        if let Some(rem) = rem {
839            rem.write(dividend);
840        }
841        res.write(VarUint248::ZERO);
842        return;
843    }
844    // When the divisor fits in 128 bits, we can use an optimized path.
845    if *divisor.high() == 0 {
846        remainder = VarUint248::ZERO;
847        if dividend.high() < divisor.low() {
848            // The result fits in 128 bits.
849            quotient = VarUint248::from_words(
850                0,
851                udiv256_by_128_to_128(
852                    *dividend.high(),
853                    *dividend.low(),
854                    *divisor.low(),
855                    remainder.low_mut(),
856                ),
857            );
858        } else {
859            // First, divide with the high part to get the remainder in dividend.s.high.
860            // After that dividend.s.high < divisor.s.low.
861            quotient = VarUint248::from_words(
862                dividend.high() / divisor.low(),
863                udiv256_by_128_to_128(
864                    dividend.high() % divisor.low(),
865                    *dividend.low(),
866                    *divisor.low(),
867                    remainder.low_mut(),
868                ),
869            );
870        }
871        if let Some(rem) = rem {
872            rem.write(remainder);
873        }
874        res.write(quotient);
875        return;
876    }
877
878    (quotient, remainder) = div_mod_knuth(&dividend, &divisor);
879
880    if let Some(rem) = rem {
881        rem.write(remainder);
882    }
883    res.write(quotient);
884}
885
886#[inline(always)]
887fn udiv256_by_128_to_128(u1: u128, u0: u128, mut v: u128, r: &mut u128) -> u128 {
888    // See https://github.com/nlordell/ethnum-rs/blob/main/src/intrinsics/native/divmod.rs
889
890    const N_UDWORD_BITS: u32 = 128;
891    const B: u128 = 1 << (N_UDWORD_BITS / 2); // Number base (128 bits)
892    let (un1, un0): (u128, u128); // Norm. dividend LSD's
893    let (vn1, vn0): (u128, u128); // Norm. divisor digits
894    let (mut q1, mut q0): (u128, u128); // Quotient digits
895    let (un128, un21, un10): (u128, u128, u128); // Dividend digit pairs
896
897    let s = v.leading_zeros();
898    if s > 0 {
899        // Normalize the divisor.
900        v <<= s;
901        un128 = (u1 << s) | (u0 >> (N_UDWORD_BITS - s));
902        un10 = u0 << s; // Shift dividend left
903    } else {
904        // Avoid undefined behavior of (u0 >> 64).
905        un128 = u1;
906        un10 = u0;
907    }
908
909    // Break divisor up into two 64-bit digits.
910    vn1 = v >> (N_UDWORD_BITS / 2);
911    vn0 = v & 0xFFFF_FFFF_FFFF_FFFF;
912
913    // Break right half of dividend into two digits.
914    un1 = un10 >> (N_UDWORD_BITS / 2);
915    un0 = un10 & 0xFFFF_FFFF_FFFF_FFFF;
916
917    // Compute the first quotient digit, q1.
918    q1 = un128 / vn1;
919    let mut rhat = un128 - q1 * vn1;
920
921    // q1 has at most error 2. No more than 2 iterations.
922    while q1 >= B || q1 * vn0 > B * rhat + un1 {
923        q1 -= 1;
924        rhat += vn1;
925        if rhat >= B {
926            break;
927        }
928    }
929
930    un21 = un128
931        .wrapping_mul(B)
932        .wrapping_add(un1)
933        .wrapping_sub(q1.wrapping_mul(v));
934
935    // Compute the second quotient digit.
936    q0 = un21 / vn1;
937    rhat = un21 - q0 * vn1;
938
939    // q0 has at most error 2. No more than 2 iterations.
940    while q0 >= B || q0 * vn0 > B * rhat + un0 {
941        q0 -= 1;
942        rhat += vn1;
943        if rhat >= B {
944            break;
945        }
946    }
947
948    *r = (un21
949        .wrapping_mul(B)
950        .wrapping_add(un0)
951        .wrapping_sub(q0.wrapping_mul(v)))
952        >> s;
953    q1 * B + q0
954}
955
956#[inline]
957pub fn div_mod_knuth(u: &VarUint248, v: &VarUint248) -> (VarUint248, VarUint248) {
958    // See https://github.com/nlordell/ethnum-rs/blob/main/src/intrinsics/native/divmod.rs
959
960    const N_UDWORD_BITS: u32 = 128;
961
962    #[inline]
963    fn full_shl(a: &VarUint248, shift: u32) -> [u128; 3] {
964        debug_assert!(shift < N_UDWORD_BITS);
965        let mut u = [0_u128; 3];
966        let u_lo = a.low() << shift;
967        let u_hi = *a >> (N_UDWORD_BITS - shift);
968        u[0] = u_lo;
969        u[1] = *u_hi.low();
970        u[2] = *u_hi.high();
971
972        u
973    }
974
975    #[inline]
976    fn full_shr(u: &[u128; 3], shift: u32) -> VarUint248 {
977        debug_assert!(shift < N_UDWORD_BITS);
978        let mut res = VarUint248::ZERO;
979        *res.low_mut() = u[0] >> shift;
980        *res.high_mut() = u[1] >> shift;
981        // carry
982        if shift > 0 {
983            let sh = N_UDWORD_BITS - shift;
984            *res.low_mut() |= u[1] << sh;
985            *res.high_mut() |= u[2] << sh;
986        }
987
988        res
989    }
990
991    // returns (lo, hi)
992    #[inline]
993    const fn split_u128_to_u128(a: u128) -> (u128, u128) {
994        (a & 0xFFFFFFFFFFFFFFFF, a >> (N_UDWORD_BITS / 2))
995    }
996
997    // returns (lo, hi)
998    #[inline]
999    const fn fullmul_u128(a: u128, b: u128) -> (u128, u128) {
1000        let (a0, a1) = split_u128_to_u128(a);
1001        let (b0, b1) = split_u128_to_u128(b);
1002
1003        let mut t = a0 * b0;
1004        let mut k: u128;
1005        let w3: u128;
1006        (w3, k) = split_u128_to_u128(t);
1007
1008        t = a1 * b0 + k;
1009        let (w1, w2) = split_u128_to_u128(t);
1010        t = a0 * b1 + w1;
1011        k = t >> 64;
1012
1013        let w_hi = a1 * b1 + w2 + k;
1014        let w_lo = (t << 64) + w3;
1015
1016        (w_lo, w_hi)
1017    }
1018
1019    #[inline]
1020    fn fullmul_u256_u128(a: &VarUint248, b: u128) -> [u128; 3] {
1021        let mut acc = [0_u128; 3];
1022        let mut lo: u128;
1023        let mut carry: u128;
1024        let c: bool;
1025        if b != 0 {
1026            (lo, carry) = fullmul_u128(*a.low(), b);
1027            acc[0] = lo;
1028            acc[1] = carry;
1029            (lo, carry) = fullmul_u128(*a.high(), b);
1030            (acc[1], c) = acc[1].overflowing_add(lo);
1031            acc[2] = carry + c as u128;
1032        }
1033
1034        acc
1035    }
1036
1037    #[inline]
1038    const fn add_carry(a: u128, b: u128, c: bool) -> (u128, bool) {
1039        let (res1, overflow1) = b.overflowing_add(c as u128);
1040        let (res2, overflow2) = u128::overflowing_add(a, res1);
1041
1042        (res2, overflow1 || overflow2)
1043    }
1044
1045    #[inline]
1046    const fn sub_carry(a: u128, b: u128, c: bool) -> (u128, bool) {
1047        let (res1, overflow1) = b.overflowing_add(c as u128);
1048        let (res2, overflow2) = u128::overflowing_sub(a, res1);
1049
1050        (res2, overflow1 || overflow2)
1051    }
1052
1053    // D1.
1054    // Make sure 128th bit in v's highest word is set.
1055    // If we shift both u and v, it won't affect the quotient
1056    // and the remainder will only need to be shifted back.
1057    let shift = v.high().leading_zeros();
1058    debug_assert!(shift < N_UDWORD_BITS);
1059    let v = *v << shift;
1060    debug_assert!(v.high() >> (N_UDWORD_BITS - 1) == 1);
1061    // u will store the remainder (shifted)
1062    let mut u = full_shl(u, shift);
1063
1064    // quotient
1065    let mut q = VarUint248::ZERO;
1066    let v_n_1 = *v.high();
1067    let v_n_2 = *v.low();
1068
1069    // D2. D7. - unrolled loop j == 0, n == 2, m == 0 (only one possible iteration)
1070    let mut r_hat: u128 = 0;
1071    let u_jn = u[2];
1072
1073    // D3.
1074    // q_hat is our guess for the j-th quotient digit
1075    // q_hat = min(b - 1, (u_{j+n} * b + u_{j+n-1}) / v_{n-1})
1076    // b = 1 << WORD_BITS
1077    // Theorem B: q_hat >= q_j >= q_hat - 2
1078    let mut q_hat = if u_jn < v_n_1 {
1079        // let (mut q_hat, mut r_hat) = _div_mod_u128(u_jn, u[j + n - 1], v_n_1);
1080        let mut q_hat = udiv256_by_128_to_128(u_jn, u[1], v_n_1, &mut r_hat);
1081        let mut overflow: bool;
1082        // this loop takes at most 2 iterations
1083        loop {
1084            let another_iteration = {
1085                // check if q_hat * v_{n-2} > b * r_hat + u_{j+n-2}
1086                let (lo, hi) = fullmul_u128(q_hat, v_n_2);
1087                hi > r_hat || (hi == r_hat && lo > u[0])
1088            };
1089            if !another_iteration {
1090                break;
1091            }
1092            q_hat -= 1;
1093            (r_hat, overflow) = r_hat.overflowing_add(v_n_1);
1094            // if r_hat overflowed, we're done
1095            if overflow {
1096                break;
1097            }
1098        }
1099        q_hat
1100    } else {
1101        // here q_hat >= q_j >= q_hat - 1
1102        u128::MAX
1103    };
1104
1105    // ex. 20:
1106    // since q_hat * v_{n-2} <= b * r_hat + u_{j+n-2},
1107    // either q_hat == q_j, or q_hat == q_j + 1
1108
1109    // D4.
1110    // let's assume optimistically q_hat == q_j
1111    // subtract (q_hat * v) from u[j..]
1112    let q_hat_v = fullmul_u256_u128(&v, q_hat);
1113    // u[j..] -= q_hat_v;
1114    let mut c = false;
1115    (u[0], c) = sub_carry(u[0], q_hat_v[0], c);
1116    (u[1], c) = sub_carry(u[1], q_hat_v[1], c);
1117    (u[2], c) = sub_carry(u[2], q_hat_v[2], c);
1118
1119    // D6.
1120    // actually, q_hat == q_j + 1 and u[j..] has overflowed
1121    // highly unlikely ~ (1 / 2^127)
1122    if c {
1123        q_hat -= 1;
1124        // add v to u[j..]
1125        c = false;
1126        (u[0], c) = add_carry(u[0], *v.low(), c);
1127        (u[1], c) = add_carry(u[1], *v.high(), c);
1128        u[2] = u[2].wrapping_add(c as u128);
1129    }
1130
1131    // D5.
1132    *q.low_mut() = q_hat;
1133
1134    // D8.
1135    let remainder = full_shr(&u, shift);
1136
1137    (q, remainder)
1138}
1139
1140impl std::fmt::Display for VarUint248 {
1141    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1142        fmt_var_uint248(*self, f)
1143    }
1144}
1145
1146const DEC_DIGITS_LUT: &[u8; 200] = b"\
1147    0001020304050607080910111213141516171819\
1148    2021222324252627282930313233343536373839\
1149    4041424344454647484950515253545556575859\
1150    6061626364656667686970717273747576777879\
1151    8081828384858687888990919293949596979899";
1152
1153fn fmt_var_uint248(mut n: VarUint248, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1154    // See https://github.com/nlordell/ethnum-rs/blob/main/src/fmt.rs
1155
1156    // 2^256 is about 1*10^78, so 79 gives an extra byte of space
1157    let mut buf = [MaybeUninit::<u8>::uninit(); 79];
1158    let mut curr = buf.len() as isize;
1159    let buf_ptr = &mut buf[0] as *mut _ as *mut u8;
1160    let lut_ptr = DEC_DIGITS_LUT.as_ptr();
1161
1162    // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
1163    // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
1164    // that it's OK to copy into `buf_ptr`, notice that at the beginning
1165    // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
1166    // each step this is kept the same as `n` is divided. Since `n` is always
1167    // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
1168    // is safe to access.
1169    unsafe {
1170        // eagerly decode 4 characters at a time
1171        while n >= 10000 {
1172            let rem = (n % 10000).as_isize();
1173            n /= 10000;
1174
1175            let d1 = (rem / 100) << 1;
1176            let d2 = (rem % 100) << 1;
1177            curr -= 4;
1178
1179            // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
1180            // otherwise `curr < 0`. But then `n` was originally at least `10000^10`
1181            // which is `10^40 > 2^128 > n`.
1182            std::ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
1183            std::ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
1184        }
1185
1186        // if we reach here numbers are <= 9999, so at most 4 chars long
1187        let mut n = n.as_isize(); // possibly reduce 64bit math
1188
1189        // decode 2 more chars, if > 2 chars
1190        if n >= 100 {
1191            let d1 = (n % 100) << 1;
1192            n /= 100;
1193            curr -= 2;
1194            std::ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
1195        }
1196
1197        // decode last 1 or 2 chars
1198        if n < 10 {
1199            curr -= 1;
1200            *buf_ptr.offset(curr) = (n as u8) + b'0';
1201        } else {
1202            let d1 = n << 1;
1203            curr -= 2;
1204            std::ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
1205        }
1206    }
1207
1208    // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
1209    // UTF-8 since `DEC_DIGITS_LUT` is
1210    let buf_slice = unsafe {
1211        std::str::from_utf8_unchecked(std::slice::from_raw_parts(
1212            buf_ptr.offset(curr),
1213            buf.len() - curr as usize,
1214        ))
1215    };
1216    f.pad_integral(true, "", buf_slice)
1217}
1218
1219impl FromStr for VarUint248 {
1220    type Err = std::num::ParseIntError;
1221
1222    fn from_str(s: &str) -> Result<Self, Self::Err> {
1223        from_str_radix(s, 10, None)
1224    }
1225}
1226
1227fn from_str_radix(
1228    src: &str,
1229    radix: u32,
1230    prefix: Option<&str>,
1231) -> Result<VarUint248, std::num::ParseIntError> {
1232    use std::num::IntErrorKind::*;
1233
1234    // See https://github.com/nlordell/ethnum-rs/blob/main/src/parse.rs
1235
1236    const fn pie(kind: std::num::IntErrorKind) -> std::num::ParseIntError {
1237        unsafe { std::mem::transmute(kind) }
1238    }
1239
1240    assert!(
1241        (2..=36).contains(&radix),
1242        "from_str_radix_int: must lie in the range `[2, 36]` - found {radix}",
1243    );
1244
1245    if src.is_empty() {
1246        return Err(pie(Empty));
1247    }
1248
1249    // all valid digits are ascii, so we will just iterate over the utf8 bytes
1250    // and cast them to chars. .to_digit() will safely return None for anything
1251    // other than a valid ascii digit for the given radix, including the first-byte
1252    // of multi-byte sequences
1253    let src = src.as_bytes();
1254
1255    let prefixed_digits = match src[0] {
1256        b'+' | b'-' if src[1..].is_empty() => {
1257            return Err(pie(InvalidDigit));
1258        }
1259        b'+' => &src[1..],
1260        _ => src,
1261    };
1262
1263    let digits = match prefix {
1264        Some(prefix) => prefixed_digits
1265            .strip_prefix(prefix.as_bytes())
1266            .ok_or(pie(InvalidDigit))?,
1267        None => prefixed_digits,
1268    };
1269    if digits.is_empty() {
1270        return Err(pie(InvalidDigit));
1271    }
1272
1273    let mut result = VarUint248::ZERO;
1274
1275    if radix <= 16 && digits.len() <= 64 {
1276        for &c in digits {
1277            result *= radix as u128;
1278            let Some(x) = (c as char).to_digit(radix) else {
1279                return Err(pie(InvalidDigit));
1280            };
1281            result += x as u128;
1282        }
1283    } else {
1284        for &c in digits {
1285            match result.checked_mul(&VarUint248::from(radix)) {
1286                Some(mul) => result = mul,
1287                None => return Err(pie(PosOverflow)),
1288            }
1289
1290            let Some(x) = (c as char).to_digit(radix) else {
1291                return Err(pie(InvalidDigit));
1292            };
1293
1294            match result.checked_add(&VarUint248::from(x)) {
1295                Some(add) => result = add,
1296                None => return Err(pie(PosOverflow)),
1297            }
1298        }
1299    }
1300
1301    Ok(result)
1302}
1303
1304#[cfg(test)]
1305mod tests {
1306    use super::*;
1307
1308    #[test]
1309    fn valid_range_is_correct() {
1310        assert!(VarUint248::ZERO.is_valid());
1311        assert!(VarUint248::ONE.is_valid());
1312        assert!(VarUint248::new(123123).is_valid());
1313        assert!(VarUint248::new(u128::MAX).is_valid());
1314        // ...
1315        assert!(VarUint248::from_words(u128::MAX >> 8, u128::MAX).is_valid());
1316
1317        assert!(!VarUint248::from_words(u128::MAX >> 7, u128::MAX).is_valid());
1318        assert!(!VarUint248::from_words(u128::MAX, u128::MAX).is_valid());
1319
1320        assert_eq!(
1321            VarUint248::new(123).saturating_sub(&VarUint248::new(321)),
1322            VarUint248::ZERO
1323        );
1324
1325        assert_eq!(
1326            VarUint248::from_words(u128::MAX, u128::MAX).saturating_sub(&VarUint248::new(1)),
1327            VarUint248::MAX
1328        );
1329        assert_eq!(
1330            VarUint248::from_words(u128::MAX, u128::MAX)
1331                .saturating_sub(&VarUint248::from_words(u128::MAX, u128::MAX)),
1332            VarUint248::ZERO
1333        );
1334    }
1335
1336    #[test]
1337    fn store_into_cell() {
1338        for i in 0..128 {
1339            let lo = 1u128 << i;
1340
1341            let value = VarUint248::new(lo);
1342            let cell = CellBuilder::build_from(value).unwrap();
1343            assert_eq!(value.bit_len().unwrap(), cell.bit_len());
1344        }
1345    }
1346
1347    #[test]
1348    fn load_from_cell() {
1349        let mut lo: u128 = 0xababcdef89abcdefdeadbeeffafacafe;
1350        for _ in 0..=128 {
1351            let value = VarUint248::new(lo);
1352
1353            let cell = CellBuilder::build_from(value).unwrap();
1354
1355            let parsed_value = cell.parse::<VarUint248>().unwrap();
1356            assert_eq!(parsed_value, value);
1357
1358            lo >>= 1;
1359        }
1360    }
1361
1362    #[test]
1363    fn identity() {
1364        assert_eq!(VarUint248::ZERO + VarUint248::ZERO, VarUint248::ZERO);
1365        assert_eq!(VarUint248::ONE * VarUint248::ZERO, VarUint248::ZERO);
1366        assert_eq!(VarUint248::ONE * VarUint248::ONE, VarUint248::ONE);
1367    }
1368
1369    #[test]
1370    fn cmp() {
1371        // 1e38
1372        let x = VarUint248::from_words(0, 100000000000000000000000000000000000000);
1373        // 1e48
1374        let y = VarUint248::from_words(2938735877, 18960114910927365649471927446130393088);
1375        assert!(x < y);
1376        assert_eq!(x.cmp(&y), std::cmp::Ordering::Less);
1377        assert!(y > x);
1378        assert_eq!(y.cmp(&x), std::cmp::Ordering::Greater);
1379
1380        let x = VarUint248::new(100);
1381        let y = VarUint248::new(100);
1382        assert!(x <= y);
1383        assert_eq!(x.cmp(&y), std::cmp::Ordering::Equal);
1384    }
1385
1386    #[test]
1387    fn mul() {
1388        assert_eq!(VarUint248::new(6) * 7, VarUint248::new(42));
1389        assert_eq!(
1390            VarUint248::new(6).checked_mul(&VarUint248::new(7)),
1391            Some(VarUint248::new(42))
1392        );
1393
1394        assert_eq!(
1395            VarUint248::MAX.checked_mul(&VarUint248::ONE),
1396            Some(VarUint248::MAX)
1397        );
1398        assert_eq!(
1399            VarUint248::MAX.checked_mul(&VarUint248::ZERO),
1400            Some(VarUint248::ZERO)
1401        );
1402
1403        assert_eq!(
1404            VarUint248::new(u128::MAX) * u128::MAX,
1405            VarUint248::from_words(!0 << 1, 1),
1406        );
1407        assert_eq!(
1408            VarUint248::new(u128::MAX).checked_mul(&VarUint248::new(u128::MAX)),
1409            Some(VarUint248::from_words(!0 << 1, 1))
1410        );
1411
1412        assert_eq!(VarUint248::MAX.checked_mul(&VarUint248::new(257)), None);
1413        assert_eq!(VarUint248::MAX.checked_mul(&VarUint248::MAX), None);
1414    }
1415
1416    #[test]
1417    fn division() {
1418        // 0 X
1419        // ---
1420        // 0 X
1421        assert_eq!(VarUint248::new(100) / 9, 11);
1422
1423        // 0 X
1424        // ---
1425        // K X
1426        assert_eq!(VarUint248::new(!0u128) / (VarUint248::ONE << 128), 0u128);
1427
1428        // K 0
1429        // ---
1430        // K 0
1431        assert_eq!(
1432            VarUint248::from_words(100, 0) / VarUint248::from_words(10, 0),
1433            10
1434        );
1435
1436        // K K
1437        // ---
1438        // K 0
1439        assert_eq!(
1440            VarUint248::from_words(100, 1337) / (VarUint248::ONE << 130u32),
1441            25
1442        );
1443        assert_eq!(
1444            VarUint248::from_words(1337, !0) / VarUint248::from_words(63, 0),
1445            21
1446        );
1447
1448        // K X
1449        // ---
1450        // 0 K
1451        assert_eq!(
1452            VarUint248::from_words(42, 0) / VarUint248::ONE,
1453            VarUint248::from_words(42, 0),
1454        );
1455        assert_eq!(
1456            VarUint248::from_words(42, 42) / (VarUint248::ONE << 42),
1457            42u128 << (128 - 42),
1458        );
1459        assert_eq!(
1460            VarUint248::from_words(1337, !0) / 0xc0ffee,
1461            35996389033280467545299711090127855,
1462        );
1463        assert_eq!(
1464            VarUint248::from_words(42, 0) / 99,
1465            144362216269489045105674075880144089708,
1466        );
1467
1468        // K X
1469        // ---
1470        // K K
1471        assert_eq!(
1472            VarUint248::from_words(100, 100) / VarUint248::from_words(1000, 1000),
1473            0,
1474        );
1475        assert_eq!(
1476            VarUint248::from_words(1337, !0) / VarUint248::from_words(43, !0),
1477            30,
1478        );
1479    }
1480
1481    #[test]
1482    #[should_panic]
1483    fn division_by_zero() {
1484        _ = VarUint248::ONE / 0;
1485    }
1486
1487    #[test]
1488    fn remainder() {
1489        // 0 X
1490        // ---
1491        // 0 X
1492        assert_eq!(VarUint248::new(100) % 9, 1);
1493
1494        // 0 X
1495        // ---
1496        // K X
1497        assert_eq!(
1498            VarUint248::new(!0u128) % (VarUint248::ONE << 128u32),
1499            !0u128
1500        );
1501
1502        // K 0
1503        // ---
1504        // K 0
1505        assert_eq!(
1506            VarUint248::from_words(100, 0) % VarUint248::from_words(10, 0),
1507            0
1508        );
1509
1510        // K K
1511        // ---
1512        // K 0
1513        assert_eq!(
1514            VarUint248::from_words(100, 1337) % (VarUint248::ONE << 130u32),
1515            1337
1516        );
1517        assert_eq!(
1518            VarUint248::from_words(1337, !0) % VarUint248::from_words(63, 0),
1519            VarUint248::from_words(14, !0),
1520        );
1521
1522        // K X
1523        // ---
1524        // 0 K
1525        assert_eq!(VarUint248::from_words(42, 0) % VarUint248::ONE, 0);
1526        assert_eq!(
1527            VarUint248::from_words(42, 42) % (VarUint248::ONE << 42),
1528            42u128
1529        );
1530        assert_eq!(VarUint248::from_words(1337, !0) % 0xc0ffee, 1910477);
1531        assert_eq!(VarUint248::from_words(42, 0) % 99, 60);
1532
1533        // K X
1534        // ---
1535        // K K
1536        assert_eq!(
1537            VarUint248::from_words(100, 100) % VarUint248::from_words(1000, 1000),
1538            VarUint248::from_words(100, 100),
1539        );
1540        assert_eq!(
1541            VarUint248::from_words(1337, !0) % VarUint248::from_words(43, !0),
1542            VarUint248::from_words(18, 29),
1543        );
1544    }
1545
1546    #[test]
1547    #[should_panic]
1548    fn remainder_by_zero() {
1549        _ = VarUint248::ONE % 0;
1550    }
1551}