/rust/registry/src/index.crates.io-1949cf8c6b5b557f/num-bigint-0.4.8/src/big_digit.rs
Line | Count | Source |
1 | | use alloc::vec::Vec; |
2 | | |
3 | | // A [`BigDigit`] is a [`BigUint`]'s composing element. |
4 | | cfg_digit!( |
5 | | pub(crate) type BigDigit = u32; |
6 | | pub(crate) type BigDigit = u64; |
7 | | ); |
8 | | |
9 | | // A [`DoubleBigDigit`] is the internal type used to do the computations. Its |
10 | | // size is the double of the size of [`BigDigit`]. |
11 | | cfg_digit!( |
12 | | pub(crate) type DoubleBigDigit = u64; |
13 | | pub(crate) type DoubleBigDigit = u128; |
14 | | ); |
15 | | |
16 | | pub(crate) const BITS: u8 = BigDigit::BITS as u8; |
17 | | pub(crate) const HALF_BITS: u8 = BITS / 2; |
18 | | pub(crate) const HALF: BigDigit = (1 << HALF_BITS) - 1; |
19 | | |
20 | | pub(crate) const MAX: BigDigit = BigDigit::MAX; |
21 | | const LO_MASK: DoubleBigDigit = MAX as DoubleBigDigit; |
22 | | |
23 | | #[inline] |
24 | 0 | fn get_hi(n: DoubleBigDigit) -> BigDigit { |
25 | 0 | (n >> BITS) as BigDigit |
26 | 0 | } |
27 | | #[inline] |
28 | 0 | fn get_lo(n: DoubleBigDigit) -> BigDigit { |
29 | 0 | (n & LO_MASK) as BigDigit |
30 | 0 | } |
31 | | |
32 | | /// Split one [`DoubleBigDigit`] into two [`BigDigit`]s. |
33 | | #[inline] |
34 | 0 | pub(crate) fn from_doublebigdigit(n: DoubleBigDigit) -> (BigDigit, BigDigit) { |
35 | 0 | (get_hi(n), get_lo(n)) |
36 | 0 | } |
37 | | |
38 | | /// Join two [`BigDigit`]s into one [`DoubleBigDigit`]. |
39 | | #[inline] |
40 | 0 | pub(crate) fn to_doublebigdigit(hi: BigDigit, lo: BigDigit) -> DoubleBigDigit { |
41 | 0 | DoubleBigDigit::from(lo) | (DoubleBigDigit::from(hi) << BITS) |
42 | 0 | } |
43 | | |
44 | | pub(crate) enum BigDigits { |
45 | | Inline(Option<BigDigit>), |
46 | | Heap(Vec<BigDigit>), |
47 | | } |
48 | | |
49 | | impl BigDigits { |
50 | | pub(crate) const ZERO: Self = BigDigits::Inline(None); |
51 | | pub(crate) const ONE: Self = BigDigits::Inline(Some(1)); |
52 | | |
53 | | #[inline] |
54 | 0 | pub(crate) const fn from_digit(x: BigDigit) -> Self { |
55 | 0 | if x == 0 { |
56 | 0 | BigDigits::ZERO |
57 | | } else { |
58 | 0 | BigDigits::Inline(Some(x)) |
59 | | } |
60 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::from_digit Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::from_digit |
61 | | |
62 | | #[inline] |
63 | 0 | pub(crate) fn from_slice(slice: &[BigDigit]) -> Self { |
64 | 0 | match slice { |
65 | 0 | &[] => BigDigits::ZERO, |
66 | 0 | &[x] => BigDigits::Inline(Some(x)), |
67 | 0 | xs => BigDigits::Heap(xs.to_vec()), |
68 | | } |
69 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::from_slice Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::from_slice |
70 | | |
71 | | #[inline] |
72 | 0 | pub(crate) fn from_vec(xs: Vec<BigDigit>) -> Self { |
73 | 0 | BigDigits::Heap(xs) |
74 | 0 | } |
75 | | |
76 | | #[inline] |
77 | 0 | pub(crate) fn clear(&mut self) { |
78 | 0 | match self { |
79 | 0 | BigDigits::Inline(x) => *x = None, |
80 | 0 | BigDigits::Heap(xs) => xs.clear(), |
81 | | } |
82 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::clear Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::clear |
83 | | |
84 | | #[inline] |
85 | 0 | pub(crate) fn push(&mut self, y: BigDigit) { |
86 | 0 | match &mut *self { |
87 | 0 | BigDigits::Inline(x @ None) => *x = Some(y), |
88 | 0 | BigDigits::Inline(Some(x)) => *self = BigDigits::Heap([*x, y].to_vec()), |
89 | 0 | BigDigits::Heap(xs) => xs.push(y), |
90 | | } |
91 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::push Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::push |
92 | | |
93 | | #[inline] |
94 | 0 | pub(crate) fn pop(&mut self) -> Option<BigDigit> { |
95 | 0 | match self { |
96 | 0 | BigDigits::Inline(x) => x.take(), |
97 | 0 | BigDigits::Heap(xs) => xs.pop(), |
98 | | } |
99 | 0 | } |
100 | | |
101 | | #[inline] |
102 | 0 | pub(crate) fn last(&self) -> Option<&BigDigit> { |
103 | 0 | match self { |
104 | 0 | BigDigits::Inline(x) => x.as_ref(), |
105 | 0 | BigDigits::Heap(xs) => xs.last(), |
106 | | } |
107 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::last Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::last |
108 | | |
109 | | #[inline] |
110 | 0 | pub(crate) fn len(&self) -> usize { |
111 | 0 | match self { |
112 | 0 | BigDigits::Inline(None) => 0, |
113 | 0 | BigDigits::Inline(Some(_)) => 1, |
114 | 0 | BigDigits::Heap(xs) => xs.len(), |
115 | | } |
116 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::len Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::len |
117 | | |
118 | | #[inline] |
119 | 0 | pub(crate) fn is_empty(&self) -> bool { |
120 | 0 | match self { |
121 | 0 | BigDigits::Inline(None) => true, |
122 | 0 | BigDigits::Inline(Some(_)) => false, |
123 | 0 | BigDigits::Heap(xs) => xs.is_empty(), |
124 | | } |
125 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::is_empty Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::is_empty |
126 | | |
127 | | #[inline] |
128 | 0 | pub(crate) fn capacity(&self) -> usize { |
129 | 0 | match self { |
130 | 0 | BigDigits::Inline(_) => 1, |
131 | 0 | BigDigits::Heap(xs) => xs.capacity(), |
132 | | } |
133 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::capacity Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::capacity |
134 | | |
135 | | #[inline] |
136 | 0 | pub(crate) fn shrink(&mut self) { |
137 | 0 | if let BigDigits::Heap(xs) = self { |
138 | 0 | if xs.len() < xs.capacity() / 2 { |
139 | 0 | match **xs { |
140 | 0 | [] => *self = BigDigits::ZERO, |
141 | 0 | [x] => *self = BigDigits::Inline(Some(x)), |
142 | 0 | _ => xs.shrink_to(xs.len() + 1), |
143 | | } |
144 | 0 | } |
145 | 0 | } |
146 | 0 | } |
147 | | |
148 | | /// Returns `true` if the most-significant digit (if any) is nonzero. |
149 | | #[inline] |
150 | 0 | pub(crate) fn is_normal(&self) -> bool { |
151 | 0 | match self { |
152 | 0 | BigDigits::Inline(Some(0)) => false, |
153 | 0 | BigDigits::Inline(_) => true, |
154 | 0 | BigDigits::Heap(xs) => !matches!(**xs, [.., 0]), |
155 | | } |
156 | 0 | } |
157 | | |
158 | | /// Strips off trailing zero bigdigits - most algorithms require |
159 | | /// the most significant digit in the number to be nonzero. |
160 | | #[inline] |
161 | 0 | pub(crate) fn normalize(&mut self) { |
162 | 0 | match self { |
163 | 0 | BigDigits::Inline(x) => { |
164 | 0 | if let Some(0) = *x { |
165 | 0 | *x = None; |
166 | 0 | } |
167 | | } |
168 | 0 | BigDigits::Heap(xs) => { |
169 | 0 | if let [.., 0] = **xs { |
170 | 0 | let len = xs.iter().rposition(|&d| d != 0).map_or(0, |i| i + 1); |
171 | 0 | xs.truncate(len); |
172 | 0 | } |
173 | 0 | if xs.len() < xs.capacity() / 2 { |
174 | 0 | match **xs { |
175 | 0 | [] => *self = BigDigits::ZERO, |
176 | 0 | [x] => *self = BigDigits::Inline(Some(x)), |
177 | 0 | _ => xs.shrink_to(xs.len() + 1), |
178 | | } |
179 | 0 | } |
180 | | } |
181 | | } |
182 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::normalize Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::normalize |
183 | | |
184 | | #[inline] |
185 | 0 | pub(crate) fn truncate(&mut self, len: usize) { |
186 | 0 | match self { |
187 | 0 | BigDigits::Inline(x) => { |
188 | 0 | if len == 0 { |
189 | 0 | *x = None; |
190 | 0 | } |
191 | | } |
192 | 0 | BigDigits::Heap(xs) => xs.truncate(len), |
193 | | } |
194 | 0 | } |
195 | | |
196 | | #[inline] |
197 | 0 | pub(crate) fn drain_front(&mut self, len: usize) { |
198 | 0 | match self { |
199 | 0 | BigDigits::Inline(x) => { |
200 | 0 | assert!(len <= 1); |
201 | 0 | if len == 1 { |
202 | 0 | *x = None; |
203 | 0 | } |
204 | | } |
205 | 0 | BigDigits::Heap(xs) => { |
206 | 0 | xs.drain(..len); |
207 | 0 | } |
208 | | } |
209 | 0 | } |
210 | | |
211 | 0 | pub(crate) fn reserve(&mut self, additional: usize) { |
212 | 0 | match &mut *self { |
213 | 0 | BigDigits::Inline(opt_x) => { |
214 | 0 | let capacity = usize::from(opt_x.is_some()) + additional; |
215 | 0 | if capacity > 1 { |
216 | 0 | let mut vec = Vec::with_capacity(capacity); |
217 | 0 | if let Some(x) = *opt_x { |
218 | 0 | vec.push(x); |
219 | 0 | } |
220 | 0 | *self = BigDigits::Heap(vec); |
221 | 0 | } |
222 | | } |
223 | 0 | BigDigits::Heap(xs) => xs.reserve(additional), |
224 | | } |
225 | 0 | } |
226 | | |
227 | 0 | pub(crate) fn resize(&mut self, len: usize, value: BigDigit) { |
228 | 0 | match &mut *self { |
229 | 0 | BigDigits::Inline(x) => match len { |
230 | 0 | 0 => *x = None, |
231 | | 1 => { |
232 | 0 | if x.is_none() { |
233 | 0 | *x = Some(value); |
234 | 0 | } |
235 | | } |
236 | | _ => { |
237 | 0 | let mut xs = Vec::with_capacity(len); |
238 | 0 | if let Some(x) = *x { |
239 | 0 | xs.push(x); |
240 | 0 | } |
241 | 0 | xs.resize(len, value); |
242 | 0 | *self = BigDigits::Heap(xs); |
243 | | } |
244 | | }, |
245 | 0 | BigDigits::Heap(xs) => xs.resize(len, value), |
246 | | } |
247 | 0 | } |
248 | | |
249 | 0 | pub(crate) fn extend_from_slice(&mut self, ys: &[BigDigit]) { |
250 | 0 | match &mut *self { |
251 | 0 | BigDigits::Inline(None) => *self = BigDigits::from_slice(ys), |
252 | 0 | BigDigits::Inline(Some(x)) => { |
253 | 0 | let len = ys.len() + 1; |
254 | 0 | if len > 1 { |
255 | 0 | let mut xs = Vec::with_capacity(len); |
256 | 0 | xs.push(*x); |
257 | 0 | xs.extend_from_slice(ys); |
258 | 0 | *self = BigDigits::Heap(xs); |
259 | 0 | } |
260 | | } |
261 | 0 | BigDigits::Heap(xs) => xs.extend_from_slice(ys), |
262 | | } |
263 | 0 | } |
264 | | |
265 | 0 | pub(crate) fn extend<I>(&mut self, mut iter: I) |
266 | 0 | where |
267 | 0 | I: ExactSizeIterator<Item = BigDigit>, |
268 | | { |
269 | 0 | match &mut *self { |
270 | 0 | BigDigits::Inline(x) => { |
271 | 0 | if x.is_none() { |
272 | 0 | match iter.next() { |
273 | 0 | Some(y) => *x = Some(y), |
274 | 0 | None => return, |
275 | | } |
276 | 0 | } |
277 | 0 | if let Some(y) = iter.next() { |
278 | 0 | let len = iter.len().saturating_add(2); |
279 | 0 | let mut xs = Vec::with_capacity(len); |
280 | 0 | xs.push(x.unwrap()); |
281 | 0 | xs.push(y); |
282 | 0 | xs.extend(iter); |
283 | 0 | *self = BigDigits::Heap(xs); |
284 | 0 | } |
285 | | } |
286 | 0 | BigDigits::Heap(xs) => xs.extend(iter), |
287 | | } |
288 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Iter<u64>, num_bigint::bigint::bits::bitor_pos_neg::{closure#0}>>Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Iter<u64>, num_bigint::bigint::bits::bitand_neg_neg::{closure#0}>>Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Iter<u64>, num_bigint::bigint::bits::bitxor_neg_neg::{closure#0}>>Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Iter<u64>, num_bigint::bigint::bits::bitxor_neg_pos::{closure#0}>>Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Iter<u64>, num_bigint::bigint::bits::bitxor_pos_neg::{closure#0}>>Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::map::Map<core::slice::iter::Chunks<u32>, num_bigint::biguint::u32_chunk_to_u64>> Unexecuted instantiation: <num_bigint::big_digit::BigDigits>::extend::<core::iter::adapters::cloned::Cloned<core::slice::iter::Iter<u64>>> |
289 | | } |
290 | | |
291 | | impl Clone for BigDigits { |
292 | | #[inline] |
293 | 0 | fn clone(&self) -> Self { |
294 | 0 | match self { |
295 | 0 | BigDigits::Inline(x) => BigDigits::Inline(*x), |
296 | 0 | BigDigits::Heap(xs) => BigDigits::from_slice(xs), |
297 | | } |
298 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits as core::clone::Clone>::clone Unexecuted instantiation: <num_bigint::big_digit::BigDigits as core::clone::Clone>::clone |
299 | | |
300 | | #[inline] |
301 | 0 | fn clone_from(&mut self, source: &Self) { |
302 | 0 | match &mut *self { |
303 | | // Reuse the existing heap allocation if we have one. |
304 | 0 | BigDigits::Heap(xs) if xs.capacity() != 0 => { |
305 | 0 | xs.clear(); |
306 | 0 | xs.extend_from_slice(source); |
307 | 0 | } |
308 | | #[allow(clippy::assigning_clones)] |
309 | 0 | _ => *self = source.clone(), |
310 | | } |
311 | 0 | } |
312 | | } |
313 | | |
314 | | impl core::ops::Deref for BigDigits { |
315 | | type Target = [BigDigit]; |
316 | | |
317 | | #[inline] |
318 | 0 | fn deref(&self) -> &Self::Target { |
319 | 0 | match self { |
320 | 0 | BigDigits::Inline(None) => &[], |
321 | 0 | BigDigits::Inline(Some(x)) => core::slice::from_ref(x), |
322 | 0 | BigDigits::Heap(xs) => xs, |
323 | | } |
324 | 0 | } Unexecuted instantiation: <num_bigint::big_digit::BigDigits as core::ops::deref::Deref>::deref Unexecuted instantiation: <num_bigint::big_digit::BigDigits as core::ops::deref::Deref>::deref |
325 | | } |
326 | | |
327 | | impl core::ops::DerefMut for BigDigits { |
328 | | #[inline] |
329 | 0 | fn deref_mut(&mut self) -> &mut Self::Target { |
330 | 0 | match self { |
331 | 0 | BigDigits::Inline(None) => &mut [], |
332 | 0 | BigDigits::Inline(Some(x)) => core::slice::from_mut(x), |
333 | 0 | BigDigits::Heap(xs) => xs, |
334 | | } |
335 | 0 | } |
336 | | } |