use super::*;
pub(crate) const SAE_BYTES_PER_F64: usize = 8;
pub(crate) const SAE_HOST_IN_CORE_FALLBACK_BYTES: usize = 2 * 1024 * 1024 * 1024;
pub(crate) const SAE_HOST_MEMORY_BUDGET_FRACTION_NUMERATOR: usize = 3;
pub(crate) const SAE_HOST_MEMORY_BUDGET_FRACTION_DENOMINATOR: usize = 5;
pub(crate) const SAE_CPU_L2_CACHE_BYTES: usize = 1024 * 1024;
pub(crate) const SAE_CHUNK_CACHE_MULTIPLE: usize = 8;
pub(crate) const SAE_MIN_STREAMING_CHUNK_ROWS: usize = 256;
pub(crate) const SAE_MATRIX_FREE_VECTOR_WORKSPACE_MULTIPLIER: usize = 32;
pub(crate) const SAE_HOST_MEMORY_RESERVE_FRACTION_DENOMINATOR: usize = 8;
pub(crate) const SAE_HOST_MEMORY_RESERVE_FLOOR_BYTES: usize = 256 * 1024 * 1024;
pub(crate) const SAE_MIN_DEVICE_POOL_IN_CORE_BUDGET_BYTES: usize = 64 * 1024 * 1024;
pub(crate) const SAE_MIN_STREAMING_BUDGET_FLOOR_BYTES: usize = 64 * 1024 * 1024;
pub(crate) const SAE_DIRECT_ALWAYS_ADMIT_BYTES: usize = 16 * 1024 * 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SaeStreamingPlan {
pub streaming: bool,
pub chunk_size: usize,
pub estimated_full_batch_bytes: usize,
pub estimated_dense_schur_bytes: usize,
pub estimated_row_cross_bytes: usize,
pub estimated_direct_peak_bytes: usize,
pub estimated_matrix_free_peak_bytes: usize,
pub in_core_budget_bytes: usize,
pub host_available_bytes: usize,
pub direct_admitted: bool,
pub matrix_free_admitted: bool,
}
pub(crate) fn sae_streaming_plan_from_budget(
n_obs: usize,
total_basis: usize,
k_atoms: usize,
d_max: usize,
border_dim: usize,
in_core_budget_bytes: usize,
chunk_window_bytes: usize,
host_available_bytes: usize,
) -> SaeStreamingPlan {
let per_row_words = total_basis
.saturating_mul(1 + d_max)
.saturating_add(k_atoms)
.max(1);
let per_row_bytes = per_row_words.saturating_mul(SAE_BYTES_PER_F64);
let full_batch_bytes = n_obs.saturating_mul(per_row_bytes);
let dense_schur_bytes = border_dim
.saturating_mul(border_dim)
.saturating_mul(SAE_BYTES_PER_F64);
let row_block_dim = k_atoms.saturating_mul(1usize.saturating_add(d_max));
let row_cross_bytes = n_obs
.saturating_mul(row_block_dim)
.saturating_mul(border_dim)
.saturating_mul(SAE_BYTES_PER_F64);
let p_out = border_dim / total_basis.max(1);
let direct_peak_bytes = full_batch_bytes
.saturating_add(row_cross_bytes)
.saturating_add(dense_schur_bytes);
let matrix_free_budget = in_core_budget_bytes.max(SAE_MIN_STREAMING_BUDGET_FLOOR_BYTES);
let chunk_resident_bytes = chunk_window_bytes.min(full_batch_bytes.max(per_row_bytes));
let border_vector_bytes = border_dim
.saturating_mul(SAE_BYTES_PER_F64)
.saturating_mul(SAE_MATRIX_FREE_VECTOR_WORKSPACE_MULTIPLIER);
let mf_cross_bytes_per_active_atom = (1usize.saturating_add(d_max))
.saturating_mul(p_out)
.saturating_mul(SAE_BYTES_PER_F64)
.max(1);
let mf_cross_budget = matrix_free_budget
.saturating_sub(border_vector_bytes)
.saturating_sub(chunk_resident_bytes);
let mf_affordable_active =
(mf_cross_budget / n_obs.max(1) / mf_cross_bytes_per_active_atom).max(1);
let mf_active_atoms = k_atoms.min(mf_affordable_active);
let matrix_free_cross_bytes = n_obs
.saturating_mul(mf_active_atoms)
.saturating_mul(1usize.saturating_add(d_max))
.saturating_mul(p_out)
.saturating_mul(SAE_BYTES_PER_F64);
let matrix_free_peak_bytes = chunk_resident_bytes
.saturating_add(matrix_free_cross_bytes)
.saturating_add(border_vector_bytes);
let direct_fits_tiny = direct_peak_bytes <= SAE_DIRECT_ALWAYS_ADMIT_BYTES
&& direct_peak_bytes <= host_available_bytes;
let direct_admitted = direct_peak_bytes <= in_core_budget_bytes || direct_fits_tiny;
let matrix_free_admitted = matrix_free_peak_bytes <= matrix_free_budget;
let rows_per_chunk = (chunk_window_bytes / per_row_bytes).max(SAE_MIN_STREAMING_CHUNK_ROWS);
SaeStreamingPlan {
streaming: !direct_admitted,
chunk_size: if direct_admitted {
n_obs.max(1)
} else {
rows_per_chunk.min(n_obs).max(1)
},
estimated_full_batch_bytes: full_batch_bytes,
estimated_dense_schur_bytes: dense_schur_bytes,
estimated_row_cross_bytes: row_cross_bytes,
estimated_direct_peak_bytes: direct_peak_bytes,
estimated_matrix_free_peak_bytes: matrix_free_peak_bytes,
in_core_budget_bytes,
host_available_bytes,
direct_admitted,
matrix_free_admitted,
}
}
pub fn sae_streaming_plan_for_shape(
n_obs: usize,
total_basis: usize,
k_atoms: usize,
d_max: usize,
border_dim: usize,
) -> SaeStreamingPlan {
let (host_budget, host_available) = sae_host_in_core_budget_bytes();
let host_window = SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE;
let pessimistic_plan = sae_streaming_plan_from_budget(
n_obs,
total_basis,
k_atoms,
d_max,
border_dim,
host_budget.min(SAE_MIN_DEVICE_POOL_IN_CORE_BUDGET_BYTES),
host_window,
host_available,
);
if pessimistic_plan.direct_admitted
&& pessimistic_plan.estimated_dense_schur_bytes <= host_budget
{
return sae_streaming_plan_from_budget(
n_obs,
total_basis,
k_atoms,
d_max,
border_dim,
host_budget,
host_window,
host_available,
);
}
let (budget, chunk_window, host_available) =
match crate::gpu::device_runtime::GpuRuntime::global() {
Some(rt) if rt.device_count() > 0 => {
let aggregate_budget: usize = rt
.device_ordinals()
.iter()
.map(|&ord| rt.memory_budget_for(ord))
.sum();
if aggregate_budget > 0 {
let per_device_budget = aggregate_budget / rt.device_count();
let window = (per_device_budget / 16)
.max(SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE);
let host_available = sae_host_available_memory_bytes();
(
(aggregate_budget / 4).min(host_available),
window,
host_available,
)
} else {
let (budget, host_available) = sae_host_in_core_budget_bytes();
(
budget,
SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE,
host_available,
)
}
}
Some(_) => {
let (budget, host_available) = sae_host_in_core_budget_bytes();
(
budget,
SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE,
host_available,
)
}
None => {
let (budget, host_available) = sae_host_in_core_budget_bytes();
(
budget,
SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE,
host_available,
)
}
};
sae_streaming_plan_from_budget(
n_obs,
total_basis,
k_atoms,
d_max,
border_dim,
budget,
chunk_window,
host_available,
)
}
impl SaeStreamingPlan {
pub(crate) fn admitted_or_error(
self,
n: usize,
p: usize,
k_atoms: usize,
) -> Result<Self, String> {
if self.direct_admitted || self.matrix_free_admitted {
Ok(self)
} else {
Err(format!(
"SaeManifoldTerm::streaming_plan: predicted working set {} bytes exceeds budget {} bytes; shape n={n},p={p},K={k_atoms}",
self.estimated_matrix_free_peak_bytes, self.in_core_budget_bytes
))
}
}
pub(crate) fn solve_options_for_border_dim(self, border_dim: usize) -> ArrowSolveOptions {
let mut options = if self.direct_admitted {
ArrowSolveOptions::automatic(border_dim)
} else {
ArrowSolveOptions::inexact_pcg()
};
options.schur_pd_floor = Some(gam_solve::arrow_schur::SPECTRAL_DEFLATION_REL_FLOOR);
options
}
pub(crate) fn direct_logdet_admitted(self) -> bool {
self.direct_admitted
}
}
pub(crate) const SAE_TOPK_ADMISSION_FRAME_RANK_BOUND: usize = 32;
pub(crate) const fn sae_topk_admission_atom_basis_bound(d_max: usize) -> usize {
let periodic = 2 * d_max + 1;
let patch = 32 + ((d_max + 1) * (d_max + 2)) / 2;
if periodic > patch { periodic } else { patch }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SaeTopKCurvedBudget {
pub n_obs: usize,
pub output_dim: usize,
pub n_atoms: usize,
pub support_k: usize,
pub d_max: usize,
pub resident_seed_bytes: usize,
pub active_state_bytes: usize,
pub routing_window_bytes: usize,
pub framed_decoder_bytes: usize,
pub border_vector_bytes: usize,
pub streaming_peak_bytes: usize,
pub streaming_budget_bytes: usize,
pub in_core_budget_bytes: usize,
pub resident_seed_admitted: bool,
pub streaming_admitted: bool,
}
impl SaeTopKCurvedBudget {
pub fn seed_chunk_rows(&self) -> usize {
let per_row_bytes = self.n_atoms.saturating_mul(SAE_BYTES_PER_F64).max(1);
((SAE_CPU_L2_CACHE_BYTES * SAE_CHUNK_CACHE_MULTIPLE) / per_row_bytes)
.max(SAE_MIN_STREAMING_CHUNK_ROWS)
.min(self.n_obs.max(1))
}
}
pub(crate) fn sae_topk_curved_budget_from_budget(
n_obs: usize,
output_dim: usize,
n_atoms: usize,
d_max: usize,
support_k: usize,
in_core_budget_bytes: usize,
) -> SaeTopKCurvedBudget {
let resident_seed_bytes = n_obs
.saturating_mul(n_atoms)
.saturating_mul(1usize.saturating_add(d_max))
.saturating_mul(SAE_BYTES_PER_F64);
let active_state_bytes = n_obs
.saturating_mul(support_k)
.saturating_mul(2usize.saturating_add(d_max))
.saturating_mul(SAE_BYTES_PER_F64);
let basis_bound = sae_topk_admission_atom_basis_bound(d_max);
let rank_bound = output_dim.min(SAE_TOPK_ADMISSION_FRAME_RANK_BOUND);
let framed_decoder_bytes = n_atoms
.saturating_mul(basis_bound)
.saturating_mul(rank_bound)
.saturating_mul(SAE_BYTES_PER_F64);
let border_vector_bytes =
framed_decoder_bytes.saturating_mul(SAE_MATRIX_FREE_VECTOR_WORKSPACE_MULTIPLIER);
let mut budget = SaeTopKCurvedBudget {
n_obs,
output_dim,
n_atoms,
support_k,
d_max,
resident_seed_bytes,
active_state_bytes,
routing_window_bytes: 0,
framed_decoder_bytes,
border_vector_bytes,
streaming_peak_bytes: 0,
streaming_budget_bytes: in_core_budget_bytes.max(SAE_MIN_STREAMING_BUDGET_FLOOR_BYTES),
in_core_budget_bytes,
resident_seed_admitted: resident_seed_bytes <= in_core_budget_bytes,
streaming_admitted: false,
};
budget.routing_window_bytes = budget
.seed_chunk_rows()
.saturating_mul(n_atoms)
.saturating_mul(SAE_BYTES_PER_F64);
budget.streaming_peak_bytes = budget
.active_state_bytes
.saturating_add(budget.routing_window_bytes)
.saturating_add(budget.framed_decoder_bytes)
.saturating_add(budget.border_vector_bytes);
budget.streaming_admitted = budget.streaming_peak_bytes <= budget.streaming_budget_bytes;
budget
}
pub fn admit_topk_curved_lane(
n_obs: usize,
output_dim: usize,
n_atoms: usize,
d_max: usize,
support_k: usize,
) -> Result<SaeTopKCurvedBudget, String> {
if n_obs == 0 || output_dim == 0 || n_atoms == 0 {
return Err(format!(
"admit_topk_curved_lane requires positive N, P, and K; got N={n_obs}, P={output_dim}, K={n_atoms}"
));
}
if d_max == 0 {
return Err("admit_topk_curved_lane requires d_max >= 1".to_string());
}
if support_k == 0 || support_k > n_atoms {
return Err(format!(
"admit_topk_curved_lane requires 1 <= support_k <= K={n_atoms}; got {support_k}"
));
}
let (in_core_budget_bytes, host_available) = sae_host_in_core_budget_bytes();
let budget = sae_topk_curved_budget_from_budget(
n_obs,
output_dim,
n_atoms,
d_max,
support_k,
in_core_budget_bytes,
);
if budget.resident_seed_admitted || budget.streaming_admitted {
return Ok(budget);
}
Err(format!(
"topk curved lane refused: streaming peak {} bytes (active sets {} + routing window {} \
+ framed decoder {} + border workspace {}) exceeds the streaming budget {} bytes \
(host available {host_available}) at N={n_obs}, P={output_dim}, K={n_atoms}, \
k_active={support_k}, d_max={d_max}. Reduce n_obs or support_k — a TOPK MANIFOLD \
request is never silently substituted with the linear sparse-code lane",
budget.streaming_peak_bytes,
budget.active_state_bytes,
budget.routing_window_bytes,
budget.framed_decoder_bytes,
budget.border_vector_bytes,
budget.streaming_budget_bytes,
))
}
pub(crate) fn sae_host_available_memory_bytes() -> usize {
let mut sys = sysinfo::System::new();
sys.refresh_memory();
let available = sys.available_memory() as usize;
let available = if available == 0 {
SAE_HOST_IN_CORE_FALLBACK_BYTES
} else {
available
};
match sae_cgroup_available_bytes() {
Some(cgroup) => available.min(cgroup),
None => available,
}
}
fn sae_cgroup_available_bytes() -> Option<usize> {
if let Some(limit) = sae_read_usize_file("/sys/fs/cgroup/memory.max") {
let current = sae_read_usize_file("/sys/fs/cgroup/memory.current").unwrap_or(0);
return Some(limit.saturating_sub(current));
}
if let Some(limit) = sae_read_usize_file("/sys/fs/cgroup/memory/memory.limit_in_bytes") {
let current =
sae_read_usize_file("/sys/fs/cgroup/memory/memory.usage_in_bytes").unwrap_or(0);
return Some(limit.saturating_sub(current));
}
None
}
fn sae_read_usize_file(path: &str) -> Option<usize> {
let raw = std::fs::read_to_string(path).ok()?;
let trimmed = raw.trim();
if trimmed == "max" {
return None;
}
let value: usize = trimmed.parse().ok()?;
if value >= (1usize << 62) {
return None;
}
Some(value)
}
pub(crate) const fn sae_host_in_core_budget_from_available(available: usize) -> usize {
let reserve = {
let frac = available / SAE_HOST_MEMORY_RESERVE_FRACTION_DENOMINATOR;
if frac > SAE_HOST_MEMORY_RESERVE_FLOOR_BYTES {
frac
} else {
SAE_HOST_MEMORY_RESERVE_FLOOR_BYTES
}
};
let usable = available.saturating_sub(reserve);
let fraction = (available.saturating_mul(SAE_HOST_MEMORY_BUDGET_FRACTION_NUMERATOR))
/ SAE_HOST_MEMORY_BUDGET_FRACTION_DENOMINATOR;
let floored = if fraction > SAE_HOST_IN_CORE_FALLBACK_BYTES {
fraction
} else {
SAE_HOST_IN_CORE_FALLBACK_BYTES
};
if floored < usable { floored } else { usable }
}
pub(crate) fn sae_host_in_core_budget_bytes() -> (usize, usize) {
let available = sae_host_available_memory_bytes();
(sae_host_in_core_budget_from_available(available), available)
}
#[cfg(test)]
mod cpu_sized_plan_laziness_tests {
use super::*;
use crate::gpu::device_runtime::GpuRuntime;
#[test]
fn cpu_sized_streaming_plan_never_probes_the_device() {
let before = GpuRuntime::global_call_count();
let plan = sae_streaming_plan_for_shape(700, 60, 6, 2, 144);
assert!(
plan.direct_admitted,
"the CPU-sized fixture must be direct-admitted (peak {} B)",
plan.estimated_direct_peak_bytes
);
assert!(!plan.streaming);
assert_eq!(plan.chunk_size, 700);
assert_eq!(
GpuRuntime::global_call_count(),
before,
"planning a CPU-sized SAE fit must short-circuit BEFORE \
GpuRuntime::global(), so no CUDA context is ever created"
);
}
#[test]
fn oversized_streaming_plan_still_consults_the_device_budget() {
let before = GpuRuntime::global_call_count();
sae_streaming_plan_for_shape(2_000_000, 4_096, 512, 8, 32_768);
assert!(
GpuRuntime::global_call_count() > before,
"an oversized plan must consult GpuRuntime::global() for the \
pooled device budget exactly as before"
);
}
#[test]
fn early_return_carries_the_host_budget_not_the_decision_floor() {
let plan = sae_streaming_plan_for_shape(700, 60, 6, 2, 144);
let (host_budget, _) = sae_host_in_core_budget_bytes();
assert_eq!(
plan.in_core_budget_bytes, host_budget,
"direct early-return must install the host budget"
);
}
}
#[cfg(test)]
mod host_in_core_budget_tests {
use super::*;
#[test]
fn budget_never_exceeds_available() {
let tiny = 512 * 1024 * 1024; let budget = sae_host_in_core_budget_from_available(tiny);
assert!(
budget <= tiny,
"budget {budget} must not exceed available {tiny}"
);
for &avail in &[
0usize,
1,
SAE_HOST_IN_CORE_FALLBACK_BYTES - 1,
SAE_HOST_IN_CORE_FALLBACK_BYTES,
SAE_HOST_IN_CORE_FALLBACK_BYTES + 1,
16 * 1024 * 1024 * 1024,
] {
let budget = sae_host_in_core_budget_from_available(avail);
assert!(
budget <= avail,
"budget {budget} must not exceed available {avail}"
);
}
}
#[test]
fn ample_memory_uses_fraction_floored_at_2gib() {
let avail = 16 * 1024 * 1024 * 1024usize;
let budget = sae_host_in_core_budget_from_available(avail);
let fraction = avail * SAE_HOST_MEMORY_BUDGET_FRACTION_NUMERATOR
/ SAE_HOST_MEMORY_BUDGET_FRACTION_DENOMINATOR;
assert_eq!(budget, fraction);
assert!(budget >= SAE_HOST_IN_CORE_FALLBACK_BYTES);
}
#[test]
fn budget_reserves_headroom_below_usable() {
for &avail in &[
256 * 1024 * 1024usize,
512 * 1024 * 1024,
2 * 1024 * 1024 * 1024,
16 * 1024 * 1024 * 1024,
128 * 1024 * 1024 * 1024,
] {
let reserve = (avail / SAE_HOST_MEMORY_RESERVE_FRACTION_DENOMINATOR)
.max(SAE_HOST_MEMORY_RESERVE_FLOOR_BYTES);
let usable = avail.saturating_sub(reserve);
let budget = sae_host_in_core_budget_from_available(avail);
assert!(
budget <= usable,
"budget {budget} must leave reserve free: usable={usable}, avail={avail}"
);
}
}
#[test]
fn below_floor_box_streams_not_oom() {
let avail = 1024 * 1024 * 1024usize; let reserve = (avail / SAE_HOST_MEMORY_RESERVE_FRACTION_DENOMINATOR)
.max(SAE_HOST_MEMORY_RESERVE_FLOOR_BYTES);
let usable = avail - reserve;
let budget = sae_host_in_core_budget_from_available(avail);
assert_eq!(
budget, usable,
"below-floor budget must collapse to usable {usable}, got {budget}"
);
assert!(budget < SAE_HOST_IN_CORE_FALLBACK_BYTES);
let plan = sae_streaming_plan_from_budget(
10_000,
4_096,
8,
8,
64,
budget,
SAE_CPU_L2_CACHE_BYTES,
avail,
);
assert!(
!plan.direct_admitted || plan.estimated_direct_peak_bytes <= budget,
"a plan exceeding the usable budget must not be direct-admitted"
);
}
#[test]
fn tiny_plan_admits_when_budget_collapsed_but_large_plan_streams() {
let budget = 0usize;
let avail = 200 * 1024 * 1024usize;
let tiny =
sae_streaming_plan_from_budget(120, 3, 1, 1, 6, budget, SAE_CPU_L2_CACHE_BYTES, avail);
assert!(
tiny.estimated_direct_peak_bytes <= SAE_DIRECT_ALWAYS_ADMIT_BYTES,
"toy plan should be far below the always-admit size, got {} bytes",
tiny.estimated_direct_peak_bytes
);
assert!(
tiny.direct_admitted,
"a tiny dense plan ({} bytes) that fits the {avail}-byte available memory \
must be direct-admitted even when the in-core budget collapsed to 0",
tiny.estimated_direct_peak_bytes
);
assert!(
!tiny.streaming,
"a direct-admitted tiny plan must run in-core, not stream"
);
let large = sae_streaming_plan_from_budget(
10_000,
4_096,
8,
8,
64,
budget,
SAE_CPU_L2_CACHE_BYTES,
avail,
);
assert!(
large.estimated_direct_peak_bytes > SAE_DIRECT_ALWAYS_ADMIT_BYTES,
"large plan must exceed the always-admit size"
);
assert!(
!large.direct_admitted,
"a large dense plan must stay gated on the (collapsed) budget and stream, \
not be admitted by the tiny-plan relaxation"
);
}
}
#[cfg(test)]
mod topk_curved_budget_tests {
use super::*;
#[test]
fn topk_curved_budget_formulas_are_the_documented_arithmetic() {
let (n, p, k, d, s) = (4096usize, 512usize, 32_000usize, 1usize, 8usize);
let budget_bytes = 16 * 1024 * 1024 * 1024usize;
let ledger = sae_topk_curved_budget_from_budget(n, p, k, d, s, budget_bytes);
assert_eq!(
ledger.resident_seed_bytes,
n * k * (1 + d) * SAE_BYTES_PER_F64
);
assert_eq!(
ledger.active_state_bytes,
n * s * (2 + d) * SAE_BYTES_PER_F64
);
let m_hat = sae_topk_admission_atom_basis_bound(d);
assert_eq!(
m_hat,
32 + 3,
"d_max=1: patch bound 32 + (2·3)/2 dominates 2d+1=3"
);
let r_hat = p.min(SAE_TOPK_ADMISSION_FRAME_RANK_BOUND);
assert_eq!(
ledger.framed_decoder_bytes,
k * m_hat * r_hat * SAE_BYTES_PER_F64
);
assert_eq!(
ledger.border_vector_bytes,
ledger.framed_decoder_bytes * SAE_MATRIX_FREE_VECTOR_WORKSPACE_MULTIPLIER
);
assert_eq!(
ledger.routing_window_bytes,
ledger.seed_chunk_rows() * k * SAE_BYTES_PER_F64
);
assert_eq!(
ledger.streaming_peak_bytes,
ledger.active_state_bytes
+ ledger.routing_window_bytes
+ ledger.framed_decoder_bytes
+ ledger.border_vector_bytes
);
assert_eq!(
ledger.streaming_budget_bytes,
budget_bytes.max(SAE_MIN_STREAMING_BUDGET_FLOOR_BYTES)
);
assert!(ledger.active_state_bytes * 100 < ledger.resident_seed_bytes);
assert!(ledger.resident_seed_admitted);
assert!(ledger.streaming_admitted);
}
#[test]
fn topk_streaming_admits_beyond_resident_and_seam_validates() {
let (n, p, k, d, s) = (1_000_000usize, 512usize, 32_000usize, 1usize, 8usize);
let budget_bytes = 16 * 1024 * 1024 * 1024usize;
let ledger = sae_topk_curved_budget_from_budget(n, p, k, d, s, budget_bytes);
assert!(!ledger.resident_seed_admitted);
assert!(
ledger.streaming_admitted,
"streaming peak {} must fit the 16 GiB budget: the O(N·k_active) state is small",
ledger.streaming_peak_bytes
);
assert!(ledger.seed_chunk_rows() >= SAE_MIN_STREAMING_CHUNK_ROWS);
assert!(ledger.seed_chunk_rows() <= n);
assert!(admit_topk_curved_lane(0, p, k, d, s).is_err());
assert!(admit_topk_curved_lane(n, p, k, 0, s).is_err());
assert!(admit_topk_curved_lane(n, p, k, d, 0).is_err());
assert!(admit_topk_curved_lane(n, p, k, d, k + 1).is_err());
let starved = sae_topk_curved_budget_from_budget(n, p, k, d, s, 0);
assert_eq!(
starved.streaming_budget_bytes,
SAE_MIN_STREAMING_BUDGET_FLOOR_BYTES
);
assert!(
!starved.streaming_admitted,
"the framed decoder + border workspace exceed the 64 MiB streaming floor at K=32000"
);
}
}