1#![allow(missing_docs)] use core::cmp::Ordering;
9
10mod add;
11pub mod div;
12mod gcd;
13mod mul;
14#[cfg(feature = "alloc")] mod mul_redc;
16mod ops;
17mod shift;
18
19pub use self::{
20 add::{adc_n, sbb_n},
21 div::div,
22 gcd::{gcd, gcd_extended, inv_mod, LehmerMatrix},
23 mul::{add_nx1, addmul, addmul_n, addmul_nx1, addmul_ref, mul_nx1, submul_nx1},
24 ops::{adc, sbb},
25 shift::{shift_left_small, shift_right_small},
26};
27#[cfg(feature = "alloc")]
28pub use mul_redc::mul_redc;
29
30trait DoubleWord<T>: Sized + Copy {
31 fn join(high: T, low: T) -> Self;
32 fn add(a: T, b: T) -> Self;
33 fn mul(a: T, b: T) -> Self;
34 fn muladd(a: T, b: T, c: T) -> Self;
35 fn muladd2(a: T, b: T, c: T, d: T) -> Self;
36
37 fn high(self) -> T;
38 fn low(self) -> T;
39 fn split(self) -> (T, T);
40}
41
42impl DoubleWord<u64> for u128 {
43 #[inline(always)]
44 fn join(high: u64, low: u64) -> Self {
45 (Self::from(high) << 64) | Self::from(low)
46 }
47
48 #[inline(always)]
50 fn add(a: u64, b: u64) -> Self {
51 Self::from(a) + Self::from(b)
52 }
53
54 #[inline(always)]
56 fn mul(a: u64, b: u64) -> Self {
57 Self::from(a) * Self::from(b)
58 }
59
60 #[inline(always)]
63 fn muladd(a: u64, b: u64, c: u64) -> Self {
64 Self::from(a) * Self::from(b) + Self::from(c)
65 }
66
67 #[inline(always)]
70 fn muladd2(a: u64, b: u64, c: u64, d: u64) -> Self {
71 Self::from(a) * Self::from(b) + Self::from(c) + Self::from(d)
72 }
73
74 #[inline(always)]
75 fn high(self) -> u64 {
76 (self >> 64) as u64
77 }
78
79 #[inline(always)]
80 #[allow(clippy::cast_possible_truncation)]
81 fn low(self) -> u64 {
82 self as u64
83 }
84
85 #[inline(always)]
86 fn split(self) -> (u64, u64) {
87 (self.low(), self.high())
88 }
89}
90
91#[inline(always)]
93#[must_use]
94pub fn cmp(left: &[u64], right: &[u64]) -> Ordering {
95 let l = core::cmp::min(left.len(), right.len());
96
97 let lhs = &left[..l];
100 let rhs = &right[..l];
101
102 for i in (0..l).rev() {
103 match i8::from(lhs[i] > rhs[i]) - i8::from(lhs[i] < rhs[i]) {
104 -1 => return Ordering::Less,
105 0 => {}
106 1 => return Ordering::Greater,
107 _ => unsafe { core::hint::unreachable_unchecked() },
108 }
109
110 }
116
117 left.len().cmp(&right.len())
118}