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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Remainder policy — the per-width algorithm matcher for signed integer
//! remainder.
//!
//! The `Rem` operator for `Int<N>` delegates to [`dispatch`], which follows
//! the canonical policy shape (see `docs/ARCHITECTURE.md` → "Policy file
//! structure"):
//!
//! 1. an [`Algorithm`] enum — the real remainder algorithm(s), 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 arms
//! are dead-arm-eliminated in release: each concrete `Int<N>` routes to a
//! single algorithm with no runtime branch on the const path.
//!
//! # The algorithms and the width split
//!
//! Remainder keys purely on `N`:
//!
//! * **`N <= 2`** (`Int<1>` = D18, `Int<2>` = D38) → [`rem_native`]: the
//! operand magnitude always fits a single `u128`, so a hardware
//! `u128 % u128` with the dividend's sign re-applied is correct and far
//! cheaper than routing through the runtime division dispatcher.
//! Microbenched at the dispatch seam: native beats the via-div-rem path
//! ~1.85x at `N == 1` and ~3.0x at `N == 2`.
//! * **`N >= 3`** → [`rem_small_fast`]: at the wide tiers the FULL-width
//! magnitude exceeds `u128`, but the integer-remainder operands are
//! frequently small (a bare integer, a scale-0 decimal). `rem_small_fast`
//! takes the same hardware `u128 % u128` whenever BOTH magnitudes fit a
//! single word — bypassing the `[u64; N]` quotient scratch and the
//! `div_rem::dispatch` shape classifier — and falls back to the multi-limb
//! divmod ([`rem_via_div_rem`]'s path) otherwise. This is a
//! single-word fast path applied generically (one kernel, value-gated, valid
//! at every `N`). Benched (`rem_kernel_ab`): `small_fast` beats the bare
//! `via_div_rem` 1.1–2.6× on small operands (the scale-0 shape) at every
//! wide tier and is at parity on full-width operands. The multi-limb
//! divmod fallback IS the division policy's Knuth / Burnikel–Ziegler
//! boundary; a remainder-only Knuth pass (skipping the quotient store) was
//! microbenched and showed no win (the quotient store is negligible next
//! to the multiply-subtract pass), so the fallback stays the full divmod.
//!
//! The `ByValue` arm of [`Select`] is present for canonical-shape
//! uniformity; `select` never returns it (the split is by `N` alone, not by
//! operand value).
//!
//! # Why `dispatch` is NOT `const fn` (and `wrapping_rem` is)
//!
//! The single algorithm (`rem_via_div_rem`) delegates to
//! [`crate::int::policy::div_rem::dispatch`], which is NOT `const fn`
//! (the division dispatcher classifies divisor shapes at runtime — a
//! `ByValue` value-matcher whose fn pointer cannot be called in a `const`
//! context). Therefore `dispatch` here cannot be `const fn` either.
//!
//! `Int<N>::wrapping_rem` **is** `const fn` and preserves that property by
//! NOT routing through this non-const dispatcher: it calls
//! [`crate::int::algos::div::div_rem`] (the const single-algorithm fast path)
//! directly, exactly as it did before this policy file was introduced. Only
//! the selection SEAM (the `Algorithm`/`Select`/`select` shape) is shared;
//! `wrapping_rem` keeps its existing const-safe implementation. This design
//! matches the existing const-ness contract exactly — no const path is
//! removed, no non-const path gains const.
//!
//! # Routed primitive
//!
//! The `Rem for Int<N>` operator routes through `dispatch` (non-const).
//! `Int<N>::wrapping_rem` (const) routes directly through
//! [`crate::int::algos::div::div_rem`] and is not altered.
use craterem_native;
use craterem_schoolbook;
use craterem_small_fast;
use craterem_via_div_rem;
use crateInt;
// ── 1. the real remainder algorithm — NAMED, no `Default` ────────────
/// The remainder algorithms this policy chooses between. The single variant
/// is the CamelCase of the algorithm fn's name minus the `rem_` function
/// prefix (`rem_via_div_rem` → `ViaDivRem`) — strict 1:1 with the
/// algorithm fn.
// ── 2. the verdict ────────────────────────────────────────────────────
/// A settled algorithm, or "the value decides". The rem picker always
/// returns `ByAlgorithm`: the choice is fully determined by `N` (which is
/// constant, and the same algorithm wins at every `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 remainder algorithm for storage limb count `N`. Total over
/// the key: `Native` for `N <= 2` (the magnitude always fits a `u128`),
/// `SmallFast` for the wide tiers (a value-gated single-word fast path with
/// a multi-limb divmod fallback).
const
// ── 4. the dispatcher: fold the verdict, then dispatch ────────────────
/// Signed integer remainder dispatcher for `Int<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 single algorithm delegates to
/// [`crate::int::policy::div_rem::dispatch`], which is a runtime-shape
/// value-matcher and therefore cannot be `const fn`. This matches the
/// existing non-const `Rem for Int<N>` operator path. `Int<N>::wrapping_rem`
/// (which IS `const fn`) does NOT route through this dispatcher; it calls the
/// const [`crate::int::algos::div::div_rem`] fast path directly, preserving
/// its existing const-ness. The `ByValue` arm returns the default algorithm
/// tag without invoking the fn pointer — no fn pointer call occurs in the
/// const-select block.
pub