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
use ;
use crateDistanceMatrix;
/// Smallest point count [`Engine::Auto`] routes. The conversion costs one
/// pass over the matrix, and a short reduction cannot earn that back.
pub const N_MIN: usize = 32;
/// Numerator of the highest edge density [`Engine::Auto`] routes:
/// `m / C(n, 2)` at the resolved threshold, with `m` the finite pairs at or
/// below it. The cutoff is four fifths, and [`density_routes`] applies it
/// as `5 * m <= 4 * C(n, 2)` so that no rounding of `0.8` and no rounding
/// of a large count enters the decision.
///
/// Above the cutoff the graph would only spend memory on edges the matrix
/// already holds.
pub const RHO_MAX_NUM: u128 = 4;
/// Denominator of [`RHO_MAX_NUM`].
pub const RHO_MAX_DEN: u128 = 5;
/// The threshold a dense run applies: the caller's, or the enclosing
/// radius.
pub
/// True when a dense input can route at all. Below [`N_MIN`] points the
/// answer is dense whatever the matrix holds, so the counting pass never
/// runs. A negative threshold is an error the engine reports, and a NaN
/// threshold fails the comparison, so neither routes.
///
/// An infinite threshold does route. It admits every finite pair and no
/// absent one, and a matrix of mostly absent pairs has a sparse graph at
/// that threshold, so the density cutoff is what decides. A matrix with no
/// absent pair has every pair as an edge and fails the cutoff.
pub
/// True when the edge density at the threshold is at or below the frozen
/// cutoff. `edges` is the count at the same threshold.
///
/// A dense matrix stores every pair, so `C(n, 2)` is bounded by the address
/// space and both products fit u128 with room to spare.
pub
/// Bytes the conversion holds per retained edge at its peak.
///
/// `DistanceMatrix::to_sparse_at` writes both directed entries of an edge
/// into one index array (`u32`, 4 bytes each) and one value array (`f64`,
/// 8 bytes each), so an edge costs 24 bytes. No triplet buffer exists.
pub const CONVERSION_BYTES_PER_EDGE: u128 = 24;
/// Bytes the conversion holds per point at its peak: the degree count, the
/// row offset, and the fill cursor, 8 bytes each. One more offset closes
/// the last row.
pub const CONVERSION_BYTES_PER_POINT: u128 = 24;
/// Smallest conversion budget [`Engine::Auto`] grants, in bytes. A small
/// matrix is a few kilobytes, too little for any useful graph, so the
/// budget never falls below this.
pub const MIN_CONVERSION_BYTES: u128 = 32 * 1024 * 1024;
/// The pairs of `n` points, `C(n, 2)`, wide enough not to overflow.
pub
/// True when the conversion peak fits the budget: [`MIN_CONVERSION_BYTES`],
/// or the bytes of the compact matrix (8 per pair), whichever is larger.
/// `edges` is the count at the resolved threshold.
///
/// The density cutoff bounds the graph in proportion to the matrix, and
/// this bounds it in bytes: a routed run then peaks at about twice the
/// compact matrix, below the dense engine's peak in the square form.
/// [`Engine::Sparse`] is an explicit request and ignores the budget.
pub
/// True when the counted graph is worth building: its density is at or
/// below the cutoff and its conversion fits the budget.
pub
/// Smallest compact matrix [`DenseStorage::Auto`] converts, in bytes. The
/// bound is 1025 points.
///
/// The full form doubles the matrix. Below this size both the matrix and
/// the reduction are small in absolute terms, so `Auto` keeps the compact
/// form and leaves the second triangle to a caller who asks for it.
///
/// Frozen on 2026-08-18 from disclosed engineering data.
pub const SQUARE_MIN_BYTES: u128 = 4 << 20;
/// Most bytes [`DenseStorage::Auto`] adds for the full form. The full form
/// adds `n(n+1)/2` entries, the compact matrix again plus its diagonal, so
/// this bounds the point count as well: 8191 points.
///
/// The bound caps what a run spends on a storage form nobody asked for.
/// [`DenseStorage::Square`] is an explicit request and ignores it.
pub const SQUARE_EXTRA_MAX_BYTES: u128 = 256 << 20;
/// Distance reads per matrix cell the fold must make before
/// [`DenseStorage::Auto`] converts. The conversion writes `n * n` cells,
/// and those reads are what the full form makes contiguous, so the ratio
/// is what the conversion has to earn back. The dim-0 columns supply one
/// read per cell on their own, so the test asks the columns above them for
/// three more.
pub const SQUARE_READS_PER_CELL: u128 = 4;
/// Bytes the full form adds over the compact one: the entries above the
/// diagonal and the diagonal itself.
pub
/// Distances the cofacet diameter fold reads, as the rule estimates them.
///
/// Two terms. The dim-0 columns classify the cofacets of every vertex, so
/// they read the whole matrix once: `n * n`. Each dim-1 column then walks
/// the candidate range and reads one distance per candidate, so the dim-1
/// columns read `edges * n` between them, and from `max_dim` 2 up the
/// assembly enumerates the same cofacets once more per further dimension.
pub
/// True when the matrix is large enough for the full form to pay and its
/// added bytes fit the budget.
pub
/// True when the fold reads enough distances to earn the conversion.
pub
/// True when the dense run reduces from the full form. `edges` is the
/// count at `threshold` when the caller has already made it; the rule
/// counts for itself only when the size test has already passed, so a run
/// that cannot convert never pays for a pass.
pub