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
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Add policy — the per-`(N, SCALE)` algorithm matcher for decimal addition.
//!
//! `D<Int<N>, SCALE>` addition delegates to [`AddPolicy::add_impl`], which
//! forwards to the one shared [`dispatch`] function. `dispatch` follows the
//! canonical policy shape (see `docs/ARCHITECTURE.md` → "Policy file
//! structure"):
//!
//! 1. an [`Algorithm`] enum — the real addition algorithm, no `Default`
//! variant;
//! 2. a [`Select`] verdict — a settled algorithm or "the value decides"
//! (add has no value split, so `ByValue` is never returned);
//! 3. a `const fn` [`select`] keyed on `(N, SCALE)`, total over the key;
//! 4. dispatch via an inline `const { select::<N, SCALE>() }` block, then
//! an **exhaustive** `match algo` — no `_`, no panic.
//!
//! Because `select` is `const` and keyed only on the const generics, the
//! `const { … }` block folds per monomorphisation and every unchosen arm
//! is dead-arm-eliminated in release: each concrete `D<Int<N>, SCALE>`
//! compiles to a direct call to one kernel, no runtime branch.
//!
//! # Why there is only one algorithm
//!
//! Decimal addition does not require rescaling: both operands share the same
//! `SCALE`, so the storage-level sum is the answer. The single algorithm
//! (`add_int_layer`) delegates to `Int<N>`'s `checked_add` and panics on
//! overflow in both debug and release (the default operator never silently
//! wraps a wrong number). There is no crossover threshold, no work-width
//! widening, and no value-dependent split. `ByValue` is present for
//! canonical-shape uniformity; `select` never returns it.
use crateInt;
// ── 1. the real addition algorithm — NAMED, no `Default` ─────────────
/// The addition algorithms this policy chooses between. The single variant
/// is the CamelCase of the kernel fn's name minus the `add_` function
/// prefix (`add_int_layer` → `IntLayer`) — strict 1:1 with the kernel fn.
// ── 2. the verdict ────────────────────────────────────────────────────
/// A settled algorithm, or "the value decides". The add picker always
/// returns `ByAlgorithm`: the choice is fully determined by `(N, SCALE)`
/// (which is constant, and the same algorithm wins at every combination).
/// `ByValue` is part of the canonical shape for uniformity; `select` never
/// returns it.
// ── 3. the matcher: const, keyed on `(N, SCALE)`, total over the key ──
/// Pick the addition algorithm for storage limb count `N` and decimal
/// `SCALE`. Total over the key; `IntLayer` wins at every `(N, SCALE)`.
const
// ── 4. the dispatcher: fold the verdict, then dispatch ────────────────
/// Decimal addition dispatcher for storage `Int<N>` and decimal `SCALE`.
///
/// Resolves the compile-time algorithm verdict via
/// `const { select::<N, SCALE>() }` (folds per monomorphisation; dead arms
/// are eliminated in release) then dispatches exhaustively over
/// [`Algorithm`].
///
/// Not `const fn`: matches the existing non-`const` `Add` operator on
/// `D<Int<N>, SCALE>`.
pub
// ── per-type `AddPolicy` trait ────────────────────────────────────────
/// Per-type policy: which kernel a `D<Int<N>, SCALE>` uses for `+`.
pub