Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/lexical-parse-float-1.0.6/src/bigint.rs
Line
Count
Source
1
//! A simple big-integer type for slow path algorithms.
2
//!
3
//! This includes minimal stack vector for use in big-integer arithmetic.
4
5
#![doc(hidden)]
6
7
use core::{cmp, mem, ops, ptr, slice};
8
9
#[cfg(feature = "radix")]
10
use crate::float::ExtendedFloat80;
11
use crate::float::RawFloat;
12
use crate::limits::{u32_power_limit, u64_power_limit};
13
#[cfg(not(feature = "compact"))]
14
use crate::table::get_large_int_power;
15
16
/// Index an array without bounds checking.
17
///
18
/// # Safety
19
///
20
/// Safe if `index < array.len()`.
21
macro_rules! index_unchecked {
22
    ($x:ident[$i:expr]) => {
23
        // SAFETY: safe if `index < array.len()`.
24
        *$x.get_unchecked($i)
25
    };
26
}
27
28
// BIGINT
29
// ------
30
31
/// Number of bits in a Bigint.
32
///
33
/// This needs to be at least the number of bits required to store
34
/// a Bigint, which is `log2(radix**digits)`.
35
/// ≅ 5600 for base-36, rounded-up.
36
#[cfg(feature = "radix")]
37
const BIGINT_BITS: usize = 6000;
38
39
/// ≅ 3600 for base-10, rounded-up.
40
#[cfg(not(feature = "radix"))]
41
const BIGINT_BITS: usize = 4000;
42
43
/// The number of limbs for the bigint.
44
const BIGINT_LIMBS: usize = BIGINT_BITS / Limb::BITS as usize;
45
46
/// Storage for a big integer type.
47
///
48
/// This is used for algorithms when we have a finite number of digits.
49
/// Specifically, it stores all the significant digits scaled to the
50
/// proper exponent, as an integral type, and then directly compares
51
/// these digits.
52
///
53
/// This requires us to store the number of significant bits, plus the
54
/// number of exponent bits (required) since we scale everything
55
/// to the same exponent.
56
#[derive(Clone, PartialEq, Eq)]
57
pub struct Bigint {
58
    /// Significant digits for the float, stored in a big integer in LE order.
59
    ///
60
    /// This is pretty much the same number of digits for any radix, since the
61
    ///  significant digits balances out the zeros from the exponent:
62
    ///     1. Decimal is 1091 digits, 767 mantissa digits + 324 exponent zeros.
63
    ///     2. Base 6 is 1097 digits, or 680 mantissa digits + 417 exponent
64
    ///        zeros.
65
    ///     3. Base 36 is 1086 digits, or 877 mantissa digits + 209 exponent
66
    ///        zeros.
67
    ///
68
    /// However, the number of bytes required is larger for large radixes:
69
    /// for decimal, we need `log2(10**1091) ≅ 3600`, while for base 36
70
    /// we need `log2(36**1086) ≅ 5600`. Since we use uninitialized data,
71
    /// we avoid a major performance hit from the large buffer size.
72
    pub data: StackVec<BIGINT_LIMBS>,
73
}
74
75
impl Bigint {
76
    /// Construct a bigfloat representing 0.
77
    #[inline(always)]
78
1.37k
    pub const fn new() -> Self {
79
1.37k
        Self {
80
1.37k
            data: StackVec::new(),
81
1.37k
        }
82
1.37k
    }
83
84
    /// Construct a bigfloat from an integer.
85
    #[inline(always)]
86
0
    pub fn from_u32(value: u32) -> Self {
87
0
        Self {
88
0
            data: StackVec::from_u32(value),
89
0
        }
90
0
    }
91
92
    /// Construct a bigfloat from an integer.
93
    #[inline(always)]
94
868
    pub fn from_u64(value: u64) -> Self {
95
868
        Self {
96
868
            data: StackVec::from_u64(value),
97
868
        }
98
868
    }
99
100
    #[inline(always)]
101
507
    pub fn hi64(&self) -> (u64, bool) {
102
507
        self.data.hi64()
103
507
    }
104
105
    /// Multiply and assign as if by exponentiation by a power.
106
    #[inline(always)]
107
2.22k
    pub fn pow(&mut self, base: u32, exp: u32) -> Option<()> {
108
2.22k
        let (odd, shift) = split_radix(base);
109
2.22k
        if odd != 0 {
110
1.37k
            pow::<BIGINT_LIMBS>(&mut self.data, odd, exp)?;
111
853
        }
112
2.22k
        if shift != 0 {
113
1.36k
            shl(&mut self.data, (exp * shift) as usize)?;
114
868
        }
115
2.22k
        Some(())
116
2.22k
    }
117
118
    /// Calculate the bit-length of the big-integer.
119
    #[inline(always)]
120
507
    pub fn bit_length(&self) -> u32 {
121
507
        bit_length(&self.data)
122
507
    }
123
}
124
125
impl ops::MulAssign<&Bigint> for Bigint {
126
0
    fn mul_assign(&mut self, rhs: &Bigint) {
127
0
        self.data *= &rhs.data;
128
0
    }
129
}
130
131
impl Default for Bigint {
132
0
    fn default() -> Self {
133
0
        Self::new()
134
0
    }
135
}
136
137
/// Number of bits in a Bigfloat.
138
///
139
/// This needs to be at least the number of bits required to store
140
/// a Bigint, which is `F::EXPONENT_BIAS + F::BITS`.
141
/// Bias ≅ 1075, with 64 extra for the digits.
142
#[cfg(feature = "radix")]
143
const BIGFLOAT_BITS: usize = 1200;
144
145
/// The number of limbs for the Bigfloat.
146
#[cfg(feature = "radix")]
147
const BIGFLOAT_LIMBS: usize = BIGFLOAT_BITS / Limb::BITS as usize;
148
149
/// Storage for a big floating-point type.
150
///
151
/// This is used for the algorithm with a non-finite digit count, which creates
152
/// a representation of `b+h` and the float scaled into the range `[1, radix)`.
153
#[cfg(feature = "radix")]
154
#[derive(Clone, PartialEq, Eq)]
155
pub struct Bigfloat {
156
    /// Significant digits for the float, stored in a big integer in LE order.
157
    ///
158
    /// This only needs ~1075 bits for the exponent, and ~64 more for the
159
    /// significant digits, since it's based on a theoretical representation
160
    /// of the halfway point. This means we can have a significantly smaller
161
    /// representation. The largest 64-bit exponent in magnitude is 2^1074,
162
    /// which will produce the same number of bits in any radix.
163
    pub data: StackVec<BIGFLOAT_LIMBS>,
164
    /// Binary exponent for the float type.
165
    pub exp: i32,
166
}
167
168
#[cfg(feature = "radix")]
169
impl Bigfloat {
170
    /// Construct a bigfloat representing 0.
171
    #[inline(always)]
172
    pub const fn new() -> Self {
173
        Self {
174
            data: StackVec::new(),
175
            exp: 0,
176
        }
177
    }
178
179
    /// Construct a bigfloat from an extended-precision float.
180
    #[inline(always)]
181
    pub fn from_float(fp: ExtendedFloat80) -> Self {
182
        Self {
183
            data: StackVec::from_u64(fp.mant),
184
            exp: fp.exp,
185
        }
186
    }
187
188
    /// Construct a bigfloat from an integer.
189
    #[inline(always)]
190
    pub fn from_u32(value: u32) -> Self {
191
        Self {
192
            data: StackVec::from_u32(value),
193
            exp: 0,
194
        }
195
    }
196
197
    /// Construct a bigfloat from an integer.
198
    #[inline(always)]
199
    pub fn from_u64(value: u64) -> Self {
200
        Self {
201
            data: StackVec::from_u64(value),
202
            exp: 0,
203
        }
204
    }
205
206
    /// Multiply and assign as if by exponentiation by a power.
207
    #[inline(always)]
208
    pub fn pow(&mut self, base: u32, exp: u32) -> Option<()> {
209
        let (odd, shift) = split_radix(base);
210
        if odd != 0 {
211
            pow::<BIGFLOAT_LIMBS>(&mut self.data, odd, exp)?;
212
        }
213
        if shift != 0 {
214
            self.exp += (exp * shift) as i32;
215
        }
216
        Some(())
217
    }
218
219
    /// Shift-left the entire buffer n bits, where bits is less than the limb
220
    /// size.
221
    #[inline(always)]
222
    pub fn shl_bits(&mut self, n: usize) -> Option<()> {
223
        shl_bits(&mut self.data, n)
224
    }
225
226
    /// Shift-left the entire buffer n limbs.
227
    #[inline(always)]
228
    pub fn shl_limbs(&mut self, n: usize) -> Option<()> {
229
        shl_limbs(&mut self.data, n)
230
    }
231
232
    /// Shift-left the entire buffer n bits.
233
    #[inline(always)]
234
    pub fn shl(&mut self, n: usize) -> Option<()> {
235
        shl(&mut self.data, n)
236
    }
237
238
    /// Get number of leading zero bits in the storage.
239
    /// Assumes the value is normalized.
240
    #[inline(always)]
241
    pub fn leading_zeros(&self) -> u32 {
242
        leading_zeros(&self.data)
243
    }
244
}
245
246
#[cfg(feature = "radix")]
247
impl ops::MulAssign<&Bigfloat> for Bigfloat {
248
    #[inline(always)]
249
    #[allow(clippy::suspicious_op_assign_impl)] // reason="intended increment"
250
    #[allow(clippy::unwrap_used)] // reason="exceeding the bounds is a developer error"
251
    fn mul_assign(&mut self, rhs: &Bigfloat) {
252
        large_mul(&mut self.data, &rhs.data).unwrap();
253
        self.exp += rhs.exp;
254
    }
255
}
256
257
#[cfg(feature = "radix")]
258
impl Default for Bigfloat {
259
    fn default() -> Self {
260
        Self::new()
261
    }
262
}
263
264
// VEC
265
// ---
266
267
/// Simple stack vector implementation.
268
#[derive(Clone)]
269
pub struct StackVec<const SIZE: usize> {
270
    /// The raw buffer for the elements.
271
    data: [mem::MaybeUninit<Limb>; SIZE],
272
    /// The number of elements in the array (we never need more than
273
    /// `u16::MAX`).
274
    length: u16,
275
}
276
277
/// Extract the hi bits from the buffer.
278
///
279
/// NOTE: Modifying this to remove unsafety which we statically
280
/// check directly in every caller leads to ~20% degradation in
281
/// performance.
282
/// - `rview`   - A reversed view over a slice.
283
/// - `fn`      - The callback to extract the high bits.
284
macro_rules! hi {
285
    (@1 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{
286
        $fn(unsafe { index_unchecked!($rview[0]) as $t })
287
    }};
288
289
    // # Safety
290
    //
291
    // Safe as long as the `stackvec.len() >= 2`.
292
    (@2 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{
293
        let r0 = unsafe { index_unchecked!($rview[0]) as $t };
294
        let r1 = unsafe { index_unchecked!($rview[1]) as $t };
295
        $fn(r0, r1)
296
    }};
297
298
    // # Safety
299
    //
300
    // Safe as long as the `stackvec.len() >= 2`.
301
    (@nonzero2 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{
302
        let (v, n) = hi!(@2 $self, $rview, $t, $fn);
303
        (v, n || unsafe { nonzero($self, 2 ) })
304
    }};
305
306
    // # Safety
307
    //
308
    // Safe as long as the `stackvec.len() >= 3`.
309
    (@3 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{
310
        let r0 = unsafe { index_unchecked!($rview[0]) as $t };
311
        let r1 = unsafe { index_unchecked!($rview[1]) as $t };
312
        let r2 = unsafe { index_unchecked!($rview[2]) as $t };
313
        $fn(r0, r1, r2)
314
    }};
315
316
    // # Safety
317
    //
318
    // Safe as long as the `stackvec.len() >= 3`.
319
    (@nonzero3 $self:ident, $rview:ident, $t:ident, $fn:ident) => {{
320
        let (v, n) = hi!(@3 $self, $rview, $t, $fn);
321
        (v, n || unsafe { nonzero($self, 3 ) })
322
    }};
323
}
324
325
impl<const SIZE: usize> StackVec<SIZE> {
326
    /// Construct an empty vector.
327
    #[must_use]
328
    #[inline(always)]
329
2.52k
    pub const fn new() -> Self {
330
2.52k
        Self {
331
2.52k
            length: 0,
332
2.52k
            data: [mem::MaybeUninit::uninit(); SIZE],
333
2.52k
        }
334
2.52k
    }
<lexical_parse_float::bigint::StackVec<62>>::new
Line
Count
Source
329
2.24k
    pub const fn new() -> Self {
330
2.24k
        Self {
331
2.24k
            length: 0,
332
2.24k
            data: [mem::MaybeUninit::uninit(); SIZE],
333
2.24k
        }
334
2.24k
    }
<lexical_parse_float::bigint::StackVec<62>>::new
Line
Count
Source
329
282
    pub const fn new() -> Self {
330
282
        Self {
331
282
            length: 0,
332
282
            data: [mem::MaybeUninit::uninit(); SIZE],
333
282
        }
334
282
    }
335
336
    /// Get a mutable ptr to the current start of the big integer.
337
    #[must_use]
338
    #[inline(always)]
339
6.28k
    pub fn as_mut_ptr(&mut self) -> *mut Limb {
340
6.28k
        self.data.as_mut_ptr().cast::<Limb>()
341
6.28k
    }
<lexical_parse_float::bigint::StackVec<62>>::as_mut_ptr
Line
Count
Source
339
5.51k
    pub fn as_mut_ptr(&mut self) -> *mut Limb {
340
5.51k
        self.data.as_mut_ptr().cast::<Limb>()
341
5.51k
    }
<lexical_parse_float::bigint::StackVec<62>>::as_mut_ptr
Line
Count
Source
339
772
    pub fn as_mut_ptr(&mut self) -> *mut Limb {
340
772
        self.data.as_mut_ptr().cast::<Limb>()
341
772
    }
342
343
    /// Get a ptr to the current start of the big integer.
344
    #[must_use]
345
    #[inline(always)]
346
0
    pub fn as_ptr(&self) -> *const Limb {
347
0
        self.data.as_ptr().cast::<Limb>()
348
0
    }
349
350
    /// Construct a vector from an existing slice.
351
    #[must_use]
352
    #[inline(always)]
353
282
    pub fn try_from(x: &[Limb]) -> Option<Self> {
354
282
        let mut vec = Self::new();
355
282
        vec.try_extend(x)?;
356
282
        Some(vec)
357
282
    }
358
359
    /// Sets the length of a vector.
360
    ///
361
    /// This will explicitly set the size of the vector, without actually
362
    /// modifying its buffers, so it is up to the caller to ensure that the
363
    /// vector is actually the specified size.
364
    ///
365
    /// # Safety
366
    ///
367
    /// Safe as long as `len` is less than `SIZE`.
368
    #[inline(always)]
369
385
    pub unsafe fn set_len(&mut self, len: usize) {
370
385
        debug_assert!(len <= u16::MAX as usize, "indexing must fit in 16 bits");
371
385
        debug_assert!(len <= SIZE, "cannot exceed our array bounds");
372
385
        self.length = len as u16;
373
385
    }
<lexical_parse_float::bigint::StackVec<62>>::set_len
Line
Count
Source
369
103
    pub unsafe fn set_len(&mut self, len: usize) {
370
103
        debug_assert!(len <= u16::MAX as usize, "indexing must fit in 16 bits");
371
103
        debug_assert!(len <= SIZE, "cannot exceed our array bounds");
372
103
        self.length = len as u16;
373
103
    }
<lexical_parse_float::bigint::StackVec<62>>::set_len
Line
Count
Source
369
282
    pub unsafe fn set_len(&mut self, len: usize) {
370
282
        debug_assert!(len <= u16::MAX as usize, "indexing must fit in 16 bits");
371
282
        debug_assert!(len <= SIZE, "cannot exceed our array bounds");
372
282
        self.length = len as u16;
373
282
    }
374
375
    /// Get the number of elements stored in the vector.
376
    #[must_use]
377
    #[inline(always)]
378
31.4k
    pub const fn len(&self) -> usize {
379
31.4k
        self.length as usize
380
31.4k
    }
<lexical_parse_float::bigint::StackVec<62>>::len
Line
Count
Source
378
28.0k
    pub const fn len(&self) -> usize {
379
28.0k
        self.length as usize
380
28.0k
    }
<lexical_parse_float::bigint::StackVec<62>>::len
Line
Count
Source
378
3.44k
    pub const fn len(&self) -> usize {
379
3.44k
        self.length as usize
380
3.44k
    }
381
382
    /// If the vector is empty.
383
    #[must_use]
384
    #[inline(always)]
385
103
    pub const fn is_empty(&self) -> bool {
386
103
        self.len() == 0
387
103
    }
<lexical_parse_float::bigint::StackVec<62>>::is_empty
Line
Count
Source
385
103
    pub const fn is_empty(&self) -> bool {
386
103
        self.len() == 0
387
103
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::is_empty
388
389
    /// The number of items the vector can hold.
390
    #[must_use]
391
    #[inline(always)]
392
6.28k
    pub const fn capacity(&self) -> usize {
393
6.28k
        SIZE
394
6.28k
    }
<lexical_parse_float::bigint::StackVec<62>>::capacity
Line
Count
Source
392
5.51k
    pub const fn capacity(&self) -> usize {
393
5.51k
        SIZE
394
5.51k
    }
<lexical_parse_float::bigint::StackVec<62>>::capacity
Line
Count
Source
392
772
    pub const fn capacity(&self) -> usize {
393
772
        SIZE
394
772
    }
395
396
    /// Append an item to the vector, without bounds checking.
397
    ///
398
    /// # Safety
399
    ///
400
    /// Safe if `self.len() < self.capacity()`.
401
    #[inline(always)]
402
5.69k
    unsafe fn push_unchecked(&mut self, value: Limb) {
403
5.69k
        debug_assert!(self.len() < self.capacity(), "cannot exceed our array bounds");
404
        // SAFETY: safe, capacity is less than the current size.
405
5.69k
        unsafe {
406
5.69k
            let len = self.len();
407
5.69k
            let ptr = self.as_mut_ptr().add(len);
408
5.69k
            ptr.write(value);
409
5.69k
            self.length += 1;
410
5.69k
        }
411
5.69k
    }
<lexical_parse_float::bigint::StackVec<62>>::push_unchecked
Line
Count
Source
402
5.41k
    unsafe fn push_unchecked(&mut self, value: Limb) {
403
5.41k
        debug_assert!(self.len() < self.capacity(), "cannot exceed our array bounds");
404
        // SAFETY: safe, capacity is less than the current size.
405
5.41k
        unsafe {
406
5.41k
            let len = self.len();
407
5.41k
            let ptr = self.as_mut_ptr().add(len);
408
5.41k
            ptr.write(value);
409
5.41k
            self.length += 1;
410
5.41k
        }
411
5.41k
    }
<lexical_parse_float::bigint::StackVec<62>>::push_unchecked
Line
Count
Source
402
281
    unsafe fn push_unchecked(&mut self, value: Limb) {
403
281
        debug_assert!(self.len() < self.capacity(), "cannot exceed our array bounds");
404
        // SAFETY: safe, capacity is less than the current size.
405
281
        unsafe {
406
281
            let len = self.len();
407
281
            let ptr = self.as_mut_ptr().add(len);
408
281
            ptr.write(value);
409
281
            self.length += 1;
410
281
        }
411
281
    }
412
413
    /// Append an item to the vector.
414
    #[inline(always)]
415
5.69k
    pub fn try_push(&mut self, value: Limb) -> Option<()> {
416
5.69k
        if self.len() < self.capacity() {
417
            // SAFETY: safe, capacity is less than the current size.
418
5.69k
            unsafe { self.push_unchecked(value) };
419
5.69k
            Some(())
420
        } else {
421
0
            None
422
        }
423
5.69k
    }
<lexical_parse_float::bigint::StackVec<62>>::try_push
Line
Count
Source
415
5.41k
    pub fn try_push(&mut self, value: Limb) -> Option<()> {
416
5.41k
        if self.len() < self.capacity() {
417
            // SAFETY: safe, capacity is less than the current size.
418
5.41k
            unsafe { self.push_unchecked(value) };
419
5.41k
            Some(())
420
        } else {
421
0
            None
422
        }
423
5.41k
    }
<lexical_parse_float::bigint::StackVec<62>>::try_push
Line
Count
Source
415
281
    pub fn try_push(&mut self, value: Limb) -> Option<()> {
416
281
        if self.len() < self.capacity() {
417
            // SAFETY: safe, capacity is less than the current size.
418
281
            unsafe { self.push_unchecked(value) };
419
281
            Some(())
420
        } else {
421
0
            None
422
        }
423
281
    }
424
425
    /// Remove an item from the end of a vector, without bounds checking.
426
    ///
427
    /// # Safety
428
    ///
429
    /// Safe if `self.len() > 0`.
430
    #[inline(always)]
431
0
    unsafe fn pop_unchecked(&mut self) -> Limb {
432
0
        debug_assert!(!self.is_empty(), "cannot pop a value if none exists");
433
0
        self.length -= 1;
434
        // SAFETY: safe if `self.length > 0`.
435
        // We have a trivial drop and copy, so this is safe.
436
0
        unsafe { ptr::read(self.as_mut_ptr().add(self.len())) }
437
0
    }
438
439
    /// Remove an item from the end of the vector and return it, or None if
440
    /// empty.
441
    #[inline(always)]
442
0
    pub fn pop(&mut self) -> Option<Limb> {
443
0
        if self.is_empty() {
444
0
            None
445
        } else {
446
            // SAFETY: safe, since `self.len() > 0`.
447
0
            unsafe { Some(self.pop_unchecked()) }
448
        }
449
0
    }
450
451
    /// Add items from a slice to the vector, without bounds checking.
452
    ///
453
    /// # Safety
454
    ///
455
    /// Safe if `self.len() + slc.len() <= self.capacity()`.
456
    #[inline(always)]
457
282
    unsafe fn extend_unchecked(&mut self, slc: &[Limb]) {
458
282
        let index = self.len();
459
282
        let new_len = index + slc.len();
460
282
        debug_assert!(self.len() + slc.len() <= self.capacity(), "cannot exceed our array bounds");
461
282
        let src = slc.as_ptr();
462
        // SAFETY: safe if `self.len() + slc.len() <= self.capacity()`.
463
282
        unsafe {
464
282
            let dst = self.as_mut_ptr().add(index);
465
282
            ptr::copy_nonoverlapping(src, dst, slc.len());
466
282
            self.set_len(new_len);
467
282
        }
468
282
    }
469
470
    /// Copy elements from a slice and append them to the vector.
471
    #[inline(always)]
472
282
    pub fn try_extend(&mut self, slc: &[Limb]) -> Option<()> {
473
282
        if self.len() + slc.len() <= self.capacity() {
474
            // SAFETY: safe, since `self.len() + slc.len() <= self.capacity()`.
475
282
            unsafe { self.extend_unchecked(slc) };
476
282
            Some(())
477
        } else {
478
0
            None
479
        }
480
282
    }
481
482
    /// Truncate vector to new length, dropping any items after `len`.
483
    ///
484
    /// # Safety
485
    ///
486
    /// Safe as long as `len <= self.capacity()`.
487
0
    unsafe fn truncate_unchecked(&mut self, len: usize) {
488
0
        debug_assert!(len <= self.capacity(), "cannot exceed our array bounds");
489
0
        self.length = len as u16;
490
0
    }
491
492
    /// Resize the buffer, without bounds checking.
493
    ///
494
    /// # Safety
495
    ///
496
    /// Safe as long as `len <= self.capacity()`.
497
    #[inline(always)]
498
209
    pub unsafe fn resize_unchecked(&mut self, len: usize, value: Limb) {
499
209
        debug_assert!(len <= self.capacity(), "cannot exceed our array bounds");
500
209
        let old_len = self.len();
501
209
        if len > old_len {
502
            // We have a trivial drop, so there's no worry here.
503
            // Just, don't set the length until all values have been written,
504
            // so we don't accidentally read uninitialized memory.
505
506
209
            let count = len - old_len;
507
209
            for index in 0..count {
508
                // SAFETY: safe if `len < self.capacity()`.
509
209
                unsafe {
510
209
                    let dst = self.as_mut_ptr().add(old_len + index);
511
209
                    ptr::write(dst, value);
512
209
                }
513
            }
514
209
            self.length = len as u16;
515
0
        } else {
516
0
            // SAFETY: safe since `len < self.len()`.
517
0
            unsafe { self.truncate_unchecked(len) };
518
0
        }
519
209
    }
520
521
    /// Try to resize the buffer.
522
    ///
523
    /// If the new length is smaller than the current length, truncate
524
    /// the input. If it's larger, then append elements to the buffer.
525
    #[inline(always)]
526
209
    pub fn try_resize(&mut self, len: usize, value: Limb) -> Option<()> {
527
209
        if len > self.capacity() {
528
0
            None
529
        } else {
530
            // SAFETY: safe, since `len <= self.capacity()`.
531
209
            unsafe { self.resize_unchecked(len, value) };
532
209
            Some(())
533
        }
534
209
    }
535
536
    // HI
537
538
    /// Get the high 16 bits from the vector.
539
    #[inline(always)]
540
0
    pub fn hi16(&self) -> (u16, bool) {
541
0
        let rview = self.rview();
542
        // SAFETY: the buffer must be at least length bytes long which we check on the
543
        // match.
544
        unsafe {
545
0
            match rview.len() {
546
0
                0 => (0, false),
547
0
                1 if Limb::BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi16_1),
548
0
                1 => hi!(@1 self, rview, u64, u64_to_hi16_1),
549
0
                _ if Limb::BITS == 32 => hi!(@nonzero2 self, rview, u32, u32_to_hi16_2),
550
0
                _ => hi!(@nonzero2 self, rview, u64, u64_to_hi16_2),
551
            }
552
        }
553
0
    }
554
555
    /// Get the high 32 bits from the vector.
556
    #[inline(always)]
557
0
    pub fn hi32(&self) -> (u32, bool) {
558
0
        let rview = self.rview();
559
        // SAFETY: the buffer must be at least length bytes long which we check on the
560
        // match.
561
        unsafe {
562
0
            match rview.len() {
563
0
                0 => (0, false),
564
0
                1 if Limb::BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi32_1),
565
0
                1 => hi!(@1 self, rview, u64, u64_to_hi32_1),
566
0
                _ if Limb::BITS == 32 => hi!(@nonzero2 self, rview, u32, u32_to_hi32_2),
567
0
                _ => hi!(@nonzero2 self, rview, u64, u64_to_hi32_2),
568
            }
569
        }
570
0
    }
