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
// SPDX-FileCopyrightText: 2026 John Moxley
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Integer hypotenuse policy -- the per-`N` algorithm matcher for
//! `round(sqrt(a^2 + b^2))`.
//!
//! `Int<N>::hypot` delegates to [`dispatch`], which follows the canonical
//! policy shape (see `docs/ARCHITECTURE.md` -> "Policy file structure"):
//!
//! 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`, 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 `N`, the `const { ... }`
//! block folds per monomorphisation and the unchosen arm is
//! dead-arm-eliminated in release: each concrete `Int<N>` compiles to a
//! direct call to one kernel, no runtime branch.
//!
//! # Algorithm
//!
//! Two algorithms:
//!
//! - [`crate::int::algos::hypot::hypot_pythagoras`] -- form `a^2 + b^2` in a
//! limb scratch buffer, take the floor root via the Newton slice `isqrt`,
//! round. The width-agnostic exact path.
//! - [`crate::int::algos::hypot::hypot_u128_fast`] -- a value-gated wrapper
//! with TWO scalar fast arms: when both operands fit a single `u64` limb the
//! radicand fits a `u128`, rooted in `u128`; when both fit two `u64` limbs
//! (`< 2^128`) the radicand fits a `u256`, rooted in fixed `u256`/`u128`
//! scalar arithmetic (Newton whose only divide is a fixed `u256 / u128`
//! long division -- no multi-precision `div_rem`). Both round with the exact
//! remainder; operands beyond `2^128` fall through to `hypot_pythagoras`,
//! paying only the cheap `fit_k` guard. Bit-identical to `hypot_pythagoras`
//! for every input and `RoundingMode`.
//!
//! `select` returns [`Algorithm::U128Fast`] at **every** `N`. The `hypot_ab`
//! microbench (per-width, per-shape; pinned core 22) measured `u128_fast`
//! ~3.5x faster than `pythagoras` on single-`u64`-limb operands (`single`) and
//! ~2.0-2.5x faster on two-`u64`-limb operands (`two` -- the decimal `s >= 19`
//! slow band that would otherwise fall to Pythagoras) at every tier
//! from `N=2` through `N=64`, and statistically TIED on full-width
//! (`multi`/`skew`) operands where the fast branch falls through. So the fast
//! path strictly dominates the plain Pythagoras path at every width;
//! `Pythagoras` is the kept-but-unselected fallback (and remains the kernel
//! `u128_fast` itself delegates to). The per-width root choice inside the
//! fallback is the `isqrt` policy's job, not hypot's.
//!
//! Returns [`None`] from the kernel on true overflow (the rounded root does
//! not fit the signed range of `Int<N>`); the type method maps that to its
//! `Option` return.
use cratehypot_pythagoras;
use cratehypot_u128_fast;
use crate;
use crateInt;
use crateRoundingMode;
// -- 1. the real hypot algorithms -- NAMED, no `Default` --------------
/// The integer hypotenuse algorithms this policy chooses between. Variants
/// are the CamelCase of each kernel fn's name minus the `hypot_` prefix --
/// strict 1:1 with the kernel fns.
// -- 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`, total over the key -----------
/// Pick the integer hypot algorithm for storage limb count `N`. Total over
/// the key. Every tier takes the native scalar fast path
/// ([`Algorithm::U128Fast`]): the `hypot_ab` microbench (pinned, per-shape)
/// measured it ~3.5x faster than [`Algorithm::Pythagoras`] on single-`u64`-limb
/// operands and ~2.0-2.5x faster on two-`u64`-limb operands (`< 2^128`) --
/// across `N=2..=64` -- and statistically tied on full-width operands (it just
/// falls through to Pythagoras, paying only the cheap `fit_k` guard). So it
/// strictly dominates the plain Pythagoras path at every width; `Pythagoras`
/// is the kept fallback, never selected directly.
const
// -- 4. the shared dispatch: resolve the verdict, then dispatch --------
/// Integer hypotenuse 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`].
/// Returns [`None`] when the rounded root does not fit the signed range of
/// `Int<N>` (true overflow). Negative inputs are handled by squaring (the
/// sign drops out).
pub