Coverage Report

Created: 2026-08-14 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}