571
572
    /// Get the high 64 bits from the vector.
573
    #[inline(always)]
574
507
    pub fn hi64(&self) -> (u64, bool) {
575
507
        let rview = self.rview();
576
        // SAFETY: the buffer must be at least length bytes long which we check on the
577
        // match.
578
        unsafe {
579
507
            match rview.len() {
580
0
                0 => (0, false),
581
0
                1 if Limb::BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi64_1),
582
99
                1 => hi!(@1 self, rview, u64, u64_to_hi64_1),
583
0
                2 if Limb::BITS == 32 => hi!(@2 self, rview, u32, u32_to_hi64_2),
584
299
                2 => hi!(@2 self, rview, u64, u64_to_hi64_2),
585
0
                _ if Limb::BITS == 32 => hi!(@nonzero3 self, rview, u32, u32_to_hi64_3),
586
109
                _ => hi!(@nonzero2 self, rview, u64, u64_to_hi64_2),
587
            }
588
        }
589
507
    }
<lexical_parse_float::bigint::StackVec<62>>::hi64
Line
Count
Source
574
507
    pub fn hi64(&self) -> (u64, bool) {
575
507
        let rview = self.rview();
576
        // SAFETY: the buffer must be at least length bytes long which we check on the
577
        // match.
578
        unsafe {
579
507
            match rview.len() {
580
0
                0 => (0, false),
581
0
                1 if Limb::BITS == 32 => hi!(@1 self, rview, u32, u32_to_hi64_1),
582
99
                1 => hi!(@1 self, rview, u64, u64_to_hi64_1),
583
0
                2 if Limb::BITS == 32 => hi!(@2 self, rview, u32, u32_to_hi64_2),
584
299
                2 => hi!(@2 self, rview, u64, u64_to_hi64_2),
585
0
                _ if Limb::BITS == 32 => hi!(@nonzero3 self, rview, u32, u32_to_hi64_3),
586
109
                _ => hi!(@nonzero2 self, rview, u64, u64_to_hi64_2),
587
            }
588
        }
589
507
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::hi64
590
591
    // FROM
592
593
    /// Create `StackVec` from u16 value.
594
    #[must_use]
595
    #[inline(always)]
596
0
    pub fn from_u16(x: u16) -> Self {
597
0
        let mut vec = Self::new();
598
0
        assert!(1 <= vec.capacity(), "cannot exceed our array bounds");
599
0
        _ = vec.try_push(x as Limb);
600
0
        vec.normalize();
601
0
        vec
602
0
    }
603
604
    /// Create `StackVec` from u32 value.
605
    #[must_use]
606
    #[inline(always)]
607
0
    pub fn from_u32(x: u32) -> Self {
608
0
        let mut vec = Self::new();
609
0
        debug_assert!(1 <= vec.capacity(), "cannot exceed our array bounds");
610
0
        assert!(1 <= SIZE, "cannot exceed our array bounds");
611
0
        _ = vec.try_push(x as Limb);
612
0
        vec.normalize();
613
0
        vec
614
0
    }
615
616
    /// Create `StackVec` from u64 value.
617
    #[must_use]
618
    #[inline(always)]
619
868
    pub fn from_u64(x: u64) -> Self {
620
868
        let mut vec = Self::new();
621
868
        debug_assert!(2 <= vec.capacity(), "cannot exceed our array bounds");
622
868
        assert!(2 <= SIZE, "cannot exceed our array bounds");
623
868
        if Limb::BITS == 32 {
624
0
            _ = vec.try_push(x as Limb);
625
0
            _ = vec.try_push((x >> 32) as Limb);
626
868
        } else {
627
868
            _ = vec.try_push(x as Limb);
628
868
        }
629
868
        vec.normalize();
630
868
        vec
631
868
    }
<lexical_parse_float::bigint::StackVec<62>>::from_u64
Line
Count
Source
619
868
    pub fn from_u64(x: u64) -> Self {
620
868
        let mut vec = Self::new();
621
868
        debug_assert!(2 <= vec.capacity(), "cannot exceed our array bounds");
622
868
        assert!(2 <= SIZE, "cannot exceed our array bounds");
623
868
        if Limb::BITS == 32 {
624
0
            _ = vec.try_push(x as Limb);
625
0
            _ = vec.try_push((x >> 32) as Limb);
626
868
        } else {
627
868
            _ = vec.try_push(x as Limb);
628
868
        }
629
868
        vec.normalize();
630
868
        vec
631
868
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::from_u64
632
633
    // INDEX
634
635
    /// Create a reverse view of the vector for indexing.
636
    #[must_use]
637
    #[inline(always)]
638
507
    pub fn rview(&self) -> ReverseView<'_, Limb> {
639
507
        ReverseView {
640
507
            inner: self,
641
507
        }
642
507
    }
<lexical_parse_float::bigint::StackVec<62>>::rview
Line
Count
Source
638
507
    pub fn rview(&self) -> ReverseView<'_, Limb> {
639
507
        ReverseView {
640
507
            inner: self,
641
507
        }
642
507
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::rview
643
644
    // MATH
645
646
    /// Normalize the integer, so any leading zero values are removed.
647
    #[inline(always)]
648
940
    pub fn normalize(&mut self) {
649
        // We don't care if this wraps: the index is bounds-checked.
650
940
        while let Some(&value) = self.get(self.len().wrapping_sub(1)) {
651
940
            if value == 0 {
652
0
                self.length -= 1;
653
0
            } else {
654
940
                break;
655
            }
656
        }
657
940
    }
<lexical_parse_float::bigint::StackVec<62>>::normalize
Line
Count
Source
648
868
    pub fn normalize(&mut self) {
649
        // We don't care if this wraps: the index is bounds-checked.
650
868
        while let Some(&value) = self.get(self.len().wrapping_sub(1)) {
651
868
            if value == 0 {
652
0
                self.length -= 1;
653
0
            } else {
654
868
                break;
655
            }
656
        }
657
868
    }
<lexical_parse_float::bigint::StackVec<62>>::normalize
Line
Count
Source
648
72
    pub fn normalize(&mut self) {
649
        // We don't care if this wraps: the index is bounds-checked.
650
72
        while let Some(&value) = self.get(self.len().wrapping_sub(1)) {
651
72
            if value == 0 {
652
0
                self.length -= 1;
653
0
            } else {
654
72
                break;
655
            }
656
        }
657
72
    }
658
659
    /// Get if the big integer is normalized.
660
    #[must_use]
661
    #[inline(always)]
662
0
    pub fn is_normalized(&self) -> bool {
663
        // We don't care if this wraps: the index is bounds-checked.
664
0
        self.get(self.len().wrapping_sub(1)) != Some(&0)
665
0
    }
666
667
    /// Calculate the fast quotient for a single limb-bit quotient.
668
    ///
669
    /// This requires a non-normalized divisor, where there at least
670
    /// `integral_binary_factor` 0 bits set, to ensure at maximum a single
671
    /// digit will be produced for a single base.
672
    ///
673
    /// Warning: This is not a general-purpose division algorithm,
674
    /// it is highly specialized for peeling off singular digits.
675
    #[inline(always)]
676
    #[cfg(feature = "radix")]
677
    pub fn quorem(&mut self, y: &Self) -> Limb {
678
        large_quorem(self, y)
679
    }
680
681
    /// `AddAssign` small integer.
682
    #[inline(always)]
683
3.30k
    pub fn add_small(&mut self, y: Limb) -> Option<()> {
684
3.30k
        small_add(self, y)
685
3.30k
    }
<lexical_parse_float::bigint::StackVec<62>>::add_small
Line
Count
Source
683
3.30k
    pub fn add_small(&mut self, y: Limb) -> Option<()> {
684
3.30k
        small_add(self, y)
685
3.30k
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::add_small
686
687
    /// `MulAssign` small integer.
688
    #[inline(always)]
689
3.30k
    pub fn mul_small(&mut self, y: Limb) -> Option<()> {
690
3.30k
        small_mul(self, y)
691
3.30k
    }
<lexical_parse_float::bigint::StackVec<62>>::mul_small
Line
Count
Source
689
3.30k
    pub fn mul_small(&mut self, y: Limb) -> Option<()> {
690
3.30k
        small_mul(self, y)
691
3.30k
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_>>::mul_small
692
}
693
694
impl<const SIZE: usize> PartialEq for StackVec<SIZE> {
695
    #[inline(always)]
696
    #[allow(clippy::op_ref)] // reason="need to convert to slice for equality"
697
0
    fn eq(&self, other: &Self) -> bool {
698
        use core::ops::Deref;
699
0
        self.len() == other.len() && self.deref() == other.deref()
700
0
    }
701
}
702
703
impl<const SIZE: usize> Eq for StackVec<SIZE> {
704
}
705
706
impl<const SIZE: usize> cmp::PartialOrd for StackVec<SIZE> {
707
    #[inline(always)]
708
0
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
709
0
        Some(self.cmp(other))
710
0
    }
711
}
712
713
impl<const SIZE: usize> cmp::Ord for StackVec<SIZE> {
714
    #[inline(always)]
715
868
    fn cmp(&self, other: &Self) -> cmp::Ordering {
716
868
        compare(self, other)
717
868
    }
<lexical_parse_float::bigint::StackVec<62> as core::cmp::Ord>::cmp
Line
Count
Source
715
868
    fn cmp(&self, other: &Self) -> cmp::Ordering {
716
868
        compare(self, other)
717
868
    }
Unexecuted instantiation: <lexical_parse_float::bigint::StackVec<_> as core::cmp::Ord>::cmp
718
}
719
720
impl<const SIZE: usize> ops::Deref for StackVec<SIZE> {
721
    type Target = [Limb];
722
    #[inline(always)]
723
5.74k
    fn deref(&self) -> &[Limb] {
724
5.74k
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
725
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
726
        // and `self.len() <= self.capacity()`.
727
        unsafe {
728
5.74k
            let ptr = self.data.as_ptr() as *const Limb;
729
5.74k
            slice::from_raw_parts(ptr, self.len())
730
        }
731
5.74k
    }
<lexical_parse_float::bigint::StackVec<62> as core::ops::deref::Deref>::deref
Line
Count
Source
723
5.46k
    fn deref(&self) -> &[Limb] {
724
5.46k
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
725
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
726
        // and `self.len() <= self.capacity()`.
727
        unsafe {
728
5.46k
            let ptr = self.data.as_ptr() as *const Limb;
729
5.46k
            slice::from_raw_parts(ptr, self.len())
730
        }
731
5.46k
    }
<lexical_parse_float::bigint::StackVec<62> as core::ops::deref::Deref>::deref
Line
Count
Source
723
282
    fn deref(&self) -> &[Limb] {
724
282
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
725
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
726
        // and `self.len() <= self.capacity()`.
727
        unsafe {
728
282
            let ptr = self.data.as_ptr() as *const Limb;
729
282
            slice::from_raw_parts(ptr, self.len())
730
        }
731
282
    }
732
}
733
734
impl<const SIZE: usize> ops::DerefMut for StackVec<SIZE> {
735
    #[inline(always)]
736
8.84k
    fn deref_mut(&mut self) -> &mut [Limb] {
737
8.84k
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
738
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
739
        // and `self.len() <= self.capacity()`.
740
8.84k
        unsafe {
741
8.84k
            let ptr = self.data.as_mut_ptr() as *mut Limb;
742
8.84k
            slice::from_raw_parts_mut(ptr, self.len())
743
8.84k
        }
744
8.84k
    }
<lexical_parse_float::bigint::StackVec<62> as core::ops::deref::DerefMut>::deref_mut
Line
Count
Source
736
7.30k
    fn deref_mut(&mut self) -> &mut [Limb] {
737
7.30k
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
738
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
739
        // and `self.len() <= self.capacity()`.
740
7.30k
        unsafe {
741
7.30k
            let ptr = self.data.as_mut_ptr() as *mut Limb;
742
7.30k
            slice::from_raw_parts_mut(ptr, self.len())
743
7.30k
        }
744
7.30k
    }
<lexical_parse_float::bigint::StackVec<62> as core::ops::deref::DerefMut>::deref_mut
Line
Count
Source
736
1.54k
    fn deref_mut(&mut self) -> &mut [Limb] {
737
1.54k
        debug_assert!(self.len() <= self.capacity(), "cannot exceed our array bounds");
738
        // SAFETY: safe since `self.data[..self.len()]` must be initialized
739
        // and `self.len() <= self.capacity()`.
740
1.54k
        unsafe {
741
1.54k
            let ptr = self.data.as_mut_ptr() as *mut Limb;
742
1.54k
            slice::from_raw_parts_mut(ptr, self.len())
743
1.54k
        }
744
1.54k
    }
745
}
746
747
impl<const SIZE: usize> ops::MulAssign<&[Limb]> for StackVec<SIZE> {
748
    #[inline(always)]
749
    #[allow(clippy::unwrap_used)] // reason="exceeding the bounds is a developer error"
750
0
    fn mul_assign(&mut self, rhs: &[Limb]) {
751
0
        large_mul(self, rhs).unwrap();
752
0
    }
753
}
754
755
impl<const SIZE: usize> Default for StackVec<SIZE> {
756
0
    fn default() -> Self {
757
0
        Self::new()
758
0
    }
759
}
760
761
// REVERSE VIEW
762
763
/// Reverse, immutable view of a sequence.
764
pub struct ReverseView<'a, T: 'a> {
765
    inner: &'a [T],
766
}
767
768
impl<'a, T: 'a> ReverseView<'a, T> {
769
    /// Get a reference to a value, without bounds checking.
770
    ///
771
    /// # Safety
772
    ///
773
    /// Safe if forward indexing would be safe for the type,
774
    /// or `index < self.inner.len()`.
775
    #[inline(always)]
776
915
    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
777
915
        debug_assert!(index < self.inner.len(), "cannot exceed our array bounds");
778
915
        let len = self.inner.len();
779
        // SAFETY: Safe as long as the index < length, so len - index - 1 >= 0 and <=
780
        // len.
781
915
        unsafe { self.inner.get_unchecked(len - index - 1) }
782
915
    }
