1use std::cmp::Ordering;
19
20#[derive(Clone, Debug, Default, PartialEq, Eq)]
22pub struct BigUint {
23 limbs: Vec<u64>,
24}
25
26impl From<u64> for BigUint {
27 fn from(v: u64) -> BigUint {
28 let mut b = BigUint { limbs: vec![v] };
29 b.trim();
30 b
31 }
32}
33
34impl BigUint {
35 fn trim(&mut self) {
36 while self.limbs.last() == Some(&0) {
37 self.limbs.pop();
38 }
39 }
40
41 pub fn is_zero(&self) -> bool {
43 self.limbs.is_empty()
44 }
45
46 pub fn bits(&self) -> usize {
48 self.limbs.last().map_or(0, |top| 64 * (self.limbs.len() - 1) + (64 - top.leading_zeros() as usize))
49 }
50
51 #[must_use]
53 pub fn mul_small(&self, k: u64) -> BigUint {
54 let mut out = Vec::with_capacity(self.limbs.len() + 1);
55 let mut carry = 0u128;
56 for &l in &self.limbs {
57 let v = u128::from(l) * u128::from(k) + carry;
58 out.push(v as u64);
59 carry = v >> 64;
60 }
61 if carry > 0 {
62 out.push(carry as u64);
63 }
64 let mut b = BigUint { limbs: out };
65 b.trim();
66 b
67 }
68
69 #[must_use]
74 pub fn div_small(&self, k: u64) -> (BigUint, u64) {
75 assert!(k != 0, "division by zero");
76 let mut out = vec![0u64; self.limbs.len()];
77 let mut rem = 0u128;
78 for (i, &l) in self.limbs.iter().enumerate().rev() {
79 let v = (rem << 64) | u128::from(l);
80 out[i] = (v / u128::from(k)) as u64;
81 rem = v % u128::from(k);
82 }
83 let mut b = BigUint { limbs: out };
84 b.trim();
85 (b, rem as u64)
86 }
87
88 #[must_use]
90 pub fn add(&self, o: &BigUint) -> BigUint {
91 let n = self.limbs.len().max(o.limbs.len());
92 let mut out = Vec::with_capacity(n + 1);
93 let mut carry = 0u128;
94 for i in 0..n {
95 let v = u128::from(*self.limbs.get(i).unwrap_or(&0)) + u128::from(*o.limbs.get(i).unwrap_or(&0)) + carry;
96 out.push(v as u64);
97 carry = v >> 64;
98 }
99 if carry > 0 {
100 out.push(carry as u64);
101 }
102 let mut b = BigUint { limbs: out };
103 b.trim();
104 b
105 }
106
107 #[must_use]
112 pub fn sub(&self, o: &BigUint) -> BigUint {
113 assert!(*self >= *o, "negative difference");
114 let mut out = Vec::with_capacity(self.limbs.len());
115 let mut borrow = 0u64;
116 for (i, &l) in self.limbs.iter().enumerate() {
117 let r = *o.limbs.get(i).unwrap_or(&0);
118 let (d1, b1) = l.overflowing_sub(r);
119 let (d2, b2) = d1.overflowing_sub(borrow);
120 out.push(d2);
121 borrow = u64::from(b1 || b2);
122 }
123 let mut b = BigUint { limbs: out };
124 b.trim();
125 b
126 }
127
128 pub fn from_bits(bits: &[u8]) -> BigUint {
130 let mut limbs = vec![0u64; bits.len().div_ceil(64)];
131 for (i, &b) in bits.iter().rev().enumerate() {
132 if b != 0 {
133 limbs[i / 64] |= 1 << (i % 64);
134 }
135 }
136 let mut v = BigUint { limbs };
137 v.trim();
138 v
139 }
140
141 pub fn to_bits(&self, n: usize) -> Vec<u8> {
143 (0..n).rev().map(|i| self.limbs.get(i / 64).map_or(0, |l| ((l >> (i % 64)) & 1) as u8)).collect()
144 }
145}
146
147impl PartialOrd for BigUint {
148 fn partial_cmp(&self, o: &BigUint) -> Option<Ordering> {
149 Some(self.cmp(o))
150 }
151}
152
153impl Ord for BigUint {
154 fn cmp(&self, o: &BigUint) -> Ordering {
155 self.limbs.len().cmp(&o.limbs.len()).then_with(|| self.limbs.iter().rev().cmp(o.limbs.iter().rev()))
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn arithmetic_agrees_with_u128() {
165 let vals: [u128; 5] = [0, 1, 0xFFFF_FFFF_FFFF_FFFF, 0x1_0000_0000_0000_0001, 12_345_678_901_234_567_890_123];
166 let big = |v: u128| BigUint::from_bits(&(0..128).rev().map(|i| ((v >> i) & 1) as u8).collect::<Vec<_>>());
167 let val = |b: &BigUint| b.to_bits(128).iter().fold(0u128, |a, &x| (a << 1) | u128::from(x));
168 for &a in &vals {
169 for &b in &vals {
170 assert_eq!(val(&big(a).add(&big(b))), a.wrapping_add(b));
171 if a >= b {
172 assert_eq!(val(&big(a).sub(&big(b))), a - b);
173 }
174 assert_eq!(big(a).cmp(&big(b)), a.cmp(&b));
175 }
176 assert_eq!(val(&big(a).mul_small(977)), a * 977);
177 let (q, r) = big(a).div_small(977);
178 assert_eq!((val(&q), u128::from(r)), (a / 977, a % 977));
179 }
180 }
181}