use crate::arrow_schur::{ArrowSchurSystem, DensePenaltyOp};
use crate::gpu_kernels::arrow_schur::{ArrowSchurGpuFailure, solve_arrow_newton_step};
use ndarray::Array2;
use std::sync::Arc;
#[test]
fn absent_dense_beta_block_declines_not_fatal() {
let (n, d, k) = (6usize, 2usize, 48usize);
let sys = ArrowSchurSystem::new_with_empty_hbb_and_htbeta_cols(n, d, k, k);
assert_eq!(sys.hbb.dim(), (0, 0), "fixture must have an absent dense β-block");
assert!(sys.hbb_matvec.is_none() && sys.htbeta_matvec.is_none());
match solve_arrow_newton_step(&sys, 1e-6, 1e-6) {
Err(ArrowSchurGpuFailure::GpuRequiresDenseSystem {
had_hbb_matvec,
had_htbeta_matvec,
}) => {
assert!(
!had_hbb_matvec && !had_htbeta_matvec,
"the dense block is structurally absent, so neither matvec flag \
should be set; got hbb={had_hbb_matvec} htbeta={had_htbeta_matvec}"
);
}
Err(ArrowSchurGpuFailure::SchurFactorFailed { reason }) => panic!(
"absent dense β-block must DECLINE, not report a numerical Schur \
failure (this is the fatal-RemlConvergenceError bug); got reason={reason:?}"
),
Err(other) => panic!(
"absent dense β-block must decline with GpuRequiresDenseSystem; got {other:?}"
),
Ok(_) => panic!(
"absent dense β-block must decline, but the device solve returned Ok"
),
}
}
#[test]
fn present_dense_beta_block_is_not_declined_as_absent() {
let (n, d, k) = (4usize, 2usize, 8usize);
let sys = ArrowSchurSystem::new(n, d, k);
assert_eq!(sys.hbb.dim(), (k, k), "fixture must supply a dense (k,k) β-block");
if let Err(ArrowSchurGpuFailure::GpuRequiresDenseSystem { .. }) =
solve_arrow_newton_step(&sys, 1e-6, 1e-6)
{
panic!(
"a system WITH a dense (k,k) H_ββ must not be declined as \
dense-block-absent"
);
}
}
#[test]
fn present_but_stale_hbb_with_penalty_op_declines_not_wrong_step() {
let (n, d, k) = (4usize, 2usize, 8usize);
let mut sys = ArrowSchurSystem::new(n, d, k);
sys.penalty_op = Some(Arc::new(DensePenaltyOp(Array2::<f64>::eye(k))));
assert_eq!(
sys.hbb.dim(),
(k, k),
"fixture must keep the STALE dense (k,k) block so the shape gate is bypassed"
);
assert!(
sys.hbb_matvec.is_none() && sys.htbeta_matvec.is_none(),
"fixture must install penalty_op ALONE (no matvec shadow) to isolate the guard"
);
match solve_arrow_newton_step(&sys, 1e-6, 1e-6) {
Err(ArrowSchurGpuFailure::GpuRequiresDenseSystem {
had_hbb_matvec,
had_htbeta_matvec,
}) => {
assert!(
!had_hbb_matvec && !had_htbeta_matvec,
"penalty_op is installed alone, so neither matvec flag should be \
set; got hbb={had_hbb_matvec} htbeta={had_htbeta_matvec}"
);
}
Err(ArrowSchurGpuFailure::SchurFactorFailed { reason }) => panic!(
"a penalty_op system must DECLINE, not report a numerical Schur \
failure; got reason={reason:?}"
),
Err(other) => panic!(
"a penalty_op system must decline with GpuRequiresDenseSystem; got {other:?}"
),
Ok(_) => panic!(
"a penalty_op system carries stale dense curvature — the device must \
NOT proceed to compute a step from it"
),
}
}