/root/kaspa/kaspa-fuzz/rusty-kaspa/math/src/lehmer.rs
Line
Count
Source
1
//! Variable-time modular inversion via Lehmer's extended-GCD algorithm, fully
2
//! stack-allocated and generic over the operand width (little-endian base-2^64
3
//! limbs). [`LehmerInvert::lehmer_invert`] is the entry point, available on
4
//! every `construct_uint!` type and on primitive `u64`/`u128` (whose native
5
//! division doubles as a reference oracle in tests and fuzzing); the production
6
//! user is the 3072-bit MuHash element.
7
//!
8
//! This is a *Euclidean* extended GCD (true quotients), not the binary
9
//! Bernstein-Yang "safegcd" divstep. The distinction matters: safegcd divides by
10
//! 2 each step, so its cofactors carry a `2^-62k` factor that must be paid down
11
//! with a full-width modular reduction every round, whereas a Euclidean GCD keeps
12
//! a single cofactor pair of clean integers that grow gradually (~`n/2` limbs on
13
//! average) and need only one sign fixup at the end.
14
//!
15
//! Outer loop ([`invert`]): each iteration extracts a 2x2 reduction matrix from
16
//! the aligned top *two* words of the two remainders (the half-GCD guess
17
//! [`hgcd2`]) and applies it to the full remainders ([`apply_matrix_xy`]) and to
18
//! the cofactor pair ([`apply_matrix_t`]), peeling ~62 bits per matrix (~50
19
//! matrices for a 3072-bit inverse). When the guess cannot confirm even one
20
//! quotient it falls back to a single exact Euclidean division step.
21
//!
22
//! The guess ([`hgcd2`]) works on the top two `u64` words: a quotient of 1 is
23
//! resolved by one two-word subtraction and a top-word compare, so a hardware
24
//! divide is needed only for `q >= 2`. A trailing half-limb refinement keeps
25
//! every matrix entry below `2^63`, so the matrix-apply accumulators never
26
//! overflow and carry no per-step guard.
27
//!
28
//! Sign convention: track only `(t0, t1)`, the cofactor of `value`, kept
29
//! non-negative and growing; flip a `swapped` flag on each Euclidean swap and
30
//! recover the answer's sign from it at exit.
31
//!
32
//! Algorithm: Knuth, TAOCP Vol. 2, sec. 4.5.2, Algorithm L. Adapted from the
33
//! MIT-licensed 256-bit implementation by Dean Little (Copyright (c) 2026 Dean
34
//! Little, <https://github.com/blueshift-gg/solana-secp256k1>, `src/lehmer.rs`),
35
//! generalized to arbitrary limb counts with a two-word half-GCD guess. Uses
36
//! native `u128`/`i128` accumulators plus the uint type's own division
37
//! ([`LehmerOps::div_rem`]) for the rare multi-limb-divisor fallback; no
38
//! external dependency.
39
//!
40
//! The limb loops are generic over the concrete `[u64; N]` buffer types
41
//! ([`LimbArray`]) rather than slices, so each width monomorphizes with
42
//! compile-time trip counts and elided bounds checks, keeping the 3072-bit
43
//! codegen equivalent to the pre-generalization fixed-width version (kept
44
//! frozen in `benches/support/lehmer_fixed48.rs` for A/B comparison).
45
46
use core::cmp::Ordering;
47
48
/// Diagnostics-only per-inverse operation counters (enabled with the
49
/// `lehmer-instrument` feature). Used by `examples/lehmer_stats.rs` to measure
50
/// the work distribution. No effect on the production path.
51
#[cfg(feature = "lehmer-instrument")]
52
pub mod instrument {
53
    use core::sync::atomic::AtomicU64;
54
    pub static MATRICES: AtomicU64 = AtomicU64::new(0);
55
    pub static FALLBACK_STEPS: AtomicU64 = AtomicU64::new(0);
56
    pub static DIVIDES: AtomicU64 = AtomicU64::new(0);
57
    pub static APPLY_XY_LIMBS: AtomicU64 = AtomicU64::new(0);
58
    pub static APPLY_T_LIMBS: AtomicU64 = AtomicU64::new(0);
59
    pub static SWAPS: AtomicU64 = AtomicU64::new(0);
60
    pub static INVERSES: AtomicU64 = AtomicU64::new(0);
61
    pub static GCD_DIV_NORM: AtomicU64 = AtomicU64::new(0);
62
}
63
64
macro_rules! count {
65
    ($name:ident += $v:expr) => {{
66
        #[cfg(feature = "lehmer-instrument")]
67
        instrument::$name.fetch_add($v, core::sync::atomic::Ordering::Relaxed);
68
    }};
69
}
70
71
// Invariant checks: `debug_assert!` by default (free in release), promoted to
72
// always-on `assert!` under the `strict-asserts` feature so optimized fuzz and
73
// test builds verify every invariant regardless of `debug-assertions`.
74
#[cfg(not(feature = "strict-asserts"))]
75
macro_rules! strict_assert {
76
    ($($arg:tt)*) => { debug_assert!($($arg)*) };
77
}
78
#[cfg(feature = "strict-asserts")]
79
macro_rules! strict_assert {
80
    ($($arg:tt)*) => { assert!($($arg)*) };
81
}
82
#[cfg(not(feature = "strict-asserts"))]
83
macro_rules! strict_assert_eq {
84
    ($($arg:tt)*) => { debug_assert_eq!($($arg)*) };
85
}
86
#[cfg(feature = "strict-asserts")]
87
macro_rules! strict_assert_eq {
88
    ($($arg:tt)*) => { assert_eq!($($arg)*) };
89
}
90
91
/// Fixed-size little-endian limb buffer, blanket-implemented for every
92
/// `[u64; N]`. The inversion's working storage; keeping the concrete array
93
/// type generic (rather than passing slices around) monomorphizes the limb
94
/// loops per width, so trip counts and bounds stay compile-time constants.
95
pub trait LimbArray: Copy {
96
    const LEN: usize;
97
    const ZERO: Self;
98
    fn as_slice(&self) -> &[u64];
99
    fn as_mut_slice(&mut self) -> &mut [u64];
100
}
101
102
impl<const N: usize> LimbArray for [u64; N] {
103
    const LEN: usize = N;
104
    const ZERO: Self = [0; N];
105
    #[inline(always)]
106
141k
    fn as_slice(&self) -> &[u64] {
107
141k
        self
108
141k
    }
_RNvXNtCs8KLYHAG7u19_10kaspa_math6lehmerAyj3_NtB2_9LimbArray8as_sliceCs3Hi7WNjIpVC_4u192
Line
Count
Source
106
122k
    fn as_slice(&self) -> &[u64] {
107
122k
        self
108
122k
    }
_RNvXNtCs8KLYHAG7u19_10kaspa_math6lehmerAyjb_NtB2_9LimbArray8as_sliceCs3Hi7WNjIpVC_4u192
Line
Count
Source
106
18.7k
    fn as_slice(&self) -> &[u64] {
107
18.7k
        self
108
18.7k
    }
Unexecuted instantiation: _RNvXININtCs8KLYHAG7u19_10kaspa_math6lehmer0KpEAypNtB5_9LimbArray8as_sliceB7_
109
    #[inline(always)]
110
59.9k
    fn as_mut_slice(&mut self) -> &mut [u64] {
111
59.9k
        self
112
59.9k
    }
_RNvXNtCs8KLYHAG7u19_10kaspa_math6lehmerAyj3_NtB2_9LimbArray12as_mut_sliceCs3Hi7WNjIpVC_4u192
Line
Count
Source
110
27.7k
    fn as_mut_slice(&mut self) -> &mut [u64] {
111
27.7k
        self
112
27.7k
    }
_RNvXNtCs8KLYHAG7u19_10kaspa_math6lehmerAyjb_NtB2_9LimbArray12as_mut_sliceCs3Hi7WNjIpVC_4u192
Line
Count
Source
110
32.2k
    fn as_mut_slice(&mut self) -> &mut [u64] {
111
32.2k
        self
112
32.2k
    }
Unexecuted instantiation: _RNvXININtCs8KLYHAG7u19_10kaspa_math6lehmer0KpEAypNtB5_9LimbArray12as_mut_sliceB7_
113
}
114
115
/// Extra limbs every cofactor buffer ([`LehmerOps::Cofactor`]) carries beyond
116
/// the operand width, absorbing carry-out during a matrix application and the
117
/// multi-limb fallback. Compile-time checked per width in [`invert`].
118
pub const COFACTOR_HEADROOM: usize = 8;
119
120
/// What Lehmer inversion needs from a uint type beyond plain limb arithmetic:
121
/// its limb representation and an exact multi-limb division (the rare fallback
122
/// when the two-word guess cannot confirm a quotient, and the defensive branch
123
/// of the final reduction).
124
///
125
/// Implemented by `construct_uint!` for every generated type, and manually for
126
/// primitive `u64`/`u128`.
127
pub trait LehmerOps: Copy {
128
    /// The operand representation, `[u64; N]`.
129
    type Limbs: LimbArray;
130
    /// The cofactor working buffer, `[u64; N + COFACTOR_HEADROOM]`. The
131
    /// cofactor of `value` is bounded in magnitude by the modulus (<= `N`
132
    /// limbs); the extra headroom absorbs carry-out during a matrix
133
    /// application and the multi-limb fallback. Supplied per-impl because
134
    /// stable Rust cannot spell the sum generically.
135
    type Cofactor: LimbArray;
136
    fn from_limbs(limbs: Self::Limbs) -> Self;
137
    fn into_limbs(self) -> Self::Limbs;
138
    /// `(self / other, self % other)`.
139
    fn div_rem(self, other: Self) -> (Self, Self);
140
}
141
142
impl LehmerOps for u64 {
143
    type Limbs = [u64; 1];
144
    type Cofactor = [u64; 1 + COFACTOR_HEADROOM];
145
    #[inline]
146
0
    fn from_limbs(limbs: Self::Limbs) -> Self {
147
0
        limbs[0]
148
0
    }
149
    #[inline]
150
0
    fn into_limbs(self) -> Self::Limbs {
151
0
        [self]
152
0
    }
153
    #[inline]
154
0
    fn div_rem(self, other: Self) -> (Self, Self) {
155
0
        (self / other, self % other)
156
0
    }
157
}
158
159
impl LehmerOps for u128 {
160
    type Limbs = [u64; 2];
161
    type Cofactor = [u64; 2 + COFACTOR_HEADROOM];
162
    #[inline]
163
0
    fn from_limbs(limbs: Self::Limbs) -> Self {
164
0
        ((limbs[1] as u128) << 64) | (limbs[0] as u128)
165
0
    }
166
    #[inline]
167
0
    fn into_limbs(self) -> Self::Limbs {
168
0
        [self as u64, (self >> 64) as u64]
169
0
    }
170
    #[inline]
171
0
    fn div_rem(self, other: Self) -> (Self, Self) {
172
0
        (self / other, self % other)
173
0
    }
174
}
175
176
/// Modular inversion as a method on any [`LehmerOps`] type.
177
pub trait LehmerInvert: Sized {
178
    /// The multiplicative inverse of `self` modulo `modulus`, in `[0, modulus)`.
179
    ///
180
    /// Total over all inputs: `self` is reduced first when `self >= modulus`,
181
    /// and `None` is returned when no inverse exists (`gcd != 1`, which covers
182
    /// a zero residue, or `modulus < 2`).
183
    fn lehmer_invert(self, modulus: Self) -> Option<Self>;
184
}
185
186
impl<U: LehmerOps> LehmerInvert for U {
187
4.94k
    fn lehmer_invert(self, modulus: Self) -> Option<Self> {
188
4.94k
        let m = modulus.into_limbs();
189
4.94k
        let ms = m.as_slice();
190
4.94k
        if ms[0] < 2 && ms[1..].iter().all(|&w| w == 0) {
_RNCNvXs1_NtCs8KLYHAG7u19_10kaspa_math6lehmerNtCs3Hi7WNjIpVC_4u1927Uint192NtB7_12LehmerInvert13lehmer_invert0BI_
Line
Count
Source
190
1.18k
        if ms[0] < 2 && ms[1..].iter().all(|&w| w == 0) {
Unexecuted instantiation: _RNCNvXININtCs8KLYHAG7u19_10kaspa_math6lehmers1_0pEpNtB7_12LehmerInvert13lehmer_invert0B9_
191
0
            return None;
192
4.94k
        }
193
4.94k
        let mut value = self.into_limbs();
194
4.94k
        if cmp_n(value.as_slice(), ms) != Ordering::Less {
195
1.99k
            value = self.div_rem(modulus).1.into_limbs();
196
2.94k
        }
197
4.94k
        let mut out = U::Limbs::ZERO;
198
4.94k
        invert::<U>(value, m, &mut out).then(|| U::from_limbs(out))
_RNCNvXs1_NtCs8KLYHAG7u19_10kaspa_math6lehmerNtCs3Hi7WNjIpVC_4u1927Uint192NtB7_12LehmerInvert13lehmer_inverts_0BI_
Line
Count
Source
198
2.41k
        invert::<U>(value, m, &mut out).then(|| U::from_limbs(out))
Unexecuted instantiation: _RNCNvXININtCs8KLYHAG7u19_10kaspa_math6lehmers1_0pEpNtB7_12LehmerInvert13lehmer_inverts_0B9_
199
4.94k
    }
_RNvXs1_NtCs8KLYHAG7u19_10kaspa_math6lehmerNtCs3Hi7WNjIpVC_4u1927Uint192NtB5_12LehmerInvert13lehmer_invertBG_
Line
Count
Source
187
4.94k
    fn lehmer_invert(self, modulus: Self) -> Option<Self> {
188
4.94k
        let m = modulus.into_limbs();
189
4.94k
        let ms = m.as_slice();
190
4.94k
        if ms[0] < 2 && ms[1..].iter().all(|&w| w == 0) {
191
0
            return None;
192
4.94k
        }
193
4.94k
        let mut value = self.into_limbs();
194
4.94k
        if cmp_n(value.as_slice(), ms) != Ordering::Less {
195
1.99k
            value = self.div_rem(modulus).1.into_limbs();
196
2.94k
        }
197
4.94k
        let mut out = U::Limbs::ZERO;
198
4.94k
        invert::<U>(value, m, &mut out).then(|| U::from_limbs(out))
199
4.94k
    }
Unexecuted instantiation: _RNvXININtCs8KLYHAG7u19_10kaspa_math6lehmers1_0pEpNtB5_12LehmerInvert13lehmer_invertB7_
200
}
201
202
// Matrix entries from `hgcd2` are below `2^63` by construction (the half-limb
203
// refinement discards the least significant half limb), so the `i128`/`u128`
204
// accumulators in the matrix applications cannot overflow
205
// (`a*x + b*y + carry < 2^128` with `a, b < 2^63` and `x, y < 2^64`).
206
207
/// Compute the multiplicative inverse of `value` modulo `modulus` (an odd
208
/// modulus, e.g. the MuHash prime), via Lehmer's extended GCD. `value`,
209
/// `modulus` and `out` are little-endian base-2^64 limb arrays, and `value`
210
/// must already be reduced (`value < modulus`).
211
/// [`LehmerInvert::lehmer_invert`] is the totalized wrapper without the
212
/// reduction precondition.
213
///
214
/// Returns `true` and writes the inverse into `out` when
215
/// `gcd(value, modulus) == 1`; returns `false` (leaving `out` unspecified)
216
/// otherwise. A zero `value` yields `false`.
217
4.94k
pub fn invert<U: LehmerOps>(value: U::Limbs, modulus: U::Limbs, out: &mut U::Limbs) -> bool {
218
    const {
219
        assert!(U::Cofactor::LEN >= U::Limbs::LEN + COFACTOR_HEADROOM, "cofactor buffer lacks the required headroom");
220
    }
221
4.94k
    count!(INVERSES += 1);
222
4.94k
    if is_zero(value.as_slice()) {
223
185
        core::hint::cold_path();
224
185
        return false;
225
4.75k
    }
226
4.75k
    strict_assert!(cmp_n(value.as_slice(), modulus.as_slice()).is_lt(), "invert requires value < modulus");
227
228
    // Euclidean state on (x, y) with x >= y, plus the cofactor of `value`.
229
    // Invariant: x ≡ -t0·value (mod m) and y ≡ t1·value (mod m) when
230
    // `swapped == false`, and the roles flip with each swap. `x`, `y` are owned
231
    // working buffers (they are reduced in place).
232
4.75k
    let mut x: U::Limbs = modulus;
233
4.75k
    let mut y: U::Limbs = value;
234
4.75k
    let mut x_len = top_len(x.as_slice());
235
4.75k
    let mut y_len = top_len(y.as_slice());
236
4.75k
    let mut t0 = U::Cofactor::ZERO;
237
4.75k
    let mut t1 = from_word::<U::Cofactor>(1);
238
4.75k
    let mut t0_len = 1usize; // 0 has conventional length 1
239
4.75k
    let mut t1_len = 1usize;
240
4.75k
    let mut swapped = false;
241
242
    // Multi-limb phase: run until y collapses to a single limb, then finish
243
    // with a u64 extended-Euclidean tail.
244
14.2k
    while y_len > 1 {
245
9.45k
        let (x_hi, y_hi) = highest_two_words_normalized(x.as_slice(), y.as_slice(), x_len);
246
9.45k
        let guess = hgcd2((x_hi >> 64) as u64, x_hi as u64, (y_hi >> 64) as u64, y_hi as u64);
247
248
9.45k
        if let Some((a, b, c, d)) = guess {
249
6.78k
            count!(MATRICES += 1);
250
6.78k
            (x_len, y_len) = apply_matrix_xy(&mut x, &mut y, x_len, a, b, c, d);
251
6.78k
            apply_matrix_t(&mut t0, &mut t1, &mut t0_len, &mut t1_len, a, b, c, d);
252
253
            // A partial guess can leave x < y; restore x >= y, toggling the sign.
254
6.78k
            if x_len < y_len || (x_len == y_len && cmp_prefix(x.as_slice(), y.as_slice(), x_len).is_lt()) {
255
3.23k
                core::mem::swap(&mut x, &mut y);
256
3.23k
                core::mem::swap(&mut x_len, &mut y_len);
257
3.23k
                core::mem::swap(&mut t0, &mut t1);
258
3.23k
                core::mem::swap(&mut t0_len, &mut t1_len);
259
3.23k
                swapped = !swapped;
260
3.54k
            }
261
2.67k
        } else {
262
2.67k
            // The guess almost always confirms a quotient, so this exact-division
263
2.67k
            // path is cold; keep it out of the hot loop body.
264
2.67k
            core::hint::cold_path();
265
2.67k
            count!(FALLBACK_STEPS += 1);
266
2.67k
            // Guess could not confirm a quotient: one exact Euclidean step.
267
2.67k
            let (q, r) = div_rem_step::<U>(&x, &y);
268
2.67k
            t_add_qmul(&mut t0, &mut t0_len, q.as_slice(), &t1, t1_len);
269
2.67k
            x = y;
270
2.67k
            x_len = y_len;
271
2.67k
            y = r;
272
2.67k
            y_len = top_len(y.as_slice());
273
2.67k
            core::mem::swap(&mut t0, &mut t1);
274
2.67k
            core::mem::swap(&mut t0_len, &mut t1_len);
275
2.67k
            swapped = !swapped;
276
2.67k
        }
277
    }
278
279
    // Single-limb tail. `y` is now <= 1 limb; one u64 extended Euclidean step
280
    // replaces the remaining ~tens of `t_add_qmul` iterations.
281
4.75k
    if y_len == 1 && y.as_slice()[0] != 0 {
282
7.50k
        if x.as_slice()[1..].iter().any(|&w| w != 0) {
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer6invertNtCs3Hi7WNjIpVC_4u1927Uint192E0BM_
Line
Count
Source
282
7.50k
        if x.as_slice()[1..].iter().any(|&w| w != 0) {
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer6invertpE0B6_
283
1.95k
            let (q, r) = div_rem_step::<U>(&x, &y);
284
1.95k
            t_add_qmul(&mut t0, &mut t0_len, q.as_slice(), &t1, t1_len);
285
1.95k
            x = from_word(y.as_slice()[0]);
286
1.95k
            y = r;
287
1.95k
            core::mem::swap(&mut t0, &mut t1);
288
1.95k
            core::mem::swap(&mut t0_len, &mut t1_len);
289
1.95k
            swapped = !swapped;
290
2.69k
        }
291
292
4.64k
        let (g, cx, cy) = gcd_ext_u64(x.as_slice()[0], y.as_slice()[0]);
293
294
        // Fold the sign of the chosen cofactor into `swapped`, then combine
295
        // magnitudes: new_t0 = |cx|·t0 + |cy|·t1.
296
4.64k
        if cx < 0 || (cx == 0 && cy > 0) {
297
2.14k
            swapped = !swapped;
298
2.50k
        }
299
4.64k
        let mut new_t0 = U::Cofactor::ZERO;
300
4.64k
        let mut new_t0_len = 1usize;
301
4.64k
        add_mul_word(&mut new_t0, &mut new_t0_len, cx.unsigned_abs(), &t0, t0_len);
302
4.64k
        add_mul_word(&mut new_t0, &mut new_t0_len, cy.unsigned_abs(), &t1, t1_len);
303
4.64k
        t0 = new_t0;
304
305
4.64k
        x = from_word(g);
306
4.64k
        x_len = if g == 0 { 0 } else { 1 };
307
109
    }
308
309
    // For an odd prime modulus and `value` in [1, m), the gcd is 1.
310
4.75k
    if !(x_len == 1 && x.as_slice()[0] == 1) {
311
2.33k
        return false;
312
2.41k
    }
313
314
    // x = 1 = ±t0·value (mod m). With `swapped`, the inverse is +t0; otherwise
315
    // it is -t0 ≡ m - t0. Reduce t0 into [0, m) first.
316
2.41k
    let mut inv = reduce_mod::<U>(&t0, &modulus);
317
2.41k
    if !swapped && !is_zero(inv.as_slice()) {
318
1.20k
        inv = sub_n(&modulus, &inv);
319
1.21k
    }
320
2.41k
    strict_assert!(
321
2.41k
        !is_zero(inv.as_slice()) && cmp_n(inv.as_slice(), modulus.as_slice()).is_lt(),
322
        "invert: result outside (0, modulus)"
323
    );
324
2.41k
    *out = inv;
325
2.41k
    true
326
4.94k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer6invertNtCs3Hi7WNjIpVC_4u1927Uint192EBK_
Line
Count
Source
217
4.94k
pub fn invert<U: LehmerOps>(value: U::Limbs, modulus: U::Limbs, out: &mut U::Limbs) -> bool {
218
    const {
219
        assert!(U::Cofactor::LEN >= U::Limbs::LEN + COFACTOR_HEADROOM, "cofactor buffer lacks the required headroom");
220
    }
221
4.94k
    count!(INVERSES += 1);
222
4.94k
    if is_zero(value.as_slice()) {
223
185
        core::hint::cold_path();
224
185
        return false;
225
4.75k
    }
226
4.75k
    strict_assert!(cmp_n(value.as_slice(), modulus.as_slice()).is_lt(), "invert requires value < modulus");
227
228
    // Euclidean state on (x, y) with x >= y, plus the cofactor of `value`.
229
    // Invariant: x ≡ -t0·value (mod m) and y ≡ t1·value (mod m) when
230
    // `swapped == false`, and the roles flip with each swap. `x`, `y` are owned
231
    // working buffers (they are reduced in place).
232
4.75k
    let mut x: U::Limbs = modulus;
233
4.75k
    let mut y: U::Limbs = value;
234
4.75k
    let mut x_len = top_len(x.as_slice());
235
4.75k
    let mut y_len = top_len(y.as_slice());
236
4.75k
    let mut t0 = U::Cofactor::ZERO;
237
4.75k
    let mut t1 = from_word::<U::Cofactor>(1);
238
4.75k
    let mut t0_len = 1usize; // 0 has conventional length 1
239
4.75k
    let mut t1_len = 1usize;
240
4.75k
    let mut swapped = false;
241
242
    // Multi-limb phase: run until y collapses to a single limb, then finish
243
    // with a u64 extended-Euclidean tail.
244
14.2k
    while y_len > 1 {
245
9.45k
        let (x_hi, y_hi) = highest_two_words_normalized(x.as_slice(), y.as_slice(), x_len);
246
9.45k
        let guess = hgcd2((x_hi >> 64) as u64, x_hi as u64, (y_hi >> 64) as u64, y_hi as u64);
247
248
9.45k
        if let Some((a, b, c, d)) = guess {
249
6.78k
            count!(MATRICES += 1);
250
6.78k
            (x_len, y_len) = apply_matrix_xy(&mut x, &mut y, x_len, a, b, c, d);
251
6.78k
            apply_matrix_t(&mut t0, &mut t1, &mut t0_len, &mut t1_len, a, b, c, d);
252
253
            // A partial guess can leave x < y; restore x >= y, toggling the sign.
254
6.78k
            if x_len < y_len || (x_len == y_len && cmp_prefix(x.as_slice(), y.as_slice(), x_len).is_lt()) {
255
3.23k
                core::mem::swap(&mut x, &mut y);
256
3.23k
                core::mem::swap(&mut x_len, &mut y_len);
257
3.23k
                core::mem::swap(&mut t0, &mut t1);
258
3.23k
                core::mem::swap(&mut t0_len, &mut t1_len);
259
3.23k
                swapped = !swapped;
260
3.54k
            }
261
2.67k
        } else {
262
2.67k
            // The guess almost always confirms a quotient, so this exact-division
263
2.67k
            // path is cold; keep it out of the hot loop body.
264
2.67k
            core::hint::cold_path();
265
2.67k
            count!(FALLBACK_STEPS += 1);
266
2.67k
            // Guess could not confirm a quotient: one exact Euclidean step.
267
2.67k
            let (q, r) = div_rem_step::<U>(&x, &y);
268
2.67k
            t_add_qmul(&mut t0, &mut t0_len, q.as_slice(), &t1, t1_len);
269
2.67k
            x = y;
270
2.67k
            x_len = y_len;
271
2.67k
            y = r;
272
2.67k
            y_len = top_len(y.as_slice());
273
2.67k
            core::mem::swap(&mut t0, &mut t1);
274
2.67k
            core::mem::swap(&mut t0_len, &mut t1_len);
275
2.67k
            swapped = !swapped;
276
2.67k
        }
277
    }
278
279
    // Single-limb tail. `y` is now <= 1 limb; one u64 extended Euclidean step
280
    // replaces the remaining ~tens of `t_add_qmul` iterations.
281
4.75k
    if y_len == 1 && y.as_slice()[0] != 0 {
282
4.64k
        if x.as_slice()[1..].iter().any(|&w| w != 0) {
283
1.95k
            let (q, r) = div_rem_step::<U>(&x, &y);
284
1.95k
            t_add_qmul(&mut t0, &mut t0_len, q.as_slice(), &t1, t1_len);
285
1.95k
            x = from_word(y.as_slice()[0]);
286
1.95k
            y = r;
287
1.95k
            core::mem::swap(&mut t0, &mut t1);
288
1.95k
            core::mem::swap(&mut t0_len, &mut t1_len);
289
1.95k
            swapped = !swapped;
290
2.69k
        }
291
292
4.64k
        let (g, cx, cy) = gcd_ext_u64(x.as_slice()[0], y.as_slice()[0]);
293
294
        // Fold the sign of the chosen cofactor into `swapped`, then combine
295
        // magnitudes: new_t0 = |cx|·t0 + |cy|·t1.
296
4.64k
        if cx < 0 || (cx == 0 && cy > 0) {
297
2.14k
            swapped = !swapped;
298
2.50k
        }
299
4.64k
        let mut new_t0 = U::Cofactor::ZERO;
300
4.64k
        let mut new_t0_len = 1usize;
301
4.64k
        add_mul_word(&mut new_t0, &mut new_t0_len, cx.unsigned_abs(), &t0, t0_len);
302
4.64k
        add_mul_word(&mut new_t0, &mut new_t0_len, cy.unsigned_abs(), &t1, t1_len);
303
4.64k
        t0 = new_t0;
304
305
4.64k
        x = from_word(g);
306
4.64k
        x_len = if g == 0 { 0 } else { 1 };
307
109
    }
308
309
    // For an odd prime modulus and `value` in [1, m), the gcd is 1.
310
4.75k
    if !(x_len == 1 && x.as_slice()[0] == 1) {
311
2.33k
        return false;
312
2.41k
    }
313
314
    // x = 1 = ±t0·value (mod m). With `swapped`, the inverse is +t0; otherwise
315
    // it is -t0 ≡ m - t0. Reduce t0 into [0, m) first.
316
2.41k
    let mut inv = reduce_mod::<U>(&t0, &modulus);
317
2.41k
    if !swapped && !is_zero(inv.as_slice()) {
318
1.20k
        inv = sub_n(&modulus, &inv);
319
1.21k
    }
320
2.41k
    strict_assert!(
321
2.41k
        !is_zero(inv.as_slice()) && cmp_n(inv.as_slice(), modulus.as_slice()).is_lt(),
322
        "invert: result outside (0, modulus)"
323
    );
324
2.41k
    *out = inv;
325
2.41k
    true
326
4.94k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer6invertpEB4_
327
328
/// Two-word subtract `(h1·2^64 + l1) - (h2·2^64 + l2)`, returning `(hi, lo)`.
329
/// Callers guarantee the minuend is the larger, so no underflow off the top.
330
#[inline(always)]
331
71.8k
fn sub2(h1: u64, l1: u64, h2: u64, l2: u64) -> (u64, u64) {
332
71.8k
    let (lo, borrow) = l1.overflowing_sub(l2);
333
71.8k
    (h1.wrapping_sub(h2).wrapping_sub(borrow as u64), lo)
334
71.8k
}
335
336
/// Fold the next half limb up into a fresh full word, `(hi << 32) | (lo >> 32)`,
337
/// for the handoff from the main hgcd2 loop (working on top *words*) to the
338
/// half-limb refinement loop. `hi < 2^32` here, so the result fits a `u64`.
339
#[inline(always)]
340
10.2k
fn fold_half(hi: u64, lo: u64) -> u64 {
341
10.2k
    (hi << 32).wrapping_add(lo >> 32)
342
10.2k
}
343
344
/// The half-GCD guess: from the aligned top *two* words of the remainders
345
/// (`(ah, al) >=~ (bh, bl)`), run Euclidean steps on the 128-bit approximation
346
/// and return the 2x2 reduction matrix in this module's `(a, b, c, d)`
347
/// convention, `(x', y') = (a·x - b·y, d·y - c·x)`. Returns `None` when no
348
/// quotient can be confirmed (the caller then takes one exact division step).
349
///
350
/// A quotient of 1 is resolved by one two-word subtraction and a top-word
351
/// compare, so [`gcd_div`] (the hardware divide) is reached only for `q >= 2`.
352
/// The trailing half-limb refinement (the `HALF_LIMIT_2` loop) keeps every
353
/// matrix entry below `2^63`, which is why the `apply_matrix_*` accumulators
354
/// need no per-step overflow guard. All matrix arithmetic is `wrapping_*`
355
/// (entries are `< 2^63`, so it never actually wraps) to avoid the workspace
356
/// `overflow-checks = true` panic pads.
357
#[inline]
358
9.45k
fn hgcd2(mut ah: u64, mut al: u64, mut bh: u64, mut bl: u64) -> Option<(u64, u64, u64, u64)> {
359
    // Need at least two leading bits of headroom in both top words. The guess
360
    // almost always confirms a quotient, so every `return None` here is cold.
361
9.45k
    if ah < 2 || bh < 2 {
362
954
        core::hint::cold_path();
363
954
        return None;
364
8.50k
    }
365
366
    // Reduction matrix M = (m00 m01; m10 m11), accumulated by the same column
367
    // updates as the full-width apply; returned remapped to (a,b,c,d).
368
    let (mut m00, mut m01, mut m10, mut m11): (u64, u64, u64, u64);
369
8.50k
    if ah > bh || (ah == bh && al > bl) {
370
8.14k
        (ah, al) = sub2(ah, al, bh, bl); // a -= b
371
8.14k
        if ah < 2 {
372
1.36k
            return None;
373
6.78k
        }
374
6.78k
        (m01, m10) = (1, 0);
375
    } else {
376
360
        (bh, bl) = sub2(bh, bl, ah, al); // b -= a
377
360
        if bh < 2 {
378
360
            return None;
379
0
        }
380
0
        (m01, m10) = (0, 1);
381
    }
382
6.78k
    (m00, m11) = (1, 1);
383
384
    const HALF: u32 = 32;
385
    const HALF_LIMIT_1: u64 = 1 << HALF;
386
387
6.78k
    let mut subtract_a = ah < bh;
388
6.78k
    let mut subtract_a1 = false;
389
6.78k
    let mut done = false;
390
    loop {
391
38.4k
        if subtract_a {
392
4.65k
            subtract_a = false;
393
4.65k
        } else {
394
33.8k
            if ah == bh {
395
197
                done = true;
396
197
                break;
397
33.6k
            }
398
33.6k
            if ah < HALF_LIMIT_1 {
399
                // Top words collapsed to a half limb: fold in the next half from
400
                // the low words and finish in the refinement loop below.
401
2.61k
                ah = fold_half(ah, al);
402
2.61k
                bh = fold_half(bh, bl);
403
2.61k
                break;
404
31.0k
            }
405
            // Subtract a -= q·b (affects the second column of M).
406
31.0k
            (ah, al) = sub2(ah, al, bh, bl);
407
31.0k
            if ah < 2 {
408
132
                done = true;
409
132
                break;
410
30.8k
            }
411
30.8k
            if ah <= bh {
412
11.9k
                m01 = m01.wrapping_add(m00); // q = 1: no divide
413
11.9k
                m11 = m11.wrapping_add(m10);
414
11.9k
            } else {
415
18.8k
                let n = ((ah as u128) << 64) | al as u128;
416
18.8k
                let d = ((bh as u128) << 64) | bl as u128;
417
18.8k
                let (mut q, r) = gcd_div(n, d);
418
18.8k
                ah = (r >> 64) as u64;
419
18.8k
                al = r as u64;
420
18.8k
                if ah < 2 {
421
503
                    m01 = m01.wrapping_add(q.wrapping_mul(m00)); // q correct, a too small
422
503
                    m11 = m11.wrapping_add(q.wrapping_mul(m10));
423
503
                    done = true;
424
503
                    break;
425
18.3k
                }
426
18.3k
                q = q.wrapping_add(1); // one subtraction already taken above
427
18.3k
                m01 = m01.wrapping_add(q.wrapping_mul(m00));
428
18.3k
                m11 = m11.wrapping_add(q.wrapping_mul(m10));
429
            }
430
        }
431
35.0k
        if ah == bh {
432
186
            done = true;
433
186
            break;
434
34.8k
        }
435
34.8k
        if bh < HALF_LIMIT_1 {
436
2.49k
            ah = fold_half(ah, al);
437
2.49k
            bh = fold_half(bh, bl);
438
2.49k
            subtract_a1 = true;
439
2.49k
            break;
440
32.3k
        }
441
        // Subtract b -= q·a (affects the first column of M).
442
32.3k
        (bh, bl) = sub2(bh, bl, ah, al);
443
32.3k
        if bh < 2 {
444
123
            done = true;
445
123
            break;
446
32.2k
        }
447
32.2k
        if bh <= ah {
448
11.7k
            m00 = m00.wrapping_add(m01); // q = 1: no divide
449
11.7k
            m10 = m10.wrapping_add(m11);
450
11.7k
        } else {
451
20.4k
            let n = ((bh as u128) << 64) | bl as u128;
452
20.4k
            let d = ((ah as u128) << 64) | al as u128;
453
20.4k
            let (mut q, r) = gcd_div(n, d);
454
20.4k
            bh = (r >> 64) as u64;
455
20.4k
            bl = r as u64;
456
20.4k
            if bh < 2 {
457
534
                m00 = m00.wrapping_add(q.wrapping_mul(m01));
458
534
                m10 = m10.wrapping_add(q.wrapping_mul(m11));
459
534
                done = true;
460
534
                break;
461
19.8k
            }
462
19.8k
            q = q.wrapping_add(1);
463
19.8k
            m00 = m00.wrapping_add(q.wrapping_mul(m01));
464
19.8k
            m10 = m10.wrapping_add(q.wrapping_mul(m11));
465
        }
466
    }
467
468
    // Half-limb refinement: peel a bit more (single-word divides on the folded
469
    // top words) until |a - b| fits in one limb + 1 bit. This is what keeps the
470
    // matrix entries below 2^63, discarding the least significant half limb.
471
6.78k
    if !done {
472
        const HALF_LIMIT_2: u64 = 1 << (HALF + 1);
473
        loop {
474
34.2k
            if subtract_a1 {
475
2.49k
                subtract_a1 = false;
476
2.49k
            } else {
477
31.7k
                ah = ah.wrapping_sub(bh);
478
31.7k
                if ah < HALF_LIMIT_2 {
479
1.26k
                    break;
480
30.4k
                }
481
30.4k
                if ah <= bh {
482
12.5k
                    m01 = m01.wrapping_add(m00);
483
12.5k
                    m11 = m11.wrapping_add(m10);
484
12.5k
                } else {
485
17.9k
                    let q = ah / bh;
486
17.9k
                    ah %= bh;
487
17.9k
                    if ah < HALF_LIMIT_2 {
488
1.35k
                        m01 = m01.wrapping_add(q.wrapping_mul(m00));
489
1.35k
                        m11 = m11.wrapping_add(q.wrapping_mul(m10));
490
1.35k
                        break;
491
16.5k
                    }
492
16.5k
                    let q = q.wrapping_add(1);
493
16.5k
                    m01 = m01.wrapping_add(q.wrapping_mul(m00));
494
16.5k
                    m11 = m11.wrapping_add(q.wrapping_mul(m10));
495
                }
496
            }
497
31.6k
            bh = bh.wrapping_sub(ah);
498
31.6k
            if bh < HALF_LIMIT_2 {
499
1.12k
                break;
500
30.5k
            }
501
30.5k
            if ah >= bh {
502
12.8k
                m00 = m00.wrapping_add(m01);
503
12.8k
                m10 = m10.wrapping_add(m11);
504
12.8k
            } else {
505
17.6k
                let q = bh / ah;
506
17.6k
                bh %= ah;
507
17.6k
                if bh < HALF_LIMIT_2 {
508
1.36k
                    m00 = m00.wrapping_add(q.wrapping_mul(m01));
509
1.36k
                    m10 = m10.wrapping_add(q.wrapping_mul(m11));
510
1.36k
                    break;
511
16.3k
                }
512
16.3k
                let q = q.wrapping_add(1);
513
16.3k
                m00 = m00.wrapping_add(q.wrapping_mul(m01));
514
16.3k
                m10 = m10.wrapping_add(q.wrapping_mul(m11));
515
            }
516
        }
517
1.67k
    }
518
519
    // Every entry stays below 2^63 (the half-limb refinement's exit bound, which
520
    // the `apply_matrix_*` overflow analyses rely on), and the column updates
521
    // preserve the unit determinant of the elementary step matrices.
522
6.78k
    strict_assert!(m00 < 1 << 63 && m01 < 1 << 63 && m10 < 1 << 63 && m11 < 1 << 63, "hgcd2: matrix entry reached 2^63");
523
6.78k
    strict_assert_eq!((m00 as i128) * (m11 as i128) - (m01 as i128) * (m10 as i128), 1, "hgcd2: determinant is not 1");
524
525
    // Remap M to this module's apply convention:
526
    // x' = m11·x - m01·y, y' = m00·y - m10·x.
527
6.78k
    Some((m11, m01, m10, m00))
528
9.45k
}
529
530
/// `(q, r) = (n / d, n % d)` for 128-bit `n, d` with `d >= 2^64`, computed from
531
/// hardware `u64` divisions (via [`div_2by1`]) instead of the `u128 / u128`
532
/// software routine. The quotient is `< 2^64` since `n < 2^128 <= d * 2^64`.
533
#[inline(always)]
534
39.2k
fn gcd_div(n: u128, d: u128) -> (u64, u128) {
535
39.2k
    count!(DIVIDES += 1);
536
39.2k
    let (n1, n0) = ((n >> 64) as u64, n as u64);
537
39.2k
    let (mut d1, mut d0) = ((d >> 64) as u64, d as u64);
538
39.2k
    strict_assert!(d1 != 0);
539
39.2k
    let (q, r) = (n1 / d1, n1 % d1);
540
39.2k
    let (q, rem) = if q > d1 {
541
        // Non-normalized divisor: when `d1`'s top word is small, the single-word
542
        // estimate `q = n1/d1` can exceed `d1`. Rare but genuinely reachable (a
543
        // b-step can drop the divisor below 2^32 before an a-step divides by it),
544
        // so this is required for correctness, not merely defensive; marked cold
545
        // because it is rare. Normalize `d1` to have its top bit set, then do one
546
        // 128/64 division.
547
2.08k
        core::hint::cold_path();
548
2.08k
        count!(GCD_DIV_NORM += 1);
549
2.08k
        let c = d1.leading_zeros();
550
2.08k
        let wc = 64 - c;
551
2.08k
        let n2 = n1 >> wc;
552
2.08k
        let n1n = (n1 << c) | (n0 >> wc);
553
2.08k
        let n0n = n0 << c;
554
2.08k
        d1 = (d1 << c) | (d0 >> wc);
555
2.08k
        d0 <<= c;
556
2.08k
        let (mut q, rem1) = div_2by1(n2, n1n, d1);
557
2.08k
        let prod = (q as u128) * (d0 as u128);
558
2.08k
        let (mut t1, mut t0) = ((prod >> 64) as u64, prod as u64);
559
2.08k
        if t1 > rem1 || (t1 == rem1 && t0 > n0n) {
560
127
            q -= 1;
561
127
            let (nt0, br) = t0.overflowing_sub(d0);
562
127
            t0 = nt0;
563
127
            t1 = t1.wrapping_sub(d1).wrapping_sub(br as u64);
564
1.95k
        }
565
2.08k
        let (rr0, br) = n0n.overflowing_sub(t0);
566
2.08k
        let rr1 = rem1.wrapping_sub(t1).wrapping_sub(br as u64);
567
2.08k
        let rr = ((rr1 as u128) << 64) | rr0 as u128;
568
2.08k
        (q, rr >> c) // undo normalization
569
    } else {
570
37.2k
        let mut q = q;
571
37.2k
        let prod = (q as u128).wrapping_mul(d0 as u128);
572
37.2k
        let (mut t1, mut t0) = ((prod >> 64) as u64, prod as u64);
573
37.2k
        if t1 > r || (t1 == r && t0 > n0) {
574
340
            q -= 1;
575
340
            let (nt0, br) = t0.overflowing_sub(d0);
576
340
            t0 = nt0;
577
340
            t1 = t1.wrapping_sub(d1).wrapping_sub(br as u64);
578
36.8k
        }
579
37.2k
        let (rr0, br) = n0.overflowing_sub(t0);
580
37.2k
        let rr1 = r.wrapping_sub(t1).wrapping_sub(br as u64);
581
37.2k
        (q, ((rr1 as u128) << 64) | rr0 as u128)
582
    };
583
    // Exact reconstruction: cannot wrap for a correct result since q·d + r = n < 2^128.
584
39.2k
    strict_assert!(rem < d && (q as u128).wrapping_mul(d).wrapping_add(rem) == n, "gcd_div: bad quotient or remainder");
585
39.2k
    (q, rem)
586
39.2k
}
587
588
/// Multiply-accumulate: `acc + m·w + carry`, returning `(low 64 bits, high 64
589
/// bits)`. The high word is the carry into the next limb. A single widening
590
/// `64x64->128` multiply plus an add-with-carry; the carry is one word.
591
#[inline(always)]
592
34.6k
fn mac(acc: u64, m: u64, w: u64, carry: u64) -> (u64, u64) {
593
34.6k
    let t = (m as u128).wrapping_mul(w as u128).wrapping_add(acc as u128).wrapping_add(carry as u128);
594
34.6k
    (t as u64, (t >> 64) as u64)
595
34.6k
}
596
597
/// Multiply-subtract-borrow: `acc - m·w - borrow`, returning `(low 64 bits,
598
/// borrow)`. The borrow is the magnitude subtracted off the next limb. It fits
599
/// in one word because callers pass `m < 2^63` (the [`hgcd2`] entry bound), so
600
/// `m·w + borrow < 2^127 + 2^64` and its high word stays below `2^63`.
601
#[inline(always)]
602
34.6k
fn msb(acc: u64, m: u64, w: u64, borrow: u64) -> (u64, u64) {
603
34.6k
    let sub = (m as u128).wrapping_mul(w as u128).wrapping_add(borrow as u128);
604
34.6k
    let (lo, b) = acc.overflowing_sub(sub as u64);
605
34.6k
    (lo, ((sub >> 64) as u64).wrapping_add(b as u64))
606
34.6k
}
607
608
/// `(x, y) <- (a·x - b·y, d·y - c·x)`, over the `len` live limbs only (the
609
/// current larger length), returning the new `(x_len, y_len)`. Both results are
610
/// non-negative and fit in `len` limbs for matrices from [`hgcd2`], so
611
/// the limbs above `len` (already zero) stay zero. Tracking lengths here lets
612
/// passes shrink with the remainders instead of always touching all limbs.
613
///
614
/// Each output uses a multiply-accumulate / multiply-subtract structure: a `mac`
615
/// carry chain for the additive term and an independent `msb` borrow chain for
616
/// the subtractive one, both single-word. Keeping the two chains independent
617
/// shortens the loop-carried dependency versus a fused signed-`i128` accumulator,
618
/// which would serialize a two-register carry plus a per-limb sign-extension
619
/// every step.
620
#[inline]
621
6.78k
fn apply_matrix_xy<A: LimbArray>(x: &mut A, y: &mut A, len: usize, a: u64, b: u64, c: u64, d: u64) -> (usize, usize) {
622
6.78k
    let (x, y) = (x.as_mut_slice(), y.as_mut_slice());
623
    // A single up-front bound: once the compiler knows `len` is within both
624
    // buffers, every `[i]` with `i < len` below is provably in-bounds, so the
625
    // per-limb bounds checks collapse into this one branch and no `unsafe` is
626
    // needed. `len` never exceeds the limb count here, so this never actually
627
    // panics.
628
6.78k
    assert!(len <= x.len() && x.len() == y.len(), "apply_matrix_xy: len exceeds the limb count");
629
6.78k
    count!(APPLY_XY_LIMBS += len as u64);
630
    // x' = a·x - b·y: `carry_ax` accumulates a·x, `borrow_x` peels off b·y.
631
6.78k
    let mut carry_ax: u64 = 0;
632
6.78k
    let mut borrow_x: u64 = 0;
633
    // y' = d·y - c·x.
634
6.78k
    let mut carry_dy: u64 = 0;
635
6.78k
    let mut borrow_y: u64 = 0;
636
637
17.3k
    for i in 0..len {
638
17.3k
        let xi = x[i];
639
17.3k
        let yi = y[i];
640
17.3k
641
17.3k
        let (px, ncx) = mac(0, a, xi, carry_ax);
642
17.3k
        let (nx, nbx) = msb(px, b, yi, borrow_x);
643
17.3k
        carry_ax = ncx;
644
17.3k
        borrow_x = nbx;
645
17.3k
646
17.3k
        let (py, ncy) = mac(0, d, yi, carry_dy);
647
17.3k
        let (ny, nby) = msb(py, c, xi, borrow_y);
648
17.3k
        carry_dy = ncy;
649
17.3k
        borrow_y = nby;
650
17.3k
651
17.3k
        x[i] = nx;
652
17.3k
        y[i] = ny;
653
17.3k
    }
654
    // Non-negative result fitting in `len` limbs: the positive carry-out exactly
655
    // cancels the negative borrow-out (both name the same high limb, which is 0).
656
6.78k
    strict_assert_eq!(carry_ax, borrow_x, "apply_matrix_xy: x went negative or overflowed len limbs");
657
6.78k
    strict_assert_eq!(carry_dy, borrow_y, "apply_matrix_xy: y went negative or overflowed len limbs");
658
659
10.7k
    let nlx = x[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xyAyj3_E0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
659
10.7k
    let nlx = x[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xypE0B6_
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xyAyj3_Es_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
659
6.78k
    let nlx = x[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xypEs_0B6_
660
10.7k
    let nly = y[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xyAyj3_Es0_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
660
10.7k
    let nly = y[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xypEs0_0B6_
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xyAyj3_Es1_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
660
6.78k
    let nly = y[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xypEs1_0B6_
661
6.78k
    (nlx, nly)
662
6.78k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xyAyj3_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
621
6.78k
fn apply_matrix_xy<A: LimbArray>(x: &mut A, y: &mut A, len: usize, a: u64, b: u64, c: u64, d: u64) -> (usize, usize) {
622
6.78k
    let (x, y) = (x.as_mut_slice(), y.as_mut_slice());
623
    // A single up-front bound: once the compiler knows `len` is within both
624
    // buffers, every `[i]` with `i < len` below is provably in-bounds, so the
625
    // per-limb bounds checks collapse into this one branch and no `unsafe` is
626
    // needed. `len` never exceeds the limb count here, so this never actually
627
    // panics.
628
6.78k
    assert!(len <= x.len() && x.len() == y.len(), "apply_matrix_xy: len exceeds the limb count");
629
6.78k
    count!(APPLY_XY_LIMBS += len as u64);
630
    // x' = a·x - b·y: `carry_ax` accumulates a·x, `borrow_x` peels off b·y.
631
6.78k
    let mut carry_ax: u64 = 0;
632
6.78k
    let mut borrow_x: u64 = 0;
633
    // y' = d·y - c·x.
634
6.78k
    let mut carry_dy: u64 = 0;
635
6.78k
    let mut borrow_y: u64 = 0;
636
637
17.3k
    for i in 0..len {
638
17.3k
        let xi = x[i];
639
17.3k
        let yi = y[i];
640
17.3k
641
17.3k
        let (px, ncx) = mac(0, a, xi, carry_ax);
642
17.3k
        let (nx, nbx) = msb(px, b, yi, borrow_x);
643
17.3k
        carry_ax = ncx;
644
17.3k
        borrow_x = nbx;
645
17.3k
646
17.3k
        let (py, ncy) = mac(0, d, yi, carry_dy);
647
17.3k
        let (ny, nby) = msb(py, c, xi, borrow_y);
648
17.3k
        carry_dy = ncy;
649
17.3k
        borrow_y = nby;
650
17.3k
651
17.3k
        x[i] = nx;
652
17.3k
        y[i] = ny;
653
17.3k
    }
654
    // Non-negative result fitting in `len` limbs: the positive carry-out exactly
655
    // cancels the negative borrow-out (both name the same high limb, which is 0).
656
6.78k
    strict_assert_eq!(carry_ax, borrow_x, "apply_matrix_xy: x went negative or overflowed len limbs");
657
6.78k
    strict_assert_eq!(carry_dy, borrow_y, "apply_matrix_xy: y went negative or overflowed len limbs");
658
659
6.78k
    let nlx = x[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
660
6.78k
    let nly = y[..len].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
661
6.78k
    (nlx, nly)
662
6.78k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer15apply_matrix_xypEB4_
663
664
/// `(t0, t1) <- (a·t0 + b·t1, c·t0 + d·t1)`, growing by at most one limb.
665
/// All-positive (the cofactor matrix uses `+` signs), so `u128` accumulators
666
/// suffice. Lengths are tracked inline; the cell at `max_len` is always written
667
/// (carry or zero) to keep `t[len..] == 0` without a separate clearing pass.
668
#[allow(clippy::too_many_arguments)]
669
#[inline]
670
6.78k
fn apply_matrix_t<C: LimbArray>(t0: &mut C, t1: &mut C, t0_len: &mut usize, t1_len: &mut usize, a: u64, b: u64, c: u64, d: u64) {
671
6.78k
    let (t0, t1) = (t0.as_mut_slice(), t1.as_mut_slice());
672
6.78k
    let max_len = (*t0_len).max(*t1_len);
673
6.78k
    count!(APPLY_T_LIMBS += max_len as u64);
674
    // Single up-front bound; see `apply_matrix_xy`. With `max_len` known to be
675
    // within both buffers, the body `[i]` (i < max_len), the carry write
676
    // `[max_len]`, and the length scan (`max_len + 1` limbs) are all provably
677
    // in-bounds, collapsing the per-limb checks into this one branch. The
678
    // cofactor magnitude is bounded by the modulus with 8 limbs of headroom,
679
    // so the bound always holds.
680
6.78k
    assert!(max_len < t0.len() && t0.len() == t1.len(), "cofactor exceeded the cofactor buffer");
681
6.78k
    let (a, b, c, d) = (a as u128, b as u128, c as u128, d as u128);
682
683
6.78k
    let mut c0: u128 = 0;
684
6.78k
    let mut c1: u128 = 0;
685
686
8.95k
    for i in 0..max_len {
687
8.95k
        let ti0 = t0[i] as u128;
688
8.95k
        let ti1 = t1[i] as u128;
689
8.95k
690
8.95k
        let p_at0 = a.wrapping_mul(ti0);
691
8.95k
        let p_bt1 = b.wrapping_mul(ti1);
692
8.95k
        let p_ct0 = c.wrapping_mul(ti0);
693
8.95k
        let p_dt1 = d.wrapping_mul(ti1);
694
8.95k
695
8.95k
        let n0 = c0.wrapping_add(p_at0).wrapping_add(p_bt1);
696
8.95k
        let n1 = c1.wrapping_add(p_ct0).wrapping_add(p_dt1);
697
8.95k
698
8.95k
        t0[i] = n0 as u64;
699
8.95k
        t1[i] = n1 as u64;
700
8.95k
        c0 = n0 >> 64;
701
8.95k
        c1 = n1 >> 64;
702
8.95k
    }
703
    // Carry-out (provably < 2^64); also clears any stale cell at `max_len`.
704
6.78k
    strict_assert!(c0 >> 64 == 0 && c1 >> 64 == 0, "apply_matrix_t: carry-out exceeded one limb");
705
6.78k
    t0[max_len] = c0 as u64;
706
6.78k
    t1[max_len] = c1 as u64;
707
708
10.3k
    let nl0 = t0[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tAyjb_E0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
708
10.3k
    let nl0 = t0[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tpE0B6_
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tAyjb_Es_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
708
6.78k
    let nl0 = t0[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tpEs_0B6_
709
10.1k
    let nl1 = t1[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tAyjb_Es0_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
709
10.1k
    let nl1 = t1[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tpEs0_0B6_
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tAyjb_Es1_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
709
6.78k
    let nl1 = t1[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tpEs1_0B6_
710
6.78k
    *t0_len = nl0.max(1);
711
6.78k
    *t1_len = nl1.max(1);
712
6.78k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tAyjb_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
670
6.78k
fn apply_matrix_t<C: LimbArray>(t0: &mut C, t1: &mut C, t0_len: &mut usize, t1_len: &mut usize, a: u64, b: u64, c: u64, d: u64) {
671
6.78k
    let (t0, t1) = (t0.as_mut_slice(), t1.as_mut_slice());
672
6.78k
    let max_len = (*t0_len).max(*t1_len);
673
6.78k
    count!(APPLY_T_LIMBS += max_len as u64);
674
    // Single up-front bound; see `apply_matrix_xy`. With `max_len` known to be
675
    // within both buffers, the body `[i]` (i < max_len), the carry write
676
    // `[max_len]`, and the length scan (`max_len + 1` limbs) are all provably
677
    // in-bounds, collapsing the per-limb checks into this one branch. The
678
    // cofactor magnitude is bounded by the modulus with 8 limbs of headroom,
679
    // so the bound always holds.
680
6.78k
    assert!(max_len < t0.len() && t0.len() == t1.len(), "cofactor exceeded the cofactor buffer");
681
6.78k
    let (a, b, c, d) = (a as u128, b as u128, c as u128, d as u128);
682
683
6.78k
    let mut c0: u128 = 0;
684
6.78k
    let mut c1: u128 = 0;
685
686
8.95k
    for i in 0..max_len {
687
8.95k
        let ti0 = t0[i] as u128;
688
8.95k
        let ti1 = t1[i] as u128;
689
8.95k
690
8.95k
        let p_at0 = a.wrapping_mul(ti0);
691
8.95k
        let p_bt1 = b.wrapping_mul(ti1);
692
8.95k
        let p_ct0 = c.wrapping_mul(ti0);
693
8.95k
        let p_dt1 = d.wrapping_mul(ti1);
694
8.95k
695
8.95k
        let n0 = c0.wrapping_add(p_at0).wrapping_add(p_bt1);
696
8.95k
        let n1 = c1.wrapping_add(p_ct0).wrapping_add(p_dt1);
697
8.95k
698
8.95k
        t0[i] = n0 as u64;
699
8.95k
        t1[i] = n1 as u64;
700
8.95k
        c0 = n0 >> 64;
701
8.95k
        c1 = n1 >> 64;
702
8.95k
    }
703
    // Carry-out (provably < 2^64); also clears any stale cell at `max_len`.
704
6.78k
    strict_assert!(c0 >> 64 == 0 && c1 >> 64 == 0, "apply_matrix_t: carry-out exceeded one limb");
705
6.78k
    t0[max_len] = c0 as u64;
706
6.78k
    t1[max_len] = c1 as u64;
707
708
6.78k
    let nl0 = t0[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
709
6.78k
    let nl1 = t1[..max_len + 1].iter().rposition(|&w| w != 0).map_or(0, |i| i + 1);
710
6.78k
    *t0_len = nl0.max(1);
711
6.78k
    *t1_len = nl1.max(1);
712
6.78k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer14apply_matrix_tpEB4_
713
714
/// `t0 += q · t1`, where `q` is up to `N` limbs (the exact Euclidean quotient).
715
4.63k
fn t_add_qmul<C: LimbArray>(t0: &mut C, t0_len: &mut usize, q: &[u64], t1: &C, t1_len: usize) {
716
4.63k
    let (t0, t1) = (t0.as_mut_slice(), t1.as_slice());
717
4.63k
    let cap = t0.len();
718
13.8k
    for (i, &qi) in q.iter().enumerate() {
719
13.8k
        if qi == 0 {
720
6.12k
            continue;
721
7.76k
        }
722
7.76k
        let qi = qi as u128;
723
7.76k
        let mut carry: u64 = 0;
724
8.47k
        for (j, &t1j) in t1.iter().enumerate().take(t1_len) {
725
8.47k
            let k = i + j;
726
8.47k
            if k >= cap {
727
0
                strict_assert_eq!(carry, 0, "t_add_qmul: truncated nonzero limb");
728
0
                break;
729
8.47k
            }
730
8.47k
            let prod = qi.wrapping_mul(t1j as u128).wrapping_add(t0[k] as u128).wrapping_add(carry as u128);
731
8.47k
            t0[k] = prod as u64;
732
8.47k
            carry = (prod >> 64) as u64;
733
        }
734
7.76k
        let mut k = i + t1_len;
735
9.33k
        while carry > 0 && k < cap {
736
1.57k
            let (s, c) = t0[k].overflowing_add(carry);
737
1.57k
            t0[k] = s;
738
1.57k
            carry = c as u64;
739
1.57k
            k += 1;
740
1.57k
        }
741
7.76k
        strict_assert!(carry == 0, "t_add_qmul: carry lost off the top");
742
    }
743
4.63k
    *t0_len = top_len_t(t0);
744
4.63k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10t_add_qmulAyjb_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
715
4.63k
fn t_add_qmul<C: LimbArray>(t0: &mut C, t0_len: &mut usize, q: &[u64], t1: &C, t1_len: usize) {
716
4.63k
    let (t0, t1) = (t0.as_mut_slice(), t1.as_slice());
717
4.63k
    let cap = t0.len();
718
13.8k
    for (i, &qi) in q.iter().enumerate() {
719
13.8k
        if qi == 0 {
720
6.12k
            continue;
721
7.76k
        }
722
7.76k
        let qi = qi as u128;
723
7.76k
        let mut carry: u64 = 0;
724
8.47k
        for (j, &t1j) in t1.iter().enumerate().take(t1_len) {
725
8.47k
            let k = i + j;
726
8.47k
            if k >= cap {
727
0
                strict_assert_eq!(carry, 0, "t_add_qmul: truncated nonzero limb");
728
0
                break;
729
8.47k
            }
730
8.47k
            let prod = qi.wrapping_mul(t1j as u128).wrapping_add(t0[k] as u128).wrapping_add(carry as u128);
731
8.47k
            t0[k] = prod as u64;
732
8.47k
            carry = (prod >> 64) as u64;
733
        }
734
7.76k
        let mut k = i + t1_len;
735
9.33k
        while carry > 0 && k < cap {
736
1.57k
            let (s, c) = t0[k].overflowing_add(carry);
737
1.57k
            t0[k] = s;
738
1.57k
            carry = c as u64;
739
1.57k
            k += 1;
740
1.57k
        }
741
7.76k
        strict_assert!(carry == 0, "t_add_qmul: carry lost off the top");
742
    }
743
4.63k
    *t0_len = top_len_t(t0);
744
4.63k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10t_add_qmulpEB4_
745
746
/// `out += w · t` (multi-limb unsigned), used by the single-limb tail.
747
9.29k
fn add_mul_word<C: LimbArray>(out: &mut C, out_len: &mut usize, w: u64, t: &C, t_len: usize) {
748
9.29k
    let (out, t) = (out.as_mut_slice(), t.as_slice());
749
9.29k
    let cap = out.len();
750
9.29k
    if w != 0 {
751
8.63k
        let w = w as u128;
752
8.63k
        let mut carry: u64 = 0;
753
18.9k
        for j in 0..t_len {
754
            // `j < t_len <= cap` always, but the bound also lets the compiler
755
            // clamp the trip count and skip the per-limb bounds check.
756
18.9k
            if j >= cap {
757
0
                break;
758
18.9k
            }
759
18.9k
            let prod = w.wrapping_mul(t[j] as u128).wrapping_add(out[j] as u128).wrapping_add(carry as u128);
760
18.9k
            out[j] = prod as u64;
761
18.9k
            carry = (prod >> 64) as u64;
762
        }
763
8.63k
        let mut k = t_len;
764
10.1k
        while carry > 0 && k < cap {
765
1.53k
            let (s, c) = out[k].overflowing_add(carry);
766
1.53k
            out[k] = s;
767
1.53k
            carry = c as u64;
768
1.53k
            k += 1;
769
1.53k
        }
770
8.63k
        strict_assert!(carry == 0, "add_mul_word: carry lost off the top");
771
666
    }
772
9.29k
    *out_len = top_len_t(out);
773
9.29k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12add_mul_wordAyjb_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
747
9.29k
fn add_mul_word<C: LimbArray>(out: &mut C, out_len: &mut usize, w: u64, t: &C, t_len: usize) {
748
9.29k
    let (out, t) = (out.as_mut_slice(), t.as_slice());
749
9.29k
    let cap = out.len();
750
9.29k
    if w != 0 {
751
8.63k
        let w = w as u128;
752
8.63k
        let mut carry: u64 = 0;
753
18.9k
        for j in 0..t_len {
754
            // `j < t_len <= cap` always, but the bound also lets the compiler
755
            // clamp the trip count and skip the per-limb bounds check.
756
18.9k
            if j >= cap {
757
0
                break;
758
18.9k
            }
759
18.9k
            let prod = w.wrapping_mul(t[j] as u128).wrapping_add(out[j] as u128).wrapping_add(carry as u128);
760
18.9k
            out[j] = prod as u64;
761
18.9k
            carry = (prod >> 64) as u64;
762
        }
763
8.63k
        let mut k = t_len;
764
10.1k
        while carry > 0 && k < cap {
765
1.53k
            let (s, c) = out[k].overflowing_add(carry);
766
1.53k
            out[k] = s;
767
1.53k
            carry = c as u64;
768
1.53k
            k += 1;
769
1.53k
        }
770
8.63k
        strict_assert!(carry == 0, "add_mul_word: carry lost off the top");
771
666
    }
772
9.29k
    *out_len = top_len_t(out);
773
9.29k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12add_mul_wordpEB4_
774
775
/// `(q, r) = (x / y, x % y)`. Fast path for a single-limb divisor (the common
776
/// case once Lehmer has shrunk `y`); otherwise the uint type's own
777
/// [`LehmerOps::div_rem`].
778
4.63k
fn div_rem_step<U: LehmerOps>(x: &U::Limbs, y: &U::Limbs) -> (U::Limbs, U::Limbs) {
779
6.75k
    if y.as_slice()[1..].iter().all(|&w| w == 0) {
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12div_rem_stepNtCs3Hi7WNjIpVC_4u1927Uint192E0BT_
Line
Count
Source
779
6.75k
    if y.as_slice()[1..].iter().all(|&w| w == 0) {
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12div_rem_steppE0B6_
780
1.95k
        let (q, r0) = div_n_by_1(x, y.as_slice()[0]);
781
1.95k
        return (q, from_word(r0));
782
2.67k
    }
783
2.67k
    let (q, r) = U::from_limbs(*x).div_rem(U::from_limbs(*y));
784
2.67k
    (q.into_limbs(), r.into_limbs())
785
4.63k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12div_rem_stepNtCs3Hi7WNjIpVC_4u1927Uint192EBR_
Line
Count
Source
778
4.63k
fn div_rem_step<U: LehmerOps>(x: &U::Limbs, y: &U::Limbs) -> (U::Limbs, U::Limbs) {
779
4.63k
    if y.as_slice()[1..].iter().all(|&w| w == 0) {
780
1.95k
        let (q, r0) = div_n_by_1(x, y.as_slice()[0]);
781
1.95k
        return (q, from_word(r0));
782
2.67k
    }
783
2.67k
    let (q, r) = U::from_limbs(*x).div_rem(U::from_limbs(*y));
784
2.67k
    (q.into_limbs(), r.into_limbs())
785
4.63k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer12div_rem_steppEB4_
786
787
/// `(q, r) = (x / d, x % d)` for a nonzero single-limb divisor `d` (the common
788
/// case once Lehmer has collapsed `y`). The divisor is constant across all
789
/// limbs, so a reciprocal is computed once and each limb costs two multiplies
790
/// instead of a hardware divide. Precomputed-reciprocal division
791
/// (Moller-Granlund, 2011).
792
1.95k
fn div_n_by_1<A: LimbArray>(x: &A, d: u64) -> (A, u64) {
793
1.95k
    strict_assert!(d != 0);
794
1.95k
    let x = x.as_slice();
795
1.95k
    let n = x.len();
796
1.95k
    let mut q = A::ZERO;
797
1.95k
    let qs = q.as_mut_slice();
798
1.95k
    let s = d.leading_zeros();
799
1.95k
    let r = if s == 0 {
800
        // `d` already has its top bit set: no normalization shift needed.
801
560
        let v = invert_limb(d);
802
560
        let mut r: u64 = 0;
803
1.68k
        for i in (0..n).rev() {
804
1.68k
            (qs[i], r) = div_2by1_preinv(r, x[i], d, v);
805
1.68k
        }
806
560
        r
807
    } else {
808
        // Normalize: divide `x << s` by `d << s` (same quotient); the bits shifted
809
        // off the top of `x` seed the running remainder, and `x % d = r >> s`.
810
1.39k
        let d_norm = d << s;
811
1.39k
        let v = invert_limb(d_norm);
812
1.39k
        let mut r = x[n - 1] >> (64 - s);
813
4.18k
        for i in (0..n).rev() {
814
4.18k
            let lo = if i == 0 { 0 } else { x[i - 1] };
815
4.18k
            let cur = (x[i] << s) | (lo >> (64 - s));
816
4.18k
            (qs[i], r) = div_2by1_preinv(r, cur, d_norm, v);
817
        }
818
1.39k
        r >> s
819
    };
820
1.95k
    strict_assert!(r < d, "div_n_by_1: remainder not below the divisor");
821
1.95k
    (q, r)
822
1.95k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10div_n_by_1Ayj3_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
792
1.95k
fn div_n_by_1<A: LimbArray>(x: &A, d: u64) -> (A, u64) {
793
1.95k
    strict_assert!(d != 0);
794
1.95k
    let x = x.as_slice();
795
1.95k
    let n = x.len();
796
1.95k
    let mut q = A::ZERO;
797
1.95k
    let qs = q.as_mut_slice();
798
1.95k
    let s = d.leading_zeros();
799
1.95k
    let r = if s == 0 {
800
        // `d` already has its top bit set: no normalization shift needed.
801
560
        let v = invert_limb(d);
802
560
        let mut r: u64 = 0;
803
1.68k
        for i in (0..n).rev() {
804
1.68k
            (qs[i], r) = div_2by1_preinv(r, x[i], d, v);
805
1.68k
        }
806
560
        r
807
    } else {
808
        // Normalize: divide `x << s` by `d << s` (same quotient); the bits shifted
809
        // off the top of `x` seed the running remainder, and `x % d = r >> s`.
810
1.39k
        let d_norm = d << s;
811
1.39k
        let v = invert_limb(d_norm);
812
1.39k
        let mut r = x[n - 1] >> (64 - s);
813
4.18k
        for i in (0..n).rev() {
814
4.18k
            let lo = if i == 0 { 0 } else { x[i - 1] };
815
4.18k
            let cur = (x[i] << s) | (lo >> (64 - s));
816
4.18k
            (qs[i], r) = div_2by1_preinv(r, cur, d_norm, v);
817
        }
818
1.39k
        r >> s
819
    };
820
1.95k
    strict_assert!(r < d, "div_n_by_1: remainder not below the divisor");
821
1.95k
    (q, r)
822
1.95k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10div_n_by_1pEB4_
823
824
/// Reciprocal of a normalized 64-bit divisor `d` (top bit set):
825
/// `v = floor((2^128 - 1) / d) - 2^64`, the "3/2" reciprocal consumed by
826
/// [`div_2by1_preinv`] (Moller-Granlund, "Improved division by invariant
827
/// integers", 2011). The lone wide divide here runs once per [`div_n_by_1`]
828
/// call (amortized over all `N` limbs), so it is off the per-limb hot path.
829
#[inline]
830
1.95k
const fn invert_limb(d: u64) -> u64 {
831
1.95k
    strict_assert!(d >> 63 == 1, "invert_limb requires a normalized divisor");
832
    // v = floor((2^128 - 1) / d) - 2^64 = floor(((!d)·2^64 + !0) / d): subtracting
833
    // 2^64·d from the numerator drops the quotient by exactly 2^64, and that
834
    // numerator's high word `!d` is `< d` for a normalized `d`, so the quotient
835
    // fits a u64 and the software 128/64 [`div_2by1`] computes it -- avoiding the
836
    // slow `u128 / u128` (`__udivti3`).
837
1.95k
    div_2by1(!d, u64::MAX, d).0
838
1.95k
}
839
840
/// `(nh·2^64 + nl) / d -> (q, r)` via the precomputed reciprocal `di` from
841
/// [`invert_limb`]. Requires `d` normalized (top bit set) and `nh < d` (so the
842
/// quotient fits a `u64`); the returned `r` satisfies `r < d`, sustaining that
843
/// precondition limb to limb. One widening multiply, a branchless first
844
/// correction, and a rarely-taken second. All `wrapping_*` (the workspace builds
845
/// with `overflow-checks = true`).
846
#[inline(always)]
847
5.86k
fn div_2by1_preinv(nh: u64, nl: u64, d: u64, di: u64) -> (u64, u64) {
848
5.86k
    strict_assert!(d >> 63 == 1 && nh < d);
849
    // (qh:ql) = nh·di + (nh + 1)·2^64 + nl
850
5.86k
    let prod = (nh as u128).wrapping_mul(di as u128);
851
5.86k
    let (mut qh, ql) = ((prod >> 64) as u64, prod as u64);
852
5.86k
    let (ql, carry) = ql.overflowing_add(nl);
853
5.86k
    qh = qh.wrapping_add(nh.wrapping_add(1)).wrapping_add(carry as u64);
854
855
5.86k
    let mut r = nl.wrapping_sub(qh.wrapping_mul(d));
856
    // First correction: if the estimate `qh` is one too high, `r` wraps above
857
    // `ql`; `mask` is all-ones then, folding the `-1`/`+d` fixup in branch-free.
858
5.86k
    let mask = 0u64.wrapping_sub((r > ql) as u64);
859
5.86k
    qh = qh.wrapping_add(mask);
860
5.86k
    r = r.wrapping_add(mask & d);
861
    // Second correction (rare): a still-too-small quotient leaves `r >= d`.
862
5.86k
    if r >= d {
863
13
        r = r.wrapping_sub(d);
864
13
        qh = qh.wrapping_add(1);
865
5.85k
    }
866
5.86k
    strict_assert!(r < d, "div_2by1_preinv: remainder not below the divisor");
867
5.86k
    (qh, r)
868
5.86k
}
869
870
/// `(hi·2^64 + lo) / d -> (q, r)`. Knuth Algorithm D specialized to 128/64.
871
/// Precondition: `d != 0` and `hi < d` (so the quotient fits in a `u64`).
872
///
873
/// Not on the per-limb hot path (that goes through [`div_n_by_1`]'s reciprocal
874
/// step, [`div_2by1_preinv`]): this generic divide is reached only once per
875
/// [`div_n_by_1`] (to seed the reciprocal, via [`invert_limb`]) and from
876
/// [`gcd_div`]'s rare normalization branch, so a plain software long division is
877
/// fine.
878
#[inline]
879
4.03k
const fn div_2by1(hi: u64, lo: u64, d: u64) -> (u64, u64) {
880
4.03k
    strict_assert!(d != 0);
881
4.03k
    strict_assert!(hi < d, "div_2by1 quotient would overflow u64");
882
883
4.03k
    let s = d.leading_zeros();
884
4.03k
    let dn = if s == 0 { d } else { d << s };
885
4.03k
    let un32 = if s == 0 { hi } else { (hi << s) | (lo >> (64 - s)) };
886
4.03k
    let un10 = if s == 0 { lo } else { lo << s };
887
888
4.03k
    let vn1 = dn >> 32;
889
4.03k
    let vn0 = dn & 0xFFFF_FFFF;
890
4.03k
    let un1 = un10 >> 32;
891
4.03k
    let un0 = un10 & 0xFFFF_FFFF;
892
893
4.03k
    let mut q1 = un32 / vn1;
894
4.03k
    let mut rhat = un32 - q1 * vn1;
895
4.24k
    while q1 >= (1u64 << 32) || q1 * vn0 > (rhat << 32) | un1 {
896
463
        q1 -= 1;
897
463
        rhat += vn1;
898
463
        if rhat >= (1u64 << 32) {
899
254
            break;
900
209
        }
901
    }
902
903
4.03k
    let un21 = (un32 << 32).wrapping_add(un1).wrapping_sub(q1.wrapping_mul(dn));
904
4.03k
    let mut q0 = un21 / vn1;
905
4.03k
    let mut rhat = un21 - q0 * vn1;
906
4.35k
    while q0 >= (1u64 << 32) || q0 * vn0 > (rhat << 32) | un0 {
907
822
        q0 -= 1;
908
822
        rhat += vn1;
909
822
        if rhat >= (1u64 << 32) {
910
502
            break;
911
320
        }
912
    }
913
914
4.03k
    let r = (un21 << 32).wrapping_add(un0).wrapping_sub(q0.wrapping_mul(dn)) >> s;
915
4.03k
    let q = (q1 << 32) | q0;
916
4.03k
    strict_assert!(
917
4.03k
        r < d && (q as u128).wrapping_mul(d as u128).wrapping_add(r as u128) == ((hi as u128) << 64) | lo as u128,
918
        "div_2by1: bad quotient or remainder"
919
    );
920
4.03k
    (q, r)
921
4.03k
}
922
923
/// Extended Euclidean GCD of two `u64`s: `(gcd, cx, cy)` with `cx·x + cy·y = g`.
924
/// Called once per inversion, so `i128` intermediates are fine.
925
4.64k
fn gcd_ext_u64(mut x: u64, mut y: u64) -> (u64, i64, i64) {
926
4.64k
    let (x0, y0) = (x as i128, y as i128);
927
4.64k
    let (mut a, mut b, mut c, mut d) = (1i128, 0i128, 0i128, 1i128);
928
61.8k
    while y != 0 {
929
57.1k
        let q = (x / y) as i128;
930
57.1k
        let r = x.wrapping_sub((q as u64).wrapping_mul(y));
931
57.1k
        let (nc, nd) = (a.wrapping_sub(q.wrapping_mul(c)), b.wrapping_sub(q.wrapping_mul(d)));
932
57.1k
        a = c;
933
57.1k
        b = d;
934
57.1k
        c = nc;
935
57.1k
        d = nd;
936
57.1k
        x = y;
937
57.1k
        y = r;
938
57.1k
    }
939
    // Cofactors are bounded by the inputs (so the i64 narrowing is lossless) and
940
    // satisfy the Bezout identity for the returned gcd.
941
4.64k
    strict_assert!(i64::try_from(a).is_ok() && i64::try_from(b).is_ok(), "gcd_ext_u64: cofactor overflowed i64");
942
4.64k
    strict_assert_eq!(a.wrapping_mul(x0).wrapping_add(b.wrapping_mul(y0)), x as i128, "gcd_ext_u64: Bezout identity failed");
943
4.64k
    (x, a as i64, b as i64)
944
4.64k
}
945
946
/// Reduce a cofactor (with at most the modulus' significant limbs) into
947
/// `[0, m)`. The cofactor is bounded by `m` at loop exit, so a few
948
/// subtractions suffice; the `div_rem` branch is a defensive fallback.
949
2.41k
fn reduce_mod<U: LehmerOps>(value: &U::Cofactor, m: &U::Limbs) -> U::Limbs {
950
2.41k
    let n = U::Limbs::LEN;
951
19.3k
    strict_assert!(value.as_slice()[n..].iter().all(|&w| w == 0), "cofactor exceeded the modulus width");
_RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10reduce_modNtCs3Hi7WNjIpVC_4u1927Uint192E0BR_
Line
Count
Source
951
19.3k
    strict_assert!(value.as_slice()[n..].iter().all(|&w| w == 0), "cofactor exceeded the modulus width");
Unexecuted instantiation: _RNCINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10reduce_modpE0B6_
952
2.41k
    let mut out = U::Limbs::ZERO;
953
2.41k
    out.as_mut_slice().copy_from_slice(&value.as_slice()[..n]);
954
2.41k
    for _ in 0..8 {
955
2.41k
        if cmp_n(out.as_slice(), m.as_slice()).is_lt() {
956
2.41k
            return out;
957
0
        }
958
0
        out = sub_n(&out, m);
959
    }
960
0
    U::from_limbs(out).div_rem(U::from_limbs(*m)).1.into_limbs()
961
2.41k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10reduce_modNtCs3Hi7WNjIpVC_4u1927Uint192EBP_
Line
Count
Source
949
2.41k
fn reduce_mod<U: LehmerOps>(value: &U::Cofactor, m: &U::Limbs) -> U::Limbs {
950
2.41k
    let n = U::Limbs::LEN;
951
2.41k
    strict_assert!(value.as_slice()[n..].iter().all(|&w| w == 0), "cofactor exceeded the modulus width");
952
2.41k
    let mut out = U::Limbs::ZERO;
953
2.41k
    out.as_mut_slice().copy_from_slice(&value.as_slice()[..n]);
954
2.41k
    for _ in 0..8 {
955
2.41k
        if cmp_n(out.as_slice(), m.as_slice()).is_lt() {
956
2.41k
            return out;
957
0
        }
958
0
        out = sub_n(&out, m);
959
    }
960
0
    U::from_limbs(out).div_rem(U::from_limbs(*m)).1.into_limbs()
961
2.41k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer10reduce_modpEB4_
962
963
/// Top 128-bit prefix of `x` and of `y`, both shifted left by the same amount so
964
/// the prefix of the larger operand `x` has its top bit set (the normalization
965
/// [`hgcd2`] expects). `y` is read at the same limb positions as `x`, so its
966
/// prefix is naturally the smaller. Requires `x` the larger operand and
967
/// `x_len >= 2`.
968
#[inline]
969
9.45k
fn highest_two_words_normalized(x: &[u64], y: &[u64], x_len: usize) -> (u128, u128) {
970
9.45k
    strict_assert!(x_len >= 2);
971
9.45k
    let i = x_len - 1;
972
9.45k
    let lz = x[i].leading_zeros();
973
9.45k
    let lo_idx_ok = i >= 2;
974
    // Combine the limbs at positions (i, i-1, i-2) into the top 128 bits after a
975
    // left shift by `lz`. `arr[i]`'s `lz` leading zeros guarantee no overflow.
976
18.9k
    let combine = |hi: u64, mid: u64, lo: u64| -> u128 {
977
18.9k
        let base = ((hi as u128) << 64) | (mid as u128);
978
18.9k
        if lz == 0 { base } else { (base << lz) | ((lo >> (64 - lz)) as u128) }
979
18.9k
    };
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer28highest_two_words_normalized0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
976
18.9k
    let combine = |hi: u64, mid: u64, lo: u64| -> u128 {
977
18.9k
        let base = ((hi as u128) << 64) | (mid as u128);
978
18.9k
        if lz == 0 { base } else { (base << lz) | ((lo >> (64 - lz)) as u128) }
979
18.9k
    };
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer28highest_two_words_normalized0B5_
980
9.45k
    let x_lo = if lo_idx_ok { x[i - 2] } else { 0 };
981
9.45k
    let y_lo = if lo_idx_ok { y[i - 2] } else { 0 };
982
9.45k
    let (x_hi, y_hi) = (combine(x[i], x[i - 1], x_lo), combine(y[i], y[i - 1], y_lo));
983
9.45k
    strict_assert!(x_hi >> 127 == 1 && y_hi <= x_hi, "highest_two_words_normalized: prefixes unnormalized or misordered");
984
9.45k
    (x_hi, y_hi)
985
9.45k
}
986
987
/// A limb buffer holding the single word `w`.
988
#[inline]
989
13.3k
fn from_word<A: LimbArray>(w: u64) -> A {
990
13.3k
    let mut a = A::ZERO;
991
13.3k
    a.as_mut_slice()[0] = w;
992
13.3k
    a
993
13.3k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer9from_wordAyj3_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
989
8.55k
fn from_word<A: LimbArray>(w: u64) -> A {
990
8.55k
    let mut a = A::ZERO;
991
8.55k
    a.as_mut_slice()[0] = w;
992
8.55k
    a
993
8.55k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer9from_wordAyjb_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
989
4.75k
fn from_word<A: LimbArray>(w: u64) -> A {
990
4.75k
    let mut a = A::ZERO;
991
4.75k
    a.as_mut_slice()[0] = w;
992
4.75k
    a
993
4.75k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer9from_wordpEB4_
994
995
#[inline]
996
8.56k
fn is_zero(x: &[u64]) -> bool {
997
10.5k
    x.iter().all(|&w| w == 0)
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7is_zero0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
997
10.5k
    x.iter().all(|&w| w == 0)
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7is_zero0B5_
998
8.56k
}
999
1000
#[inline]
1001
12.1k
fn top_len(x: &[u64]) -> usize {
1002
20.3k
    x.iter().rposition(|&w| w != 0).map_or(0, |i| i + 1)
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7top_len0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
1002
20.3k
    x.iter().rposition(|&w| w != 0).map_or(0, |i| i + 1)
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7top_len0B5_
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7top_lens_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
1002
12.0k
    x.iter().rposition(|&w| w != 0).map_or(0, |i| i + 1)
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer7top_lens_0B5_
1003
12.1k
}
1004
1005
/// Significant length of a cofactor buffer; 0 maps to 1 by convention.
1006
#[inline]
1007
13.9k
fn top_len_t(x: &[u64]) -> usize {
1008
137k
    x.iter().rposition(|&w| w != 0).map_or(1, |i| i + 1)
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer9top_len_t0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
1008
137k
    x.iter().rposition(|&w| w != 0).map_or(1, |i| i + 1)
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer9top_len_t0B5_
_RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer9top_len_ts_0Cs3Hi7WNjIpVC_4u192
Line
Count
Source
1008
13.1k
    x.iter().rposition(|&w| w != 0).map_or(1, |i| i + 1)
Unexecuted instantiation: _RNCNvNtCs8KLYHAG7u19_10kaspa_math6lehmer9top_len_ts_0B5_
1009
13.9k
}
1010
1011
#[inline]
1012
1.20k
fn sub_n<A: LimbArray>(a: &A, b: &A) -> A {
1013
1.20k
    let mut out = A::ZERO;
1014
1.20k
    let (a, b, o) = (a.as_slice(), b.as_slice(), out.as_mut_slice());
1015
1.20k
    let mut borrow = 0u64;
1016
3.61k
    for i in 0..o.len() {
1017
3.61k
        let (d1, b1) = a[i].overflowing_sub(b[i]);
1018
3.61k
        let (d2, b2) = d1.overflowing_sub(borrow);
1019
3.61k
        o[i] = d2;
1020
3.61k
        borrow = (b1 | b2) as u64;
1021
3.61k
    }
1022
1.20k
    out
1023
1.20k
}
_RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer5sub_nAyj3_ECs3Hi7WNjIpVC_4u192
Line
Count
Source
1012
1.20k
fn sub_n<A: LimbArray>(a: &A, b: &A) -> A {
1013
1.20k
    let mut out = A::ZERO;
1014
1.20k
    let (a, b, o) = (a.as_slice(), b.as_slice(), out.as_mut_slice());
1015
1.20k
    let mut borrow = 0u64;
1016
3.61k
    for i in 0..o.len() {
1017
3.61k
        let (d1, b1) = a[i].overflowing_sub(b[i]);
1018
3.61k
        let (d2, b2) = d1.overflowing_sub(borrow);
1019
3.61k
        o[i] = d2;
1020
3.61k
        borrow = (b1 | b2) as u64;
1021
3.61k
    }
1022
1.20k
    out
1023
1.20k
}
Unexecuted instantiation: _RINvNtCs8KLYHAG7u19_10kaspa_math6lehmer5sub_npEB4_
1024
1025
/// Full-width limb compare of two equal-length buffers.
1026
#[inline]
1027
14.5k
fn cmp_n(a: &[u64], b: &[u64]) -> Ordering {
1028
14.5k
    strict_assert_eq!(a.len(), b.len());
1029
14.5k
    cmp_prefix(a, b, a.len())
1030
14.5k
}
1031
1032
#[inline]
1033
21.1k
fn cmp_prefix(a: &[u64], b: &[u64], n: usize) -> Ordering {
1034
27.7k
    for i in (0..n).rev() {
1035
27.7k
        match a[i].cmp(&b[i]) {
1036
7.03k
            Ordering::Equal => continue,
1037
20.7k
            other => return other,
1038
        }
1039
    }
1040
393
    Ordering::Equal
1041
21.1k
}
1042
1043
#[cfg(test)]
1044
mod tests {
1045
    use super::*;
1046
    use crate::Uint3072;
1047
    use rand_chacha::{
1048
        ChaCha8Rng,
1049
        rand_core::{RngCore, SeedableRng},
1050
    };
1051
1052
    const N: usize = 48;
1053
1054
    // MuHash prime: 2^3072 - 1103717.
1055
    const MUHASH_PRIME: Uint3072 = {
1056
        let mut max = Uint3072::MAX;
1057
        max.0[0] -= 1103717 - 1;
1058
        max
1059
    };
1060
1061
    fn lehmer_inv(value: [u64; N], modulus: [u64; N]) -> Option<[u64; N]> {
1062
        let mut out = [0u64; N];
1063
        invert::<Uint3072>(value, modulus, &mut out).then_some(out)
1064
    }
1065
1066
    // Malachite reference oracle over any LehmerOps type. The generic `Uint::mod_inverse` was
1067
    // removed, so this calls malachite's `Natural::mod_inverse` directly (malachite is a
1068
    // dev-dependency, available here). Requires `value < modulus`, like `invert`.
1069
    fn malachite_inv<U: LehmerOps>(value: U, modulus: U) -> Option<U> {
1070
        use malachite_base::num::arithmetic::traits::ModInverse;
1071
        use malachite_nz::natural::Natural;
1072
        let x = Natural::from_limbs_asc(value.into_limbs().as_slice());
1073
        let m = Natural::from_limbs_asc(modulus.into_limbs().as_slice());
1074
        x.mod_inverse(m).map(|inv| {
1075
            let mut out = U::Limbs::ZERO;
1076
            let limbs = inv.into_limbs_asc();
1077
            out.as_mut_slice()[..limbs.len()].copy_from_slice(&limbs);
1078
            U::from_limbs(out)
1079
        })
1080
    }
1081
1082
    fn addmod(a: Uint3072, b: Uint3072, m: Uint3072) -> Uint3072 {
1083
        let (res, overflow) = a.overflowing_add(b);
1084
        if overflow || res >= m { res.overflowing_sub(m).0 } else { res }
1085
    }
1086
1087
    /// `(a * b) mod m` via binary double-and-add (overflow-safe oracle).
1088
    fn mulmod(a: Uint3072, b: Uint3072, m: Uint3072) -> Uint3072 {
1089
        let mut result = Uint3072::ZERO;
1090
        let mut base = a % m;
1091
        let mut exp = b;
1092
        while !exp.is_zero() {
1093
            if exp.0[0] & 1 == 1 {
1094
                result = addmod(result, base, m);
1095
            }
1096
            base = addmod(base, base, m);
1097
            exp = exp >> 1;
1098
        }
1099
        result
1100
    }
1101
1102
    #[test]
1103
    fn matches_malachite_muhash_prime() {
1104
        // Lehmer must agree bit-for-bit with malachite (the reference) on the MuHash prime.
1105
        let mut rng = ChaCha8Rng::seed_from_u64(42);
1106
        let mut buf = [0u8; Uint3072::BYTES];
1107
        for _ in 0..2000 {
1108
            rng.fill_bytes(&mut buf);
1109
            let v = Uint3072::from_le_bytes(buf) % MUHASH_PRIME;
1110
            if v.is_zero() {
1111
                continue;
1112
            }
1113
            let expected = malachite_inv(v, MUHASH_PRIME).unwrap();
1114
            let got = lehmer_inv(v.0, MUHASH_PRIME.0).unwrap();
1115
            assert_eq!(got.as_slice(), expected.0.as_slice(), "v={v}");
1116
        }
1117
    }
1118
1119
    #[test]
1120
    fn product_is_one_muhash_prime() {
1121
        // v * inv(v) == 1 (mod prime), independent of any oracle.
1122
        let mut rng = ChaCha8Rng::seed_from_u64(99);
1123
        let mut buf = [0u8; Uint3072::BYTES];
1124
        for _ in 0..500 {
1125
            rng.fill_bytes(&mut buf);
1126
            let v = Uint3072::from_le_bytes(buf) % MUHASH_PRIME;
1127
            if v.is_zero() {
1128
                continue;
1129
            }
1130
            let inv = lehmer_inv(v.0, MUHASH_PRIME.0).unwrap();
1131
            assert_eq!(mulmod(v, Uint3072(inv), MUHASH_PRIME), Uint3072::from_u64(1), "v={v}");
1132
        }
1133
    }
1134
1135
    #[test]
1136
    fn small_values_force_multilimb_quotient() {
1137
        // Tiny `value` makes the first quotient ~48 limbs, exercising the
1138
        // multi-limb `div_rem` fallback and the wide `t_add_qmul` path.
1139
        for v_small in [1u64, 2, 3, 5, 7, 1103717, u64::MAX] {
1140
            let v = Uint3072::from_u64(v_small);
1141
            let inv = lehmer_inv(v.0, MUHASH_PRIME.0).unwrap();
1142
            assert_eq!(mulmod(v, Uint3072(inv), MUHASH_PRIME), Uint3072::from_u64(1), "v={v_small}");
1143
        }
1144
    }
1145
1146
    #[test]
1147
    fn edge_cases_muhash_prime() {
1148
        let one = Uint3072::from_u64(1);
1149
        let p_minus_1 = MUHASH_PRIME.overflowing_sub(one).0;
1150
        assert_eq!(lehmer_inv(one.0, MUHASH_PRIME.0).unwrap().as_slice(), one.0.as_slice());
1151
        assert_eq!(lehmer_inv(p_minus_1.0, MUHASH_PRIME.0).unwrap().as_slice(), p_minus_1.0.as_slice());
1152
        assert!(lehmer_inv(Uint3072::ZERO.0, MUHASH_PRIME.0).is_none());
1153
    }
1154
1155
    #[test]
1156
    fn div_n_by_1_matches_uint_div() {
1157
        // The reciprocal n-by-1 division must agree with Uint3072::div_rem across
1158
        // tiny, normalized (top bit set), and arbitrary unnormalized divisors.
1159
        let mut rng = ChaCha8Rng::seed_from_u64(7);
1160
        let mut buf = [0u8; Uint3072::BYTES];
1161
        for _ in 0..20000 {
1162
            rng.fill_bytes(&mut buf);
1163
            let x = Uint3072::from_le_bytes(buf);
1164
            let d = match rng.next_u64() % 4 {
1165
                0 => 1 + (rng.next_u64() % 1000),  // tiny (large shift)
1166
                1 => rng.next_u64() | (1 << 63),   // already normalized
1167
                2 => (rng.next_u64() >> 7).max(1), // unnormalized
1168
                _ => rng.next_u64().max(1),        // arbitrary
1169
            };
1170
            let (q, r) = div_n_by_1(&x.0, d);
1171
            let mut dl = [0u64; N];
1172
            dl[0] = d;
1173
            let (eq, er) = Uint3072(x.0).div_rem(Uint3072(dl));
1174
            assert_eq!(q.as_slice(), eq.0.as_slice(), "quotient mismatch x={x} d={d}");
1175
            assert_eq!(r, er.0[0], "remainder mismatch x={x} d={d}");
1176
        }
1177
        // Boundary divisors: 1, 2, MAX, 2^63 (min normalized), 2^63-1 (max
1178
        // unnormalized), and the MuHash prime difference constant.
1179
        for &d in &[1u64, 2, 3, u64::MAX, 1 << 63, (1 << 63) - 1, 1103717] {
1180
            rng.fill_bytes(&mut buf);
1181
            let x = Uint3072::from_le_bytes(buf);
1182
            let (q, r) = div_n_by_1(&x.0, d);
1183
            let mut dl = [0u64; N];
1184
            dl[0] = d;
1185
            let (eq, er) = Uint3072(x.0).div_rem(Uint3072(dl));
1186
            assert_eq!(q.as_slice(), eq.0.as_slice(), "quotient mismatch x={x} d={d}");
1187
            assert_eq!(r, er.0[0], "remainder mismatch x={x} d={d}");
1188
        }
1189
    }
1190
1191
    #[test]
1192
    fn gcd_div_matches_u128_both_branches() {
1193
        // `gcd_div` computes `(n/d, n%d)` for 128-bit `n, d` with `d >= 2^64`.
1194
        // Cover both arms against the native `u128` oracle: the normal arm
1195
        // (`q = n1/d1 <= d1`) and the rare normalization arm (`q > d1`), which
1196
        // fires when the divisor's top word is small. The normalization arm is
1197
        // hit only occasionally through `invert`, so pin it directly here.
1198
        let oracle = |n: u128, d: u128| ((n / d) as u64, n % d);
1199
1200
        // Explicit cases that force `q > d1` (small divisor top word).
1201
        let forcing: &[(u128, u128)] = &[
1202
            (u128::MAX, (1u128 << 64) | 1), // d1 = 1
1203
            (u128::MAX, 1u128 << 64),       // d = 2^64
1204
            ((0xDEAD_BEEFu128 << 96) | 0x1234, (1u128 << 64) | u64::MAX as u128),
1205
            (u128::MAX, (2u128 << 64) | 7),                     // d1 = 2
1206
            (u128::MAX - 12345, (0x1_0000u128 << 64) | 0xABCD), // d1 = 2^16
1207
        ];
1208
        for &(n, d) in forcing {
1209
            assert!((n >> 64) as u64 / (d >> 64) as u64 > (d >> 64) as u64, "case does not force q>d1");
1210
            assert_eq!(gcd_div(n, d), oracle(n, d), "q>d1 arm mismatch n={n} d={d}");
1211
        }
1212
        // Normal arm (`q <= d1`): divisor with a large top word.
1213
        for &(n, d) in &[(u128::MAX, (u64::MAX as u128) << 64 | 3), (1u128 << 127, (1u128 << 127) | 1)] {
1214
            assert!((n >> 64) as u64 / (d >> 64) as u64 <= (d >> 64) as u64, "case is not the normal arm");
1215
            assert_eq!(gcd_div(n, d), oracle(n, d), "normal arm mismatch n={n} d={d}");
1216
        }
1217
1218
        // Randomized, biased to small divisor top words so most iterations take
1219
        // the `q > d1` arm; every result checked bit-for-bit against `u128`.
1220
        let mut rng = ChaCha8Rng::seed_from_u64(2024);
1221
        let mut branch_hits = 0u64;
1222
        for _ in 0..200_000 {
1223
            let n = ((rng.next_u64() as u128) << 64) | rng.next_u64() as u128;
1224
            let d1 = (rng.next_u64() % (1 << 20)) + 1; // 1 ..= 2^20
1225
            let d = ((d1 as u128) << 64) | rng.next_u64() as u128;
1226
            assert_eq!(gcd_div(n, d), oracle(n, d), "random gcd_div mismatch n={n} d={d}");
1227
            if (n >> 64) as u64 / d1 > d1 {
1228
                branch_hits += 1;
1229
            }
1230
        }
1231
        assert!(branch_hits > 1000, "q>d1 arm under-exercised: only {branch_hits} hits");
1232
    }
1233
1234
    #[test]
1235
    fn q_gt_d1_vector_matches_malachite() {
1236
        // A full-inverse input that drives `gcd_div` through its `q > d1`
1237
        // normalization arm, pinned as an explicit regression case (that arm is
1238
        // otherwise only hit occasionally by the random-vector tests).
1239
        let v: [u64; N] = [
1240
            0xbaac78a3d8d04a44,
1241
            0x454126b8efd12383,
1242
            0xa93bb055d701be60,
1243
            0xe940f5627944ba89,
1244
            0x68842c54edf3df88,
1245
            0xf7c6332a4e2be869,
1246
            0x396e8533e978070a,
1247
            0x2703f08794977aad,
1248
            0x373dc910525ad335,
1249
            0x52520bee468a9073,
1250
            0xf4580a27f3ca91ee,
1251
            0x5de1060b3d65f732,
1252
            0x4b1072d2e2cc0da1,
1253
            0x4e2a032ba51f609a,
1254
            0xeae5995402410005,
1255
            0x885f9eb04a59ab3c,
1256
            0x165446e913daa18e,
1257
            0xf2b1311c3eb843c0,
1258
            0x630b8232162a2fca,
1259
            0xe4224b2c61bafd4e,
1260
            0x25397d500e52b519,
1261
            0x7cd55e35a4ac6022,
1262
            0x8629892065e194c0,
1263
            0x713ea3ded7bcd68c,
1264
            0xf1f138b0052d1fdc,
1265
            0x7974414d82958c31,
1266
            0xc29243783567cf96,
1267
            0xf9214af62a72ec1e,
1268
            0xa1e4feb97fdbfe07,
1269
            0x5c92a43f23a3989e,
1270
            0x1ad829d92571a26a,
1271
            0xd09dd31bf57bf618,
1272
            0x00772f32162d2fd3,
1273
            0x1c0dcedad1142715,
1274
            0x677b857b2c9c2713,
1275
            0xe64b41b0e187f9e7,
1276
            0x4062f89c0309cd59,
1277
            0x3edc673c30e10664,
1278
            0x330b6c680b777302,
1279
            0x423676df7dfd8ccf,
1280
            0x347fe8b7dee8ca42,
1281
            0x0fb4eb8629ef71c1,
1282
            0x5e898abada4103ac,
1283
            0x39820234bad59fb2,
1284
            0xd780c6aeaaa89812,
1285
            0x61bdb22ece416ba0,
1286
            0x79f1821384ef3f44,
1287
            0x803912aebf95eede,
1288
        ];
1289
        let got = lehmer_inv(v, MUHASH_PRIME.0).unwrap();
1290
        assert_eq!(got.as_slice(), malachite_inv(Uint3072(v), MUHASH_PRIME).unwrap().0.as_slice());
1291
        assert_eq!(mulmod(Uint3072(v), Uint3072(got), MUHASH_PRIME), Uint3072::from_u64(1));
1292
    }
1293
1294
    #[test]
1295
    fn hgcd2_none_when_top_word_below_two() {
1296
        // The guess returns `None` (caller falls back to one exact division step)
1297
        // exactly when a top word is `< 2`; otherwise it confirms a matrix.
1298
        assert!(hgcd2(1, 0, 5, 0).is_none()); // ah < 2
1299
        assert!(hgcd2(5, 0, 0, 9).is_none()); // bh < 2
1300
        assert!(hgcd2(u64::MAX, 0, u64::MAX >> 1, 0).is_some()); // well-separated -> confirms a quotient
1301
    }
1302
1303
    /// Extended-Euclid reference for u64 moduli, in i128 (all magnitudes fit).
1304
    fn egcd_inv_u64(v: u64, m: u64) -> Option<u64> {
1305
        let (mut old_r, mut r) = (m as i128, v as i128);
1306
        let (mut old_t, mut t) = (0i128, 1i128);
1307
        while r != 0 {
1308
            let q = old_r / r;
1309
            (old_r, r) = (r, old_r - q * r);
1310
            (old_t, t) = (t, old_t - q * t);
1311
        }
1312
        (old_r == 1).then(|| old_t.rem_euclid(m as i128) as u64)
1313
    }
1314
1315
    #[test]
1316
    fn u64_exhaustive_small_range() {
1317
        // Every (value, modulus) with modulus in [2, 512) and value in [0, 4m):
1318
        // agreement with the extended-Euclid oracle, covering gcd != 1 -> None
1319
        // and the value-reduction path.
1320
        for m in 2u64..512 {
1321
            for v in 0..m * 4 {
1322
                let got = v.lehmer_invert(m);
1323
                assert_eq!(got, egcd_inv_u64(v % m, m), "v={v} m={m}");
1324
                if let Some(inv) = got {
1325
                    assert_eq!((inv as u128 * (v % m) as u128 % m as u128) as u64, 1, "v={v} m={m}");
1326
                }
1327
            }
1328
        }
1329
    }
1330
1331
    #[test]
1332
    fn u64_random_matches_oracle() {
1333
        let mut rng = ChaCha8Rng::seed_from_u64(17);
1334
        for _ in 0..200_000 {
1335
            let m = rng.next_u64().max(2);
1336
            let v = rng.next_u64();
1337
            assert_eq!(v.lehmer_invert(m), egcd_inv_u64(v % m, m), "v={v} m={m}");
1338
        }
1339
    }
1340
1341
    #[test]
1342
    fn u128_random_matches_malachite() {
1343
        // Primitive u128 impl vs malachite, mixing full-width and single-limb
1344
        // operands to cross the multi-limb/single-limb phase boundary.
1345
        let mut rng = ChaCha8Rng::seed_from_u64(23);
1346
        let mut sample = |wide: bool| {
1347
            if wide { ((rng.next_u64() as u128) << 64) | rng.next_u64() as u128 } else { rng.next_u64() as u128 }
1348
        };
1349
        for i in 0..50_000u32 {
1350
            let m = sample(i % 4 != 0).max(2);
1351
            let v = sample(i % 3 != 0);
1352
            let got = v.lehmer_invert(m);
1353
            assert_eq!(got, malachite_inv(v % m, m), "v={v} m={m}");
1354
        }
1355
    }
1356
1357
    #[test]
1358
    fn uint_sizes_match_malachite() {
1359
        // The construct_uint! impls at the other production widths, vs malachite.
1360
        use crate::{Uint192, Uint256, Uint320};
1361
        let mut rng = ChaCha8Rng::seed_from_u64(29);
1362
        macro_rules! check {
1363
            ($ty:ty, $iters:expr) => {{
1364
                let mut buf = [0u8; <$ty>::BYTES];
1365
                for _ in 0..$iters {
1366
                    rng.fill_bytes(&mut buf);
1367
                    let m = <$ty>::from_le_bytes(buf);
1368
                    if m < 2u64 {
1369
                        continue;
1370
                    }
1371
                    rng.fill_bytes(&mut buf);
1372
                    let v = <$ty>::from_le_bytes(buf);
1373
                    assert_eq!(v.lehmer_invert(m), malachite_inv(v % m, m), "v={v} m={m}");
1374
                }
1375
            }};
1376
        }
1377
        check!(Uint192, 3000);
1378
        check!(Uint256, 3000);
1379
        check!(Uint320, 3000);
1380
    }
1381
1382
    #[test]
1383
    fn lehmer_invert_edge_semantics() {
1384
        // Totality of the trait method: degenerate moduli, unreduced values,
1385
        // non-coprime pairs.
1386
        assert_eq!(0u64.lehmer_invert(0), None);
1387
        assert_eq!(5u64.lehmer_invert(0), None);
1388
        assert_eq!(5u64.lehmer_invert(1), None);
1389
        assert_eq!(1u64.lehmer_invert(2), Some(1));
1390
        assert_eq!(7u64.lehmer_invert(7), None); // value == modulus reduces to 0
1391
        assert_eq!(9u64.lehmer_invert(7), 2u64.lehmer_invert(7)); // reduction path
1392
        assert_eq!(4u64.lehmer_invert(6), None); // gcd = 2
1393
        assert_eq!(3u64.lehmer_invert(8), Some(3)); // even modulus, coprime value
1394
        assert_eq!(3u128.lehmer_invert(8), Some(3));
1395
        assert_eq!(Uint3072::from_u64(5).lehmer_invert(Uint3072::from_u64(1)), None);
1396
        assert_eq!(Uint3072::from_u64(3).lehmer_invert(Uint3072::from_u64(8)), Some(Uint3072::from_u64(3)));
1397
    }
1398
}
/root/kaspa/kaspa-fuzz/rusty-kaspa/math/src/uint.rs
Line
Count
Source
1
#[doc(hidden)]
2
pub use {faster_hex, js_sys, kaspa_utils, serde, wasm_bindgen};
3
4
// TODO: Add u32 support for optimization on 32 bit machines.
5
6
#[macro_export]
7
macro_rules! construct_uint {
8
    ($name:ident, $n_words:literal $(, $derive_trait:ty)*) => {
9
        /// Little-endian large integer type
10
        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug$(, $derive_trait )*)]
11
        pub struct $name(pub [u64; $n_words]);
12
        #[allow(unused)]
13
        impl $name {
14
            pub const ZERO: Self = $name([0; $n_words]);
15
            pub const MIN: Self = Self::ZERO;
16
            pub const MAX: Self = $name([u64::MAX; $n_words]);
17
            pub const BITS: u32 = $n_words * u64::BITS;
18
            pub const BYTES: usize = $n_words * size_of::<u64>();
19
            pub const LIMBS: usize = $n_words;
20
21
            #[inline]
22
0
            pub fn from_u64(n: u64) -> Self {
23
0
                let mut ret = Self::ZERO;
24
0
                ret.0[0] = n;
25
0
                ret
26
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1928from_u64
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3208from_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30728from_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1928from_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2568from_u64
27
            #[inline]
28
0
            pub fn from_u128(n: u128) -> Self {
29
0
                let mut ret = Self::ZERO;
30
0
                ret.0[0] = n as u64;
31
0
                ret.0[1] = (n >> 64) as u64;
32
0
                ret
33
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1929from_u128
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3209from_u128
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30729from_u128
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1929from_u128
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2569from_u128
34
35
            #[inline]
36
5.02k
            pub fn as_u128(self) -> u128 {
37
5.02k
                self.0[0] as u128 | ((self.0[1] as u128) << 64)
38
5.02k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1927as_u128
Line
Count
Source
36
5.02k
            pub fn as_u128(self) -> u128 {
37
5.02k
                self.0[0] as u128 | ((self.0[1] as u128) << 64)
38
5.02k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3207as_u128
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30727as_u128
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1927as_u128
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2567as_u128
39
40
            #[inline]
41
5.04k
            pub fn as_u64(self) -> u64 {
42
5.04k
                self.0[0] as u64
43
5.04k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1926as_u64
Line
Count
Source
41
5.04k
            pub fn as_u64(self) -> u64 {
42
5.04k
                self.0[0] as u64
43
5.04k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3206as_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30726as_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1926as_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2566as_u64
44
45
            #[inline(always)]
46
0
            pub fn is_zero(self) -> bool {
47
0
                self.0.iter().all(|&a| a == 0)
Unexecuted instantiation: _RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint1927is_zero0B4_
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint3207is_zero0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint30727is_zero0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint1927is_zero0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint2567is_zero0B7_
48
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1927is_zero
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3207is_zero
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30727is_zero
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1927is_zero
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2567is_zero
49
50
            /// Return the least number of bits needed to represent the number
51
            #[inline(always)]
52
35.8k
            pub fn bits(&self) -> u32 {
53
45.5k
                for (i, &word) in self.0.iter().enumerate().rev() {
54
45.5k
                    if word != 0 {
55
34.5k
                        return u64::BITS * (i as u32 + 1) - word.leading_zeros();
56
11.0k
                    }
57
                }
58
1.37k
                0
59
35.8k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1924bits
Line
Count
Source
52
35.8k
            pub fn bits(&self) -> u32 {
53
45.5k
                for (i, &word) in self.0.iter().enumerate().rev() {
54
45.5k
                    if word != 0 {
55
34.5k
                        return u64::BITS * (i as u32 + 1) - word.leading_zeros();
56
11.0k
                    }
57
                }
58
1.37k
                0
59
35.8k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3204bits
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30724bits
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1924bits
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2564bits
60
61
            #[inline(always)]
62
0
            pub fn leading_zeros(&self) -> u32 {
63
0
                return Self::BITS - self.bits();
64
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19213leading_zeros
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32013leading_zeros
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307213leading_zeros
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19213leading_zeros
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25613leading_zeros
65
66
            #[inline]
67
17.1k
            pub fn overflowing_shl(self, mut s: u32) -> (Self, bool) {
68
17.1k
                let overflows = s >= Self::BITS;
69
17.1k
                s %= Self::BITS;
70
17.1k
                let mut ret = [0u64; $n_words];
71
17.1k
                let left_words = (s / 64) as usize;
72
17.1k
                let left_shifts = s % 64;
73
74
46.8k
                for i in left_words..$n_words {
75
46.8k
                    ret[i] = self.0[i - left_words] << left_shifts;
76
46.8k
                }
77
17.1k
                if left_shifts > 0 {
78
8.59k
                    let left_over = 64 - left_shifts;
79
13.5k
                    for i in left_words + 1..$n_words {
80
13.5k
                        ret[i] |= self.0[i - 1 - left_words] >> left_over;
81
13.5k
                    }
82
8.56k
                }
83
17.1k
                (Self(ret), overflows)
84
17.1k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215overflowing_shl
Line
Count
Source
67
17.1k
            pub fn overflowing_shl(self, mut s: u32) -> (Self, bool) {
68
17.1k
                let overflows = s >= Self::BITS;
69
17.1k
                s %= Self::BITS;
70
17.1k
                let mut ret = [0u64; $n_words];
71
17.1k
                let left_words = (s / 64) as usize;
72
17.1k
                let left_shifts = s % 64;
73
74
46.8k
                for i in left_words..$n_words {
75
46.8k
                    ret[i] = self.0[i - left_words] << left_shifts;
76
46.8k
                }
77
17.1k
                if left_shifts > 0 {
78
8.59k
                    let left_over = 64 - left_shifts;
79
13.5k
                    for i in left_words + 1..$n_words {
80
13.5k
                        ret[i] |= self.0[i - 1 - left_words] >> left_over;
81
13.5k
                    }
82
8.56k
                }
83
17.1k
                (Self(ret), overflows)
84
17.1k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015overflowing_shl
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215overflowing_shl
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215overflowing_shl
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615overflowing_shl
85
86
            #[inline]
87
0
            pub fn wrapping_shl(self, s: u32) -> Self {
88
0
                self.overflowing_shl(s).0
89
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19212wrapping_shl
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32012wrapping_shl
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307212wrapping_shl
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19212wrapping_shl
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25612wrapping_shl
90
91
            #[inline]
92
325k
            pub fn overflowing_shr(self, mut s: u32) -> (Self, bool) {
93
325k
                let overflows = s >= Self::BITS;
94
325k
                s %= Self::BITS;
95
325k
                let mut ret = [0u64; Self::LIMBS];
96
325k
                let left_words = (s / 64) as usize;
97
325k
                let left_shifts = s % 64;
98
99
975k
                for i in left_words..Self::LIMBS {
100
975k
                    ret[i - left_words] = self.0[i] >> left_shifts;
101
975k
                }
102
325k
                if left_shifts > 0 {
103
323k
                    let left_over = 64 - left_shifts;
104
645k
                    for i in left_words + 1..Self::LIMBS {
105
645k
                        ret[i - left_words - 1] |= self.0[i] << left_over;
106
645k
                    }
107
2.04k
                }
108
325k
                (Self(ret), overflows)
109
325k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215overflowing_shr
Line
Count
Source
92
325k
            pub fn overflowing_shr(self, mut s: u32) -> (Self, bool) {
93
325k
                let overflows = s >= Self::BITS;
94
325k
                s %= Self::BITS;
95
325k
                let mut ret = [0u64; Self::LIMBS];
96
325k
                let left_words = (s / 64) as usize;
97
325k
                let left_shifts = s % 64;
98
99
975k
                for i in left_words..Self::LIMBS {
100
975k
                    ret[i - left_words] = self.0[i] >> left_shifts;
101
975k
                }
102
325k
                if left_shifts > 0 {
103
323k
                    let left_over = 64 - left_shifts;
104
645k
                    for i in left_words + 1..Self::LIMBS {
105
645k
                        ret[i - left_words - 1] |= self.0[i] << left_over;
106
645k
                    }
107
2.04k
                }
108
325k
                (Self(ret), overflows)
109
325k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015overflowing_shr
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215overflowing_shr
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215overflowing_shr
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615overflowing_shr
110
111
            #[inline]
112
5.49k
            pub fn overflowing_add(mut self, other: Self) -> (Self, bool) {
113
                // Replace with std once stabilized:https://github.com/rust-lang/rust/issues/85532
114
                #[inline(always)]
115
16.4k
                pub const fn carrying_add_u64(lhs: u64, rhs: u64, carry: bool) -> (u64, bool) {
116
16.4k
                    let (a, b) = lhs.overflowing_add(rhs);
117
16.4k
                    let (c, d) = a.overflowing_add(carry as u64);
118
16.4k
                    (c, b != d)
119
16.4k
                }
_RNvNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19215overflowing_add16carrying_add_u64
Line
Count
Source
115
16.4k
                pub const fn carrying_add_u64(lhs: u64, rhs: u64, carry: bool) -> (u64, bool) {
116
16.4k
                    let (a, b) = lhs.overflowing_add(rhs);
117
16.4k
                    let (c, d) = a.overflowing_add(carry as u64);
118
16.4k
                    (c, b != d)
119
16.4k
                }
Unexecuted instantiation: _RNvNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32015overflowing_add16carrying_add_u64
Unexecuted instantiation: _RNvNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307215overflowing_add16carrying_add_u64
Unexecuted instantiation: _RNvNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19215overflowing_add16carrying_add_u64
Unexecuted instantiation: _RNvNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25615overflowing_add16carrying_add_u64
120
5.49k
                let mut carry = false;
121
                let mut carry_out;
122
16.4k
                for i in 0..Self::LIMBS {
123
16.4k
                    (self.0[i], carry_out) = carrying_add_u64(self.0[i], other.0[i], carry);
124
16.4k
                    carry = carry_out;
125
16.4k
                }
126
5.49k
                (self, carry)
127
5.49k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215overflowing_add
Line
Count
Source
112
5.49k
            pub fn overflowing_add(mut self, other: Self) -> (Self, bool) {
113
                // Replace with std once stabilized:https://github.com/rust-lang/rust/issues/85532
114
                #[inline(always)]
115
                pub const fn carrying_add_u64(lhs: u64, rhs: u64, carry: bool) -> (u64, bool) {
116
                    let (a, b) = lhs.overflowing_add(rhs);
117
                    let (c, d) = a.overflowing_add(carry as u64);
118
                    (c, b != d)
119
                }
120
5.49k
                let mut carry = false;
121
                let mut carry_out;
122
16.4k
                for i in 0..Self::LIMBS {
123
16.4k
                    (self.0[i], carry_out) = carrying_add_u64(self.0[i], other.0[i], carry);
124
16.4k
                    carry = carry_out;
125
16.4k
                }
126
5.49k
                (self, carry)
127
5.49k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015overflowing_add
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215overflowing_add
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215overflowing_add
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615overflowing_add
128
129
            #[inline]
130
5.17k
            pub fn overflowing_add_u64(mut self, other: u64) -> (Self, bool) {
131
                let mut carry: bool;
132
5.17k
                (self.0[0], carry) = self.0[0].overflowing_add(other);
133
7.59k
                for i in 1..Self::LIMBS {
134
7.59k
                    if !carry {
135
4.30k
                        break;
136
3.29k
                    }
137
3.29k
                    (self.0[i], carry) = self.0[i].overflowing_add(1);
138
                }
139
5.17k
                (self, carry)
140
5.17k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19219overflowing_add_u64
Line
Count
Source
130
5.17k
            pub fn overflowing_add_u64(mut self, other: u64) -> (Self, bool) {
131
                let mut carry: bool;
132
5.17k
                (self.0[0], carry) = self.0[0].overflowing_add(other);
133
7.59k
                for i in 1..Self::LIMBS {
134
7.59k
                    if !carry {
135
4.30k
                        break;
136
3.29k
                    }
137
3.29k
                    (self.0[i], carry) = self.0[i].overflowing_add(1);
138
                }
139
5.17k
                (self, carry)
140
5.17k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32019overflowing_add_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307219overflowing_add_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19219overflowing_add_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25619overflowing_add_u64
141
142
            #[inline]
143
145k
            pub fn overflowing_sub(mut self, other: Self) -> (Self, bool) {
144
                // Replace with std once stabilized:https://github.com/rust-lang/rust/issues/85532
145
                #[inline(always)]
146
436k
                pub const fn borrowing_sub_u64(lhs: u64, rhs: u64, borrow: bool) -> (u64, bool) {
147
436k
                    let (a, b) = lhs.overflowing_sub(rhs);
148
436k
                    let (c, d) = a.overflowing_sub(borrow as u64);
149
436k
                    (c, b != d)
150
436k
                }
_RNvNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19215overflowing_sub17borrowing_sub_u64
Line
Count
Source
146
436k
                pub const fn borrowing_sub_u64(lhs: u64, rhs: u64, borrow: bool) -> (u64, bool) {
147
436k
                    let (a, b) = lhs.overflowing_sub(rhs);
148
436k
                    let (c, d) = a.overflowing_sub(borrow as u64);
149
436k
                    (c, b != d)
150
436k
                }
Unexecuted instantiation: _RNvNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32015overflowing_sub17borrowing_sub_u64
Unexecuted instantiation: _RNvNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307215overflowing_sub17borrowing_sub_u64
Unexecuted instantiation: _RNvNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19215overflowing_sub17borrowing_sub_u64
Unexecuted instantiation: _RNvNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25615overflowing_sub17borrowing_sub_u64
151
152
145k
                let mut carry = false;
153
                let mut carry_out;
154
436k
                for i in 0..Self::LIMBS {
155
436k
                    (self.0[i], carry_out) = borrowing_sub_u64(self.0[i], other.0[i], carry);
156
436k
                    carry = carry_out;
157
436k
                }
158
145k
                (self, carry)
159
145k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215overflowing_sub
Line
Count
Source
143
145k
            pub fn overflowing_sub(mut self, other: Self) -> (Self, bool) {
144
                // Replace with std once stabilized:https://github.com/rust-lang/rust/issues/85532
145
                #[inline(always)]
146
                pub const fn borrowing_sub_u64(lhs: u64, rhs: u64, borrow: bool) -> (u64, bool) {
147
                    let (a, b) = lhs.overflowing_sub(rhs);
148
                    let (c, d) = a.overflowing_sub(borrow as u64);
149
                    (c, b != d)
150
                }
151
152
145k
                let mut carry = false;
153
                let mut carry_out;
154
436k
                for i in 0..Self::LIMBS {
155
436k
                    (self.0[i], carry_out) = borrowing_sub_u64(self.0[i], other.0[i], carry);
156
436k
                    carry = carry_out;
157
436k
                }
158
145k
                (self, carry)
159
145k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015overflowing_sub
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215overflowing_sub
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215overflowing_sub
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615overflowing_sub
160
161
            #[inline]
162
0
            pub fn saturating_sub(self, other: Self) -> Self {
163
0
                let (sum, carry) = self.overflowing_sub(other);
164
0
                if carry { Self::ZERO } else { sum }
165
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19214saturating_sub
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32014saturating_sub
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307214saturating_sub
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19214saturating_sub
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25614saturating_sub
166
167
            #[inline]
168
0
            pub fn saturating_add(self, other: Self) -> Self {
169
0
                let (sum, carry) = self.overflowing_add(other);
170
0
                if carry { Self::MAX } else { sum }
171
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19214saturating_add
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32014saturating_add
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307214saturating_add
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19214saturating_add
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25614saturating_add
172
173
            /// Multiplication by u64
174
            #[inline]
175
5.15k
            pub fn overflowing_mul_u64(self, other: u64) -> (Self, bool) {
176
5.15k
                let (this, carry) = self.carrying_mul_u64(other);
177
5.15k
                (this, carry != 0)
178
5.15k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19219overflowing_mul_u64
Line
Count
Source
175
5.15k
            pub fn overflowing_mul_u64(self, other: u64) -> (Self, bool) {
176
5.15k
                let (this, carry) = self.carrying_mul_u64(other);
177
5.15k
                (this, carry != 0)
178
5.15k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32019overflowing_mul_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307219overflowing_mul_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19219overflowing_mul_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25619overflowing_mul_u64
179
180
            #[inline]
181
5.15k
            pub fn carrying_mul_u64(mut self, other: u64) -> (Self, u64) {
182
5.15k
                let mut carry: u128 = 0;
183
15.4k
                for i in 0..Self::LIMBS {
184
15.4k
                    // TODO: Use `carrying_mul` when stabilized: https://github.com/rust-lang/rust/issues/85532
185
15.4k
                    let n = carry + (other as u128) * (self.0[i] as u128);
186
15.4k
                    self.0[i] = n as u64;
187
15.4k
                    carry = (n >> 64) & u64::MAX as u128;
188
15.4k
                }
189
5.15k
                (self, carry as u64)
190
5.15k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19216carrying_mul_u64
Line
Count
Source
181
5.15k
            pub fn carrying_mul_u64(mut self, other: u64) -> (Self, u64) {
182
5.15k
                let mut carry: u128 = 0;
183
15.4k
                for i in 0..Self::LIMBS {
184
15.4k
                    // TODO: Use `carrying_mul` when stabilized: https://github.com/rust-lang/rust/issues/85532
185
15.4k
                    let n = carry + (other as u128) * (self.0[i] as u128);
186
15.4k
                    self.0[i] = n as u64;
187
15.4k
                    carry = (n >> 64) & u64::MAX as u128;
188
15.4k
                }
189
5.15k
                (self, carry as u64)
190
5.15k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32016carrying_mul_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307216carrying_mul_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19216carrying_mul_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25616carrying_mul_u64
191
192
            #[inline]
193
5.46k
            pub fn overflowing_mul(self, other: Self) -> (Self, bool) {
194
                // We should probably replace this with a Montgomery multiplication algorithm
195
5.46k
                let mut result = Self::ZERO;
196
5.46k
                let mut carry_out = false;
197
16.3k
                for j in 0..Self::LIMBS {
198
16.3k
                    let mut carry = 0;
199
16.3k
                    let mut i = 0;
200
49.1k
                    while i + j < Self::LIMBS {
201
32.7k
                        let n = (self.0[i] as u128) * (other.0[j] as u128) + (result.0[i + j] as u128) + (carry as u128);
202
32.7k
                        result.0[i + j] = n as u64;
203
32.7k
                        carry = (n >> 64) as u64;
204
32.7k
                        i += 1;
205
32.7k
                    }
206
16.3k
                    carry_out |= carry != 0;
207
                }
208
5.46k
                (result, carry_out)
209
5.46k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215overflowing_mul
Line
Count
Source
193
5.46k
            pub fn overflowing_mul(self, other: Self) -> (Self, bool) {
194
                // We should probably replace this with a Montgomery multiplication algorithm
195
5.46k
                let mut result = Self::ZERO;
196
5.46k
                let mut carry_out = false;
197
16.3k
                for j in 0..Self::LIMBS {
198
16.3k
                    let mut carry = 0;
199
16.3k
                    let mut i = 0;
200
49.1k
                    while i + j < Self::LIMBS {
201
32.7k
                        let n = (self.0[i] as u128) * (other.0[j] as u128) + (result.0[i + j] as u128) + (carry as u128);
202
32.7k
                        result.0[i + j] = n as u64;
203
32.7k
                        carry = (n >> 64) as u64;
204
32.7k
                        i += 1;
205
32.7k
                    }
206
16.3k
                    carry_out |= carry != 0;
207
                }
208
5.46k
                (result, carry_out)
209
5.46k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015overflowing_mul
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215overflowing_mul
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215overflowing_mul
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615overflowing_mul
210
            /// Creates big integer value from a byte slice using
211
            /// little-endian encoding
212
            #[inline(always)]
213
147k
            pub fn from_le_bytes(bytes: [u8; Self::BYTES]) -> Self {
214
147k
                let mut out = [0u64; Self::LIMBS];
215
                // This should optimize to basically a transmute.
216
147k
                out.iter_mut()
217
147k
                    .zip(bytes.chunks_exact(8))
218
441k
                    .for_each(|(word, bytes)| *word = u64::from_le_bytes(bytes.try_into().unwrap()));
_RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19213from_le_bytes0B4_
Line
Count
Source
218
441k
                    .for_each(|(word, bytes)| *word = u64::from_le_bytes(bytes.try_into().unwrap()));
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32013from_le_bytes0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307213from_le_bytes0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19213from_le_bytes0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25613from_le_bytes0B7_
219
147k
                Self(out)
220
147k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19213from_le_bytes
Line
Count
Source
213
147k
            pub fn from_le_bytes(bytes: [u8; Self::BYTES]) -> Self {
214
147k
                let mut out = [0u64; Self::LIMBS];
215
                // This should optimize to basically a transmute.
216
147k
                out.iter_mut()
217
147k
                    .zip(bytes.chunks_exact(8))
218
147k
                    .for_each(|(word, bytes)| *word = u64::from_le_bytes(bytes.try_into().unwrap()));
219
147k
                Self(out)
220
147k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32013from_le_bytes
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307213from_le_bytes
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19213from_le_bytes
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25613from_le_bytes
221
222
            /// Creates big integer value from a byte slice using
223
            /// big-endian encoding
224
            #[inline(always)]
225
0
            pub fn from_be_bytes(bytes: [u8; Self::BYTES]) -> Self {
226
0
                let mut out = [0u64; Self::LIMBS];
227
0
                out.iter_mut()
228
0
                    .rev()
229
0
                    .zip(bytes.chunks_exact(8))
230
0
                    .for_each(|(word, bytes)| *word = u64::from_be_bytes(bytes.try_into().unwrap()));
Unexecuted instantiation: _RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19213from_be_bytes0B4_
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32013from_be_bytes0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307213from_be_bytes0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19213from_be_bytes0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25613from_be_bytes0B7_
231
0
                Self(out)
232
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19213from_be_bytes
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32013from_be_bytes
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307213from_be_bytes
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19213from_be_bytes
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25613from_be_bytes
233
234
            /// Convert's the Uint into little endian byte array
235
            #[inline(always)]
236
75.8k
            pub fn to_le_bytes(self) -> [u8; Self::BYTES] {
237
75.8k
                let mut out = [0u8; Self::BYTES];
238
                // This should optimize to basically a transmute.
239
227k
                out.chunks_exact_mut(8).zip(self.0).for_each(|(bytes, word)| bytes.copy_from_slice(&word.to_le_bytes()));
_RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19211to_le_bytes0B4_
Line
Count
Source
239
227k
                out.chunks_exact_mut(8).zip(self.0).for_each(|(bytes, word)| bytes.copy_from_slice(&word.to_le_bytes()));
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32011to_le_bytes0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307211to_le_bytes0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19211to_le_bytes0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25611to_le_bytes0B7_
240
75.8k
                out
241
75.8k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19211to_le_bytes
Line
Count
Source
236
75.8k
            pub fn to_le_bytes(self) -> [u8; Self::BYTES] {
237
75.8k
                let mut out = [0u8; Self::BYTES];
238
                // This should optimize to basically a transmute.
239
75.8k
                out.chunks_exact_mut(8).zip(self.0).for_each(|(bytes, word)| bytes.copy_from_slice(&word.to_le_bytes()));
240
75.8k
                out
241
75.8k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32011to_le_bytes
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307211to_le_bytes
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19211to_le_bytes
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25611to_le_bytes
242
243
            /// Convert's the Uint into big endian byte array
244
            #[inline(always)]
245
0
            pub fn to_be_bytes(self) -> [u8; Self::BYTES] {
246
0
                let mut out = [0u8; Self::BYTES];
247
                // This should optimize to basically a transmute.
248
0
                out.chunks_exact_mut(8)
249
0
                    .zip(self.0.into_iter().rev())
250
0
                    .for_each(|(bytes, word)| bytes.copy_from_slice(&word.to_be_bytes()));
Unexecuted instantiation: _RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19211to_be_bytes0B4_
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32011to_be_bytes0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307211to_be_bytes0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19211to_be_bytes0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25611to_be_bytes0B7_
251
0
                out
252
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19211to_be_bytes
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32011to_be_bytes
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307211to_be_bytes
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19211to_be_bytes
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25611to_be_bytes
253
254
            #[inline(always)]
255
0
            pub fn to_be_bytes_var(self) -> Vec<u8> {
256
0
                let bytes = self.to_be_bytes();
257
0
                let start = bytes.iter().copied().position(|b| b != 0).unwrap_or(bytes.len());
Unexecuted instantiation: _RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19215to_be_bytes_var0B4_
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32015to_be_bytes_var0B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307215to_be_bytes_var0B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19215to_be_bytes_var0B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25615to_be_bytes_var0B7_
258
0
                Vec::from(&bytes[start..])
259
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19215to_be_bytes_var
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32015to_be_bytes_var
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307215to_be_bytes_var
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19215to_be_bytes_var
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25615to_be_bytes_var
260
261
            #[inline]
262
0
            pub fn div_rem_u64(mut self, other: u64) -> (Self, u64) {
263
0
                let mut rem = 0u64;
264
0
                self.0.iter_mut().rev().for_each(|d| {
265
0
                    let n = (rem as u128) << 64 | (*d as u128);
266
0
                    *d = (n / other as u128) as u64;
267
0
                    rem = (n % other as u128) as u64;
268
0
                });
Unexecuted instantiation: _RNCNvMCs3Hi7WNjIpVC_4u192NtB4_7Uint19211div_rem_u640B4_
Unexecuted instantiation: _RNCNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint32011div_rem_u640B8_
Unexecuted instantiation: _RNCNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint307211div_rem_u640B8_
Unexecuted instantiation: _RNCNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint19211div_rem_u640B7_
Unexecuted instantiation: _RNCNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint25611div_rem_u640B7_
269
0
                (self, rem)
270
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19211div_rem_u64
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32011div_rem_u64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307211div_rem_u64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19211div_rem_u64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25611div_rem_u64
271
272
            #[inline]
273
0
            pub fn as_f64(&self) -> f64 {
274
                // Reference: https://blog.m-ou.se/floats/
275
                // Step 1: Get leading zeroes
276
0
                let leading_zeroes =  self.leading_zeros();
277
                // Step 2: Align the bits to the left, so the highest bit will be 1.
278
0
                let left_aligned = self.wrapping_shl(leading_zeroes);
279
                // Step 3: Take the highest 53 bits as the mantissa (equivalent to shifting by (Self::BITS - 53))
280
0
                let mut mantissa = left_aligned.0[Self::LIMBS - 1] >> 11;
281
                // Step 4: Get the dropped bits, which are the bits that are not part of the mantissa
282
                // The dropped bits are left_aligned << 53 (everything except the highest 53 bits).
283
                // Unlike the blog here we split the highest bit and the rest of the bits into 2 variables.
284
                // We first take the highest 11 bits that were dropped.
285
0
                let highest_dropped_bits = left_aligned.0[Self::LIMBS - 1] << 53;
286
0
                let highest_dropped_bit = highest_dropped_bits >> 63 != 0;
287
                // Now we OR together the rest of the bits.
288
0
                let mut rest_dropped_bits = highest_dropped_bits << 1; // Remove the highest.
289
0
                for &word in &left_aligned.0[..Self::LIMBS - 1] {
290
0
                    rest_dropped_bits |= word;
291
0
                }
292
                // This is true if the dropped bits are higher than half the int.
293
0
                let higher_than_half = highest_dropped_bit & (rest_dropped_bits != 0);
294
0
                let exactly_half_but_mantissa_odd = highest_dropped_bit & (rest_dropped_bits == 0) & (mantissa & 1 == 1);
295
                // Step 5: if the dropped bits are higher than half the int, we add 1 to the mantissa.
296
                // If the dropped bits are exactly half the int, we add 1 to the mantissa only if the mantissa is odd. (IEEE-754)
297
0
                mantissa += (higher_than_half | exactly_half_but_mantissa_odd) as u64;
298
                // Step 6: Calculate the exponent
299
                // If self is 0, exponent should be 0 (special meaning) and mantissa will end up 0 too
300
                // Otherwise, (Self::BITS - 1 - leading_zeros) + 1022 so it simplifies to Self::BITS + 1021 - leading_zeroes
301
                // 1023 and 1022 are the cutoffs for the exponent having the msb next to the decimal point
302
0
                let exponent = if self.is_zero() { 0 } else { u64::from(Self::BITS) + 1021 - u64::from(leading_zeroes) };
303
                // Step 7: sign bit is always 0, exponent is shifted into place
304
                // Use addition instead of bitwise OR to saturate the exponent if mantissa overflows
305
0
                f64::from_bits((exponent << 52) + mantissa)
306
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1926as_f64
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3206as_f64
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30726as_f64
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1926as_f64
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2566as_f64
307
308
            // divmod like operation, returns (quotient, remainder)
309
            #[inline]
310
15.4k
            pub fn div_rem(self, other: Self) -> (Self, Self) {
311
15.4k
                let mut sub_copy = self;
312
15.4k
                let mut shift_copy = other;
313
15.4k
                let mut ret = [0u64; Self::LIMBS];
314
315
15.4k
                let my_bits = self.bits();
316
15.4k
                let your_bits = other.bits();
317
318
                // Check for division by 0
319
15.4k
                assert_ne!(your_bits, 0, "attempted to divide {} by zero", self);
320
321
                // Early return in case we are dividing by a larger number than us
322
15.4k
                if my_bits < your_bits {
323
3.37k
                    return (Self(ret), sub_copy);
324
12.0k
                }
325
326
                // Bitwise long division
327
12.0k
                let mut shift = my_bits - your_bits;
328
12.0k
                shift_copy = shift_copy << shift;
329
                loop {
330
320k
                    if sub_copy >= shift_copy {
331
145k
                        let (shift_index, shift_val) = ((shift / 64) as usize, shift % 64);
332
145k
                        ret[shift_index] |= 1 << shift_val;
333
145k
                        sub_copy = sub_copy - shift_copy;
334
175k
                    }
335
320k
                    shift_copy = shift_copy >> 1;
336
320k
                    if shift == 0 {
337
12.0k
                        break;
338
308k
                    }
339
308k
                    shift -= 1;
340
                }
341
342
12.0k
                (Self(ret), sub_copy)
343
15.4k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1927div_rem
Line
Count
Source
310
15.4k
            pub fn div_rem(self, other: Self) -> (Self, Self) {
311
15.4k
                let mut sub_copy = self;
312
15.4k
                let mut shift_copy = other;
313
15.4k
                let mut ret = [0u64; Self::LIMBS];
314
315
15.4k
                let my_bits = self.bits();
316
15.4k
                let your_bits = other.bits();
317
318
                // Check for division by 0
319
15.4k
                assert_ne!(your_bits, 0, "attempted to divide {} by zero", self);
320
321
                // Early return in case we are dividing by a larger number than us
322
15.4k
                if my_bits < your_bits {
323
3.37k
                    return (Self(ret), sub_copy);
324
12.0k
                }
325
326
                // Bitwise long division
327
12.0k
                let mut shift = my_bits - your_bits;
328
12.0k
                shift_copy = shift_copy << shift;
329
                loop {
330
320k
                    if sub_copy >= shift_copy {
331
145k
                        let (shift_index, shift_val) = ((shift / 64) as usize, shift % 64);
332
145k
                        ret[shift_index] |= 1 << shift_val;
333
145k
                        sub_copy = sub_copy - shift_copy;
334
175k
                    }
335
320k
                    shift_copy = shift_copy >> 1;
336
320k
                    if shift == 0 {
337
12.0k
                        break;
338
308k
                    }
339
308k
                    shift -= 1;
340
                }
341
342
12.0k
                (Self(ret), sub_copy)
343
15.4k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3207div_rem
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30727div_rem
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1927div_rem
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2567div_rem
344
345
            // The general malachite-backed `mod_inverse` was removed; modular inversion is
346
            // provided for every Uint by the in-repo `lehmer` module (`math/src/lehmer.rs`, MIT,
347
            // faster than malachite) through the `LehmerInvert` extension trait, backed by the
348
            // `LehmerOps` impl below.
349
350
            #[inline]
351
4.98k
            pub fn iter_be_bits(self) -> impl ExactSizeIterator<Item = bool> + core::iter::FusedIterator {
352
                struct BinaryIterator {
353
                    array: [u64; $n_words],
354
                    bit: usize,
355
                }
356
357
                impl Iterator for BinaryIterator {
358
                    type Item = bool;
359
360
                    #[inline]
361
961k
                    fn next(&mut self) -> Option<Self::Item> {
362
961k
                        if self.bit >= 64 * $n_words {
363
4.98k
                            return None;
364
956k
                        }
365
956k
                        let (word, subbit) = (self.bit / 64, self.bit % 64);
366
956k
                        let current_bit = self.array[$n_words - word - 1] & (1 << 64 - subbit - 1);
367
956k
                        self.bit += 1;
368
956k
                        Some(current_bit != 0)
369
961k
                    }
_RNvXNvMCs3Hi7WNjIpVC_4u192NtB5_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator4next
Line
Count
Source
361
961k
                    fn next(&mut self) -> Option<Self::Item> {
362
961k
                        if self.bit >= 64 * $n_words {
363
4.98k
                            return None;
364
956k
                        }
365
956k
                        let (word, subbit) = (self.bit / 64, self.bit % 64);
366
956k
                        let current_bit = self.array[$n_words - word - 1] & (1 << 64 - subbit - 1);
367
956k
                        self.bit += 1;
368
956k
                        Some(current_bit != 0)
369
961k
                    }
Unexecuted instantiation: _RNvXNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint32012iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator4next
Unexecuted instantiation: _RNvXNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint307212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator4next
Unexecuted instantiation: _RNvXNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator4next
Unexecuted instantiation: _RNvXNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint25612iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator4next
370
371
                    #[inline]
372
0
                    fn nth(&mut self, n: usize) -> Option<Self::Item> {
373
0
                        match self.bit.checked_add(n) {
374
0
                            Some(bit) => {
375
0
                                self.bit = bit;
376
0
                                self.next()
377
                            }
378
                            None => {
379
0
                                self.bit = usize::MAX;
380
0
                                None
381
                            }
382
                        }
383
0
                    }
Unexecuted instantiation: _RNvXNvMCs3Hi7WNjIpVC_4u192NtB5_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator3nth
Unexecuted instantiation: _RNvXNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint32012iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator3nth
Unexecuted instantiation: _RNvXNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint307212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator3nth
Unexecuted instantiation: _RNvXNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator3nth
Unexecuted instantiation: _RNvXNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint25612iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator3nth
384
                    #[inline]
385
0
                    fn size_hint(&self) -> (usize, Option<usize>) {
386
0
                        let remaining_bits = $n_words * (u64::BITS as usize) - self.bit;
387
0
                        (remaining_bits, Some(remaining_bits))
388
0
                    }
Unexecuted instantiation: _RNvXNvMCs3Hi7WNjIpVC_4u192NtB5_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator9size_hint
Unexecuted instantiation: _RNvXNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint32012iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator9size_hint
Unexecuted instantiation: _RNvXNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint307212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator9size_hint
Unexecuted instantiation: _RNvXNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint19212iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator9size_hint
Unexecuted instantiation: _RNvXNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint25612iter_be_bitsNtB2_14BinaryIteratorNtNtNtNtCsloNou9alJSK_4core4iter6traits8iterator8Iterator9size_hint
389
                }
390
                impl ExactSizeIterator for BinaryIterator {}
391
                impl core::iter::FusedIterator for BinaryIterator {}
392
393
4.98k
                BinaryIterator { array: self.0, bit: 0 }
394
4.98k
            }
_RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19212iter_be_bits
Line
Count
Source
351
4.98k
            pub fn iter_be_bits(self) -> impl ExactSizeIterator<Item = bool> + core::iter::FusedIterator {
352
                struct BinaryIterator {
353
                    array: [u64; $n_words],
354
                    bit: usize,
355
                }
356
357
                impl Iterator for BinaryIterator {
358
                    type Item = bool;
359
360
                    #[inline]
361
                    fn next(&mut self) -> Option<Self::Item> {
362
                        if self.bit >= 64 * $n_words {
363
                            return None;
364
                        }
365
                        let (word, subbit) = (self.bit / 64, self.bit % 64);
366
                        let current_bit = self.array[$n_words - word - 1] & (1 << 64 - subbit - 1);
367
                        self.bit += 1;
368
                        Some(current_bit != 0)
369
                    }
370
371
                    #[inline]
372
                    fn nth(&mut self, n: usize) -> Option<Self::Item> {
373
                        match self.bit.checked_add(n) {
374
                            Some(bit) => {
375
                                self.bit = bit;
376
                                self.next()
377
                            }
378
                            None => {
379
                                self.bit = usize::MAX;
380
                                None
381
                            }
382
                        }
383
                    }
384
                    #[inline]
385
                    fn size_hint(&self) -> (usize, Option<usize>) {
386
                        let remaining_bits = $n_words * (u64::BITS as usize) - self.bit;
387
                        (remaining_bits, Some(remaining_bits))
388
                    }
389
                }
390
                impl ExactSizeIterator for BinaryIterator {}
391
                impl core::iter::FusedIterator for BinaryIterator {}
392
393
4.98k
                BinaryIterator { array: self.0, bit: 0 }
394
4.98k
            }
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32012iter_be_bits
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307212iter_be_bits
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19212iter_be_bits
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25612iter_be_bits
395
396
            /// Converts a Self::BYTES*2 hex string interpreted as big endian, into a Uint
397
            #[inline]
398
0
            pub fn from_hex(hex: &str) -> Result<Self, $crate::uint::faster_hex::Error> {
399
0
                if hex.len() > Self::BYTES * 2 {
400
0
                    return Err($crate::uint::faster_hex::Error::InvalidLength(hex.len()));
401
0
                }
402
0
                let mut out = [0u8; Self::BYTES];
403
0
                let mut input = [b'0'; Self::BYTES * 2];
404
0
                let start = input.len() - hex.len();
405
0
                input[start..].copy_from_slice(hex.as_bytes());
406
0
                $crate::uint::faster_hex::hex_decode(&input, &mut out)?;
407
0
                Ok(Self::from_be_bytes(out))
408
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1928from_hex
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3208from_hex
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30728from_hex
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1928from_hex
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2568from_hex
409
410
            #[inline]
411
0
            pub fn from_be_bytes_var(bytes: &[u8]) -> Result<Self, $crate::uint::TryFromSliceError> {
412
0
                if bytes.len() > Self::BYTES {
413
0
                    return Err($crate::uint::TryFromSliceError);
414
0
                }
415
0
                let mut out = [0u8; Self::BYTES];
416
0
                let start = Self::BYTES - bytes.len();
417
0
                out[start..].copy_from_slice(bytes);
418
0
                Ok(Self::from_be_bytes(out))
419
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint19217from_be_bytes_var
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint32017from_be_bytes_var
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint307217from_be_bytes_var
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint19217from_be_bytes_var
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint25617from_be_bytes_var
420
421
            #[inline]
422
0
            pub fn as_bigint(&self) -> Result<$crate::uint::js_sys::BigInt, $crate::Error> {
423
0
                self.try_into()
424
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1929as_bigint
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3209as_bigint
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30729as_bigint
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1929as_bigint
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2569as_bigint
425
426
            #[inline]
427
0
            pub fn to_bigint(self) -> Result<$crate::uint::js_sys::BigInt, $crate::Error> {
428
0
                self.try_into()
429
0
            }
Unexecuted instantiation: _RNvMCs3Hi7WNjIpVC_4u192NtB2_7Uint1929to_bigint
Unexecuted instantiation: _RNvMs1J_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint3209to_bigint
Unexecuted instantiation: _RNvMs2x_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint30729to_bigint
Unexecuted instantiation: _RNvMs5_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint1929to_bigint
Unexecuted instantiation: _RNvMsV_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint2569to_bigint
430
431
        }
432
433
        impl $crate::lehmer::LehmerOps for $name {
434
            type Limbs = [u64; $n_words];
435
            type Cofactor = [u64; $n_words + $crate::lehmer::COFACTOR_HEADROOM];
436
            #[inline]
437
7.76k
            fn from_limbs(limbs: Self::Limbs) -> Self {
438
7.76k
                Self(limbs)
439
7.76k
            }
_RNvXs_Cs3Hi7WNjIpVC_4u192NtB4_7Uint192NtNtCs8KLYHAG7u19_10kaspa_math6lehmer9LehmerOps10from_limbs
Line
Count
Source
437
7.76k
            fn from_limbs(limbs: Self::Limbs) -> Self {
438
7.76k
                Self(limbs)
439
7.76k
            }
Unexecuted instantiation: _RNvXs1K_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtB6_6lehmer9LehmerOps10from_limbs
Unexecuted instantiation: _RNvXs2y_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtB6_6lehmer9LehmerOps10from_limbs
Unexecuted instantiation: _RNvXs6_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtB5_6lehmer9LehmerOps10from_limbs
Unexecuted instantiation: _RNvXsW_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint256NtNtB5_6lehmer9LehmerOps10from_limbs
440
            #[inline]
441
17.2k
            fn into_limbs(self) -> Self::Limbs {
442
17.2k
                self.0
443
17.2k
            }
_RNvXs_Cs3Hi7WNjIpVC_4u192NtB4_7Uint192NtNtCs8KLYHAG7u19_10kaspa_math6lehmer9LehmerOps10into_limbs
Line
Count
Source
441
17.2k
            fn into_limbs(self) -> Self::Limbs {
442
17.2k
                self.0
443
17.2k
            }
Unexecuted instantiation: _RNvXs1K_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtB6_6lehmer9LehmerOps10into_limbs
Unexecuted instantiation: _RNvXs2y_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtB6_6lehmer9LehmerOps10into_limbs
Unexecuted instantiation: _RNvXs6_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtB5_6lehmer9LehmerOps10into_limbs
Unexecuted instantiation: _RNvXsW_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint256NtNtB5_6lehmer9LehmerOps10into_limbs
444
            #[inline]
445
4.67k
            fn div_rem(self, other: Self) -> (Self, Self) {
446
4.67k
                $name::div_rem(self, other)
447
4.67k
            }
_RNvXs_Cs3Hi7WNjIpVC_4u192NtB4_7Uint192NtNtCs8KLYHAG7u19_10kaspa_math6lehmer9LehmerOps7div_rem
Line
Count
Source
445
4.67k
            fn div_rem(self, other: Self) -> (Self, Self) {
446
4.67k
                $name::div_rem(self, other)
447
4.67k
            }
Unexecuted instantiation: _RNvXs1K_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtB6_6lehmer9LehmerOps7div_rem
Unexecuted instantiation: _RNvXs2y_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtB6_6lehmer9LehmerOps7div_rem
Unexecuted instantiation: _RNvXs6_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtB5_6lehmer9LehmerOps7div_rem
Unexecuted instantiation: _RNvXsW_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint256NtNtB5_6lehmer9LehmerOps7div_rem
448
        }
449
450
        impl $crate::uint::kaspa_utils::mem_size::MemSizeEstimator for $name {
451
0
            fn estimate_mem_units(&self) -> usize {
452
0
                1
453
454
0
            }
Unexecuted instantiation: _RNvXs0_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils8mem_size16MemSizeEstimator18estimate_mem_units
Unexecuted instantiation: _RNvXs1L_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsk5EKZBqjsTv_11kaspa_utils8mem_size16MemSizeEstimator18estimate_mem_units
Unexecuted instantiation: _RNvXs2z_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsk5EKZBqjsTv_11kaspa_utils8mem_size16MemSizeEstimator18estimate_mem_units
Unexecuted instantiation: _RNvXs7_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils8mem_size16MemSizeEstimator18estimate_mem_units
Unexecuted instantiation: _RNvXsX_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint256NtNtCsk5EKZBqjsTv_11kaspa_utils8mem_size16MemSizeEstimator18estimate_mem_units
455
        }
456
457
        impl $crate::uint::kaspa_utils::hex::ToHex for $name {
458
0
            fn to_hex(&self) -> String {
459
0
                self.to_be_bytes().as_slice().to_hex()
460
0
            }
Unexecuted instantiation: _RNvXs1_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs1M_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs2A_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs8_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXsY_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint256NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
461
        }
462
463
        impl $crate::uint::kaspa_utils::hex::ToHex for &$name {
464
0
            fn to_hex(&self) -> String {
465
0
                self.to_be_bytes().as_slice().to_hex()
466
0
            }
Unexecuted instantiation: _RNvXs2_Cs3Hi7WNjIpVC_4u192RNtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs1N_Cs8KLYHAG7u19_10kaspa_mathRNtB6_7Uint320NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs2B_Cs8KLYHAG7u19_10kaspa_mathRNtB6_8Uint3072NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXs9_Cs8KLYHAG7u19_10kaspa_mathRNtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
Unexecuted instantiation: _RNvXsZ_Cs8KLYHAG7u19_10kaspa_mathRNtB5_7Uint256NtNtCsk5EKZBqjsTv_11kaspa_utils3hex5ToHex6to_hex
467
        }
468
469
        impl $crate::uint::kaspa_utils::hex::FromHex for $name {
470
            type Error = $crate::Error;
471
0
            fn from_hex(hex: &str) -> Result<$name, Self::Error> {
472
0
                Ok($name::from_hex(hex)?)
473
0
            }
Unexecuted instantiation: _RNvXs3_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex7FromHex8from_hex
Unexecuted instantiation: _RNvXs10_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsk5EKZBqjsTv_11kaspa_utils3hex7FromHex8from_hex
Unexecuted instantiation: _RNvXs1O_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsk5EKZBqjsTv_11kaspa_utils3hex7FromHex8from_hex
Unexecuted instantiation: _RNvXs2C_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsk5EKZBqjsTv_11kaspa_utils3hex7FromHex8from_hex
Unexecuted instantiation: _RNvXsa_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsk5EKZBqjsTv_11kaspa_utils3hex7FromHex8from_hex
474
        }
475
476
        impl PartialEq<u64> for $name {
477
            #[inline]
478
0
            fn eq(&self, other: &u64) -> bool {
479
0
                let bigger = self.0[1..].iter().any(|&x| x != 0);
Unexecuted instantiation: _RNCNvXs4_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq0B7_
Unexecuted instantiation: _RNCNvXs11_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq0B8_
Unexecuted instantiation: _RNCNvXs1P_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq0B8_
Unexecuted instantiation: _RNCNvXs2D_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq0B8_
Unexecuted instantiation: _RNCNvXsb_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq0B7_
480
0
                !bigger && self.0[0] == *other
481
0
            }
Unexecuted instantiation: _RNvXs4_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq
Unexecuted instantiation: _RNvXs11_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq
Unexecuted instantiation: _RNvXs1P_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq
Unexecuted instantiation: _RNvXs2D_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq
Unexecuted instantiation: _RNvXsb_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqyE2eq
482
        }
483
        impl PartialOrd<u64> for $name {
484
            #[inline]
485
6.25k
            fn partial_cmp(&self, other: &u64) -> Option<core::cmp::Ordering> {
486
8.52k
                let bigger = self.0[1..].iter().any(|&x| x != 0);
_RNCNvXs5_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp0B7_
Line
Count
Source
486
8.52k
                let bigger = self.0[1..].iter().any(|&x| x != 0);
Unexecuted instantiation: _RNCNvXs12_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXs1Q_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXs2E_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXsc_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp0B7_
487
6.25k
                if bigger {
488
4.52k
                    Some(core::cmp::Ordering::Greater)
489
                } else {
490
1.72k
                    self.0[0].partial_cmp(other)
491
                }
492
6.25k
            }
_RNvXs5_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp
Line
Count
Source
485
6.25k
            fn partial_cmp(&self, other: &u64) -> Option<core::cmp::Ordering> {
486
6.25k
                let bigger = self.0[1..].iter().any(|&x| x != 0);
487
6.25k
                if bigger {
488
4.52k
                    Some(core::cmp::Ordering::Greater)
489
                } else {
490
1.72k
                    self.0[0].partial_cmp(other)
491
                }
492
6.25k
            }
Unexecuted instantiation: _RNvXs12_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp
Unexecuted instantiation: _RNvXs1Q_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp
Unexecuted instantiation: _RNvXs2E_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp
Unexecuted instantiation: _RNvXsc_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdyE11partial_cmp
493
        }
494
495
        impl PartialEq<u128> for $name {
496
            #[inline]
497
0
            fn eq(&self, other: &u128) -> bool {
498
0
                let bigger = self.0[2..].iter().any(|&x| x != 0);
Unexecuted instantiation: _RNCNvXs6_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq0B7_
Unexecuted instantiation: _RNCNvXs13_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq0B8_
Unexecuted instantiation: _RNCNvXs1R_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq0B8_
Unexecuted instantiation: _RNCNvXs2F_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq0B8_
Unexecuted instantiation: _RNCNvXsd_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq0B7_
499
0
                !bigger && self.0[0] == (*other as u64) && self.0[1] == ((*other >> 64) as u64)
500
0
            }
Unexecuted instantiation: _RNvXs6_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq
Unexecuted instantiation: _RNvXs13_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq
Unexecuted instantiation: _RNvXs1R_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq
Unexecuted instantiation: _RNvXs2F_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq
Unexecuted instantiation: _RNvXsd_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp9PartialEqoE2eq
501
        }
502
        impl PartialOrd<u128> for $name {
503
            #[inline]
504
0
            fn partial_cmp(&self, other: &u128) -> Option<core::cmp::Ordering> {
505
0
                let bigger = self.0[2..].iter().any(|&x| x != 0);
Unexecuted instantiation: _RNCNvXs7_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp0B7_
Unexecuted instantiation: _RNCNvXs14_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXs1S_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXs2G_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp0B8_
Unexecuted instantiation: _RNCNvXse_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp0B7_
506
0
                if bigger {
507
0
                    Some(core::cmp::Ordering::Greater)
508
                } else {
509
0
                    self.as_u128().partial_cmp(other)
510
                }
511
0
            }
Unexecuted instantiation: _RNvXs7_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp
Unexecuted instantiation: _RNvXs14_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp
Unexecuted instantiation: _RNvXs1S_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp
Unexecuted instantiation: _RNvXs2G_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp
Unexecuted instantiation: _RNvXse_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core3cmp10PartialOrdoE11partial_cmp
512
        }
513
514
        impl PartialOrd for $name {
515
            #[inline]
516
320k
            fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
517
320k
                Some(self.cmp(&other))
518
320k
            }
_RNvXs8_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core3cmp10PartialOrd11partial_cmp
Line
Count
Source
516
320k
            fn partial_cmp(&self, other: &$name) -> Option<core::cmp::Ordering> {
517
320k
                Some(self.cmp(&other))
518
320k
            }
Unexecuted instantiation: _RNvXs15_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core3cmp10PartialOrd11partial_cmp
Unexecuted instantiation: _RNvXs1T_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core3cmp10PartialOrd11partial_cmp
Unexecuted instantiation: _RNvXs2H_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core3cmp10PartialOrd11partial_cmp
Unexecuted instantiation: _RNvXsf_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core3cmp10PartialOrd11partial_cmp
519
        }
520
521
        impl Ord for $name {
522
            #[inline]
523
320k
            fn cmp(&self, other: &$name) -> core::cmp::Ordering {
524
                // We need to manually implement ordering because we use little-endian
525
                // and the auto derive is a lexicographic ordering(i.e. memcmp)
526
                // which with numbers is equivalent to big-endian
527
320k
                Iterator::cmp(self.0.iter().rev(), other.0.iter().rev())
528
320k
            }
_RNvXs9_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core3cmp3Ord3cmp
Line
Count
Source
523
320k
            fn cmp(&self, other: &$name) -> core::cmp::Ordering {
524
                // We need to manually implement ordering because we use little-endian
525
                // and the auto derive is a lexicographic ordering(i.e. memcmp)
526
                // which with numbers is equivalent to big-endian
527
320k
                Iterator::cmp(self.0.iter().rev(), other.0.iter().rev())
528
320k
            }
Unexecuted instantiation: _RNvXs16_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core3cmp3Ord3cmp
Unexecuted instantiation: _RNvXs1U_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core3cmp3Ord3cmp
Unexecuted instantiation: _RNvXs2I_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core3cmp3Ord3cmp
Unexecuted instantiation: _RNvXsg_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core3cmp3Ord3cmp
529
        }
530
531
        impl core::ops::Add<$name> for $name {
532
            type Output = $name;
533
534
            #[inline]
535
            #[track_caller]
536
5.49k
            fn add(self, other: $name) -> $name {
537
5.49k
                let (sum, carry) = self.overflowing_add(other);
538
5.49k
                debug_assert!(!carry, "attempt to add with overflow"); // Check in debug that it didn't overflow
539
5.49k
                sum
540
5.49k
            }
_RNvXsa_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Add3add
Line
Count
Source
536
5.49k
            fn add(self, other: $name) -> $name {
537
5.49k
                let (sum, carry) = self.overflowing_add(other);
538
5.49k
                debug_assert!(!carry, "attempt to add with overflow"); // Check in debug that it didn't overflow
539
5.49k
                sum
540
5.49k
            }
Unexecuted instantiation: _RNvXs17_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops5arith3Add3add
Unexecuted instantiation: _RNvXs1V_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops5arith3Add3add
Unexecuted instantiation: _RNvXs2J_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops5arith3Add3add
Unexecuted instantiation: _RNvXsh_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Add3add
541
        }
542
543
        impl core::ops::Add<u64> for $name {
544
            type Output = $name;
545
546
            #[inline]
547
            #[track_caller]
548
5.17k
            fn add(self, other: u64) -> $name {
549
5.17k
                let (sum, carry) = self.overflowing_add_u64(other);
550
5.17k
                debug_assert!(!carry, "attempt to add with overflow"); // Check in debug that it didn't overflow
551
5.17k
                sum
552
5.17k
            }
_RNvXsb_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3AddyE3add
Line
Count
Source
548
5.17k
            fn add(self, other: u64) -> $name {
549
5.17k
                let (sum, carry) = self.overflowing_add_u64(other);
550
5.17k
                debug_assert!(!carry, "attempt to add with overflow"); // Check in debug that it didn't overflow
551
5.17k
                sum
552
5.17k
            }
Unexecuted instantiation: _RNvXs18_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops5arith3AddyE3add
Unexecuted instantiation: _RNvXs1W_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops5arith3AddyE3add
Unexecuted instantiation: _RNvXs2K_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops5arith3AddyE3add
Unexecuted instantiation: _RNvXsi_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3AddyE3add
553
        }
554
555
        impl core::ops::Sub<$name> for $name {
556
            type Output = $name;
557
558
            #[inline]
559
            #[track_caller]
560
145k
            fn sub(self, other: $name) -> $name {
561
145k
                let (sum, carry) = self.overflowing_sub(other);
562
145k
                debug_assert!(!carry, "attempt to subtract with overflow"); // Check in debug that it didn't overflow
563
145k
                sum
564
145k
            }
_RNvXsc_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Sub3sub
Line
Count
Source
560
145k
            fn sub(self, other: $name) -> $name {
561
145k
                let (sum, carry) = self.overflowing_sub(other);
562
145k
                debug_assert!(!carry, "attempt to subtract with overflow"); // Check in debug that it didn't overflow
563
145k
                sum
564
145k
            }
Unexecuted instantiation: _RNvXs19_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops5arith3Sub3sub
Unexecuted instantiation: _RNvXs1X_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops5arith3Sub3sub
Unexecuted instantiation: _RNvXs2L_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops5arith3Sub3sub
Unexecuted instantiation: _RNvXsj_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Sub3sub
565
        }
566
567
        impl core::ops::Mul<$name> for $name {
568
            type Output = $name;
569
570
            #[inline]
571
            #[track_caller]
572
5.46k
            fn mul(self, other: $name) -> $name {
573
5.46k
                let (product, carry) = self.overflowing_mul(other);
574
5.46k
                debug_assert!(!carry, "attempt to multiply with overflow"); // Check in debug that it didn't overflow
575
5.46k
                product
576
5.46k
            }
_RNvXsd_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Mul3mul
Line
Count
Source
572
5.46k
            fn mul(self, other: $name) -> $name {
573
5.46k
                let (product, carry) = self.overflowing_mul(other);
574
5.46k
                debug_assert!(!carry, "attempt to multiply with overflow"); // Check in debug that it didn't overflow
575
5.46k
                product
576
5.46k
            }
Unexecuted instantiation: _RNvXs1Y_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops5arith3Mul3mul
Unexecuted instantiation: _RNvXs1a_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops5arith3Mul3mul
Unexecuted instantiation: _RNvXs2M_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops5arith3Mul3mul
Unexecuted instantiation: _RNvXsk_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Mul3mul
577
        }
578
579
        impl core::ops::Mul<u64> for $name {
580
            type Output = $name;
581
582
            #[inline]
583
            #[track_caller]
584
5.15k
            fn mul(self, other: u64) -> $name {
585
5.15k
                let (product, carry) = self.overflowing_mul_u64(other);
586
5.15k
                debug_assert!(!carry, "attempt to multiply with overflow"); // Check in debug that it didn't overflow
587
5.15k
                product
588
5.15k
            }
_RNvXse_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3MulyE3mul
Line
Count
Source
584
5.15k
            fn mul(self, other: u64) -> $name {
585
5.15k
                let (product, carry) = self.overflowing_mul_u64(other);
586
5.15k
                debug_assert!(!carry, "attempt to multiply with overflow"); // Check in debug that it didn't overflow
587
5.15k
                product
588
5.15k
            }
Unexecuted instantiation: _RNvXs1Z_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops5arith3MulyE3mul
Unexecuted instantiation: _RNvXs1b_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops5arith3MulyE3mul
Unexecuted instantiation: _RNvXs2N_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops5arith3MulyE3mul
Unexecuted instantiation: _RNvXsl_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3MulyE3mul
589
        }
590
591
        impl core::ops::Div<$name> for $name {
592
            type Output = $name;
593
594
            #[inline]
595
5.41k
            fn div(self, other: $name) -> $name {
596
5.41k
                self.div_rem(other).0
597
5.41k
            }
_RNvXsf_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Div3div
Line
Count
Source
595
5.41k
            fn div(self, other: $name) -> $name {
596
5.41k
                self.div_rem(other).0
597
5.41k
            }
Unexecuted instantiation: _RNvXs1c_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops5arith3Div3div
Unexecuted instantiation: _RNvXs20_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops5arith3Div3div
Unexecuted instantiation: _RNvXs2O_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops5arith3Div3div
Unexecuted instantiation: _RNvXsm_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Div3div
598
        }
599
600
        impl core::ops::Rem<$name> for $name {
601
            type Output = $name;
602
603
            #[inline]
604
5.32k
            fn rem(self, other: $name) -> $name {
605
5.32k
                self.div_rem(other).1
606
5.32k
            }
_RNvXsg_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Rem3rem
Line
Count
Source
604
5.32k
            fn rem(self, other: $name) -> $name {
605
5.32k
                self.div_rem(other).1
606
5.32k
            }
Unexecuted instantiation: _RNvXs1d_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops5arith3Rem3rem
Unexecuted instantiation: _RNvXs21_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops5arith3Rem3rem
Unexecuted instantiation: _RNvXs2P_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops5arith3Rem3rem
Unexecuted instantiation: _RNvXsn_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops5arith3Rem3rem
607
        }
608
609
        impl core::ops::Div<u64> for $name {
610
            type Output = $name;
611
612
            #[inline]
613
0
            fn div(self, other: u64) -> $name {
614
0
                self.div_rem_u64(other).0
615
0
            }
Unexecuted instantiation: _RNvXsh_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3DivyE3div
Unexecuted instantiation: _RNvXs1e_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops5arith3DivyE3div
Unexecuted instantiation: _RNvXs22_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops5arith3DivyE3div
Unexecuted instantiation: _RNvXs2Q_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops5arith3DivyE3div
Unexecuted instantiation: _RNvXso_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3DivyE3div
616
        }
617
618
        impl core::ops::Rem<u64> for $name {
619
            type Output = u64;
620
621
0
            fn rem(self, other: u64) -> u64 {
622
0
                self.div_rem_u64(other).1
623
0
            }
Unexecuted instantiation: _RNvXsi_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3RemyE3rem
Unexecuted instantiation: _RNvXs1f_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops5arith3RemyE3rem
Unexecuted instantiation: _RNvXs23_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops5arith3RemyE3rem
Unexecuted instantiation: _RNvXs2R_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops5arith3RemyE3rem
Unexecuted instantiation: _RNvXsp_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops5arith3RemyE3rem
624
        }
625
626
        impl core::ops::BitAnd<$name> for $name {
627
            type Output = $name;
628
629
            #[inline]
630
5.26k
            fn bitand(mut self, other: $name) -> $name {
631
15.8k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a &= *b);
_RNCNvXsj_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand0B7_
Line
Count
Source
631
15.8k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a &= *b);
Unexecuted instantiation: _RNCNvXs1g_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand0B8_
Unexecuted instantiation: _RNCNvXs24_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand0B8_
Unexecuted instantiation: _RNCNvXs2S_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand0B8_
Unexecuted instantiation: _RNCNvXsq_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand0B7_
632
5.26k
                self
633
5.26k
            }
_RNvXsj_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand
Line
Count
Source
630
5.26k
            fn bitand(mut self, other: $name) -> $name {
631
5.26k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a &= *b);
632
5.26k
                self
633
5.26k
            }
Unexecuted instantiation: _RNvXs1g_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand
Unexecuted instantiation: _RNvXs24_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand
Unexecuted instantiation: _RNvXs2S_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand
Unexecuted instantiation: _RNvXsq_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitAnd6bitand
634
        }
635
636
        impl core::ops::BitXor<$name> for $name {
637
            type Output = $name;
638
639
            #[inline]
640
5.21k
            fn bitxor(mut self, other: $name) -> $name {
641
15.6k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a ^= *b);
_RNCNvXsk_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor0B7_
Line
Count
Source
641
15.6k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a ^= *b);
Unexecuted instantiation: _RNCNvXs1h_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor0B8_
Unexecuted instantiation: _RNCNvXs25_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor0B8_
Unexecuted instantiation: _RNCNvXs2T_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor0B8_
Unexecuted instantiation: _RNCNvXsr_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor0B7_
642
5.21k
                self
643
5.21k
            }
_RNvXsk_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor
Line
Count
Source
640
5.21k
            fn bitxor(mut self, other: $name) -> $name {
641
5.21k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a ^= *b);
642
5.21k
                self
643
5.21k
            }
Unexecuted instantiation: _RNvXs1h_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor
Unexecuted instantiation: _RNvXs25_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor
Unexecuted instantiation: _RNvXs2T_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor
Unexecuted instantiation: _RNvXsr_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit6BitXor6bitxor
644
        }
645
646
        impl core::ops::BitOr<$name> for $name {
647
            type Output = $name;
648
649
            #[inline]
650
5.23k
            fn bitor(mut self, other: $name) -> $name {
651
15.7k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a |= *b);
_RNCNvXsl_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor0B7_
Line
Count
Source
651
15.7k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a |= *b);
Unexecuted instantiation: _RNCNvXs1i_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor0B8_
Unexecuted instantiation: _RNCNvXs26_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor0B8_
Unexecuted instantiation: _RNCNvXs2U_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor0B8_
Unexecuted instantiation: _RNCNvXss_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor0B7_
652
5.23k
                self
653
5.23k
            }
_RNvXsl_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor
Line
Count
Source
650
5.23k
            fn bitor(mut self, other: $name) -> $name {
651
5.23k
                self.0.iter_mut().zip(other.0.iter()).for_each(|(a, b)| *a |= *b);
652
5.23k
                self
653
5.23k
            }
Unexecuted instantiation: _RNvXs1i_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor
Unexecuted instantiation: _RNvXs26_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor
Unexecuted instantiation: _RNvXs2U_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor
Unexecuted instantiation: _RNvXss_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit5BitOr5bitor
654
        }
655
656
        impl core::ops::Not for $name {
657
            type Output = $name;
658
659
            #[inline]
660
0
            fn not(mut self) -> $name {
661
0
                self.0.iter_mut().for_each(|a| *a = !*a);
Unexecuted instantiation: _RNCNvXsm_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not0B7_
Unexecuted instantiation: _RNCNvXs1j_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not0B8_
Unexecuted instantiation: _RNCNvXs27_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not0B8_
Unexecuted instantiation: _RNCNvXs2V_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not0B8_
Unexecuted instantiation: _RNCNvXst_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not0B7_
662
0
                self
663
0
            }
Unexecuted instantiation: _RNvXsm_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not
Unexecuted instantiation: _RNvXs1j_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not
Unexecuted instantiation: _RNvXs27_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not
Unexecuted instantiation: _RNvXs2V_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not
Unexecuted instantiation: _RNvXst_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtNtCsloNou9alJSK_4core3ops3bit3Not3not
664
        }
665
666
        impl core::ops::Shl<u32> for $name {
667
            type Output = $name;
668
669
            #[inline]
670
            #[track_caller]
671
17.1k
            fn shl(self, shift: u32) -> $name {
672
17.1k
                let (res, carry) = self.overflowing_shl(shift);
673
17.1k
                debug_assert!(!carry, "attempt to shift left with overflow"); // Check in debug that it didn't overflow
674
17.1k
                res
675
17.1k
            }
_RNvXsn_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops3bit3ShlmE3shl
Line
Count
Source
671
17.1k
            fn shl(self, shift: u32) -> $name {
672
17.1k
                let (res, carry) = self.overflowing_shl(shift);
673
17.1k
                debug_assert!(!carry, "attempt to shift left with overflow"); // Check in debug that it didn't overflow
674
17.1k
                res
675
17.1k
            }
Unexecuted instantiation: _RNvXs1k_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops3bit3ShlmE3shl
Unexecuted instantiation: _RNvXs28_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops3bit3ShlmE3shl
Unexecuted instantiation: _RNvXs2W_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops3bit3ShlmE3shl
Unexecuted instantiation: _RNvXsu_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops3bit3ShlmE3shl
676
        }
677
678
        impl core::ops::Shr<u32> for $name {
679
            type Output = $name;
680
681
            #[inline]
682
            #[track_caller]
683
325k
            fn shr(self, shift: u32) -> $name {
684
325k
                let (res, carry) = self.overflowing_shr(shift);
685
325k
                debug_assert!(!carry, "attempt to shift left with overflow"); // Check in debug that it didn't overflow
686
325k
                res
687
325k
            }
_RNvXso_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops3bit3ShrmE3shr
Line
Count
Source
683
325k
            fn shr(self, shift: u32) -> $name {
684
325k
                let (res, carry) = self.overflowing_shr(shift);
685
325k
                debug_assert!(!carry, "attempt to shift left with overflow"); // Check in debug that it didn't overflow
686
325k
                res
687
325k
            }
Unexecuted instantiation: _RNvXs1l_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtNtCsloNou9alJSK_4core3ops3bit3ShrmE3shr
Unexecuted instantiation: _RNvXs29_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtNtCsloNou9alJSK_4core3ops3bit3ShrmE3shr
Unexecuted instantiation: _RNvXs2X_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtNtCsloNou9alJSK_4core3ops3bit3ShrmE3shr
Unexecuted instantiation: _RNvXsv_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtNtCsloNou9alJSK_4core3ops3bit3ShrmE3shr
688
        }
689
690
        impl core::iter::Sum for $name {
691
            #[inline]
692
            #[track_caller]
693
0
            fn sum<I: Iterator<Item = Self>>(mut iter: I) -> Self {
694
0
                let first = iter.next().unwrap_or_else(|| Self::ZERO);
695
0
                iter.fold(first, |a, b| a + b)
Unexecuted instantiation: _RNCINvXsp_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEs_0B8_
Unexecuted instantiation: _RNCINvXs1m_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXs2Y_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXs2a_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXsw_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEs_0B8_
696
0
            }
Unexecuted instantiation: _RINvXsp_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEB6_
Unexecuted instantiation: _RINvXs1m_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEB7_
Unexecuted instantiation: _RINvXs2Y_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEB7_
Unexecuted instantiation: _RINvXs2a_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEB7_
Unexecuted instantiation: _RINvXsw_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3Sum3sumpEB6_
697
        }
698
699
        impl core::iter::Product for $name {
700
            #[inline]
701
            #[track_caller]
702
0
            fn product<I: Iterator<Item = Self>>(mut iter: I) -> Self {
703
0
                let first = iter.next().unwrap_or_else(|| Self::from_u64(1));
Unexecuted instantiation: _RNCINvXsq_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpE0B8_
Unexecuted instantiation: _RNCINvXs1n_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpE0B9_
Unexecuted instantiation: _RNCINvXs2Z_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpE0B9_
Unexecuted instantiation: _RNCINvXs2b_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpE0B9_
Unexecuted instantiation: _RNCINvXsx_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpE0B8_
704
0
                iter.fold(first, |a, b| a * b)
Unexecuted instantiation: _RNCINvXsq_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEs_0B8_
Unexecuted instantiation: _RNCINvXs1n_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEs_0B9_
Unexecuted instantiation: _RNCINvXs2Z_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEs_0B9_
Unexecuted instantiation: _RNCINvXs2b_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEs_0B9_
Unexecuted instantiation: _RNCINvXsx_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEs_0B8_
705
0
            }
Unexecuted instantiation: _RINvXsq_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEB6_
Unexecuted instantiation: _RINvXs1n_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEB7_
Unexecuted instantiation: _RINvXs2Z_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEB7_
Unexecuted instantiation: _RINvXs2b_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEB7_
Unexecuted instantiation: _RINvXsx_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192NtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7Product7productpEB6_
706
        }
707
708
        impl<'a> core::iter::Sum<&'a $name> for $name {
709
            #[inline]
710
            #[track_caller]
711
0
            fn sum<I: Iterator<Item = &'a Self>>(mut iter: I) -> Self {
712
0
                let first = iter.next().copied().unwrap_or_else(|| Self::ZERO);
713
0
                iter.fold(first, |a, &b| a + b)
Unexecuted instantiation: _RNCINvXsr_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBr_E3sumpEs_0B8_
Unexecuted instantiation: _RNCINvXs1o_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBz_E3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXs2c_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBz_E3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXs30_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBz_E3sumpEs_0B9_
Unexecuted instantiation: _RNCINvXsy_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBy_E3sumpEs_0B8_
714
0
            }
Unexecuted instantiation: _RINvXsr_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBp_E3sumpEB6_
Unexecuted instantiation: _RINvXs1o_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBx_E3sumpEB7_
Unexecuted instantiation: _RINvXs2c_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBx_E3sumpEB7_
Unexecuted instantiation: _RINvXs30_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBx_E3sumpEB7_
Unexecuted instantiation: _RINvXsy_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum3SumRBw_E3sumpEB6_
715
        }
716
717
        impl<'a> core::iter::Product<&'a $name> for $name {
718
            #[inline]
719
            #[track_caller]
720
0
            fn product<I: Iterator<Item = &'a Self>>(mut iter: I) -> Self {
721
0
                let first = iter.next().copied().unwrap_or_else(|| Self::from_u64(1));
Unexecuted instantiation: _RNCINvXss_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBr_E7productpE0B8_
Unexecuted instantiation: _RNCINvXs1p_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpE0B9_
Unexecuted instantiation: _RNCINvXs2d_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpE0B9_
Unexecuted instantiation: _RNCINvXs31_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpE0B9_
Unexecuted instantiation: _RNCINvXsz_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBy_E7productpE0B8_
722
0
                iter.fold(first, |a, &b| a * b)
Unexecuted instantiation: _RNCINvXss_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBr_E7productpEs_0B8_
Unexecuted instantiation: _RNCINvXs1p_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpEs_0B9_
Unexecuted instantiation: _RNCINvXs2d_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpEs_0B9_
Unexecuted instantiation: _RNCINvXs31_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBz_E7productpEs_0B9_
Unexecuted instantiation: _RNCINvXsz_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBy_E7productpEs_0B8_
723
0
            }
Unexecuted instantiation: _RINvXss_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBp_E7productpEB6_
Unexecuted instantiation: _RINvXs1p_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBx_E7productpEB7_
Unexecuted instantiation: _RINvXs2d_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBx_E7productpEB7_
Unexecuted instantiation: _RINvXs31_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBx_E7productpEB7_
Unexecuted instantiation: _RINvXsz_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192INtNtNtNtCsloNou9alJSK_4core4iter6traits5accum7ProductRBw_E7productpEB6_
724
        }
725
726
        impl Default for $name {
727
            #[inline]
728
0
            fn default() -> Self {
729
0
                Self::ZERO
730
0
            }
Unexecuted instantiation: _RNvXst_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core7default7Default7default
Unexecuted instantiation: _RNvXs1q_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core7default7Default7default
Unexecuted instantiation: _RNvXs2e_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core7default7Default7default
Unexecuted instantiation: _RNvXs32_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core7default7Default7default
Unexecuted instantiation: _RNvXsA_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core7default7Default7default
731
        }
732
733
        impl From<u64> for $name {
734
            #[inline]
735
0
            fn from(x: u64) -> Self {
736
0
                Self::from_u64(x)
737
0
            }
Unexecuted instantiation: _RNvXsu_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core7convert4FromyE4from
Unexecuted instantiation: _RNvXs1r_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core7convert4FromyE4from
Unexecuted instantiation: _RNvXs2f_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core7convert4FromyE4from
Unexecuted instantiation: _RNvXs33_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core7convert4FromyE4from
Unexecuted instantiation: _RNvXsB_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core7convert4FromyE4from
738
        }
739
740
        impl core::convert::TryFrom<$name> for u128 {
741
            type Error = $crate::uint::TryFromIntError;
742
743
            #[inline]
744
0
            fn try_from(value: $name) -> Result<Self, Self::Error> {
745
0
                if value.0[2..].iter().any(|&x| x != 0) {
Unexecuted instantiation: _RNCNvXsv_Cs3Hi7WNjIpVC_4u192oINtNtCsloNou9alJSK_4core7convert7TryFromNtB7_7Uint192E8try_from0B7_
Unexecuted instantiation: _RNCNvXs1s_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB8_7Uint256E8try_from0B8_
Unexecuted instantiation: _RNCNvXs2g_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB8_7Uint320E8try_from0B8_
Unexecuted instantiation: _RNCNvXs34_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB8_8Uint3072E8try_from0B8_
Unexecuted instantiation: _RNCNvXsC_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB7_7Uint192E8try_from0B7_
746
0
                    Err($crate::uint::TryFromIntError)
747
                } else {
748
0
                    Ok(value.as_u128())
749
                }
750
0
            }
Unexecuted instantiation: _RNvXsv_Cs3Hi7WNjIpVC_4u192oINtNtCsloNou9alJSK_4core7convert7TryFromNtB5_7Uint192E8try_from
Unexecuted instantiation: _RNvXs1s_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_7Uint256E8try_from
Unexecuted instantiation: _RNvXs2g_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_7Uint320E8try_from
Unexecuted instantiation: _RNvXs34_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_8Uint3072E8try_from
Unexecuted instantiation: _RNvXsC_Cs8KLYHAG7u19_10kaspa_mathoINtNtCsloNou9alJSK_4core7convert7TryFromNtB5_7Uint192E8try_from
751
        }
752
753
        impl core::fmt::LowerHex for $name {
754
            #[inline]
755
0
            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
756
0
                let mut hex = [0u8; Self::BYTES * 2];
757
0
                let bytes = self.to_be_bytes();
758
0
                $crate::uint::faster_hex::hex_encode(&bytes, &mut hex).expect("The output is exactly twice the size of the input");
759
0
                let first_non_zero = hex.iter().position(|&x| x != b'0').unwrap_or(hex.len() - 1);
Unexecuted instantiation: _RNCNvXsw_Cs3Hi7WNjIpVC_4u192NtB7_7Uint192NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt0B7_
Unexecuted instantiation: _RNCNvXs1t_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint256NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt0B8_
Unexecuted instantiation: _RNCNvXs2h_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint320NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt0B8_
Unexecuted instantiation: _RNCNvXs35_Cs8KLYHAG7u19_10kaspa_mathNtB8_8Uint3072NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt0B8_
Unexecuted instantiation: _RNCNvXsD_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint192NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt0B7_
760
                // The string is hex encoded so must be valid UTF8.
761
0
                let str = unsafe { core::str::from_utf8_unchecked(&hex[first_non_zero..]) };
762
0
                f.pad_integral(true, "0x", str)
763
0
            }
Unexecuted instantiation: _RNvXsw_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt
Unexecuted instantiation: _RNvXs1t_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt
Unexecuted instantiation: _RNvXs2h_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt
Unexecuted instantiation: _RNvXs35_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt
Unexecuted instantiation: _RNvXsD_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt8LowerHex3fmt
764
        }
765
766
        // Based on https://github.com/rust-lang/rust/blob/2e44c17c12cec45b6a682b1e53a04ac5b5fcc9d2/library/core/src/fmt/num.rs#L209
767
        impl core::fmt::Display for $name {
768
            #[inline]
769
0
            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
770
                // 2 digit decimal look up table
771
                static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
772
            2021222324252627282930313233343536373839\
773
            4041424344454647484950515253545556575859\
774
            6061626364656667686970717273747576777879\
775
            8081828384858687888990919293949596979899";
776
777
0
                let mut buf = [0u8; $name::LIMBS * 20]; // 2**64-1 takes 20 digits to represent.
778
0
                let mut n = *self;
779
0
                let mut curr = buf.len();
780
781
                // eagerly decode 4 characters at a time
782
                const STEP: u64 = 10_000;
783
0
                while n >= STEP {
784
0
                    let rem: u64;
785
0
                    (n, rem) = n.div_rem_u64(STEP);
786
0
                    let rem = rem as usize;
787
0
                    let d1 = (rem / 100) << 1;
788
0
                    let d2 = (rem % 100) << 1;
789
0
                    curr -= 4;
790
0
791
0
                    buf[curr] = DEC_DIGITS_LUT[d1];
792
0
                    buf[curr + 1] = DEC_DIGITS_LUT[d1 + 1];
793
0
                    buf[curr + 2] = DEC_DIGITS_LUT[d2];
794
0
                    buf[curr + 3] = DEC_DIGITS_LUT[d2 + 1];
795
0
                }
796
                // if we reach here numbers are <= 9999, so at most 4 chars long
797
0
                let mut n = n.as_u64() as usize; // possibly reduce 64bit math
798
799
                // decode 2 more chars, if > 2 chars
800
0
                if n >= 100 {
801
0
                    let d1 = (n % 100) << 1;
802
0
                    n /= 100;
803
0
                    curr -= 2;
804
0
                    buf[curr] = DEC_DIGITS_LUT[d1 as usize];
805
0
                    buf[curr + 1] = DEC_DIGITS_LUT[d1 + 1 as usize];
806
0
                }
807
808
                // decode last 1 or 2 chars
809
0
                if n < 10 {
810
0
                    curr -= 1;
811
0
                    buf[curr] = (n as u8) + b'0'
812
0
                } else {
813
0
                    let d1 = n << 1;
814
0
                    curr -= 2;
815
0
                    buf[curr] = DEC_DIGITS_LUT[d1];
816
0
                    buf[curr + 1] = DEC_DIGITS_LUT[d1 + 1];
817
0
                }
818
819
                // SAFETY: everything up to `curr` is valid UTF8 because `DEC_DIGITS_LUT` is.
820
0
                let buf_str = unsafe { std::str::from_utf8_unchecked(&buf[curr..]) };
821
0
                f.pad_integral(true, "", buf_str)
822
0
            }
Unexecuted instantiation: _RNvXsx_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs1u_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs2i_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXs36_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core3fmt7Display3fmt
Unexecuted instantiation: _RNvXsE_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt7Display3fmt
823
        }
824
825
        impl core::fmt::Binary for $name {
826
            #[inline]
827
0
            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
828
                const BIN_LEN: usize = $name::BITS as usize;
829
0
                let mut buf = [0u8; BIN_LEN];
830
0
                let mut first_one = BIN_LEN - 1;
831
0
                for (index, (bit, char)) in self.iter_be_bits().zip(buf.iter_mut()).enumerate() {
832
0
                    *char = bit as u8 + b'0';
833
0
                    if first_one == BIN_LEN - 1 && bit {
834
0
                        first_one = index;
835
0
                    }
836
                }
837
                // We only wrote '0' and '1' so this is always valid UTF-8
838
0
                let buf_str = unsafe { std::str::from_utf8_unchecked(&buf[first_one..]) };
839
0
                f.pad_integral(true, "0b", buf_str)
840
0
            }
Unexecuted instantiation: _RNvXsy_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt6Binary3fmt
Unexecuted instantiation: _RNvXs1v_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256NtNtCsloNou9alJSK_4core3fmt6Binary3fmt
Unexecuted instantiation: _RNvXs2j_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320NtNtCsloNou9alJSK_4core3fmt6Binary3fmt
Unexecuted instantiation: _RNvXs37_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072NtNtCsloNou9alJSK_4core3fmt6Binary3fmt
Unexecuted instantiation: _RNvXsF_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192NtNtCsloNou9alJSK_4core3fmt6Binary3fmt
841
        }
842
843
        // We can't derive because the array might be bigger than 32,
844
        // so we just implement it the same as arrays.
845
        impl $crate::uint::serde::Serialize for $name {
846
            #[inline]
847
0
            fn serialize<S: $crate::uint::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
848
0
                if serializer.is_human_readable() {
849
0
                    let mut hex = [0u8; Self::BYTES * 2];
850
0
                    let bytes = self.to_be_bytes();
851
0
                    $crate::uint::faster_hex::hex_encode(&bytes, &mut hex).expect("The output is exactly twice the size of the input");
852
0
                    let hex_str = unsafe { std::str::from_utf8_unchecked(&hex) };
853
0
                    serializer.serialize_str(hex_str)
854
                } else {
855
                    use $crate::uint::serde::ser::SerializeTuple;
856
0
                    let mut seq = serializer.serialize_tuple(Self::LIMBS)?;
857
0
                    for limb in &self.0 {
858
0
                        seq.serialize_element(limb)?;
859
                    }
860
0
                    seq.end()
861
                }
862
0
            }
Unexecuted instantiation: _RINvXsz_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core3ser9Serialize9serializepEB6_
Unexecuted instantiation: _RINvXs1w_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core3ser9Serialize9serializepEB7_
Unexecuted instantiation: _RINvXs2k_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core3ser9Serialize9serializepEB7_
Unexecuted instantiation: _RINvXs38_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core3ser9Serialize9serializepEB7_
Unexecuted instantiation: _RINvXsG_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core3ser9Serialize9serializepEB6_
863
        }
864
865
        impl<'de> $crate::uint::serde::Deserialize<'de> for $name {
866
            #[inline]
867
0
            fn deserialize<D: $crate::uint::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
868
0
                if deserializer.is_human_readable() {
869
0
                    let hex = <std::string::String as $crate::uint::serde::Deserialize>::deserialize(deserializer)?;
870
0
                    Ok(Self::from_hex(&hex).map_err($crate::uint::serde::de::Error::custom)?)
871
                } else {
872
                    use core::{fmt, marker::PhantomData};
873
                    use $crate::uint::serde::de::{Error, SeqAccess, Visitor};
874
                    struct EmptyVisitor(PhantomData<$name>);
875
                    impl<'de> Visitor<'de> for EmptyVisitor {
876
                        type Value = $name;
877
                        #[inline]
878
879
0
                        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
880
0
                            formatter.write_str(concat!("an integer with ", $n_words, " limbs"))
881
0
                        }
Unexecuted instantiation: _RNvXNvXsA_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB2_12EmptyVisitorNtBG_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB2_12EmptyVisitorNtBO_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB2_12EmptyVisitorNtBO_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB2_12EmptyVisitorNtBP_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB2_12EmptyVisitorNtBN_7Visitor9expecting
882
883
                        #[inline]
884
0
                        fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
885
0
                            let mut ret = $name::ZERO;
886
0
                            for (i, limb) in ret.0.iter_mut().enumerate() {
887
0
                                *limb = seq.next_element()?.ok_or_else(|| Error::invalid_length(i, &self))?;
Unexecuted instantiation: _RNCINvXNvXsA_Cs3Hi7WNjIpVC_4u192NtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB5_12EmptyVisitorNtBJ_7Visitor9visit_seqpE0Bb_
Unexecuted instantiation: _RNCINvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB5_12EmptyVisitorNtBR_7Visitor9visit_seqpE0Bc_
Unexecuted instantiation: _RNCINvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB5_12EmptyVisitorNtBR_7Visitor9visit_seqpE0Bc_
Unexecuted instantiation: _RNCINvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBc_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB5_12EmptyVisitorNtBS_7Visitor9visit_seqpE0Bc_
Unexecuted instantiation: _RNCINvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB5_12EmptyVisitorNtBQ_7Visitor9visit_seqpE0Bb_
888
                            }
889
0
                            Ok(ret)
890
0
                        }
Unexecuted instantiation: _RINvXNvXsA_Cs3Hi7WNjIpVC_4u192NtB9_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB3_12EmptyVisitorNtBH_7Visitor9visit_seqpEB9_
Unexecuted instantiation: _RINvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBa_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB3_12EmptyVisitorNtBP_7Visitor9visit_seqpEBa_
Unexecuted instantiation: _RINvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBa_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB3_12EmptyVisitorNtBP_7Visitor9visit_seqpEBa_
Unexecuted instantiation: _RINvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBa_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB3_12EmptyVisitorNtBQ_7Visitor9visit_seqpEBa_
Unexecuted instantiation: _RINvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializeNtB3_12EmptyVisitorNtBO_7Visitor9visit_seqpEB9_
891
                    }
892
0
                    deserializer.deserialize_tuple(Self::LIMBS, EmptyVisitor(PhantomData))
893
                }
894
0
            }
Unexecuted instantiation: _RINvXsA_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializepEB6_
Unexecuted instantiation: _RINvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializepEB7_
Unexecuted instantiation: _RINvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializepEB7_
Unexecuted instantiation: _RINvXs39_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializepEB7_
Unexecuted instantiation: _RINvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize11deserializepEB6_
895
896
            #[inline]
897
0
            fn deserialize_in_place<D: $crate::uint::serde::Deserializer<'de>>(
898
0
                deserializer: D,
899
0
                place: &mut Self,
900
0
            ) -> Result<(), D::Error> {
901
0
                if deserializer.is_human_readable() {
902
903
                    use core::fmt;
904
                    use $crate::uint::serde::de::{Error, Visitor};
905
                    struct InPlaceVisitor<'a>(&'a mut $name);
906
907
                    impl<'de, 'a> Visitor<'de> for InPlaceVisitor<'a> {
908
                        type Value = ();
909
                        #[inline]
910
0
                        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
911
0
                            formatter.write_str("a hex string")
912
0
                        }
Unexecuted instantiation: _RNvXNvXsA_Cs3Hi7WNjIpVC_4u192NtB8_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB2_14InPlaceVisitorNtBG_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB2_14InPlaceVisitorNtBO_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB2_14InPlaceVisitorNtBO_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtB9_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB2_14InPlaceVisitorNtBP_7Visitor9expecting
Unexecuted instantiation: _RNvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB8_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB2_14InPlaceVisitorNtBN_7Visitor9expecting
913
                        #[inline]
914
0
                        fn visit_str<E>(self, hex: &str) -> Result<Self::Value, E>
915
0
                        where
916
0
                            E: Error,
917
                        {
918
0
                            if hex.len() > $name::BYTES * 2 {
919
0
                                return Err($crate::uint::serde::de::Error::custom("invalid hex string length"));
920
0
                            }
921
0
                            let mut bytes = [0u8; $name::BYTES];
922
0
                            let mut input = [b'0'; $name::BYTES * 2];
923
0
                            let start = input.len() - hex.len();
924
0
                            input[start..].copy_from_slice(hex.as_bytes());
925
0
                            $crate::uint::faster_hex::hex_decode(&input, &mut bytes).map_err(Error::custom)?;
926
927
0
                            self.0.0.iter_mut()
928
0
                                .rev()
929
0
                                .zip(bytes.chunks_exact(8))
930
0
                                .for_each(|(word, bytes)| *word = u64::from_be_bytes(bytes.try_into().unwrap()));
Unexecuted instantiation: _RNCINvXNvXsA_Cs3Hi7WNjIpVC_4u192NtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_14InPlaceVisitorNtBJ_7Visitor9visit_strpE0Bb_
Unexecuted instantiation: _RNCINvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_14InPlaceVisitorNtBR_7Visitor9visit_strpE0Bc_
Unexecuted instantiation: _RNCINvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_14InPlaceVisitorNtBR_7Visitor9visit_strpE0Bc_
Unexecuted instantiation: _RNCINvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBc_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_14InPlaceVisitorNtBS_7Visitor9visit_strpE0Bc_
Unexecuted instantiation: _RNCINvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_14InPlaceVisitorNtBQ_7Visitor9visit_strpE0Bb_
931
932
0
                            Ok(())
933
0
                        }
Unexecuted instantiation: _RINvXNvXsA_Cs3Hi7WNjIpVC_4u192NtB9_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB3_14InPlaceVisitorNtBH_7Visitor9visit_strpEB9_
Unexecuted instantiation: _RINvXNvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBa_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB3_14InPlaceVisitorNtBP_7Visitor9visit_strpEBa_
Unexecuted instantiation: _RINvXNvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBa_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB3_14InPlaceVisitorNtBP_7Visitor9visit_strpEBa_
Unexecuted instantiation: _RINvXNvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBa_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB3_14InPlaceVisitorNtBQ_7Visitor9visit_strpEBa_
Unexecuted instantiation: _RINvXNvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB9_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB3_14InPlaceVisitorNtBO_7Visitor9visit_strpEB9_
934
                    }
935
0
                    deserializer.deserialize_str(InPlaceVisitor(place))
936
937
                } else {
938
                    use core::fmt;
939
                    use $crate::uint::serde::de::{Error, SeqAccess, Visitor};
940
                    struct InPlaceVisitor<'a>(&'a mut $name);
941
942
                    impl<'de, 'a> Visitor<'de> for InPlaceVisitor<'a> {
943
                        type Value = ();
944
                        #[inline]
945
0
                        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
946
0
                            formatter.write_str(concat!("an integer with ", $n_words, " limbs"))
947
0
                        }
Unexecuted instantiation: _RNvXs_NvXsA_Cs3Hi7WNjIpVC_4u192NtBa_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB4_s_14InPlaceVisitorNtBI_7Visitor9expecting
Unexecuted instantiation: _RNvXs_NvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBb_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB4_s_14InPlaceVisitorNtBQ_7Visitor9expecting
Unexecuted instantiation: _RNvXs_NvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBb_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB4_s_14InPlaceVisitorNtBQ_7Visitor9expecting
Unexecuted instantiation: _RNvXs_NvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBb_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB4_s_14InPlaceVisitorNtBR_7Visitor9expecting
Unexecuted instantiation: _RNvXs_NvXsH_Cs8KLYHAG7u19_10kaspa_mathNtBa_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB4_s_14InPlaceVisitorNtBP_7Visitor9expecting
948
                        #[inline]
949
0
                        fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
950
0
                            for (idx, dest) in self.0 .0[..].iter_mut().enumerate() {
951
0
                                match seq.next_element()? {
952
0
                                    Some(elem) => *dest = elem,
953
                                    None => {
954
0
                                        return Err(Error::invalid_length(idx, &self));
955
                                    }
956
                                }
957
                            }
958
0
                            Ok(())
959
0
                        }
Unexecuted instantiation: _RINvXs_NvXsA_Cs3Hi7WNjIpVC_4u192NtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_s_14InPlaceVisitorNtBJ_7Visitor9visit_seqpEBb_
Unexecuted instantiation: _RINvXs_NvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_s_14InPlaceVisitorNtBR_7Visitor9visit_seqpEBc_
Unexecuted instantiation: _RINvXs_NvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtBc_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_s_14InPlaceVisitorNtBR_7Visitor9visit_seqpEBc_
Unexecuted instantiation: _RINvXs_NvXs39_Cs8KLYHAG7u19_10kaspa_mathNtBc_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_s_14InPlaceVisitorNtBS_7Visitor9visit_seqpEBc_
Unexecuted instantiation: _RINvXs_NvXsH_Cs8KLYHAG7u19_10kaspa_mathNtBb_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placeNtB5_s_14InPlaceVisitorNtBQ_7Visitor9visit_seqpEBb_
960
                    }
961
0
                    deserializer.deserialize_tuple(Self::LIMBS, InPlaceVisitor(place))
962
                }
963
0
            }
Unexecuted instantiation: _RINvXsA_Cs3Hi7WNjIpVC_4u192NtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placepEB6_
Unexecuted instantiation: _RINvXs1x_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint256NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placepEB7_
Unexecuted instantiation: _RINvXs2l_Cs8KLYHAG7u19_10kaspa_mathNtB7_7Uint320NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placepEB7_
Unexecuted instantiation: _RINvXs39_Cs8KLYHAG7u19_10kaspa_mathNtB7_8Uint3072NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placepEB7_
Unexecuted instantiation: _RINvXsH_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint192NtNtCs3hf9a0Cf7S3_10serde_core2de11Deserialize20deserialize_in_placepEB6_
964
965
        }
966
967
        impl TryFrom<&$name> for $crate::uint::js_sys::BigInt {
968
            type Error = $crate::Error;
969
            #[inline]
970
0
            fn try_from(value: &$name) -> Result<$crate::uint::js_sys::BigInt, Self::Error> {
971
                use $crate::wasm::*;
972
0
                BigInt::new(&JsValue::from_str(&format!("0x{value:x}"))).map_err(|err|$crate::Error::JsSys(Sendable(err)))
Unexecuted instantiation: _RNCNvXsB_Cs3Hi7WNjIpVC_4u192NtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB7_7Uint192E8try_from0B7_
Unexecuted instantiation: _RNCNvXs1y_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB8_7Uint256E8try_from0B8_
Unexecuted instantiation: _RNCNvXs2m_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB8_7Uint320E8try_from0B8_
Unexecuted instantiation: _RNCNvXs3a_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB8_8Uint3072E8try_from0B8_
Unexecuted instantiation: _RNCNvXsI_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB7_7Uint192E8try_from0B7_
973
0
            }
Unexecuted instantiation: _RNvXsB_Cs3Hi7WNjIpVC_4u192NtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB5_7Uint192E8try_from
Unexecuted instantiation: _RNvXs1y_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB6_7Uint256E8try_from
Unexecuted instantiation: _RNvXs2m_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB6_7Uint320E8try_from
Unexecuted instantiation: _RNvXs3a_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB6_8Uint3072E8try_from
Unexecuted instantiation: _RNvXsI_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromRNtB5_7Uint192E8try_from
974
        }
975
976
        impl TryFrom<$name> for $crate::uint::js_sys::BigInt {
977
            type Error = $crate::Error;
978
            #[inline]
979
0
            fn try_from(value: $name) -> Result<$crate::uint::js_sys::BigInt, Self::Error> {
980
                use $crate::wasm::*;
981
0
                BigInt::try_from(&value)
982
0
            }
Unexecuted instantiation: _RNvXsC_Cs3Hi7WNjIpVC_4u192NtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromNtB5_7Uint192E8try_from
Unexecuted instantiation: _RNvXs1z_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_7Uint256E8try_from
Unexecuted instantiation: _RNvXs2n_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_7Uint320E8try_from
Unexecuted instantiation: _RNvXs3b_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromNtB6_8Uint3072E8try_from
Unexecuted instantiation: _RNvXsJ_Cs8KLYHAG7u19_10kaspa_mathNtCs2VzSvXtaRFf_6js_sys6BigIntINtNtCsloNou9alJSK_4core7convert7TryFromNtB5_7Uint192E8try_from
983
        }
984
985
        impl TryFrom<$crate::uint::wasm_bindgen::JsValue> for $name {
986
            type Error = $crate::Error;
987
0
            fn try_from(js_value: $crate::uint::wasm_bindgen::JsValue) -> Result<Self, Self::Error> {
988
                use $crate::wasm::*;
989
990
0
                if js_value.is_string() || js_value.is_array() {
991
0
                    let bytes = js_value.try_as_vec_u8()?;
992
0
                    Ok(Self::from_be_bytes_var(&bytes)?)
993
0
                } else if js_value.is_bigint() {
994
0
                    let v: &BigInt = js_value.dyn_ref().unwrap();
995
0
                    let hex = String::from(v.to_string(16)?);
996
0
                    Ok(Self::from_hex(hex.as_str())?)
997
                } else {
998
0
                    return Err(Self::Error::NotCompatible);
999
                }
1000
0
            }
Unexecuted instantiation: _RNvXsD_Cs3Hi7WNjIpVC_4u192NtB5_7Uint192INtNtCsloNou9alJSK_4core7convert7TryFromNtCseeN0L2AkAf8_12wasm_bindgen7JsValueE8try_from
Unexecuted instantiation: _RNvXs1A_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint256INtNtCsloNou9alJSK_4core7convert7TryFromNtCseeN0L2AkAf8_12wasm_bindgen7JsValueE8try_from
Unexecuted instantiation: _RNvXs2o_Cs8KLYHAG7u19_10kaspa_mathNtB6_7Uint320INtNtCsloNou9alJSK_4core7convert7TryFromNtCseeN0L2AkAf8_12wasm_bindgen7JsValueE8try_from
Unexecuted instantiation: _RNvXs3c_Cs8KLYHAG7u19_10kaspa_mathNtB6_8Uint3072INtNtCsloNou9alJSK_4core7convert7TryFromNtCseeN0L2AkAf8_12wasm_bindgen7JsValueE8try_from
Unexecuted instantiation: _RNvXsK_Cs8KLYHAG7u19_10kaspa_mathNtB5_7Uint192INtNtCsloNou9alJSK_4core7convert7TryFromNtCseeN0L2AkAf8_12wasm_bindgen7JsValueE8try_from
1001
        }
1002
1003
    };
1004
}
1005
1006
/// The error type returned when a checked integral type conversion fails.
1007
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1008
pub struct TryFromIntError;
1009
1010
impl std::error::Error for TryFromIntError {}
1011
1012
impl core::fmt::Display for TryFromIntError {
1013
0
    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1014
0
        "out of range integral type conversion attempted".fmt(fmt)
1015
0
    }
1016
}
1017
1018
impl From<core::convert::Infallible> for TryFromIntError {
1019
    fn from(x: core::convert::Infallible) -> TryFromIntError {
1020
        match x {}
1021
    }
1022
}
1023
1024
/// The error type returned when a slice conversion fails.
1025
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1026
pub struct TryFromSliceError;
1027
1028
impl std::error::Error for TryFromSliceError {}
1029
1030
impl core::fmt::Display for TryFromSliceError {
1031
0
    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1032
0
        "conversion attempted from a slice too large".fmt(fmt)
1033
0
    }
1034
}
1035
1036
impl From<core::convert::Infallible> for TryFromSliceError {
1037
    fn from(x: core::convert::Infallible) -> TryFromSliceError {
1038
        match x {}
1039
    }
1040
}
1041
1042
#[cfg(test)]
1043
mod tests {
1044
    use rand_chacha::{
1045
        ChaCha8Rng,
1046
        rand_core::{RngCore, SeedableRng},
1047
    };
1048
    use std::fmt::Write;
1049
    construct_uint!(Uint128, 2);
1050
1051
    #[test]
1052
    fn test_u128() {
1053
        use core::fmt::Arguments;
1054
        let mut fmt_buf = String::with_capacity(256);
1055
        let mut fmt_buf2 = String::with_capacity(256);
1056
        let mut assert_equal_args = |arg1: Arguments, arg2: Arguments| {
1057
            fmt_buf.clear();
1058
            fmt_buf2.clear();
1059
            fmt_buf.write_fmt(arg1).unwrap();
1060
            fmt_buf2.write_fmt(arg2).unwrap();
1061
            assert_eq!(fmt_buf, fmt_buf2);
1062
        };
1063
        let mut assert_equal = |a: Uint128, b: u128, check_fmt: bool| {
1064
            assert_eq!(a, b);
1065
            assert_eq!(a.to_le_bytes(), b.to_le_bytes());
1066
            if !check_fmt {
1067
                return;
1068
            }
1069
1070
            assert_equal_args(format_args!("{a:}"), format_args!("{b:}"));
1071
            assert_equal_args(format_args!("{a:b}"), format_args!("{b:b}")); // Test Binary
1072
            assert_equal_args(format_args!("{a:#b}"), format_args!("{b:#b}")); // Test Binary with prefix
1073
            assert_equal_args(format_args!("{a:0128b}"), format_args!("{b:0128b}")); // Test binary with length
1074
            assert_equal_args(format_args!("{a:x}"), format_args!("{b:x}")); // Test LowerHex
1075
            assert_equal_args(format_args!("{a:#x}"), format_args!("{b:#x}")); // Test LowerHex with prefix
1076
            // Test LowerHex with padding
1077
            assert_equal_args(format_args!("{a:032x}"), format_args!("{b:032x}"));
1078
        };
1079
        let mut rng = ChaCha8Rng::from_seed([0; 32]);
1080
        let mut buf = [0u8; 16];
1081
        let mut str_buf = String::with_capacity(32);
1082
        for i in 0..80_000 {
1083
            // Checking all the fmt's is quite expensive.
1084
            let check_fmt = i % 8 == 1;
1085
            rng.fill_bytes(&mut buf);
1086
            let mine = Uint128::from_le_bytes(buf);
1087
            let default = u128::from_le_bytes(buf);
1088
            rng.fill_bytes(&mut buf);
1089
            let mine2 = Uint128::from_le_bytes(buf);
1090
            let default2 = u128::from_le_bytes(buf);
1091
            assert_equal(mine, default, check_fmt);
1092
            assert_equal(mine2, default2, check_fmt);
1093
1094
            let mine = mine.overflowing_add(mine2).0.overflowing_mul(mine2).0;
1095
            let default = default.overflowing_add(default2).0.overflowing_mul(default2).0;
1096
            assert_equal(mine, default, check_fmt);
1097
            let shift = rng.next_u32() % 4096;
1098
            {
1099
                let mine_overflow_shl = mine.overflowing_shl(shift);
1100
                let default_overflow_shl = default.overflowing_shl(shift);
1101
                assert_equal(mine_overflow_shl.0, default_overflow_shl.0, check_fmt);
1102
                assert_eq!(mine_overflow_shl.1, default_overflow_shl.1);
1103
            }
1104
            {
1105
                let mine_overflow_shr = mine.overflowing_shl(shift);
1106
                let default_overflow_shr = default.overflowing_shl(shift);
1107
                assert_equal(mine_overflow_shr.0, default_overflow_shr.0, check_fmt);
1108
                assert_eq!(mine_overflow_shr.1, default_overflow_shr.1);
1109
            }
1110
            {
1111
                let mine_divrem = mine.div_rem(mine2);
1112
                let default_divrem = (default / default2, default % default2);
1113
                assert_equal(mine_divrem.0, default_divrem.0, check_fmt);
1114
                assert_equal(mine_divrem.1, default_divrem.1, check_fmt);
1115
            }
1116
            // Test conversion to f64
1117
            {
1118
                let mine_f64 = mine.as_f64();
1119
                let default_f64 = default as f64;
1120
                assert_eq!(mine_f64, default_f64);
1121
            }
1122
            // Test fast u64 division.
1123
            {
1124
                let rand_u64 = rng.next_u64();
1125
                let mine_divrem = mine.div_rem_u64(rand_u64);
1126
                let default_divrem = (default / u128::from(rand_u64), default % u128::from(rand_u64));
1127
                assert_equal(mine_divrem.0, default_divrem.0, check_fmt);
1128
                assert_eq!(mine_divrem.1, u64::try_from(default_divrem.1).unwrap());
1129
            }
1130
            // Test fast u64 multiplication
1131
            {
1132
                let rand_u64 = rng.next_u64();
1133
                let mine_mult = mine.overflowing_mul_u64(rand_u64);
1134
                let default_mult = default.overflowing_mul(rand_u64 as u128);
1135
                assert_equal(mine_mult.0, default_mult.0, check_fmt);
1136
                assert_eq!(mine_mult.1, default_mult.1);
1137
            }
1138
            // Test fast u64 addition
1139
            {
1140
                let rand_u64 = rng.next_u64();
1141
                let mine_add = mine.overflowing_add_u64(rand_u64);
1142
                let default_add = default.overflowing_add(rand_u64 as u128);
1143
                assert_equal(mine_add.0, default_add.0, check_fmt);
1144
                assert_eq!(mine_add.1, default_add.1);
1145
            }
1146
            // Roundtrip Little-Endian bytes conversion
1147
            {
1148
                let mine_le = mine.to_le_bytes();
1149
                let default_le = default.to_le_bytes();
1150
                assert_eq!(mine_le, default_le);
1151
                assert_eq!(mine, Uint128::from_le_bytes(mine_le));
1152
            }
1153
            // Roundtrip Big-Endian bytes conversion
1154
            {
1155
                let mine_le = mine.to_be_bytes();
1156
                let default_le = default.to_be_bytes();
1157
                assert_eq!(mine_le, default_le);
1158
                assert_eq!(mine, Uint128::from_be_bytes(mine_le));
1159
            }
1160
            // Roundtrip hex
1161
            if check_fmt {
1162
                str_buf.clear();
1163
                str_buf.write_fmt(format_args!("{mine:032x}")).unwrap();
1164
                assert_eq!(mine, Uint128::from_hex(&str_buf).unwrap());
1165
            }
1166
        }
1167
    }
1168
1169
    #[test]
1170
    fn test_saturating_ops() {
1171
        let u1 = Uint128::from_u128(u128::MAX);
1172
        let u2 = Uint128::from_u64(u64::MAX);
1173
        // Sub
1174
        assert_eq!(u1.saturating_sub(u2), Uint128::from_u128(u128::MAX - u64::MAX as u128));
1175
        assert_eq!(u1.saturating_sub(u2).as_u128(), u128::MAX - u64::MAX as u128);
1176
        assert_eq!(u2.saturating_sub(u1), Uint128::ZERO);
1177
        // Add
1178
        assert_eq!(u1.saturating_add(Uint128::from_u64(1)), Uint128::MAX);
1179
        assert_eq!(u2.saturating_add(Uint128::from_u64(1)), Uint128::from_u128(u64::MAX as u128 + 1));
1180
    }
1181
1182
    // `test_mod_inv` is commented out: it exercised the generic `mod_inverse` (Uint128), which was
1183
    // removed along with the malachite-backed implementation. The only production inverse is the
1184
    // 3072-bit MuHash case, now covered by the `lehmer.rs` unit tests (bit-for-bit vs malachite +
1185
    // `v * inv == 1` self-check) and the `math/fuzz` `u3072` target. Kept here for history.
1186
    /*
1187
    #[test]
1188
    fn test_mod_inv() {
1189
        use core::cmp::Ordering;
1190
        let mut rng = ChaCha8Rng::from_seed([0; 32]);
1191
        let mut buf = [0u8; 16];
1192
        for _ in 0..50_000 {
1193
            rng.fill_bytes(&mut buf);
1194
            let uint1 = Uint128::from_le_bytes(buf);
1195
            rng.fill_bytes(&mut buf);
1196
            let uint2 = Uint128::from_le_bytes(buf);
1197
            let (bigger, smaller) = match uint1.cmp(&uint2) {
1198
                Ordering::Greater => (uint1, uint2),
1199
                Ordering::Less => (uint2, uint1),
1200
                Ordering::Equal => continue,
1201
            };
1202
            let inv = smaller.mod_inverse(bigger);
1203
            if let Some(inv) = inv {
1204
                assert_eq!(prod_bin(inv, smaller, bigger), 1u64);
1205
            }
1206
        }
1207
1208
        fn sum(x: Uint128, y: Uint128, m: Uint128) -> Uint128 {
1209
            let res = x.overflowing_add(y).0;
1210
            if res < x || res >= m { res.overflowing_sub(m).0 } else { res }
1211
        }
1212
        fn prod_bin(x: Uint128, y: Uint128, m: Uint128) -> Uint128 {
1213
            if y == 1u64 {
1214
                return x;
1215
            } else if y == 0u64 {
1216
                return Uint128::ZERO;
1217
            }
1218
            let mut res = prod_bin(x, y >> 1, m);
1219
            res = sum(res, res, m);
1220
            if (y.as_u64() & 1) == 1 {
1221
                res = sum(res, x, m);
1222
            }
1223
            res
1224
        }
1225
    }
1226
    */
1227
}
/root/kaspa/kaspa-fuzz/rusty-kaspa/math/src/int.rs
Line
Count
Source
1
use core::fmt::{self, Display};
2
use core::ops::{Add, Div, Mul, Sub};
3
4
#[derive(Copy, Clone, Debug)]
5
pub struct SignedInteger<T> {
6
    abs: T,
7
    negative: bool,
8
}
9
10
impl<T> From<T> for SignedInteger<T> {
11
    #[inline]
12
0
    fn from(u: T) -> Self {
13
0
        Self { abs: u, negative: false }
14
0
    }
15
}
16
impl<T: From<u64>> SignedInteger<T> {
17
    #[inline]
18
0
    pub fn positive_u64(u: u64) -> Self {
19
0
        Self { abs: T::from(u), negative: false }
20
0
    }
21
}
22
23
impl<T: Display> Display for SignedInteger<T> {
24
    #[inline]
25
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26
0
        if self.negative {
27
0
            write!(f, "-")?;
28
0
        }
29
0
        write!(f, "{}", self.abs)
30
0
    }
31
}
32
33
impl<T: Copy> SignedInteger<T> {
34
    #[inline]
35
0
    pub const fn abs(&self) -> T {
36
0
        self.abs
37
0
    }
38
39
    #[inline]
40
0
    pub const fn negative(&self) -> bool {
41
0
        self.negative
42
0
    }
43
}
44
45
impl<T: Sub<Output = T> + Add<Output = T> + Ord> Sub for SignedInteger<T> {
46
    type Output = Self;
47
    #[inline]
48
    #[track_caller]
49
0
    fn sub(self, other: Self) -> Self::Output {
50
0
        match (self.negative, other.negative) {
51
            (false, false) | (true, true) => {
52
0
                if self.abs < other.abs {
53
0
                    Self { negative: !self.negative, abs: other.abs - self.abs }
54
                } else {
55
0
                    Self { negative: self.negative, abs: self.abs - other.abs }
56
                }
57
            }
58
0
            (false, true) | (true, false) => Self { negative: self.negative, abs: self.abs + other.abs },
59
        }
60
0
    }
61
}
62
63
impl<T: Mul<Output = T>> Mul for SignedInteger<T> {
64
    type Output = Self;
65
    #[inline]
66
    #[track_caller]
67
0
    fn mul(self, rhs: Self) -> Self::Output {
68
0
        Self { negative: self.negative ^ rhs.negative, abs: self.abs * rhs.abs }
69
0
    }
70
}
71
72
impl<T: Div<Output = T>> Div for SignedInteger<T> {
73
    type Output = Self;
74
    #[inline]
75
    #[track_caller]
76
0
    fn div(self, rhs: Self) -> Self::Output {
77
0
        Self { negative: self.negative ^ rhs.negative, abs: self.abs / rhs.abs }
78
0
    }
79
}
80
81
impl<T: PartialEq + PartialEq<u64>> PartialEq for SignedInteger<T> {
82
0
    fn eq(&self, other: &Self) -> bool {
83
0
        if self.abs == 0 && other.abs == 0 {
84
            // neg/pos zeros are considered equal
85
0
            return true;
86
0
        }
87
0
        self.negative == other.negative && self.abs == other.abs
88
0
    }
89
}
90
91
impl<T: PartialEq + PartialEq<u64>> Eq for SignedInteger<T> {}
92
93
impl<T: PartialOrd + PartialEq<u64>> PartialOrd for SignedInteger<T> {
94
0
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
95
0
        if self.abs == 0 && other.abs == 0 {
96
            // neg/pos zeros are considered equal
97
0
            return Some(std::cmp::Ordering::Equal);
98
0
        }
99
0
        match (self.negative, other.negative) {
100
0
            (false, false) => self.abs.partial_cmp(&other.abs),
101
0
            (true, true) => other.abs.partial_cmp(&self.abs),
102
0
            (true, false) => Some(std::cmp::Ordering::Less),
103
0
            (false, true) => Some(std::cmp::Ordering::Greater),
104
        }
105
0
    }
106
}
107
108
#[cfg(test)]
109
mod tests {
110
    use crate::{Uint192, int::SignedInteger};
111
112
    fn from_u64(val: u64) -> SignedInteger<Uint192> {
113
        SignedInteger::from(Uint192::from_u64(val))
114
    }
115
116
    #[test]
117
    fn test_partial_eq() {
118
        assert_eq!(from_u64(0), SignedInteger::from(Uint192::ZERO));
119
        assert_eq!(from_u64(0), from_u64(10) - from_u64(10));
120
        assert_eq!(from_u64(0), from_u64(10) - from_u64(20) - from_u64(10) * (from_u64(0) - from_u64(1))); // 0 == 10 - 20 -(-10)
121
        assert_eq!(from_u64(0) - from_u64(1000), from_u64(0) - from_u64(1000)); // -1000 = -1000
122
        assert_eq!(from_u64(1000), from_u64(1000));
123
    }
124
125
    #[test]
126
    fn test_partial_cmp() {
127
        // Test cases related to 0 and equality
128
        assert!(from_u64(0) >= from_u64(10) - from_u64(20) - from_u64(10) * (from_u64(0) - from_u64(1))); // pos 0 >= neg 0
129
        assert!(from_u64(0) <= from_u64(10) - from_u64(20) - from_u64(10) * (from_u64(0) - from_u64(1))); // pos 0 <= neg 0
130
131
        // Test all possible neg/pos combinations
132
        assert!(from_u64(100) > from_u64(0) - from_u64(1000)); // pos > neg
133
        assert!(from_u64(0) - from_u64(100) < from_u64(10)); // neg < pos
134
        assert!(from_u64(0) - from_u64(1000) < from_u64(0) - from_u64(100)); // -1000 < -100
135
        assert!(from_u64(0) - from_u64(1000) <= from_u64(0) - from_u64(1000)); // -1000 <= -1000
136
        assert!(from_u64(0) - from_u64(1000) >= from_u64(0) - from_u64(1000)); // -1000 >= -1000
137
        assert!(from_u64(1000) > from_u64(100));
138
        assert!(from_u64(100) < from_u64(1000));
139
        assert!(from_u64(1000) >= from_u64(1000));
140
        assert!(from_u64(100) <= from_u64(100));
141
    }
142
}
/root/kaspa/kaspa-fuzz/rusty-kaspa/math/src/lib.rs
Line
Count
Source
1
use borsh::{BorshDeserialize, BorshSerialize};
2
use wasm_bindgen::JsValue;
3
use workflow_core::sendable::Sendable;
4
5
pub mod int;
6
pub mod lehmer;
7
pub mod uint;
8
pub mod wasm;
9
10
construct_uint!(Uint192, 3, BorshSerialize, BorshDeserialize);
11
construct_uint!(Uint256, 4);
12
construct_uint!(Uint320, 5);
13
construct_uint!(Uint3072, 48);
14
15
/// Returns the ceiling of the base-2 logarithm of `x`, i.e. the smallest `k` such that `2^k >= x`.
16
/// If `x` is 0, returns 0.
17
#[inline]
18
0
pub const fn ceil_log_2(x: u64) -> u64 {
19
0
    (u64::BITS - x.saturating_sub(1).leading_zeros()) as u64
20
0
}
21
22
#[derive(thiserror::Error, Debug)]
23
pub enum Error {
24
    #[error("{0:?}")]
25
    JsValue(Sendable<JsValue>),
26
27
    #[error("Invalid hex string: {0}")]
28
    Hex(#[from] faster_hex::Error),
29
30
    #[error(transparent)]
31
    TryFromSliceError(#[from] uint::TryFromSliceError),
32
    // TryFromSliceError(#[from] std::array::TryFromSliceError),
33
    #[error("Utf8 error: {0}")]
34
    Utf8(#[from] std::str::Utf8Error),
35
36
    #[error(transparent)]
37
    WorkflowWasm(#[from] workflow_wasm::error::Error),
38
39
    #[error(transparent)]
40
    SerdeWasmBindgen(#[from] serde_wasm_bindgen::Error),
41
42
    #[error("{0:?}")]
43
    JsSys(Sendable<js_sys::Error>),
44
45
    #[error("Supplied value is not compatible with this type")]
46
    NotCompatible,
47
48
    #[error("range error: {0:?}")]
49
    Range(Sendable<js_sys::RangeError>),
50
}
51
52
impl From<js_sys::Error> for Error {
53
0
    fn from(err: js_sys::Error) -> Self {
54
0
        Error::JsSys(Sendable(err))
55
0
    }
56
}
57
58
impl From<js_sys::RangeError> for Error {
59
0
    fn from(err: js_sys::RangeError) -> Self {
60
0
        Error::Range(Sendable(err))
61
0
    }
62
}
63
64
impl From<JsValue> for Error {
65
0
    fn from(err: JsValue) -> Self {
66
0
        Error::JsValue(Sendable(err))
67
0
    }
68
}
69
70
impl Uint256 {
71
    #[inline]
72
0
    pub fn from_compact_target_bits(bits: u32) -> Self {
73
        // This is a floating-point "compact" encoding originally used by
74
        // OpenSSL, which satoshi put into consensus code, so we're stuck
75
        // with it. The exponent needs to have 3 subtracted from it, hence
76
        // this goofy decoding code:
77
0
        let (mant, expt) = {
78
0
            let unshifted_expt = bits >> 24;
79
0
            if unshifted_expt <= 3 {
80
0
                ((bits & 0xFFFFFF) >> (8 * (3 - unshifted_expt)), 0)
81
            } else {
82
0
                (bits & 0xFFFFFF, 8 * ((bits >> 24) - 3))
83
            }
84
        };
85
        // The mantissa is signed but may not be negative
86
0
        if mant > 0x7FFFFF { Uint256::ZERO } else { Uint256::from_u64(u64::from(mant)) << expt }
87
0
    }
88
89
    #[inline]
90
    /// Computes the target value in float format from BigInt format.
91
0
    pub fn compact_target_bits(self) -> u32 {
92
0
        let mut size = self.bits().div_ceil(8);
93
0
        let mut compact = if size <= 3 {
94
0
            (self.as_u64() << (8 * (3 - size))) as u32
95
        } else {
96
0
            let bn = self >> (8 * (size - 3));
97
0
            bn.as_u64() as u32
98
        };
99
100
0
        if (compact & 0x00800000) != 0 {
101
0
            compact >>= 8;
102
0
            size += 1;
103
0
        }
104
0
        compact | (size << 24)
105
0
    }
106
}
107
108
impl From<Uint256> for Uint320 {
109
    #[inline]
110
0
    fn from(u: Uint256) -> Self {
111
0
        let mut result = Uint320::ZERO;
112
0
        result.0[..4].copy_from_slice(&u.0);
113
0
        result
114
0
    }
115
}
116
117
impl TryFrom<Uint320> for Uint256 {
118
    type Error = crate::uint::TryFromIntError;
119
120
    #[inline]
121
0
    fn try_from(value: Uint320) -> Result<Self, Self::Error> {
122
0
        if value.0[4] != 0 {
123
0
            Err(crate::uint::TryFromIntError)
124
        } else {
125
0
            let mut result = Uint256::ZERO;
126
0
            result.0.copy_from_slice(&value.0[..4]);
127
0
            Ok(result)
128
        }
129
0
    }
130
}
131
132
impl TryFrom<Uint256> for Uint192 {
133
    type Error = crate::uint::TryFromIntError;
134
135
    #[inline]
136
0
    fn try_from(value: Uint256) -> Result<Self, Self::Error> {
137
0
        if value.0[3] != 0 {
138
0
            Err(crate::uint::TryFromIntError)
139
        } else {
140
0
            let mut result = Uint192::ZERO;
141
0
            result.0.copy_from_slice(&value.0[..3]);
142
0
            Ok(result)
143
        }
144
0
    }
145
}
146
147
#[cfg(test)]
148
mod tests {
149
    use crate::{Uint256, Uint3072};
150
151
    #[test]
152
    fn test_overflow_bug() {
153
        let a = Uint256::from_le_bytes([
154
            255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
155
            255, 255,
156
        ]);
157
        let b = Uint256::from_le_bytes([
158
            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 71, 33, 0, 0, 0, 0, 0, 0,
159
            0, 32, 0, 0, 0,
160
        ]);
161
        let c = a.overflowing_add(b).0;
162
        let expected = [254, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 71, 33, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0];
163
        assert_eq!(c.to_le_bytes(), expected);
164
    }
165
    #[rustfmt::skip]
166
    #[test]
167
    fn div_rem_u3072_bug() {
168
        let r = Uint3072([
169
            18446744073708447899, 18446744069733351423, 18446744073709551615, 18446744073709551615,
170
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
171
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
172
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
173
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
174
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
175
            18446744073709551615, 18446744073642442751, 18446744073709551615, 18446744073709551615,
176
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
177
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
178
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
179
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
180
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
181
        ]);
182
        let newr = Uint3072([
183
            0, 3976200192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184
            0, 67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185
        ]);
186
        let expected = Uint3072([
187
            18446744073709551614, 18446744073709551615, 18446744073709551615, 18446744073709551615,
188
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
189
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
190
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
191
            18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615,
192
            18446744073709551615, 18446744073709551615, 274877906943, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
194
        ]);
195
        assert_eq!(r / newr, expected);
196
    }
197
}
198
199
#[cfg(test)]
200
mod ceil_log_2_tests {
201
    use crate::ceil_log_2;
202
203
    /// Independent reference: the smallest `k` such that `2^k >= x`. Computed in `u128` so it
204
    /// stays correct for `x` near `u64::MAX` (where the answer is 64). Returns 0 if `x` is 0.
205
    fn oracle(x: u64) -> u64 {
206
        if x == 0 {
207
            return 0;
208
        }
209
        let mut k = 0u64;
210
        while (1u128 << k) < x as u128 {
211
            k += 1;
212
        }
213
        k
214
    }
215
216
    /// A spread of inputs exercising the dense low range, every power-of-2 boundary, and the top.
217
    fn sample_inputs() -> impl Iterator<Item = u64> {
218
        let dense = 0..=8192u64;
219
        let boundaries = (0..64u32).flat_map(|k| {
220
            let p = 1u64 << k;
221
            // p-1 (clamped away from negative), p, p+1
222
            [p.saturating_sub(1), p, p + 1]
223
        });
224
        dense.chain(boundaries).chain([u64::MAX])
225
    }
226
227
    #[test]
228
    fn known_values() {
229
        for (x, expected) in [
230
            (0u64, 0u64),
231
            (1, 0),
232
            (2, 1),
233
            (3, 2),
234
            (4, 2),
235
            (5, 3),
236
            (7, 3),
237
            (8, 3),
238
            (9, 4),
239
            (1023, 10),
240
            (1024, 10),
241
            (1025, 11),
242
            (1u64 << 63, 63),
243
            ((1u64 << 63) + 1, 64),
244
            (u64::MAX, 64),
245
        ] {
246
            assert_eq!(ceil_log_2(x), expected, "ceil_log_2({x})");
247
        }
248
    }
249
250
    #[test]
251
    fn correctness_matches_oracle() {
252
        for x in sample_inputs() {
253
            assert_eq!(ceil_log_2(x), oracle(x), "x={x}");
254
        }
255
    }
256
257
    #[test]
258
    fn compatibility_matches_malachite() {
259
        // Direct equivalence with the malachite `CeilingLogBase2` this replaced. malachite is a
260
        // dev-dependency only (the oracle); permanent coverage is `correctness_matches_oracle`.
261
        // Skip x=0 since malachite panics on it; our implementation intentionally returns 0.
262
        use malachite_base::num::arithmetic::traits::CeilingLogBase2;
263
        for x in sample_inputs() {
264
            if x != 0 {
265
                assert_eq!(ceil_log_2(x), x.ceiling_log_base_2(), "x={x}");
266
            }
267
        }
268
    }
269
}