<lexical_parse_float::bigint::ReverseView<u64>>::get_unchecked
Line
Count
Source
776
915
    pub unsafe fn get_unchecked(&self, index: usize) -> &T {
777
915
        debug_assert!(index < self.inner.len(), "cannot exceed our array bounds");
778
915
        let len = self.inner.len();
779
        // SAFETY: Safe as long as the index < length, so len - index - 1 >= 0 and <=
780
        // len.
781
915
        unsafe { self.inner.get_unchecked(len - index - 1) }
782
915
    }
Unexecuted instantiation: <lexical_parse_float::bigint::ReverseView<_>>::get_unchecked
783
784
    /// Get a reference to a value.
785
    #[inline(always)]
786
0
    pub fn get(&self, index: usize) -> Option<&T> {
787
0
        let len = self.inner.len();
788
        // We don't care if this wraps: the index is bounds-checked.
789
0
        self.inner.get(len.wrapping_sub(index + 1))
790
0
    }
791
792
    /// Get the length of the inner buffer.
793
    #[inline(always)]
794
507
    pub const fn len(&self) -> usize {
795
507
        self.inner.len()
796
507
    }
<lexical_parse_float::bigint::ReverseView<u64>>::len
Line
Count
Source
794
507
    pub const fn len(&self) -> usize {
795
507
        self.inner.len()
796
507
    }
