Skip to main content

a/math/numbers/
bits.rs

1//! Bitwise operations on [`Number`]s: `&`, `|`, `^`, `&=`, `|=` and `^=`, with either operand
2//! owned or borrowed, `!`, and the bits of a number: [`Number::bits`], [`Number::count_ones`],
3//! [`Number::trailing_zeros`], [`Number::bit`] and [`Number::set_bit`].
4//!
5//! The operators work as if both operands were in two's complement with infinitely many bits, as
6//! those of `i32` do on 32 and GMP's `mpz_and`, `mpz_ior`, `mpz_xor` and `mpz_com` on any number:
7//! a negative number has infinitely many ones above its magnitude's bits, `-x` being `!x + 1`. The
8//! result is stored back as a sign and a magnitude. With `X` and `Y` the magnitudes, a negative
9//! operand is `!(X - 1)` and a negative result `!(R - 1)`, so every combination of signs comes down
10//! to one operation `g` on the bytes of `X` or `X - 1` and `Y` or `Y - 1`, plus one when the result
11//! is negative:
12//!
13//! | | `x & y` | `x \| y` | `x ^ y` |
14//! | --- | --- | --- | --- |
15//! | `+ +` | `X & Y` | `X \| Y` | `X ^ Y` |
16//! | `+ -` | `X & !(Y - 1)` | `-((Y - 1) & !X) - 1` | `-(X ^ (Y - 1)) - 1` |
17//! | `- +` | `!(X - 1) & Y` | `-((X - 1) & !Y) - 1` | `-((X - 1) ^ Y) - 1` |
18//! | `- -` | `-((X - 1) \| (Y - 1)) - 1` | `-((X - 1) & (Y - 1)) - 1` | `(X - 1) ^ (Y - 1)` |
19//!
20//! `!x` is `-x - 1`: `-(X + 1)` for `x >= 0`, and `X - 1` for `x < 0`.
21//!
22//! The ones taken from the magnitudes and the one added to the result are borrows and a carry
23//! that run through the low bytes only: `X - 1` differs from `X` below its lowest nonzero byte
24//! and at it, and the carry of `R + 1` runs through the bytes of `R` that are `0xFF`. So the
25//! result is computed limb by limb (eight bytes, the least significant first) with the borrows
26//! and the carry in flags, from the low end until all three are spent, which for random operands
27//! is the first limb: the head. Above it, each byte of the result is `g` of the bytes of the
28//! magnitudes at its position, with no carry from one byte to the next, so the rest is a loop
29//! over the bytes in the order of memory, the same for both byte orders: NEON on aarch64, sixteen
30//! bytes a step (`and`, `orr`, `eor` or `bic`), and words of eight bytes elsewhere. Above the
31//! shorter operand, the result is the longer one's bytes or zero, by the operation.
32//!
33//! The paths, by the operands:
34//!
35//! - Both vectors of at most 16 bytes: in registers, as `u128`s in two's complement.
36//! - Neither negative, in the same byte order: the operation, known at compile time, runs over
37//!   the shorter magnitude's bytes with the kernel, with no borrow or carry, straight into the
38//!   vector the result goes to; its length is the longer magnitude's for `|` and `^` of different
39//!   lengths, and is otherwise read from the top down, one read for random operands: of the
40//!   result, in place little-endian, and of the operands otherwise.
41//! - Both of at most 64 bytes otherwise: in registers, as up to eight limbs each, as the
42//!   addition's medium path reads them, with no branch on the signs or the length.
43//! - Longer ones, in an operand's vector with room: the head of one limb, the length from the top
44//!   of the operands (one read), one kernel call and a copy of the longer operand's top bytes.
45//! - Otherwise (a new vector, a longer head, or a big-endian result of another length than the
46//!   vector it is built in), everything about the result but its bytes is planned first, as for
47//!   the other operators: the head, by a pass over its limbs that only reads them, and the exact
48//!   length. Only then is a vector chosen, and the result written in it, each byte once; in place,
49//!   the bytes the longer operand gives are left where they are, and a big-endian result that
50//!   moves is written in the order that reads every byte of the operand before it is written over.
51
52// The kernels of the loops over the bytes, under the name `kernels`: NEON on the 64-bit
53// little-endian aarch64 targets whose operating system allows unaligned accesses (those of the
54// addition's assembly), where NEON is enabled, as it is by default; the portable ones elsewhere and
55// under Miri, which runs no SIMD of this kind.
56#[cfg(all(
57    target_arch = "aarch64",
58    target_endian = "little",
59    target_pointer_width = "64",
60    target_feature = "neon",
61    any(
62        target_vendor = "apple",
63        target_os = "linux",
64        target_os = "android",
65        target_os = "windows",
66        target_os = "freebsd",
67        target_os = "netbsd",
68        target_os = "openbsd",
69        target_os = "fuchsia"
70    ),
71    not(miri)
72))]
73#[path = "bits/aarch64.rs"]
74mod kernels;
75#[cfg(not(all(
76    target_arch = "aarch64",
77    target_endian = "little",
78    target_pointer_width = "64",
79    target_feature = "neon",
80    any(
81        target_vendor = "apple",
82        target_os = "linux",
83        target_os = "android",
84        target_os = "windows",
85        target_os = "freebsd",
86        target_os = "netbsd",
87        target_os = "openbsd",
88        target_os = "fuchsia"
89    ),
90    not(miri)
91)))]
92#[path = "bits/portable.rs"]
93mod kernels;
94
95use super::add::{
96    SMALL, long, medium, read, read_limbs, read_small, significant_len, small, top_of, write,
97    write_small,
98};
99use super::{ByteOrder, Number};
100use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
101use core::{mem, ptr};
102
103// The operations on the bytes of two magnitudes `x` and `y` that the operators come down to.
104
105/// `x & y`.
106const AND: u8 = 0;
107/// `x | y`.
108const OR: u8 = 1;
109/// `x ^ y`.
110const XOR: u8 = 2;
111/// `x & !y`.
112const AND_NOT: u8 = 3;
113/// `!x & y`.
114const NOT_AND: u8 = 4;
115
116/// The operation `g` on the words `x` and `y`.
117#[inline(always)]
118fn apply(g: u8, x: u64, y: u64) -> u64 {
119    match g {
120        AND => x & y,
121        OR => x | y,
122        XOR => x ^ y,
123        AND_NOT => x & !y,
124        _ => !x & y,
125    }
126}
127
128/// A bitwise operator on two numbers.
129#[derive(Clone, Copy)]
130#[repr(u8)]
131enum Op {
132    And,
133    Or,
134    Xor,
135}
136
137/// The operation on the magnitudes and the sign of the result of `op` for operands with the signs
138/// `nx` and `ny`, as in the table of the module: the result is `g(X', Y')`, plus one when it is
139/// negative, with `X' = X - 1` for a negative `x` and `X` otherwise, and `Y'` likewise. Read from
140/// a table, with no branch.
141#[inline(always)]
142fn select(op: Op, nx: bool, ny: bool) -> (u8, bool) {
143    /// `g` in the low bits and the sign of the result in the top one, by the operator and the
144    /// signs `nx ny` of the operands: `+ +`, `+ -`, `- +`, `- -`.
145    const TABLE: [[u8; 4]; 3] = [
146        [AND, AND_NOT, NOT_AND, OR | 0x80],
147        [OR, NOT_AND | 0x80, AND_NOT | 0x80, AND | 0x80],
148        [XOR, XOR | 0x80, XOR | 0x80, XOR],
149    ];
150    let t = TABLE[op as usize][usize::from(nx) * 2 + usize::from(ny)];
151    (t & 0x7F, t & 0x80 != 0)
152}
153
154// The operators
155
156/// Implements a bitwise operator: `$Op` with its method `$op` for each form of the operands, and
157/// `$Assign` with `$assign`. `$sym` is the operator; the examples compute `12 $sym -10`, which is
158/// `$value` (`$magnitude` and `$negative`), `0x0F_00 $sym 0x00_F0` (`$wide`, as stored
159/// big-endian) and `0xFF $sym 0x01_00` (`$by_b`, stored as `$in_b`, in the vector of the right
160/// operand when `$built_in_b`).
161macro_rules! bitwise {
162    (
163        $Op:ident, $op:ident, $Assign:ident, $assign:ident, $kind:expr, $OP:expr, $sym:literal,
164        $what:literal, $value:literal, $magnitude:literal, $negative:literal, $wide:literal,
165        $by_b:literal, $in_b:literal, $built_in_b:literal
166    ) => {
167        impl $Op<&Number> for &Number {
168            type Output = Number;
169
170            #[doc = concat!("Returns `self ", $sym, " rhs`, the bitwise ", $what, " of the numbers in")]
171            /// infinite two's complement, in the byte order of `self`, in the shortest form.
172            ///
173            /// The result is built in one new vector of exactly its length (one byte for zero);
174            /// both operands are left as they were. The operands may have any signs, byte orders
175            /// and lengths, and need not be in the shortest form.
176            ///
177            /// # Examples
178            ///
179            /// ```
180            /// use a::math::numbers::{ByteOrder, Number};
181            ///
182            /// let a = Number::new_from_i32(12, ByteOrder::BigEndian);
183            /// let b = Number::new_from_i32(-10, ByteOrder::LittleEndian);
184            #[doc = concat!("let c = &a ", $sym, " &b;")]
185            #[doc = concat!("// As for `i32`: `12 ", $sym, " -10` is ", $value, ".")]
186            #[doc = concat!("assert_eq!(c.value, [", $magnitude, "]);")]
187            #[doc = concat!("assert_eq!(c.is_negative(), ", $negative, ");")]
188            /// assert!(c.byte_order() == ByteOrder::BigEndian);
189            /// ```
190            fn $op(self, rhs: &Number) -> Number {
191                if small(self, rhs) {
192                    // SAFETY: both vectors hold at most 16 bytes.
193                    let s = unsafe { small_result(self, rhs, $kind) };
194                    return small_number(self.byte_order, s);
195                }
196                if let Some(n) = plus_new::<{ $OP }>(self, rhs) {
197                    return n;
198                }
199                if medium(self, rhs) {
200                    // SAFETY: both vectors hold at most 64 bytes.
201                    let m = unsafe { medium_result::<{ $OP }>(self, rhs) };
202                    return medium_number(self.byte_order, &m);
203                }
204                ref_ref(self, rhs, $kind)
205            }
206        }
207
208        impl $Op<&Number> for Number {
209            type Output = Number;
210
211            #[doc = concat!("Returns `self ", $sym, " rhs`, in the byte order of `self`, in the shortest")]
212            #[doc = concat!("form, as `self ", $sym, "= rhs` does.")]
213            ///
214            /// The result is built in the vector of `self` when its capacity has room for it,
215            /// which allocates nothing, and otherwise in one new vector of exactly its length.
216            /// `rhs` is left as it was.
217            ///
218            /// # Examples
219            ///
220            /// ```
221            /// use a::math::numbers::{ByteOrder, Number};
222            ///
223            /// let mut value = Vec::with_capacity(4);
224            /// value.extend([0x0F, 0x00]);
225            /// let a = Number::new(value, ByteOrder::BigEndian);
226            /// let pointer = a.value.as_ptr();
227            ///
228            #[doc = concat!("let c = a ", $sym, " &Number::new_from_u8(0xF0, ByteOrder::LittleEndian);")]
229            #[doc = concat!("assert_eq!(c.value, [", $wide, "]);")]
230            /// assert_eq!(c.value.as_ptr(), pointer);
231            /// ```
232            fn $op(mut self, rhs: &Number) -> Number {
233                $Assign::$assign(&mut self, rhs);
234                self
235            }
236        }
237
238        impl $Op<Number> for &Number {
239            type Output = Number;
240
241            #[doc = concat!("Returns `self ", $sym, " rhs`, in the byte order of `self`, in the shortest")]
242            /// form.
243            ///
244            /// The result is built in the vector of `rhs` when its capacity has room for it, also
245            /// when `rhs` is in the other byte order, and otherwise in one new vector of exactly
246            /// its length. `self` is left as it was.
247            ///
248            /// # Examples
249            ///
250            /// ```
251            /// use a::math::numbers::{ByteOrder, Number};
252            ///
253            /// let a = Number::new_from_u16(0x0F00, ByteOrder::BigEndian);
254            /// let mut value = Vec::with_capacity(4);
255            /// value.extend([0xF0]);
256            /// let b = Number::new(value, ByteOrder::LittleEndian);
257            /// let pointer = b.value.as_ptr();
258            ///
259            #[doc = concat!("let c = &a ", $sym, " b;")]
260            #[doc = concat!("assert_eq!(c.value, [", $wide, "]);")]
261            /// assert_eq!(c.value.as_ptr(), pointer);
262            /// assert!(c.byte_order() == ByteOrder::BigEndian);
263            /// ```
264            fn $op(self, mut rhs: Number) -> Number {
265                if small(self, &rhs) {
266                    // SAFETY: both vectors hold at most 16 bytes.
267                    let s = unsafe { small_result(self, &rhs, $kind) };
268                    let order = self.byte_order;
269                    put_small(&mut rhs.value, order, s);
270                    return Number {
271                        value: rhs.value,
272                        negative: s.negative,
273                        byte_order: order,
274                    };
275                }
276                // The operations are symmetric: `rhs op self` over `rhs`.
277                if plus_over::<{ $OP }>(&mut rhs, self) {
278                    return rhs;
279                }
280                if medium(self, &rhs) {
281                    // SAFETY: both vectors hold at most 64 bytes.
282                    let m = unsafe { medium_result::<{ $OP }>(self, &rhs) };
283                    let order = self.byte_order;
284                    put_medium(&mut rhs.value, order, &m);
285                    return Number {
286                        value: rhs.value,
287                        negative: m.negative,
288                        byte_order: order,
289                    };
290                }
291                // `rhs` is dropped on return, with the vector it holds then, if any.
292                ref_value(self, &mut rhs, $kind)
293            }
294        }
295
296        impl $Op<Number> for Number {
297            type Output = Number;
298
299            #[doc = concat!("Returns `self ", $sym, " rhs`, in the byte order of `self`, in the shortest")]
300            #[doc = concat!("form, as `self ", $sym, "= rhs` does.")]
301            ///
302            /// The result is built in the vector of `self` when its capacity has room for it, or
303            /// else in the vector of `rhs` when that has room, also when `rhs` is in the other
304            /// byte order, either of which allocates nothing; otherwise it gets one new vector of
305            /// exactly its length.
306            ///
307            /// # Examples
308            ///
309            /// ```
310            /// use a::math::numbers::{ByteOrder, Number};
311            ///
312            /// let a = Number::new_from_i32(12, ByteOrder::LittleEndian);
313            /// let b = Number::new_from_i32(-10, ByteOrder::BigEndian);
314            #[doc = concat!("let c = a ", $sym, " b;")]
315            #[doc = concat!("assert_eq!(c.value, [", $magnitude, "]);")]
316            #[doc = concat!("assert_eq!(c.is_negative(), ", $negative, ");")]
317            /// ```
318            fn $op(mut self, rhs: Number) -> Number {
319                $Assign::$assign(&mut self, rhs);
320                self
321            }
322        }
323
324        impl $Assign<&Number> for Number {
325            #[doc = concat!("Sets `self` to `self ", $sym, " rhs`, keeping its byte order, in the shortest form.")]
326            ///
327            /// The result is built in the vector of `self` when its capacity has room for it,
328            /// which allocates nothing, and otherwise in one new vector of exactly its length,
329            /// which replaces it. `rhs` is left as it was.
330            ///
331            /// # Examples
332            ///
333            /// ```
334            /// use a::math::numbers::{ByteOrder, Number};
335            ///
336            /// let mut n = Number::new_from_i32(12, ByteOrder::LittleEndian);
337            #[doc = concat!("n ", $sym, "= &Number::new_from_i32(-10, ByteOrder::BigEndian);")]
338            #[doc = concat!("assert_eq!(n.value, [", $magnitude, "]);")]
339            #[doc = concat!("assert_eq!(n.is_negative(), ", $negative, ");")]
340            /// ```
341            #[inline]
342            fn $assign(&mut self, rhs: &Number) {
343                if small(self, rhs) {
344                    // SAFETY: both vectors hold at most 16 bytes.
345                    let s = unsafe { small_result(self, rhs, $kind) };
346                    put_small(&mut self.value, self.byte_order, s);
347                    self.negative = s.negative;
348                    return;
349                }
350                if plus_over::<{ $OP }>(self, rhs) {
351                    return;
352                }
353                if medium(self, rhs) {
354                    // SAFETY: both vectors hold at most 64 bytes.
355                    let m = unsafe { medium_result::<{ $OP }>(self, rhs) };
356                    put_medium(&mut self.value, self.byte_order, &m);
357                    self.negative = m.negative;
358                    return;
359                }
360                assign_ref(self, rhs, $kind);
361            }
362        }
363
364        impl $Assign<Number> for Number {
365            #[doc = concat!("Sets `self` to `self ", $sym, " rhs`, keeping its byte order, in the shortest form.")]
366            ///
367            /// The result is built in the vector of `self` when its capacity has room for it, or
368            /// else in the vector of `rhs` when that has room, also when `rhs` is in the other
369            /// byte order, either of which allocates nothing; otherwise it gets one new vector of
370            /// exactly its length.
371            ///
372            /// # Examples
373            ///
374            /// ```
375            /// use a::math::numbers::{ByteOrder, Number};
376            ///
377            /// // `n` has room for one byte only; the vector of the right operand has more.
378            /// let mut value = Vec::with_capacity(1);
379            /// value.push(0xFF);
380            /// let mut n = Number::new(value, ByteOrder::BigEndian);
381            /// let mut value = Vec::with_capacity(4);
382            /// value.extend([0x00, 0x01]);
383            /// let b = Number::new(value, ByteOrder::LittleEndian);
384            /// let pointer = b.value.as_ptr();
385            #[doc = concat!("n ", $sym, "= b;")]
386            #[doc = concat!("// `0xFF ", $sym, " 0x01_00` is ", $by_b, ".")]
387            #[doc = concat!("assert_eq!(n.value, [", $in_b, "]);")]
388            #[doc = concat!("assert_eq!(n.value.as_ptr() == pointer, ", $built_in_b, ");")]
389            /// ```
390            #[inline]
391            fn $assign(&mut self, mut rhs: Number) {
392                if small(self, &rhs) {
393                    // SAFETY: both vectors hold at most 16 bytes.
394                    let s = unsafe { small_result(self, &rhs, $kind) };
395                    if self.value.capacity() < s.len && rhs.value.capacity() >= s.len {
396                        // The vector of `self` goes to `rhs`, and is dropped with it.
397                        mem::swap(&mut self.value, &mut rhs.value);
398                    }
399                    put_small(&mut self.value, self.byte_order, s);
400                    self.negative = s.negative;
401                    return;
402                }
403                if plus_over::<{ $OP }>(self, &rhs) {
404                    return;
405                }
406                if medium(self, &rhs) {
407                    // SAFETY: both vectors hold at most 64 bytes.
408                    let m = unsafe { medium_result::<{ $OP }>(self, &rhs) };
409                    if self.value.capacity() < m.len && rhs.value.capacity() >= m.len {
410                        // The vector of `self` goes to `rhs`, and is dropped with it.
411                        mem::swap(&mut self.value, &mut rhs.value);
412                    }
413                    put_medium(&mut self.value, self.byte_order, &m);
414                    self.negative = m.negative;
415                    return;
416                }
417                // `rhs` is dropped on return, with the vector it holds then.
418                assign_value(self, &mut rhs, $kind);
419            }
420        }
421    };
422}
423
424bitwise!(
425    BitAnd,
426    bitand,
427    BitAndAssign,
428    bitand_assign,
429    Op::And,
430    AND,
431    "&",
432    "and",
433    "4",
434    "4",
435    "false",
436    "0",
437    "0",
438    "0",
439    "false"
440);
441bitwise!(
442    BitOr,
443    bitor,
444    BitOrAssign,
445    bitor_assign,
446    Op::Or,
447    OR,
448    "|",
449    "or",
450    "-2",
451    "2",
452    "true",
453    "0x0F, 0xF0",
454    "0x01_FF",
455    "0x01, 0xFF",
456    "true"
457);
458bitwise!(
459    BitXor,
460    bitxor,
461    BitXorAssign,
462    bitxor_assign,
463    Op::Xor,
464    XOR,
465    "^",
466    "exclusive or",
467    "-6",
468    "6",
469    "true",
470    "0x0F, 0xF0",
471    "0x01_FF",
472    "0x01, 0xFF",
473    "true"
474);
475
476impl Not for Number {
477    type Output = Number;
478
479    /// Returns `!self`, every bit of the number in infinite two's complement inverted, which is
480    /// `-self - 1`, in the byte order of `self`, in the shortest form.
481    ///
482    /// The result is built in the vector of `self` when its capacity has room for it, which
483    /// allocates nothing, and otherwise in one new vector of exactly its length; it is at most one
484    /// byte longer. Only the bytes the carry of `+ 1` (or the borrow of `- 1`) passes through
485    /// are written, which for random numbers is the lowest one: a number in the shortest form
486    /// takes constant time.
487    ///
488    /// # Examples
489    ///
490    /// ```
491    /// use a::math::numbers::{ByteOrder, Number};
492    ///
493    /// // As for `i32`: `!0xFF` is `-0x100`, and `!-0x100` is `0xFF`.
494    /// let n = !Number::new_from_i32(0xFF, ByteOrder::BigEndian);
495    /// assert_eq!(n.value, [0x01, 0x00]);
496    /// assert!(n.is_negative());
497    /// let n = !n;
498    /// assert_eq!(n.value, [0xFF]);
499    /// assert!(!n.is_negative());
500    /// ```
501    #[inline]
502    fn not(mut self) -> Number {
503        not_in_place(&mut self);
504        self
505    }
506}
507
508impl Not for &Number {
509    type Output = Number;
510
511    /// Returns `!self`, which is `-self - 1`, in the byte order of `self`, in the shortest form.
512    ///
513    /// The result is built in one new vector of exactly its length; `self` is left as it was.
514    ///
515    /// # Examples
516    ///
517    /// ```
518    /// use a::math::numbers::{ByteOrder, Number};
519    ///
520    /// let a = Number::new_from_i32(-1, ByteOrder::LittleEndian);
521    /// let n = !&a;
522    /// assert_eq!(n.value, [0]);
523    /// assert!(!n.is_negative());
524    /// ```
525    #[inline]
526    fn not(self) -> Number {
527        not_new(self)
528    }
529}
530
531// Small numbers
532
533/// The result of a bitwise operation on two small operands, computed in registers.
534#[derive(Clone, Copy)]
535struct Small {
536    /// The low eight bytes of the magnitude.
537    lo: u64,
538    /// The next eight bytes of the magnitude.
539    hi: u64,
540    /// The length of the result in the shortest form, from 1 to 17: one byte for zero, and 17 for
541    /// a magnitude of `2^128`, whose seventeenth byte is 1 and the others 0.
542    len: usize,
543    /// Whether the result is negative; never for zero.
544    negative: bool,
545}
546
547/// The magnitude `m` with the sign `negative`, or `2^128` when `top` is set, as a [`Small`].
548#[inline(always)]
549fn small_of(m: u128, top: bool, negative: bool) -> Small {
550    Small {
551        lo: m as u64,
552        hi: (m >> 64) as u64,
553        len: if top {
554            SMALL + 1
555        } else {
556            SMALL - (m | 1).leading_zeros() as usize / 8
557        },
558        negative,
559    }
560}
561
562/// `a op b` for small operands, in two's complement on `u128`s: a negative magnitude `x` is
563/// `-x` there, with infinitely many ones above, and a negative result `r` is the magnitude
564/// `2^128 - r`, which is `2^128` itself, 17 bytes, for `r = 0`.
565///
566/// # Safety
567///
568/// Both vectors must hold at most [`SMALL`] bytes.
569#[inline(always)]
570unsafe fn small_result(a: &Number, b: &Number, op: Op) -> Small {
571    // SAFETY: as the caller guarantees.
572    let (x, y) = unsafe {
573        (
574            read_small(&a.value, a.byte_order),
575            read_small(&b.value, b.byte_order),
576        )
577    };
578    // A magnitude of zero is zero, whatever the sign says.
579    let (nx, ny) = (a.negative && x != 0, b.negative && y != 0);
580    let tx = if nx { x.wrapping_neg() } else { x };
581    let ty = if ny { y.wrapping_neg() } else { y };
582    let (r, negative) = match op {
583        Op::And => (tx & ty, nx & ny),
584        Op::Or => (tx | ty, nx | ny),
585        Op::Xor => (tx ^ ty, nx ^ ny),
586    };
587    let m = if negative { r.wrapping_neg() } else { r };
588    small_of(m, negative && r == 0, negative)
589}
590
591/// Writes the small result `s` as the whole value of `v`, in its vector when it has room, in a
592/// new one otherwise.
593#[inline(always)]
594fn put_small(v: &mut Vec<u8>, order: ByteOrder, s: Small) {
595    if v.capacity() >= s.len {
596        // SAFETY: the vector has room for the `len` bytes, from 1 to 17, all of which
597        // `write_small` writes before the length is set.
598        unsafe {
599            write_small(v.as_mut_ptr(), order, s.lo, s.hi, s.len);
600            v.set_len(s.len);
601        }
602    } else {
603        replace_small(v, order, s);
604    }
605}
606
607/// Replaces `v` with one new vector of exactly the small result's length, holding it. Out of
608/// line and cold, so that the small path saves no registers for it.
609#[cold]
610#[inline(never)]
611fn replace_small(v: &mut Vec<u8>, order: ByteOrder, s: Small) {
612    *v = new_small(order, s);
613}
614
615/// The small result `s` in one new vector of exactly its length.
616#[inline(always)]
617fn new_small(order: ByteOrder, s: Small) -> Vec<u8> {
618    let mut v = Vec::with_capacity(s.len);
619    // SAFETY: the new vector has room for the `len` bytes, from 1 to 17, all of which
620    // `write_small` writes before the length is set.
621    unsafe {
622        write_small(v.as_mut_ptr(), order, s.lo, s.hi, s.len);
623        v.set_len(s.len);
624    }
625    v
626}
627
628/// The small result `s` as a number in one new vector, in the byte order `order`. Out of line,
629/// so that the small path of `&a op &b` saves no registers for the allocation.
630#[inline(never)]
631fn small_number(order: ByteOrder, s: Small) -> Number {
632    Number {
633        value: new_small(order, s),
634        negative: s.negative,
635        byte_order: order,
636    }
637}
638
639// Operands that are not negative
640
641/// `a op b` written over `a`, for `a` and `b` that are not negative (as their signs say), in the
642/// same byte order, of which at least one has more than 16 bytes, when `a`'s vector has room for
643/// the longest the result can be, and big-endian, the result's positions are those of `a`:
644/// `op` is the operation on the magnitudes' bytes, known here, with no borrow or carry, so the
645/// kernel runs straight over the bytes of the shorter magnitude, and the longer one's top bytes
646/// follow for `|` and `^`. The length of the result is the longer magnitude's then, and otherwise
647/// found from the top down, one read for random operands (of the operands big-endian, of the
648/// result little-endian); big-endian, a shorter result is moved to the start of the vector. Returns whether it did, with nothing written
649/// otherwise; zero operands are left to the general path.
650///
651/// Measured on an Apple M4 Max over operands in the level-1 cache, `a ^= &b` of 24, 64 and 128
652/// bytes took 13, 16 and 17 cycles so, against 17, 28 and 28 through the paths for any signs, and
653/// GMP 6.3's `mpz_xor(a, a, b)` 11, 13 and 20.
654#[inline(always)]
655fn plus_over<const OP: u8>(a: &mut Number, b: &Number) -> bool {
656    if a.negative | b.negative || a.byte_order != b.byte_order {
657        return false;
658    }
659    if a.byte_order == ByteOrder::BigEndian {
660        plus_over_in::<OP, true>(&mut a.value, &b.value)
661    } else {
662        plus_over_in::<OP, false>(&mut a.value, &b.value)
663    }
664}
665
666/// [`plus_over`] for the layout `BE`.
667#[inline(never)]
668fn plus_over_in<const OP: u8, const BE: bool>(v: &mut Vec<u8>, y: &[u8]) -> bool {
669    let n = v.len();
670    let (lx, ly) = (sig_len::<BE>(v), sig_len::<BE>(y));
671    let (long, short) = (lx.max(ly), lx.min(ly));
672    // The bound of the result's length, which is its length but for `&`, and `^` of magnitudes
673    // of the same length.
674    let u = if OP == AND { short } else { long };
675    if short == 0 || v.capacity() < u || (BE && u != n) {
676        return false;
677    }
678    let ye = end::<BE>(y);
679    // The length of a result that can be shorter than `u`: big-endian, from the top of the
680    // operands down, before anything is written; little-endian, read back from the top of the
681    // result. Read back big-endian, it waited for the kernel's stores (measured on an Apple M4
682    // Max, a big-endian `^=` of 40 to 64 bytes took 30 to 34 cycles so, against 19 to 20), and
683    // read first little-endian, it took two cycles more than read back.
684    let cut = OP == AND || (OP == XOR && lx == ly);
685    let first = if cut && BE {
686        // SAFETY: the positions below `short` are significant in both magnitudes.
687        unsafe { highest::<BE, BE>(OP, end::<BE>(v), ye, 0, short) }.unwrap_or(1)
688    } else {
689        long
690    };
691    let base = v.as_mut_ptr();
692    // SAFETY: the reads are of the significant bytes of each magnitude, the writes of the
693    // `u <= capacity` bytes of `v`, at the positions of `x` (big-endian, `x` ends at `n = u`),
694    // each block of `x` read before it is written over at the same positions.
695    unsafe {
696        let dst = if BE { base.add(n) } else { base };
697        kernels::logic::<OP, false, false>(
698            at_mut::<BE>(dst, 0, short),
699            at::<BE>(dst, 0, short),
700            at::<BE>(ye, 0, short),
701            short,
702        );
703        let len = if cut && BE {
704            if first < u {
705                ptr::copy(base.add(u - first), base, first);
706            }
707            first
708        } else if cut {
709            highest_of::<BE>(dst, u)
710        } else {
711            if ly > lx {
712                let k = long - short;
713                ptr::copy_nonoverlapping(at::<BE>(ye, short, k), at_mut::<BE>(dst, short, k), k);
714            }
715            long
716        };
717        v.set_len(len);
718    }
719    true
720}
721
722/// The length up to the highest nonzero byte of the `u >= 1` bytes at the least significant end
723/// `end` in the layout `BE`, or 1 when they are all zero: from the top down, eight at a time.
724///
725/// # Safety
726///
727/// The `u` bytes must be valid for reads.
728#[inline(always)]
729unsafe fn highest_of<const BE: bool>(end: *const u8, u: usize) -> usize {
730    let mut q = u;
731    // SAFETY: every read is of positions below `u`.
732    unsafe {
733        while q >= 8 {
734            let w = load::<BE>(end, q - 8);
735            if w != 0 {
736                return q - w.leading_zeros() as usize / 8;
737            }
738            q -= 8;
739        }
740        while q > 1 && get::<BE>(end, q - 1) == 0 {
741            q -= 1;
742        }
743        q.max(1)
744    }
745}
746
747/// `a op b` in one new vector of exactly its length, for `a` and `b` that are not negative, in
748/// the same byte order, of which at least one has more than 16 bytes, as [`plus_over`] computes
749/// it, with the length found first: the longer magnitude's, or from the top down for `&`, and
750/// `^` of magnitudes of the same length. `None` for the other operands, and zero ones.
751#[inline(always)]
752fn plus_new<const OP: u8>(a: &Number, b: &Number) -> Option<Number> {
753    if a.negative | b.negative || a.byte_order != b.byte_order {
754        return None;
755    }
756    let value = if a.byte_order == ByteOrder::BigEndian {
757        plus_new_in::<OP, true>(&a.value, &b.value)?
758    } else {
759        plus_new_in::<OP, false>(&a.value, &b.value)?
760    };
761    Some(Number {
762        value,
763        negative: false,
764        byte_order: a.byte_order,
765    })
766}
767
768/// [`plus_new`] for the layout `BE`.
769#[inline(never)]
770fn plus_new_in<const OP: u8, const BE: bool>(x: &[u8], y: &[u8]) -> Option<Vec<u8>> {
771    let (lx, ly) = (sig_len::<BE>(x), sig_len::<BE>(y));
772    let (long, short) = (lx.max(ly), lx.min(ly));
773    let (xe, ye) = (end::<BE>(x), end::<BE>(y));
774    let len = if OP == AND || (OP == XOR && lx == ly) {
775        // SAFETY: the positions below `short` are significant in both magnitudes.
776        unsafe { highest::<BE, BE>(OP, xe, ye, 0, short)? }
777    } else if short > 0 {
778        long
779    } else {
780        return None;
781    };
782    let mut v = Vec::<u8>::with_capacity(len);
783    // SAFETY: the new vector has room for the `len` bytes, all of which are written: positions
784    // below `min(short, len)` by the kernel, the others, for `|` and `^`, from the longer
785    // magnitude.
786    unsafe {
787        let base = v.as_mut_ptr();
788        let dst = if BE { base.add(len) } else { base };
789        let k = short.min(len);
790        kernels::logic::<OP, false, false>(
791            at_mut::<BE>(dst, 0, k),
792            at::<BE>(xe, 0, k),
793            at::<BE>(ye, 0, k),
794            k,
795        );
796        if len > short {
797            let (from, k) = (if lx > ly { xe } else { ye }, len - short);
798            ptr::copy_nonoverlapping(at::<BE>(from, short, k), at_mut::<BE>(dst, short, k), k);
799        }
800        v.set_len(len);
801    }
802    Some(v)
803}
804
805// Operands of up to 64 bytes
806
807/// The result of a bitwise operation on two operands of up to 64 bytes, computed in registers.
808struct Medium {
809    /// The limbs of the magnitude, the least significant first: up to eight, then the ninth,
810    /// which is 1 for a magnitude of `2^(64 L)`, then zeros.
811    limbs: [u64; 9],
812    /// The length of the result in the shortest form: one byte for zero.
813    len: usize,
814    /// The number `L` of limbs the operands were read as, when the result is at least
815    /// `8 (L - 1)` bytes long, with its top eight positions in `top`; zero otherwise.
816    long: usize,
817    /// The eight positions of the result that end at its top, when `long` is set.
818    top: u64,
819    /// Whether the result is negative; never for zero.
820    negative: bool,
821}
822
823/// `a op b` for operands of at most 64 bytes, `op` one of [`AND`], [`OR`] and [`XOR`], by the
824/// number of limbs of the longer vector, from 3 to 8.
825///
826/// The limit is the addition's medium path's, whose reading of limbs this shares. Measured on an
827/// Apple M4 Max with negative operands, `a &= &b` and `a ^= &b` of 40 and 48 bytes took 28 to 32
828/// cycles in registers, against 36 to 40 through the general path; at 64 bytes the two are about
829/// even (36 to 41 cycles against 35 to 48).
830///
831/// # Safety
832///
833/// Both vectors must hold at most [`MEDIUM`](super::add::MEDIUM) bytes.
834#[inline(always)]
835unsafe fn medium_result<const OP: u8>(a: &Number, b: &Number) -> Medium {
836    // SAFETY: as the caller guarantees, the vectors hold at most `8 L` bytes for the `L` chosen.
837    unsafe {
838        match a.value.len().max(b.value.len()).div_ceil(8) {
839            ..=3 => medium_of::<OP, 3>(a, b),
840            4 => medium_of::<OP, 4>(a, b),
841            5 => medium_of::<OP, 5>(a, b),
842            6 => medium_of::<OP, 6>(a, b),
843            7 => medium_of::<OP, 7>(a, b),
844            _ => medium_of::<OP, 8>(a, b),
845        }
846    }
847}
848
849/// [`medium_result`] for vectors of at most `L` limbs: the magnitudes read into `L` limbs each as
850/// the addition reads them, turned into two's complement where they are negative (`!x + 1`, one
851/// chain of carries, the limbs above the vector all ones), `op` on the limbs, and a negative
852/// result turned back into its magnitude the same way, all without a branch.
853///
854/// # Safety
855///
856/// Both vectors must hold at most `8 L` bytes.
857#[inline(never)]
858unsafe fn medium_of<const OP: u8, const L: usize>(a: &Number, b: &Number) -> Medium {
859    // SAFETY: as the caller guarantees.
860    let (x, y) = unsafe {
861        (
862            read_limbs::<L>(&a.value, a.byte_order),
863            read_limbs::<L>(&b.value, b.byte_order),
864        )
865    };
866    let nonzero = |v: &[u64; 9]| v.iter().take(L).fold(0, |o, &l| o | l) != 0;
867    // A magnitude of zero is zero, whatever the sign says.
868    let (nx, ny) = (a.negative && nonzero(&x), b.negative && nonzero(&y));
869    let negative = match OP {
870        AND => nx & ny,
871        OR => nx | ny,
872        _ => nx ^ ny,
873    };
874    let (mx, my, mr) = (
875        0u64.wrapping_sub(u64::from(nx)),
876        0u64.wrapping_sub(u64::from(ny)),
877        0u64.wrapping_sub(u64::from(negative)),
878    );
879    let (mut cx, mut cy, mut cr) = (nx, ny, negative);
880    let mut limbs = [0u64; 9];
881    for i in 0..L {
882        let (tx, c) = (x[i] ^ mx).overflowing_add(u64::from(cx));
883        cx = c;
884        let (ty, c) = (y[i] ^ my).overflowing_add(u64::from(cy));
885        cy = c;
886        let r = match OP {
887            AND => tx & ty,
888            OR => tx | ty,
889            _ => tx ^ ty,
890        };
891        let (m, c) = (r ^ mr).overflowing_add(u64::from(cr));
892        cr = c;
893        limbs[i] = m;
894    }
895    // Above the limbs, the result is `mr` in two's complement, and its magnitude zero, but for
896    // the carry out of the top limb: a negative result that is zero in all `L` limbs is
897    // `-2^(64 L)`.
898    limbs[L] = u64::from(cr);
899    if long::<L>(&limbs) {
900        // The length and the top eight positions without a branch, as the addition finds them:
901        // whether `&` or `|` of operands of a sign each loses a top byte is a coin toss.
902        let (len, top) = top_of::<L>(&limbs);
903        return Medium {
904            limbs,
905            len,
906            long: L,
907            top,
908            negative,
909        };
910    }
911    let mut t = L;
912    while t > 0 && limbs[t] == 0 {
913        t -= 1;
914    }
915    Medium {
916        limbs,
917        len: 8 * t + 8 - (limbs[t] | 1).leading_zeros() as usize / 8,
918        long: 0,
919        top: 0,
920        negative,
921    }
922}
923
924/// Writes the medium result `m` over the first `m.len` bytes at `p`, in the layout of `order`.
925///
926/// A result of at least `8 (L - 1)` bytes, as for operands of `L` limbs that do not nearly
927/// cancel, is written by stores chosen by `L`, not by its length, which `&` and `|` make a coin
928/// toss: limbs `0..L - 1` at their places, limb `L - 1` at its place or, for a result shorter
929/// than `8 L` bytes, below the top eight positions, and then those, as the addition writes a
930/// medium sum. Measured on an Apple M4 Max, `a &= &b` of a positive `a` and a negative `b` of 24
931/// and 48 bytes took 20 and 29 cycles so, against 25 and 32 with stores chosen by the length. Otherwise: up to 16 bytes as the addition writes a short sum; beyond, the whole
932/// limbs, then the eight positions that end at the top, over the limb below.
933///
934/// # Safety
935///
936/// `p` must be valid for writing `m.len` bytes.
937#[inline(always)]
938unsafe fn write_medium(p: *mut u8, order: ByteOrder, m: &Medium) {
939    let (r, len) = (&m.limbs, m.len);
940    let be = order == ByteOrder::BigEndian;
941    // SAFETY: every write lies inside the `len` bytes at `p`: a long result has `len >= 8 (L - 1)`
942    // bytes and `L >= 3`, so `len >= 16`.
943    unsafe {
944        if m.long > 0 {
945            let l = m.long;
946            let c = (8 * (l - 1)).min(len - 8);
947            for (i, limb) in r.iter().enumerate().take(l - 1) {
948                if be {
949                    write(p.add(len - 8 - 8 * i), limb.to_be_bytes());
950                } else {
951                    write(p.add(8 * i), limb.to_le_bytes());
952                }
953            }
954            if be {
955                write(p.add(len - 8 - c), r[l - 1].to_be_bytes());
956                write(p, m.top.to_be_bytes());
957            } else {
958                write(p.add(c), r[l - 1].to_le_bytes());
959                write(p.add(len - 8), m.top.to_le_bytes());
960            }
961            return;
962        }
963        if len <= SMALL {
964            write_small(p, order, r[0], r[1], len);
965            return;
966        }
967        let (full, rem) = (len / 8, len % 8);
968        for (i, limb) in r.iter().enumerate().take(full) {
969            if be {
970                write(p.add(len - 8 - 8 * i), limb.to_be_bytes());
971            } else {
972                write(p.add(8 * i), limb.to_le_bytes());
973            }
974        }
975        if rem > 0 {
976            let k = 8 * rem as u32;
977            let top = (r[full - 1] >> k) | (r[full] << (64 - k));
978            if be {
979                write(p, top.to_be_bytes());
980            } else {
981                write(p.add(len - 8), top.to_le_bytes());
982            }
983        }
984    }
985}
986
987/// Writes the medium result `m` as the whole value of `v`, in its vector when it has room, in a
988/// new one otherwise.
989#[inline(always)]
990fn put_medium(v: &mut Vec<u8>, order: ByteOrder, m: &Medium) {
991    if v.capacity() < m.len {
992        *v = Vec::with_capacity(m.len);
993    }
994    // SAFETY: the vector has room for the `len` bytes, all of which are written before the length
995    // is set.
996    unsafe {
997        write_medium(v.as_mut_ptr(), order, m);
998        v.set_len(m.len);
999    }
1000}
1001
1002/// The medium result `m` as a number in one new vector, in the byte order `order`.
1003#[inline(never)]
1004fn medium_number(order: ByteOrder, m: &Medium) -> Number {
1005    let mut value = Vec::new();
1006    put_medium(&mut value, order, m);
1007    Number {
1008        value,
1009        negative: m.negative,
1010        byte_order: order,
1011    }
1012}
1013
1014// The general path: operands of more than 64 bytes, out of line, so that the small path saves no
1015// registers for it.
1016
1017/// `a op b` for borrowed operands, of which at least one has more than 64 bytes.
1018#[inline(never)]
1019fn ref_ref(a: &Number, b: &Number, op: Op) -> Number {
1020    let plan = plan(a, b, op);
1021    Number {
1022        value: new_result(a, b, &plan),
1023        negative: plan.negative,
1024        byte_order: a.byte_order,
1025    }
1026}
1027
1028/// `a op b` for a borrowed `a` and an owned `b`, of which at least one has more than 64 bytes.
1029/// The result takes the vector of `b` when it is built there, leaving `b` an empty one; the
1030/// caller drops `b` either way.
1031#[inline(never)]
1032fn ref_value(a: &Number, b: &mut Number, op: Op) -> Number {
1033    let order = a.byte_order;
1034    // The operations are symmetric: `b op a` over `b`, when it is in the result's byte order.
1035    if b.byte_order == order
1036        && let Some(negative) = over(&mut b.value, order, b.negative, a, op)
1037    {
1038        return Number {
1039            value: mem::take(&mut b.value),
1040            negative,
1041            byte_order: order,
1042        };
1043    }
1044    let plan = plan(a, b, op);
1045    let value = if b.value.capacity() >= plan.len {
1046        if b.byte_order != order {
1047            b.value.reverse();
1048            b.byte_order = order;
1049        }
1050        // SAFETY: the vector of `b`, in the byte order of the result now, has room for it, and the
1051        // plan with the operands swapped is that of `b` and `a`.
1052        unsafe { in_vector(&mut b.value, order, a, &plan.swapped()) };
1053        mem::take(&mut b.value)
1054    } else {
1055        new_result(a, b, &plan)
1056    };
1057    Number {
1058        value,
1059        negative: plan.negative,
1060        byte_order: order,
1061    }
1062}
1063
1064/// `a op= b` for a borrowed `b`, where at least one of them has more than 64 bytes.
1065#[inline(never)]
1066fn assign_ref(a: &mut Number, b: &Number, op: Op) {
1067    if let Some(negative) = over(&mut a.value, a.byte_order, a.negative, b, op) {
1068        a.negative = negative;
1069        return;
1070    }
1071    let plan = plan(a, b, op);
1072    if a.value.capacity() >= plan.len {
1073        // SAFETY: the vector of `a` has room for the result, and the plan is that of `a` and `b`.
1074        unsafe { in_vector(&mut a.value, a.byte_order, b, &plan) };
1075    } else {
1076        a.value = new_result(a, b, &plan);
1077    }
1078    a.negative = plan.negative;
1079}
1080
1081/// `a op= b` for an owned `b`, where at least one of them has more than 64 bytes. When the
1082/// result is built in the vector of `b`, the vector of `a` goes to `b`; the caller drops `b`
1083/// either way.
1084#[inline(never)]
1085fn assign_value(a: &mut Number, b: &mut Number, op: Op) {
1086    let order = a.byte_order;
1087    if let Some(negative) = over(&mut a.value, order, a.negative, b, op) {
1088        a.negative = negative;
1089        return;
1090    }
1091    let plan = plan(a, b, op);
1092    if a.value.capacity() >= plan.len {
1093        // SAFETY: the vector of `a` has room for the result, and the plan is that of `a` and `b`.
1094        unsafe { in_vector(&mut a.value, order, b, &plan) };
1095    } else if b.value.capacity() >= plan.len {
1096        if b.byte_order != order {
1097            b.value.reverse();
1098            b.byte_order = order;
1099        }
1100        // SAFETY: the vector of `b`, in the byte order of the result now, has room for it, and the
1101        // plan with the operands swapped is that of `b` and `a`.
1102        unsafe { in_vector(&mut b.value, order, a, &plan.swapped()) };
1103        mem::swap(&mut a.value, &mut b.value);
1104    } else {
1105        a.value = new_result(a, b, &plan);
1106    }
1107    a.negative = plan.negative;
1108}
1109
1110// Over an operand
1111
1112/// `x op y` written over `x`, the magnitude in `v` in the layout `order` with the sign
1113/// `negative_x`, as the general path's first try, when it is simple: `v` has room for the result
1114/// in the shortest form, which big-endian also ends where `x` does, and a borrow or a carry runs
1115/// through one limb at most, as for random operands. Then the plan is cut short: the length of the
1116/// result is the longer magnitude's when the result takes its top bytes, and otherwise found from
1117/// the top down, one read for random operands; the head is one limb, computed and written first;
1118/// and the rest is one call to the kernel and a copy. Returns the sign of the result, or `None`,
1119/// with nothing written, for the cases left to the plan.
1120///
1121/// Measured on an Apple M4 Max over operands in the level-1 cache, the plan and its second pass
1122/// over the head cost a `^=` of 256 bytes about 340 instructions a call, 57 cycles; this path,
1123/// 250 instructions and 35 to 38 cycles.
1124#[inline]
1125fn over(v: &mut Vec<u8>, order: ByteOrder, negative_x: bool, y: &Number, op: Op) -> Option<bool> {
1126    // SAFETY: `v` and `y` are a valid vector and number.
1127    unsafe {
1128        match (
1129            order == ByteOrder::BigEndian,
1130            y.byte_order == ByteOrder::BigEndian,
1131        ) {
1132            (true, true) => over_in::<true, true>(v, negative_x, y, op),
1133            (true, false) => over_in::<true, false>(v, negative_x, y, op),
1134            (false, true) => over_in::<false, true>(v, negative_x, y, op),
1135            (false, false) => over_in::<false, false>(v, negative_x, y, op),
1136        }
1137    }
1138}
1139
1140/// [`over`] for `x` in the layout `XBE` and `y` in `YBE`.
1141///
1142/// # Safety
1143///
1144/// None beyond the validity of `v` and `y`; unsafe for the raw reads and writes inside.
1145#[inline(never)]
1146unsafe fn over_in<const XBE: bool, const YBE: bool>(
1147    v: &mut Vec<u8>,
1148    negative_x: bool,
1149    y: &Number,
1150    op: Op,
1151) -> Option<bool> {
1152    let n = v.len();
1153    let lx = sig_len::<XBE>(v);
1154    let ly = sig_len::<YBE>(&y.value);
1155    let (nx, ny) = (negative_x && lx > 0, y.negative && ly > 0);
1156    let (g, negative) = select(op, nx, ny);
1157    let tail = tail_of(g, lx, ly);
1158    let (long, short) = (lx.max(ly), lx.min(ly));
1159    let x = end::<XBE>(v);
1160    let ye = end::<YBE>(&y.value);
1161    // SAFETY: the reads are of the significant bytes of each magnitude.
1162    let (head, lo) = unsafe {
1163        if nx | ny | negative {
1164            let mut flags = Flags {
1165                x: nx,
1166                y: ny,
1167                carry: negative,
1168            };
1169            let w = flags.next(g, limb::<XBE>(x, lx, 0), limb::<YBE>(ye, ly, 0));
1170            if flags.running() || short < 8 {
1171                return None;
1172            }
1173            (w, 8)
1174        } else {
1175            (0, 0)
1176        }
1177    };
1178    let len = if tail != Tail::Zero {
1179        long
1180    } else {
1181        // SAFETY: the positions below `short` are significant in both magnitudes.
1182        match unsafe { highest::<XBE, YBE>(g, x, ye, lo, short) } {
1183            Some(len) => len,
1184            None if lo == 0 => return None,
1185            // The head's limb, alone.
1186            None => 8 - (head | 1).leading_zeros() as usize / 8,
1187        }
1188    };
1189    if v.capacity() < len || (XBE && len != n) {
1190        return None;
1191    }
1192    let base = v.as_mut_ptr();
1193    // SAFETY: the result ends where `x` does, big-endian, as `len == n`; the reads are of the
1194    // significant bytes of each magnitude, the writes of the `len <= capacity` bytes of `v`, each
1195    // limb or block of `x` read before it is written over at the same positions. The bulk ends at
1196    // `len` when that is below `short`, and the head is at most `len` long but for its zero bytes.
1197    unsafe {
1198        let dst = if XBE { base.add(n) } else { base };
1199        let x = dst.cast_const();
1200        if lo > 0 {
1201            put_limb::<XBE>(dst, len, 0, head);
1202        }
1203        let bulk = short.min(len);
1204        if bulk > lo {
1205            let k = bulk - lo;
1206            logic::<false>(
1207                g,
1208                XBE != YBE,
1209                at_mut::<XBE>(dst, lo, k),
1210                at::<XBE>(x, lo, k),
1211                at::<YBE>(ye, lo, k),
1212                k,
1213            );
1214        }
1215        if tail == Tail::Y {
1216            let k = long - short;
1217            if XBE != YBE {
1218                kernels::copy_reversed(at_mut::<XBE>(dst, short, k), at::<YBE>(ye, short, k), k);
1219            } else {
1220                ptr::copy_nonoverlapping(at::<YBE>(ye, short, k), at_mut::<XBE>(dst, short, k), k);
1221            }
1222        }
1223        v.set_len(len);
1224    }
1225    Some(negative)
1226}
1227
1228/// What the bytes of the result of `g` above the shorter magnitude are, for magnitudes of `lx`
1229/// and `ly` significant bytes: `g(x, 0)` is `x` for `|`, `^` and `x & !y`, and zero for the
1230/// others; `g(0, y)` likewise.
1231#[inline(always)]
1232fn tail_of(g: u8, lx: usize, ly: usize) -> Tail {
1233    // Bit `g` of each mask: whether `g` keeps the longer `x`, or the longer `y`.
1234    const KEEPS_X: u8 = 1 << OR | 1 << XOR | 1 << AND_NOT;
1235    const KEEPS_Y: u8 = 1 << OR | 1 << XOR | 1 << NOT_AND;
1236    if lx > ly && KEEPS_X >> g & 1 != 0 {
1237        Tail::X
1238    } else if ly > lx && KEEPS_Y >> g & 1 != 0 {
1239        Tail::Y
1240    } else {
1241        Tail::Zero
1242    }
1243}
1244
1245/// The significant length of the magnitude in `v` in the layout `BE`: its length when its top
1246/// byte is not zero, as in the shortest form, at the cost of one read, and otherwise as
1247/// [`significant_len`] finds it.
1248#[inline(always)]
1249fn sig_len<const BE: bool>(v: &[u8]) -> usize {
1250    let n = v.len();
1251    // SAFETY: the top byte is read when there is one.
1252    if n > 0 && unsafe { get::<BE>(end::<BE>(v), n - 1) } != 0 {
1253        n
1254    } else {
1255        significant_len::<BE>(v)
1256    }
1257}
1258
1259// Planning
1260
1261/// What the bytes of the result above the shorter magnitude are.
1262#[derive(Clone, Copy, PartialEq, Eq)]
1263enum Tail {
1264    /// Zero: the result ends below them.
1265    Zero,
1266    /// Those of `x`.
1267    X,
1268    /// Those of `y`.
1269    Y,
1270}
1271
1272/// Everything about the result of a bitwise operation on `x` and `y` but its bytes.
1273#[derive(Clone, Copy)]
1274struct Plan {
1275    /// The operation on the bytes of the magnitudes (or of the magnitudes less one).
1276    g: u8,
1277    /// The significant length of `x`.
1278    lx: usize,
1279    /// The significant length of `y`.
1280    ly: usize,
1281    /// Whether `x` is negative and not zero: `X - 1` is taken instead of `X`.
1282    nx: bool,
1283    /// Whether `y` is negative and not zero.
1284    ny: bool,
1285    /// Whether the result is negative: one is added to what `g` gives.
1286    negative: bool,
1287    /// The number of limbs at the low end through which a borrow or the carry runs, worked out
1288    /// one at a time; above them, each byte of the result is `g` of the operands' bytes.
1289    head: usize,
1290    /// The bytes of the result above the shorter magnitude.
1291    tail: Tail,
1292    /// The length of the result in the shortest form: one byte for zero.
1293    len: usize,
1294}
1295
1296impl Plan {
1297    /// The plan of the same operation with `x` and `y` swapped.
1298    #[inline(always)]
1299    fn swapped(&self) -> Plan {
1300        Plan {
1301            g: match self.g {
1302                AND_NOT => NOT_AND,
1303                NOT_AND => AND_NOT,
1304                g => g,
1305            },
1306            lx: self.ly,
1307            ly: self.lx,
1308            nx: self.ny,
1309            ny: self.nx,
1310            tail: match self.tail {
1311                Tail::X => Tail::Y,
1312                Tail::Y => Tail::X,
1313                Tail::Zero => Tail::Zero,
1314            },
1315            ..*self
1316        }
1317    }
1318}
1319
1320/// The borrows of `X - 1` and `Y - 1` and the carry of the result's `+ 1`, from one limb to the
1321/// next.
1322struct Flags {
1323    x: bool,
1324    y: bool,
1325    carry: bool,
1326}
1327
1328impl Flags {
1329    /// The limb of the result from the limbs `x` and `y` of the magnitudes at the same position,
1330    /// and the flags for the next limb. A borrow out of `X - 1` stops at the lowest nonzero limb
1331    /// of `X`, and the carry at the lowest limb of `g` that is not all ones.
1332    #[inline(always)]
1333    fn next(&mut self, g: u8, x: u64, y: u64) -> u64 {
1334        let xm = x.wrapping_sub(u64::from(self.x));
1335        self.x &= x == 0;
1336        let ym = y.wrapping_sub(u64::from(self.y));
1337        self.y &= y == 0;
1338        let m = apply(g, xm, ym);
1339        let r = m.wrapping_add(u64::from(self.carry));
1340        self.carry &= m == u64::MAX;
1341        r
1342    }
1343
1344    /// Whether a borrow or the carry is still running.
1345    #[inline(always)]
1346    fn running(&self) -> bool {
1347        self.x | self.y | self.carry
1348    }
1349}
1350
1351/// The plan of `a op b`, with `x` = `a` and `y` = `b`.
1352#[inline]
1353fn plan(a: &Number, b: &Number, op: Op) -> Plan {
1354    match (
1355        a.byte_order == ByteOrder::BigEndian,
1356        b.byte_order == ByteOrder::BigEndian,
1357    ) {
1358        (true, true) => plan_in::<true, true>(a, b, op),
1359        (true, false) => plan_in::<true, false>(a, b, op),
1360        (false, true) => plan_in::<false, true>(a, b, op),
1361        (false, false) => plan_in::<false, false>(a, b, op),
1362    }
1363}
1364
1365/// [`plan`] for `a` in the layout `XBE` and `b` in `YBE`.
1366#[inline(always)]
1367fn plan_in<const XBE: bool, const YBE: bool>(a: &Number, b: &Number, op: Op) -> Plan {
1368    let lx = sig_len::<XBE>(&a.value);
1369    let ly = sig_len::<YBE>(&b.value);
1370    let (nx, ny) = (a.negative && lx > 0, b.negative && ly > 0);
1371    let (g, negative) = select(op, nx, ny);
1372    let tail = tail_of(g, lx, ly);
1373    let (xe, ye) = (end::<XBE>(&a.value), end::<YBE>(&b.value));
1374    // The head, and the length of its part of the result.
1375    let (mut head, mut top) = (0, 0);
1376    if nx | ny | negative {
1377        let mut flags = Flags {
1378            x: nx,
1379            y: ny,
1380            carry: negative,
1381        };
1382        loop {
1383            // SAFETY: `limb` reads the significant bytes of each magnitude only. The loop ends:
1384            // past both magnitudes, whose borrows end at their lowest nonzero byte, `g(0, 0)` is
1385            // zero and ends the carry.
1386            let r = unsafe { flags.next(g, limb::<XBE>(xe, lx, head), limb::<YBE>(ye, ly, head)) };
1387            if r != 0 {
1388                top = 8 * head + 8 - r.leading_zeros() as usize / 8;
1389            }
1390            head += 1;
1391            if !flags.running() {
1392                break;
1393            }
1394        }
1395    }
1396    let (long, short) = (lx.max(ly), lx.min(ly));
1397    let len = if 8 * head >= long {
1398        top.max(1)
1399    } else if tail != Tail::Zero {
1400        // The top byte of the longer magnitude, which is not zero.
1401        long
1402    } else {
1403        // SAFETY: the positions below `short` are significant in both magnitudes.
1404        unsafe { highest::<XBE, YBE>(g, xe, ye, 8 * head, short) }.unwrap_or(top.max(1))
1405    };
1406    Plan {
1407        g,
1408        lx,
1409        ly,
1410        nx,
1411        ny,
1412        negative,
1413        head,
1414        tail,
1415        len,
1416    }
1417}
1418
1419/// The length up to the highest nonzero byte of `g(x, y)` at positions `lo..hi`, or `None` when
1420/// they are all zero: from the top down, eight positions at a time, so that for random operands
1421/// the first read decides.
1422///
1423/// # Safety
1424///
1425/// Positions `lo..hi` of the magnitudes at the least significant ends `x` (layout `XBE`) and `y`
1426/// (layout `YBE`) must be valid for reads.
1427#[inline(always)]
1428unsafe fn highest<const XBE: bool, const YBE: bool>(
1429    g: u8,
1430    x: *const u8,
1431    y: *const u8,
1432    lo: usize,
1433    hi: usize,
1434) -> Option<usize> {
1435    let mut q = hi;
1436    // SAFETY: every read is of positions from `lo` to `hi`.
1437    unsafe {
1438        while q >= lo + 8 {
1439            let m = apply(g, load::<XBE>(x, q - 8), load::<YBE>(y, q - 8));
1440            if m != 0 {
1441                return Some(q - m.leading_zeros() as usize / 8);
1442            }
1443            q -= 8;
1444        }
1445        while q > lo {
1446            let m = apply(
1447                g,
1448                u64::from(get::<XBE>(x, q - 1)),
1449                u64::from(get::<YBE>(y, q - 1)),
1450            );
1451            if m as u8 != 0 {
1452                return Some(q);
1453            }
1454            q -= 1;
1455        }
1456    }
1457    None
1458}
1459
1460// Building the result
1461
1462/// Where the result is written, relative to the magnitude `x` it is computed from.
1463#[derive(Clone, Copy, PartialEq, Eq)]
1464enum Place {
1465    /// In a vector of its own.
1466    New,
1467    /// Over `x`, at the same positions.
1468    Same,
1469    /// Over `x`, `d > 0` bytes further on in memory: a big-endian result longer than the vector
1470    /// of `x`, whose least significant byte is at the end.
1471    Above,
1472    /// Over `x`, `d > 0` bytes further back in memory: a big-endian result shorter than the vector
1473    /// of `x`.
1474    Below,
1475}
1476
1477/// The limbs of the head a result written [`Place::Below`] its operand holds back until the rest
1478/// is written: as many as random operands need, one, and more. A longer head moves the operand
1479/// first.
1480const HELD: usize = 4;
1481
1482/// The result of `plan` in one new vector of exactly its length, from `x` = `a` and `y` = `b`.
1483fn new_result(a: &Number, b: &Number, plan: &Plan) -> Vec<u8> {
1484    let mut v = Vec::<u8>::with_capacity(plan.len);
1485    let p = v.as_mut_ptr();
1486    // SAFETY: the new vector has room for the `len` bytes of the result, all of which `compute`
1487    // writes, apart from the operands.
1488    unsafe {
1489        match (
1490            a.byte_order == ByteOrder::BigEndian,
1491            b.byte_order == ByteOrder::BigEndian,
1492        ) {
1493            (true, true) => compute::<true, true>(
1494                p.add(plan.len),
1495                end::<true>(&a.value),
1496                end::<true>(&b.value),
1497                plan,
1498                Place::New,
1499            ),
1500            (true, false) => compute::<true, false>(
1501                p.add(plan.len),
1502                end::<true>(&a.value),
1503                end::<false>(&b.value),
1504                plan,
1505                Place::New,
1506            ),
1507            (false, true) => compute::<false, true>(
1508                p,
1509                end::<false>(&a.value),
1510                end::<true>(&b.value),
1511                plan,
1512                Place::New,
1513            ),
1514            (false, false) => compute::<false, false>(
1515                p,
1516                end::<false>(&a.value),
1517                end::<false>(&b.value),
1518                plan,
1519                Place::New,
1520            ),
1521        }
1522        v.set_len(plan.len);
1523    }
1524    v
1525}
1526
1527/// Computes the result of `plan` over `x`, the magnitude in `v` in the layout `order`, and `y`,
1528/// and sets the length of `v` to it.
1529///
1530/// # Safety
1531///
1532/// The capacity of `v` must be at least the length of the result, and the plan that of `x` and
1533/// `y`.
1534#[inline(always)]
1535unsafe fn in_vector(v: &mut Vec<u8>, order: ByteOrder, y: &Number, plan: &Plan) {
1536    let (n, len) = (v.len(), plan.len);
1537    let base = v.as_mut_ptr();
1538    // SAFETY: as the caller guarantees: the vector has room for the `len` bytes, all of which
1539    // `compute` writes. Big-endian, `x` ends at `n` and the result at `len`.
1540    unsafe {
1541        if order == ByteOrder::BigEndian {
1542            let place = match len.cmp(&n) {
1543                core::cmp::Ordering::Equal => Place::Same,
1544                core::cmp::Ordering::Greater => Place::Above,
1545                core::cmp::Ordering::Less => Place::Below,
1546            };
1547            let (dst, x) = (base.add(len), base.add(n).cast_const());
1548            if y.byte_order == ByteOrder::BigEndian {
1549                compute::<true, true>(dst, x, end::<true>(&y.value), plan, place);
1550            } else {
1551                compute::<true, false>(dst, x, end::<false>(&y.value), plan, place);
1552            }
1553        } else if y.byte_order == ByteOrder::BigEndian {
1554            compute::<false, true>(base, base, end::<true>(&y.value), plan, Place::Same);
1555        } else {
1556            compute::<false, false>(base, base, end::<false>(&y.value), plan, Place::Same);
1557        }
1558        v.set_len(len);
1559    }
1560}
1561
1562/// Writes the `len` bytes of the result of `plan` at the least significant end `dst` in the
1563/// layout `XBE`, from the magnitudes at the least significant ends `x` (layout `XBE`) and `y`
1564/// (`YBE`), with `dst` placed as `place` says relative to `x`: the head limb by limb, the bytes
1565/// above it up to the shorter magnitude by the kernels, and the tail copied.
1566///
1567/// Over `x`, every byte of it is read before it is written over: at the same positions each
1568/// limb or block is read before it is written; for a result further on in memory, the head
1569/// first and the rest from the least significant byte up; for one further back, the head is
1570/// held back (or `x` moved first, for a long head), the tail first and the rest from the most
1571/// significant byte down.
1572///
1573/// # Safety
1574///
1575/// The magnitudes' significant bytes must be valid for reads, `dst` for writing the `len` bytes,
1576/// and `place` true of them; the plan must be that of `x` and `y`.
1577#[inline(never)]
1578unsafe fn compute<const XBE: bool, const YBE: bool>(
1579    dst: *mut u8,
1580    x: *const u8,
1581    y: *const u8,
1582    plan: &Plan,
1583    place: Place,
1584) {
1585    let mixed = XBE != YBE;
1586    let len = plan.len;
1587    let short = plan.lx.min(plan.ly);
1588    let lo = 8 * plan.head;
1589    // The head's limbs below the end of the result, the bulk `lo..bulk` and the tail `rest..len`.
1590    let held = plan.head.min(len.div_ceil(8));
1591    let bulk = short.min(len);
1592    let rest = short.max(lo);
1593    // SAFETY: as the caller guarantees; every position written is below `len`, and every one
1594    // read is significant in its magnitude. The order of the steps is that of the doc comment.
1595    unsafe {
1596        match place {
1597            Place::Below if held > HELD => {
1598                // Moves the bytes of `x` the result needs to its positions first: those below
1599                // the result's end, which is all that the result depends on.
1600                let m = plan.lx.min(len);
1601                ptr::copy(x.sub(m), dst.sub(m), m);
1602                let moved = Plan { lx: m, ..*plan };
1603                compute::<XBE, YBE>(dst, dst, y, &moved, Place::Same);
1604            }
1605            Place::Below => {
1606                let mut limbs = [0u64; HELD];
1607                let mut flags = Flags {
1608                    x: plan.nx,
1609                    y: plan.ny,
1610                    carry: plan.negative,
1611                };
1612                for (i, w) in limbs.iter_mut().enumerate().take(held) {
1613                    *w = flags.next(
1614                        plan.g,
1615                        limb::<XBE>(x, plan.lx, i),
1616                        limb::<YBE>(y, plan.ly, i),
1617                    );
1618                }
1619                tail::<XBE, YBE>(dst, x, y, plan, rest, place);
1620                if bulk > lo {
1621                    let n = bulk - lo;
1622                    logic::<false>(
1623                        plan.g,
1624                        mixed,
1625                        at_mut::<XBE>(dst, lo, n),
1626                        at::<XBE>(x, lo, n),
1627                        at::<YBE>(y, lo, n),
1628                        n,
1629                    );
1630                }
1631                for (i, &w) in limbs.iter().enumerate().take(held) {
1632                    put_limb::<XBE>(dst, len, i, w);
1633                }
1634            }
1635            _ => {
1636                let mut flags = Flags {
1637                    x: plan.nx,
1638                    y: plan.ny,
1639                    carry: plan.negative,
1640                };
1641                for i in 0..held {
1642                    let w = flags.next(
1643                        plan.g,
1644                        limb::<XBE>(x, plan.lx, i),
1645                        limb::<YBE>(y, plan.ly, i),
1646                    );
1647                    put_limb::<XBE>(dst, len, i, w);
1648                }
1649                if bulk > lo {
1650                    let n = bulk - lo;
1651                    let (d, xs, ys) = (
1652                        at_mut::<XBE>(dst, lo, n),
1653                        at::<XBE>(x, lo, n),
1654                        at::<YBE>(y, lo, n),
1655                    );
1656                    if place == Place::Above {
1657                        logic::<true>(plan.g, mixed, d, xs, ys, n);
1658                    } else {
1659                        logic::<false>(plan.g, mixed, d, xs, ys, n);
1660                    }
1661                }
1662                tail::<XBE, YBE>(dst, x, y, plan, rest, place);
1663            }
1664        }
1665    }
1666}
1667
1668/// Writes the tail of the result, positions `rest..len`, from the longer magnitude, unless they
1669/// are already there; or the zero byte of a zero result that nothing else writes.
1670///
1671/// # Safety
1672///
1673/// As for [`compute`].
1674#[inline(always)]
1675unsafe fn tail<const XBE: bool, const YBE: bool>(
1676    dst: *mut u8,
1677    x: *const u8,
1678    y: *const u8,
1679    plan: &Plan,
1680    rest: usize,
1681    place: Place,
1682) {
1683    let len = plan.len;
1684    if len <= rest {
1685        return;
1686    }
1687    let n = len - rest;
1688    // SAFETY: as the caller guarantees: positions `rest..len` are significant in the longer
1689    // magnitude, and below `len` in the result.
1690    unsafe {
1691        match plan.tail {
1692            Tail::X if place != Place::Same => {
1693                ptr::copy(at::<XBE>(x, rest, n), at_mut::<XBE>(dst, rest, n), n);
1694            }
1695            Tail::Y if XBE != YBE => {
1696                kernels::copy_reversed(at_mut::<XBE>(dst, rest, n), at::<YBE>(y, rest, n), n);
1697            }
1698            Tail::Y => {
1699                ptr::copy_nonoverlapping(at::<YBE>(y, rest, n), at_mut::<XBE>(dst, rest, n), n);
1700            }
1701            Tail::Zero => {
1702                // Zero, from operands of which one is zero and neither is negative: its byte is
1703                // all that the head and the bulk leave out.
1704                ptr::write_bytes(at_mut::<XBE>(dst, rest, n), 0, n);
1705            }
1706            Tail::X => {}
1707        }
1708    }
1709}
1710
1711/// A kernel: `dst[k] = g(x[k], y[k])` over `n` bytes.
1712type Kernel = unsafe fn(*mut u8, *const u8, *const u8, usize);
1713
1714/// The kernels by direction, `y` reversed or not, and the operation `g`.
1715const KERNELS: [[[Kernel; 5]; 2]; 2] = [
1716    [
1717        [
1718            kernels::logic::<AND, false, false>,
1719            kernels::logic::<OR, false, false>,
1720            kernels::logic::<XOR, false, false>,
1721            kernels::logic::<AND_NOT, false, false>,
1722            kernels::logic::<NOT_AND, false, false>,
1723        ],
1724        [
1725            kernels::logic::<AND, true, false>,
1726            kernels::logic::<OR, true, false>,
1727            kernels::logic::<XOR, true, false>,
1728            kernels::logic::<AND_NOT, true, false>,
1729            kernels::logic::<NOT_AND, true, false>,
1730        ],
1731    ],
1732    [
1733        [
1734            kernels::logic::<AND, false, true>,
1735            kernels::logic::<OR, false, true>,
1736            kernels::logic::<XOR, false, true>,
1737            kernels::logic::<AND_NOT, false, true>,
1738            kernels::logic::<NOT_AND, false, true>,
1739        ],
1740        [
1741            kernels::logic::<AND, true, true>,
1742            kernels::logic::<OR, true, true>,
1743            kernels::logic::<XOR, true, true>,
1744            kernels::logic::<AND_NOT, true, true>,
1745            kernels::logic::<NOT_AND, true, true>,
1746        ],
1747    ],
1748];
1749
1750/// Runs the kernel of the operation `g` over the `n` bytes at `dst`, `x` and `y`, in the order
1751/// of memory, `y` reversed when `mixed`; from the top down when `DOWN`. One call through a table,
1752/// whose target is the same from one call to the next for the same operation and signs.
1753///
1754/// # Safety
1755///
1756/// As for the kernels.
1757#[inline(always)]
1758unsafe fn logic<const DOWN: bool>(
1759    g: u8,
1760    mixed: bool,
1761    dst: *mut u8,
1762    x: *const u8,
1763    y: *const u8,
1764    n: usize,
1765) {
1766    // SAFETY: as the caller guarantees; `g` is one of the five operations.
1767    unsafe { KERNELS[usize::from(DOWN)][usize::from(mixed)][usize::from(g)](dst, x, y, n) }
1768}
1769
1770// Not
1771
1772/// `!a` for a borrowed `a`, in one new vector: `-(A + 1)` for `a >= 0`, `A - 1` for `a < 0`.
1773#[inline(never)]
1774fn not_new(a: &Number) -> Number {
1775    let order = a.byte_order;
1776    if a.value.len() <= SMALL {
1777        // SAFETY: the vector holds at most 16 bytes.
1778        let s = unsafe { small_not(a) };
1779        return small_number(order, s);
1780    }
1781    let (value, negative) = if order == ByteOrder::BigEndian {
1782        not_copy::<true>(a)
1783    } else {
1784        not_copy::<false>(a)
1785    };
1786    Number {
1787        value,
1788        negative,
1789        byte_order: order,
1790    }
1791}
1792
1793/// `!a` for a small `a`, in registers.
1794///
1795/// # Safety
1796///
1797/// The vector of `a` must hold at most [`SMALL`] bytes.
1798#[inline(always)]
1799unsafe fn small_not(a: &Number) -> Small {
1800    // SAFETY: as the caller guarantees.
1801    let x = unsafe { read_small(&a.value, a.byte_order) };
1802    if a.negative && x != 0 {
1803        small_of(x - 1, false, false)
1804    } else {
1805        let (m, carry) = x.overflowing_add(1);
1806        small_of(m, carry, true)
1807    }
1808}
1809
1810/// `!a` in a new vector, for `a` in the layout `BE`: its bytes and its sign.
1811///
1812/// For a magnitude of more than eight bytes whose eight least significant ones the `+ 1` (or the
1813/// `- 1`) does not carry (or borrow) out of, as for random numbers, the magnitude is copied and
1814/// those eight bytes written with the one added (or taken); otherwise as [`step`] writes it.
1815fn not_copy<const BE: bool>(a: &Number) -> (Vec<u8>, bool) {
1816    let l = sig_len::<BE>(&a.value);
1817    let src = end::<BE>(&a.value);
1818    let negative = !(a.negative && l > 0);
1819    if l > 8 {
1820        // SAFETY: the eight least significant bytes are significant.
1821        let w = unsafe { load::<BE>(src, 0) };
1822        let (low, out) = if negative {
1823            w.overflowing_add(1)
1824        } else {
1825            w.overflowing_sub(1)
1826        };
1827        if !out {
1828            let mut v = Vec::<u8>::with_capacity(l);
1829            // SAFETY: the new vector has room for the `l` bytes of the result, the magnitude's with
1830            // the eight least significant ones replaced, all of which are written before the
1831            // length is set.
1832            unsafe {
1833                let base = v.as_mut_ptr();
1834                ptr::copy_nonoverlapping(at::<BE>(src, 0, l), base, l);
1835                store::<BE>(if BE { base.add(l) } else { base }, 0, low);
1836                v.set_len(l);
1837            }
1838            return (v, negative);
1839        }
1840    }
1841    // SAFETY: `run` reads the significant bytes only.
1842    let (r, len) = unsafe { run::<BE>(src, l, negative) };
1843    let mut v = Vec::<u8>::with_capacity(len);
1844    let base = v.as_mut_ptr();
1845    let dst = if BE {
1846        // SAFETY: the end of the new vector's `len` bytes.
1847        unsafe { base.add(len) }
1848    } else {
1849        base
1850    };
1851    // SAFETY: the new vector has room for the `len` bytes, all of which `step` writes.
1852    unsafe {
1853        step::<BE>(dst, src, l, r, len, negative, false);
1854        v.set_len(len);
1855    }
1856    (v, negative)
1857}
1858
1859/// `!a` in the vector of `a`.
1860#[inline(never)]
1861fn not_in_place(a: &mut Number) {
1862    if a.value.len() <= SMALL {
1863        // SAFETY: the vector holds at most 16 bytes.
1864        let s = unsafe { small_not(a) };
1865        put_small(&mut a.value, a.byte_order, s);
1866        a.negative = s.negative;
1867        return;
1868    }
1869    if a.byte_order == ByteOrder::BigEndian {
1870        not_in::<true>(a);
1871    } else {
1872        not_in::<false>(a);
1873    }
1874}
1875
1876/// [`not_in_place`] for `a` in the layout `BE`.
1877///
1878/// A magnitude of more than eight bytes whose eight least significant ones the `+ 1` (or the
1879/// `- 1`) does not carry (or borrow) out of, as for random numbers, keeps its length, and only
1880/// those eight bytes are written, in place (big-endian, when no zero byte comes before the
1881/// magnitude). Measured on an Apple M4 Max, `!a` took 15 to 16 cycles so, from 17 bytes to
1882/// 64 KiB, against 18 to 19 with the run and the step of the general case; most of it is the
1883/// moving of `a` in and out, as num-bigint's `!a` takes as long, and GMP's `mpz_com(a, a)`, in
1884/// place, 7.
1885fn not_in<const BE: bool>(a: &mut Number) {
1886    let n = a.value.len();
1887    let l = sig_len::<BE>(&a.value);
1888    let negative = !(a.negative && l > 0);
1889    if l > 8 && (!BE || l == n) {
1890        let base = a.value.as_mut_ptr();
1891        let e = if BE {
1892            // SAFETY: the end of the vector, `l == n` bytes on.
1893            unsafe { base.add(n) }
1894        } else {
1895            base
1896        };
1897        // SAFETY: the eight least significant bytes are significant.
1898        let w = unsafe { load::<BE>(e, 0) };
1899        let (low, out) = if negative {
1900            w.overflowing_add(1)
1901        } else {
1902            w.overflowing_sub(1)
1903        };
1904        if !out {
1905            // SAFETY: the same eight bytes, and `l <= n` bytes stay.
1906            unsafe {
1907                store::<BE>(e, 0, low);
1908                a.value.set_len(l);
1909            }
1910            a.negative = negative;
1911            return;
1912        }
1913    }
1914    // SAFETY: `run` reads the significant bytes only.
1915    let (r, len) = unsafe { run::<BE>(end::<BE>(&a.value), l, negative) };
1916    if a.value.capacity() < len {
1917        // Only `0xFF…FF + 1`, one byte longer, which is all zeros but its top byte.
1918        let (value, negative) = not_copy::<BE>(a);
1919        a.value = value;
1920        a.negative = negative;
1921        return;
1922    }
1923    a.negative = negative;
1924    let base = a.value.as_mut_ptr();
1925    // SAFETY: the vector has room for the `len` bytes of the result, all of which `step` writes.
1926    // Big-endian, a result whose length differs from `l` has all its bytes written, as `step`
1927    // says, so the bytes of `a` need not move; one of the same length as `l` is written over
1928    // them, moved to the start of the vector first when zero bytes come before them.
1929    unsafe {
1930        if BE {
1931            if len == l && n > l {
1932                ptr::copy(base.add(n - l), base, l);
1933            }
1934            let in_place = len == l;
1935            step::<true>(
1936                base.add(len),
1937                base.add(l).cast_const(),
1938                l,
1939                r,
1940                len,
1941                negative,
1942                in_place,
1943            );
1944        } else {
1945            step::<false>(base, base.cast_const(), l, r, len, negative, true);
1946        }
1947        a.value.set_len(len);
1948    }
1949}
1950
1951/// For `!a` with a magnitude of `l` significant bytes at the least significant end `src` in the
1952/// layout `BE`: the position `r` of the lowest byte that the `+ 1` (when `plus`, for a result
1953/// that is negative) or the `- 1` changes, the bytes below it being `0xFF` or zero, and the
1954/// length of the result.
1955///
1956/// # Safety
1957///
1958/// The `l` bytes must be valid for reads.
1959#[inline(always)]
1960unsafe fn run<const BE: bool>(src: *const u8, l: usize, plus: bool) -> (usize, usize) {
1961    // The bytes the run passes through: `0xFF` for `+ 1`, zero for `- 1`.
1962    let pass = if plus { u64::MAX } else { 0 };
1963    let mut r = 0;
1964    // SAFETY: every read is of positions below `l`.
1965    unsafe {
1966        while r + 8 <= l && load::<BE>(src, r) == pass {
1967            r += 8;
1968        }
1969        while r < l && get::<BE>(src, r) == pass as u8 {
1970            r += 1;
1971        }
1972        let len = if plus {
1973            // `0xFF…FF + 1` is one byte longer, and `0 + 1` is 1.
1974            if r == l { l + 1 } else { l }
1975        } else if r + 1 == l && get::<BE>(src, r) == 1 {
1976            // `0x01_00…00 - 1` is one byte shorter, and `1 - 1` is zero, one byte.
1977            (l - 1).max(1)
1978        } else {
1979            l
1980        };
1981        (r, len)
1982    }
1983}
1984
1985/// Writes the `len` bytes of `A + 1` (when `plus`) or `A - 1` at the least significant end `dst`
1986/// in the layout `BE`, for `A` of `l` significant bytes at `src` whose run of `0xFF` (or zero)
1987/// bytes ends at `r`: those bytes turn to zero (or `0xFF`), byte `r` gains (or loses) one, and the
1988/// others are copied, unless `in_place`, where they are already there. A result of another
1989/// length than `l` is all zeros but a top byte of 1, or all `0xFF`, and reads nothing.
1990///
1991/// # Safety
1992///
1993/// `r` and `len` must be those [`run`] gives. The `l` bytes at `src` must be valid for reads and
1994/// the `len` bytes at `dst` for writes; `in_place` only when `dst` is `src`, or `len != l`.
1995#[inline(always)]
1996unsafe fn step<const BE: bool>(
1997    dst: *mut u8,
1998    src: *const u8,
1999    l: usize,
2000    r: usize,
2001    len: usize,
2002    plus: bool,
2003    in_place: bool,
2004) {
2005    let fill = if plus { 0 } else { 0xFF };
2006    // SAFETY: as the caller guarantees; every write is of positions below `len`, every read of
2007    // positions below `l`.
2008    unsafe {
2009        if len != l {
2010            // `0xFF…FF + 1` (or `0 + 1`), all zeros but a top byte of 1, or `0x01_00…00 - 1`,
2011            // all `0xFF`.
2012            ptr::write_bytes(at_mut::<BE>(dst, 0, len), fill, len);
2013            if plus {
2014                set::<BE>(dst, len - 1, 1);
2015            }
2016            return;
2017        }
2018        // Of the same length, the run ends inside the magnitude.
2019        ptr::write_bytes(at_mut::<BE>(dst, 0, r), fill, r);
2020        let byte = get::<BE>(src, r);
2021        set::<BE>(dst, r, if plus { byte + 1 } else { byte - 1 });
2022        if !in_place && l > r + 1 {
2023            let n = l - r - 1;
2024            ptr::copy_nonoverlapping(at::<BE>(src, r + 1, n), at_mut::<BE>(dst, r + 1, n), n);
2025        }
2026    }
2027}
2028
2029// The bits of a number
2030
2031impl Number {
2032    /// Returns the number of bits of the magnitude, `|self|.ilog2() + 1`, or 0 for zero: the
2033    /// position of the highest one plus one, as `BigInt::bits` in num-bigint and
2034    /// `mpz_sizeinbase(x, 2)` in GMP (which gives 1 for zero).
2035    ///
2036    /// It takes constant time for a number in the shortest form: the length of the magnitude and
2037    /// its top byte decide.
2038    ///
2039    /// # Examples
2040    ///
2041    /// ```
2042    /// use a::math::numbers::{ByteOrder, Number};
2043    ///
2044    /// assert_eq!(Number::new_from_i32(-0x1FF, ByteOrder::BigEndian).bits(), 9);
2045    /// assert_eq!(Number::new_from_u64(1 << 40, ByteOrder::LittleEndian).bits(), 41);
2046    /// assert_eq!(Number::new_from_u8(0, ByteOrder::BigEndian).bits(), 0);
2047    /// ```
2048    pub fn bits(&self) -> u64 {
2049        let (l, top) = if self.byte_order == ByteOrder::BigEndian {
2050            top_byte::<true>(&self.value)
2051        } else {
2052            top_byte::<false>(&self.value)
2053        };
2054        if l == 0 {
2055            0
2056        } else {
2057            8 * (l as u64 - 1) + u64::from(8 - top.leading_zeros())
2058        }
2059    }
2060
2061    /// Returns the number of ones in the magnitude, as Python's `int.bit_count` and num-bigint's
2062    /// `BigUint::count_ones` count them, and GMP's `mpz_popcount` for numbers that are not
2063    /// negative: the sign is not counted. (In two's complement a negative number has infinitely
2064    /// many ones, which `mpz_popcount` gives as its largest value.)
2065    ///
2066    /// The bytes are counted as they are stored, in either byte order, sixteen at a time with
2067    /// NEON's `cnt` on aarch64.
2068    ///
2069    /// # Examples
2070    ///
2071    /// ```
2072    /// use a::math::numbers::{ByteOrder, Number};
2073    ///
2074    /// assert_eq!(Number::new_from_i32(0b1011, ByteOrder::BigEndian).count_ones(), 3);
2075    /// // The magnitude of -0b1011 has as many.
2076    /// assert_eq!(Number::new_from_i32(-0b1011, ByteOrder::LittleEndian).count_ones(), 3);
2077    /// ```
2078    pub fn count_ones(&self) -> u64 {
2079        let v = &self.value;
2080        if v.len() <= SMALL {
2081            // As the addition reads a short magnitude, inline; the order of the bytes does not
2082            // matter.
2083            // SAFETY: the vector holds at most 16 bytes.
2084            return u64::from(unsafe { read_small(v, ByteOrder::LittleEndian) }.count_ones());
2085        }
2086        // SAFETY: the bytes of the vector are valid for reads.
2087        unsafe { kernels::count_ones(v.as_ptr(), v.len()) }
2088    }
2089
2090    /// Returns the number of zeros below the lowest one of the magnitude, the position of that
2091    /// one, or `None` for zero, as num-bigint's `BigInt::trailing_zeros` and GMP's `mpz_scan1(x, 0)`
2092    /// give it. The same for `x` and `-x`: in two's complement, `-x` has its lowest one where
2093    /// `x` has.
2094    ///
2095    /// The bytes are read from the least significant up, eight at a time while they are zero, so
2096    /// for random numbers the first read decides.
2097    ///
2098    /// # Examples
2099    ///
2100    /// ```
2101    /// use a::math::numbers::{ByteOrder, Number};
2102    ///
2103    /// assert_eq!(Number::new_from_i32(-0x500, ByteOrder::BigEndian).trailing_zeros(), Some(8));
2104    /// assert_eq!(Number::new_from_u8(0, ByteOrder::LittleEndian).trailing_zeros(), None);
2105    /// ```
2106    pub fn trailing_zeros(&self) -> Option<u64> {
2107        // SAFETY: `lowest` reads the bytes of the vector only.
2108        unsafe {
2109            if self.byte_order == ByteOrder::BigEndian {
2110                lowest::<true>(&self.value)
2111            } else {
2112                lowest::<false>(&self.value)
2113            }
2114        }
2115    }
2116
2117    /// Returns bit `i` of the number in infinite two's complement, as num-bigint's `BigInt::bit`
2118    /// and GMP's `mpz_tstbit`: for a negative number, `-x` is `!x + 1`, so its bits are those of
2119    /// `!(|x| - 1)`, and all those above the magnitude are ones.
2120    ///
2121    /// For a number that is not negative this takes constant time; for a negative one, the bytes
2122    /// below bit `i` are read from the nearest down until one is not zero, which for random
2123    /// numbers is the first.
2124    ///
2125    /// # Examples
2126    ///
2127    /// ```
2128    /// use a::math::numbers::{ByteOrder, Number};
2129    ///
2130    /// // -4 is …11111100.
2131    /// let n = Number::new_from_i32(-4, ByteOrder::BigEndian);
2132    /// assert!(!n.bit(0) && !n.bit(1) && n.bit(2) && n.bit(3) && n.bit(1000));
2133    /// let n = Number::new_from_i32(4, ByteOrder::LittleEndian);
2134    /// assert!(n.bit(2) && !n.bit(3) && !n.bit(1000));
2135    /// ```
2136    pub fn bit(&self, i: u64) -> bool {
2137        if self.byte_order == ByteOrder::BigEndian {
2138            bit_of::<true>(self, i)
2139        } else {
2140            bit_of::<false>(self, i)
2141        }
2142    }
2143
2144    /// Sets bit `i` of the number in infinite two's complement to `value`, as num-bigint's
2145    /// `BigInt::set_bit` and GMP's `mpz_setbit` and `mpz_clrbit` do, and stores the result back
2146    /// as a sign and a magnitude, in the byte order of `self`, in the shortest form.
2147    ///
2148    /// For a number that is not negative, the bit of the magnitude is set or cleared. For a
2149    /// negative one, whose magnitude `X` has its lowest one at position `t`: above `t` the bits are
2150    /// those of `!X`, so setting bit `i > t` clears it in `X` and clearing it sets it; bit `t` is
2151    /// one, and clearing it adds `2^t` to `X`; below `t` the bits are zeros, and setting bit `i`
2152    /// subtracts `2^i` from `X`.
2153    ///
2154    /// The vector grows as needed, by `Vec`'s rules, and shrinks to the shortest form; a
2155    /// big-endian magnitude that grows or shrinks at its top moves its bytes, as its most
2156    /// significant byte comes first. Otherwise a number in the shortest form costs constant time
2157    /// (but for the borrows and carries of a negative number, which for random numbers end in the
2158    /// first byte).
2159    ///
2160    /// # Panics
2161    ///
2162    /// When the result is too long to be allocated.
2163    ///
2164    /// # Examples
2165    ///
2166    /// ```
2167    /// use a::math::numbers::{ByteOrder, Number};
2168    ///
2169    /// let mut n = Number::new_from_i32(5, ByteOrder::BigEndian);
2170    /// n.set_bit(9, true);
2171    /// assert_eq!(n.value, [0x02, 0x05]);
2172    ///
2173    /// // -4 is …11111100: setting bit 0 gives …11111101, -3.
2174    /// let mut n = Number::new_from_i32(-4, ByteOrder::LittleEndian);
2175    /// n.set_bit(0, true);
2176    /// assert_eq!(n.value, [3]);
2177    /// assert!(n.is_negative());
2178    /// // Clearing bit 2 gives …11111001, -7.
2179    /// n.set_bit(2, false);
2180    /// assert_eq!(n.value, [7]);
2181    /// assert!(n.is_negative());
2182    /// ```
2183    #[track_caller]
2184    pub fn set_bit(&mut self, i: u64, value: bool) {
2185        if self.byte_order == ByteOrder::BigEndian {
2186            set_bit_in::<true>(self, i, value);
2187        } else {
2188            set_bit_in::<false>(self, i, value);
2189        }
2190    }
2191}
2192
2193/// The significant length of the magnitude in `v` in the layout `BE`, and its top byte (0 for
2194/// zero).
2195#[inline(always)]
2196fn top_byte<const BE: bool>(v: &[u8]) -> (usize, u8) {
2197    let l = significant_len::<BE>(v);
2198    if l == 0 {
2199        return (0, 0);
2200    }
2201    // SAFETY: position `l - 1` is in the vector.
2202    (l, unsafe { get::<BE>(end::<BE>(v), l - 1) })
2203}
2204
2205/// The position of the lowest one of the magnitude in `v` in the layout `BE`, or `None` for
2206/// zero.
2207///
2208/// # Safety
2209///
2210/// None beyond the validity of `v`; unsafe for the raw reads inside.
2211#[inline(always)]
2212unsafe fn lowest<const BE: bool>(v: &[u8]) -> Option<u64> {
2213    let (e, n) = (end::<BE>(v), v.len());
2214    let mut p = 0;
2215    // SAFETY: every read is of positions below `n`.
2216    unsafe {
2217        while p + 8 <= n {
2218            let w = load::<BE>(e, p);
2219            if w != 0 {
2220                return Some(8 * p as u64 + u64::from(w.trailing_zeros()));
2221            }
2222            p += 8;
2223        }
2224        while p < n {
2225            let b = get::<BE>(e, p);
2226            if b != 0 {
2227                return Some(8 * p as u64 + u64::from(b.trailing_zeros()));
2228            }
2229            p += 1;
2230        }
2231    }
2232    None
2233}
2234
2235/// Whether any of the positions `0..q` of the magnitude at the least significant end `e` in the
2236/// layout `BE` is not zero: from `q - 1` down, eight at a time.
2237///
2238/// # Safety
2239///
2240/// The `q` positions must be valid for reads.
2241#[inline(always)]
2242unsafe fn any_below<const BE: bool>(e: *const u8, q: usize) -> bool {
2243    let mut p = q;
2244    // SAFETY: every read is of positions below `q`.
2245    unsafe {
2246        while p >= 8 {
2247            if load::<BE>(e, p - 8) != 0 {
2248                return true;
2249            }
2250            p -= 8;
2251        }
2252        while p > 0 {
2253            if get::<BE>(e, p - 1) != 0 {
2254                return true;
2255            }
2256            p -= 1;
2257        }
2258    }
2259    false
2260}
2261
2262/// Bit `k` of position `q` of the magnitude at the least significant end `e` in the layout `BE`,
2263/// and whether any bit below it is set: one read of the eight positions that end with `q`, whose
2264/// test a random number passes every time, and only when they are all zero below that bit are
2265/// the positions further down read. (A test of the bits of the byte at `q` alone would be a coin
2266/// toss for a random `k`.) Measured on an Apple M4 Max, `set_bit` of negative numbers of 1 KiB
2267/// at random positions took 8 to 10 cycles so, in either byte order, against 8 and 19 with a
2268/// read of the byte and then of the eight below it, and GMP's `mpz_setbit` 7.
2269///
2270/// # Safety
2271///
2272/// Positions `0..=q` must be valid for reads.
2273#[inline(always)]
2274unsafe fn bit_and_below<const BE: bool>(e: *const u8, q: usize, k: u32) -> (bool, bool) {
2275    // SAFETY: as the caller guarantees; below position 7, `limb` reads the `q + 1` positions.
2276    unsafe {
2277        let (word, s) = if q >= 7 {
2278            (load::<BE>(e, q - 7), 56 + k)
2279        } else {
2280            (limb::<BE>(e, q + 1, 0), 8 * q as u32 + k)
2281        };
2282        let own = (word >> s) & 1 == 1;
2283        let below = word & ((1 << s) - 1) != 0 || (q > 7 && any_below::<BE>(e, q - 7));
2284        (own, below)
2285    }
2286}
2287
2288/// [`Number::bit`] for a number in the layout `BE`.
2289#[inline(always)]
2290fn bit_of<const BE: bool>(a: &Number, i: u64) -> bool {
2291    let (e, n) = (end::<BE>(&a.value), a.value.len());
2292    let (q, k) = (i / 8, (i % 8) as u32);
2293    if q >= n as u64 {
2294        // Above the magnitude: ones for a negative number, which zero is not.
2295        return a.negative && significant_len::<BE>(&a.value) > 0;
2296    }
2297    let q = q as usize;
2298    // SAFETY: position `q` is below `n`.
2299    unsafe {
2300        if !a.negative {
2301            return (get::<BE>(e, q) >> k) & 1 == 1;
2302        }
2303        // Bit `i` of `-x` is that of `x` up to its lowest one, and the opposite above it.
2304        let (own, below) = bit_and_below::<BE>(e, q, k);
2305        own ^ below
2306    }
2307}
2308
2309/// [`Number::set_bit`] for a number in the layout `BE`.
2310#[track_caller]
2311fn set_bit_in<const BE: bool>(a: &mut Number, i: u64, value: bool) {
2312    let l = sig_len::<BE>(&a.value);
2313    if l != a.value.len() || l == 0 {
2314        // The shortest form first: the bytes above the magnitude go, and a zero is not negative.
2315        trim::<BE>(&mut a.value, l);
2316        if l == 0 {
2317            a.negative = false;
2318        }
2319    }
2320    if !a.negative {
2321        if value {
2322            set_magnitude_bit::<BE>(&mut a.value, i);
2323        } else {
2324            clear_magnitude_bit::<BE>(&mut a.value, i);
2325        }
2326        return;
2327    }
2328    // A negative number's bit `i` is that of `!(x - 1)`: the opposite of its magnitude's above
2329    // the lowest one, which is at `i` when no bit below is set and bit `i` is.
2330    let (e, n) = (end::<BE>(&a.value), a.value.len());
2331    let (q, k) = (i / 8, (i % 8) as u32);
2332    let (below, own) = if q >= n as u64 {
2333        (true, false)
2334    } else {
2335        // SAFETY: position `q` is below `n`.
2336        let (own, below) = unsafe { bit_and_below::<BE>(e, q as usize, k) };
2337        (below, own)
2338    };
2339    match (below, own, value) {
2340        // Above the lowest one, the bits are those of `!x`.
2341        (true, _, true) => clear_magnitude_bit::<BE>(&mut a.value, i),
2342        (true, _, false) => set_magnitude_bit::<BE>(&mut a.value, i),
2343        // The lowest one, cleared: `-x - 2^i`, a magnitude `x + 2^i`.
2344        (false, true, false) => add_power::<BE>(&mut a.value, i),
2345        // Below it, set: `-x + 2^i`, a magnitude `x - 2^i`.
2346        (false, false, true) => subtract_power::<BE>(&mut a.value, i),
2347        _ => {}
2348    }
2349}
2350
2351/// Drops the bytes of `v` above its significant length `l`, keeping one byte for zero.
2352fn trim<const BE: bool>(v: &mut Vec<u8>, l: usize) {
2353    let keep = l.max(1);
2354    if v.len() > keep {
2355        if BE {
2356            v.drain(..v.len() - keep);
2357        } else {
2358            v.truncate(keep);
2359        }
2360    } else if v.is_empty() {
2361        v.push(0);
2362    }
2363}
2364
2365/// Grows the magnitude in `v`, in the shortest form, with zero bytes above it to `len` bytes:
2366/// big-endian, its bytes move up to make room for them at the start.
2367///
2368/// # Panics
2369///
2370/// When it cannot be allocated.
2371#[track_caller]
2372fn grow<const BE: bool>(v: &mut Vec<u8>, len: usize) {
2373    let (n, more) = (v.len(), len - v.len());
2374    if v.try_reserve(more).is_err() {
2375        too_long(len);
2376    }
2377    // SAFETY: the vector has room for `len` bytes; big-endian its `n` bytes move up by `more`,
2378    // and the `more` bytes before them, all of the new ones, are set to zero before the length is.
2379    unsafe {
2380        let p = v.as_mut_ptr();
2381        if BE {
2382            ptr::copy(p, p.add(more), n);
2383            ptr::write_bytes(p, 0, more);
2384        } else {
2385            ptr::write_bytes(p.add(n), 0, more);
2386        }
2387        v.set_len(len);
2388    }
2389}
2390
2391/// Panics for a `set_bit` whose result cannot be allocated.
2392#[cold]
2393#[inline(never)]
2394#[track_caller]
2395fn too_long(len: usize) -> ! {
2396    panic!("a number of {len} bytes cannot be allocated")
2397}
2398
2399/// Panics for a `set_bit` at a position beyond any vector.
2400#[cold]
2401#[inline(never)]
2402#[track_caller]
2403fn too_far(i: u64) -> ! {
2404    panic!("a number with bit {i} set cannot be allocated")
2405}
2406
2407/// Sets bit `i` of the magnitude in `v`, in the shortest form, growing it as needed.
2408#[track_caller]
2409fn set_magnitude_bit<const BE: bool>(v: &mut Vec<u8>, i: u64) {
2410    let n = v.len();
2411    let q = i / 8;
2412    if q >= n as u64 {
2413        let Some(len) = usize::try_from(q).ok().and_then(|q| q.checked_add(1)) else {
2414            too_far(i)
2415        };
2416        grow::<BE>(v, len);
2417    }
2418    let n = v.len();
2419    // SAFETY: position `q` is in the vector.
2420    unsafe {
2421        let e = v.as_mut_ptr().add(if BE { n } else { 0 });
2422        let q = q as usize;
2423        set::<BE>(e, q, get::<BE>(e, q) | (1 << (i % 8)));
2424    }
2425}
2426
2427/// Clears bit `i` of the magnitude in `v`, in the shortest form, shrinking it to the shortest
2428/// form.
2429fn clear_magnitude_bit<const BE: bool>(v: &mut Vec<u8>, i: u64) {
2430    let n = v.len();
2431    let q = i / 8;
2432    if q >= n as u64 {
2433        return;
2434    }
2435    let q = q as usize;
2436    // SAFETY: position `q` is in the vector.
2437    let byte = unsafe {
2438        let e = v.as_mut_ptr().add(if BE { n } else { 0 });
2439        let byte = get::<BE>(e, q) & !(1 << (i % 8));
2440        set::<BE>(e, q, byte);
2441        byte
2442    };
2443    if byte == 0 && q + 1 == n {
2444        let l = significant_len::<BE>(v);
2445        trim::<BE>(v, l);
2446    }
2447}
2448
2449/// Adds `2^t` to the magnitude in `v`, in the shortest form, whose bit `t` is set: the carry runs
2450/// through the bytes above that are `0xFF`, and past the top makes it one byte longer.
2451#[track_caller]
2452fn add_power<const BE: bool>(v: &mut Vec<u8>, t: u64) {
2453    let n = v.len();
2454    let mut q = (t / 8) as usize;
2455    // SAFETY: every position read and written is below `n`.
2456    unsafe {
2457        let e = v.as_mut_ptr().add(if BE { n } else { 0 });
2458        let (byte, carry) = get::<BE>(e, q).overflowing_add(1 << (t % 8));
2459        set::<BE>(e, q, byte);
2460        if !carry {
2461            return;
2462        }
2463        q += 1;
2464        while q < n && get::<BE>(e, q) == 0xFF {
2465            set::<BE>(e, q, 0);
2466            q += 1;
2467        }
2468        if q < n {
2469            set::<BE>(e, q, get::<BE>(e, q) + 1);
2470            return;
2471        }
2472    }
2473    grow::<BE>(v, n + 1);
2474    // SAFETY: position `n` is the new top byte.
2475    unsafe {
2476        let e = v.as_mut_ptr().add(if BE { n + 1 } else { 0 });
2477        set::<BE>(e, n, 1);
2478    }
2479}
2480
2481/// Subtracts `2^i` from the magnitude in `v`, in the shortest form, whose bits below `i` are
2482/// zero and which is above `2^i`: the borrow runs through the zero bytes above, and the result is
2483/// left in the shortest form.
2484fn subtract_power<const BE: bool>(v: &mut Vec<u8>, i: u64) {
2485    let n = v.len();
2486    let mut q = (i / 8) as usize;
2487    // SAFETY: every position read and written is below `n`: the magnitude is above `2^i`, so the
2488    // borrow ends inside it.
2489    unsafe {
2490        let e = v.as_mut_ptr().add(if BE { n } else { 0 });
2491        let (byte, borrow) = get::<BE>(e, q).overflowing_sub(1 << (i % 8));
2492        set::<BE>(e, q, byte);
2493        if borrow {
2494            q += 1;
2495            while get::<BE>(e, q) == 0 {
2496                set::<BE>(e, q, 0xFF);
2497                q += 1;
2498            }
2499            set::<BE>(e, q, get::<BE>(e, q) - 1);
2500        }
2501    }
2502    if q + 1 == n {
2503        let l = significant_len::<BE>(v);
2504        trim::<BE>(v, l);
2505    }
2506}
2507
2508// Positions
2509
2510/// The least significant end of the magnitude in `v` in the layout `BE`: the address of its
2511/// first byte little-endian, and the address one past its last byte big-endian.
2512#[inline(always)]
2513fn end<const BE: bool>(v: &[u8]) -> *const u8 {
2514    if BE { v.as_ptr_range().end } else { v.as_ptr() }
2515}
2516
2517/// The lowest address of positions `p..p + n` of the magnitude at the least significant end
2518/// `end` in the layout `BE`: `end + p` little-endian, `end - p - n` big-endian.
2519///
2520/// # Safety
2521///
2522/// The address must lie in the allocation of `end`.
2523#[inline(always)]
2524unsafe fn at<const BE: bool>(end: *const u8, p: usize, n: usize) -> *const u8 {
2525    // SAFETY: as the caller guarantees.
2526    unsafe { if BE { end.sub(p + n) } else { end.add(p) } }
2527}
2528
2529/// [`at`] for writing.
2530///
2531/// # Safety
2532///
2533/// As for [`at`].
2534#[inline(always)]
2535unsafe fn at_mut<const BE: bool>(end: *mut u8, p: usize, n: usize) -> *mut u8 {
2536    // SAFETY: as the caller guarantees.
2537    unsafe { if BE { end.sub(p + n) } else { end.add(p) } }
2538}
2539
2540/// Reads position `p` of the magnitude at the least significant end `end` in the layout `BE`.
2541///
2542/// # Safety
2543///
2544/// The byte must be valid for reading.
2545#[inline(always)]
2546unsafe fn get<const BE: bool>(end: *const u8, p: usize) -> u8 {
2547    // SAFETY: as the caller guarantees.
2548    unsafe { *at::<BE>(end, p, 1) }
2549}
2550
2551/// Writes position `p` of the magnitude at the least significant end `end` in the layout `BE`.
2552///
2553/// # Safety
2554///
2555/// The byte must be valid for writing.
2556#[inline(always)]
2557unsafe fn set<const BE: bool>(end: *mut u8, p: usize, v: u8) {
2558    // SAFETY: as the caller guarantees.
2559    unsafe { *at_mut::<BE>(end, p, 1) = v };
2560}
2561
2562/// Reads positions `p..p + 8` of the magnitude at the least significant end `end` in the layout
2563/// `BE` as a `u64` whose least significant byte is position `p`.
2564///
2565/// # Safety
2566///
2567/// The eight bytes must be valid for reading; they need no alignment.
2568#[inline(always)]
2569unsafe fn load<const BE: bool>(end: *const u8, p: usize) -> u64 {
2570    // SAFETY: as the caller guarantees.
2571    unsafe {
2572        let bytes = read(at::<BE>(end, p, 8));
2573        if BE {
2574            u64::from_be_bytes(bytes)
2575        } else {
2576            u64::from_le_bytes(bytes)
2577        }
2578    }
2579}
2580
2581/// Writes positions `p..p + 8` of the magnitude at the least significant end `end` in the layout
2582/// `BE`, as [`load`] reads them.
2583///
2584/// # Safety
2585///
2586/// The eight bytes must be valid for writing; they need no alignment.
2587#[inline(always)]
2588unsafe fn store<const BE: bool>(end: *mut u8, p: usize, v: u64) {
2589    // SAFETY: as the caller guarantees.
2590    unsafe {
2591        let bytes = if BE { v.to_be_bytes() } else { v.to_le_bytes() };
2592        write(at_mut::<BE>(end, p, 8), bytes);
2593    }
2594}
2595
2596/// Limb `i`, positions `8i..8i + 8`, of the magnitude of `l` significant bytes at the least
2597/// significant end `end` in the layout `BE`, its positions from `l` up zero: a limb inside it as
2598/// it is, the top one from the eight positions that end at `l` (or, below 8, as the addition
2599/// reads a short magnitude), shifted down.
2600///
2601/// # Safety
2602///
2603/// The `l` bytes must be valid for reads.
2604#[inline(always)]
2605unsafe fn limb<const BE: bool>(end: *const u8, l: usize, i: usize) -> u64 {
2606    let p = 8 * i;
2607    // SAFETY: every read is of positions below `l`.
2608    unsafe {
2609        if p + 8 <= l {
2610            load::<BE>(end, p)
2611        } else if p >= l {
2612            0
2613        } else if l >= 8 {
2614            load::<BE>(end, l - 8) >> (8 * (p + 8 - l))
2615        } else {
2616            let order = if BE {
2617                ByteOrder::BigEndian
2618            } else {
2619                ByteOrder::LittleEndian
2620            };
2621            read_small(&*ptr::slice_from_raw_parts(at::<BE>(end, 0, l), l), order) as u64
2622        }
2623    }
2624}
2625
2626/// Writes limb `i` of a result of `len` bytes at the least significant end `end` in the layout
2627/// `BE`: its positions below `len`.
2628///
2629/// # Safety
2630///
2631/// `8 i < len`, and the `len` bytes must be valid for writes.
2632#[inline(always)]
2633unsafe fn put_limb<const BE: bool>(end: *mut u8, len: usize, i: usize, v: u64) {
2634    let p = 8 * i;
2635    // SAFETY: as the caller guarantees; a part of a limb, `n` from 1 to 7 bytes, is written as
2636    // `write_small` writes so short a sum.
2637    unsafe {
2638        if p + 8 <= len {
2639            store::<BE>(end, p, v);
2640        } else {
2641            let n = len - p;
2642            let order = if BE {
2643                ByteOrder::BigEndian
2644            } else {
2645                ByteOrder::LittleEndian
2646            };
2647            write_small(at_mut::<BE>(end, p, n), order, v, 0, n);
2648        }
2649    }
2650}