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
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Hypot policy — the per-`(N, SCALE)` algorithm matcher for
//! `sqrt(self² + other²)` (hypotenuse without intermediate overflow).
//!
//! See `docs/ARCHITECTURE.md` → "Policy file structure".
//!
//! `D<Int<N>, SCALE>::hypot_strict_with(other, mode)` delegates directly to
//! the one shared [`dispatch`] generic function. `dispatch` follows the
//! canonical policy shape (mirroring [`crate::policy::sqrt`]):
//!
//! 1. an [`Algorithm`] enum — the real hypot algorithms, no `Default`
//! variant;
//! 2. a [`Select`] verdict — a settled algorithm or "the value decides"
//! (`hypot` 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.
//!
//! # Algorithm
//!
//! The single algorithm ([`crate::algos::hypot::hypot_pythagoras`]) forms the
//! radicand `a² + b²` in a limb scratch buffer and takes the root via the
//! int layer's width-agnostic slice `isqrt`. The root goes **down** to the
//! integer layer; the kernel never calls the decimal `sqrt` surface on the
//! tier's own value. No work-width parameter — the policy is a pure
//! `(N, SCALE)` matcher (see [`crate::policy::sqrt`] for the limb-expansion
//! rationale).
//!
//! `hypot(0, 0) = 0` (bit-exact); `hypot(0, x) = |x|` (`isqrt(x²) = |x|`).
use cratehypot;
use crate;
use crateInt;
use crateRoundingMode;
// ── 1. the real hypot algorithm — NAMED, no `Default` ────────────────
/// The hypot algorithms this policy chooses between. The single variant is
/// the CamelCase of the kernel name minus the `hypot_` prefix — strict 1:1
/// with the kernel computation.
// ── 2. the const verdict ──────────────────────────────────────────────
/// A settled algorithm, or "the value decides". The hypot picker always
/// returns `ByAlgorithm`. `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 hypot algorithm for storage limb count `N` and decimal `SCALE`.
/// Total over the key; `Pythagoras` wins at every `(N, SCALE)`.
const
// ── 4. the shared dispatch: resolve the verdict, then dispatch ────────
/// Shared hypot dispatch for storage `Int<N>`, decimal `SCALE`. Both
/// operands carry the same `10^SCALE`, so it cancels out of the root and
/// this is exactly integer hypot on the raw storages (dispatched DOWN to the
/// int tier, which forms `a² + b²` in a limb scratch buffer). No work-width
/// parameter; `SCALE` only labels the out-of-range panic. Negative inputs
/// are handled by squaring (sign drops out).
pub
/// The `checked` primitive under [`dispatch`]: the kernel's own
/// out-of-range `None` propagates instead of panicking. `dispatch` is
/// the unwrap-or-panic wrapper over this single detection point (the
/// overflow contract's "detect once, apply the policy in the wrapper").
pub