Unexecuted instantiation: <lexical_parse_float::bigint::ReverseView<_>>::len
797
798
    /// If the vector is empty.
799
    #[inline(always)]
800
0
    pub const fn is_empty(&self) -> bool {
801
0
        self.inner.is_empty()
802
0
    }
803
}
804
805
impl<T> ops::Index<usize> for ReverseView<'_, T> {
806
    type Output = T;
807
808
    #[inline(always)]
809
0
    fn index(&self, index: usize) -> &T {
810
0
        let len = self.inner.len();
811
0
        &(*self.inner)[len - index - 1]
812
0
    }
813
}
814
815
// HI
816
// --
817
818
/// Check if any of the remaining bits are non-zero.
819
///
820
/// # Safety
821
///
822
/// Safe as long as `rindex <= x.len()`. This is only called
823
/// where the type size is directly from the caller, and removing
824
/// it leads to a ~20% degradation in performance.
825
#[must_use]
826
#[inline(always)]
827
9
pub unsafe fn nonzero(x: &[Limb], rindex: usize) -> bool {
828
9
    debug_assert!(rindex <= x.len(), "cannot exceed our array bounds");
829
9
    let len = x.len();
830
    // SAFETY: safe if `rindex < x.len()`, since then `x.len() - rindex < x.len()`.
831
9
    let slc = unsafe { &index_unchecked!(x[..len - rindex]) };
832
9
    slc.iter().rev().any(|&x| x != 0)
lexical_parse_float::bigint::nonzero::{closure#0}
Line
Count
Source
832
9
    slc.iter().rev().any(|&x| x != 0)
Unexecuted instantiation: lexical_parse_float::bigint::nonzero::{closure#0}
833
9
}
834
835
// These return the high X bits and if the bits were truncated.
836
837
/// Shift 32-bit integer to high 16-bits.
838
#[must_use]
839
#[inline(always)]
840
0
pub const fn u32_to_hi16_1(r0: u32) -> (u16, bool) {
841
0
    let r0 = u32_to_hi32_1(r0).0;
842
0
    ((r0 >> 16) as u16, r0 as u16 != 0)
843
0
}
844
845
/// Shift 2 32-bit integers to high 16-bits.
846
#[must_use]
847
#[inline(always)]
848
0
pub const fn u32_to_hi16_2(r0: u32, r1: u32) -> (u16, bool) {
849
0
    let (r0, n) = u32_to_hi32_2(r0, r1);
850
0
    ((r0 >> 16) as u16, n || r0 as u16 != 0)
851
0
}
852
853
/// Shift 32-bit integer to high 32-bits.
854
#[must_use]
855
#[inline(always)]
856
0
pub const fn u32_to_hi32_1(r0: u32) -> (u32, bool) {
857
0
    let ls = r0.leading_zeros();
858
0
    (r0 << ls, false)
859
0
}
860
861
/// Shift 2 32-bit integers to high 32-bits.
862
#[must_use]
863
#[inline(always)]
864
0
pub const fn u32_to_hi32_2(r0: u32, r1: u32) -> (u32, bool) {
865
0
    let ls = r0.leading_zeros();
866
0
    let rs = 32 - ls;
867
0
    let v = match ls {
868
0
        0 => r0,
869
0
        _ => (r0 << ls) | (r1 >> rs),
870
    };
871
0
    let n = r1 << ls != 0;
872
0
    (v, n)
873
0
}
874
875
/// Shift 32-bit integer to high 64-bits.
876
#[must_use]
877
#[inline(always)]
878
0
pub const fn u32_to_hi64_1(r0: u32) -> (u64, bool) {
879
0
    u64_to_hi64_1(r0 as u64)
880
0
}
881
882
/// Shift 2 32-bit integers to high 64-bits.
883
#[must_use]
884
#[inline(always)]
885
0
pub const fn u32_to_hi64_2(r0: u32, r1: u32) -> (u64, bool) {
886
0
    let r0 = (r0 as u64) << 32;
887
0
    let r1 = r1 as u64;
888
0
    u64_to_hi64_1(r0 | r1)
889
0
}
890
891
/// Shift 3 32-bit integers to high 64-bits.
892
#[must_use]
893
#[inline(always)]
894
0
pub const fn u32_to_hi64_3(r0: u32, r1: u32, r2: u32) -> (u64, bool) {
895
0
    let r0 = r0 as u64;
896
0
    let r1 = (r1 as u64) << 32;
897
0
    let r2 = r2 as u64;
898
0
    u64_to_hi64_2(r0, r1 | r2)
899
0
}
900
901
/// Shift 64-bit integer to high 16-bits.
902
#[must_use]
903
#[inline(always)]
904
0
pub const fn u64_to_hi16_1(r0: u64) -> (u16, bool) {
905
0
    let r0 = u64_to_hi64_1(r0).0;
906
0
    ((r0 >> 48) as u16, r0 as u16 != 0)
907
0
}
908
909
/// Shift 2 64-bit integers to high 16-bits.
910
#[must_use]
911
#[inline(always)]
912
0
pub const fn u64_to_hi16_2(r0: u64, r1: u64) -> (u16, bool) {
913
0
    let (r0, n) = u64_to_hi64_2(r0, r1);
914
0
    ((r0 >> 48) as u16, n || r0 as u16 != 0)
915
0
}
916
917
/// Shift 64-bit integer to high 32-bits.
918
#[must_use]
919
#[inline(always)]
920
0
pub const fn u64_to_hi32_1(r0: u64) -> (u32, bool) {
921
0
    let r0 = u64_to_hi64_1(r0).0;
922
0
    ((r0 >> 32) as u32, r0 as u32 != 0)
923
0
}
924
925
/// Shift 2 64-bit integers to high 32-bits.
926
#[must_use]
927
#[inline(always)]
928
0
pub const fn u64_to_hi32_2(r0: u64, r1: u64) -> (u32, bool) {
929
0
    let (r0, n) = u64_to_hi64_2(r0, r1);
930
0
    ((r0 >> 32) as u32, n || r0 as u32 != 0)
931
0
}
932
933
/// Shift 64-bit integer to high 64-bits.
934
#[must_use]
935
#[inline(always)]
936
99
pub const fn u64_to_hi64_1(r0: u64) -> (u64, bool) {
937
99
    let ls = r0.leading_zeros();
938
99
    (r0 << ls, false)
939
99
}
940
941
/// Shift 2 64-bit integers to high 64-bits.
942
#[must_use]
943
#[inline(always)]
944
408
pub const fn u64_to_hi64_2(r0: u64, r1: u64) -> (u64, bool) {
945
408
    let ls = r0.leading_zeros();
946
408
    let rs = 64 - ls;
947
408
    let v = match ls {
948
3
        0 => r0,
949
405
        _ => (r0 << ls) | (r1 >> rs),
950
    };
951
408
    let n = r1 << ls != 0;
952
408
    (v, n)
953
408
}
954
955
// POWERS
956
// ------
957
958
/// MulAssign by a power.
959
///
960
/// Theoretically...
961
///
962
/// Use an exponentiation by squaring method, since it reduces the time
963
/// complexity of the multiplication to ~`O(log(n))` for the squaring,
964
/// and `O(n*m)` for the result. Since `m` is typically a lower-order
965
/// factor, this significantly reduces the number of multiplications
966
/// we need to do. Iteratively multiplying by small powers follows
967
/// the nth triangular number series, which scales as `O(p^2)`, but
968
/// where `p` is `n+m`. In short, it scales very poorly.
969
///
970
/// Practically....
971
///
972
/// Exponentiation by Squaring:
973
///     running 2 tests
974
///     test bigcomp_f32_lexical ... bench:       1,018 ns/iter (+/- 78)
975
///     test bigcomp_f64_lexical ... bench:       3,639 ns/iter (+/- 1,007)
976
///
977
/// Exponentiation by Iterative Small Powers:
978
///     running 2 tests
979
///     test bigcomp_f32_lexical ... bench:         518 ns/iter (+/- 31)
980
///     test bigcomp_f64_lexical ... bench:         583 ns/iter (+/- 47)
981
///
982
/// Exponentiation by Iterative Large Powers (of 2):
983
///     running 2 tests
984
///     test bigcomp_f32_lexical ... bench:         671 ns/iter (+/- 31)
985
///     test bigcomp_f64_lexical ... bench:       1,394 ns/iter (+/- 47)
986
///
987
/// The following benchmarks were run on `1 * 5^300`, using native `pow`,
988
/// a version with only small powers, and one with pre-computed powers
989
/// of `5^(3 * max_exp)`, rather than `5^(5 * max_exp)`.
990
///
991
/// However, using large powers is crucial for good performance for higher
992
/// powers.
993
///     pow/default             time:   [426.20 ns 427.96 ns 429.89 ns]
994
///     pow/small               time:   [2.9270 us 2.9411 us 2.9565 us]
995
///     pow/large:3             time:   [838.51 ns 842.21 ns 846.27 ns]
996
///
997
/// Even using worst-case scenarios, exponentiation by squaring is
998
/// significantly slower for our workloads. Just multiply by small powers,
999
/// in simple cases, and use pre-calculated large powers in other cases.
1000
///
1001
/// Furthermore, using sufficiently big large powers is also crucial for
1002
/// performance. This is a trade-off of binary size and performance, and
1003
/// using a single value at ~`5^(5 * max_exp)` seems optimal.
1004
#[allow(clippy::doc_markdown)] // reason="not attempted to be referencing items"
1005
#[allow(clippy::missing_inline_in_public_items)] // reason="only public for testing"
1006
1.37k
pub fn pow<const SIZE: usize>(x: &mut StackVec<SIZE>, base: u32, mut exp: u32) -> Option<()> {
1007
    // Minimize the number of iterations for large exponents: just
1008
    // do a few steps with a large powers.
1009
    #[cfg(not(feature = "compact"))]
1010
    {
1011
1.37k
        let (large, step) = get_large_int_power(base);
1012
1.44k
        while exp >= step {
1013
72
            large_mul(x, large)?;
1014
72
            exp -= step;
1015
        }
1016
    }
1017
1018
    // Now use our pre-computed small powers iteratively.
1019
1.37k
    let small_step = if Limb::BITS == 32 {
1020
0
        u32_power_limit(base)
1021
    } else {
1022
1.37k
        u64_power_limit(base)
1023
    };
1024
1.37k
    let max_native = (base as Limb).pow(small_step);
1025
1.78k
    while exp >= small_step {
1026
411
        small_mul(x, max_native)?;
1027
411
        exp -= small_step;
1028
    }
1029
1.37k
    if exp != 0 {
1030
905
        let small_power = f64::int_pow_fast_path(exp as usize, base);
1031
905
        small_mul(x, small_power as Limb)?;
1032
470
    }
1033
1.37k
    Some(())
1034
1.37k
}
lexical_parse_float::bigint::pow::<62>
Line
Count
Source
1006
1.37k
pub fn pow<const SIZE: usize>(x: &mut StackVec<SIZE>, base: u32, mut exp: u32) -> Option<()> {
1007
    // Minimize the number of iterations for large exponents: just
1008
    // do a few steps with a large powers.
1009
    #[cfg(not(feature = "compact"))]
1010
    {
1011
1.37k
        let (large, step) = get_large_int_power(base);
1012
1.44k
        while exp >= step {
1013
72
            large_mul(x, large)?;
1014
72
            exp -= step;
1015
        }
1016
    }
1017
1018
    // Now use our pre-computed small powers iteratively.
1019
1.37k
    let small_step = if Limb::BITS == 32 {
1020
0
        u32_power_limit(base)
1021
    } else {
1022
1.37k
        u64_power_limit(base)
1023
    };
1024
1.37k
    let max_native = (base as Limb).pow(small_step);
1025
1.78k
    while exp >= small_step {
1026
411
        small_mul(x, max_native)?;
1027
411
        exp -= small_step;
1028
    }
1029
1.37k
    if exp != 0 {
1030
905
        let small_power = f64::int_pow_fast_path(exp as usize, base);
1031
905
        small_mul(x, small_power as Limb)?;
1032
470
    }
1033
1.37k
    Some(())
1034
1.37k
}
Unexecuted instantiation: lexical_parse_float::bigint::pow::<_>
1035
1036
// SCALAR
1037
// ------
1038
1039
/// Add two small integers and return the resulting value and if overflow
1040
/// happens.
1041
#[must_use]
1042
#[inline(always)]
1043
3.48k
pub const fn scalar_add(x: Limb, y: Limb) -> (Limb, bool) {
1044
3.48k
    x.overflowing_add(y)
1045
3.48k
}
1046
1047
/// Multiply two small integers (with carry) (and return the overflow
1048
/// contribution).
1049
///
1050
/// Returns the (low, high) components.
1051
#[must_use]
1052
#[inline(always)]
1053
6.99k
pub const fn scalar_mul(x: Limb, y: Limb, carry: Limb) -> (Limb, Limb) {
1054
    // Cannot overflow, as long as wide is 2x as wide. This is because
1055
    // the following is always true:
1056
    // `Wide::MAX - (Narrow::MAX * Narrow::MAX) >= Narrow::MAX`
1057
6.99k
    let z: Wide = (x as Wide) * (y as Wide) + (carry as Wide);
1058
6.99k
    (z as Limb, (z >> Limb::BITS) as Limb)
1059
6.99k
}
1060
1061
// SMALL
1062
// -----
1063
1064
/// Add small integer to bigint starting from offset.
1065
#[inline(always)]
1066
3.30k
pub fn small_add_from<const SIZE: usize>(
1067
3.30k
    x: &mut StackVec<SIZE>,
1068
3.30k
    y: Limb,
1069
3.30k
    start: usize,
1070
3.30k
) -> Option<()> {
1071
3.30k
    let mut index = start;
1072
3.30k
    let mut carry = y;
1073
5.07k
    while carry != 0 && index < x.len() {
1074
1.76k
        // NOTE: Don't need unsafety because the compiler will optimize it out.
1075
1.76k
        let result = scalar_add(x[index], carry);
1076
1.76k
        x[index] = result.0;
1077
1.76k
        carry = result.1 as Limb;
1078
1.76k
        index += 1;
1079
1.76k
    }
1080
    // If we carried past all the elements, add to the end of the buffer.
1081
3.30k
    if carry != 0 {
1082
1.37k
        x.try_push(carry)?;
1083
1.93k
    }
1084
3.30k
    Some(())
1085
3.30k
}
lexical_parse_float::bigint::small_add_from::<62>
Line
Count
Source
1066
3.30k
pub fn small_add_from<const SIZE: usize>(
1067
3.30k
    x: &mut StackVec<SIZE>,
1068
3.30k
    y: Limb,
1069
3.30k
    start: usize,
1070
3.30k
) -> Option<()> {
1071
3.30k
    let mut index = start;
1072
3.30k
    let mut carry = y;
1073
5.07k
    while carry != 0 && index < x.len() {
1074
1.76k
        // NOTE: Don't need unsafety because the compiler will optimize it out.
1075
1.76k
        let result = scalar_add(x[index], carry);
1076
1.76k
        x[index] = result.0;
1077
1.76k
        carry = result.1 as Limb;
1078
1.76k
        index += 1;
1079
1.76k
    }
1080
    // If we carried past all the elements, add to the end of the buffer.
1081
3.30k
    if carry != 0 {
1082
1.37k
        x.try_push(carry)?;
1083
1.93k
    }
1084
3.30k
    Some(())
1085
3.30k
}
Unexecuted instantiation: lexical_parse_float::bigint::small_add_from::<62>
1086
1087
/// Add small integer to bigint.
1088
#[inline(always)]
1089
3.30k
pub fn small_add<const SIZE: usize>(x: &mut StackVec<SIZE>, y: Limb) -> Option<()> {
1090
3.30k
    small_add_from(x, y, 0)
1091
3.30k
}
lexical_parse_float::bigint::small_add::<62>
Line
Count
Source
1089
3.30k
pub fn small_add<const SIZE: usize>(x: &mut StackVec<SIZE>, y: Limb) -> Option<()> {
1090
3.30k
    small_add_from(x, y, 0)
1091
3.30k
}
Unexecuted instantiation: lexical_parse_float::bigint::small_add::<_>
1092
1093
/// Multiply bigint by small integer.
1094
#[inline(always)]
1095
4.90k
pub fn small_mul<const SIZE: usize>(x: &mut StackVec<SIZE>, y: Limb) -> Option<()> {
1096
4.90k
    let mut carry = 0;
1097
6.99k
    for xi in x.iter_mut() {
1098
6.99k
        let result = scalar_mul(*xi, y, carry);
1099
6.99k
        *xi = result.0;
1100
6.99k
        carry = result.1;
1101
6.99k
    }
1102
    // If we carried past all the elements, add to the end of the buffer.
1103
4.90k
    if carry != 0 {
1104
3.17k
        x.try_push(carry)?;
1105
1.72k
    }
1106
4.90k
    Some(())
1107
4.90k
}
lexical_parse_float::bigint::small_mul::<62>
Line
Count
Source
1095
4.62k
pub fn small_mul<const SIZE: usize>(x: &mut StackVec<SIZE>, y: Limb) -> Option<()> {
1096
4.62k
    let mut carry = 0;
1097
5.58k
    for xi in x.iter_mut() {
1098
5.58k
        let result = scalar_mul(*xi, y, carry);
1099
5.58k
        *xi = result.0;
1100
5.58k
        carry = result.1;
1101
5.58k
    }
1102
    // If we carried past all the elements, add to the end of the buffer.
1103
4.62k
    if carry != 0 {
1104
2.89k
        x.try_push(carry)?;
1105
1.72k
    }
1106
4.62k
    Some(())
1107
4.62k
}
lexical_parse_float::bigint::small_mul::<62>
Line
Count
Source
1095
282
pub fn small_mul<const SIZE: usize>(x: &mut StackVec<SIZE>, y: Limb) -> Option<()> {
1096
282
    let mut carry = 0;
1097
1.41k
    for xi in x.iter_mut() {
1098
1.41k
        let result = scalar_mul(*xi, y, carry);
1099
1.41k
        *xi = result.0;
1100
1.41k
        carry = result.1;
1101
1.41k
    }
1102
    // If we carried past all the elements, add to the end of the buffer.
1103
282
    if carry != 0 {
1104
281
        x.try_push(carry)?;
1105
1
    }
1106
282
    Some(())
1107
282
}
1108
1109
// LARGE
1110
// -----
1111
1112
/// Add bigint to bigint starting from offset.
1113
#[allow(clippy::missing_inline_in_public_items)] // reason="only public for testing"
1114
210
pub fn large_add_from<const SIZE: usize>(
1115
210
    x: &mut StackVec<SIZE>,
1116
210
    y: &[Limb],
1117
210
    start: usize,
1118
210
) -> Option<()> {
1119
    // The effective `x` buffer is from `xstart..x.len()`, so we need to treat
1120
    // that as the current range. If the effective `y` buffer is longer, need
1121
    // to resize to that, + the start index.
1122
210
    if y.len() > x.len().saturating_sub(start) {
1123
        // Ensure we panic if we can't extend the buffer.
1124
        // This avoids any unsafe behavior afterwards.
1125
209
        x.try_resize(y.len() + start, 0)?;
1126
1
    }
1127
1128
    // Iteratively add elements from `y` to `x`.
1129
210
    let mut carry = false;
1130
1.25k
    for index in 0..y.len() {
1131
1.25k
        let xi = &mut x[start + index];
1132
1.25k
        let yi = y[index];
1133
1134
        // Only one op of the two ops can overflow, since we added at max
1135
        // `Limb::max_value() + Limb::max_value()`. Add the previous carry,
1136
        // and store the current carry for the next.
1137
1.25k
        let result = scalar_add(*xi, yi);
1138
1.25k
        *xi = result.0;
1139
1.25k
        let mut tmp = result.1;
1140
1.25k
        if carry {
1141
455
            let result = scalar_add(*xi, 1);
1142
455
            *xi = result.0;
1143
455
            tmp |= result.1;
1144
804
        }
1145
1.25k
        carry = tmp;
1146
    }
1147
1148
    // Handle overflow.
1149
210
    if carry {
1150
0
        small_add_from(x, 1, y.len() + start)?;
1151
210
    }
1152
210
    Some(())
1153
210
}
1154
1155
/// Add bigint to bigint.
1156
#[inline(always)]
1157
0
pub fn large_add<const SIZE: usize>(x: &mut StackVec<SIZE>, y: &[Limb]) -> Option<()> {
1158
0
    large_add_from(x, y, 0)
1159
0
}
1160
1161
/// Grade-school multiplication algorithm.
1162
///
1163
/// Slow, naive algorithm, using limb-bit bases and just shifting left for
1164
/// each iteration. This could be optimized with numerous other algorithms,
1165
/// but it's extremely simple, and works in O(n*m) time, which is fine
1166
/// by me. Each iteration, of which there are `m` iterations, requires
1167
/// `n` multiplications, and `n` additions, or grade-school multiplication.
1168
///
1169
/// Don't use Karatsuba multiplication, since out implementation seems to
1170
/// be slower asymptotically, which is likely just due to the small sizes
1171
/// we deal with here. For example, running on the following data:
1172
///
1173
/// ```text
1174
/// const SMALL_X: &[u32] = &[
1175
///     766857581, 3588187092, 1583923090, 2204542082, 1564708913, 2695310100, 3676050286,
1176
///     1022770393, 468044626, 446028186
1177
/// ];
1178
/// const SMALL_Y: &[u32] = &[
1179
///     3945492125, 3250752032, 1282554898, 1708742809, 1131807209, 3171663979, 1353276095,
1180
///     1678845844, 2373924447, 3640713171
1181
/// ];
1182
/// const LARGE_X: &[u32] = &[
1183
///     3647536243, 2836434412, 2154401029, 1297917894, 137240595, 790694805, 2260404854,
1184
///     3872698172, 690585094, 99641546, 3510774932, 1672049983, 2313458559, 2017623719,
1185
///     638180197, 1140936565, 1787190494, 1797420655, 14113450, 2350476485, 3052941684,
1186
///     1993594787, 2901001571, 4156930025, 1248016552, 848099908, 2660577483, 4030871206,
1187
///     692169593, 2835966319, 1781364505, 4266390061, 1813581655, 4210899844, 2137005290,
1188
///     2346701569, 3715571980, 3386325356, 1251725092, 2267270902, 474686922, 2712200426,
1189
///     197581715, 3087636290, 1379224439, 1258285015, 3230794403, 2759309199, 1494932094,
1190
///     326310242
1191
/// ];
1192
/// const LARGE_Y: &[u32] = &[
1193
///     1574249566, 868970575, 76716509, 3198027972, 1541766986, 1095120699, 3891610505,
1194
///     2322545818, 1677345138, 865101357, 2650232883, 2831881215, 3985005565, 2294283760,
1195
///     3468161605, 393539559, 3665153349, 1494067812, 106699483, 2596454134, 797235106,
1196
///     705031740, 1209732933, 2732145769, 4122429072, 141002534, 790195010, 4014829800,
1197
///     1303930792, 3649568494, 308065964, 1233648836, 2807326116, 79326486, 1262500691,
1198
///     621809229, 2258109428, 3819258501, 171115668, 1139491184, 2979680603, 1333372297,
1199
///     1657496603, 2790845317, 4090236532, 4220374789, 601876604, 1828177209, 2372228171,
1200
///     2247372529
1201
/// ];
1202
/// ```
1203
///
1204
/// We get the following results:
1205
///
1206
/// ```text
1207
/// mul/small:long          time:   [220.23 ns 221.47 ns 222.81 ns]
1208
/// Found 4 outliers among 100 measurements (4.00%)
1209
///   2 (2.00%) high mild
1210
///   2 (2.00%) high severe
1211
/// mul/small:karatsuba     time:   [233.88 ns 234.63 ns 235.44 ns]
1212
/// Found 11 outliers among 100 measurements (11.00%)
1213
///   8 (8.00%) high mild
1214
///   3 (3.00%) high severe
1215
/// mul/large:long          time:   [1.9365 us 1.9455 us 1.9558 us]
1216
/// Found 12 outliers among 100 measurements (12.00%)
1217
///   7 (7.00%) high mild
1218
///   5 (5.00%) high severe
1219
/// mul/large:karatsuba     time:   [4.4250 us 4.4515 us 4.4812 us]
1220
/// ```
1221
///
1222
/// In short, Karatsuba multiplication is never worthwhile for out use-case.
1223
#[must_use]
1224
#[allow(clippy::needless_range_loop)] // reason="required for performance, see benches"
1225
#[allow(clippy::missing_inline_in_public_items)] // reason="only public for testing"
1226
72
pub fn long_mul<const SIZE: usize>(x: &[Limb], y: &[Limb]) -> Option<StackVec<SIZE>> {
1227
    // Using the immutable value, multiply by all the scalars in y, using
1228
    // the algorithm defined above. Use a single buffer to avoid
1229
    // frequent reallocations. Handle the first case to avoid a redundant
1230
    // addition, since we know y.len() >= 1.
1231
72
    let mut z = StackVec::<SIZE>::try_from(x)?;
1232
72
    if let Some(&y0) = y.first() {
1233
72
        small_mul(&mut z, y0)?;
1234
1235
        // NOTE: Don't use enumerate/skip since it's slow.
1236
210
        for index in 1..y.len() {
1237
210
            let yi = y[index];
1238
210
            if yi != 0 {
1239
210
                let mut zi = StackVec::<SIZE>::try_from(x)?;
1240
210
                small_mul(&mut zi, yi)?;
1241
210
                large_add_from(&mut z, &zi, index)?;
1242
0
            }
1243
        }
1244
0
    }
1245
1246
72
    z.normalize();
1247
72
    Some(z)
1248
72
}
1249
1250
/// Multiply bigint by bigint using grade-school multiplication algorithm.
1251
#[inline(always)]
1252
72
pub fn large_mul<const SIZE: usize>(x: &mut StackVec<SIZE>, y: &[Limb]) -> Option<()> {
1253
    // Karatsuba multiplication never makes sense, so just use grade school
1254
    // multiplication.
1255
72
    if y.len() == 1 {
1256
        // SAFETY: safe since `y.len() == 1`.
1257
        // NOTE: The compiler does not seem to optimize this out correctly.
1258
0
        small_mul(x, unsafe { index_unchecked!(y[0]) })?;
1259
    } else {
1260
72
        *x = long_mul(y, x)?;
1261
    }
1262
72
    Some(())
1263
72
}
lexical_parse_float::bigint::large_mul::<62>
Line
Count
Source
1252
72
pub fn large_mul<const SIZE: usize>(x: &mut StackVec<SIZE>, y: &[Limb]) -> Option<()> {
1253
    // Karatsuba multiplication never makes sense, so just use grade school
1254
    // multiplication.
1255
72
    if y.len() == 1 {
1256
        // SAFETY: safe since `y.len() == 1`.
1257
        // NOTE: The compiler does not seem to optimize this out correctly.
1258
0
        small_mul(x, unsafe { index_unchecked!(y[0]) })?;
1259
    } else {
1260
72
        *x = long_mul(y, x)?;
1261
    }
1262
72
    Some(())
1263
72
}
Unexecuted instantiation: lexical_parse_float::bigint::large_mul::<62>
1264
1265
/// Emit a single digit for the quotient and store the remainder in-place.
1266
///
1267
/// An extremely efficient division algorithm for small quotients, requiring
1268
/// you to know the full range of the quotient prior to use. For example,
1269
/// with a quotient that can range from [0, 10), you must have 4 leading
1270
/// zeros in the divisor, so we can use a single-limb division to get
1271
/// an accurate estimate of the quotient. Since we always underestimate
1272
/// the quotient, we can add 1 and then emit the digit.
1273
///
1274
/// Requires a non-normalized denominator, with at least [1-6] leading
1275
/// zeros, depending on the base (for example, 1 for base2, 6 for base36).
1276
///
1277
/// Adapted from David M. Gay's dtoa, and therefore under an MIT license:
1278
///     www.netlib.org/fp/dtoa.c
1279
#[cfg(feature = "radix")]
1280
#[allow(clippy::many_single_char_names)] // reason = "mathematical names of variables"
1281
pub fn large_quorem<const SIZE: usize>(x: &mut StackVec<SIZE>, y: &[Limb]) -> Limb {
1282
    // If we have an empty divisor, error out early.
1283
    assert!(!y.is_empty(), "large_quorem:: division by zero error.");
1284
    assert!(x.len() <= y.len(), "large_quorem:: oversized numerator.");
1285
    let mask = Limb::MAX as Wide;
1286
1287
    // Numerator is smaller the denominator, quotient always 0.
1288
    if x.len() < y.len() {
1289
        return 0;
1290
    }
1291
1292
    // Calculate our initial estimate for q.
1293
    let xm_1 = x[x.len() - 1];
1294
    let yn_1 = y[y.len() - 1];
1295
    let mut q = xm_1 / (yn_1 + 1);
1296
1297
    // Need to calculate the remainder if we don't have a 0 quotient.
1298
    if q != 0 {
1299
        let mut borrow: Wide = 0;
1300
        let mut carry: Wide = 0;
1301
        for j in 0..x.len() {
1302
            let yj = y[j] as Wide;
1303
            let p = yj * q as Wide + carry;
1304
            carry = p >> Limb::BITS;
1305
            let xj = x[j] as Wide;
1306
            let t = xj.wrapping_sub(p & mask).wrapping_sub(borrow);
1307
            borrow = (t >> Limb::BITS) & 1;
1308
            x[j] = t as Limb;
1309
        }
1310
        x.normalize();
1311
    }
1312
1313
    // Check if we under-estimated x.
1314
    if compare(x, y) != cmp::Ordering::Less {
1315
        q += 1;
1316
        let mut borrow: Wide = 0;
1317
        let mut carry: Wide = 0;
1318
        for j in 0..x.len() {
1319
            let yj = y[j] as Wide;
1320
            let p = yj + carry;
1321
            carry = p >> Limb::BITS;
1322
            let xj = x[j] as Wide;
1323
            let t = xj.wrapping_sub(p & mask).wrapping_sub(borrow);
1324
            borrow = (t >> Limb::BITS) & 1;
1325
            x[j] = t as Limb;
1326
        }
1327
        x.normalize();
1328
    }
1329
1330
    q
1331
}
1332
1333
// COMPARE
1334
// -------
1335
1336
/// Compare `x` to `y`, in little-endian order.
1337
#[must_use]
1338
#[inline(always)]
1339
868
pub fn compare(x: &[Limb], y: &[Limb]) -> cmp::Ordering {
1340
868
    match x.len().cmp(&y.len()) {
1341
        cmp::Ordering::Equal => {
1342
868
            let iter = x.iter().rev().zip(y.iter().rev());
1343
1.82k
            for (&xi, yi) in iter {
1344
1.80k
                match xi.cmp(yi) {
1345
956
                    cmp::Ordering::Equal => (),
1346
851
                    ord => return ord,
1347
                }
1348
            }
1349
            // Equal case.
1350
17
            cmp::Ordering::Equal
1351
        },
1352
0
        ord => ord,
1353
    }
1354
868
}
1355
1356
// SHIFT
1357
// -----
1358
1359
/// Shift-left `n` bits inside a buffer.
1360
#[inline(always)]
1361
910
pub fn shl_bits<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1362
910
    debug_assert!(n != 0, "cannot shift left by 0 bits");
1363
1364
    // Internally, for each item, we shift left by n, and add the previous
1365
    // right shifted limb-bits.
1366
    // For example, we transform (for u8) shifted left 2, to:
1367
    //      b10100100 b01000010
1368
    //      b10 b10010001 b00001000
1369
910
    debug_assert!(n < Limb::BITS as usize, "cannot shift left more bits than in our limb");
1370
910
    let rshift = Limb::BITS as usize - n;
1371
910
    let lshift = n;
1372
910
    let mut prev: Limb = 0;
1373
2.35k
    for xi in x.iter_mut() {
1374
2.35k
        let tmp = *xi;
1375
2.35k
        *xi <<= lshift;
1376
2.35k
        *xi |= prev >> rshift;
1377
2.35k
        prev = tmp;
1378
2.35k
    }
1379
1380
    // Always push the carry, even if it creates a non-normal result.
1381
910
    let carry = prev >> rshift;
1382
910
    if carry != 0 {
1383
272
        x.try_push(carry)?;
1384
638
    }
1385
1386
910
    Some(())
1387
910
}
lexical_parse_float::bigint::shl_bits::<62>
Line
Count
Source
1361
910
pub fn shl_bits<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1362
910
    debug_assert!(n != 0, "cannot shift left by 0 bits");
1363
1364
    // Internally, for each item, we shift left by n, and add the previous
1365
    // right shifted limb-bits.
1366
    // For example, we transform (for u8) shifted left 2, to:
1367
    //      b10100100 b01000010
1368
    //      b10 b10010001 b00001000
1369
910
    debug_assert!(n < Limb::BITS as usize, "cannot shift left more bits than in our limb");
1370
910
    let rshift = Limb::BITS as usize - n;
1371
910
    let lshift = n;
1372
910
    let mut prev: Limb = 0;
1373
2.35k
    for xi in x.iter_mut() {
1374
2.35k
        let tmp = *xi;
1375
2.35k
        *xi <<= lshift;
1376
2.35k
        *xi |= prev >> rshift;
1377
2.35k
        prev = tmp;
1378
2.35k
    }
1379
1380
    // Always push the carry, even if it creates a non-normal result.
1381
910
    let carry = prev >> rshift;
1382
910
    if carry != 0 {
1383
272
        x.try_push(carry)?;
1384
638
    }
1385
1386
910
    Some(())
1387
910
}
Unexecuted instantiation: lexical_parse_float::bigint::shl_bits::<_>
1388
1389
/// Shift-left `n` limbs inside a buffer.
1390
#[inline(always)]
1391
103
pub fn shl_limbs<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1392
103
    debug_assert!(n != 0, "cannot shift left by 0 bits");
