pub const AC_GPUTRAIN_005_MAX_STEP_TIME_MS_RTX4090_370M: f32 = 500.0;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Gputrain005Verdict {
Pass,
Fail,
}
#[must_use]
pub const fn verdict_from_step_time_ms(measured_ms: f32, threshold_ms: f32) -> Gputrain005Verdict {
if !measured_ms.is_finite() || !threshold_ms.is_finite() {
return Gputrain005Verdict::Fail;
}
if measured_ms < 0.0 {
return Gputrain005Verdict::Fail;
}
if threshold_ms <= 0.0 {
return Gputrain005Verdict::Fail;
}
if measured_ms <= threshold_ms {
Gputrain005Verdict::Pass
} else {
Gputrain005Verdict::Fail
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn falsify_gputrain_005_step_time_threshold_logic() {
let threshold = AC_GPUTRAIN_005_MAX_STEP_TIME_MS_RTX4090_370M;
assert_eq!(
verdict_from_step_time_ms(500.0, threshold),
Gputrain005Verdict::Pass,
"measured == threshold (500.0 ms) must Pass per inclusive ceiling",
);
let one_ulp_above = f32::from_bits(threshold.to_bits() + 1);
assert!(one_ulp_above > threshold);
assert_eq!(
verdict_from_step_time_ms(one_ulp_above, threshold),
Gputrain005Verdict::Fail,
"one ULP above threshold (~500.00006 ms) must Fail",
);
for &measured in &[0.0f32, 1.0, 100.0, 250.0, 400.0, 499.999] {
assert_eq!(
verdict_from_step_time_ms(measured, threshold),
Gputrain005Verdict::Pass,
"measured={measured} ms (well under {threshold} ms) must Pass",
);
}
for &measured in &[501.0f32, 600.0, 1_000.0, 10_000.0, 60_000.0, f32::MAX] {
assert_eq!(
verdict_from_step_time_ms(measured, threshold),
Gputrain005Verdict::Fail,
"measured={measured} ms (above {threshold} ms) must Fail",
);
}
for &bad in &[f32::NAN, f32::INFINITY, f32::NEG_INFINITY] {
assert_eq!(
verdict_from_step_time_ms(bad, threshold),
Gputrain005Verdict::Fail,
"non-finite measured ({bad:?}) must Fail",
);
assert_eq!(
verdict_from_step_time_ms(100.0, bad),
Gputrain005Verdict::Fail,
"non-finite threshold ({bad:?}) must Fail",
);
}
assert_eq!(
verdict_from_step_time_ms(-1.0, threshold),
Gputrain005Verdict::Fail,
"negative measured step time must Fail (non-physical)",
);
assert_eq!(
verdict_from_step_time_ms(-0.0001, threshold),
Gputrain005Verdict::Fail,
"tiny-negative measured step time must Fail",
);
assert_eq!(
verdict_from_step_time_ms(100.0, 0.0),
Gputrain005Verdict::Fail,
"zero threshold must Fail (ceiling of 0 is nonsense)",
);
assert_eq!(
verdict_from_step_time_ms(100.0, -1.0),
Gputrain005Verdict::Fail,
"negative threshold must Fail",
);
assert!(
(AC_GPUTRAIN_005_MAX_STEP_TIME_MS_RTX4090_370M - 500.0).abs() < 1e-6,
"INV-GPUTRAIN-005 step-time ceiling is 500.0 ms \
(spec §14.4 / gpu-training-backend-v1 INV-GPUTRAIN-005)",
);
}
}