Skip to main content

a/math/numbers/
shift.rs

1//! Bit shifts of [`Number`]s: `<<`, `>>`, `<<=` and `>>=` by a `usize` number of bits.
2//!
3//! The shifts follow the rules of Rust's primitive signed integers, with no bits lost at the
4//! top: `a << k` is `a · 2^k`, and `a >> k` is `a / 2^k` rounded towards negative infinity,
5//! the arithmetic shift of a two's-complement integer, so `-7 >> 1` is `-4` and `-1 >> k` is
6//! `-1` for every `k`. On a sign and a magnitude, a shift moves the bits of the magnitude and
7//! keeps the sign, except that a negative number whose shifted-out bits are not all zero has
8//! one added to the magnitude of its quotient. That can carry: `-0x1FF >> 1` is `-0x100`, one
9//! byte longer than `0x1FF >> 1`.
10//!
11//! A shift by `k = 8q + r` bits moves the bytes of the magnitude by `q` positions and their
12//! bits by `r`. Everything about the result but its bytes is planned first: the significant
13//! length `l` of the magnitude, the length of the result (`l + q` bytes for `<<`, or one more
14//! when the bits shifted out of the top byte are not zero; `l - q` for `>>`, or one fewer when
15//! nothing is left of the top byte), and, for a negative `>>`, whether one is added. Only then
16//! is a vector chosen for the result, as the other operators choose one: the vector of the
17//! operand taken by value, or of the target of `<<=` or `>>=`, when its capacity has room for
18//! the result, and otherwise one new vector of exactly the result's length. A right shift is
19//! never longer than its operand, so `>>` and `>>=` on an owned number allocate nothing (but
20//! for zero in a vector without capacity, which needs one byte).
21//!
22//! Operands of at most 16 bytes, shifted left by fewer than 128 bits or right by any amount,
23//! take a short path in registers: the magnitude is read into a `u128` as the addition reads
24//! it, shifted (left, as two `u64`s into four, by a branch on the amount below 64 that is the
25//! same for every call with that amount), and the result, at most 32 bytes, written in the
26//! operand's byte order. `<<=` of 17 to 32 bytes by fewer than 64 bits does the same with four
27//! limbs. The longer ones are handled out of line, in one pass over the bytes, in place in
28//! either byte order; in place, every call the out-of-line functions make is their last step,
29//! with its arguments in registers, so that they keep no stack frame:
30//!
31//! - A shift by whole bytes moves them, inline up to 64 bytes (all of them read before any is
32//!   written) and with `memmove` beyond. Big-endian in place it moves nothing: `>>` drops the
33//!   bytes at the end of the vector, and `<<` writes zeros after them.
34//! - A shift with bits is done by kernels chosen at compile time: on 64-bit little-endian
35//!   `aarch64` with NEON, sixteen bytes at a time in byte lanes, each byte of the result made
36//!   from the byte at its position and its neighbour, in the order of memory, so that one
37//!   kernel serves both byte orders with no byte reversal, each block loaded once and stored on
38//!   16 bytes from 64 bytes up; elsewhere and under Miri, portable ones on `u64`s that carry the
39//!   bits shifted out of one group of eight bytes into the next.
40//!   In place they keep every byte read before a write reaches it: `<<` little-endian runs
41//!   from the most significant byte down, as the bytes move up; the others run upwards.
42//! - Zeros below the result of `<<` are written inline up to 64 bytes, with `memset` beyond.
43//! - A negative quotient rounded down has one added to its eight least significant bytes,
44//!   which are computed from the input before the kernel writes over it, so that they are not
45//!   read back from stores still on their way; the bytes above are carried into only when
46//!   those eight are all 0xFF.
47//!
48//! Some facts about the result are coin tosses for random numbers: whether the bits shifted out
49//! of the top byte by `<<` are zero (the result is one byte longer or not), whether the top
50//! byte is left with anything by `>>` (one byte shorter or not), and whether a bit shifted out
51//! of a negative number is set (it is rounded or not). None of them is decided by a branch: the
52//! byte above the top is written where the result's top byte is written anyway when it is not
53//! needed, the kernels count their blocks from the input's length rather than the result's,
54//! and the one of the rounding is an addition of zero or one.
55
56// The kernels that shift the bits of long magnitudes, under the name `kernels`: NEON on the
57// 64-bit little-endian aarch64 targets that the addition's assembly runs on (the ones whose
58// operating system allows unaligned accesses), where NEON is enabled, as it is by default; the
59// portable ones elsewhere and under Miri, which runs no SIMD of this kind.
60#[cfg(all(
61    target_arch = "aarch64",
62    target_endian = "little",
63    target_pointer_width = "64",
64    target_feature = "neon",
65    any(
66        target_vendor = "apple",
67        target_os = "linux",
68        target_os = "android",
69        target_os = "windows",
70        target_os = "freebsd",
71        target_os = "netbsd",
72        target_os = "openbsd",
73        target_os = "fuchsia"
74    ),
75    not(miri)
76))]
77#[path = "shift/aarch64.rs"]
78mod kernels;
79#[cfg(not(all(
80    target_arch = "aarch64",
81    target_endian = "little",
82    target_pointer_width = "64",
83    target_feature = "neon",
84    any(
85        target_vendor = "apple",
86        target_os = "linux",
87        target_os = "android",
88        target_os = "windows",
89        target_os = "freebsd",
90        target_os = "netbsd",
91        target_os = "openbsd",
92        target_os = "fuchsia"
93    ),
94    not(miri)
95)))]
96#[path = "shift/portable.rs"]
97mod kernels;
98
99use super::add::{SMALL, read, read_small, significant_len, write, write_small};
100use super::{ByteOrder, Number};
101use core::hint::select_unpredictable;
102use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
103use core::ptr;
104use std::alloc::{Layout, alloc};
105
106impl Shl<usize> for Number {
107    type Output = Number;
108
109    /// Returns `self · 2^rhs`, in the byte order of `self`, in the shortest form, as
110    /// `self <<= rhs` does.
111    ///
112    /// The result is built in the vector of `self` when its capacity has room for it, which
113    /// allocates nothing, and otherwise in one new vector of exactly its length.
114    ///
115    /// # Panics
116    ///
117    /// When the result is too long to be allocated.
118    ///
119    /// # Examples
120    ///
121    /// ```
122    /// use a::math::numbers::{ByteOrder, Number};
123    ///
124    /// let mut value = Vec::with_capacity(4);
125    /// value.extend([0x81, 0x02]);
126    /// let a = Number::new(value, ByteOrder::BigEndian);
127    /// let pointer = a.value.as_ptr();
128    ///
129    /// // 0x81_02 << 9 = 0x01_02_04_00, in the vector of `a`.
130    /// let shifted = a << 9;
131    /// assert_eq!(shifted.value, [0x01, 0x02, 0x04, 0x00]);
132    /// assert_eq!(shifted.value.as_ptr(), pointer);
133    /// ```
134    #[inline]
135    fn shl(mut self, rhs: usize) -> Number {
136        self <<= rhs;
137        self
138    }
139}
140
141impl Shl<usize> for &Number {
142    type Output = Number;
143
144    /// Returns `self · 2^rhs`, in the byte order of `self`, in the shortest form.
145    ///
146    /// The result is built in one new vector of exactly its length (one byte for zero), the
147    /// only allocation; `self` is left as it was. It may have any sign and length, and need not
148    /// be in the shortest form.
149    ///
150    /// # Panics
151    ///
152    /// When the result is too long to be allocated.
153    ///
154    /// # Examples
155    ///
156    /// ```
157    /// use a::math::numbers::{ByteOrder, Number};
158    ///
159    /// // -3 << 8 = -0x03_00.
160    /// let a = Number::new_from_i32(-3, ByteOrder::LittleEndian);
161    /// let shifted = &a << 8;
162    /// assert_eq!(shifted.value, [0x00, 0x03]);
163    /// assert!(shifted.is_negative());
164    ///
165    /// // Zero stays zero, however far it is shifted.
166    /// let zero = Number::new_from_u8(0, ByteOrder::BigEndian);
167    /// assert_eq!((&zero << usize::MAX).value, [0]);
168    /// ```
169    #[inline]
170    fn shl(self, rhs: usize) -> Number {
171        if short_shl(self, rhs) {
172            // SAFETY: the vector holds at most 16 bytes, and the shift is below 128 bits.
173            let s = unsafe { small_shl(self, rhs) };
174            return small_number(self.byte_order, s);
175        }
176        shl_ref(self, rhs)
177    }
178}
179
180impl ShlAssign<usize> for Number {
181    /// Multiplies `self` by `2^rhs`, keeping its byte order, in the shortest form.
182    ///
183    /// The result is built in the vector of `self` when its capacity has room for it, which
184    /// allocates nothing, and otherwise in one new vector of exactly its length, which replaces
185    /// it.
186    ///
187    /// # Panics
188    ///
189    /// When the result is too long to be allocated.
190    ///
191    /// # Examples
192    ///
193    /// ```
194    /// use a::math::numbers::{ByteOrder, Number};
195    ///
196    /// let mut n = Number::new_from_u8(0xFF, ByteOrder::LittleEndian);
197    /// n <<= 4;
198    /// assert_eq!(n.value, [0xF0, 0x0F]);
199    /// n <<= 16;
200    /// assert_eq!(n.value, [0x00, 0x00, 0xF0, 0x0F]);
201    /// ```
202    #[inline]
203    fn shl_assign(&mut self, rhs: usize) {
204        if short_shl(self, rhs) {
205            // SAFETY: the vector holds at most 16 bytes, and the shift is below 128 bits.
206            let s = unsafe { small_shl(self, rhs) };
207            self.negative = s.negative;
208            put_small(&mut self.value, self.byte_order, s);
209            return;
210        }
211        shl_assign_long(self, rhs);
212    }
213}
214
215impl Shr<usize> for Number {
216    type Output = Number;
217
218    /// Returns `self / 2^rhs` rounded towards negative infinity, in the byte order of `self`,
219    /// in the shortest form, as `self >>= rhs` does.
220    ///
221    /// The result is built in the vector of `self`, which always has room for it unless it is
222    /// an empty vector without capacity; nothing is allocated then.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// use a::math::numbers::{ByteOrder, Number};
228    ///
229    /// let a = Number::new_from_u32(0x01_02_03, ByteOrder::BigEndian);
230    /// let pointer = a.value.as_ptr();
231    ///
232    /// // 0x01_02_03 >> 9 = 0x81, in the vector of `a`.
233    /// let shifted = a >> 9;
234    /// assert_eq!(shifted.value, [0x81]);
235    /// assert_eq!(shifted.value.as_ptr(), pointer);
236    /// ```
237    #[inline]
238    fn shr(mut self, rhs: usize) -> Number {
239        self >>= rhs;
240        self
241    }
242}
243
244impl Shr<usize> for &Number {
245    type Output = Number;
246
247    /// Returns `self / 2^rhs` rounded towards negative infinity, in the byte order of `self`,
248    /// in the shortest form.
249    ///
250    /// The result is built in one new vector of exactly its length (one byte for zero), the
251    /// only allocation; `self` is left as it was. It may have any sign and length, and need not
252    /// be in the shortest form.
253    ///
254    /// # Examples
255    ///
256    /// ```
257    /// use a::math::numbers::{ByteOrder, Number};
258    ///
259    /// // As for i32: -7 >> 1 = -4, 7 >> 1000 = 0 and -7 >> 1000 = -1.
260    /// let a = Number::new_from_i32(-7, ByteOrder::BigEndian);
261    /// let shifted = &a >> 1;
262    /// assert_eq!(shifted.value, [4]);
263    /// assert!(shifted.is_negative());
264    /// let shifted = &a >> 1000;
265    /// assert_eq!(shifted.value, [1]);
266    /// assert!(shifted.is_negative());
267    /// let b = Number::new_from_i32(7, ByteOrder::BigEndian);
268    /// assert_eq!((&b >> 1000).value, [0]);
269    /// ```
270    #[inline]
271    fn shr(self, rhs: usize) -> Number {
272        if self.value.len() <= SMALL {
273            // SAFETY: the vector holds at most 16 bytes.
274            let s = unsafe { small_shr(self, rhs) };
275            return small_number(self.byte_order, s);
276        }
277        shr_ref(self, rhs)
278    }
279}
280
281impl ShrAssign<usize> for Number {
282    /// Divides `self` by `2^rhs`, rounding towards negative infinity, keeping its byte order, in
283    /// the shortest form.
284    ///
285    /// The result is built in the vector of `self`, which always has room for it unless it is
286    /// an empty vector without capacity; nothing is allocated then.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// use a::math::numbers::{ByteOrder, Number};
292    ///
293    /// // -0x01_FF >> 1 = -0x01_00: the bit shifted out rounds the quotient down, which carries.
294    /// let mut n = Number::new_from_i32(-0x01FF, ByteOrder::LittleEndian);
295    /// n >>= 1;
296    /// assert_eq!(n.value, [0x00, 0x01]);
297    /// assert!(n.is_negative());
298    /// n >>= 9;
299    /// assert_eq!(n.value, [1]);
300    /// assert!(n.is_negative());
301    /// ```
302    #[inline]
303    fn shr_assign(&mut self, rhs: usize) {
304        if self.value.len() <= SMALL {
305            // SAFETY: the vector holds at most 16 bytes.
306            let s = unsafe { small_shr(self, rhs) };
307            self.negative = s.negative;
308            put_small(&mut self.value, self.byte_order, s);
309            return;
310        }
311        shr_assign_long(self, rhs);
312    }
313}
314
315// Small numbers
316
317/// The longest left shift, in bits, that the short path takes: a magnitude of 16 bytes shifted
318/// by less fits in 32.
319const SMALL_SHIFT: usize = 128;
320
321/// Whether `a << k` takes the short path: the vector holds at most [`SMALL`] bytes and `k` is
322/// below [`SMALL_SHIFT`].
323#[inline(always)]
324fn short_shl(a: &Number, k: usize) -> bool {
325    a.value.len() <= SMALL && k < SMALL_SHIFT
326}
327
328/// A result of the short path, as it computes it in registers.
329#[derive(Clone, Copy)]
330struct Small {
331    /// The 16 least significant bytes of the magnitude.
332    lo: u128,
333    /// The 16 bytes above them.
334    hi: u128,
335    /// The length of the result in the shortest form, from 1 to 32: one byte for zero.
336    len: usize,
337    /// Whether the result is negative; never for zero.
338    negative: bool,
339}
340
341/// `a << k` for a vector of at most 16 bytes and `k` below 128: the magnitude as 32 bytes.
342///
343/// The halves are shifted as `u64`s, by `k` or `k - 64` bits as `k` is below 64 or not, which
344/// is the same for every call with the same amount: two shifts and an `or` each, where a `u128`
345/// shift by any amount is a select on the amount besides.
346///
347/// # Safety
348///
349/// The vector of `a` must hold at most [`SMALL`] bytes, and `k` must be below 128.
350#[inline(always)]
351unsafe fn small_shl(a: &Number, k: usize) -> Small {
352    // SAFETY: as the caller guarantees.
353    let x = unsafe { read_small(&a.value, a.byte_order) };
354    let (x0, x1) = (x as u64, (x >> 64) as u64);
355    // `y >> (64 - s)` for `s` below 64, in two steps, so that `s = 0` moves every bit out.
356    let up = |y: u64, s: usize| (y >> 1) >> (63 - s);
357    let (l0, l1, h0, h1) = if k < 64 {
358        (x0 << k, x1 << k | up(x0, k), up(x1, k), 0)
359    } else {
360        let k = k - 64;
361        (0, x0 << k, x1 << k | up(x0, k), up(x1, k))
362    };
363    let bits = 128 - x.leading_zeros() as usize;
364    Small {
365        lo: u128::from(l0) | u128::from(l1) << 64,
366        hi: u128::from(h0) | u128::from(h1) << 64,
367        len: if x == 0 { 1 } else { (bits + k).div_ceil(8) },
368        negative: a.negative && x != 0,
369    }
370}
371
372/// `a >> k` for a vector of at most 16 bytes: the quotient, rounded down, in 16 bytes.
373///
374/// # Safety
375///
376/// The vector of `a` must hold at most [`SMALL`] bytes.
377#[inline(always)]
378unsafe fn small_shr(a: &Number, k: usize) -> Small {
379    // SAFETY: as the caller guarantees.
380    let x = unsafe { read_small(&a.value, a.byte_order) };
381    let negative = a.negative && x != 0;
382    // The quotient and the bits shifted out; every bit for a shift by 128 or more.
383    let (quotient, rest) = if k < 128 {
384        (x >> k, x & ((1 << k) - 1))
385    } else {
386        (0, x)
387    };
388    // A negative quotient is rounded down, away from zero, when a bit that is not zero is
389    // shifted out. It does not overflow: the quotient is below 2^127 when a bit is shifted out.
390    let magnitude = quotient + u128::from(negative && rest != 0);
391    Small {
392        lo: magnitude,
393        hi: 0,
394        len: SMALL - (magnitude | 1).leading_zeros() as usize / 8,
395        negative,
396    }
397}
398
399/// Writes the small result `s` over the first `s.len` bytes at `dst`, in the layout of `order`:
400/// up to 16 bytes as [`write_small`] writes a sum; from 17, the 16 least significant bytes whole
401/// and the ones above them, from 1 to 16, again as [`write_small`] writes them.
402///
403/// # Safety
404///
405/// `dst` must be valid for writing `s.len` bytes.
406#[inline(always)]
407unsafe fn write_small_result(dst: *mut u8, order: ByteOrder, s: Small) {
408    let len = s.len;
409    // SAFETY: every write lies inside the `len` bytes at `dst`: what `write_small` writes for
410    // `len <= 16`, and otherwise `[0, 16)` and the `len - 16` bytes after them, or big-endian
411    // the `len - 16` bytes before the last 16.
412    unsafe {
413        if len <= SMALL {
414            write_small(dst, order, s.lo as u64, (s.lo >> 64) as u64, len);
415            return;
416        }
417        let (h0, h1) = (s.hi as u64, (s.hi >> 64) as u64);
418        if order == ByteOrder::BigEndian {
419            write(dst.add(len - 16), s.lo.to_be_bytes());
420            write_small(dst, order, h0, h1, len - SMALL);
421        } else {
422            write(dst, s.lo.to_le_bytes());
423            write_small(dst.add(SMALL), order, h0, h1, len - SMALL);
424        }
425    }
426}
427
428/// Writes the small result `s` as the whole value of `v`, in its vector when it has room, in a
429/// new one otherwise.
430#[inline(always)]
431fn put_small(v: &mut Vec<u8>, order: ByteOrder, s: Small) {
432    if v.capacity() >= s.len {
433        // SAFETY: the vector has room for the `s.len` bytes, all of which are written before the
434        // length is set.
435        unsafe {
436            write_small_result(v.as_mut_ptr(), order, s);
437            v.set_len(s.len);
438        }
439    } else {
440        replace_small(v, order, s.lo, s.hi, s.len);
441    }
442}
443
444/// Replaces `v` with one new vector of exactly the small result's length, holding it, the result
445/// given by its fields. Out of line and cold, and called last, with its arguments in registers,
446/// so that the short path keeps no stack frame for it.
447#[cold]
448#[inline(never)]
449fn replace_small(v: &mut Vec<u8>, order: ByteOrder, lo: u128, hi: u128, len: usize) {
450    // The sign is the caller's to set; the bytes do not depend on it.
451    let s = Small {
452        lo,
453        hi,
454        len,
455        negative: false,
456    };
457    *v = new_small(order, s);
458}
459
460/// The small result `s` in one new vector of exactly its length.
461#[inline(always)]
462fn new_small(order: ByteOrder, s: Small) -> Vec<u8> {
463    let mut v = Vec::with_capacity(s.len);
464    // SAFETY: the new vector has room for the `s.len` bytes, all of which are written before the
465    // length is set.
466    unsafe {
467        write_small_result(v.as_mut_ptr(), order, s);
468        v.set_len(s.len);
469    }
470    v
471}
472
473/// The small result `s` as a number in one new vector, in the byte order `order`. Out of line,
474/// so that the short path of a borrowed operand saves no registers for the allocation.
475#[inline(never)]
476fn small_number(order: ByteOrder, s: Small) -> Number {
477    Number {
478        value: new_small(order, s),
479        negative: s.negative,
480        byte_order: order,
481    }
482}
483
484// The general path: out of line, so that the short path saves no registers for it.
485
486/// `&a << k` for the operands the short path leaves.
487#[inline(never)]
488fn shl_ref(a: &Number, k: usize) -> Number {
489    let value = match a.byte_order {
490        ByteOrder::BigEndian => shl_new::<true>(&a.value, k),
491        ByteOrder::LittleEndian => shl_new::<false>(&a.value, k),
492    };
493    let zero = matches!(value.as_slice(), [0]);
494    Number {
495        value,
496        negative: a.negative && !zero,
497        byte_order: a.byte_order,
498    }
499}
500
501/// `a <<= k` for the operands the short path leaves.
502#[inline(never)]
503fn shl_assign_long(a: &mut Number, k: usize) {
504    match a.byte_order {
505        ByteOrder::BigEndian => shl_in::<true>(a, k),
506        ByteOrder::LittleEndian => shl_in::<false>(a, k),
507    }
508}
509
510/// `&a >> k` for the operands the short path leaves.
511#[inline(never)]
512fn shr_ref(a: &Number, k: usize) -> Number {
513    if k / 8 >= a.value.len() {
514        let negative = shifted_away(a);
515        return Number {
516            value: vec![u8::from(negative)],
517            negative,
518            byte_order: a.byte_order,
519        };
520    }
521    let (value, negative) = match a.byte_order {
522        ByteOrder::BigEndian => shr_new::<true>(&a.value, a.negative, k),
523        ByteOrder::LittleEndian => shr_new::<false>(&a.value, a.negative, k),
524    };
525    Number {
526        value,
527        negative,
528        byte_order: a.byte_order,
529    }
530}
531
532/// `a >>= k` for the operands the short path leaves.
533#[inline(never)]
534fn shr_assign_long(a: &mut Number, k: usize) {
535    if k / 8 >= a.value.len() {
536        a.negative = shifted_away(a);
537        // SAFETY: the vector holds more than 16 bytes, and has room for the one, written before
538        // the length is set.
539        unsafe {
540            *a.value.as_mut_ptr() = u8::from(a.negative);
541            a.value.set_len(1);
542        }
543        return;
544    }
545    a.negative = match a.byte_order {
546        ByteOrder::BigEndian => shr_in::<true>(&mut a.value, a.negative, k),
547        ByteOrder::LittleEndian => shr_in::<false>(&mut a.value, a.negative, k),
548    };
549}
550
551/// Whether `a >> k` is -1 when the shift moves out every byte of the vector of `a`, and not 0:
552/// whether `a` is negative and not zero. Its first byte decides for a number in the shortest
553/// form, in either byte order.
554#[inline(always)]
555fn shifted_away(a: &Number) -> bool {
556    a.negative && a.value.iter().any(|&b| b != 0)
557}
558
559/// Makes `v` zero, `[0]`: in its vector when it has room for the byte, and otherwise in one new
560/// vector of one byte. Out of line and cold.
561#[cold]
562#[inline(never)]
563fn set_zero(v: &mut Vec<u8>) {
564    if v.capacity() == 0 {
565        *v = vec![0];
566    } else {
567        v.clear();
568        v.push(0);
569    }
570}
571
572// Left shifts
573
574/// The magnitude `x << k`, planned: `x` has `l` significant bytes, not zero, and the result
575/// `len` bytes, its bytes at positions `q..len` and zeros below them.
576#[derive(Clone, Copy)]
577struct Left {
578    /// The significant length of `x`.
579    l: usize,
580    /// The whole bytes of the shift.
581    q: usize,
582    /// The bits of the shift besides them, below 8.
583    r: u32,
584    /// The length of the result: `l + q`, and one more when the top `r` bits of the top byte
585    /// are not all zero.
586    len: usize,
587}
588
589impl Left {
590    /// Plans the shift by `k` of the magnitude of `l` significant bytes, not zero, whose most
591    /// significant byte is `top`.
592    ///
593    /// The length cannot overflow: `l` is at most `isize::MAX`, a vector's length, and `q` at
594    /// most `usize::MAX / 8`, so `l + q + 1` stays below `usize::MAX`. It may exceed what can be
595    /// allocated, which the allocation reports.
596    #[inline(always)]
597    fn plan(l: usize, top: u8, k: usize) -> Left {
598        let (q, r) = (k / 8, (k % 8) as u32);
599        let extra = (u32::from(top) << r) >> 8 != 0;
600        Left {
601            l,
602            q,
603            r,
604            len: l + q + usize::from(extra),
605        }
606    }
607}
608
609/// The significant length of the magnitude in `v` in the layout `BE` and its most significant
610/// byte, which is zero only for zero: one read when the vector's most significant byte is not
611/// zero, as in the shortest form, and otherwise as [`significant_len`] finds it.
612#[inline(always)]
613fn top_of<const BE: bool>(v: &[u8]) -> (usize, u8) {
614    let most = if BE { v.first() } else { v.last() };
615    match most {
616        Some(&top) if top != 0 => (v.len(), top),
617        _ => {
618            let l = significant_len::<BE>(v);
619            // SAFETY: position `l - 1` is a significant byte when `l > 0`.
620            let top = if l == 0 {
621                0
622            } else {
623                unsafe { get::<BE>(end::<BE>(v), l - 1) }
624            };
625            (l, top)
626        }
627    }
628}
629
630/// `x << k` for the magnitude `x` in the bytes of `v` in the layout `BE`, in one new vector of
631/// exactly its length.
632#[inline(always)]
633fn shl_new<const BE: bool>(v: &[u8], k: usize) -> Vec<u8> {
634    let (l, top) = top_of::<BE>(v);
635    if l == 0 {
636        return vec![0];
637    }
638    // SAFETY: `end` is the least significant end of `v`, of `l` significant bytes.
639    unsafe { shl_from::<BE>(end::<BE>(v), Left::plan(l, top, k)) }
640}
641
642/// `x << k`, planned as `plan`, in one new vector of exactly its length, for the magnitude `x`
643/// at the least significant end `src` in the layout `BE`.
644///
645/// # Safety
646///
647/// The `plan.l` significant bytes at `src` must be valid for reads.
648#[inline(never)]
649unsafe fn shl_from<const BE: bool>(src: *const u8, plan: Left) -> Vec<u8> {
650    let mut out = allocate(plan.len);
651    let dst = out.as_mut_ptr();
652    // SAFETY: the new vector has room for the result, whose bytes are all written before the
653    // length is set, apart from `x`.
654    unsafe {
655        shl_into::<BE>(if BE { dst.add(plan.len) } else { dst }, src, plan);
656        out.set_len(plan.len);
657    }
658    out
659}
660
661/// `a <<= k` for the magnitude of `a` in the layout `BE`, in the vector of `a` when its capacity
662/// has room for the result, and otherwise in one new vector of exactly its length, which replaces
663/// it.
664///
665/// Every call it makes is its last step, with its arguments in registers, so that a shift of bits
666/// in place keeps no stack frame and saves no registers: zero, a new vector, and a shift of whole
667/// bytes out of line, and the zeros below a long result by `memset`. The vector's length is set
668/// first, as nothing reads it before the bytes are written.
669#[inline(always)]
670fn shl_in<const BE: bool>(a: &mut Number, k: usize) {
671    if a.value.len() <= MEDIUM && k < 64 {
672        // SAFETY: the vector holds 17 to 32 bytes, as the short path leaves the shorter ones.
673        return unsafe { medium_shl::<BE>(a, k) };
674    }
675    let v = &mut a.value;
676    let (l, top) = top_of::<BE>(v);
677    if l == 0 {
678        a.negative = false;
679        return set_zero(v);
680    }
681    let (len, capacity) = (v.len(), v.capacity());
682    let plan = Left::plan(l, top, k);
683    if capacity < plan.len {
684        return shl_grow::<BE>(v, plan.l, plan.q, plan.r, plan.len);
685    }
686    let p = v.as_mut_ptr();
687    // SAFETY: the `len` bytes at `p` are the vector's, of `l` significant bytes, and its capacity
688    // has room for the result, whose bytes are all written before the vector is read again.
689    // Big-endian, the input ends at `p + len` and the result at `p + plan.len`, as their least
690    // significant bytes come last, and the result ends at most one byte further: `plan.len` is
691    // `l + q` or one more, and its bytes from position `q` up are `l` or one more.
692    unsafe {
693        let src: *const u8 = if BE { p.add(len) } else { p };
694        let dst = if BE { p.add(plan.len) } else { p };
695        v.set_len(plan.len);
696        if plan.r == 0 {
697            return shl_bytes::<BE>(dst, src, plan.l, plan.q);
698        }
699        shl_bits_into::<BE>(dst, src, plan);
700    }
701}
702
703/// The longest vector, in bytes, whose left shift by fewer than 64 bits [`shl_in`] computes in
704/// registers.
705const MEDIUM: usize = 32;
706
707/// `a <<= k` for a vector of 17 to 32 bytes and `k` below 64, in registers: the magnitude read
708/// as four limbs, as the short path reads two, shifted into five, and the result, at most 40
709/// bytes, written as sixteen, sixteen and the rest, or fewer. Measured on an Apple M4 Max, `<<=`
710/// by 13 bits of 17 to 32 bytes took 10 to 13 cycles so, against 16 to 17 by the kernels, whose
711/// cost for one or two blocks is in their edges.
712///
713/// # Safety
714///
715/// The vector of `a` must hold 17 to 32 bytes, and `k` must be below 64.
716#[inline(always)]
717unsafe fn medium_shl<const BE: bool>(a: &mut Number, k: usize) {
718    let v = &mut a.value;
719    let (p, n) = (v.as_ptr(), v.len());
720    // SAFETY: the 16 bytes at the least significant end and the `n - 16` from 1 to 16 above them
721    // lie in the vector.
722    let (lo, hi) = unsafe {
723        let above = core::slice::from_raw_parts(if BE { p } else { p.add(16) }, n - 16);
724        if BE {
725            (
726                u128::from_be_bytes(read(p.add(n - 16))),
727                read_small(above, ByteOrder::BigEndian),
728            )
729        } else {
730            (
731                u128::from_le_bytes(read(p)),
732                read_small(above, ByteOrder::LittleEndian),
733            )
734        }
735    };
736    let bits = if hi != 0 {
737        256 - hi.leading_zeros()
738    } else {
739        128 - lo.leading_zeros()
740    } as usize;
741    if bits == 0 {
742        a.negative = false;
743        return set_zero(v);
744    }
745    let len = (bits + k).div_ceil(8);
746    let (x0, x1, x2, x3) = (lo as u64, (lo >> 64) as u64, hi as u64, (hi >> 64) as u64);
747    // `y >> (64 - k)` in two steps, so that `k = 0` moves every bit out.
748    let up = |y: u64| (y >> 1) >> (63 - k);
749    let y = [
750        x0 << k,
751        x1 << k | up(x0),
752        x2 << k | up(x1),
753        x3 << k | up(x2),
754        up(x3),
755    ];
756    if v.capacity() < len {
757        return medium_grow::<BE>(v, y[0], y[1], y[2], y[3], y[4], len);
758    }
759    // SAFETY: the vector has room for the `len` bytes, all of which are written before it is
760    // read again.
761    unsafe {
762        v.set_len(len);
763        write_medium::<BE>(v.as_mut_ptr(), y, len);
764    }
765}
766
767/// [`medium_shl`] for a vector whose capacity has no room for the result, the limbs `y0` to `y4` of
768/// `len` bytes: one new vector of exactly that length replaces it. Out of line and cold, and its
769/// arguments in registers, so that the caller keeps no stack frame for it.
770#[cold]
771#[inline(never)]
772fn medium_grow<const BE: bool>(
773    v: &mut Vec<u8>,
774    y0: u64,
775    y1: u64,
776    y2: u64,
777    y3: u64,
778    y4: u64,
779    len: usize,
780) {
781    let y = [y0, y1, y2, y3, y4];
782    let mut out = allocate(len);
783    // SAFETY: the new vector has room for the `len` bytes, all of which are written before the
784    // length is set.
785    unsafe {
786        write_medium::<BE>(out.as_mut_ptr(), y, len);
787        out.set_len(len);
788    }
789    *v = out;
790}
791
792/// Writes the `len` bytes of the limbs `y`, least significant first, at `dst` in the layout `BE`:
793/// up to 16 as the addition writes a short sum, and otherwise the low 16 whole and the bytes
794/// above them, up to 16 again as a short sum or 16 whole and up to 8 more.
795///
796/// # Safety
797///
798/// `len` must be from 1 to 40 and hold the significant bytes of `y`, and `dst` be valid for
799/// writing `len` bytes.
800#[inline(always)]
801unsafe fn write_medium<const BE: bool>(dst: *mut u8, y: [u64; 5], len: usize) {
802    let order = order::<BE>();
803    let pair = |l: u64, h: u64| u128::from(l) | u128::from(h) << 64;
804    // SAFETY: as the caller guarantees: positions `0..16`, `16..32` and the rest, each written
805    // in its place in the layout.
806    unsafe {
807        if len <= SMALL {
808            return write_small(dst, order, y[0], y[1], len);
809        }
810        let low = pair(y[0], y[1]);
811        if BE {
812            write(dst.add(len - 16), low.to_be_bytes());
813        } else {
814            write(dst, low.to_le_bytes());
815        }
816        let rest = len - SMALL;
817        if rest <= SMALL {
818            let at = if BE { dst } else { dst.add(SMALL) };
819            return write_small(at, order, y[2], y[3], rest);
820        }
821        let middle = pair(y[2], y[3]);
822        if BE {
823            write(dst.add(len - 32), middle.to_be_bytes());
824            write_small(dst, order, y[4], 0, len - 32);
825        } else {
826            write(dst.add(SMALL), middle.to_le_bytes());
827            write_small(dst.add(32), order, y[4], 0, len - 32);
828        }
829    }
830}
831
832/// [`shl_in`] for a vector whose capacity has no room for the result: one new vector of exactly
833/// its length, planned as the fields of a [`Left`], replaces it. Out of line and cold.
834#[cold]
835#[inline(never)]
836fn shl_grow<const BE: bool>(v: &mut Vec<u8>, l: usize, q: usize, r: u32, len: usize) {
837    let src: *const u8 = end::<BE>(v);
838    // SAFETY: `src` is the least significant end of `v`, of `l` significant bytes.
839    *v = unsafe { shl_from::<BE>(src, Left { l, q, r, len }) };
840}
841
842/// [`shl_into`] for a shift of whole bytes, `x << 8q` of `l` bytes: out of line, as its moves
843/// and zeros of more than 64 bytes call `memmove` and `memset`.
844///
845/// # Safety
846///
847/// As for [`shl_into`].
848#[inline(never)]
849unsafe fn shl_bytes<const BE: bool>(dst: *mut u8, src: *const u8, l: usize, q: usize) {
850    // SAFETY: as the caller guarantees.
851    unsafe {
852        shl_into::<BE>(
853            dst,
854            src,
855            Left {
856                l,
857                q,
858                r: 0,
859                len: l + q,
860            },
861        )
862    }
863}
864
865/// Writes `x << k`, planned as `plan`, at the least significant end `dst` in the layout `BE`,
866/// from the magnitude `x` at the least significant end `src` in the same layout, which may be
867/// in the same vector.
868///
869/// The bytes are written from the most significant down, each group of eight read before a
870/// write reaches it: the result's bytes lie at or above the positions of the bytes they come
871/// from, little-endian at higher addresses; big-endian the result ends at most one byte further
872/// than the input, and its groups of eight are written over bytes of the input that have been
873/// read.
874///
875/// # Safety
876///
877/// The `plan.l` significant bytes at `src` must be valid for reads and the `plan.len` bytes at
878/// `dst` for writes. If they overlap, `dst` must be `src` little-endian, and big-endian at most
879/// `src + 1`.
880#[inline(always)]
881unsafe fn shl_into<const BE: bool>(dst: *mut u8, src: *const u8, plan: Left) {
882    let Left { l, q, r, .. } = plan;
883    // SAFETY: every position read is below `l` and every position written below `len`; the
884    // order of the accesses is as described above.
885    unsafe {
886        if r == 0 {
887            // Whole bytes: a move of the magnitude, then the zeros below it. Big-endian in place
888            // the magnitude stays where it is, unless it has zero bytes above it.
889            let (from, to) = (at::<BE>(src, 0, l), at_mut::<BE>(dst, q, l));
890            if !ptr::eq(from, to) {
891                move_bytes(to, from, l);
892            }
893            zero::<BE>(dst, q);
894        } else {
895            shl_bits_into::<BE>(dst, src, plan);
896        }
897    }
898}
899
900/// [`shl_into`] for a shift with bits, `r` from 1 to 7: the zeros below the result last.
901///
902/// # Safety
903///
904/// As for [`shl_into`].
905#[inline(always)]
906unsafe fn shl_bits_into<const BE: bool>(dst: *mut u8, src: *const u8, plan: Left) {
907    let Left { l, q, r, len } = plan;
908    // SAFETY: as for `shl_into`.
909    unsafe {
910        if l < SMALL {
911            // Up to 15 bytes, shifted in a register, which they fill with the bits out of the
912            // top. They are all read before any is written.
913            let x = read_small(slice::<BE>(src, 0, l), order::<BE>()) << r;
914            let n = len - q;
915            write_small(
916                at_mut::<BE>(dst, q, n),
917                order::<BE>(),
918                x as u64,
919                (x >> 64) as u64,
920                n,
921            );
922        } else {
923            // The result's bytes at positions `q + l - 1` and `q + l`: the top byte shifted, with
924            // the bits of the byte below it, and the bits shifted out of the top. Read before
925            // the kernel writes over them in place.
926            let (top, below) = (get::<BE>(src, l - 1), get::<BE>(src, l - 2));
927            let high = (top << r) | (below >> (8 - r));
928            let out = top >> (8 - r);
929            kernels::shl_bits::<BE>(dst, src, l, q, r);
930            // The bits out of the top go to position `q + l` when they are not all zero, and
931            // otherwise position `q + l - 1` gets its own byte again, so that no branch decides
932            // on them: for random numbers they are a coin toss for some shifts.
933            let extra = out != 0;
934            set::<BE>(
935                dst,
936                q + l - 1 + usize::from(extra),
937                select_unpredictable(extra, out, high),
938            );
939        }
940        zero::<BE>(dst, q);
941    }
942}
943
944// Right shifts
945
946/// The magnitude `x >> k` of a number of `l` significant bytes, rounded down when it is
947/// negative, planned for the quotients that [`short_right`] leaves out of the registers.
948#[derive(Clone, Copy)]
949struct Right {
950    /// The significant length of `x`.
951    l: usize,
952    /// The whole bytes of the shift.
953    q: usize,
954    /// The bits of the shift besides them, below 8.
955    r: u32,
956    /// The length of `x >> k`, not rounded: `l - q`, or one fewer when the top byte shifted by
957    /// `r` bits is zero. At least 16.
958    len: usize,
959    /// Whether one is added to `x >> k`: the number is negative and a bit shifted out is not
960    /// zero.
961    round: bool,
962}
963
964impl Right {
965    /// Plans the shift by `k` of the magnitude of `l` significant bytes at the least
966    /// significant end `src` in the layout `BE`, whose most significant byte is `top`,
967    /// `negative` if the number is, for which [`short_right`] does not hold.
968    ///
969    /// # Safety
970    ///
971    /// The `l` significant bytes at `src` must be valid for reads.
972    #[inline(always)]
973    unsafe fn plan<const BE: bool>(
974        src: *const u8,
975        l: usize,
976        top: u8,
977        k: usize,
978        negative: bool,
979    ) -> Right {
980        let (q, r) = (k / 8, (k % 8) as u32);
981        // SAFETY: `q < l`, as `short_right` does not hold.
982        unsafe {
983            Right {
984                l,
985                q,
986                r,
987                len: l - q - usize::from(top >> r == 0),
988                round: negative && shifted_out::<BE>(src, l, q, r),
989            }
990        }
991    }
992}
993
994/// Whether `x >> k`, for `x` of `l` significant bytes, is computed in registers: the bytes from
995/// position `k / 8` up are at most 16. Longer quotients go to the kernels, which beat two
996/// registers of 128 bits from 17 bytes up.
997#[inline(always)]
998fn short_right(l: usize, k: usize) -> bool {
999    l.saturating_sub(k / 8) <= SMALL
1000}
1001
1002/// The magnitude `x >> k`, where `x` has `l` significant bytes at the least significant end
1003/// `src` in the layout `BE`, with the sign `negative`, when [`short_right`] says so: the
1004/// quotient, rounded down, in registers.
1005///
1006/// # Safety
1007///
1008/// The `l` significant bytes at `src` must be valid for reads, and `short_right(l, k)` must hold.
1009#[inline(always)]
1010unsafe fn short_quotient<const BE: bool>(
1011    src: *const u8,
1012    l: usize,
1013    k: usize,
1014    negative: bool,
1015) -> Small {
1016    let (q, r) = (k / 8, (k % 8) as u32);
1017    let negative = negative && l != 0;
1018    // SAFETY: positions `q..l`, at most 16, are significant bytes, and so are the positions below
1019    // `q` that `shifted_out` reads when `q < l`.
1020    let (x, round) = unsafe {
1021        if q < l {
1022            let x = read_small(slice::<BE>(src, q, l - q), order::<BE>());
1023            (x, negative && shifted_out::<BE>(src, l, q, r))
1024        } else {
1025            (0, negative)
1026        }
1027    };
1028    // Rounded down, 16 bytes of 0xFF shifted by whole bytes carry into a 17th.
1029    let (magnitude, carry) = (x >> r).overflowing_add(u128::from(round));
1030    Small {
1031        lo: magnitude,
1032        hi: u128::from(carry),
1033        len: if carry {
1034            SMALL + 1
1035        } else {
1036            SMALL - (magnitude | 1).leading_zeros() as usize / 8
1037        },
1038        negative,
1039    }
1040}
1041
1042/// `&x >> k` for the magnitude `x` in the bytes of `v` in the layout `BE` with the sign
1043/// `negative`, in one new vector of exactly its length; returns it and the sign of the result.
1044#[inline(always)]
1045fn shr_new<const BE: bool>(v: &[u8], negative: bool, k: usize) -> (Vec<u8>, bool) {
1046    let (l, top) = top_of::<BE>(v);
1047    let src = end::<BE>(v);
1048    // SAFETY: `src` is the least significant end of `v`, of `l` significant bytes.
1049    unsafe {
1050        if short_right(l, k) {
1051            let s = short_quotient::<BE>(src, l, k, negative);
1052            return (new_small(order::<BE>(), s), s.negative);
1053        }
1054        let plan = Right::plan::<BE>(src, l, top, k, negative);
1055        // Rounded down, the quotient is one byte longer when all its bytes are 0xFF. Whether it
1056        // is rounded is a coin toss when few bits are shifted out, and whether its bytes are all
1057        // 0xFF is not, for random numbers: that is asked first.
1058        let carry = negative && all_ones::<BE>(src, plan) && plan.round;
1059        let len = plan.len + usize::from(carry);
1060        let mut out = Vec::<u8>::with_capacity(len);
1061        let dst = out.as_mut_ptr();
1062        let dst = if BE { dst.add(len) } else { dst };
1063        if carry {
1064            ptr::write_bytes(at_mut::<BE>(dst, 0, len), 0, len);
1065            set::<BE>(dst, plan.len, 1);
1066        } else {
1067            shr_into::<BE>(dst, src, plan);
1068            if negative {
1069                // Without a branch on the rounding, a coin toss when few bits are shifted out.
1070                round_up::<BE>(dst, plan.len, quotient_low::<BE>(src, plan), plan.round);
1071            }
1072        }
1073        out.set_len(len);
1074        (out, negative)
1075    }
1076}
1077
1078/// `x >>= k` for the magnitude `x` in `v` in the layout `BE` with the sign `negative`, in the
1079/// vector of `v`; returns the sign of the result.
1080#[inline(always)]
1081fn shr_in<const BE: bool>(v: &mut Vec<u8>, negative: bool, k: usize) -> bool {
1082    let (l, top) = top_of::<BE>(v);
1083    let len = v.len();
1084    let p = v.as_mut_ptr();
1085    // SAFETY: the `len` bytes at `p` are the vector's, of `l` significant bytes; the result is
1086    // at most `l` bytes long, one for zero, which the vector has room for unless it has no
1087    // capacity, which `put_small` sees to.
1088    unsafe {
1089        let src: *const u8 = if BE { p.add(len) } else { p };
1090        if short_right(l, k) {
1091            let s = short_quotient::<BE>(src, l, k, negative);
1092            put_small(v, order::<BE>(), s);
1093            return s.negative;
1094        }
1095        let plan = Right::plan::<BE>(src, l, top, k, negative);
1096        // Big-endian, the result starts at the start of the vector, and is written from its
1097        // least significant byte up, at the end; a group of eight is read at most eight
1098        // positions before it is written, which keeps every group read before it is written
1099        // over when the input ends where the vector does. Zero bytes above the most significant
1100        // one move the input's end away, and the significant bytes are moved to the start of
1101        // the vector first.
1102        let src = if BE && len != l {
1103            ptr::copy(p.add(len - l), p, l);
1104            p.add(l)
1105        } else {
1106            src
1107        };
1108        let dst = if BE { p.add(plan.len) } else { p };
1109        // The quotient's eight least significant bytes, read before they are written over. For
1110        // a negative number, whether it is rounded down is a coin toss when few bits are shifted
1111        // out, so the one is added without a branch, a zero when it is not rounded.
1112        let low = if negative {
1113            quotient_low::<BE>(src, plan)
1114        } else {
1115            0
1116        };
1117        shr_into::<BE>(dst, src, plan);
1118        let mut n = plan.len;
1119        if negative && round_up::<BE>(dst, n, low, plan.round) {
1120            // Every byte was 0xFF and is now zero: the quotient is 256^n, one byte longer, which
1121            // the vector has room for (it is at most `l - q + 1` bytes, `q >= 1` when the top
1122            // byte is 0xFF after the shift).
1123            n += 1;
1124            if BE {
1125                *p.add(n - 1) = 0;
1126                *p = 1;
1127            } else {
1128                *p.add(n - 1) = 1;
1129            }
1130        }
1131        v.set_len(n);
1132    }
1133    negative && l != 0
1134}
1135
1136/// Writes the `plan.len` bytes of `x >> k`, not rounded, at the least significant end `dst` in
1137/// the layout `BE`, from the magnitude `x` at the least significant end `src` in the same
1138/// layout, which may be in the same vector.
1139///
1140/// The bytes are written from the least significant up, each group of eight read before a write
1141/// reaches it: the result's bytes lie at or below the positions of the bytes they come from,
1142/// little-endian at lower addresses; big-endian the input ends at the end of the vector and the
1143/// result `q` or `q + 1` bytes before.
1144///
1145/// # Safety
1146///
1147/// The `plan.l` significant bytes at `src` must be valid for reads and the `plan.len` bytes at
1148/// `dst` for writes. If they overlap, `dst` must be `src` little-endian, and big-endian
1149/// `src - plan.l + plan.len`, with the input's significant bytes at the start of the vector.
1150#[inline(always)]
1151unsafe fn shr_into<const BE: bool>(dst: *mut u8, src: *const u8, plan: Right) {
1152    let Right { l, q, r, len, .. } = plan;
1153    // SAFETY: as the caller guarantees.
1154    unsafe {
1155        if r == 0 {
1156            let (from, to) = (at::<BE>(src, q, len), at_mut::<BE>(dst, 0, len));
1157            // Big-endian in place, a shift by whole bytes leaves the quotient where it is.
1158            if !ptr::eq(from, to) {
1159                move_bytes(to, from, len);
1160            }
1161        } else {
1162            // The byte above the top of the quotient, position `q + len`: the top byte of `x`
1163            // when the shift leaves nothing of it, and above `x` otherwise. Chosen without a
1164            // branch, as for random numbers it is a coin toss for some shifts.
1165            let top = get::<BE>(src, l - 1);
1166            let above = top & 0u8.wrapping_sub(u8::from(q + len < l));
1167            kernels::shr_bits::<BE>(dst, src, l, q, r, len, above);
1168        }
1169    }
1170}
1171
1172/// Whether a bit shifted out by `>> (8q + r)` is not zero: one of positions `0..q`, or of the
1173/// `r` low bits of position `q`, of the magnitude of `l > q` significant bytes at the least
1174/// significant end `src`. Eight positions at a time, so that it stops after one read for
1175/// random numbers.
1176///
1177/// # Safety
1178///
1179/// The `l` significant bytes at `src` must be valid for reads, and `q < l`.
1180#[inline(always)]
1181unsafe fn shifted_out<const BE: bool>(src: *const u8, l: usize, q: usize, r: u32) -> bool {
1182    let mut p = 0;
1183    // SAFETY: every read is of positions below `l`: `p + 8 <= q < l`, then `p + 8 <= l`, then
1184    // positions up to `q`.
1185    unsafe {
1186        while q - p >= 8 {
1187            if load::<BE>(src, p) != 0 {
1188                return true;
1189            }
1190            p += 8;
1191        }
1192        if l - p >= 8 {
1193            // The fewer than eight positions left and the `r` bits, in one group: below 64 bits.
1194            let bits = 8 * (q - p) as u32 + r;
1195            return load::<BE>(src, p) & ((1 << bits) - 1) != 0;
1196        }
1197        while p < q {
1198            if get::<BE>(src, p) != 0 {
1199                return true;
1200            }
1201            p += 1;
1202        }
1203        get::<BE>(src, q) & ((1 << r) - 1) != 0
1204    }
1205}
1206
1207/// Whether the `plan.len` bytes of `x >> k`, before it is rounded, are all 0xFF, for the
1208/// magnitude `x` at the least significant end `src` in the layout `BE`: then the rounded
1209/// quotient is one byte longer. For random numbers it stops after the first group of eight.
1210///
1211/// # Safety
1212///
1213/// The `plan.l` significant bytes at `src` must be valid for reads.
1214unsafe fn all_ones<const BE: bool>(src: *const u8, plan: Right) -> bool {
1215    let Right { l, q, r, len, .. } = plan;
1216    // The byte of the quotient at position `p`; the bits from above the magnitude are zero.
1217    // SAFETY: positions `q + p` and `q + p + 1` are read only below `l`.
1218    let byte = |p: usize| unsafe {
1219        let above = if q + p + 1 < l {
1220            get::<BE>(src, q + p + 1)
1221        } else {
1222            0
1223        };
1224        ((u16::from(get::<BE>(src, q + p)) | (u16::from(above) << 8)) >> r) as u8
1225    };
1226    let mut p = 0;
1227    // SAFETY: positions `q + p..q + p + 8` lie below `q + len <= l`.
1228    unsafe {
1229        while p + 8 <= len && q + p + 8 < l {
1230            let above = u64::from(get::<BE>(src, q + p + 8));
1231            // `<< (64 - r)` in two steps: for `r == 0` every bit moves out.
1232            let v = (load::<BE>(src, q + p) >> r) | ((above << 1) << (63 - r));
1233            if v != u64::MAX {
1234                return false;
1235            }
1236            p += 8;
1237        }
1238    }
1239    (p..len).all(|p| byte(p) == 0xFF)
1240}
1241
1242/// Positions `0..8` of `x >> k`, not rounded, for the magnitude `x` at the least significant end
1243/// `src` in the layout `BE`, planned as `plan`: from positions `q..q + 9` of `x`, all below `l`
1244/// as the quotient is at least 16 bytes long.
1245///
1246/// # Safety
1247///
1248/// The `plan.l` significant bytes at `src` must be valid for reads.
1249#[inline(always)]
1250unsafe fn quotient_low<const BE: bool>(src: *const u8, plan: Right) -> u64 {
1251    let Right { q, r, .. } = plan;
1252    // SAFETY: `q + 9 <= l`, as the quotient's `l - q` or `l - q - 1` bytes are at least 16.
1253    unsafe {
1254        let above = u64::from(get::<BE>(src, q + 8));
1255        // `<< (64 - r)` in two steps: for `r == 0` every bit moves out.
1256        (load::<BE>(src, q) >> r) | ((above << 1) << (63 - r))
1257    }
1258}
1259
1260/// Adds `round` (one or zero) to the quotient of `n >= 16` bytes at the least significant end
1261/// `dst` in the layout `BE`, whose eight least significant bytes were `low` when they were
1262/// written: they are written again plus `round`, and only when that carries are the bytes above
1263/// read and carried into, which a random number does not need. Reading back the bytes just
1264/// written would wait for the stores of the kernel, which the core cannot forward to a load of
1265/// another width or place. Returns whether it carries out of the top, all bytes then zero.
1266///
1267/// # Safety
1268///
1269/// The `n` bytes must be valid for reads and writes, and positions `0..8` hold `low`.
1270#[inline(always)]
1271unsafe fn round_up<const BE: bool>(dst: *mut u8, n: usize, low: u64, round: bool) -> bool {
1272    let (sum, carry) = low.overflowing_add(u64::from(round));
1273    // SAFETY: as the caller guarantees.
1274    unsafe {
1275        store::<BE>(dst, 0, sum);
1276        carry && increment::<BE>(dst, 8, n)
1277    }
1278}
1279
1280/// Adds one to positions `p..n` of the magnitude at the least significant end `dst` in the
1281/// layout `BE`, eight bytes at a time while the carry goes on; returns whether it carries out of
1282/// the top, all those bytes then zero. Out of line and cold: it runs only when the eight bytes
1283/// below carry out, all 0xFF.
1284///
1285/// # Safety
1286///
1287/// The bytes must be valid for reads and writes.
1288#[cold]
1289#[inline(never)]
1290unsafe fn increment<const BE: bool>(dst: *mut u8, mut p: usize, n: usize) -> bool {
1291    // SAFETY: every access is of positions below `n`.
1292    unsafe {
1293        while n - p >= 8 {
1294            let v = load::<BE>(dst, p).wrapping_add(1);
1295            store::<BE>(dst, p, v);
1296            if v != 0 {
1297                return false;
1298            }
1299            p += 8;
1300        }
1301        while p < n {
1302            let v = get::<BE>(dst, p).wrapping_add(1);
1303            set::<BE>(dst, p, v);
1304            if v != 0 {
1305                return false;
1306            }
1307            p += 1;
1308        }
1309    }
1310    true
1311}
1312
1313// Memory
1314
1315/// One new vector of capacity `len`, empty, `len > 0`.
1316///
1317/// # Panics
1318///
1319/// When it cannot be allocated, rather than aborting as a failed allocation does otherwise: a
1320/// left shift can ask for any length, and a shift too long for the memory is a mistake of the
1321/// caller's, not a lack of memory.
1322fn allocate(len: usize) -> Vec<u8> {
1323    let Ok(layout) = Layout::array::<u8>(len) else {
1324        too_long(len)
1325    };
1326    // SAFETY: the layout is not empty, as `len > 0`.
1327    let p = unsafe { alloc(layout) };
1328    if p.is_null() {
1329        too_long(len);
1330    }
1331    // SAFETY: `p` was allocated by the global allocator with the layout of `len` bytes, which is
1332    // the capacity given, and the vector is empty.
1333    unsafe { Vec::from_raw_parts(p, 0, len) }
1334}
1335
1336/// Panics for a left shift whose result of `len` bytes cannot be allocated.
1337#[cold]
1338#[inline(never)]
1339fn too_long(len: usize) -> ! {
1340    panic!("a shifted number of {len} bytes cannot be allocated")
1341}
1342
1343/// Writes zeros over positions `0..q` at the least significant end `dst` in the layout `BE`.
1344///
1345/// # Safety
1346///
1347/// The `q` bytes must be valid for writes.
1348#[inline(always)]
1349unsafe fn zero<const BE: bool>(dst: *mut u8, q: usize) {
1350    // SAFETY: as the caller guarantees.
1351    unsafe { zero_bytes(at_mut::<BE>(dst, 0, q), q) };
1352}
1353
1354/// Writes zeros over the `n` bytes at `dst`: up to 64 bytes inline, in stores of 16 bytes or
1355/// fewer that overlap, and with `memset` beyond, whose call costs more than a short run of
1356/// zeros.
1357///
1358/// # Safety
1359///
1360/// The `n` bytes must be valid for writes.
1361#[inline(always)]
1362unsafe fn zero_bytes(dst: *mut u8, n: usize) {
1363    // SAFETY: every write lies in the `n` bytes at `dst`.
1364    unsafe {
1365        if n == 0 {
1366            // Shifts by fewer than eight bits, first.
1367        } else if n > 64 {
1368            ptr::write_bytes(dst, 0, n);
1369        } else if n >= 16 {
1370            write(dst, [0u8; 16]);
1371            write(dst.add(n - 16), [0u8; 16]);
1372            if n > 32 {
1373                write(dst.add(16), [0u8; 16]);
1374                write(dst.add(n - 32), [0u8; 16]);
1375            }
1376        } else if n >= 8 {
1377            write(dst, [0u8; 8]);
1378            write(dst.add(n - 8), [0u8; 8]);
1379        } else if n >= 4 {
1380            write(dst, [0u8; 4]);
1381            write(dst.add(n - 4), [0u8; 4]);
1382        } else {
1383            *dst = 0;
1384            *dst.add(n / 2) = 0;
1385            *dst.add(n - 1) = 0;
1386        }
1387    }
1388}
1389
1390/// Copies the `n` bytes at `src` to `dst`, which may overlap them: up to 64 bytes inline, every
1391/// byte read before any is written (the reads and the writes overlap where the length is not a
1392/// multiple of their width, and agree there), and with `memmove` beyond.
1393///
1394/// # Safety
1395///
1396/// The `n` bytes at `src` must be valid for reads and the `n` at `dst` for writes.
1397#[inline(always)]
1398unsafe fn move_bytes(dst: *mut u8, src: *const u8, n: usize) {
1399    // SAFETY: every read lies in the `n` bytes at `src` and every write in the `n` at `dst`.
1400    unsafe {
1401        if n > 64 {
1402            ptr::copy(src, dst, n);
1403        } else if n > 32 {
1404            let a: [u8; 16] = read(src);
1405            let b: [u8; 16] = read(src.add(16));
1406            let c: [u8; 16] = read(src.add(n - 32));
1407            let d: [u8; 16] = read(src.add(n - 16));
1408            write(dst, a);
1409            write(dst.add(16), b);
1410            write(dst.add(n - 32), c);
1411            write(dst.add(n - 16), d);
1412        } else if n >= 16 {
1413            let a: [u8; 16] = read(src);
1414            let b: [u8; 16] = read(src.add(n - 16));
1415            write(dst, a);
1416            write(dst.add(n - 16), b);
1417        } else if n >= 8 {
1418            let a: [u8; 8] = read(src);
1419            let b: [u8; 8] = read(src.add(n - 8));
1420            write(dst, a);
1421            write(dst.add(n - 8), b);
1422        } else if n >= 4 {
1423            let a: [u8; 4] = read(src);
1424            let b: [u8; 4] = read(src.add(n - 4));
1425            write(dst, a);
1426            write(dst.add(n - 4), b);
1427        } else if n > 0 {
1428            let (a, b, c) = (*src, *src.add(n / 2), *src.add(n - 1));
1429            *dst = a;
1430            *dst.add(n / 2) = b;
1431            *dst.add(n - 1) = c;
1432        }
1433    }
1434}
1435
1436// Positions
1437
1438/// The byte order of the layout `BE`.
1439#[inline(always)]
1440fn order<const BE: bool>() -> ByteOrder {
1441    if BE {
1442        ByteOrder::BigEndian
1443    } else {
1444        ByteOrder::LittleEndian
1445    }
1446}
1447
1448/// Positions `p..p + n` of the magnitude at the least significant end `end` in the layout `BE`,
1449/// as a slice of its bytes in that layout.
1450///
1451/// # Safety
1452///
1453/// The `n` bytes must be valid for reads, and not written while the slice is alive.
1454#[inline(always)]
1455unsafe fn slice<'a, const BE: bool>(end: *const u8, p: usize, n: usize) -> &'a [u8] {
1456    // SAFETY: as the caller guarantees.
1457    unsafe { &*ptr::slice_from_raw_parts(at::<BE>(end, p, n), n) }
1458}
1459
1460/// The least significant end of the magnitude in `v` in the layout `BE`: the address of its
1461/// first byte little-endian, and the address one past its last byte big-endian.
1462#[inline(always)]
1463fn end<const BE: bool>(v: &[u8]) -> *const u8 {
1464    if BE { v.as_ptr_range().end } else { v.as_ptr() }
1465}
1466
1467/// The lowest address of positions `p..p + n` of the magnitude at the least significant end
1468/// `end` in the layout `BE`: `end + p` little-endian, `end - p - n` big-endian.
1469///
1470/// # Safety
1471///
1472/// The address must lie in the allocation of `end`.
1473#[inline(always)]
1474unsafe fn at<const BE: bool>(end: *const u8, p: usize, n: usize) -> *const u8 {
1475    // SAFETY: as the caller guarantees.
1476    unsafe { if BE { end.sub(p + n) } else { end.add(p) } }
1477}
1478
1479/// [`at`] for writing.
1480///
1481/// # Safety
1482///
1483/// As for [`at`].
1484#[inline(always)]
1485unsafe fn at_mut<const BE: bool>(end: *mut u8, p: usize, n: usize) -> *mut u8 {
1486    // SAFETY: as the caller guarantees.
1487    unsafe { if BE { end.sub(p + n) } else { end.add(p) } }
1488}
1489
1490/// Reads position `p` of the magnitude at the least significant end `end` in the layout `BE`.
1491///
1492/// # Safety
1493///
1494/// The byte must be valid for reading.
1495#[inline(always)]
1496unsafe fn get<const BE: bool>(end: *const u8, p: usize) -> u8 {
1497    // SAFETY: as the caller guarantees.
1498    unsafe { *at::<BE>(end, p, 1) }
1499}
1500
1501/// Writes position `p` of the magnitude at the least significant end `end` in the layout `BE`.
1502///
1503/// # Safety
1504///
1505/// The byte must be valid for writing.
1506#[inline(always)]
1507unsafe fn set<const BE: bool>(end: *mut u8, p: usize, v: u8) {
1508    // SAFETY: as the caller guarantees.
1509    unsafe { *at_mut::<BE>(end, p, 1) = v };
1510}
1511
1512/// Reads positions `p..p + 8` of the magnitude at the least significant end `end` in the
1513/// layout `BE` as a `u64` whose least significant byte is position `p`.
1514///
1515/// # Safety
1516///
1517/// The eight bytes must be valid for reading; they need no alignment.
1518#[inline(always)]
1519unsafe fn load<const BE: bool>(end: *const u8, p: usize) -> u64 {
1520    // SAFETY: as the caller guarantees.
1521    unsafe {
1522        let bytes = read(at::<BE>(end, p, 8));
1523        if BE {
1524            u64::from_be_bytes(bytes)
1525        } else {
1526            u64::from_le_bytes(bytes)
1527        }
1528    }
1529}
1530
1531/// Writes positions `p..p + 8` of the magnitude at the least significant end `end` in the
1532/// layout `BE`, as [`load`] reads them.
1533///
1534/// # Safety
1535///
1536/// The eight bytes must be valid for writing; they need no alignment.
1537#[inline(always)]
1538unsafe fn store<const BE: bool>(end: *mut u8, p: usize, v: u64) {
1539    // SAFETY: as the caller guarantees.
1540    unsafe {
1541        let bytes = if BE { v.to_be_bytes() } else { v.to_le_bytes() };
1542        write(at_mut::<BE>(end, p, 8), bytes);
1543    }
1544}