1393
103
    if n + x.len() > x.capacity() {
1394
0
        None
1395
103
    } else if !x.is_empty() {
1396
103
        let len = n + x.len();
1397
103
        let x_len = x.len();
1398
103
        let ptr = x.as_mut_ptr();
1399
103
        let src = ptr;
1400
        // SAFETY: since x is not empty, and `x.len() + n <= x.capacity()`.
1401
103
        unsafe {
1402
103
            // Move the elements.
1403
103
            let dst = ptr.add(n);
1404
103
            ptr::copy(src, dst, x_len);
1405
103
            // Write our 0s.
1406
103
            ptr::write_bytes(ptr, 0, n);
1407
103
            x.set_len(len);
1408
103
        }
1409
103
        Some(())
1410
    } else {
1411
0
        Some(())
1412
    }
1413
103
}
lexical_parse_float::bigint::shl_limbs::<62>
Line
Count
Source
1391
103
pub fn shl_limbs<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1392
103
    debug_assert!(n != 0, "cannot shift left by 0 bits");
1393
103
    if n + x.len() > x.capacity() {
1394
0
        None
1395
103
    } else if !x.is_empty() {
1396
103
        let len = n + x.len();
1397
103
        let x_len = x.len();
1398
103
        let ptr = x.as_mut_ptr();
1399
103
        let src = ptr;
1400
        // SAFETY: since x is not empty, and `x.len() + n <= x.capacity()`.
1401
103
        unsafe {
1402
103
            // Move the elements.
1403
103
            let dst = ptr.add(n);
1404
103
            ptr::copy(src, dst, x_len);
1405
103
            // Write our 0s.
1406
103
            ptr::write_bytes(ptr, 0, n);
1407
103
            x.set_len(len);
1408
103
        }
1409
103
        Some(())
1410
    } else {
1411
0
        Some(())
1412
    }
