1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Per-width / limb-count algorithm-selection dispatch.
//!
//! The integer layer's counterpart to the decimal `policy/` bucket:
//! the place where operand width / limb count selects which kernel
//! runs. Unlike the decimal families, the integer types carry **no
//! `SCALE`** — `Int<N>` / `Uint<N>` and the named `Int*` / `Uint*`
//! aliases are pure fixed-width integers — so the dispatch key is the
//! limb count `N` (a compile-time const at every monomorphisation) and,
//! for division, the **runtime shape** of the operands (effective limb
//! count after stripping leading zeros). There is therefore no
//! `match (W, SCALE)` table to write for this layer: the decimal
//! `match (W, SCALE)` form has no `SCALE` axis here, and the divmod
//! selection cannot be a compile-time match because it keys on a
//! property only known at run time.
//!
//! The per-family dispatch as it actually ships today:
//!
//! - **add** — width-keyed only, one algorithm at every `N`. Routes
//! through [`add::dispatch`] (a `const fn` policy so the block folds
//! per monomorphisation) to [`crate::int::algos::support::limbs::add_assign_fixed`]
//! (the ripple-carry kernel).
//! - **sub** — width-keyed only, one algorithm at every `N`. Routes
//! through [`sub::dispatch`] (`const fn`) to
//! [`crate::int::algos::support::limbs::sub_assign_fixed`] (the ripple-borrow kernel).
//! - **neg** — unary, one algorithm at every `N`. Routes through
//! [`neg::dispatch`] (`const fn`) to the two's-complement bitwise-NOT-
//! plus-one kernel.
//! - **cmp** — width-keyed only, one algorithm at every `N`. Routes the
//! signed same-width total-order comparison through [`cmp::dispatch`]
//! (`const fn`) to the limbwise signed-comparison kernel.
//! - **eq** — width-keyed only, one algorithm at every `N`. Routes the
//! equality test through [`eq::dispatch`] (`const fn`) to the limbwise
//! equality kernel.
//! - **rem** — derives the remainder via the division policy. Routes the
//! `Rem` operator through [`rem::dispatch`] (NOT `const fn`, because
//! it delegates to [`div_rem::dispatch`] which is runtime-shape keyed).
//! `Int<N>::wrapping_rem` (which IS `const fn`) calls the const
//! [`crate::int::algos::div::div_rem`] algo directly.
//! - **mul** — schoolbook at every width. The fixed-width types use the
//! truncated low-`N` schoolbook product
//! ([`crate::int::algos::mul::mul_schoolbook::mul_low_fixed`] /
//! [`crate::int::algos::sqr::sqr_low_fixed::sqr_low_fixed`]);
//! the slice dispatcher [`mul::dispatch`] additionally
//! crosses over to Karatsuba at the benched 48-limb threshold, so
//! D924 (48) / D1232 (64) storage products and wider cross-scale
//! multiplies take Karatsuba while the narrower widths stay schoolbook.
//! - **÷ 10^SCALE** (decimal scale-narrowing) — this `(W, SCALE)`-keyed
//! path is part of the **decimal** storage boundary, not the integer
//! layer: D18 narrow tiers divide on hardware
//! (`i128_divrem_by_u64_with_mode`), D38 takes the 2-word MG path, and
//! the wide tiers route `mg_divide::div_wide_pow10`, which selects
//! MG-single (`SCALE ≤ 19`, divisor fits one word) vs MG-lifted
//! (wider) internally. It lives in `crate::algos::support::mg_divide` /
//! `crate::macros::arithmetic`; the integer layer exposes only the raw
//! divmod the wide path builds on.
//! - **divmod** — divisor-shape keyed at run time
//! ([`div_rem::dispatch`]): single-limb divisor (incl. every
//! `10^scale`, `scale ≤ 19`) takes the hardware fast path; a divisor of
//! `n ≥ 16` limbs whose numerator top ≥ `2·n` takes Burnikel–Ziegler;
//! everything else takes Knuth Algorithm D. The const-evaluable
//! `wrapping_div` / `wrapping_rem` stay on the `const fn`
//! [`div_rem::div_rem`] so they can run at compile time.
//! - **isqrt** — `N ∈ {1, 2}` takes the hardware native path (`u64::isqrt`/
//! `u128::isqrt`); `N >= 3` takes the Newton limb kernel
//! ([`crate::int::algos::isqrt::isqrt_newton::isqrt_newton`]). Routes through
//! [`isqrt::dispatch`] (const `N`-keyed; not `const fn`).
//! - **icbrt** — same shape as isqrt: `N ∈ {1, 2}` routes through the
//! Newton kernel at small width; `N >= 3` takes the full Newton limb
//! iteration ([`crate::int::algos::icbrt::icbrt_newton::icbrt_newton`]). Routes through
//! [`icbrt::dispatch`] (not `const fn`).
//! - **pow** — binary square-and-multiply at every `N`. Routes through
//! [`pow::dispatch`] (`const fn`).
//! - **sqr** — half-product squaring kernel at every `N`. Routes through
//! [`sqr::dispatch`] (`const fn`).
//! - **cube** — sqr-then-multiply at every `N`. Routes through
//! [`cube::dispatch`] (`const fn`).
//! - **sum_sq** — `a^2 + b^2` (schoolbook) at every `N`. Routes through
//! [`sum_sq::dispatch`]; the hypot kernel shares its radicand former.
//! - **hypot** — `round(sqrt(a^2 + b^2))` at every `N`. Routes through
//! [`hypot::dispatch`] to the Pythagoras kernel (forms the `sum_sq`
//! radicand, then the Newton slice `isqrt` + round step).
//!
//! All dispatchers follow the canonical [`Select`] / `select` /
//! exhaustive-`match algo` policy shape (see `docs/ARCHITECTURE.md` →
//! "Policy file structure"). The add / sub / neg / cmp / eq dispatchers
//! are pure `ByAlgorithm` `const fn` (the const block folds, no runtime
//! branch). The divmod and mul dispatchers key on the operands' *runtime*
//! shape (effective limb count / operand length) and are
//! `Select::ByValue`-style value matchers: the const layer settles on
//! "the shape decides", the matcher classifies, and the dispatcher does an
//! exhaustive `match algo` to the pure engines / kernels in
//! [`crate::int::algos::div`] / [`crate::int::algos::support::limbs`]. The rem
//! dispatcher is non-const and delegates to the divmod dispatcher.
//! The benched crossover thresholds ([`div_rem::BZ_THRESHOLD`] and `mul`'s
//! file-private Karatsuba threshold) are policy DATA in those files, not
//! magic numbers in the kernels.
/// Addition policy: default-delegating ripple-carry matcher for `Int<N>`.
pub
/// Signed comparison policy: default-delegating limbwise matcher for `Int<N>`.
pub
/// Integer cube policy: sqr-then-multiply matcher for `Uint<N>`.
pub
/// Division/remainder policy: divisor-shape algorithm matcher for `Int<N>`.
pub
/// Equality policy: default-delegating limbwise matcher for `Int<N>`.
pub
/// Integer hypotenuse policy: isqrt-vs-schoolbook matcher for `Int<N>`.
pub
/// Integer cube-root policy: native-vs-Newton matcher for `Uint<N>`.
pub
/// Integer square-root policy: native-vs-Newton matcher for `Uint<N>`.
pub
/// Multiply policy: schoolbook-vs-Karatsuba algorithm matcher.
pub
/// Truncated-low multiply policy: the `u64`/`u128` limb-width matcher.
pub
/// Negate policy: default-delegating two's-complement matcher for `Int<N>`.
pub
/// Integer exponentiation policy: square-and-multiply matcher for `Uint<N>`.
pub
/// Remainder policy: default-delegating via-div_rem matcher for `Int<N>`.
pub
/// Integer squaring policy: half-product via-mul matcher for `Uint<N>`.
pub
/// Truncated-low squaring policy: the `u64`/`u128` limb-width matcher.
pub
/// Subtract policy: default-delegating ripple-borrow matcher for `Int<N>`.
pub
/// Integer sum-of-squares policy: `a^2 + b^2` schoolbook matcher for `Int<N>`.
pub