sigmoid and elu on a range that reaches -2^63; an rq whose q passes 64 bits (with y back in range where a post bias allows); l2norm at eps = 2^64 - 1; a graph that fails acc32 by each parameter key of section 7.2 alone; lut16 at +-32768; and in graphs/load.jsonl, a graph refused at step 8 for an empty check intersection and for an accumulator past i64. The independent checker recomputes every one of them from its own bounds pass. Co-Authored-By: Claude Opus 5.5 <[email protected]>
78 lines
3.6 KiB
Rust
78 lines
3.6 KiB
Rust
//! The vectors whose outcome only load step 8 decides (§14.1 item 6), checked against
|
||
//! the reason the text gives for each: the bounds pass must refuse or tag them for
|
||
//! that reason, not another.
|
||
|
||
use std::path::PathBuf;
|
||
|
||
use wai_ops::bounds::{self, Profile};
|
||
use wai_ops::json::{self, unhex};
|
||
use wai_ops::{graph::Graph, plan};
|
||
|
||
fn lines(file: &str) -> Vec<json::Value> {
|
||
let p = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../ops-conformance").join(file);
|
||
std::fs::read_to_string(&p).unwrap().lines().map(|l| json::parse(l.as_bytes()).unwrap()).collect()
|
||
}
|
||
|
||
fn graph_of(v: &json::Value) -> Graph {
|
||
Graph::parse(&unhex(v.get("graph").unwrap().as_str().unwrap()).unwrap()).unwrap()
|
||
}
|
||
|
||
/// Every key of §7.2's table has a vector that fails `acc32` by that parameter
|
||
/// condition alone: its graph meets `acc64`, every interval fits `acc32`, and its one
|
||
/// node's only failure is that key.
|
||
#[test]
|
||
fn each_acc32_parameter_key_fails_alone() {
|
||
let want = ["rq.mult", "rq.shift", "rq.post_bias", "weights", "chscale.m", "chscale.s", "igdn.gamma", "igdn.shift", "leaky.a"];
|
||
let mut seen: Vec<String> = Vec::new();
|
||
for op in ["rescale", "conv", "conv_transpose", "chscale", "igdn", "leaky"] {
|
||
for v in lines(&format!("vectors/{op}.jsonl")) {
|
||
if !v.get("id").unwrap().as_str().unwrap().contains("/acc32_param/") {
|
||
continue;
|
||
}
|
||
let g = graph_of(&v);
|
||
let sizes = plan::load_plan(&g).unwrap();
|
||
let b = bounds::pass(&g, sizes.as_deref()).unwrap();
|
||
assert!(b.meets(&g, Profile::Acc64));
|
||
let n = &b.nodes[0];
|
||
assert!(n.inter.iter().all(|i| i.iv.fits(i.class.width(Profile::Acc32))), "{op}: an interval fails acc32");
|
||
assert!(n.results.iter().all(|r| r.fits(32)));
|
||
assert_eq!(n.params32.len(), 1, "{op}: {:?}", n.params32);
|
||
let f = b.first_failure(&g, Profile::Acc32).unwrap();
|
||
assert_eq!(f.miss.key, n.params32[0]);
|
||
seen.push(f.miss.key.clone());
|
||
}
|
||
}
|
||
// `weights` has one for each of `conv` and `conv_transpose`.
|
||
seen.sort();
|
||
seen.dedup();
|
||
let mut w: Vec<String> = want.iter().map(|s| s.to_string()).collect();
|
||
w.sort();
|
||
assert_eq!(seen, w);
|
||
}
|
||
|
||
/// `sigmoid` and `elu` at −2^63 fail `acc64` through `exp.negx`, at 65 bits; an `rq`
|
||
/// whose `q` passes 64 bits fails at `rq.q` while `rq.y` fits where a `post` bias
|
||
/// brings it back. Without a bias (`chscale`, `mul`) `y` and the producer result pass
|
||
/// with `q`, at the same bits, and `out.0` is the smallest key of the three.
|
||
#[test]
|
||
fn step8_refusals_fail_where_the_text_says() {
|
||
for (file, key) in [("sigmoid", "exp.negx"), ("elu", "exp.negx"), ("rescale", "rq.q"), ("conv", "rq.q"), ("conv_transpose", "rq.q"), ("chscale", "out.0"), ("mul", "out.0")] {
|
||
let mut n = 0;
|
||
for v in lines(&format!("vectors/{file}.jsonl")) {
|
||
let id = v.get("id").unwrap().as_str().unwrap();
|
||
if !(id.contains("/step8/") || id.contains("/step8_q/")) || v.get("load").unwrap().as_str() == Some("ok") {
|
||
continue;
|
||
}
|
||
let g = graph_of(&v);
|
||
let b = bounds::pass(&g, None).unwrap();
|
||
let f = b.first_failure(&g, Profile::Acc64).unwrap();
|
||
assert_eq!((f.miss.key.as_str(), f.miss.bits), (key, Some(65)), "{id}");
|
||
if matches!(file, "rescale" | "conv" | "conv_transpose") {
|
||
let y = b.nodes[0].inter.iter().find(|i| i.key == "rq.y").unwrap();
|
||
assert!(y.iv.fits(64), "{id}: y fits");
|
||
}
|
||
n += 1;
|
||
}
|
||
assert!(n > 0, "{file}: no step-8 refusal");
|
||
}
|
||
}
|