1413
103
}
Unexecuted instantiation: lexical_parse_float::bigint::shl_limbs::<_>
1414
1415
/// Shift-left buffer by n bits.
1416
#[must_use]
1417
#[inline(always)]
1418
1.36k
pub fn shl<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1419
1.36k
    let rem = n % Limb::BITS as usize;
1420
1.36k
    let div = n / Limb::BITS as usize;
1421
1.36k
    if rem != 0 {
1422
910
        shl_bits(x, rem)?;
1423
450
    }
1424
1.36k
    if div != 0 {
1425
103
        shl_limbs(x, div)?;
1426
1.25k
    }
1427
1.36k
    Some(())
1428
1.36k
}
lexical_parse_float::bigint::shl::<62>
Line
Count
Source
1418
1.36k
pub fn shl<const SIZE: usize>(x: &mut StackVec<SIZE>, n: usize) -> Option<()> {
1419
1.36k
    let rem = n % Limb::BITS as usize;
1420
1.36k
    let div = n / Limb::BITS as usize;
1421
1.36k
    if rem != 0 {
1422
910
        shl_bits(x, rem)?;
1423
450
    }
1424
1.36k
    if div != 0 {
1425
103
        shl_limbs(x, div)?;
1426
1.25k
    }
1427
1.36k
    Some(())
1428
1.36k
}
Unexecuted instantiation: lexical_parse_float::bigint::shl::<_>
1429
1430
/// Get number of leading zero bits in the storage.
1431
#[must_use]
1432
#[inline(always)]
1433
507
pub fn leading_zeros(x: &[Limb]) -> u32 {
1434
507
    let length = x.len();
1435
    // `wrapping_sub` is fine, since it'll just return None.
1436
507
    if let Some(&value) = x.get(length.wrapping_sub(1)) {
1437
507
        value.leading_zeros()
1438
    } else {
1439
0
        0
1440
    }
1441
507
}
1442
1443
/// Calculate the bit-length of the big-integer.
1444
#[must_use]
1445
#[inline(always)]
1446
507
pub fn bit_length(x: &[Limb]) -> u32 {
1447
507
    let nlz = leading_zeros(x);
1448
507
    Limb::BITS * x.len() as u32 - nlz
1449
507
}
1450
1451
// RADIX
1452
// -----
1453
1454
/// Get the base, odd radix, and the power-of-two for the type.
1455
#[must_use]
1456
#[inline(always)]
1457
#[cfg(feature = "radix")]
1458
pub const fn split_radix(radix: u32) -> (u32, u32) {
1459
    match radix {
1460
        2 => (0, 1),
1461
        3 => (3, 0),
1462
        4 => (0, 2),
1463
        5 => (5, 0),
1464
        6 => (3, 1),
1465
        7 => (7, 0),
1466
        8 => (0, 3),
1467
        9 => (9, 0),
1468
        10 => (5, 1),
1469
        11 => (11, 0),
1470
        12 => (6, 1),
1471
        13 => (13, 0),
1472
        14 => (7, 1),
1473
        15 => (15, 0),
1474
        16 => (0, 4),
1475
        17 => (17, 0),
1476
        18 => (9, 1),
1477
        19 => (19, 0),
1478
        20 => (5, 2),
1479
        21 => (21, 0),
1480
        22 => (11, 1),
1481
        23 => (23, 0),
1482
        24 => (3, 3),
1483
        25 => (25, 0),
1484
        26 => (13, 1),
1485
        27 => (27, 0),
1486
        28 => (7, 2),
1487
        29 => (29, 0),
1488
        30 => (15, 1),
1489
        31 => (31, 0),
1490
        32 => (0, 5),
1491
        33 => (33, 0),
1492
        34 => (17, 1),
1493
        35 => (35, 0),
1494
        36 => (9, 2),
1495
        // Any other radix should be unreachable.
1496
        _ => (0, 0),
1497
    }
1498
}
1499
1500
/// Get the base, odd radix, and the power-of-two for the type.
1501
#[must_use]
1502
#[inline(always)]
1503
#[cfg(all(feature = "power-of-two", not(feature = "radix")))]
1504
pub const fn split_radix(radix: u32) -> (u32, u32) {
1505
    match radix {
1506
        // Is also needed for decimal floats, due to `negative_digit_comp`.
1507
        2 => (0, 1),
1508
        4 => (0, 2),
1509
        // Is also needed for decimal floats, due to `negative_digit_comp`.
1510
        5 => (5, 0),
1511
        8 => (0, 3),
1512
        10 => (5, 1),
1513
        16 => (0, 4),
1514
        32 => (0, 5),
1515
        // Any other radix should be unreachable.
1516
        _ => (0, 0),
1517
    }
1518
}
1519
1520
/// Get the base, odd radix, and the power-of-two for the type.
1521
#[must_use]
1522
#[inline(always)]
1523
#[cfg(not(feature = "power-of-two"))]
1524
2.22k
pub const fn split_radix(radix: u32) -> (u32, u32) {
1525
2.22k
    match radix {
1526
        // Is also needed for decimal floats, due to `negative_digit_comp`.
1527
853
        2 => (0, 1),
1528
        // Is also needed for decimal floats, due to `negative_digit_comp`.
1529
868
        5 => (5, 0),
1530
507
        10 => (5, 1),
1531
        // Any other radix should be unreachable.
1532
0
        _ => (0, 0),
1533
    }
1534
2.22k
}
1535
1536
// LIMB
1537
// ----
1538
1539
//  Type for a single limb of the big integer.
1540
//
1541
//  A limb is analogous to a digit in base10, except, it stores 32-bit
1542
//  or 64-bit numbers instead. We want types where 64-bit multiplication
1543
//  is well-supported by the architecture, rather than emulated in 3
1544
//  instructions. The quickest way to check this support is using a
1545
//  cross-compiler for numerous architectures, along with the following
1546
//  source file and command:
1547
//
1548
//  Compile with `gcc main.c -c -S -O3 -masm=intel`
1549
//
1550
//  And the source code is:
1551
//  ```text
1552
//  #include <stdint.h>
1553
//
1554
//  struct i128 {
1555
//      uint64_t hi;
1556
//      uint64_t lo;
1557
//  };
1558
//
1559
//  // Type your code here, or load an example.
1560
//  struct i128 square(uint64_t x, uint64_t y) {
1561
//      __int128 prod = (__int128)x * (__int128)y;
1562
//      struct i128 z;
1563
//      z.hi = (uint64_t)(prod >> 64);
1564
//      z.lo = (uint64_t)prod;
1565
//      return z;
1566
//  }
1567
//  ```
1568
//
1569
//  If the result contains `call __multi3`, then the multiplication
1570
//  is emulated by the compiler. Otherwise, it's natively supported.
1571
//
1572
//  This should be all-known 64-bit platforms supported by Rust.
1573
//      https://forge.rust-lang.org/platform-support.html
1574
//
1575
//  # Supported
1576
//
1577
//  Platforms where native 128-bit multiplication is explicitly supported:
1578
//      - x86_64 (Supported via `MUL`).
1579
//      - mips64 (Supported via `DMULTU`, which `HI` and `LO` can be read-from).
1580
//      - s390x (Supported via `MLGR`).
1581
//
1582
//  # Efficient
1583
//
1584
//  Platforms where native 64-bit multiplication is supported and
1585
//  you can extract hi-lo for 64-bit multiplications.
1586
//      - aarch64 (Requires `UMULH` and `MUL` to capture high and low bits).
1587
//      - powerpc64 (Requires `MULHDU` and `MULLD` to capture high and low
1588
//        bits).
1589
//      - riscv64 (Requires `MUL` and `MULH` to capture high and low bits).
1590
//
1591
//  # Unsupported
1592
//
1593
//  Platforms where native 128-bit multiplication is not supported,
1594
//  requiring software emulation.
1595
//      sparc64 (`UMUL` only supports double-word arguments).
1596
//      sparcv9 (Same as sparc64).
1597
//
1598
//  These tests are run via `xcross`, my own library for C cross-compiling,
1599
//  which supports numerous targets (far in excess of Rust's tier 1 support,
1600
//  or rust-embedded/cross's list). xcross may be found here:
1601
//      https://github.com/Alexhuszagh/xcross
1602
//
1603
//  To compile for the given target, run:
1604
//      `xcross gcc main.c -c -S -O3 --target $target`
1605
//
1606
//  All 32-bit architectures inherently do not have support. That means
1607
//  we can essentially look for 64-bit architectures that are not SPARC.
1608
1609
#[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))]
1610
pub type Limb = u64;
1611
#[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))]
1612
pub type Wide = u128;
1613
#[cfg(all(target_pointer_width = "64", not(target_arch = "sparc")))]
1614
pub type SignedWide = i128;
1615
1616
#[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))]
1617
pub type Limb = u32;
1618
#[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))]
1619
pub type Wide = u64;
1620
#[cfg(not(all(target_pointer_width = "64", not(target_arch = "sparc"))))]
1621
pub type SignedWide = i64;