1use crate::traits::Digit;
4
5use core::cmp::Ordering;
6
7pub(crate) mod fmt;
8pub(crate) mod froms;
9pub(crate) mod ops;
10
11mod digits_vec;
12use digits_vec::Digits;
13
14#[cfg(test)]
15mod test;
16
17#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct BigUint<T: Digit> {
26 pub(crate) val: Vec<T>,
27}
28
29impl<T: Digit> BigUint<T> {
30 pub fn new(val: T) -> BigUint<T> {
34 BigUint { val: vec![val] }
35 }
36
37 #[inline]
45 pub fn with_capacity(mut self, capacity: usize) -> BigUint<T> {
46 self.set_capacity(capacity);
47 self
48 }
49
50 #[inline]
59 pub fn set_capacity(&mut self, capacity: usize) {
60 if capacity > 0 {
61 let target_length = (capacity - 1) / T::NB_BITS + 1;
62 let reserve = target_length.max(self.val.len()) - self.val.len();
63 self.val.reserve(reserve);
64 }
65 }
66
67 #[inline]
75 pub fn capacity(&self) -> usize {
76 self.val.capacity() * T::NB_BITS
77 }
78
79 #[inline]
81 pub fn nb_bits(&self) -> usize {
82 nb_bits(&self.val)
83 }
84
85 #[inline]
89 pub fn bit(&self, b: usize) -> bool {
90 if b >= self.val.len() * T::NB_BITS {
91 false
92 } else {
93 (self.val[b / T::NB_BITS] >> b % T::NB_BITS) & T::ONE != T::ZERO
94 }
95 }
96
97 #[inline]
101 pub fn set_bit(&mut self, b: usize, val: bool) {
102 if val {
103 self.val
104 .resize((b / T::NB_BITS + 1).max(self.val.len()), T::ZERO);
105 let mask = T::ONE << (b % T::NB_BITS);
106 self.val[b / T::NB_BITS] |= mask;
107 } else {
108 let mask = T::MAX - (T::ONE << (b % T::NB_BITS));
109 self.val[b / T::NB_BITS] &= mask;
110 self.remove_leading_zeros();
111 }
112 }
113
114 #[inline]
117 pub fn bits(&self) -> impl DoubleEndedIterator<Item = bool> + '_ {
118 (0..self.nb_bits()).map(|b| self.bit(b))
119 }
120
121 pub fn copy_from(&mut self, other: &Self) {
123 self.val.resize(other.val.len(), T::ZERO);
124 self.val[..].copy_from_slice(&other.val[..]);
125 }
126
127 #[inline]
130 pub(crate) fn remove_leading_zeros(&mut self) {
131 let count = self.val.len() - self.val.iter().rev().take_while(|n| **n == T::ZERO).count();
132 self.val.truncate(std::cmp::max(count, 1));
133 }
134
135 #[inline]
136 pub(crate) fn ord(&self, other: &[T]) -> Ordering {
137 ord(&self.val, other)
138 }
139}
140
141#[inline]
142pub(crate) fn nb_bits<T: Digit>(a: &[T]) -> usize {
143 match a.last() {
144 None => 0,
145 Some(last) => T::NB_BITS * (a.len() - 1) + (T::NB_BITS - last.leading_zeros() as usize),
146 }
147}
148
149#[inline]
150pub(crate) fn ord<T: Digit>(a: &[T], b: &[T]) -> Ordering {
151 let mut a_len = a.len();
152 while a_len > 0 && a[a_len - 1] == T::ZERO {
153 a_len -= 1;
154 }
155 let mut b_len = b.len();
156 while b_len > 0 && b[b_len - 1] == T::ZERO {
157 b_len -= 1;
158 }
159
160 match a_len.cmp(&b_len) {
161 Ordering::Equal => (),
162 o => return o,
163 };
164 for (a, b) in a[..a_len].iter().zip(b[..b_len].iter()).rev() {
165 match a.cmp(b) {
166 Ordering::Equal => continue,
167 o => return o,
168 };
169 }
170 Ordering::Equal
171}
172
173impl<T: Digit> Default for BigUint<T> {
175 fn default() -> BigUint<T> {
176 BigUint::new(T::ZERO)
177 }
178}
179
180impl<T: Digit> std::hash::Hash for BigUint<T> {
181 fn hash<H>(&self, state: &mut H)
182 where
183 H: std::hash::Hasher,
184 {
185 self.val.hash(state);
186 }
187}
188
189impl<T: Digit> PartialOrd<BigUint<T>> for BigUint<T> {
190 fn partial_cmp(&self, other: &BigUint<T>) -> Option<Ordering> {
191 Some(self.cmp(other))
192 }
193}
194
195impl<T: Digit> Ord for BigUint<T> {
196 fn cmp(&self, other: &BigUint<T>) -> Ordering {
197 self.ord(&other.val)
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use crate::biguint::ord;
204 use crate::traits::Digit;
205 use core::cmp::Ordering;
206
207 use typed_test_gen::test_with;
208
209 #[test_with(u32, u64)]
210 fn test_ord<T: Digit>() {
211 let a = [T::ONE, T::ONE, T::ZERO, T::ZERO];
212 let b = [T::ONE, T::ONE, T::ONE];
213 assert_eq!(ord(&a, &b), Ordering::Less);
214
215 let a = [T::ONE, T::ONE, T::ONE, T::ZERO];
216 let b = [T::ONE, T::ONE, T::ONE];
217 assert_eq!(ord(&a, &b), Ordering::Equal);
218
219 let a = [T::ONE, T::ONE, T::ONE, T::ZERO];
220 let b = [T::ONE, T::ZERO, T::ONE];
221 assert_eq!(ord(&a, &b), Ordering::Greater);
222 }
223}