Skip to main content

oxidd_core/util/num/
bigint.rs

1// spell-checker:ignore trunc
2
3use std::cmp::Ordering;
4use std::fmt::Write;
5use std::mem::ManuallyDrop;
6use std::ops::{Add, Shl, Shr};
7use std::ptr::NonNull;
8use std::{fmt, mem};
9
10use crate::util::IsFloatingPoint;
11
12/// Natural number, specifically well-suited for counting satisfying assignments
13///
14/// When counting the number of satisfying assignments in a decision diagram,
15/// the numbers often have many trailing zeros (in binary representation). Based
16/// on this observation, we decompose numbers as *m* × 2^<sup>e</sup> with a
17/// mantissa *m* and an exponent *e*. We require that both *m* and *e* are
18/// natural numbers. Further, *m* is odd unless the represented number is zero,
19/// in which case both *m* and *e* are zero.
20///
21/// The exponent *e* is stored as a [`u64`] and the mantissa *m* as an array of
22/// [`u64`] "digits." In case *m* fits into a single [`u64`] digit, *m* is
23/// stored inline, i.e., without any heap allocation.
24///
25/// Conceptually, this type is similar to arbitrary precision floats. However,
26/// we do not require the user to choose the precision, instead we always
27/// represent numbers exactly.
28///
29/// To account for computation errors (e.g., an exponent that cannot be
30/// represented as a [`u64`]). this type includes a NaN value. It is undefined
31/// if this value is larger or smaller than actual natural numbers. Therefore,
32/// this type does not implement [`Ord`] but only [`PartialOrd`].
33///
34/// Also note that the implementation of [`Shr`] is tailored to the application
35/// in counting satisfying assignments, where it is used as an exact division by
36/// (a power of) two. If a 1-bit would get lost by a shift to the right, i.e.,
37/// the division result would not be exact, the computation result is NaN to
38/// make the error obvious. A context for such an error may be pretending that a
39/// Boolean function has a smaller domain than it actually has.
40#[derive(Eq)]
41pub struct Natural {
42    /// Unless this pointer is `DANGLING`, it points to an array of `len` `u64`
43    /// "digits." The array starts with the least significant digit (i.e.,
44    /// little endian). If the most significant digit is 0, the most significant
45    /// bit of the second-most significant digit is 1. The least significant bit
46    /// of the least significant digit in the array is always 1. Further, the
47    /// number represented by the array (i.e., disregarding `shl`) is
48    /// greater than `u64::MAX`.
49    ///
50    /// Allowing the most significant to be 0 avoids the need to re-allocate
51    /// memory in the addition of two numbers: We can predict the sum's bit
52    /// width almost exactly in constant time, we only don't know whether there
53    /// is a final carry if the operands have different bit width. Hence, we
54    /// just always assume that there will be a carry and potentially allocate
55    /// one more digit than needed.
56    ptr: std::ptr::NonNull<u64>,
57    /// If `ptr` is not `DANGLING`, then `len` represents the length of
58    /// the array to which `ptr` points. Otherwise the number represented by the
59    /// [`Natural`] is `len << shl`. If `len != 0`, then the least significant
60    /// bit of `len` is 1.
61    len: u64,
62    /// Trailing zeros of the represented number (in binary representation). If
63    /// `u64::MAX`, this indicates a computation error (NaN).
64    shl: u64,
65}
66
67/// An unaligned, dangling pointer
68const DANGLING: NonNull<u64> = {
69    assert!(
70        std::mem::align_of::<u64>() > 1,
71        "The implementation of `Natural` assumes that `u64` has at least 2 byte alignment"
72    );
73    NonNull::without_provenance(std::num::NonZeroUsize::new(1).unwrap())
74};
75
76#[inline]
77fn shl_amount(value: u64) -> u32 {
78    if value == 0 {
79        0
80    } else {
81        value.trailing_zeros()
82    }
83}
84
85#[inline]
86fn bit_width(digits: &[u64], shl: u64) -> u128 {
87    (u64::BITS as u128 * digits.len() as u128) - digits.last().unwrap().leading_zeros() as u128
88        + shl as u128
89}
90
91impl Natural {
92    /// The number 0
93    pub const ZERO: Self = Self {
94        ptr: DANGLING,
95        len: 0,
96        shl: 0,
97    };
98    /// cbindgen:ignore
99    const NAN: Self = Self {
100        ptr: DANGLING,
101        len: 0,
102        shl: u64::MAX,
103    };
104
105    #[allow(unused)] // only used by tests or with debug assertions enabled
106    fn check_inv(&self) {
107        if self.ptr == DANGLING {
108            if self.len == 0 {
109                assert!(self.shl == 0 || self.shl == u64::MAX);
110            } else {
111                assert_eq!(self.len & 1, 1);
112            }
113        } else {
114            assert_ne!(self.len, 0);
115            assert_ne!(self.len, 1);
116            // SAFETY: `self.ptr` is not `DANGLING`
117            let digits =
118                unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) };
119            if *digits.last().unwrap() == 0 {
120                assert_eq!(digits[digits.len() - 2] >> (u64::BITS - 1), 1);
121            }
122            assert_eq!(digits[0] & 1, 1);
123        }
124    }
125
126    /// Decompose a [`Natural`] into its raw parts
127    ///
128    /// The first tuple component is either [`std::ptr::null_mut()`] and the
129    /// mantissa is just the second tuple component, or the first component
130    /// points to an array with the number of elements specified by the second
131    /// component. This array contains the mantissa digits, starting with the
132    /// least significant one.
133    ///
134    /// The third component is the exponent, or [`u64::MAX`] to represent a
135    /// failed computation (NaN).
136    ///
137    /// This method is primarily intended for use with foreign function
138    /// interfaces and thus hidden from the documentation.
139    ///
140    /// See [`Self::from_raw_parts()`] for the inverse operation.
141    #[inline]
142    #[doc(hidden)]
143    pub fn into_raw_parts(self) -> (*mut u64, u64, u64) {
144        let ptr = if self.ptr == DANGLING {
145            std::ptr::null_mut()
146        } else {
147            self.ptr.as_ptr()
148        };
149        let this = ManuallyDrop::new(self);
150        (ptr, this.len, this.shl)
151    }
152
153    /// Create a [`Natural`] from its raw parts
154    ///
155    /// If `ptr` is [`std::ptr::null_mut()`], then `len` is the mantissa.
156    /// Otherwise `ptr` points to `len` digits (starting with the least
157    /// significant one) describing the mantissa. `exp` is the exponent, or
158    /// [`u64::MAX`] to represent a failed computation (NaN).
159    ///
160    /// This method is primarily intended for use with foreign function
161    /// interfaces and thus hidden from the documentation.
162    ///
163    /// See [`Self::into_raw_parts()`] for the inverse operation.
164    ///
165    /// # SAFETY
166    ///
167    /// `ptr` must either be null or point to an array of `len` elements and
168    /// be valid for reads. In general, functions taking an owned or mutably
169    /// borrowed [`Natural`] additionally assume that this array is valid for
170    /// writes and that it can be deallocated by turning it into a boxed slice.
171    #[inline]
172    #[doc(hidden)]
173    pub unsafe fn from_raw_parts(ptr: *mut u64, len: u64, exp: u64) -> Self {
174        debug_assert!(ptr.is_null() || len != 0);
175        debug_assert!(len != 0 || exp == 0 || exp == u64::MAX);
176        let ptr = NonNull::new(ptr).unwrap_or(DANGLING);
177        let num = Self { ptr, len, shl: exp };
178        #[cfg(debug_assertions)]
179        num.check_inv();
180        num
181    }
182
183    #[inline]
184    fn from_mantissa_single_with_shl(mantissa: u64, shl: u64) -> Self {
185        debug_assert!(
186            mantissa & 1 == 1 || (mantissa == 0 && (shl == 0 || shl == u64::MAX)),
187            "invalid arguments (mantissa: {mantissa}, shl: {shl})"
188        );
189        Self {
190            ptr: DANGLING,
191            len: mantissa,
192            shl,
193        }
194    }
195
196    #[inline]
197    fn from_mantissa_with_shl(mantissa: Box<[u64]>, shl: u64) -> Self {
198        let len = mantissa.len() as u64;
199        debug_assert!(len >= 2);
200        debug_assert!(
201            mantissa[len as usize - 1] != 0 || mantissa[len as usize - 2] >> (u64::BITS - 1) == 1
202        );
203        debug_assert_eq!(mantissa[0] & 1, 1);
204        let ptr = NonNull::new(Box::into_raw(mantissa).cast()).unwrap();
205        Self { ptr, len, shl }
206    }
207
208    /// Create a `Natural` from a sequence of digits
209    ///
210    /// Here, `le` stands for *little endian*, i.e., the first element of
211    /// `digits` is the least significant digit.
212    pub fn from_le_digits(digits: &[u64]) -> Self {
213        let mut digits = digits;
214        while let [r @ .., 0] = digits {
215            digits = r;
216        }
217        let mut shl_digits = 0u64;
218        while let [0, r @ ..] = digits {
219            digits = r;
220            shl_digits += 1;
221        }
222        match digits {
223            [] => Self::ZERO,
224            &[d] => {
225                debug_assert_ne!(d, 0);
226                let shl = d.trailing_zeros();
227                Self {
228                    ptr: DANGLING,
229                    len: d >> shl,
230                    shl: (shl as u64).saturating_add(shl_digits.saturating_mul(u64::BITS as u64)),
231                }
232            }
233            &[lsd, .., msd] => {
234                debug_assert_ne!(lsd, 0);
235                let shr_bits = lsd.trailing_zeros();
236                let shl = shl_digits.saturating_mul(u64::BITS as u64);
237                if shr_bits == 0 {
238                    return Self {
239                        ptr: NonNull::new(Box::<[u64]>::into_raw(digits.into()).cast()).unwrap(),
240                        len: digits.len() as u64,
241                        shl,
242                    };
243                }
244                let shl = shl.saturating_add(shr_bits as u64);
245
246                let len = digits.len() - ((shr_bits + msd.leading_zeros()) / u64::BITS) as usize;
247                if len == 1 {
248                    return Self {
249                        ptr: DANGLING,
250                        len: msd.rotate_right(shr_bits) | (lsd >> shr_bits),
251                        shl,
252                    };
253                }
254
255                let lower_mask = u64::MAX >> shr_bits;
256                let upper_mask = !lower_mask;
257                let mut v = Vec::with_capacity(len);
258                let mut lower = lsd >> shr_bits;
259                v.extend(digits[1..].iter().map(|&d| {
260                    let rot = d.rotate_right(shr_bits);
261                    let d = lower | (rot & upper_mask);
262                    lower = rot & lower_mask;
263                    d
264                }));
265                if v.len() != len {
266                    v.push(lower);
267                }
268                debug_assert_eq!(v.len(), len);
269
270                Self {
271                    ptr: NonNull::new(Box::into_raw(v.into_boxed_slice()).cast()).unwrap(),
272                    len: len as u64,
273                    shl,
274                }
275            }
276        }
277    }
278
279    /// Get the mantissa
280    ///
281    /// The returned sequence starts with the least significant digit and has
282    /// minimal length, but at least one element. So unless the mantissa is 0,
283    /// the most significant digit (i.e., the last element) is non-zero.
284    #[inline]
285    pub fn mantissa(&self) -> &[u64] {
286        let digits = if self.ptr == DANGLING {
287            std::slice::from_ref(&self.len)
288        } else {
289            // SAFETY: `self.ptr` is not `DANGLING`
290            let digits =
291                unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) };
292            // SAFETY: follows from the representation invariant
293            if *unsafe { digits.last().unwrap_unchecked() } == 0 {
294                &digits[..self.len as usize - 1]
295            } else {
296                digits
297            }
298        };
299        // SAFETY: follows from the representation invariant
300        unsafe { std::hint::assert_unchecked(!digits.is_empty()) };
301        digits
302    }
303
304    /// Get the mantissa
305    ///
306    /// Note that unlike [`Self::mantissa()`], this method returns a full view
307    /// on the array (i.e., it does not remove any leading zero).
308    #[inline]
309    fn mantissa_raw(&self) -> &[u64] {
310        let digits = if self.ptr == DANGLING {
311            std::slice::from_ref(&self.len)
312        } else {
313            // SAFETY: `self.ptr` is not `DANGLING`
314            unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
315        };
316        // SAFETY: follows from the representation invariant
317        unsafe { std::hint::assert_unchecked(!digits.is_empty()) };
318        digits
319    }
320
321    /// Get a mutable reference to the mantissa
322    ///
323    /// Note that unlike [`Self::mantissa()`], this method returns a full view
324    /// on the array (i.e., it does not remove any leading zero).
325    #[inline]
326    fn mantissa_mut(&mut self) -> &mut [u64] {
327        let digits = if self.ptr == DANGLING {
328            std::slice::from_mut(&mut self.len)
329        } else {
330            // SAFETY: `self.ptr` is not `DANGLING`
331            unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
332        };
333        // SAFETY: follows from the representation invariant
334        unsafe { std::hint::assert_unchecked(!digits.is_empty()) };
335        digits
336    }
337
338    /// Get the exponent
339    #[inline(always)]
340    pub fn exp(&self) -> u64 {
341        self.shl
342    }
343
344    /// Check if the number is NaN
345    #[inline(always)]
346    pub fn is_nan(&self) -> bool {
347        self.shl == u64::MAX
348    }
349
350    /// Compute the number of bits needed to represent the number explicitly,
351    /// that is *1 + floor(log₂(self))*.
352    pub fn bit_width(&self) -> u128 {
353        bit_width(self.mantissa_raw(), self.shl)
354    }
355}
356
357impl Drop for Natural {
358    fn drop(&mut self) {
359        if self.ptr != DANGLING {
360            let slice = std::ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize);
361            // SAFETY: ptr is not dangling, thus the pointer is valid and we own the slice
362            drop(unsafe { Box::from_raw(slice) });
363        }
364    }
365}
366
367// SAFETY: we uniquely own the referenced memory
368unsafe impl Send for Natural {}
369unsafe impl Sync for Natural {}
370
371impl Clone for Natural {
372    fn clone(&self) -> Self {
373        if self.ptr == DANGLING {
374            return Self { ..*self };
375        }
376        let slice = std::ptr::slice_from_raw_parts(self.ptr.as_ptr(), self.len as usize);
377        // SAFETY: `self.ptr` is not dangling, thus the pointer is valid and we
378        // have shared access to the slice
379        let clone: *mut [u64] = Box::into_raw(unsafe { &*slice }.into());
380        Self {
381            ptr: NonNull::new(clone.cast()).unwrap(),
382            ..*self
383        }
384    }
385
386    fn clone_from(&mut self, source: &Self) {
387        self.shl = source.shl;
388        if self.ptr == DANGLING {
389            if source.ptr != DANGLING {
390                let slice = std::ptr::slice_from_raw_parts(source.ptr.as_ptr(), self.len as usize);
391                // SAFETY: `source.ptr` is not dangling, thus the pointer is
392                // valid and we have shared access to the slice
393                let clone: *mut [u64] = Box::into_raw(unsafe { &*slice }.into());
394                self.ptr = NonNull::new(clone.cast()).unwrap();
395            }
396            self.len = source.len;
397            return;
398        }
399
400        let dst = std::ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize);
401        if source.ptr != DANGLING {
402            // SAFETY: `source.ptr` is not dangling, thus the pointer is valid
403            // and we have shared access to the slice
404            let src =
405                unsafe { std::slice::from_raw_parts(source.ptr.as_ptr(), source.len as usize) };
406            if self.len == source.len {
407                // SAFETY: `self.ptr` is not dangling, thus the pointer is valid
408                // and we own the slice
409                unsafe { &mut *dst }.copy_from_slice(src);
410                return;
411            }
412            self.ptr = NonNull::new(Box::<[u64]>::into_raw(src.into()).cast()).unwrap();
413        }
414        self.len = source.len;
415
416        // SAFETY: `self.ptr` is not dangling, thus the pointer is valid and we
417        // own the slice
418        drop(unsafe { Box::from_raw(dst) });
419    }
420}
421
422impl PartialEq for Natural {
423    fn eq(&self, other: &Self) -> bool {
424        if self.shl != other.shl {
425            return false;
426        }
427        if self.is_nan() {
428            return true; // both are `None`-alike
429        }
430        self.mantissa() == other.mantissa()
431    }
432}
433impl PartialOrd for Natural {
434    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
435        if self.is_nan() || other.is_nan() {
436            return None;
437        }
438
439        let l_digits = self.mantissa();
440        let r_digits = other.mantissa();
441
442        let l_bw = bit_width(l_digits, self.shl);
443        let r_bw = bit_width(r_digits, other.shl);
444        if l_bw != r_bw {
445            return Some(l_bw.cmp(&r_bw));
446        }
447
448        let (&l_msd, mut l_digits) = l_digits.split_last().unwrap();
449        let (&r_msd, mut r_digits) = r_digits.split_last().unwrap();
450        let l_shl = l_msd.leading_zeros();
451        let r_shl = r_msd.leading_zeros();
452        let mut l = l_msd << l_shl;
453        let mut r = r_msd << r_shl;
454
455        let l_upper_mask = u64::MAX << l_shl;
456        let l_lower_mask = !l_upper_mask;
457        let r_upper_mask = u64::MAX << r_shl;
458        let r_lower_mask = !r_upper_mask;
459        while let ([l_rest @ .., l_next], [r_rest @ .., r_next]) = (l_digits, r_digits) {
460            let l_rot = l_next.rotate_left(l_shl);
461            let r_rot = r_next.rotate_left(r_shl);
462            let l_digit = l | (l_rot & l_lower_mask);
463            let r_digit = r | (r_rot & r_lower_mask);
464
465            if l_digit != r_digit {
466                return Some(l_digit.cmp(&r_digit));
467            }
468
469            l = l_rot & l_upper_mask;
470            r = r_rot & r_upper_mask;
471            l_digits = l_rest;
472            r_digits = r_rest;
473        }
474
475        Some(match (l_digits, r_digits) {
476            ([], []) => l.cmp(&r),
477            ([.., l_next], _) => {
478                debug_assert!(r_digits.is_empty());
479                let cmp = (l | (l_next.rotate_left(l_shl) & l_lower_mask)).cmp(&r);
480                // The rest of `l_digits` contains at least one non-zero bit,
481                // while the remaining bits (after unfolding `other.shl`) are
482                // all zero.
483                cmp.then(Ordering::Greater)
484            }
485            (_, [.., r_next]) => {
486                let cmp = l.cmp(&(r | (r_next.rotate_left(r_shl) & r_lower_mask)));
487                cmp.then(Ordering::Less)
488            }
489        })
490    }
491}
492
493impl std::hash::Hash for Natural {
494    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
495        if self.is_nan() {
496            1.hash(state);
497        } else {
498            debug_assert!(
499                self.len != 0 || self.shl == 0,
500                "0 has a unique representation"
501            );
502            self.shl.hash(state);
503            self.mantissa().hash(state);
504        }
505    }
506}
507
508/// cbindgen:ignore
509impl IsFloatingPoint for Natural {
510    const FLOATING_POINT: bool = false;
511    const MIN_EXP: i32 = 0;
512}
513
514impl From<u128> for Natural {
515    #[inline]
516    fn from(value: u128) -> Self {
517        if value == 0 {
518            return Self::ZERO;
519        }
520        let leading = value.leading_zeros();
521        let shl = value.trailing_zeros();
522        if leading - shl <= u64::BITS {
523            Self::from_mantissa_single_with_shl((value >> shl) as u64, shl as u64)
524        } else {
525            let value = value >> shl;
526            Self::from_mantissa_with_shl(
527                [value as u64, (value >> u64::BITS) as u64].into(),
528                shl as u64,
529            )
530        }
531    }
532}
533impl From<u64> for Natural {
534    #[inline]
535    fn from(value: u64) -> Self {
536        let shl = shl_amount(value);
537        Self::from_mantissa_single_with_shl(value >> shl, shl as u64)
538    }
539}
540impl From<u32> for Natural {
541    #[inline(always)]
542    fn from(value: u32) -> Self {
543        Self::from(value as u64)
544    }
545}
546impl From<u16> for Natural {
547    #[inline(always)]
548    fn from(value: u16) -> Self {
549        Self::from(value as u64)
550    }
551}
552impl From<u8> for Natural {
553    #[inline(always)]
554    fn from(value: u8) -> Self {
555        Self::from(value as u64)
556    }
557}
558
559impl Add for Natural {
560    type Output = Self;
561    fn add(mut self, mut rhs: Self) -> Self {
562        if rhs.len == 0 {
563            return self;
564        }
565        if self.len == 0 {
566            return rhs;
567        }
568
569        if self.shl > rhs.shl {
570            mem::swap(&mut self, &mut rhs);
571        }
572
573        let l_shl = self.shl;
574        let r_shl = rhs.shl;
575        let l_digits = self.mantissa_mut();
576        let r_digits = rhs.mantissa_mut();
577
578        let l_bit_width = bit_width(l_digits, l_shl);
579        let r_bit_width = bit_width(r_digits, r_shl);
580        // target bit width (may be one less if `l_bit_width != r_bit_width`)
581        let bit_width = std::cmp::max(l_bit_width, r_bit_width) + 1;
582
583        if l_shl < r_shl {
584            if r_shl == u64::MAX {
585                return Self::NAN;
586            }
587
588            // mantissa bit/digit count; possibly one too large each
589            let bit_len = bit_width - l_shl as u128;
590            let len = bit_len.div_ceil(u64::BITS as u128) as usize;
591            debug_assert_ne!(len, 0);
592
593            let start_digit = ((r_shl - l_shl) / u64::BITS as u64) as usize;
594            let start_bit = (r_shl - l_shl) as u32 % u64::BITS;
595            let upper_mask = u64::MAX << start_bit;
596            let lower_mask = !upper_mask;
597
598            if bit_len <= (u64::BITS + 1) as u128 {
599                debug_assert_eq!(start_digit, 0);
600                debug_assert_eq!(self.ptr, DANGLING);
601                debug_assert_eq!(rhs.ptr, DANGLING);
602                debug_assert_eq!(rhs.len.rotate_left(start_bit) & lower_mask, 0);
603                let (d, carry) = self.len.overflowing_add(rhs.len << start_bit);
604                return if carry {
605                    Self::from_mantissa_with_shl([d, 1].into(), l_shl)
606                } else {
607                    Self::from_mantissa_single_with_shl(d, l_shl)
608                };
609            }
610
611            if len == l_digits.len() {
612                // we can (likely) update in-place
613                debug_assert!(r_digits.len() + start_digit <= l_digits.len());
614                let mut lower = 0;
615                let mut carry = false;
616                for (l, r) in l_digits[start_digit..].iter_mut().zip(&r_digits[..]) {
617                    let rot = r.rotate_left(start_bit);
618                    (*l, carry) = l.carrying_add(rot & upper_mask | lower, carry);
619                    lower = rot & lower_mask;
620                }
621                let i = start_digit + r_digits.len();
622                if let Some(l) = l_digits.get_mut(i) {
623                    (*l, carry) = l.carrying_add(lower, carry);
624                    lower = 0;
625                    for l in &mut l_digits[i + 1..] {
626                        (*l, carry) = l.overflowing_add(carry as u64);
627                    }
628                }
629                debug_assert_eq!(lower, 0);
630                debug_assert!(!carry);
631                return self;
632            }
633
634            let mut vec = Vec::with_capacity(len);
635            if start_digit >= l_digits.len() {
636                vec.extend_from_slice(l_digits);
637                if start_digit > l_digits.len() {
638                    vec.extend((l_digits.len()..start_digit).map(|_| 0));
639                }
640                if start_bit == 0 {
641                    vec.extend_from_slice(r_digits);
642                } else {
643                    let mut lower = 0;
644                    vec.extend(r_digits.iter().map(|&r| {
645                        let rot = r.rotate_left(start_bit);
646                        rot & upper_mask | mem::replace(&mut lower, rot & lower_mask)
647                    }));
648                    if lower != 0 {
649                        vec.push(lower);
650                    }
651                }
652            } else {
653                vec.extend_from_slice(&l_digits[..start_digit]);
654                let mut lower = 0;
655                let mut carry = false;
656                let zipped = l_digits[start_digit..].iter().zip(r_digits.iter());
657                vec.extend(zipped.map(|(l, r)| {
658                    let rot = r.rotate_left(start_bit);
659                    let res = l.carrying_add(rot & upper_mask | lower, carry);
660                    carry = res.1;
661                    lower = rot & lower_mask;
662                    res.0
663                }));
664                let l_i = start_digit + r_digits.len(); // assuming `r_digits` is exhausted
665                let r_i = l_digits.len() - start_digit; // assuming `l_digits` is exhausted
666                if let Some(l) = l_digits.get(l_i) {
667                    let res = l.carrying_add(lower, carry);
668                    vec.push(res.0);
669                    carry = res.1;
670                    lower = 0;
671                    vec.extend(l_digits[l_i + 1..].iter().map(|l| {
672                        let res = l.overflowing_add(carry as u64);
673                        carry = res.1;
674                        res.0
675                    }));
676                } else if r_i < r_digits.len() {
677                    vec.extend(r_digits[r_i..].iter().map(|r| {
678                        let rot = r.rotate_left(start_bit);
679                        let res = (rot & upper_mask | lower).overflowing_add(carry as u64);
680                        lower = rot & lower_mask;
681                        carry = res.1;
682                        res.0
683                    }));
684                }
685                if vec.len() != vec.capacity() {
686                    vec.push(lower + carry as u64);
687                } else {
688                    debug_assert_eq!(lower + carry as u64, 0);
689                }
690            }
691
692            debug_assert_eq!(vec.capacity(), vec.len());
693            return Self::from_mantissa_with_shl(vec.into_boxed_slice(), l_shl);
694        }
695
696        debug_assert_eq!(l_shl, r_shl);
697
698        // the least significant bits cancel each other
699        // -> determine the new left shift
700        let (mut lsd, mut carry) = l_digits[0].overflowing_add(r_digits[0]);
701        let mut i_in = 1;
702        while lsd == 0 {
703            let l = l_digits.get(i_in).copied().unwrap_or_default();
704            let r = r_digits.get(i_in).copied().unwrap_or_default();
705            i_in += 1;
706            debug_assert!(carry);
707            (lsd, carry) = l.carrying_add(r, true);
708        }
709        let bit_shr = shl_amount(lsd);
710        let Some(shl) = l_shl
711            .checked_add(bit_shr as u64)
712            .and_then(|sum| sum.checked_add((i_in as u64 - 1).checked_mul(u64::BITS as u64)?))
713        else {
714            return Self::NAN;
715        };
716        // mantissa bit/digit count; possibly one too large each
717        let bit_len = bit_width - shl as u128;
718        debug_assert_ne!(bit_len, 0);
719        let len = bit_len.div_ceil(u64::BITS as u128) as usize;
720
721        let l = l_digits.get(i_in).copied().unwrap_or_default();
722        let r = r_digits.get(i_in).copied().unwrap_or_default();
723        i_in += 1;
724        let (next_lsd, mut carry) = l.carrying_add(r, carry);
725        let mut rot = next_lsd.rotate_right(bit_shr);
726
727        let lower_mask = u64::MAX >> bit_shr;
728        let upper_mask = !lower_mask;
729        let d = (lsd >> bit_shr) | (rot & upper_mask);
730
731        // `l_digits` and `r_digits` may be arbitrarily long, while the sum may
732        // fit into a single digit. We also account for the case in which
733        // `bit_len` is over-estimated by a bit.
734        if bit_len <= (u64::BITS + 1) as u128 && rot & lower_mask == 0 {
735            debug_assert!(!carry);
736            return Self::from_mantissa_single_with_shl(d, shl);
737        }
738        debug_assert!(len >= 2);
739
740        if len == l_digits.len() {
741            // we can (likely) update in-place
742            l_digits[0] = d;
743            let mut i_out = 1;
744            while let Some(l) = l_digits.get(i_in)
745                && let Some(r) = r_digits.get(i_in)
746            {
747                i_in += 1;
748                let res = l.carrying_add(*r, carry);
749                let next_rot = res.0.rotate_right(bit_shr);
750                carry = res.1;
751                l_digits[i_out] = (rot & lower_mask) | (next_rot & upper_mask);
752                i_out += 1;
753                rot = next_rot;
754            }
755
756            if i_in < r_digits.len() {
757                // This loop can run for up to `l_digits.len()` iterations,
758                // e.g., if the position of sum's least significant bit with
759                // value 1 corresponds to the position of `l_digits`' most
760                // significant bit.
761                for r in &r_digits[i_in..] {
762                    let res = r.overflowing_add(carry as u64);
763                    let next_rot = res.0.rotate_right(bit_shr);
764                    carry = res.1;
765                    l_digits[i_out] = (rot & lower_mask) | (next_rot & upper_mask);
766                    i_out += 1;
767                    if i_out == len {
768                        self.shl = shl;
769                        return self;
770                    }
771                    rot = next_rot;
772                }
773            } else {
774                while let Some(l) = l_digits.get(i_in) {
775                    i_in += 1;
776                    let res = l.overflowing_add(carry as u64);
777                    let next_rot = res.0.rotate_right(bit_shr);
778                    carry = res.1;
779                    l_digits[i_out] = (rot & lower_mask) | (next_rot & upper_mask);
780                    i_out += 1;
781                    rot = next_rot;
782                }
783            }
784
785            if bit_shr == 0 {
786                debug_assert_eq!(lower_mask, u64::MAX);
787                l_digits[i_out] = rot;
788                if i_out + 1 != l_digits.len() {
789                    i_out += 1;
790                    l_digits[i_out] = carry as u64;
791                }
792            } else {
793                l_digits[i_out] = (rot & lower_mask) | (carry as u64).rotate_right(bit_shr);
794            }
795            debug_assert_eq!(i_out + 1, l_digits.len());
796            self.shl = shl;
797            return self;
798        }
799
800        let mut vec = Vec::with_capacity(len);
801        vec.push(d);
802        let (long, short) = if l_digits.len() >= r_digits.len() {
803            (l_digits, r_digits)
804        } else {
805            (r_digits, l_digits)
806        };
807        if i_in < short.len() {
808            let zipped = short[i_in..].iter().zip(&long[i_in..]);
809            vec.extend(zipped.map(|(l, r)| {
810                let res = l.carrying_add(*r, carry);
811                let next_rot = res.0.rotate_right(bit_shr);
812                carry = res.1;
813                (mem::replace(&mut rot, next_rot) & lower_mask) | (next_rot & upper_mask)
814            }));
815            i_in = short.len();
816        }
817        if i_in < long.len() {
818            vec.extend(long[i_in..].iter().map(|x| {
819                let res = x.overflowing_add(carry as u64);
820                let next_rot = res.0.rotate_right(bit_shr);
821                carry = res.1;
822                (mem::replace(&mut rot, next_rot) & lower_mask) | (next_rot & upper_mask)
823            }));
824        }
825
826        if bit_shr == 0 {
827            debug_assert_eq!(lower_mask, u64::MAX);
828            vec.push(rot);
829            if carry {
830                vec.push(1);
831            }
832        } else {
833            let d = (rot & lower_mask) | (carry as u64).rotate_right(bit_shr);
834            if d != 0 {
835                vec.push(d);
836            }
837        }
838        if vec.len() < vec.capacity() {
839            vec.push(0);
840        }
841        debug_assert_eq!(vec.len(), vec.capacity());
842        Self::from_mantissa_with_shl(vec.into_boxed_slice(), shl)
843    }
844}
845
846impl Shl<u64> for Natural {
847    type Output = Self;
848    #[inline]
849    fn shl(mut self, rhs: u64) -> Self {
850        if self.len != 0 {
851            self.shl = self.shl.saturating_add(rhs); // possibly becomes NaN
852        }
853        self
854    }
855}
856impl Shl<u32> for Natural {
857    type Output = Self;
858    #[inline(always)]
859    fn shl(self, rhs: u32) -> Self {
860        self.shl(rhs as u64)
861    }
862}
863
864impl Shr<u64> for Natural {
865    type Output = Self;
866    #[inline]
867    fn shr(mut self, rhs: u64) -> Self {
868        if self.shl >= rhs {
869            if self.shl != u64::MAX {
870                self.shl -= rhs;
871            }
872        } else if self.len != 0 {
873            self.shl = u64::MAX; // set to NaN
874        }
875        self
876    }
877}
878impl Shr<u32> for Natural {
879    type Output = Self;
880    #[inline(always)]
881    fn shr(self, rhs: u32) -> Self {
882        self.shr(rhs as u64)
883    }
884}
885
886fn to_u_big(value: &[u64]) -> dashu_int::UBig {
887    // `UBig::from_words` doesn't optimize these cases:
888    match *value {
889        [d] => return d.into(),
890        [d1, d2] => return (d1 as u128 | ((d2 as u128) << 64)).into(),
891        _ => {}
892    }
893
894    const IS_MULTIPLE: bool =
895        mem::size_of::<u64>().is_multiple_of(mem::size_of::<dashu_int::Word>());
896    const SCALE: usize = mem::size_of::<u64>() / mem::size_of::<dashu_int::Word>();
897    const ALIGN_MATCH: bool = mem::align_of::<dashu_int::Word>() <= mem::align_of::<u64>();
898    // spell-checker:ignore CONV
899    #[cfg(target_endian = "little")]
900    const FAST_CONV: bool = ALIGN_MATCH && IS_MULTIPLE;
901    #[cfg(target_endian = "big")]
902    const FAST_CONV: bool = ALIGN_MATCH && IS_MULTIPLE && SCALE == 1;
903
904    if FAST_CONV {
905        // SAFETY: `dashu_int::Word` is a primitive integer type with equal or
906        // smaller alignment and fits precisely `SCALE` times into a `u64`.
907        dashu_int::UBig::from_words(unsafe {
908            std::slice::from_raw_parts(
909                value.as_ptr().cast::<dashu_int::Word>(),
910                value.len() * SCALE,
911            )
912        })
913    } else {
914        #[cfg(target_endian = "big")]
915        let value: Box<[u64]> = value.iter().map(|d| d.swap_bytes()).collect();
916        #[cfg(target_endian = "big")]
917        let value = value.as_slice();
918
919        // SAFETY: reinterpreting a `&[u64]` as `&[u8]` is safe
920        dashu_int::UBig::from_le_bytes(unsafe {
921            std::slice::from_raw_parts(value.as_ptr().cast::<u8>(), mem::size_of_val(value))
922        })
923    }
924}
925
926impl TryFrom<&Natural> for dashu_int::UBig {
927    type Error = super::NotRepresentable;
928
929    fn try_from(value: &Natural) -> Result<Self, Self::Error> {
930        if value.shl > std::cmp::min(1 << 40, usize::MAX as u64) {
931            return Err(super::NotRepresentable); // covers NaN
932        }
933        let mut mantissa = to_u_big(value.mantissa());
934        mantissa <<= value.shl as usize;
935        Ok(mantissa)
936    }
937}
938
939impl TryFrom<&Natural> for u128 {
940    type Error = super::NotRepresentable;
941
942    fn try_from(value: &Natural) -> Result<Self, Self::Error> {
943        if value.shl < u128::BITS as u64
944            && let mantissa = value.mantissa_raw()
945            && mantissa.len() <= 3
946            && mantissa.len() as u32 * u64::BITS - mantissa.last().unwrap().leading_zeros()
947                + value.shl as u32
948                <= u128::BITS
949        {
950            let upper = mantissa.get(1).copied().unwrap_or_default();
951            return Ok(mantissa[0] as u128 | ((upper as u128) << u64::BITS));
952        }
953        Err(super::NotRepresentable)
954    }
955}
956impl TryFrom<&Natural> for u64 {
957    type Error = super::NotRepresentable;
958
959    fn try_from(value: &Natural) -> Result<Self, Self::Error> {
960        if value.shl < u64::BITS as u64
961            && value.ptr == DANGLING
962            && value.shl as u32 <= value.len.leading_zeros()
963        {
964            return Ok(value.len << value.shl);
965        }
966        Err(super::NotRepresentable)
967    }
968}
969impl From<&Natural> for f64 {
970    fn from(value: &Natural) -> Self {
971        const ZERO_OFFSET: u32 = 1023;
972        const MANTISSA_BITS: u32 = f64::MANTISSA_DIGITS - 1; // don't count the 1 from the integral part
973        const EXP_BITS: u32 = u64::BITS - MANTISSA_BITS - 1;
974
975        if value.is_nan() {
976            return f64::NAN;
977        }
978        let mantissa = value.mantissa();
979        let msd = *mantissa.last().unwrap();
980        if msd == 0 {
981            return 0.;
982        }
983        let leading_zeros = msd.leading_zeros();
984        let bit_width = (mantissa.len() as u64)
985            .saturating_mul(u64::BITS as u64)
986            .saturating_add(value.shl)
987            - leading_zeros as u64;
988        // 1 has bit width 1 but is 1×2⁰ → exponent is one less
989        if bit_width > f64::MAX_EXP as u64 {
990            return f64::INFINITY;
991        }
992        let exp = bit_width as u32 + ZERO_OFFSET - 1;
993        debug_assert!(exp < (1 << EXP_BITS) - 1);
994
995        let msd2 = if let [.., msd2, _] = *mantissa {
996            msd2
997        } else {
998            0
999        };
1000        // fractional part with the most significant bit truncated away; needs
1001        // to be shifted to the right
1002        let frac_trunc_msb = if msd != 1 {
1003            msd << (leading_zeros + 1) | msd2 >> (u64::BITS - (leading_zeros + 1))
1004        } else {
1005            msd2
1006        };
1007        let shr = u64::BITS - MANTISSA_BITS;
1008        let frac_trunc = frac_trunc_msb >> shr;
1009        let frac_rounded = frac_trunc
1010            + if bit_width - value.shl == f64::MANTISSA_DIGITS as u64 + 1 {
1011                frac_trunc & 1 // tie -> round to even
1012            } else {
1013                (frac_trunc_msb >> (shr - 1)) & 1
1014            };
1015        debug_assert!(frac_rounded <= 1 << MANTISSA_BITS);
1016        // `frac_rounded` may now be `1 << MANTISSA_BITS`, but this is
1017        // fine: we will just get the next exponent or +inf.
1018        f64::from_bits(((exp as u64) << MANTISSA_BITS) + frac_rounded)
1019    }
1020}
1021
1022fn fmt_nan(f: &mut fmt::Formatter<'_>) -> fmt::Result {
1023    if let Some(width) = f.width()
1024        && width >= 2
1025    {
1026        let w = width - 1;
1027        let c = f.fill();
1028        match f.align() {
1029            Some(fmt::Alignment::Left) => {
1030                f.write_char('?')?;
1031                for _ in 0..w {
1032                    f.write_char(c)?;
1033                }
1034            }
1035            Some(fmt::Alignment::Center) => {
1036                let first_half = w / 2;
1037                for _ in 0..first_half {
1038                    f.write_char(c)?;
1039                }
1040                f.write_char('?')?;
1041                for _ in 0..(w - first_half) {
1042                    f.write_char(c)?;
1043                }
1044            }
1045            _ => {
1046                for _ in 0..w {
1047                    f.write_char(c)?;
1048                }
1049                f.write_char('?')?;
1050            }
1051        }
1052        Ok(())
1053    } else {
1054        f.write_char('?')
1055    }
1056}
1057
1058impl fmt::Display for Natural {
1059    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1060        match dashu_int::UBig::try_from(self) {
1061            Ok(num) => num.fmt(f),
1062            Err(_) => fmt_nan(f),
1063        }
1064    }
1065}
1066
1067/// Re-implementation of [`fmt::Formatter::pad_integral()`] that does not force
1068/// us to write all digits to a buffer first
1069#[inline]
1070fn pad_integral(
1071    f: &mut fmt::Formatter<'_>,
1072    digits: u128,
1073    prefix: &str,
1074    write_digits: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
1075) -> fmt::Result {
1076    let prefix_width = f.alternate() as usize * prefix.len() + f.sign_plus() as usize;
1077    let min_digits = f.width().unwrap_or(0).saturating_sub(prefix_width);
1078    let mut pad = match usize::try_from(digits) {
1079        Ok(digits) => min_digits.saturating_sub(digits),
1080        Err(_) => 0,
1081    };
1082
1083    if pad != 0 && f.sign_aware_zero_pad() {
1084        for _ in 0..pad {
1085            f.write_char('0')?;
1086        }
1087        pad = 0;
1088    }
1089
1090    if f.sign_plus() {
1091        f.write_char('+')?;
1092    }
1093    if f.alternate() {
1094        f.write_str(prefix)?;
1095    }
1096
1097    let fill_char = f.fill();
1098    if pad != 0 {
1099        let pad_front = match f.align() {
1100            Some(fmt::Alignment::Left) => 0,
1101            Some(fmt::Alignment::Center) => pad / 2,
1102            _ => pad,
1103        };
1104        pad -= pad_front;
1105        for _ in 0..pad_front {
1106            f.write_char(fill_char)?;
1107        }
1108    }
1109
1110    write_digits(f)?;
1111
1112    for _ in 0..pad {
1113        f.write_char(fill_char)?;
1114    }
1115
1116    Ok(())
1117}
1118
1119impl fmt::Binary for Natural {
1120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1121        if self.is_nan() {
1122            return fmt_nan(f);
1123        }
1124
1125        let mantissa = self.mantissa();
1126        let bit_width = bit_width(mantissa, self.shl);
1127
1128        pad_integral(f, bit_width, "0b", move |f| {
1129            let msd = *mantissa.last().unwrap();
1130            if msd == 0 {
1131                return f.write_char('0');
1132            }
1133
1134            let mut pos = u64::BITS - msd.leading_zeros();
1135            for &d in mantissa.iter().rev() {
1136                while pos != 0 {
1137                    pos -= 1;
1138                    f.write_char(if d & (1 << pos) != 0 { '1' } else { '0' })?;
1139                }
1140                pos = u64::BITS;
1141            }
1142
1143            for _ in 0..self.shl {
1144                f.write_char('0')?;
1145            }
1146            Ok(())
1147        })
1148    }
1149}
1150
1151impl Natural {
1152    #[inline] // for constant propagation
1153    fn fmt_pow2(
1154        &self,
1155        f: &mut fmt::Formatter<'_>,
1156        bits_per_digit: u32,
1157        prefix: &str,
1158        to_char: impl Fn(u8) -> char,
1159    ) -> fmt::Result {
1160        debug_assert!(bits_per_digit < u64::BITS);
1161        if self.is_nan() {
1162            return fmt_nan(f);
1163        }
1164
1165        let mut mantissa = self.mantissa();
1166        let bit_width = bit_width(mantissa, self.shl);
1167        let digits = bit_width.div_ceil(bits_per_digit as u128);
1168        let rem_bits = (bit_width % bits_per_digit as u128) as u32;
1169
1170        pad_integral(f, digits, prefix, move |f| {
1171            let mut msd = *mantissa.split_off_last().unwrap();
1172            if msd == 0 {
1173                return f.write_char('0');
1174            }
1175            // 0001010101 0000
1176            //  ^  |  |   |  |
1177
1178            let rem_bits = if rem_bits == 0 {
1179                bits_per_digit
1180            } else {
1181                rem_bits
1182            };
1183            let mut offset = (u64::BITS - msd.leading_zeros()) as i32 - rem_bits as i32;
1184            let mut done = false;
1185            while !done {
1186                let digit = if offset >= 0 {
1187                    msd >> offset
1188                } else {
1189                    let upper = msd << offset.abs();
1190                    offset += u64::BITS as i32;
1191
1192                    if let Some(v) = mantissa.split_off_last() {
1193                        msd = *v;
1194                        upper | (msd >> offset)
1195                    } else if offset == (u64::BITS - bits_per_digit) as i32 {
1196                        break;
1197                    } else {
1198                        done = true;
1199                        upper
1200                    }
1201                } & ((1 << bits_per_digit) - 1);
1202                f.write_char(to_char(digit as u8))?;
1203                offset -= bits_per_digit as i32;
1204            }
1205
1206            let trailing_zeros = self.shl / bits_per_digit as u64;
1207            for _ in 0..trailing_zeros {
1208                f.write_char('0')?;
1209            }
1210
1211            Ok(())
1212        })
1213    }
1214}
1215
1216impl fmt::Octal for Natural {
1217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1218        self.fmt_pow2(f, 3, "0o", |d| (b'0' + d) as char)
1219    }
1220}
1221impl fmt::LowerHex for Natural {
1222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1223        self.fmt_pow2(f, 4, "0x", |d| {
1224            (if d < 10 { b'0' + d } else { b'a' + (d - 10) }) as char
1225        })
1226    }
1227}
1228impl fmt::UpperHex for Natural {
1229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1230        self.fmt_pow2(f, 4, "0x", |d| {
1231            (if d < 10 { b'0' + d } else { b'A' + (d - 10) }) as char
1232        })
1233    }
1234}
1235
1236impl fmt::Debug for Natural {
1237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1238        if self.is_nan() {
1239            return fmt_nan(f);
1240        }
1241
1242        let mantissa = self.mantissa();
1243        if let [d] = mantissa {
1244            d.fmt(f)?;
1245        } else {
1246            to_u_big(mantissa).fmt(f)?;
1247        }
1248        f.write_str(" * 2^")?;
1249        self.shl.fmt(f)
1250    }
1251}
1252
1253#[cfg(test)]
1254mod test {
1255    use super::Natural;
1256    use std::fmt::Write as _;
1257
1258    #[test]
1259    fn test_from_clone_and_shift_small() {
1260        let zero = Natural::from(0u32);
1261        zero.check_inv();
1262        assert_eq!(zero, Natural::ZERO);
1263
1264        let clone = zero.clone();
1265        clone.check_inv();
1266        assert_eq!(clone, Natural::ZERO);
1267
1268        let mut clone = clone << 1u64;
1269        clone.check_inv();
1270        assert_eq!(clone, Natural::ZERO);
1271
1272        let one = Natural::from(1u64);
1273        one.check_inv();
1274        assert_ne!(one, Natural::ZERO);
1275        assert!(one > Natural::ZERO);
1276
1277        let two = Natural::from(2u64);
1278        two.check_inv();
1279        assert_ne!(two, one);
1280        assert!(two > one);
1281
1282        clone.clone_from(&one);
1283        clone.check_inv();
1284        assert_eq!(clone, one);
1285
1286        let clone = clone << 1u32;
1287        clone.check_inv();
1288        assert_eq!(clone, two);
1289    }
1290
1291    #[test]
1292    fn test_from_le_digits() {
1293        for slice in [[].as_slice(), &[0], &[0, 0]] {
1294            let num = Natural::from_le_digits(slice);
1295            num.check_inv();
1296            assert_eq!(num, Natural::ZERO);
1297        }
1298
1299        let one = Natural::from(1u32);
1300        for slice in [[1].as_slice(), &[1, 0]] {
1301            let num = Natural::from_le_digits(slice);
1302            num.check_inv();
1303            assert_eq!(num, one);
1304        }
1305
1306        let two = Natural::from(2u32);
1307        let num = Natural::from_le_digits(&[2]);
1308        num.check_inv();
1309        assert_eq!(num, two);
1310
1311        let a = one.clone() << u64::BITS;
1312        let b = Natural::from_le_digits(&[0, 1]);
1313        b.check_inv();
1314        assert_eq!(a, b);
1315
1316        let a = Natural::from(0b11u32) << (2 * u64::BITS - 1);
1317        let b = Natural::from_le_digits(&[0, 1 << (u64::BITS - 1), 1]);
1318        b.check_inv();
1319        assert_eq!(a, b);
1320
1321        let half_bits = u64::BITS / 2;
1322        let a = Natural::from_le_digits(&[!0 << half_bits, !0, !0 >> half_bits]);
1323        a.check_inv();
1324        let b = Natural::from_le_digits(&[!0, !0]);
1325        b.check_inv();
1326        let b = b << half_bits;
1327        b.check_inv();
1328        assert_eq!(a, b);
1329
1330        let half1_bits = u64::BITS / 2 - 1;
1331        let a = Natural::from_le_digits(&[!0 << half1_bits, !0, !0 >> half1_bits]);
1332        a.check_inv();
1333        let b = Natural::from_le_digits(&[!0, !0, 0b11]);
1334        b.check_inv();
1335        let b = b << half1_bits;
1336        b.check_inv();
1337        assert_eq!(a, b);
1338    }
1339
1340    #[test]
1341    fn test_add() {
1342        for shl in [0, 1, u64::BITS - 1] {
1343            let case = |lhs: Natural, rhs: Natural, sum: Natural| {
1344                let lhs = lhs << shl;
1345                let rhs = rhs << shl;
1346                let expected = sum << shl;
1347                let actual = lhs.clone() + rhs.clone();
1348                actual.check_inv();
1349                assert_eq!(actual, expected);
1350                let actual_rev = rhs + lhs;
1351                actual_rev.check_inv();
1352                assert_eq!(actual_rev, expected);
1353            };
1354
1355            // --- zero operand ---
1356            case(1u32.into(), Natural::ZERO, 1u32.into());
1357            case(u64::MAX.into(), Natural::ZERO, u64::MAX.into());
1358            case(
1359                Natural::from_le_digits(&[1, 1]),
1360                Natural::ZERO,
1361                Natural::from_le_digits(&[1, 1]),
1362            );
1363
1364            // --- same shl for both operands ---
1365            case(1u32.into(), 1u32.into(), 2u32.into());
1366
1367            let a = Natural::from_le_digits(&[!0, 1]);
1368            case(a.clone(), a.clone(), a << 1u32);
1369
1370            case(
1371                u64::MAX.into(),
1372                1u32.into(),
1373                Natural::from(1u32) << u64::BITS,
1374            );
1375
1376            case(
1377                u64::MAX.into(),
1378                u64::MAX.into(),
1379                Natural::from_le_digits(&[u64::MAX << 1, 1]),
1380            );
1381
1382            case(
1383                u64::MAX.into(),
1384                Natural::from_le_digits(&[1, !0, 1]),
1385                Natural::from(1u32) << (2 * u64::BITS + 1),
1386            );
1387
1388            case(
1389                Natural::from_le_digits(&[1, 1 << (u64::BITS - 1)]),
1390                Natural::from_le_digits(&[u64::MAX, 1 << (u64::BITS - 1)]),
1391                Natural::from_le_digits(&[1, 1]) << u64::BITS,
1392            );
1393
1394            case(
1395                Natural::from_le_digits(&[1, 1]),
1396                Natural::from_le_digits(&[!0, !0, 1]),
1397                Natural::from_le_digits(&[1, 0b10]) << u64::BITS,
1398            );
1399
1400            case(
1401                Natural::from_le_digits(&[1, 1]),
1402                Natural::from_le_digits(&[!0, !0, !0]),
1403                Natural::from_le_digits(&[1, 0, 1]) << u64::BITS,
1404            );
1405
1406            case(
1407                Natural::from_le_digits(&[1, 1 << (u64::BITS - 1)]),
1408                Natural::from_le_digits(&[!0, !0, !0, 1]),
1409                Natural::from_le_digits(&[1, 0b100]) << (2 * u64::BITS - 1),
1410            );
1411
1412            case(
1413                Natural::from_le_digits(&[1, 1 << (u64::BITS - 1)]),
1414                Natural::from_le_digits(&[!0, !0, !0, u64::MAX >> 1]),
1415                Natural::from_le_digits(&[1, 0, 1]) << (2 * u64::BITS - 1),
1416            );
1417
1418            case(
1419                Natural::from_le_digits(&[1, 0, 1]),
1420                1u32.into(),
1421                Natural::from_le_digits(&[2, 0, 1]),
1422            );
1423
1424            // --- different shl ---
1425            case(1u32.into(), 2u32.into(), 3u32.into());
1426
1427            let max_bit: u64 = 1 << (u64::BITS - 1);
1428            case(
1429                (1 | max_bit).into(),
1430                (1 ^ u64::MAX).into(),
1431                Natural::from_le_digits(&[u64::MAX ^ max_bit, 1]),
1432            );
1433
1434            case(
1435                Natural::from_le_digits(&[0, 1]),
1436                1u32.into(),
1437                Natural::from_le_digits(&[1, 1]),
1438            );
1439
1440            case(
1441                Natural::from_le_digits(&[0, 2]),
1442                1u32.into(),
1443                Natural::from_le_digits(&[1, 2]),
1444            );
1445
1446            case(
1447                Natural::from_le_digits(&[1, 1]),
1448                Natural::from_le_digits(&[0, 2]),
1449                Natural::from_le_digits(&[1, 3]),
1450            );
1451
1452            case(
1453                Natural::from_le_digits(&[1, 1]),
1454                Natural::from_le_digits(&[0, 2, 1]),
1455                Natural::from_le_digits(&[1, 3, 1]),
1456            );
1457
1458            case(
1459                Natural::from_le_digits(&[1, 1]),
1460                Natural::from_le_digits(&[0, 2, 2]),
1461                Natural::from_le_digits(&[1, 3, 2]),
1462            );
1463
1464            case(
1465                Natural::from_le_digits(&[1, u64::MAX]),
1466                Natural::from_le_digits(&[0, 2, 1]),
1467                Natural::from_le_digits(&[1, 1, 2]),
1468            );
1469
1470            case(
1471                Natural::from_le_digits(&[!0]),
1472                Natural::from_le_digits(&[2, !0]),
1473                Natural::from_le_digits(&[1, 0, 1]),
1474            );
1475        }
1476    }
1477
1478    #[test]
1479    fn test_to_f64() {
1480        for val in 0..0x10000u64 {
1481            assert_eq!(f64::from(&Natural::from(val)), val as f64);
1482        }
1483        for shl in 52..60 {
1484            for val in ((1u64 << shl) - 0xf)..=((1 << shl) + 0xf) {
1485                assert_eq!(f64::from(&Natural::from(val)), val as f64, "{val}");
1486            }
1487        }
1488        assert_eq!(
1489            f64::from(&Natural::from_mantissa_single_with_shl(1, 1023)),
1490            2f64.powi(1023),
1491        );
1492        assert_eq!(
1493            f64::from(&Natural::from_mantissa_single_with_shl(1, 1024)),
1494            f64::INFINITY,
1495        );
1496    }
1497
1498    #[test]
1499    fn fmt_bin() -> std::fmt::Result {
1500        let mut buf = String::with_capacity(128);
1501
1502        write!(buf, "{:b}", Natural::from(0u32))?;
1503        assert_eq!(&buf, "0");
1504        buf.clear();
1505
1506        write!(buf, "{:#b}", Natural::from(0u32))?;
1507        assert_eq!(&buf, "0b0");
1508        buf.clear();
1509
1510        write!(buf, "{:b}", Natural::from(1u32))?;
1511        assert_eq!(&buf, "1");
1512        buf.clear();
1513
1514        write!(buf, "{:b}", Natural::from(2u32))?;
1515        assert_eq!(&buf, "10");
1516        buf.clear();
1517
1518        write!(buf, "{:b}", Natural::from(3u32))?;
1519        assert_eq!(&buf, "11");
1520        buf.clear();
1521
1522        write!(buf, "{:b}", Natural::from(4u32))?;
1523        assert_eq!(&buf, "100");
1524        buf.clear();
1525
1526        write!(buf, "{:b}", Natural::from_le_digits(&[1, 1]))?;
1527        assert_eq!(buf, format!("{:b}", (1u128 << 64) | 1));
1528        buf.clear();
1529
1530        Ok(())
1531    }
1532
1533    #[test]
1534    fn fmt_oct() -> std::fmt::Result {
1535        let mut buf = String::with_capacity(16);
1536
1537        write!(buf, "{:o}", Natural::from(0u32))?;
1538        assert_eq!(&buf, "0");
1539        buf.clear();
1540
1541        write!(buf, "{:#o}", Natural::from(0u32))?;
1542        assert_eq!(&buf, "0o0");
1543        buf.clear();
1544
1545        write!(buf, "{:o}", Natural::from(1u32))?;
1546        assert_eq!(&buf, "1");
1547        buf.clear();
1548
1549        write!(buf, "{:o}", Natural::from(9u32))?;
1550        assert_eq!(&buf, "11");
1551        buf.clear();
1552
1553        write!(buf, "{:o}", Natural::from(0o71u32))?;
1554        assert_eq!(&buf, "71");
1555        buf.clear();
1556
1557        write!(buf, "{:o}", Natural::from(0o72u32))?;
1558        assert_eq!(&buf, "72");
1559        buf.clear();
1560
1561        write!(buf, "{:o}", Natural::from(0o74u32))?;
1562        assert_eq!(&buf, "74");
1563        buf.clear();
1564
1565        Ok(())
1566    }
1567
1568    #[test]
1569    fn fmt_hex() -> std::fmt::Result {
1570        let mut buf = String::with_capacity(16);
1571
1572        write!(buf, "{:x}", Natural::from(0u32))?;
1573        assert_eq!(&buf, "0");
1574        buf.clear();
1575
1576        write!(buf, "{:#x}", Natural::from(0u32))?;
1577        assert_eq!(&buf, "0x0");
1578        buf.clear();
1579
1580        write!(buf, "{:x}", Natural::from(1u32))?;
1581        assert_eq!(&buf, "1");
1582        buf.clear();
1583
1584        write!(buf, "{:x}", Natural::from(0xau32))?;
1585        assert_eq!(&buf, "a");
1586        buf.clear();
1587
1588        write!(buf, "{:X}", Natural::from(0xau32))?;
1589        assert_eq!(&buf, "A");
1590        buf.clear();
1591
1592        write!(buf, "{:x}", Natural::from(0xf1u32))?;
1593        assert_eq!(&buf, "f1");
1594        buf.clear();
1595
1596        write!(buf, "{:x}", Natural::from(0xf2u32))?;
1597        assert_eq!(&buf, "f2");
1598        buf.clear();
1599
1600        write!(buf, "{:x}", Natural::from(0xf4u32))?;
1601        assert_eq!(&buf, "f4");
1602        buf.clear();
1603
1604        write!(buf, "{:x}", Natural::from(0xf8u32))?;
1605        assert_eq!(&buf, "f8");
1606        buf.clear();
1607
1608        Ok(())
1609    }
1610}