Skip to main content

a/math/numbers/
pow.rs

1//! Powers of [`Number`]s: [`Number::pow`], a power by a `u32` exponent, and [`Number::pow_mod`], a
2//! power modulo a number.
3//!
4//! A power is computed by binary exponentiation from the top bit of the exponent, a square for
5//! each bit and a product by the base for each one, on limbs of 8 bytes with the multiplication's
6//! squares and products. The zero bits at the low end of the base are taken out first and shifted
7//! back in at the end, and the result's length is bounded before it starts, so that its working
8//! memory is allocated once; a power of up to 64 bytes is computed in registers.
9//!
10//! A power modulo an odd number is computed in Montgomery's form ([`montgomery`]) by a sliding
11//! window over the exponent's bits ([`window`]); modulo a power of two by the low halves of products
12//! ([`low`]); and modulo any other even number `m = 2^k m'` as both, modulo `m'` and modulo `2^k`,
13//! put together by the Chinese remainder theorem, as GMP's `mpz_powm` does.
14
15// The kernel of Montgomery's reduction under the name `kernels`, chosen as those of the
16// multiplication are: assembly on 64-bit little-endian aarch64 where the system allows unaligned
17// accesses, and portable Rust elsewhere and under Miri.
18#[cfg(all(
19    target_arch = "aarch64",
20    target_endian = "little",
21    target_pointer_width = "64",
22    any(
23        target_vendor = "apple",
24        target_os = "linux",
25        target_os = "android",
26        target_os = "windows",
27        target_os = "freebsd",
28        target_os = "netbsd",
29        target_os = "openbsd",
30        target_os = "fuchsia"
31    ),
32    not(miri)
33))]
34#[path = "pow/aarch64.rs"]
35mod kernels;
36#[cfg(not(all(
37    target_arch = "aarch64",
38    target_endian = "little",
39    target_pointer_width = "64",
40    any(
41        target_vendor = "apple",
42        target_os = "linux",
43        target_os = "android",
44        target_os = "windows",
45        target_os = "freebsd",
46        target_os = "netbsd",
47        target_os = "openbsd",
48        target_os = "fuchsia"
49    ),
50    not(miri)
51)))]
52#[path = "pow/portable.rs"]
53mod kernels;
54pub(super) mod low;
55pub(crate) mod montgomery;
56pub(super) mod window;
57
58use super::add::{SMALL, read_small, write_small};
59use super::div::by_zero;
60use super::div::limbs::{bdiv_q, binvert_limb, rshift};
61use super::mul::limbs::{add_1, add_n, mul, mul_itch, sqr, sqr_itch, sub_1, sub_n};
62use super::mul::{Operand, Product, STACK_LIMBS, on_heap, on_stack, to_limbs};
63use super::{ByteOrder, Number};
64use core::mem::MaybeUninit;
65use core::ptr;
66use low::{Low, Low2, LowN, mullo, mullo_itch};
67use montgomery::{Mont1, Mont2, MontN, Montgomery, even, lshift, rem, rem_itch};
68use window::{power, power_in_registers, window};
69
70impl Number {
71    /// Returns `self` raised to the power `exp`, in the byte order of `self`, in the shortest form,
72    /// in one new vector of exactly its length.
73    ///
74    /// As for `i32::pow`, `x^0` is 1 for every `x`, zero included. The power is negative when
75    /// `self` is negative and `exp` odd. The result is exact, however long: a power of `n` bytes
76    /// by `exp` takes up to `n exp` bytes.
77    ///
78    /// # Panics
79    ///
80    /// When the power is too long to allocate.
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// use a::math::numbers::{ByteOrder, Number};
86    ///
87    /// // (-3)^5 = -243 = -0xF3.
88    /// let p = Number::new_from_i32(-3, ByteOrder::BigEndian).pow(5);
89    /// assert_eq!(p.value, [0xF3]);
90    /// assert!(p.is_negative());
91    ///
92    /// // 0x100^3 = 0x01_00_00_00, and anything to the power 0 is 1.
93    /// let p = Number::new_from_u32(0x100, ByteOrder::LittleEndian).pow(3);
94    /// assert_eq!(p.value, [0, 0, 0, 1]);
95    /// assert_eq!(Number::new_from_u8(0, ByteOrder::BigEndian).pow(0).value, [1]);
96    /// ```
97    pub fn pow(&self, exp: u32) -> Number {
98        let order = self.byte_order;
99        if exp == 0 {
100            return small_number(order, 1, false);
101        }
102        let negative = self.negative && exp & 1 == 1;
103        if self.value.len() <= SMALL {
104            // SAFETY: the vector holds at most 16 bytes.
105            let x = unsafe { read_small(&self.value, order) };
106            if x == 0 {
107                return small_number(order, 0, false);
108            }
109            if let Some(p) = small_power(x, exp) {
110                return small_number(order, p, negative);
111            }
112            let z = x.trailing_zeros();
113            let o = x >> z;
114            if o == 1 || u64::from(128 - o.leading_zeros()) * u64::from(exp) <= 512 {
115                return register_power(
116                    [o as u64, (o >> 64) as u64],
117                    z as usize,
118                    exp,
119                    negative,
120                    order,
121                );
122            }
123        }
124        let x = Operand::of(self);
125        if x.significant == 0 {
126            return small_number(order, 0, false);
127        }
128        power_of(x, exp, negative, order)
129    }
130
131    /// Returns `self` raised to the power `exp` modulo `modulus`: the `r` with `0 <= r < |modulus|`
132    /// and `r = self^exp (mod |modulus|)`, Euclid's remainder, as `rem_euclid` gives it, in the
133    /// byte order of `self`, in the shortest form, in one new vector of exactly its length.
134    ///
135    /// `self` may be negative, or longer than the modulus, and the modulus negative: only its
136    /// magnitude counts. `x^0` is 1 for every `x`, zero included, so modulo 1, where every
137    /// remainder is 0, `x^0 mod 1 = 0`.
138    ///
139    /// The time it takes depends on the exponent's bits, not only on its length: it is not a
140    /// constant-time exponentiation, and is not meant for secret exponents (keys) where whoever
141    /// could time it could learn them.
142    ///
143    /// # Panics
144    ///
145    /// When `modulus` is zero, with the message of `%`, and when `exp` is negative, with the message
146    /// `negative exponent`: a negative power is a power of the inverse of `self` modulo `modulus`,
147    /// which has to be computed first, with `mod_inverse`, and raised to `-exp`.
148    ///
149    /// # Examples
150    ///
151    /// ```
152    /// use a::math::numbers::{ByteOrder, Number};
153    ///
154    /// // 4^13 mod 497 = 445 = 0x01_BD.
155    /// let b = Number::new_from_u32(4, ByteOrder::BigEndian);
156    /// let e = Number::new_from_u32(13, ByteOrder::LittleEndian);
157    /// let m = Number::new_from_u32(497, ByteOrder::BigEndian);
158    /// assert_eq!(b.pow_mod(&e, &m).value, [0x01, 0xBD]);
159    ///
160    /// // (-4)^13 mod 497 = 497 - 445 = 52: the remainder is never negative.
161    /// let b = Number::new_from_i32(-4, ByteOrder::BigEndian);
162    /// let r = b.pow_mod(&e, &m);
163    /// assert_eq!(r.value, [52]);
164    /// assert!(!r.is_negative());
165    /// ```
166    #[track_caller]
167    pub fn pow_mod(&self, exp: &Number, modulus: &Number) -> Number {
168        let m = Operand::of(modulus);
169        if m.significant == 0 {
170            by_zero::<true>();
171        }
172        let e = Operand::of(exp);
173        if exp.negative && e.significant != 0 {
174            negative_exponent();
175        }
176        let order = self.byte_order;
177        if self.value.len() <= SMALL && exp.value.len() <= SMALL && modulus.value.len() <= SMALL {
178            // SAFETY: the vectors hold at most 16 bytes.
179            let (b, e, m) = unsafe {
180                (
181                    read_small(&self.value, order),
182                    read_small(&exp.value, exp.byte_order),
183                    read_small(&modulus.value, modulus.byte_order),
184                )
185            };
186            let mut r = small_pow_mod(b, e, m);
187            if self.negative && e & 1 == 1 && r != 0 {
188                r = m - r;
189            }
190            return small_number(order, r, false);
191        }
192        let b = Operand::of(self);
193        pow_mod_of(b, self.negative, e, m, order)
194    }
195}
196
197/// `b^e mod m` for `m` not zero, all in registers: modulo the odd part of `m` in Montgomery's
198/// form, modulo its power of two by wrapping products, put together as [`pow_mod_in`] puts them.
199#[inline(never)]
200fn small_pow_mod(b: u128, e: u128, m: u128) -> u128 {
201    if m == 1 {
202        return 0;
203    }
204    if e == 0 {
205        return 1;
206    }
207    if b == 0 {
208        return 0;
209    }
210    let el = [e as u64, (e >> 64) as u64];
211    let ebits = 128 - e.leading_zeros() as usize;
212    let z = m.trailing_zeros();
213    let odd = m >> z;
214    let bl = [b as u64, (b >> 64) as u64];
215    let bn = if bl[1] != 0 { 2 } else { 1 };
216    // The power modulo the odd part, by the residue of the base.
217    let r1 = if odd == 1 {
218        0
219    } else {
220        let ol = [odd as u64, (odd >> 64) as u64];
221        let mut s = [0u64; 16];
222        // SAFETY: the dividend of at most 4 limbs by a divisor of 1 or 2 takes at most
223        // `rem_itch(4, 2)` = 14 limbs of scratch, which `s` holds; the divisor's alignment is a
224        // matter of speed for the long divisions only.
225        unsafe {
226            if ol[1] == 0 {
227                let ring = Mont1::new(ol[0]);
228                let mut x = 0;
229                rem(&mut x, bl.as_ptr(), bn, 1, ol.as_ptr(), 1, s.as_mut_ptr());
230                let y = power_in_registers(&ring, x, el.as_ptr(), ebits);
231                u128::from(ring.plain(y))
232            } else {
233                let ring = Mont2::new(ol);
234                let mut x = [0; 2];
235                rem(
236                    x.as_mut_ptr(),
237                    bl.as_ptr(),
238                    bn,
239                    2,
240                    ol.as_ptr(),
241                    2,
242                    s.as_mut_ptr(),
243                );
244                // SAFETY: the exponent's limbs hold its `ebits` bits.
245                let y = power_in_registers(&ring, x, el.as_ptr(), ebits);
246                let y = ring.plain(y);
247                u128::from(y[0]) | (u128::from(y[1]) << 64)
248            }
249        }
250    };
251    if z == 0 {
252        return r1;
253    }
254    // The power modulo `2^z`, `z < 128`: zero when the base's zero bits fill it.
255    let mask = (1u128 << z) - 1;
256    let v = b.trailing_zeros();
257    let r2 = if v > 0
258        && u128::from(v)
259            .checked_mul(e)
260            .is_none_or(|p| p >= u128::from(z))
261    {
262        0
263    } else {
264        // SAFETY: the exponent's limbs hold its `ebits` bits.
265        unsafe { power_in_registers(&Low2, b, el.as_ptr(), ebits) & mask }
266    };
267    if odd == 1 {
268        return r2;
269    }
270    // `r1 + m' ((r2 - r1) / m' mod 2^z)`, with `1 / m' mod 2^128` by Newton's steps.
271    let mut inv = u128::from(binvert_limb(odd as u64));
272    inv = inv.wrapping_mul(2u128.wrapping_sub(odd.wrapping_mul(inv)));
273    let x = r2.wrapping_sub(r1).wrapping_mul(inv) & mask;
274    r1 + odd * x
275}
276
277/// Panics for a negative exponent of [`Number::pow_mod`].
278#[cold]
279#[inline(never)]
280#[track_caller]
281fn negative_exponent() -> ! {
282    panic!("negative exponent")
283}
284
285// Small powers
286
287/// `x^exp` when it fits in 128 bits, which the bits of `x` show: its odd part `o = x / 2^z` to the
288/// power `exp` is below `2^(exp bits(o))`. Binary exponentiation from the top bit, in registers.
289#[inline]
290fn small_power(x: u128, exp: u32) -> Option<u128> {
291    let z = x.trailing_zeros();
292    let o = x >> z;
293    let bits = 128 - o.leading_zeros();
294    if u64::from(bits + z) * u64::from(exp) > 128 {
295        return None;
296    }
297    let mut p = o;
298    for i in (0..31 - exp.leading_zeros()).rev() {
299        p *= p;
300        if exp >> i & 1 == 1 {
301            p *= o;
302        }
303    }
304    Some(p << (z * exp))
305}
306
307/// The number of magnitude `p` and sign `negative`, which zero does not keep, in one new vector of
308/// exactly its length, in the byte order `order`.
309fn small_number(order: ByteOrder, p: u128, negative: bool) -> Number {
310    let len = 16 - (p | 1).leading_zeros() as usize / 8;
311    let mut v = Vec::with_capacity(len);
312    // SAFETY: the new vector has room for the `len` bytes, from 1 to 16, all of which are written
313    // before the length is set.
314    unsafe {
315        write_small(v.as_mut_ptr(), order, p as u64, (p >> 64) as u64, len);
316        v.set_len(len);
317    }
318    Number {
319        value: v,
320        negative: negative && p != 0,
321        byte_order: order,
322    }
323}
324
325// Long powers
326
327/// The number of zero bits at the low end of the magnitude of the operand `x`, not zero, and its
328/// number of bits.
329///
330/// # Safety
331///
332/// The operand's vector must be valid for reads.
333unsafe fn zeros_and_bits(x: Operand) -> (usize, usize) {
334    let l = x.significant;
335    // SAFETY: every byte read is one of the `l` significant ones: big-endian the last `l` of the
336    // vector, little-endian the first `l`.
337    unsafe {
338        let byte = |i: usize| {
339            if x.big_endian {
340                *x.ptr.add(x.len - 1 - i)
341            } else {
342                *x.ptr.add(i)
343            }
344        };
345        let mut i = 0;
346        while byte(i) == 0 {
347            i += 1;
348        }
349        let zeros = 8 * i + byte(i).trailing_zeros() as usize;
350        (zeros, 8 * l - byte(l - 1).leading_zeros() as usize)
351    }
352}
353
354/// The limbs of an odd power of `bits` bits by `exp`, a limb more for the shift that puts back the
355/// base's low zero bits.
356///
357/// # Panics
358///
359/// When it does not fit in memory.
360fn power_limbs(bits: usize, exp: u32) -> usize {
361    let limbs = (bits as u128 * u128::from(exp)).div_ceil(64) + 1;
362    match usize::try_from(limbs) {
363        Ok(limbs) if limbs <= isize::MAX as usize / 32 => limbs,
364        _ => too_long(),
365    }
366}
367
368/// Panics for a power too long to allocate.
369#[cold]
370#[inline(never)]
371fn too_long() -> ! {
372    panic!("the power is too long to allocate")
373}
374
375/// `x^exp` for the operand `x`, not zero, with the sign `negative`, in the byte order `order`.
376#[inline(never)]
377fn power_of(x: Operand, exp: u32, negative: bool, order: ByteOrder) -> Number {
378    let xn = x.significant.div_ceil(8);
379    // SAFETY: the operand's vector is valid for reads, and its magnitude not zero.
380    let (z, bits) = unsafe { zeros_and_bits(x) };
381    let odd_bits = bits - z;
382    // An odd part of 1 makes the power a shift, whatever the exponent: in registers too, rather
383    // than in working memory sized for `exp` bits.
384    if odd_bits == 1 || odd_bits <= 128 && odd_bits as u64 * u64::from(exp) <= 512 {
385        // SAFETY: the operand's vector is valid for reads, and its odd part has at most 128 bits.
386        return unsafe { short_power(x, z, exp, negative, order) };
387    }
388    let on = odd_bits.div_ceil(64);
389    let rn = power_limbs(odd_bits, exp);
390    if rn > STACK_LIMBS {
391        // A power too long for the memory fails here, before the scratch of its squares is counted,
392        // which takes long for lengths far beyond the memory.
393        let mut v = Vec::<Pair>::new();
394        if v.try_reserve_exact(rn + 1).is_err() {
395            too_long();
396        }
397    }
398    // The scratch of the squares and products, at the lengths the power reaches: none while they
399    // are short enough for the schoolbook method (squares below 56 limbs, products by a base below
400    // 24). The lengths are bounds: a square's top limb may be zero, and then the power is shorter,
401    // and the scratch of a shorter length may be more (`sqr_itch` and `mul_itch` are not
402    // monotonic: a square of 202 limbs takes 486 limbs, of 203 and 204 less), which `power_in`
403    // allocates when it needs it.
404    let mut scratch = 0;
405    if rn >= 112 || on >= 24 {
406        let mut len = on;
407        for i in (0..31 - exp.leading_zeros()).rev() {
408            scratch = scratch.max(sqr_itch(len));
409            len = (2 * len).min(rn);
410            if exp >> i & 1 == 1 {
411                scratch = scratch.max(mul_itch(len.max(on), len.min(on)));
412                len = (len + on).min(rn);
413            }
414        }
415    }
416    // The operand, its odd part, two buffers for the power, and the scratch.
417    let need = even(xn) + even(on) + 2 * even(rn + 1) + scratch;
418    let compute = |s: *mut MaybeUninit<u64>| {
419        // SAFETY: the working memory holds `need` limbs, as the layout below takes them.
420        unsafe { power_in(s.cast(), x, xn, z, on, exp, rn, scratch, negative, order) }
421    };
422    if need <= SHORT_LIMBS {
423        let mut s = [PAIR; SHORT_LIMBS / 2];
424        compute(s.as_mut_ptr().cast())
425    } else if need <= STACK_LIMBS {
426        on_stack(compute)
427    } else {
428        on_heap_or_panic(need, compute)
429    }
430}
431
432/// The limbs of working memory up to which a power is computed in a buffer in the frame of its own
433/// function, rather than in the multiplication's 8 KiB on the stack, whose frame costs a probe of
434/// each of its pages.
435const SHORT_LIMBS: usize = 96;
436
437/// Two limbs of working memory, aligned to 16 bytes, as the multiplication's kernels want them.
438#[derive(Clone, Copy)]
439#[repr(C, align(16))]
440struct Pair([MaybeUninit<u64>; 2]);
441
442/// An uninitialised pair of limbs.
443const PAIR: Pair = Pair([MaybeUninit::uninit(); 2]);
444
445/// Runs `f` on `need` limbs of working memory on the heap, aligned to 16 bytes, freed on return;
446/// panics when they cannot be allocated, as a power too long for the memory is a mistake of the
447/// caller's.
448#[cold]
449#[inline(never)]
450fn on_heap_or_panic<R>(need: usize, f: impl FnOnce(*mut MaybeUninit<u64>) -> R) -> R {
451    let mut s = Vec::<Pair>::new();
452    if s.try_reserve_exact(need.div_ceil(2)).is_err() {
453        too_long();
454    }
455    f(s.as_mut_ptr().cast())
456}
457
458/// `x^exp` for the operand `x`, not zero, of `z` zero bits at its low end and an odd part of at most
459/// 128 bits whose power has at most 512, or of 1, whose power is 1: in registers, four limbs for a
460/// power of up to 256 bits and eight beyond.
461///
462/// # Safety
463///
464/// The operand's vector must be valid for reads.
465#[inline(never)]
466unsafe fn short_power(x: Operand, z: usize, exp: u32, negative: bool, order: ByteOrder) -> Number {
467    // The odd part, shifted down from its limbs, which fits in two.
468    let (zl, zb) = (z / 64, (z % 64) as u32);
469    // SAFETY: as the caller guarantees.
470    let l = |i: usize| unsafe { limb_at(x, zl + i) };
471    let (l0, l1, l2) = (l(0), l(1), l(2));
472    let o = if zb == 0 {
473        [l0, l1]
474    } else {
475        [
476            (l0 >> zb) | (l1 << (64 - zb)),
477            (l1 >> zb) | (l2 << (64 - zb)),
478        ]
479    };
480    register_power(o, z, exp, negative, order)
481}
482
483/// `(o 2^z)^exp` for the odd `o` of two limbs, whose power has at most 512 bits: in registers, four
484/// limbs for a power of up to 256 bits and eight beyond, shifted by `z exp` bits as it is written.
485#[inline(never)]
486fn register_power(o: [u64; 2], z: usize, exp: u32, negative: bool, order: ByteOrder) -> Number {
487    let bits = 128
488        - if o[1] != 0 {
489            o[1].leading_zeros()
490        } else {
491            64 + o[0].leading_zeros()
492        };
493    let shift = z as u128 * u128::from(exp);
494    // SAFETY: the limbs hold the odd power, with a limb of room above it.
495    unsafe {
496        if bits == 1 || bits as u64 * u64::from(exp) <= 256 {
497            let mut r = odd_power::<4, 5>(o, exp);
498            shifted_number(r.as_mut_ptr(), len_of(&r[..4]), shift, negative, order)
499        } else {
500            let mut r = odd_power::<8, 9>(o, exp);
501            shifted_number(r.as_mut_ptr(), len_of(&r[..8]), shift, negative, order)
502        }
503    }
504}
505
506/// The limbs of `r` without the zero limbs at its top.
507#[inline(always)]
508fn len_of(r: &[u64]) -> usize {
509    r.len() - r.iter().rev().take_while(|&&l| l == 0).count()
510}
511
512/// `o^exp` in `N` limbs, which hold it, and one more of room, `M = N + 1`: binary exponentiation
513/// from the top bit on the limbs the power has so far, a square and, for a one bit, a product by
514/// the base's one or two limbs each step; no limb of a square or a product reaches past the power's
515/// own `N`.
516#[inline(always)]
517fn odd_power<const N: usize, const M: usize>(o: [u64; 2], exp: u32) -> [u64; M] {
518    let ol = if o[1] != 0 { 2 } else { 1 };
519    let mut p = [0u64; N];
520    p[0] = o[0];
521    p[1] = o[1];
522    let mut len = ol;
523    for i in (0..31 - exp.leading_zeros()).rev() {
524        // The square, `2 len` limbs or one fewer, below `N` limbs as the power is.
525        let mut r = [0u64; N];
526        for a in 0..len {
527            let mut carry = 0u64;
528            for b in 0..len {
529                let t =
530                    u128::from(p[a]) * u128::from(p[b]) + u128::from(r[a + b]) + u128::from(carry);
531                r[a + b] = t as u64;
532                carry = (t >> 64) as u64;
533            }
534            if a + len < N {
535                r[a + len] = carry;
536            }
537        }
538        len = (2 * len).min(N);
539        if r[len - 1] == 0 {
540            len -= 1;
541        }
542        p = r;
543        if exp >> i & 1 == 1 {
544            let mut r = [0u64; N];
545            for (a, &oa) in o.iter().enumerate().take(ol) {
546                let mut carry = 0u64;
547                for b in 0..len.min(N - a) {
548                    let t = u128::from(oa) * u128::from(p[b])
549                        + u128::from(r[a + b])
550                        + u128::from(carry);
551                    r[a + b] = t as u64;
552                    carry = (t >> 64) as u64;
553                }
554                if a + len < N {
555                    r[a + len] = carry;
556                }
557            }
558            len = (len + ol).min(N);
559            if r[len - 1] == 0 {
560                len -= 1;
561            }
562            p = r;
563        }
564    }
565    let mut r = [0u64; M];
566    r[..N].copy_from_slice(&p);
567    r
568}
569
570/// Limb `i` of the magnitude of the operand `x`, zero above its significant bytes.
571///
572/// # Safety
573///
574/// The operand's vector must be valid for reads.
575#[inline(always)]
576unsafe fn limb_at(x: Operand, i: usize) -> u64 {
577    let mut l = 0;
578    for k in (0..8).rev() {
579        let p = 8 * i + k;
580        let byte = if p >= x.significant {
581            0
582        } else if x.big_endian {
583            // SAFETY: byte `p` of the magnitude lies inside the significant bytes.
584            unsafe { *x.ptr.add(x.len - 1 - p) }
585        } else {
586            // SAFETY: as above.
587            unsafe { *x.ptr.add(p) }
588        };
589        l = (l << 8) | u64::from(byte);
590    }
591    l
592}
593
594/// The number of the odd power in the `len` limbs at `r`, the top one not zero, shifted left by
595/// `shift` bits, with the sign `negative`, in one new vector of exactly its length.
596///
597/// # Safety
598///
599/// The limbs must be valid for reads and writes, with one more above them.
600unsafe fn shifted_number(
601    r: *mut u64,
602    mut len: usize,
603    shift: u128,
604    negative: bool,
605    order: ByteOrder,
606) -> Number {
607    // SAFETY: as the caller guarantees.
608    unsafe {
609        // The zero bits of the power: whole bytes, and the bits below a byte, which shift the limbs
610        // of the odd power.
611        let bytes = usize::try_from(shift / 8).unwrap_or_else(|_| too_long());
612        *r.add(len) = lshift(r, r, len, (shift % 8) as u32);
613        if *r.add(len) != 0 {
614            len += 1;
615        }
616        let odd_len = 8 * len - (*r.add(len - 1)).leading_zeros() as usize / 8;
617        let total = odd_len
618            .checked_add(bytes)
619            .filter(|&t| t <= isize::MAX as usize)
620            .unwrap_or_else(|| too_long());
621        let mut v: Vec<u8> = Vec::new();
622        if v.try_reserve_exact(total).is_err() {
623            too_long();
624        }
625        let dst = v.as_mut_ptr();
626        let product = Product {
627            r,
628            len: odd_len,
629            negative,
630        };
631        if order == ByteOrder::BigEndian {
632            product.write(dst, order);
633            ptr::write_bytes(dst.add(odd_len), 0, bytes);
634        } else {
635            ptr::write_bytes(dst, 0, bytes);
636            product.write(dst.add(bytes), order);
637        }
638        v.set_len(total);
639        Number {
640            value: v,
641            negative,
642            byte_order: order,
643        }
644    }
645}
646
647/// [`power_of`] in the working memory at `s`, for the operand `x` of `xn` limbs and `z` zero bits
648/// at its low end, whose odd part has `on` limbs; `room` limbs of it are for the scratch of the
649/// squares and products, and one that needs more takes a buffer of its own.
650///
651/// # Safety
652///
653/// The working memory holds the limbs that `power_of` counts, and starts on 16 bytes; the
654/// operand's vector is valid for reads, and its magnitude not zero.
655#[allow(clippy::too_many_arguments)]
656unsafe fn power_in(
657    s: *mut u64,
658    x: Operand,
659    xn: usize,
660    z: usize,
661    on: usize,
662    exp: u32,
663    rn: usize,
664    room: usize,
665    negative: bool,
666    order: ByteOrder,
667) -> Number {
668    // SAFETY: as the caller guarantees: every buffer lies in the working memory, apart, and every
669    // length stays within its buffer, as `power_of` bounds them.
670    unsafe {
671        let a = s;
672        let o = a.add(even(xn));
673        let p = o.add(even(on));
674        let q = p.add(even(rn + 1));
675        let t = q.add(even(rn + 1));
676        to_limbs(x, a);
677        // The odd part.
678        let (zl, zb) = (z / 64, (z % 64) as u32);
679        if zb != 0 {
680            rshift(a.add(zl), xn - zl, zb);
681        }
682        ptr::copy_nonoverlapping(a.add(zl), o, on);
683        // Binary exponentiation from the top bit, the power going back and forth between `p` and
684        // `q`.
685        let (mut r, mut w) = (p, q);
686        ptr::copy_nonoverlapping(o, r, on);
687        let mut len = on;
688        for i in (0..31 - exp.leading_zeros()).rev() {
689            with_room(t, room, sqr_itch(len), |t| sqr(w, r, len, t));
690            len *= 2;
691            if *w.add(len - 1) == 0 {
692                len -= 1;
693            }
694            (r, w) = (w, r);
695            if exp >> i & 1 == 1 {
696                let itch = mul_itch(len.max(on), len.min(on));
697                with_room(t, room, itch, |t| {
698                    if len >= on {
699                        mul(w, r, len, o, on, t);
700                    } else {
701                        mul(w, o, on, r, len, t);
702                    }
703                });
704                len += on;
705                if *w.add(len - 1) == 0 {
706                    len -= 1;
707                }
708                (r, w) = (w, r);
709            }
710        }
711        shifted_number(r, len, z as u128 * u128::from(exp), negative, order)
712    }
713}
714
715/// Runs `f` on scratch of `need` limbs: the `room` limbs at `t` when they are enough, and otherwise a
716/// buffer of its own, on 16 bytes, freed on return.
717///
718/// # Safety
719///
720/// The `room` limbs at `t` must be valid for reads and writes.
721unsafe fn with_room<R>(t: *mut u64, room: usize, need: usize, f: impl FnOnce(*mut u64) -> R) -> R {
722    if need <= room {
723        f(t)
724    } else {
725        more_room(need, f)
726    }
727}
728
729/// The buffer of [`with_room`] when the planned scratch is not enough. Out of line and cold.
730#[cold]
731#[inline(never)]
732fn more_room<R>(need: usize, f: impl FnOnce(*mut u64) -> R) -> R {
733    let mut s = Vec::<Pair>::with_capacity(need.div_ceil(2));
734    f(s.as_mut_ptr().cast())
735}
736
737// Powers modulo a number
738
739/// The shape of a modulus `m = 2^z m'`, `m'` odd, as [`pow_mod_in`] takes it apart.
740#[derive(Clone, Copy)]
741struct Shape {
742    /// The limbs of `m`.
743    mn: usize,
744    /// The zero bits at its low end.
745    z: usize,
746    /// The limbs of `m'`.
747    nodd: usize,
748    /// The limbs of `2^z - 1`, the residues modulo `2^z`.
749    kn: usize,
750}
751
752impl Shape {
753    /// The shape of the modulus `m`, not zero.
754    ///
755    /// # Safety
756    ///
757    /// The operand's vector must be valid for reads.
758    unsafe fn of(m: Operand) -> Self {
759        // SAFETY: as the caller guarantees.
760        let (z, bits) = unsafe { zeros_and_bits(m) };
761        Shape {
762            mn: m.significant.div_ceil(8),
763            z,
764            nodd: (bits - z).div_ceil(64),
765            kn: z.div_ceil(64),
766        }
767    }
768
769    /// Whether `m'` is 1, so that `m` is a power of two.
770    fn power_of_two(&self, bits: usize) -> bool {
771        bits == self.z + 1
772    }
773}
774
775/// `b^e mod |m|` for the operands `b`, of sign `negative_b`, `e` and `m`, not zero, in the byte
776/// order `order`.
777#[inline(never)]
778fn pow_mod_of(b: Operand, negative_b: bool, e: Operand, m: Operand, order: ByteOrder) -> Number {
779    let (bn, en) = (b.significant.div_ceil(8), e.significant.div_ceil(8));
780    // SAFETY: the modulus's vector is valid for reads, and its magnitude not zero.
781    let shape = unsafe { Shape::of(m) };
782    // The exponent's bits, for the window: an upper bound from its bytes, as the table is sized
783    // for it.
784    let ebits = 8 * e.significant;
785    let need = pow_mod_itch(bn, en, ebits, shape);
786    let compute = |s: *mut MaybeUninit<u64>| {
787        // SAFETY: the working memory holds `need` limbs.
788        unsafe { pow_mod_in(s.cast(), b, negative_b, e, m, shape, order) }
789    };
790    if need <= STACK_LIMBS {
791        on_stack(compute)
792    } else {
793        on_heap(need, compute)
794    }
795}
796
797/// The limbs of working memory of [`pow_mod_in`] for a base of `bn` limbs, an exponent of `en`
798/// limbs and at most `ebits` bits, and a modulus of the shape `shape`.
799fn pow_mod_itch(bn: usize, en: usize, ebits: usize, shape: Shape) -> usize {
800    let Shape { mn, nodd, kn, .. } = shape;
801    let inputs = even(bn) + even(en) + 3 * even(mn + 1);
802    let mut work = rem_itch(bn, mn);
803    if kn == 0 {
804        work = work.max(powm_odd_itch(bn, ebits, nodd));
805    } else {
806        // The power modulo `2^z`, the inverse of `m'` and Hensel's numerator for it, the
807        // difference and the product of `m'` by the correction.
808        let crt = 4 * even(kn) + even(nodd + kn + 1);
809        let products = mullo_itch(kn).max(mul_itch(nodd.max(kn), nodd.min(kn)));
810        let rest = powm_odd_itch(bn, ebits, nodd)
811            .max(powlo_itch(ebits, kn))
812            .max(products);
813        work = work.max(crt + rest);
814    }
815    inputs + work
816}
817
818/// [`pow_mod_of`] in the working memory at `s`.
819///
820/// # Safety
821///
822/// The working memory holds [`pow_mod_itch`] limbs and starts on 16 bytes; the operands' vectors
823/// are valid for reads, the modulus is not zero, and `shape` is its shape.
824unsafe fn pow_mod_in(
825    s: *mut u64,
826    b: Operand,
827    negative_b: bool,
828    e: Operand,
829    m: Operand,
830    shape: Shape,
831    order: ByteOrder,
832) -> Number {
833    let (bn, en) = (b.significant.div_ceil(8), e.significant.div_ceil(8));
834    let Shape { mn, z, nodd, kn } = shape;
835    // SAFETY: every buffer lies in the working memory that `pow_mod_itch` counts, apart from the
836    // others, and starts on 16 bytes.
837    unsafe {
838        let bp = s;
839        let ep = bp.add(even(bn));
840        let mp = ep.add(even(en));
841        let odd = mp.add(even(mn + 1));
842        let r = odd.add(even(mn + 1));
843        let t = r.add(even(mn + 1));
844        to_limbs(m, mp);
845        let one = mn == 1 && *mp == 1;
846        if en == 0 {
847            // `x^0 = 1`, which is 0 modulo 1.
848            return small_number(order, u128::from(!one), false);
849        }
850        if bn == 0 || one {
851            return small_number(order, 0, false);
852        }
853        to_limbs(e, ep);
854        to_limbs(b, bp);
855        let ebits = 64 * en - (*ep.add(en - 1)).leading_zeros() as usize;
856        let mbits = 64 * mn - (*mp.add(mn - 1)).leading_zeros() as usize;
857        if ebits == 1 {
858            // `b^1`: the remainder alone.
859            rem(r, bp, bn, 0, mp, mn, t);
860        } else if z == 0 {
861            powm_odd(r, bp, bn, ep, ebits, mp, mn, t);
862        } else if shape.power_of_two(mbits) {
863            powlo(r, bp, bn, ep, en, ebits, z, t);
864            ptr::write_bytes(r.add(kn), 0, mn - kn);
865        } else {
866            // `m'`, then both powers, put together: `r = r1 + m' ((r2 - r1) / m' mod 2^z)`, below
867            // `m`.
868            let (zl, zb) = (z / 64, (z % 64) as u32);
869            ptr::copy_nonoverlapping(mp.add(zl), odd, mn - zl);
870            if zb != 0 {
871                rshift(odd, mn - zl, zb);
872            }
873            let r2 = t;
874            let inv = r2.add(even(kn));
875            let num = inv.add(even(kn));
876            let d = num.add(even(kn));
877            let y = d.add(even(kn));
878            let rest = y.add(even(nodd + kn + 1));
879            powm_odd(r, bp, bn, ep, ebits, odd, nodd, rest);
880            powlo(r2, bp, bn, ep, en, ebits, z, rest);
881            ptr::write_bytes(num, 0, kn);
882            *num = 1;
883            bdiv_q(inv, num, kn, odd, nodd, binvert_limb(*odd));
884            // `r2 - r1` modulo `2^(64 kn)`, `r1` cut or extended to `kn` limbs.
885            if nodd >= kn {
886                sub_n(d, r2, r, kn);
887            } else {
888                let borrow = sub_n(d, r2, r, nodd);
889                ptr::copy_nonoverlapping(r2.add(nodd), d.add(nodd), kn - nodd);
890                sub_1(d.add(nodd), kn - nodd, u64::from(borrow));
891            }
892            let x = num;
893            mullo(x, d, inv, kn, rest);
894            if zb != 0 {
895                *x.add(kn - 1) &= (1 << zb) - 1;
896            }
897            if nodd >= kn {
898                mul(y, odd, nodd, x, kn, rest);
899            } else {
900                mul(y, x, kn, odd, nodd, rest);
901            }
902            // `r1` and the correction, below `m`, so its limbs from `mn` up are zero.
903            let carry = add_n(y, y, r, nodd);
904            add_1(y.add(nodd), kn, u64::from(carry));
905            ptr::copy_nonoverlapping(y, r, mn);
906        }
907        // A negative base to an odd power: `|m| - r` unless `r` is zero.
908        let mut top = mn;
909        while top > 0 && *r.add(top - 1) == 0 {
910            top -= 1;
911        }
912        if negative_b && *ep & 1 == 1 && top != 0 {
913            sub_n(r, mp, r, mn);
914            top = mn;
915            while top > 0 && *r.add(top - 1) == 0 {
916                top -= 1;
917            }
918        }
919        number_of(r, top, order)
920    }
921}
922
923/// The non-negative number of the `n` limbs at `r`, the top one not zero (none for zero), in one
924/// new vector of exactly its length, in the byte order `order`.
925///
926/// # Safety
927///
928/// The limbs must be valid for reads.
929unsafe fn number_of(r: *const u64, n: usize, order: ByteOrder) -> Number {
930    // SAFETY: as the caller guarantees.
931    unsafe {
932        if n == 0 {
933            return small_number(order, 0, false);
934        }
935        let len = 8 * n - (*r.add(n - 1)).leading_zeros() as usize / 8;
936        let mut v = Vec::with_capacity(len);
937        Product {
938            r,
939            len,
940            negative: false,
941        }
942        .write(v.as_mut_ptr(), order);
943        v.set_len(len);
944        Number {
945            value: v,
946            negative: false,
947            byte_order: order,
948        }
949    }
950}
951
952/// The limbs of scratch space of [`powm_odd`] for a base of `bn` limbs, an exponent of at most
953/// `ebits` bits and a modulus of `n` limbs.
954fn powm_odd_itch(bn: usize, ebits: usize, n: usize) -> usize {
955    if n <= 2 {
956        rem_itch(bn + n, n)
957    } else {
958        let table = (1 << (window(ebits) - 1)) * even(n);
959        Montgomery::new_itch(n) + table + Montgomery::itch(n).max(rem_itch(bn + n, n))
960    }
961}
962
963/// Sets the `n` limbs at `r` to `b^e mod m` for the `bn` limbs at `b`, not zero, the exponent of
964/// `ebits` bits at `e`, at least 2, and the odd `m` of `n` limbs at `m`, above 1, its top limb not
965/// zero.
966///
967/// # Safety
968///
969/// The limbs must be valid, apart; the scratch at `s` holds [`powm_odd_itch`] limbs and starts on
970/// 16 bytes.
971#[allow(clippy::too_many_arguments)]
972unsafe fn powm_odd(
973    r: *mut u64,
974    b: *const u64,
975    bn: usize,
976    e: *const u64,
977    ebits: usize,
978    m: *const u64,
979    n: usize,
980    s: *mut u64,
981) {
982    // SAFETY: as the caller guarantees; the residue of the base goes to the first entry of the
983    // table, and the working memory of the Montgomery arithmetic before it.
984    unsafe {
985        match n {
986            1 => {
987                let ring = Mont1::new(*m);
988                let mut x = 0;
989                rem(&mut x, b, bn, 1, m, 1, s);
990                let y = power_in_registers(&ring, x, e, ebits);
991                *r = ring.plain(y);
992            }
993            2 => {
994                let ring = Mont2::new([*m, *m.add(1)]);
995                let mut x = [0; 2];
996                rem(x.as_mut_ptr(), b, bn, 2, m, 2, s);
997                let y = power_in_registers(&ring, x, e, ebits);
998                let z = ring.plain(y);
999                (*r, *r.add(1)) = (z[0], z[1]);
1000            }
1001            // Three to seven limbs in registers: measured on an Apple M4 Max with exponents as
1002            // long as the modulus, 6 limbs took 54,300 cycles so against 62,700 in limbs, 7 limbs
1003            // 83,800 against 92,400, and 8 limbs 123,000 against 117,000.
1004            3 => powm_registers::<3>(r, b, bn, e, ebits, m, s),
1005            4 => powm_registers::<4>(r, b, bn, e, ebits, m, s),
1006            5 => powm_registers::<5>(r, b, bn, e, ebits, m, s),
1007            6 => powm_registers::<6>(r, b, bn, e, ebits, m, s),
1008            7 => powm_registers::<7>(r, b, bn, e, ebits, m, s),
1009            _ => {
1010                let ring = Montgomery::new(m, n, s);
1011                let table = s.add(Montgomery::new_itch(n));
1012                let stride = even(n);
1013                let t = table.add((1 << (window(ebits) - 1)) * stride);
1014                rem(table, b, bn, n, m, n, t);
1015                power(&ring, r, e, ebits, table, stride, t);
1016                ring.plain(r, r, t);
1017            }
1018        }
1019    }
1020}
1021
1022/// [`powm_odd`] for a modulus of `N` limbs, in registers.
1023///
1024/// # Safety
1025///
1026/// As for [`powm_odd`].
1027#[inline(never)]
1028unsafe fn powm_registers<const N: usize>(
1029    r: *mut u64,
1030    b: *const u64,
1031    bn: usize,
1032    e: *const u64,
1033    ebits: usize,
1034    m: *const u64,
1035    s: *mut u64,
1036) {
1037    // SAFETY: as the caller guarantees.
1038    unsafe {
1039        let mut mm = [0; N];
1040        ptr::copy_nonoverlapping(m, mm.as_mut_ptr(), N);
1041        let ring = MontN::new(mm);
1042        let mut x = [0; N];
1043        rem(x.as_mut_ptr(), b, bn, N, m, N, s);
1044        let y = power_in_registers(&ring, x, e, ebits);
1045        let z = ring.plain(y);
1046        ptr::copy_nonoverlapping(z.as_ptr(), r, N);
1047    }
1048}
1049
1050/// The limbs of scratch space of [`powlo`] for an exponent of at most `ebits` bits and a modulus of
1051/// `n` limbs.
1052fn powlo_itch(ebits: usize, n: usize) -> usize {
1053    (1 << (window(ebits) - 1)) * even(n) + Low::itch(n)
1054}
1055
1056/// Sets the `z.div_ceil(64)` limbs at `r` to `b^e mod 2^z` for the `bn` limbs at `b`, not zero, the
1057/// exponent of `en` limbs and `ebits` bits at `e`, at least 2, and `z >= 1`.
1058///
1059/// An even base `b = 2^v b'` gives 0 when `v e >= z`; otherwise the power is taken by the low halves
1060/// of products, in registers up to two limbs.
1061///
1062/// # Safety
1063///
1064/// The limbs must be valid, apart; the scratch at `s` holds [`powlo_itch`] limbs and starts on 16
1065/// bytes.
1066#[allow(clippy::too_many_arguments)]
1067unsafe fn powlo(
1068    r: *mut u64,
1069    b: *const u64,
1070    bn: usize,
1071    e: *const u64,
1072    en: usize,
1073    ebits: usize,
1074    z: usize,
1075    s: *mut u64,
1076) {
1077    let kn = z.div_ceil(64);
1078    // SAFETY: as the caller guarantees.
1079    unsafe {
1080        let mut v = 0;
1081        while *b.add(v / 64) == 0 {
1082            v += 64;
1083        }
1084        v += (*b.add(v / 64)).trailing_zeros() as usize;
1085        if v > 0 && (en > 1 || u128::from(*e) * v as u128 >= z as u128) {
1086            ptr::write_bytes(r, 0, kn);
1087            return;
1088        }
1089        if kn <= 2 {
1090            let x = u128::from(*b)
1091                | if bn > 1 {
1092                    u128::from(*b.add(1)) << 64
1093                } else {
1094                    0
1095                };
1096            let y = power_in_registers(&Low2, x, e, ebits);
1097            let y = if z < 128 { y & ((1 << z) - 1) } else { y };
1098            *r = y as u64;
1099            if kn == 2 {
1100                *r.add(1) = (y >> 64) as u64;
1101            }
1102            return;
1103        }
1104        match kn {
1105            3 => return low_registers::<3>(r, b, bn, e, ebits, z),
1106            4 => return low_registers::<4>(r, b, bn, e, ebits, z),
1107            5 => return low_registers::<5>(r, b, bn, e, ebits, z),
1108            6 => return low_registers::<6>(r, b, bn, e, ebits, z),
1109            7 => return low_registers::<7>(r, b, bn, e, ebits, z),
1110            8 => return low_registers::<8>(r, b, bn, e, ebits, z),
1111            _ => {}
1112        }
1113        let table = s;
1114        let stride = even(kn);
1115        let t = table.add((1 << (window(ebits) - 1)) * stride);
1116        let have = bn.min(kn);
1117        ptr::copy_nonoverlapping(b, table, have);
1118        ptr::write_bytes(table.add(have), 0, kn - have);
1119        power(&Low { n: kn }, r, e, ebits, table, stride, t);
1120        if !z.is_multiple_of(64) {
1121            *r.add(kn - 1) &= (1 << (z % 64)) - 1;
1122        }
1123    }
1124}
1125
1126/// [`powlo`] for `N = z.div_ceil(64)` limbs from 3 to 8, in registers.
1127///
1128/// # Safety
1129///
1130/// As for [`powlo`].
1131#[inline(never)]
1132unsafe fn low_registers<const N: usize>(
1133    r: *mut u64,
1134    b: *const u64,
1135    bn: usize,
1136    e: *const u64,
1137    ebits: usize,
1138    z: usize,
1139) {
1140    let mut x = [0u64; N];
1141    // SAFETY: as the caller guarantees: the base's low limbs, the exponent's bits and the `N`
1142    // limbs of the result.
1143    unsafe {
1144        ptr::copy_nonoverlapping(b, x.as_mut_ptr(), bn.min(N));
1145        let mut y = power_in_registers(&LowN::<N>, x, e, ebits);
1146        if !z.is_multiple_of(64) {
1147            y[N - 1] &= (1 << (z % 64)) - 1;
1148        }
1149        ptr::copy_nonoverlapping(y.as_ptr(), r, N);
1150    }
1151}