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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Integer square-root policy — the native-vs-Newton algorithm matcher.
//!
//! `Uint<N>::isqrt` delegates to [`dispatch`], which follows the canonical
//! policy shape (see `docs/ARCHITECTURE.md` → "Policy file structure"):
//!
//! 1. an [`Algorithm`] enum — the real isqrt algorithms, no `Default`
//! variant;
//! 2. a [`Select`] verdict — a settled algorithm or "the value decides";
//! 3. a `const fn` [`select`] keyed on `N`, total over the key;
//! 4. dispatch via an inline `const { select::<N>() }` block, then an
//! **exhaustive** `match algo` — no `_`, no panic.
//!
//! Because `select` is `const` and keyed only on the const generic `N`,
//! the `const { … }` block folds per monomorphisation and the unchosen arm
//! is dead-arm-eliminated in release: each concrete `Uint<N>` compiles to a
//! direct call to the chosen kernel, no runtime branch.
//!
//! # Algorithm selection
//!
//! The two algorithms correspond directly to the arms of the existing
//! const-`N` ladder in [`crate::int::algos::isqrt::isqrt_mag_fixed::isqrt_mag_fixed`], which
//! this policy formalises:
//!
//! - **`N ∈ {1, 2}`** → [`isqrt_native`]: single hardware instruction via
//! `u64::isqrt` (`N == 1`) or `u128::isqrt` (`N == 2`). The fastest path
//! at these widths; genuinely width-bespoke (no generic form).
//! - **`N >= 3`** → [`isqrt_newton`]: width-agnostic Newton iteration with a
//! hardware-`f64::sqrt` seed over u64 limbs — one algorithm serving every
//! wider int. Today's `limbs_isqrt_u64` (now in `int/algos/roots.rs`).
//!
//! The `ByValue` arm of [`Select`] is present for canonical-shape uniformity;
//! `select` never returns it (the choice is fully determined by `N`).
//!
//! # Const-ness
//!
//! `dispatch` is **not** `const fn`. The `Newton` arm calls
//! [`isqrt_newton`], which performs Newton iteration and is not
//! const-evaluable. The `Native` arm could in principle be `const`, but
//! because the policy must accommodate both arms a single `const fn` is not
//! possible. `Uint<N>::isqrt` is therefore not `const fn`.
use crateisqrt_karatsuba as isqrt_karatsuba_kernel;
use crateisqrt_mag_fixed;
use crateisqrt_schoolbook as isqrt_schoolbook_kernel;
use crateUint;
// ── 1. the real isqrt algorithms — NAMED, no `Default` ───────────────
/// The integer square-root algorithms this policy chooses between. Variants
/// are the CamelCase of each kernel fn's name minus the `isqrt_` function
/// prefix — strict 1:1 with the kernel fns.
///
/// Names follow RULES §4: `isqrt_native` → `Native`, `isqrt_newton` →
/// `Newton`.
// ── 2. the verdict ────────────────────────────────────────────────────
/// A settled algorithm, or "the value decides". The isqrt picker always
/// returns `ByAlgorithm`: the choice is fully determined by `N`. `ByValue`
/// is part of the canonical shape for uniformity across functions; `select`
/// never returns it.
// ── 3. the matcher: const, keyed on `N`, total over the key ──────────
/// Pick the isqrt algorithm for storage limb count `N`. Total over the key.
///
/// - `N ∈ {1, 2}` → [`Algorithm::Native`] (hardware single-instruction path).
/// - `3 <= N < 64` → [`Algorithm::Newton`] (generic limb Newton).
/// - `N >= 64` (the widest tier, D1232) → [`Algorithm::Karatsuba`]: the
/// half-width-divide recursion crosses over Newton here (the `isqrt_ab` A/B
/// win-region; below it Newton's lower constant factor wins).
const
// ── algorithm fns: thin delegations to the existing kernels ──────────
/// Native hardware integer square root for `Uint<N>` where `N ∈ {1, 2}`.
///
/// Delegates to [`isqrt_mag_fixed`] which const-splits on `N` internally:
/// `N == 1` → `u64::isqrt`, `N == 2` → `u128::isqrt`. Both are single
/// hardware instructions on modern ISAs.
pub
/// Newton integer square root for `Uint<N>` where `N >= 3`.
///
/// Delegates to [`isqrt_mag_fixed`] which routes to
/// [`crate::int::algos::isqrt::isqrt_newton::isqrt_newton`] for `N >= 3`: Newton
/// iteration with a hardware-`f64::sqrt` seed over the u64 limbs.
pub
/// Karatsuba Square Root for `Uint<N>` — the widest-tier (`N >= 64`) arm.
///
/// Delegates to
/// [`isqrt_karatsuba_kernel`][`crate::int::algos::isqrt::isqrt_karatsuba::isqrt_karatsuba`]:
/// the RR-3805 recursion whose per-level divide is half-width and runs only
/// `O(log n)` times. Bit-identical to [`isqrt_newton`]; the `isqrt_ab` A/B
/// shows it wins at `N == 64` where Newton's full-width-divide-per-iteration
/// cost finally dominates.
pub
/// Schoolbook two-bits-at-a-time integer square root for `Uint<N>`.
///
/// Delegates to
/// [`isqrt_schoolbook_kernel`][`crate::int::algos::isqrt::isqrt_schoolbook::isqrt_schoolbook`]:
/// classical bitwise digit-by-digit algorithm; no division, no float seed.
/// Serves any `N` as a generic reference baseline.
pub
// ── 4. the dispatcher: fold the verdict, then dispatch ────────────────
/// Integer square-root dispatcher for `Uint<N>`.
///
/// Resolves the compile-time algorithm verdict via
/// `const { select::<N>() }` (folds per monomorphisation; dead arms are
/// eliminated in release) then dispatches exhaustively over [`Algorithm`].
///
/// Not `const fn`: the `Newton` arm delegates to
/// [`crate::int::algos::isqrt::isqrt_newton::isqrt_newton`] (Newton iteration, not
/// const-evaluable).
pub