diff --git a/.trinity/seals/t27o_T27oLedger.json b/.trinity/seals/t27o_T27oLedger.json
index 0d70e686d7..2e0bdbe576 100644
--- a/.trinity/seals/t27o_T27oLedger.json
+++ b/.trinity/seals/t27o_T27oLedger.json
@@ -1,5 +1,5 @@
{
- "built_by": "t27c-bootstrap@0.5.2+9b556b7c3",
+ "built_by": "t27c-bootstrap@0.5.2+ea35d9b72",
"closure": [
{
"spec": "specs/tri/lab/receipt.t27",
@@ -15,23 +15,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
- "gen_hash_c": "sha256:428200eaf55079318d360ecec24a359a21320f1f64f94c50001bb93159d8f882",
- "gen_hash_rust": "sha256:02f9f45cec23ed1149a09edd668dfc48aef3b4d83d0ad7a1f0709a564fd6d3c5",
- "gen_hash_verilog": "sha256:7d461b24959b4ee95bcb3617f2a41e5eaac048bf7640f8a467f7e60b6db1c3b8",
- "gen_hash_zig": "sha256:174c0e2cf57c8647ba48908f90aaaf5f87456ddbae3346f0db0550bbd8c57026",
+ "gen_hash_c": "sha256:9d516eccbc6e4404953f1f5c85c3fcce8c3e0abe08bcca15cfa0e5abb70a5185",
+ "gen_hash_rust": "sha256:1b30b3432b64262d5c3e42e5fbec57937afbc0c0b31fbc2ccf27a11513431955",
+ "gen_hash_verilog": "sha256:744dab1dd12a361c179b15417e0feebebaef4cd8b3c7044c0452458c5ba43cba",
+ "gen_hash_zig": "sha256:274bbd97674fbb7f4d3e100a400e64e10861c1651dd961a31ad9335690a124c9",
"module": "T27oLedger",
"ring": 12,
"seal_schema": 2,
- "sealed_at": "2026-10-18T21:16:15Z",
+ "sealed_at": "2026-10-19T05:41:02Z",
"sealed_by": "t27c-bootstrap@0.5.2",
- "spec_hash": "sha256:98b04611fe2950faac8f137f1dbc7be83d595049988dbb13a520d840e4b09dd6",
+ "spec_hash": "sha256:1ca252b0187eb7b996e2e1f0c5331fe53c0db65b3f4aa78f85a3eb5d0704b023",
"spec_path": "specs/tools/t27o/ledger.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
- "passed": 29,
- "total": 29,
+ "passed": 38,
+ "total": 38,
"vacuous": 0
},
"toolchain": {
diff --git a/.trinity/seals/t27o_T27oZig.json b/.trinity/seals/t27o_T27oZig.json
index 92ce0b6a27..84a5de9db6 100644
--- a/.trinity/seals/t27o_T27oZig.json
+++ b/.trinity/seals/t27o_T27oZig.json
@@ -7,23 +7,23 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
- "gen_hash_c": "sha256:1902658b3fdd4234f5995a344bff8e880b6469635ea1fb0af023899d9cc6ead8",
- "gen_hash_rust": "sha256:b804e5f4927cb4226bd6623c919e290f26a54d42d2c09ae9b949daeb1f00ee46",
- "gen_hash_verilog": "sha256:1824c0407ae4c0cf97e7afb4b103ad6adcc20052636dbad081dd9330c1439e8e",
- "gen_hash_zig": "sha256:c6e3f12811dd2eeaab6f29949789c444d9b65bdfa683d7a9d2ddb46d0359b906",
+ "gen_hash_c": "sha256:7725f48195f1d63c346c554a9f476564993956aa96528440617597f9f7af0df2",
+ "gen_hash_rust": "sha256:5b79bfee2a5d9770de677f1717c9fb5fbf022ca8353f0ced3993efc58011cb60",
+ "gen_hash_verilog": "sha256:172face9cae7881f4f41c5fd65f10e3c57ddeee52e62861bfe810c8152590e4f",
+ "gen_hash_zig": "sha256:8a89267d881f63316a6ff08b4ed3d755002640d19562da007fc2023179ed9f9f",
"module": "T27oZig",
"ring": 12,
"seal_schema": 2,
- "sealed_at": "2026-10-19T03:31:24Z",
+ "sealed_at": "2026-10-19T06:34:03Z",
"sealed_by": "t27c-bootstrap@0.5.2",
- "spec_hash": "sha256:a21f02d266648e370fcaf0e2d9cc50f30b4b23277caa3dc4a625369a1b4c59e0",
+ "spec_hash": "sha256:8322d4dd716d084c17c366d336e9b70f4720b392dd8614b3983579fdf2c28b38",
"spec_path": "specs/tools/t27o/zig_convert.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
- "passed": 45,
- "total": 45,
+ "passed": 61,
+ "total": 61,
"vacuous": 0
},
"toolchain": {
diff --git a/.trinity/seals/t27o_T27oZigStd.json b/.trinity/seals/t27o_T27oZigStd.json
new file mode 100644
index 0000000000..d277819ff3
--- /dev/null
+++ b/.trinity/seals/t27o_T27oZigStd.json
@@ -0,0 +1,28 @@
+{
+ "built_by": "t27c-bootstrap@0.5.2+ea35d9b72",
+ "closure": [],
+ "config": "gen=c,rust,verilog,zig;tests=zig",
+ "gen_hash_c": "sha256:75c0ec2458e26d4de273854fe7346972fcff9e85a19b52bd940c94f82cbaee1a",
+ "gen_hash_rust": "sha256:b0c91ce7507930661c0606e5764ca3c1c49fb9f18f1a3672835f156a52818ba7",
+ "gen_hash_verilog": "sha256:d49e1fdaf0787d3c2f03c44f1bcc3020d9c3c62fba11c7dcfb5bfa38ec1e40fa",
+ "gen_hash_zig": "sha256:05fe1623474e2296103ada5d5ade121c1271609c5581723d4f7fd4bdfb31c702",
+ "module": "T27oZigStd",
+ "ring": 12,
+ "seal_schema": 2,
+ "sealed_at": "2026-10-19T06:07:00Z",
+ "sealed_by": "t27c-bootstrap@0.5.2",
+ "spec_hash": "sha256:282b6910324ebe55c2d5ba68c39ed2db1663c4fbf2864deba3265c908ebbef3a",
+ "spec_path": "specs/tools/t27o/zig_std.t27",
+ "tests": {
+ "failed": 0,
+ "failing": [],
+ "forced": false,
+ "passed": 7,
+ "total": 7,
+ "vacuous": 0
+ },
+ "toolchain": {
+ "test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
+ "zig": "0.16.0"
+ }
+}
\ No newline at end of file
diff --git a/cli/tri/src/main.rs b/cli/tri/src/main.rs
index 2e8c36a72a..d82c7e7e2a 100644
--- a/cli/tri/src/main.rs
+++ b/cli/tri/src/main.rs
@@ -56,12 +56,10 @@ mod gen_cache; // the gen-hash cache's eviction limit, for `tri hot caches` (#89
mod bit_cache; // the bitstream cache's eviction limit, for `tri hot caches` (#8952)
#[path = "../../../gen/rust/tri/hot/hot.rs"] #[allow(dead_code, unused_parens)]
mod hot; // t27c gen-rust of specs/tri/hot/hot.t27 (#8870): every rule of `tri hot`
-#[path = "../../../gen/rust/tools/t27o/ledger.rs"] #[allow(dead_code, unused_parens, clippy::all)]
-mod t27o_ledger; // t27c gen-rust of specs/tools/t27o/ledger.t27: which runner's exit code is a verdict for `tri t27o --check` (#10525)
+#[path = "../../../gen/rust/tools/t27o/ledger.rs"] #[allow(dead_code, unused_parens, clippy::all)] mod t27o_ledger; // t27c gen-rust of specs/tools/t27o/ledger.t27: which runner's exit code is a verdict for `tri t27o --check` (#10525), which front end reads a file, what a .zig file is judged by (#10823)
#[path = "../../../gen/rust/tri/lanes/lanes.rs"] #[allow(dead_code, unused_parens)]
mod lanes; // t27c gen-rust of specs/tri/lanes/lanes.t27: every rule of `tri lanes`
-#[path = "../../../gen/rust/tools/t27o/rust_convert.rs"] #[allow(dead_code, unused_parens, unused_mut, unused_variables, non_snake_case, unused_assignments, clippy::all)]
-mod t27o; // t27c gen-rust of specs/tools/t27o/rust_convert.t27: every rule of `tri t27o` (#8967)
+#[path = "../../../gen/rust/tools/t27o/rust_convert.rs"] #[allow(dead_code, unused_parens, unused_mut, unused_variables, non_snake_case, unused_assignments, clippy::all)] mod t27o; // t27c gen-rust of specs/tools/t27o/rust_convert.t27: every rule of `tri t27o` (#8967)
#[path = "../../../gen/rust/tools/t27o/spice_convert.rs"] #[allow(dead_code, unused_parens, unused_mut, unused_variables, non_snake_case, unused_assignments, clippy::all)] mod spice; // t27c gen-rust of specs/tools/t27o/spice_convert.t27: the SPICE front end of `tri t27o` (#10509)
#[path = "../../../gen/rust/tools/t27o/zig_convert.rs"] #[allow(dead_code, unused_parens, unused_mut, unused_variables, non_snake_case, unused_assignments, clippy::all)] mod zig; // t27c gen-rust of specs/tools/t27o/zig_convert.t27: the Zig front end of `tri t27o` (#10765)
mod renum;
@@ -432,7 +430,7 @@ enum Commands {
/// Print one JSON object instead of the table.
#[arg(long)] json: bool,
},
- /// t27o (Ouroboros): a Rust file as a t27 spec; --oracle prints the rustc harness, --check runs it and t27c test-report on the spec and its oracle tests (rules: specs/tools/t27o/rust_convert.t27). A .spice/.cir/.sp netlist prints its inventory or the refusal, and with --emit-cell the constants of the M1 linear cell folded from it (rules: specs/tools/t27o/spice_convert.t27). A .zig file prints the spec and its count line (rules: specs/tools/t27o/zig_convert.t27); its own tests are the oracle, so run `t27b test` on the spec (--oracle and --check are for Rust).
+ /// t27o (Ouroboros): a Rust file as a t27 spec; --oracle prints the rustc harness, --check runs it and t27c test-report on the spec and its oracle tests (rules: specs/tools/t27o/rust_convert.t27). A .spice/.cir/.sp netlist prints its inventory or the refusal, and with --emit-cell the constants of the M1 linear cell folded from it (rules: specs/tools/t27o/spice_convert.t27). A .zig file prints the spec and its count line (rules: specs/tools/t27o/zig_convert.t27); its own tests are the oracle, so --check writes the spec and judges it by them, and --oracle says it does not apply.
T27o {
file: String,
/// The module name; default the file's stem.
@@ -445,7 +443,7 @@ enum Commands {
/// A netlist: print the M1 cell constants (CELL_N, CELL_D, CELL_NV) folded from it, or the refusal, instead of the inventory.
#[arg(long)] emit_cell: bool,
},
- /// t27o over a tree (#10543): every tracked .rs file converted in-process; a file's row is reused while its key holds (its SHA-256 and the seals of rust_convert.t27 and rust_std.t27, read from the t27 checkout this runs in); `--repo
` sweeps another checkout, with a cache of its own (#10638); counts, coverage and the ranked first-refusal kinds (rules: specs/tools/t27o/ledger.t27).
+ /// t27o over a tree (#10543): every tracked .rs and .zig file converted in-process; a file's row is reused while its key holds (its SHA-256 and the seals of rust_convert.t27 and rust_std.t27, and of zig_convert.t27 for a .zig file, read from the t27 checkout this runs in); `--repo ` sweeps another checkout, with a cache of its own (#10638); counts, coverage and the ranked first-refusal kinds (rules: specs/tools/t27o/ledger.t27).
T27oSweep { paths: Vec, #[arg(long, default_value = t27o_ledger::SWEEP_HERE)] repo: String, #[arg(long, default_value_t = t27o_ledger::SWEEP_MAX_BYTES)] max_bytes: usize, #[arg(long)] cache: Option, #[arg(long, default_value_t = t27o_ledger::SWEEP_TOP)] top: usize },
}
@@ -1355,6 +1353,12 @@ fn main() -> Result<()> {
}
/// `tri t27o` (#8967): every rule is gen-rust of rust_convert.t27; this reads the file, runs rustc and t27c, and writes.
+fn zig_source(file: &Path, src: &[u8]) -> Vec { // a .zig source with the consts it imports from files of its own directory tree written in: zig_convert.t27 `imports` names the files, `inline_imports` writes the values, this only reads (a symlink out of the tree is not followed; #10823)
+ let (dir, mut want, mut ext, mut flat, mut st) = (file.parent().and_then(|d| fs::canonicalize(d).ok()).unwrap_or_default(), vec![0u8; src.len() + 64], Vec::new(), vec![0u8; 4 * src.len() + 64], vec![0usize; zig::ZI_SLOTS]);
+ let w = zig::imports(src, &mut want, &mut st).min(want.len()); for rel in String::from_utf8_lossy(&want[..w]).lines() { if let Some(t) = fs::canonicalize(dir.join(rel)).ok().filter(|f| f.starts_with(&dir)).and_then(|f| fs::read(f).ok()) { ext.extend([&[zig::Z_B_REC][..], rel.as_bytes(), b"\n", &t].concat()); } }
+ let n = zig::inline_imports(src, &ext, &mut flat, &mut st).min(flat.len()); flat.truncate(n); flat
+}
+
fn cmd_t27o(file: &str, name: Option<&str>, oracle: bool, check: bool, t27c: Option<&str>, emit_cell: bool) -> Result {
let src = fs::read(file).with_context(|| format!("reading {file}"))?;
if spice::is_spice_name(file.as_bytes()) { // a netlist: every rule is specs/tools/t27o/spice_convert.t27 (#10509)
@@ -1364,24 +1368,19 @@ fn cmd_t27o(file: &str, name: Option<&str>, oracle: bool, check: bool, t27c: Opt
return Ok(spice::exit_code(&st));
}
let stem = name.map_or_else(|| Path::new(file).file_stem().map_or("Converted".into(), |s| s.to_string_lossy().into_owned()), str::to_string);
+ let zig = t27o_ledger::front_end(file.as_bytes()) == t27o_ledger::FE_ZIG; if zig && oracle { println!("{}", t27o_ledger::NOTE_ZIG_ORACLE); return Ok(0); } // a .zig file: its own tests are the oracle (ledger.t27, #10823)
+ let src = if zig { zig_source(Path::new(file), &src) } else { src };
let (mut out, mut st, mut spec) = (vec![0u8; 1 << 24], vec![0usize; 1 << 18], vec![0u8; 1 << 24]);
- let n = if zig::is_zig_name(file.as_bytes()) { zig::to_t27(&src, stem.as_bytes(), &mut out, &mut st) } else if oracle || check { t27o::oracle(&src, &mut out, &mut st) } else { t27o::convert(&src, stem.as_bytes(), &mut out, &mut st) };
- if !check {
- std::io::Write::write_all(&mut std::io::stdout(), &out[..n.min(out.len())])?;
- return Ok(0);
+ let mut n = if zig { zig::to_t27(&src, stem.as_bytes(), &mut out, &mut st) } else if oracle || check { t27o::oracle(&src, &mut out, &mut st) } else { t27o::convert(&src, stem.as_bytes(), &mut out, &mut st) };
+ if !check { std::io::Write::write_all(&mut std::io::stdout(), &out[..n.min(out.len())])?; return Ok(0); }
+ let (h, exe, path) = (Path::new(file).with_file_name("zz_t27o_oracle.rs"), std::env::temp_dir().join("t27o_oracle"), PathBuf::from(format!("specs/t27o_check/{stem}.t27"))); // the harness sits next to the source, so its #[path] mods resolve; the spec under specs/, so its `use`s do
+ if !zig { // a Rust file: the harness rustc builds is run and its samples follow the spec
+ fs::write(&h, &out[..n.min(out.len())])?; let built = Command::new("rustc").args(["--edition", "2021", "-o"]).arg(&exe).arg(&h).status(); fs::remove_file(&h)?; anyhow::ensure!(built?.success(), "rustc refused the oracle harness of {file}");
+ let m = t27o::convert(&src, stem.as_bytes(), &mut spec, &mut st); out = [&spec[..m.min(spec.len())], &Command::new(&exe).output()?.stdout[..]].concat(); n = out.len();
}
- // the harness sits next to the source, so its #[path] mods resolve; the spec under specs/, so its `use`s do
- let (h, exe, path) = (Path::new(file).with_file_name("zz_t27o_oracle.rs"), std::env::temp_dir().join("t27o_oracle"), PathBuf::from(format!("specs/t27o_check/{stem}.t27")));
- fs::write(&h, &out[..n.min(out.len())])?;
- let built = Command::new("rustc").args(["--edition", "2021", "-o"]).arg(&exe).arg(&h).status();
- fs::remove_file(&h)?;
- anyhow::ensure!(built?.success(), "rustc refused the oracle harness of {file}");
- let m = t27o::convert(&src, stem.as_bytes(), &mut spec, &mut st);
- fs::create_dir_all("specs/t27o_check")?;
- fs::write(&path, [&spec[..m.min(spec.len())], &Command::new(&exe).output()?.stdout[..]].concat())?;
- println!("{}", path.display());
- let b = ["target/release/t27b", "target/debug/t27b"].into_iter().find(|p| Path::new(p).exists()).unwrap_or("t27b"); // t27b judges first, t27c only when its exit is no verdict (specs/tools/t27o/ledger.t27, #10525)
- let c = Command::new(b).arg("test").arg(&path).status().ok().and_then(|s| s.code()).unwrap_or(-1);
+ fs::create_dir_all("specs/t27o_check")?; fs::write(&path, &out[..n.min(out.len())])?; println!("{}", path.display());
+ if !t27o_ledger::has_evidence(zig, st[zig::Z_NTEST]) { eprintln!("{}", t27o_ledger::NOTE_ZIG_UNJUDGED); return Ok(t27o_ledger::EXIT_UNJUDGED as u8); }
+ let b = ["target/release/t27b", "target/debug/t27b"].into_iter().find(|p| Path::new(p).exists()).unwrap_or("t27b"); let c = Command::new(b).arg("test").arg(&path).status().ok().and_then(|s| s.code()).unwrap_or(-1); // t27b judges first, t27c only when its exit is no verdict (specs/tools/t27o/ledger.t27, #10525)
if !t27o_ledger::needs_reference(t27o_ledger::t27b_outcome(c)) { return Ok(c as u8); } eprintln!("t27o: {b} test exited {c} ({}), so t27c test-report judges instead", t27o_ledger::ORC_NAMES[t27o_ledger::t27b_outcome(c) as usize]);
Ok(Command::new(mutate::resolve_t27c(t27c)).arg("test-report").arg(&path).status()?.code().unwrap_or(1) as u8)
}
@@ -1389,7 +1388,7 @@ fn cmd_t27o(file: &str, name: Option<&str>, oracle: bool, check: bool, t27c: Opt
/// `tri t27o-sweep` (#10543): every rule is ledger.t27 (which files, whether a row is reusable, coverage, root vs cascade, the ranking); this lists, hashes, converts in-process and keeps the cache.
fn cmd_t27o_sweep(paths: &[String], repo: &str, max: usize, cache: Option<&str>, top: usize) -> Result {
let t0 = std::time::Instant::now(); let seal = |f: &str| -> Result { let p = std::env::current_dir()?.join(f); Ok(serde_json::from_slice::(&fs::read(&p).with_context(|| format!("{}: cannot read the seal; {}", p.display(), t27o_ledger::SEAL_HINT))?)?["spec_hash"].as_str().with_context(|| format!("{}: no spec_hash", p.display()))?.to_string()) };
- let (conv, std) = (seal(t27o_ledger::SEAL_CONVERTER)?, seal(t27o_ledger::SEAL_STD)?); let repo: &'static str = repo.to_string().leak(); // the keys come from this checkout; the listing, the files and the cache belong to `root`
+ let (conv, std, zs) = (seal(t27o_ledger::SEAL_CONVERTER)?, seal(t27o_ledger::SEAL_STD)?, seal(t27o_ledger::SEAL_ZIG)?); let zk = format!("{conv}+{zs}"); let repo: &'static str = repo.to_string().leak(); // the keys come from this checkout; the listing, the files and the cache belong to `root`
let root: &'static str = if t27o_ledger::repo_is_here(repo) { t27o_ledger::SWEEP_HERE } else { fs::canonicalize(repo).with_context(|| format!("{repo}: cannot open the repository"))?.to_string_lossy().into_owned().leak() }; let cache = cache.map_or_else(|| { let mut b = vec![0u8; 4096]; let n = t27o_ledger::cache_path(root, &mut b); String::from_utf8_lossy(&b[..n]).into_owned() }, str::to_string);
let old: &'static str = fs::read_to_string(&cache).unwrap_or_default().leak(); let rows: std::collections::HashMap<&'static str, Vec<&'static str>> = old.lines().map(|l| l.split('\t').collect::>()).filter(|f| f.len() == 10).map(|f| (f[0], f)).collect();
let ls = Command::new("git").args(["-C", root, "ls-files", "--"]).args(paths).output()?; anyhow::ensure!(ls.status.success(), "{root}: git ls-files failed: {}", String::from_utf8_lossy(&ls.stderr).trim()); let listing: &'static str = String::from_utf8(ls.stdout)?.leak();
@@ -1397,13 +1396,14 @@ fn cmd_t27o_sweep(paths: &[String], repo: &str, max: usize, cache: Option<&str>,
for p in listing.lines().filter(|p| t27o_ledger::sweep_path(p)) {
let Ok(src) = fs::read(Path::new(root).join(p)) else { continue };
if t27o_ledger::over_cap(src.len(), max) { n[2] += 1; println!("{p} {} bytes skipped", src.len()); continue; }
- let (sha, r) = (format!("{:x}", Sha256::digest(&src)), rows.get(p));
- let reuse = t27o_ledger::reuse_row(t27o_ledger::key_check(r.is_some(), r.is_some_and(|r| r[1] == sha), r.is_some_and(|r| r[2] == conv), r.is_some_and(|r| r[3] == std)));
+ let z = t27o_ledger::front_end(p.as_bytes()) == t27o_ledger::FE_ZIG; let ck = if z { &zk } else { &conv }; // a .zig row is keyed by both converters' seals, and by the source with its imported consts written in (#10823)
+ let src = if z { zig_source(&Path::new(root).join(p), &src) } else { src }; let (sha, r) = (format!("{:x}", Sha256::digest(&src)), rows.get(p));
+ let reuse = t27o_ledger::reuse_row(t27o_ledger::key_check(r.is_some(), r.is_some_and(|r| r[1] == sha), r.is_some_and(|r| r[2] == *ck), r.is_some_and(|r| r[3] == std)));
let f: Vec<&'static str> = if reuse { r.unwrap().clone() } else {
- let (mut out, mut st, mut k) = (vec![0u8; 1 << 24], vec![0usize; 1 << 16], std::collections::BTreeMap::<&'static str, usize>::new());
- let m = t27o::convert(&src, Path::new(p).file_stem().map_or("Converted".into(), |s| s.to_string_lossy().into_owned()).as_bytes(), &mut out, &mut st);
+ let (mut out, mut st, mut k) = (vec![0u8; 1 << 24], vec![0usize; 1 << 18], std::collections::BTreeMap::<&'static str, usize>::new()); let stem = Path::new(p).file_stem().map_or("Converted".into(), |s| s.to_string_lossy().into_owned());
+ let m = if z { zig::to_t27(&src, stem.as_bytes(), &mut out, &mut st) } else { t27o::convert(&src, stem.as_bytes(), &mut out, &mut st) };
let o: &'static str = String::from_utf8_lossy(&out[..m.min(out.len())]).into_owned().leak(); for l in o.lines().filter(|l| t27o_ledger::is_refusal(l)) { *k.entry(&l[t27o_ledger::kind_from(l)..t27o_ledger::kind_to(l)]).or_default() += 1; }
- format!("{p}\t{sha}\t{conv}\t{std}\t{}\t{}\t{}\t{}\t{}\t{}", st[t27o::NFN], st[t27o::NOK], st[t27o::NTEST], st[t27o::NTS], st[t27o::NSTUB], k.iter().map(|(a, b)| format!("{a}={b}")).collect::>().join(";")).leak().split('\t').collect()
+ format!("{p}\t{sha}\t{ck}\t{std}\t{}\t{}\t{}\t{}\t{}\t{}", st[t27o::NFN], st[t27o::NOK], st[t27o::NTEST], st[t27o::NTS], st[t27o::NSTUB], k.iter().map(|(a, b)| format!("{a}={b}")).collect::>().join(";")).leak().split('\t').collect()
};
n[reuse as usize] += 1; tab += &format!("{}\n", f.join("\t"));
(0..5).for_each(|i| tot[i] += f[4 + i].parse::().unwrap_or(0));
diff --git a/gen/rust/tools/t27o/ledger.rs b/gen/rust/tools/t27o/ledger.rs
index 7bd930bc18..1f94ee3b14 100644
--- a/gen/rust/tools/t27o/ledger.rs
+++ b/gen/rust/tools/t27o/ledger.rs
@@ -1,6 +1,6 @@
// Generated from .t27 spec
// DO NOT EDIT — generated by t27c
-// NOT LOWERED BY THIS BACKEND: 29 test(s), 0 invariant(s), 0 function(s) with no body.
+// NOT LOWERED BY THIS BACKEND: 38 test(s), 0 invariant(s), 0 function(s) with no body.
// This backend emits declarations only. The spec's checks live in
// the Zig and Verilog outputs; do not read this file as verified.
@@ -78,6 +78,33 @@ pub const T27B_DISAGREE: i32 = 4;
pub const T27B_CODEGEN_LIMIT: i32 = 5;
+pub const FE_RUST: u32 = 0;
+
+pub const FE_ZIG: u32 = 1;
+
+pub const EXIT_UNJUDGED: i32 = 6;
+
+pub const NOTE_ZIG_ORACLE: &'static str = "t27o: --oracle does not apply to a .zig file: its own tests are the oracle, and --check runs them on the spec";
+
+pub const NOTE_ZIG_UNJUDGED: &'static str = "t27o: no test of this .zig file converted, so nothing judges the spec; a spec that ran no test is not a pass";
+
+pub fn front_end(path: &[u8]) -> u32 {
+ if (path.len() < 4) {
+ return FE_RUST;
+ }
+ if ((((path[((path.len() - 4)) as usize] == 46) && (path[((path.len() - 3)) as usize] == 122)) && (path[((path.len() - 2)) as usize] == 105)) && (path[((path.len() - 1)) as usize] == 103)) {
+ return FE_ZIG;
+ }
+ return FE_RUST;
+}
+
+pub fn has_evidence(is_zig: bool, tests_converted: usize) -> bool {
+ if (is_zig == false) {
+ return true;
+ }
+ return (tests_converted > 0);
+}
+
pub fn t27b_outcome(code: i32) -> u32 {
if (code == T27B_PASS) {
return ORC_PASS;
@@ -236,6 +263,8 @@ pub const SEAL_CONVERTER: &'static str = ".trinity/seals/t27o_T27oRust.json";
pub const SEAL_STD: &'static str = ".trinity/seals/t27o_T27oRustStd.json";
+pub const SEAL_ZIG: &'static str = ".trinity/seals/t27o_T27oZig.json";
+
pub const SEAL_HINT: &'static str = "run from a t27 checkout";
pub const COVERAGE_UNKNOWN: usize = 1001;
@@ -250,7 +279,7 @@ pub fn sweep_path(path: &'static str) -> bool {
if (path.len() < 3) {
return false;
}
- if (span_is(path, (path.len() - 3), path.len(), ".rs") == false) {
+ if ((span_is(path, (path.len() - 3), path.len(), ".rs") == false) && (front_end(path.as_bytes()) != FE_ZIG)) {
return false;
}
let mut from: usize = 0;
@@ -355,7 +384,7 @@ pub fn kind_to(line: &'static str) -> usize {
return line.len();
}
let mut k: usize = reason_from(line);
- while ((k < line.len()) && (line.as_bytes()[(k) as usize] != 96)) {
+ while (((k < line.len()) && (line.as_bytes()[(k) as usize] != 96)) && (line.as_bytes()[(k) as usize] != 59)) {
k = (k + 1);
}
if ((k > reason_from(line)) && (line.as_bytes()[((k - 1)) as usize] == 32)) {
diff --git a/gen/rust/tools/t27o/zig_convert.rs b/gen/rust/tools/t27o/zig_convert.rs
index df27576097..d588867841 100644
--- a/gen/rust/tools/t27o/zig_convert.rs
+++ b/gen/rust/tools/t27o/zig_convert.rs
@@ -1,20 +1,20 @@
// Generated from .t27 spec
// DO NOT EDIT — generated by t27c
-// NOT LOWERED BY THIS BACKEND: 45 test(s), 0 invariant(s), 0 function(s) with no body.
+// NOT LOWERED BY THIS BACKEND: 61 test(s), 0 invariant(s), 0 function(s) with no body.
// This backend emits declarations only. The spec's checks live in
// the Zig and Verilog outputs; do not read this file as verified.
-pub const Z_NFN: usize = 8;
+pub const Z_NFN: usize = NFN;
-pub const Z_NOK: usize = 9;
+pub const Z_NOK: usize = NOK;
-pub const Z_NTS: usize = 10;
+pub const Z_NTS: usize = NTS;
-pub const Z_NTEST: usize = 11;
+pub const Z_NTEST: usize = NTEST;
-pub const Z_CLS: usize = 12;
+pub const Z_CLS: usize = 8;
-pub const Z_STMT: usize = 13;
+pub const Z_STMT: usize = 9;
pub const Z_TMP: usize = 14;
@@ -28,7 +28,9 @@ pub const Z_ROUND: usize = 18;
pub const Z_RET: usize = 19;
-pub const Z_GREW: usize = 20;
+pub const Z_GREW: usize = 100;
+
+pub const Z_USEPOS: usize = 101;
pub const Z_HIT: usize = 21;
@@ -72,10 +74,6 @@ pub const Z_B_TILDE: u8 = 126;
pub const Z_B_P: u8 = 112;
-pub const Z_B_I: u8 = 105;
-
-pub const Z_B_G: u8 = 103;
-
pub fn z_tok_end(src: &[u8], p: usize) -> usize {
if (p >= src.len()) {
return p;
@@ -199,6 +197,10 @@ pub const Z_R_BOPERAND: usize = 32;
pub const Z_R_HOIST: usize = 33;
+pub const Z_R_POW: usize = 34;
+
+pub const Z_R_POWCONST: usize = 35;
+
pub fn z_put_why(st: &mut [usize], out: &mut [u8], code: usize) -> () {
if (code == Z_R_GENERIC) {
puts(st, out, b"comptime or generic");
@@ -328,6 +330,14 @@ pub fn z_put_why(st: &mut [usize], out: &mut [u8], code: usize) -> () {
puts(st, out, b"array literal outside a statement");
return ();
}
+ if (code == Z_R_POW) {
+ puts(st, out, b"pow of a type other than f64");
+ return ();
+ }
+ if (code == Z_R_POWCONST) {
+ puts(st, out, b"pow in a file-level const");
+ return ();
+ }
puts(st, out, b"syntax");
}
@@ -1192,6 +1202,25 @@ pub fn z_std_member(src: &[u8], st: &mut [usize], out: &mut [u8], a0: usize, ns:
z_want(src, st, b")");
return L_ATOM;
}
+ if word_is(src, ma, mb, b"pow") {
+ if (st[(Z_INCONST) as usize] == 1) {
+ refuse(st, Z_R_POWCONST, a0, a0, mb);
+ return L_ATOM;
+ }
+ z_want(src, st, b"(");
+ if !(z_take(src, st, b"f64")) {
+ refuse(st, Z_R_POW, a0, a0, mb);
+ return L_ATOM;
+ }
+ z_want(src, st, b",");
+ puts(st, out, b"std_math_pow_f64(");
+ z_args_rest(src, st, out);
+ if (st[(Z_NARGS) as usize] != 2) {
+ refuse(st, Z_R_SYNTAX, a0, a0, mb);
+ }
+ st[(Z_CLS) as usize] = ZC_F64;
+ return L_ATOM;
+ }
if (word_is(src, ma, mb, b"maxInt") || word_is(src, ma, mb, b"minInt")) {
z_want(src, st, b"(");
let ta: usize = st[(P) as usize];
@@ -3321,12 +3350,322 @@ pub fn z_item(src: &[u8], st: &mut [usize], out: &mut [u8]) -> () {
st[(P) as usize] = skip_ws(src, end);
}
-pub fn is_zig_name(name: &[u8]) -> bool {
- if (name.len() < 4) {
+pub const Z_B_REC: u8 = 1;
+
+pub const Z_LIT_MAX: usize = 64;
+
+pub const ZI_NA: usize = 8;
+
+pub const ZI_NB: usize = 9;
+
+pub const ZI_TA: usize = 10;
+
+pub const ZI_TB: usize = 11;
+
+pub const ZI_PA: usize = 12;
+
+pub const ZI_PB: usize = 13;
+
+pub const ZI_MA: usize = 14;
+
+pub const ZI_MB: usize = 15;
+
+pub const ZI_SEMI: usize = 16;
+
+pub const ZI_XA: usize = 17;
+
+pub const ZI_XB: usize = 18;
+
+pub const ZI_LA: usize = 19;
+
+pub const ZI_LB: usize = 20;
+
+pub const ZI_SLOTS: usize = 21;
+
+pub fn z_import_path_ok(src: &[u8], a: usize, b: usize) -> bool {
+ if ((b < (a + 5)) || (b > src.len())) {
+ return false;
+ }
+ if !(word_is(src, (b - 4), b, b".zig")) {
+ return false;
+ }
+ if (src[(a) as usize] == B_SLASH) {
+ return false;
+ }
+ let mut comp: usize = a;
+ let mut k: usize = a;
+ while (k < b) {
+ let c: u8 = src[(k) as usize];
+ if ((((c == B_BACKSLASH) || (c == B_COLON)) || (c < B_SPACE)) || (c == B_DEL)) {
+ return false;
+ }
+ if (c == B_SLASH) {
+ if ((((k - comp) == 2) && (src[(comp) as usize] == B_DOT)) && (src[((comp + 1)) as usize] == B_DOT)) {
+ return false;
+ }
+ comp = (k + 1);
+ }
+ k = (k + 1);
+ }
+ return true;
+}
+
+pub fn z_lit_end(buf: &[u8], p: usize) -> usize {
+ let mut q: usize = p;
+ if (head(buf, q) == B_MINUS) {
+ q = (q + 1);
+ }
+ let e: usize = z_tok_end(buf, q);
+ if (((e <= q) || (e > buf.len())) || ((e - p) > Z_LIT_MAX)) {
+ return p;
+ }
+ if is_digit(head(buf, q)) {
+ return e;
+ }
+ if (q != p) {
+ return p;
+ }
+ if (word_is(buf, q, e, b"true") || word_is(buf, q, e, b"false")) {
+ return e;
+ }
+ if (((head(buf, q) != B_QUOTE) || (e < (q + 2))) || (buf[((e - 1)) as usize] != B_QUOTE)) {
+ return p;
+ }
+ let mut k: usize = (q + 1);
+ while (k < (e - 1)) {
+ if ((buf[(k) as usize] == B_BACKSLASH) || (buf[(k) as usize] == B_NL)) {
+ return p;
+ }
+ k = (k + 1);
+ }
+ return e;
+}
+
+pub fn z_import_const(src: &[u8], p: usize, ps: &mut [usize]) -> bool {
+ let mut q: usize = p;
+ if z_is(src, q, b"pub") {
+ q = skip_ws(src, z_tok_end(src, q));
+ }
+ if !(z_is(src, q, b"const")) {
+ return false;
+ }
+ let na: usize = skip_ws(src, z_tok_end(src, q));
+ let nb: usize = z_tok_end(src, na);
+ if !(is_alpha(head(src, na))) {
+ return false;
+ }
+ ps[(ZI_NA) as usize] = na;
+ ps[(ZI_NB) as usize] = nb;
+ ps[(ZI_TA) as usize] = 0;
+ ps[(ZI_TB) as usize] = 0;
+ let mut t: usize = skip_ws(src, nb);
+ if z_is(src, t, b":") {
+ let ta: usize = skip_ws(src, z_tok_end(src, t));
+ let tb: usize = z_tok_end(src, ta);
+ if !(z_scalar(src, ta, tb)) {
+ return false;
+ }
+ ps[(ZI_TA) as usize] = ta;
+ ps[(ZI_TB) as usize] = tb;
+ t = skip_ws(src, tb);
+ }
+ if !(z_is(src, t, b"=")) {
+ return false;
+ }
+ let i: usize = skip_ws(src, z_tok_end(src, t));
+ if !(z_is(src, i, b"@import")) {
+ return false;
+ }
+ let o: usize = skip_ws(src, z_tok_end(src, i));
+ if !(z_is(src, o, b"(")) {
+ return false;
+ }
+ let s: usize = skip_ws(src, z_tok_end(src, o));
+ let sb: usize = z_tok_end(src, s);
+ if (((head(src, s) != B_QUOTE) || (sb < (s + 3))) || (head(src, (sb - 1)) != B_QUOTE)) {
+ return false;
+ }
+ if !(z_import_path_ok(src, (s + 1), (sb - 1))) {
+ return false;
+ }
+ let c: usize = skip_ws(src, sb);
+ if !(z_is(src, c, b")")) {
+ return false;
+ }
+ let d: usize = skip_ws(src, z_tok_end(src, c));
+ if !(z_is(src, d, b".")) {
+ return false;
+ }
+ let m: usize = skip_ws(src, z_tok_end(src, d));
+ let mb: usize = z_tok_end(src, m);
+ if !(is_alpha(head(src, m))) {
+ return false;
+ }
+ let semi: usize = skip_ws(src, mb);
+ if (head(src, semi) != B_SEMI) {
+ return false;
+ }
+ ps[(ZI_PA) as usize] = (s + 1);
+ ps[(ZI_PB) as usize] = (sb - 1);
+ ps[(ZI_MA) as usize] = m;
+ ps[(ZI_MB) as usize] = mb;
+ ps[(ZI_SEMI) as usize] = semi;
+ return true;
+}
+
+pub fn z_ext_value(ext: &[u8], nb: usize, ps: &mut [usize]) -> bool {
+ ps[(ZI_XA) as usize] = 0;
+ ps[(ZI_XB) as usize] = 0;
+ let mut t: usize = skip_ws(ext, nb);
+ if z_is(ext, t, b":") {
+ let ta: usize = skip_ws(ext, z_tok_end(ext, t));
+ let tb: usize = z_tok_end(ext, ta);
+ if !(z_scalar(ext, ta, tb)) {
+ return false;
+ }
+ ps[(ZI_XA) as usize] = ta;
+ ps[(ZI_XB) as usize] = tb;
+ t = skip_ws(ext, tb);
+ }
+ if !(z_is(ext, t, b"=")) {
+ return false;
+ }
+ let la: usize = skip_ws(ext, z_tok_end(ext, t));
+ let le: usize = z_lit_end(ext, la);
+ if ((le == la) || (head(ext, skip_ws(ext, le)) != B_SEMI)) {
return false;
}
- let f: usize = (name.len() - 4);
- return ((((name[(f) as usize] == B_DOT) && (name[((f + 1)) as usize] == B_LOWER_Z)) && (name[((f + 2)) as usize] == Z_B_I)) && (name[((f + 3)) as usize] == Z_B_G));
+ ps[(ZI_LA) as usize] = la;
+ ps[(ZI_LB) as usize] = le;
+ return true;
+}
+
+pub fn z_ext_const(ext: &[u8], lo: usize, hi: usize, src: &[u8], ps: &mut [usize]) -> bool {
+ let mut p: usize = skip_ws(ext, lo);
+ while (p < hi) {
+ let mut end: usize = z_item_end(ext, p);
+ if (end <= p) {
+ end = (p + 1);
+ }
+ if (end > hi) {
+ return false;
+ }
+ let mut q: usize = p;
+ if z_is(ext, q, b"pub") {
+ q = skip_ws(ext, z_tok_end(ext, q));
+ if z_is(ext, q, b"const") {
+ let na: usize = skip_ws(ext, z_tok_end(ext, q));
+ let nb: usize = z_tok_end(ext, na);
+ if word_is(ext, na, nb, &src[(ps[(ZI_MA) as usize]) as usize..(ps[(ZI_MB) as usize]) as usize]) {
+ return z_ext_value(ext, nb, ps);
+ }
+ }
+ }
+ p = skip_ws(ext, end);
+ }
+ return false;
+}
+
+pub fn z_seg_end(ext: &[u8], from: usize) -> usize {
+ let mut k: usize = from;
+ while ((k < ext.len()) && (ext[(k) as usize] != Z_B_REC)) {
+ k = (k + 1);
+ }
+ return k;
+}
+
+pub fn z_rec_text(ext: &[u8], src: &[u8], a: usize, b: usize) -> usize {
+ let n: usize = (b - a);
+ let mut k: usize = 0;
+ while (((k + n) + 1) < ext.len()) {
+ if (((ext[(k) as usize] == Z_B_REC) && (ext[(((k + 1) + n)) as usize] == B_NL)) && word_is(ext, (k + 1), ((k + 1) + n), &src[(a) as usize..(b) as usize])) {
+ return ((k + n) + 2);
+ }
+ k = (k + 1);
+ }
+ return ext.len();
+}
+
+pub fn z_listed(out: &[u8], w: usize, src: &[u8], a: usize, b: usize) -> bool {
+ let n: usize = (b - a);
+ let mut k: usize = 0;
+ while (((k + n) < w) && ((k + n) < out.len())) {
+ if ((((k == 0) || (out[((k - 1)) as usize] == B_NL)) && (out[((k + n)) as usize] == B_NL)) && word_is(out, k, (k + n), &src[(a) as usize..(b) as usize])) {
+ return true;
+ }
+ k = (k + 1);
+ }
+ return false;
+}
+
+pub fn z_one_line(src: &[u8], a: usize, b: usize) -> bool {
+ let mut k: usize = a;
+ while ((k < b) && (k < src.len())) {
+ if ((src[(k) as usize] == B_NL) || (src[(k) as usize] == B_CR)) {
+ return false;
+ }
+ k = (k + 1);
+ }
+ return true;
+}
+
+pub fn imports(src: &[u8], out: &mut [u8], st: &mut [usize]) -> usize {
+ if (st.len() < ZI_SLOTS) {
+ return 0;
+ }
+ st[(W) as usize] = 0;
+ let mut p: usize = skip_ws(src, 0);
+ while (p < src.len()) {
+ let mut end: usize = z_item_end(src, p);
+ if (end <= p) {
+ end = (p + 1);
+ }
+ if (z_import_const(src, p, st) && !(z_listed(out, st[(W) as usize], src, st[(ZI_PA) as usize], st[(ZI_PB) as usize]))) {
+ put_src(src, st, out, st[(ZI_PA) as usize], st[(ZI_PB) as usize]);
+ put(st, out, B_NL);
+ }
+ p = skip_ws(src, end);
+ }
+ return st[(W) as usize];
+}
+
+pub fn inline_imports(src: &[u8], ext: &[u8], out: &mut [u8], st: &mut [usize]) -> usize {
+ if (st.len() < ZI_SLOTS) {
+ return 0;
+ }
+ st[(W) as usize] = 0;
+ let mut done: usize = 0;
+ let mut p: usize = skip_ws(src, 0);
+ while (p < src.len()) {
+ let mut end: usize = z_item_end(src, p);
+ if (end <= p) {
+ end = (p + 1);
+ }
+ if z_import_const(src, p, st) {
+ let lo: usize = z_rec_text(ext, src, st[(ZI_PA) as usize], st[(ZI_PB) as usize]);
+ if (((lo < ext.len()) && z_ext_const(ext, lo, z_seg_end(ext, lo), src, st)) && z_one_line(src, st[(ZI_NB) as usize], st[(ZI_SEMI) as usize])) {
+ put_src(src, st, out, done, st[(ZI_NB) as usize]);
+ if (st[(ZI_TA) as usize] != 0) {
+ puts(st, out, b": ");
+ put_src(src, st, out, st[(ZI_TA) as usize], st[(ZI_TB) as usize]);
+ puts(st, out, b" = ");
+ } else {
+ if (st[(ZI_XA) as usize] != 0) {
+ puts(st, out, b": ");
+ put_src(ext, st, out, st[(ZI_XA) as usize], st[(ZI_XB) as usize]);
+ puts(st, out, b" = ");
+ } else {
+ puts(st, out, b" = ");
+ }
+ }
+ put_src(ext, st, out, st[(ZI_LA) as usize], st[(ZI_LB) as usize]);
+ done = st[(ZI_SEMI) as usize];
+ }
+ }
+ p = skip_ws(src, end);
+ }
+ put_src(src, st, out, done, src.len());
+ return st[(W) as usize];
}
pub fn z_ci_at(src: &[u8], i: usize, s: &[u8]) -> bool {
@@ -3403,6 +3742,31 @@ pub fn z_report(st: &mut [usize], out: &mut [u8]) -> () {
puts(st, out, b"%\n");
}
+pub fn z_out_mentions(out: &[u8], a: usize, b: usize, s: &[u8]) -> bool {
+ let mut j: usize = a;
+ while ((j + s.len()) <= b) {
+ if z_out_has(out, j, s) {
+ return true;
+ }
+ j = (j + 1);
+ }
+ return false;
+}
+
+pub fn z_put_uses(st: &mut [usize], out: &mut [u8]) -> () {
+ let from: usize = st[(Z_USEPOS) as usize];
+ let w0: usize = st[(W) as usize];
+ if ((w0 <= out.len()) && !(z_out_mentions(out, from, w0, b"std_math_pow_f64("))) {
+ return ();
+ }
+ puts(st, out, b"use tools::t27o::zig_std::std_math_pow_f64;\n\n");
+ if (st[(W) as usize] <= out.len()) {
+ reverse(out, from, w0);
+ reverse(out, w0, st[(W) as usize]);
+ reverse(out, from, st[(W) as usize]);
+ }
+}
+
pub fn z_pass(src: &[u8], name: &[u8], out: &mut [u8], st: &mut [usize], whole: bool) -> () {
st[(W) as usize] = 0;
st[(ERR) as usize] = 0;
@@ -3432,11 +3796,13 @@ pub fn z_pass(src: &[u8], name: &[u8], out: &mut [u8], st: &mut [usize], whole:
if whole {
z_header(st, out, name);
}
+ st[(Z_USEPOS) as usize] = st[(W) as usize];
st[(P) as usize] = skip_ws(src, 0);
while (st[(P) as usize] < src.len()) {
z_item(src, st, out);
}
if whole {
+ z_put_uses(st, out);
z_report(st, out);
}
}
@@ -3496,6 +3862,27 @@ pub fn to_t27(src: &[u8], name: &[u8], out: &mut [u8], st: &mut [usize]) -> usiz
return z_passes(src, name, out, st, true);
}
+pub fn z_ext_add(ext: &mut [u8], w: usize, rel: &[u8], text: &[u8]) -> usize {
+ let mut n: usize = w;
+ ext[(n) as usize] = Z_B_REC;
+ n = (n + 1);
+ let mut k: usize = 0;
+ while (k < rel.len()) {
+ ext[(n) as usize] = rel[(k) as usize];
+ n = (n + 1);
+ k = (k + 1);
+ }
+ ext[(n) as usize] = B_NL;
+ n = (n + 1);
+ k = 0;
+ while (k < text.len()) {
+ ext[(n) as usize] = text[(k) as usize];
+ n = (n + 1);
+ k = (k + 1);
+ }
+ return n;
+}
+
pub const AT: usize = 3;
pub const B_AMP: u8 = 38;
@@ -3624,10 +4011,20 @@ pub const L_UNARY: usize = 13;
pub const L_XOR: usize = 7;
+pub const NFN: usize = 10;
+
pub const NHI: usize = 5;
pub const NLO: usize = 4;
+pub const NOK: usize = 11;
+
+pub const NSTUB: usize = 20;
+
+pub const NTEST: usize = 13;
+
+pub const NTS: usize = 12;
+
pub const P: usize = 0;
pub const W: usize = 1;
@@ -3989,6 +4386,18 @@ pub fn reserved(src: &[u8], a: usize, b: usize) -> bool {
return ((((((((((((((((((((((((((word_is(src, a, b, b"and") || word_is(src, a, b, b"or")) || word_is(src, a, b, b"test")) || word_is(src, a, b, b"var")) || word_is(src, a, b, b"error")) || word_is(src, a, b, b"null")) || word_is(src, a, b, b"undefined")) || word_is(src, a, b, b"switch")) || word_is(src, a, b, b"orelse")) || word_is(src, a, b, b"try")) || word_is(src, a, b, b"defer")) || word_is(src, a, b, b"comptime")) || word_is(src, a, b, b"module")) || word_is(src, a, b, b"invariant")) || word_is(src, a, b, b"bench")) || word_is(src, a, b, b"catch")) || word_is(src, a, b, b"unreachable")) || word_is(src, a, b, b"anytype")) || word_is(src, a, b, b"opaque")) || word_is(src, a, b, b"packed")) || word_is(src, a, b, b"export")) || word_is(src, a, b, b"inline")) || word_is(src, a, b, b"align")) || word_is(src, a, b, b"noreturn")) || word_is(src, a, b, b"errdefer")) || word_is(src, a, b, b"spec")) || word_is(src, a, b, b"void"));
}
+pub fn reverse(out: &mut [u8], a: usize, b: usize) -> () {
+ let mut i: usize = a;
+ let mut j: usize = b;
+ while (j > (i + 1)) {
+ j = (j - 1);
+ let t: u8 = out[(i) as usize];
+ out[(i) as usize] = out[(j) as usize];
+ out[(j) as usize] = t;
+ i = (i + 1);
+ }
+}
+
pub fn same_at(src: &[u8], q: usize, e: usize, a: usize) -> bool {
let mut k: usize = 0;
while ((q + k) < e) {
diff --git a/specs/tools/t27o/ledger.t27 b/specs/tools/t27o/ledger.t27
index db1bf7667c..278cabadd9 100644
--- a/specs/tools/t27o/ledger.t27
+++ b/specs/tools/t27o/ledger.t27
@@ -97,6 +97,37 @@ pub const T27B_FRONT_END : i32 = 3;
pub const T27B_DISAGREE : i32 = 4;
pub const T27B_CODEGEN_LIMIT : i32 = 5;
+; --- Which front end reads a file, and what `--check` and `--oracle` mean for a Zig file (#10823) ----------
+; By its extension: a .zig file goes to zig_convert.t27, any other file to rust_convert.t27 (a netlist is
+; spice_convert.t27's, and `tri t27o` sends it there before it asks). `tri t27o` and `tri t27o-sweep` both ask
+; front_end, so the two cannot disagree about a file.
+; A Rust file is judged twice: by its translated tests and by an oracle, the original compiled by rustc and run on
+; sampled inputs. A Zig file has no such harness: its own tests ARE the oracle, translated into the spec, and
+; `t27b test` runs them (judged as above, t27b_outcome and needs_reference). So `--oracle` has nothing to run for a
+; Zig file, and `--check` has evidence only when at least one test of the file converted: a spec with none passes
+; `t27b test` as 0 of 0, and a pass that ran nothing is no verdict (#10497; oracle_outcome with nothing sampled is
+; ORC_SKIPPED, never ORC_PASS). EXIT_UNJUDGED is outside t27b's table (0 .. 5), so no verdict of t27b is mistaken for it.
+
+pub const FE_RUST : u32 = 0;
+pub const FE_ZIG : u32 = 1;
+pub const EXIT_UNJUDGED : i32 = 6;
+pub const NOTE_ZIG_ORACLE : str = "t27o: --oracle does not apply to a .zig file: its own tests are the oracle, and --check runs them on the spec";
+pub const NOTE_ZIG_UNJUDGED : str = "t27o: no test of this .zig file converted, so nothing judges the spec; a spec that ran no test is not a pass";
+
+; The front end of a path, by its last four bytes: ".zig" is the Zig one, everything else the Rust one.
+pub fn front_end(path: []const u8) -> u32 {
+ if (path.len < 4) { return FE_RUST; }
+ if (path[path.len - 4] == 46 and path[path.len - 3] == 122 and path[path.len - 2] == 105 and path[path.len - 1] == 103) { return FE_ZIG; }
+ return FE_RUST;
+}
+
+; Does `--check` have anything to judge the spec by? A Rust file always has its oracle; a Zig file has the tests that
+; converted and nothing else.
+pub fn has_evidence(is_zig: bool, tests_converted: usize) -> bool {
+ if (is_zig == false) { return true; }
+ return tests_converted > 0;
+}
+
; --- Decisions -------------------------------------------------------------------------------
; The oracle outcome of one `t27b test` run of a converted spec, from its exit code. A construct
@@ -221,6 +252,9 @@ pub const SWEEP_HERE : str = ".";
; swept repository), and what a missing one is told to do.
pub const SEAL_CONVERTER : str = ".trinity/seals/t27o_T27oRust.json";
pub const SEAL_STD : str = ".trinity/seals/t27o_T27oRustStd.json";
+; A .zig row is also made with zig_convert.t27, so its converter key is the Zig seal's spec_hash joined to the Rust one's
+; (zig_convert.t27 uses rust_convert.t27's helpers): a change to either converter makes every Zig row stale (#10823).
+pub const SEAL_ZIG : str = ".trinity/seals/t27o_T27oZig.json";
pub const SEAL_HINT : str = "run from a t27 checkout";
; seen == 0 has no share: unknown, one above 100.0 percent, never a number inside the scale.
pub const COVERAGE_UNKNOWN : usize = 1001;
@@ -233,11 +267,11 @@ pub fn reuse_row(state: u32) -> bool {
return state == K_FRESH;
}
-; Is this tracked path one the sweep converts: a .rs file with no gen/ or target/ directory above it
-; (generated Rust is gen-rust of a .t27 spec, build output is neither).
+; Is this tracked path one the sweep converts: a .rs or a .zig file (#10823) with no gen/ or target/ directory above it
+; (generated Rust is gen-rust of a .t27 spec, build output is neither, and a generator's Zig sits under gen/ too).
pub fn sweep_path(path: string) -> bool {
if (path.len < 3) { return false; }
- if (span_is(path, path.len - 3, path.len, ".rs") == false) { return false; }
+ if (span_is(path, path.len - 3, path.len, ".rs") == false and front_end(path) != FE_ZIG) { return false; }
var from : usize = 0;
var k : usize = 0;
while (k < path.len) {
@@ -319,7 +353,9 @@ pub fn reason_from(line: string) -> usize {
}
; The kind of a refusal is the reason's words before the first backtick (the quoted text that follows
-; them differs from one refusal to the next). A line with no reason is its own kind, whole.
+; them differs from one refusal to the next) or the first semicolon: a row of the sweep's cache separates its
+; kinds with ';', and the Zig front end's "generated; convert its source spec instead" was cut in two by it and
+; counted as the second half (#10823). A line with no reason is its own kind, whole.
pub fn kind_from(line: string) -> usize {
if (reason_from(line) == line.len) { return 0; }
return reason_from(line);
@@ -328,7 +364,7 @@ pub fn kind_from(line: string) -> usize {
pub fn kind_to(line: string) -> usize {
if (reason_from(line) == line.len) { return line.len; }
var k : usize = reason_from(line);
- while (k < line.len and line[k] != 96) { k = k + 1; }
+ while (k < line.len and line[k] != 96 and line[k] != 59) { k = k + 1; }
if (k > reason_from(line) and line[k - 1] == 32) { return k - 1; }
return k;
}
@@ -635,6 +671,91 @@ test the_seals_are_read_from_the_checkout_and_a_missing_one_says_so {
assert(span_is(SEAL_STD, 0, SEAL_STD.len, ".trinity/seals/t27o_T27oRustStd.json"));
assert(starts_at(SEAL_CONVERTER, 0, ".trinity/seals/"));
assert(starts_at(SEAL_STD, 0, ".trinity/seals/"));
+ assert(span_is(SEAL_ZIG, 0, SEAL_ZIG.len, ".trinity/seals/t27o_T27oZig.json"));
+ assert(starts_at(SEAL_ZIG, 0, ".trinity/seals/"));
+ assert(SEAL_ZIG.len != SEAL_CONVERTER.len);
assert(span_is(SEAL_HINT, 0, SEAL_HINT.len, "run from a t27 checkout"));
assert(SEAL_CONVERTER.len != SEAL_STD.len);
}
+
+; --- Tests: the front end of a file, and `--check` / `--oracle` of a Zig file (#10823) -----------------
+
+test a_file_ending_in_dot_zig_goes_to_the_zig_front_end_and_any_other_to_the_rust_one {
+ assert(front_end("a.zig") == FE_ZIG);
+ assert(front_end("src/x/y.zig") == FE_ZIG);
+ assert(front_end("/srv/checkouts/trinity/src/vsa/ops.zig") == FE_ZIG);
+ assert(front_end("a.rs") == FE_RUST);
+ assert(front_end("cli/tri/src/main.rs") == FE_RUST);
+ assert(FE_ZIG != FE_RUST);
+}
+
+test negative_control_a_name_that_only_contains_zig_is_not_a_zig_file {
+ assert(front_end("") == FE_RUST);
+ assert(front_end("zig") == FE_RUST);
+ assert(front_end(".zi") == FE_RUST);
+ assert(front_end("a.zig.rs") == FE_RUST);
+ assert(front_end("a.zigg") == FE_RUST);
+ assert(front_end("azig") == FE_RUST);
+ assert(front_end("a.ZIG") == FE_RUST);
+ assert(front_end("a.cir") == FE_RUST);
+ assert(front_end("zig/a.rs") == FE_RUST);
+}
+
+test a_zig_file_is_judged_by_the_tests_that_converted_and_a_rust_file_by_its_oracle {
+ assert(has_evidence(true, 1));
+ assert(has_evidence(true, 600));
+ assert(has_evidence(false, 0));
+ assert(has_evidence(false, 3));
+}
+
+test negative_control_a_zig_spec_with_no_converted_test_has_nothing_to_judge_it_by {
+ assert(has_evidence(true, 0) == false);
+ assert(t27b_outcome(T27B_PASS) == ORC_PASS);
+ assert(EXIT_UNJUDGED > T27B_CODEGEN_LIMIT);
+ assert(t27b_outcome(EXIT_UNJUDGED) == ORC_UNKNOWN);
+ assert(needs_reference(t27b_outcome(EXIT_UNJUDGED)));
+}
+
+test the_notes_of_a_zig_file_say_what_does_not_apply_and_what_ran_nothing {
+ assert(starts_at(NOTE_ZIG_ORACLE, 0, "t27o: --oracle does not apply to a .zig file"));
+ assert(starts_at(NOTE_ZIG_UNJUDGED, 0, "t27o: no test of this .zig file converted"));
+ assert(NOTE_ZIG_ORACLE.len > 0);
+ assert(NOTE_ZIG_UNJUDGED.len > 0);
+}
+
+test the_sweep_takes_zig_files_beside_rust_ones {
+ assert(sweep_path("src/vsa/ops.zig"));
+ assert(sweep_path("crates/trios-x/src/lib.zig"));
+ assert(sweep_path("build.zig"));
+ assert(sweep_path("a.zig"));
+ assert(sweep_path("src/targets/x.zig"));
+ assert(sweep_path("src/generator/x.zig"));
+ assert(sweep_path("src/main.rs"));
+}
+
+test negative_control_a_generated_or_target_zig_path_and_a_near_miss_are_not_swept {
+ assert(sweep_path("gen/zig/x.zig") == false);
+ assert(sweep_path("deploy/trinity-nexus/tools/src/gen/batch_gen.zig") == false);
+ assert(sweep_path("target/x.zig") == false);
+ assert(sweep_path("a/b/target/c.zig") == false);
+ assert(sweep_path("main.zig.bak") == false);
+ assert(sweep_path("zig") == false);
+ assert(sweep_path("x.zi") == false);
+ assert(sweep_path("x.zig/y.txt") == false);
+}
+
+test a_refusal_kind_stops_at_a_semicolon_because_the_cache_row_separates_kinds_with_one {
+ const g : string = "// t27o: refused file (line 1): generated; convert its source spec instead";
+ assert(is_refusal(g));
+ assert(span_is(g, kind_from(g), kind_to(g), "generated"));
+ const h : string = "// t27o: refused fn f (line 3): pointer `*` at line 3; 2 fn inside";
+ assert(span_is(h, kind_from(h), kind_to(h), "pointer"));
+}
+
+test negative_control_a_kind_with_no_semicolon_or_backtick_is_still_the_whole_reason {
+ const k : string = "// t27o: refused fn f (line 3): name table full";
+ assert(span_is(k, kind_from(k), kind_to(k), "name table full"));
+ const c : string = "// t27o: refused fn f (line 3): uses refused `g` at line 4; 1 fn inside";
+ assert(span_is(c, kind_from(c), kind_to(c), "uses refused"));
+ assert(is_cascade("uses refused"));
+}
diff --git a/specs/tools/t27o/zig_convert.t27 b/specs/tools/t27o/zig_convert.t27
index 8c673a0eff..2980813d9d 100644
--- a/specs/tools/t27o/zig_convert.t27
+++ b/specs/tools/t27o/zig_convert.t27
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// specs/tools/t27o/zig_convert.t27 -- t27o (Ouroboros), its Zig front end (#10765, step 1 of #10597, option B of #10522):
// hand-written Zig becomes a t27 spec, judged by the file's own `test` blocks. It sits beside rust_convert.t27 and
-// spice_convert.t27 and is reached by file extension: `tri t27o file.zig` prints the spec and the count line.
+// spice_convert.t27 and is reached by file extension (ledger.t27 front_end): `tri t27o file.zig` prints the spec and the count line.
// --
// The contract is the Rust front end's: an item converts exactly or is refused with its reason, never approximated. A
// refused item is a comment where it stood, `// t27o: refused fn NAME (line N): `` at line M`, and the last
@@ -20,6 +20,10 @@
// `const B: f64 = std.math.pi * 2.0;`), and of an array literal (`const T = [_]u8{ 1, 2, 3 };` is
// `const T : [3]u8 = [1, 2, 3];`); `test "name" { .. }`. `const std = @import("std");` and `const math = std.math;` leave
// no trace: the table knows them as namespaces (std, math, mem, testing, ascii) and `math.pi`, `std.math.pi` mean the same.
+// - Consts of another file (#10823): `pub const C = @import("x.zig").C;` where x.zig is a file of this one's own directory tree
+// and its `pub const C` is a scalar literal is written as that const, before the file is read (`imports` names the files the
+// glue reads, `inline_imports` writes the values; see the section "consts imported from another file"). Any other import
+// stays external: a use of its name is refused ("uses external").
// - Containers: the fns and consts of a `struct`, `enum` or `union` are read one by one and named `Container_name`
// (`Optimizer.bitLength(n)` and a bare `bitLength(n)` inside it are `Optimizer_bitLength(n)`), as the Rust front end names
// a method `Type_method`. A container that holds only fns and consts is a namespace and leaves no comment; one with a
@@ -36,6 +40,12 @@
// `@floor` `@ceil` `@round` `@exp` `@log` `@cos` `@abs` `@min` `@max` `@divTrunc` `@rem` `@mod`, and std.math.pi / e / tau / phi
// / sqrt2 / ln2 ..., maxInt / minInt (written as the literal), sqrt / floor / ceil / exp / cos (the builtin of the same
// name), isNan / isPositiveInf / isNegativeInf / inf / nan, std.mem.eql(u8, a, b) and std.debug.assert(c) (an `assert(c)`).
+// - std.math.pow(f64, x, y) (#10823) is `std_math_pow_f64(x, y)` of zig_std.t27, which the spec `use`s (the line follows the
+// header, when a fn or test that stayed in the output calls it): Zig's own algorithm (Go's math.Pow: the significand of x
+// squared, the exponent counted apart, exp(yf * log x) for the fraction, one ldexp), step for step, equal to Zig's bits on
+// 433 recorded vectors under t27b and t27c. Plain repeated multiplication is not: it differs on 69 of the 191 integer powers among them.
+// Any other type (`pow(f32, ..)`, the old two-operand `pow(x, y)`) is refused as "pow of a type other than f64", and a call in
+// a file-level const as "pow in a file-level const" (t27b cannot evaluate a call there; Zig does it at compile time).
// - Tests: `try std.testing.expectEqual(e, a)` is `assert(a == e)`, `expect(c)` is `assert(c)`, `expectApproxEqAbs(e, a, t)`
// is `assert(@abs(a - e) <= t)` (Zig also passes two equal infinities; this does not), `expectApproxEqRel(e, a, t)` is
// `assert(@abs(a - e) <= @max(@abs(a), @abs(e)) * t)`, `expectEqualStrings(e, a)` and `expectEqualSlices(u8, e, a)` are
@@ -58,13 +68,13 @@
// literal (Zig narrows the result type), a float `@rem` / `@mod` / `@divTrunc`, a literal operand of `@exp` `@floor`
// `@ceil` `@round` `@cos` (Zig types it from the result location), a builtin whose operand is not a literal inside a
// file-level const, and an `@intCast` that is a shift count. `@truncate` `@bitCast` `@sin` `@log2` `@Vector` and the like have no
-// t27b routine and are refused by name, as are `std.math.pow` / log / clamp / maxInt of a non-integer, `std.mem.startsWith`
-// and the rest of std: "std call `std.math.pow`".
+// t27b routine and are refused by name, as are `std.math.log` / clamp / maxInt of a non-integer, `std.mem.startsWith`
+// and the rest of std: "std call `std.math.log`".
// --
// Refused, with the kind a sweep ranks them by: pointers and `.*`, optionals and `.?` / orelse, error unions / try / catch /
// error values, types other than the scalars above (structs, enums, unions as values, u128, arbitrary-width ints), comptime and
// anytype, payload captures, labels, defer, unreachable, anonymous literals, export / extern / inline fns, mutable
-// file-level vars, a const that is another file's, names nobody declares, bare braces as a statement. Step 2 of #10597
+// file-level vars, a const that is another file's and no scalar literal of its own tree, names nobody declares, bare braces as a statement. Step 2 of #10597
// reads same-file structs / enums and `*T` self methods; step 3 error unions.
// --
// Three t27c behaviours shaped this spec: `use` splices by NAME (every word outside a `//` comment, string literals
@@ -105,25 +115,31 @@ use tools::t27o::rust_convert::reserved;
use tools::t27o::rust_convert::is_upper;
use tools::t27o::rust_convert::is_open;
use tools::t27o::rust_convert::is_close;
+use tools::t27o::rust_convert::reverse;
// ---------------------------------------------------------------- state
/// Slots 0 .. 6 are rust_convert's (its put, newline and refuse read them): P the reader's position, W how much
/// is written, ERR the refusal, AT where it was found, NLO and NHI the source text it names, IND the indent.
/// They are used here by their names and not declared again.
-pub const Z_NFN : usize = 8;
-pub const Z_NOK : usize = 9;
-pub const Z_NTS : usize = 10;
-pub const Z_NTEST : usize = 11;
-pub const Z_CLS : usize = 12;
-pub const Z_STMT : usize = 13;
+/// The five counters (fn seen, converted, tests seen, tests converted, stubs) sit where rust_convert's report reads
+/// them (NFN, NOK, NTS, NTEST, NSTUB): `tri t27o-sweep` reads one set of slots for either front end (#10823). No fn is
+/// kept as a stub here, so NSTUB stays 0.
+pub const Z_NFN : usize = NFN;
+pub const Z_NOK : usize = NOK;
+pub const Z_NTS : usize = NTS;
+pub const Z_NTEST : usize = NTEST;
+pub const Z_CLS : usize = 8;
+pub const Z_STMT : usize = 9;
pub const Z_TMP : usize = 14;
pub const Z_INTEST : usize = 15;
pub const Z_NNAMES : usize = 16;
pub const Z_NFILE : usize = 17;
pub const Z_ROUND : usize = 18;
pub const Z_RET : usize = 19;
-pub const Z_GREW : usize = 20;
+pub const Z_GREW : usize = 100;
+/// Where the `use` lines of the output go: just after the header.
+pub const Z_USEPOS : usize = 101;
pub const Z_HIT : usize = 21;
pub const Z_NARGS : usize = 22;
pub const Z_ARG0 : usize = 23;
@@ -149,8 +165,6 @@ pub const Z_NAME_SLOTS : usize = 5;
pub const Z_B_AT : u8 = 64;
pub const Z_B_TILDE : u8 = 126;
pub const Z_B_P : u8 = 112;
-pub const Z_B_I : u8 = 105;
-pub const Z_B_G : u8 = 103;
// ---------------------------------------------------------------- tokens
@@ -241,6 +255,8 @@ pub const Z_R_FULL : usize = 30;
pub const Z_R_ITEM : usize = 31;
pub const Z_R_BOPERAND : usize = 32;
pub const Z_R_HOIST : usize = 33;
+pub const Z_R_POW : usize = 34;
+pub const Z_R_POWCONST : usize = 35;
/// The reason of a refusal code, in words: the kind a sweep ranks refusals by (rust_convert's reasons read the same way).
pub fn z_put_why(st: []usize, out: []u8, code: usize) -> void {
@@ -276,6 +292,8 @@ pub fn z_put_why(st: []usize, out: []u8, code: usize) -> void {
if (code == Z_R_ITEM) { puts(st, out, "declaration"); return; }
if (code == Z_R_BOPERAND) { puts(st, out, "builtin operand t27b cannot run"); return; }
if (code == Z_R_HOIST) { puts(st, out, "array literal outside a statement"); return; }
+ if (code == Z_R_POW) { puts(st, out, "pow of a type other than f64"); return; }
+ if (code == Z_R_POWCONST) { puts(st, out, "pow in a file-level const"); return; }
puts(st, out, "syntax");
}
@@ -1018,6 +1036,23 @@ pub fn z_std_member(src: []const u8, st: []usize, out: []u8, a0: usize, ns: usiz
z_want(src, st, ")");
return L_ATOM;
}
+ if (word_is(src, ma, mb, "pow")) {
+ if (st[Z_INCONST] == 1) {
+ refuse(st, Z_R_POWCONST, a0, a0, mb);
+ return L_ATOM;
+ }
+ z_want(src, st, "(");
+ if (!z_take(src, st, "f64")) {
+ refuse(st, Z_R_POW, a0, a0, mb);
+ return L_ATOM;
+ }
+ z_want(src, st, ",");
+ puts(st, out, "std_math_pow_f64(");
+ z_args_rest(src, st, out);
+ if (st[Z_NARGS] != 2) { refuse(st, Z_R_SYNTAX, a0, a0, mb); }
+ st[Z_CLS] = ZC_F64;
+ return L_ATOM;
+ }
if (word_is(src, ma, mb, "maxInt") or word_is(src, ma, mb, "minInt")) {
z_want(src, st, "(");
const ta : usize = st[P];
@@ -2872,15 +2907,275 @@ pub fn z_item(src: []const u8, st: []usize, out: []u8) -> void {
st[P] = skip_ws(src, end);
}
-// ---------------------------------------------------------------- the file
+// ---------------------------------------------------------------- consts imported from another file (#10823)
+// `pub const C = @import("x.zig").C;` makes C another file's: the converter alone knows nothing of x.zig, so every use
+// of C is refused ("uses external"). When x.zig is a file of this file's own directory tree and its `pub const C` is a
+// scalar literal, the value is written in place of the import, before the file is read: `pub const C: u32 = 5;`.
+// Two fns, both pure, and the glue between them (it alone reads files): `imports` lists the paths to read, once each;
+// the glue reads them and passes the bundle on, one record per file it could read, `Z_B_REC path \n text`;
+// `inline_imports` finds each record by its path. A line is never added or taken: a declaration spread over several
+// lines is left as it is, and so is anything that is not a literal. What is left stays refused with its reason:
+// "uses external `C`".
+// Allowed: a path of the form `a.zig` or `dir/a.zig` (also `./a.zig`), no `..`, no leading `/`, no `\`, no `:`: the
+// directory tree of the file that imports, never above it. Values: an integer, a float, `true`, `false`, or a string
+// with no escape, of at most Z_LIT_MAX bytes, under a scalar type or none. A const of any other type, an expression, a
+// const that is not `pub` (Zig itself refuses it through @import), a fn or a type is not resolved.
+
+/// Starts each record of the bundle `inline_imports` reads: this byte, the path, a newline, the file's text. A file that
+/// holds this byte is not resolved from.
+pub const Z_B_REC : u8 = 1;
+/// The longest literal written in: with it, the output is never more than 4 times the source and 64 bytes.
+pub const Z_LIT_MAX : usize = 64;
+
+/// The slots of one import declaration, in the state vector the glue passes (from 8: slot 1 is W, where the output is
+/// counted): the name, the type written in the importing file (0 when none), the path without its quotes, the member, the
+/// `;` that ends it; then, once the imported file is read, its type and its literal.
+pub const ZI_NA : usize = 8;
+pub const ZI_NB : usize = 9;
+pub const ZI_TA : usize = 10;
+pub const ZI_TB : usize = 11;
+pub const ZI_PA : usize = 12;
+pub const ZI_PB : usize = 13;
+pub const ZI_MA : usize = 14;
+pub const ZI_MB : usize = 15;
+pub const ZI_SEMI : usize = 16;
+pub const ZI_XA : usize = 17;
+pub const ZI_XB : usize = 18;
+pub const ZI_LA : usize = 19;
+pub const ZI_LB : usize = 20;
+/// The state vector `imports` and `inline_imports` need holds at least this many slots.
+pub const ZI_SLOTS : usize = 21;
+
+/// Is src[a .. b] a path inside the directory tree of the file that imports it: ends in .zig, relative, no `..`
+/// component, no backslash, no colon, no control byte?
+pub fn z_import_path_ok(src: []const u8, a: usize, b: usize) -> bool {
+ if (b < a + 5 or b > src.len) { return false; }
+ if (!word_is(src, b - 4, b, ".zig")) { return false; }
+ if (src[a] == B_SLASH) { return false; }
+ var comp : usize = a;
+ var k : usize = a;
+ while (k < b) {
+ const c : u8 = src[k];
+ if (c == B_BACKSLASH or c == B_COLON or c < B_SPACE or c == B_DEL) { return false; }
+ if (c == B_SLASH) {
+ if (k - comp == 2 and src[comp] == B_DOT and src[comp + 1] == B_DOT) { return false; }
+ comp = k + 1;
+ }
+ k = k + 1;
+ }
+ return true;
+}
+
+/// The end of the scalar literal at buf[p]: a number (a minus sign before it allowed), `true`, `false`, or a string with no
+/// escape and no newline, of at most Z_LIT_MAX bytes. p itself when there is none.
+pub fn z_lit_end(buf: []const u8, p: usize) -> usize {
+ var q : usize = p;
+ if (head(buf, q) == B_MINUS) { q = q + 1; }
+ const e : usize = z_tok_end(buf, q);
+ if (e <= q or e > buf.len or e - p > Z_LIT_MAX) { return p; }
+ if (is_digit(head(buf, q))) { return e; }
+ if (q != p) { return p; }
+ if (word_is(buf, q, e, "true") or word_is(buf, q, e, "false")) { return e; }
+ if (head(buf, q) != B_QUOTE or e < q + 2 or buf[e - 1] != B_QUOTE) { return p; }
+ var k : usize = q + 1;
+ while (k < e - 1) {
+ if (buf[k] == B_BACKSLASH or buf[k] == B_NL) { return p; }
+ k = k + 1;
+ }
+ return e;
+}
+
+/// Does the item starting at src[p] have the form `[pub] const NAME [: scalar] = @import("path.zig").MEMBER;` with a path
+/// z_import_path_ok allows? Its slots are written in ps (ZI_NA .. ZI_SEMI).
+pub fn z_import_const(src: []const u8, p: usize, ps: []usize) -> bool {
+ var q : usize = p;
+ if (z_is(src, q, "pub")) { q = skip_ws(src, z_tok_end(src, q)); }
+ if (!z_is(src, q, "const")) { return false; }
+ const na : usize = skip_ws(src, z_tok_end(src, q));
+ const nb : usize = z_tok_end(src, na);
+ if (!is_alpha(head(src, na))) { return false; }
+ ps[ZI_NA] = na;
+ ps[ZI_NB] = nb;
+ ps[ZI_TA] = 0;
+ ps[ZI_TB] = 0;
+ var t : usize = skip_ws(src, nb);
+ if (z_is(src, t, ":")) {
+ const ta : usize = skip_ws(src, z_tok_end(src, t));
+ const tb : usize = z_tok_end(src, ta);
+ if (!z_scalar(src, ta, tb)) { return false; }
+ ps[ZI_TA] = ta;
+ ps[ZI_TB] = tb;
+ t = skip_ws(src, tb);
+ }
+ if (!z_is(src, t, "=")) { return false; }
+ const i : usize = skip_ws(src, z_tok_end(src, t));
+ if (!z_is(src, i, "@import")) { return false; }
+ const o : usize = skip_ws(src, z_tok_end(src, i));
+ if (!z_is(src, o, "(")) { return false; }
+ const s : usize = skip_ws(src, z_tok_end(src, o));
+ const sb : usize = z_tok_end(src, s);
+ if (head(src, s) != B_QUOTE or sb < s + 3 or head(src, sb - 1) != B_QUOTE) { return false; }
+ if (!z_import_path_ok(src, s + 1, sb - 1)) { return false; }
+ const c : usize = skip_ws(src, sb);
+ if (!z_is(src, c, ")")) { return false; }
+ const d : usize = skip_ws(src, z_tok_end(src, c));
+ if (!z_is(src, d, ".")) { return false; }
+ const m : usize = skip_ws(src, z_tok_end(src, d));
+ const mb : usize = z_tok_end(src, m);
+ if (!is_alpha(head(src, m))) { return false; }
+ const semi : usize = skip_ws(src, mb);
+ if (head(src, semi) != B_SEMI) { return false; }
+ ps[ZI_PA] = s + 1;
+ ps[ZI_PB] = sb - 1;
+ ps[ZI_MA] = m;
+ ps[ZI_MB] = mb;
+ ps[ZI_SEMI] = semi;
+ return true;
+}
+
+/// The value of the const the declaration named by ps imports, read from ext[nb ..] (the text after the const's name in the
+/// imported file): `[: scalar] = literal;`. Its type and its literal are written in ps (ZI_XA .. ZI_LB).
+pub fn z_ext_value(ext: []const u8, nb: usize, ps: []usize) -> bool {
+ ps[ZI_XA] = 0;
+ ps[ZI_XB] = 0;
+ var t : usize = skip_ws(ext, nb);
+ if (z_is(ext, t, ":")) {
+ const ta : usize = skip_ws(ext, z_tok_end(ext, t));
+ const tb : usize = z_tok_end(ext, ta);
+ if (!z_scalar(ext, ta, tb)) { return false; }
+ ps[ZI_XA] = ta;
+ ps[ZI_XB] = tb;
+ t = skip_ws(ext, tb);
+ }
+ if (!z_is(ext, t, "=")) { return false; }
+ const la : usize = skip_ws(ext, z_tok_end(ext, t));
+ const le : usize = z_lit_end(ext, la);
+ if (le == la or head(ext, skip_ws(ext, le)) != B_SEMI) { return false; }
+ ps[ZI_LA] = la;
+ ps[ZI_LB] = le;
+ return true;
+}
+
+/// Is there, in the file ext[lo .. hi), a file-level `pub const MEMBER` whose value is a scalar literal? MEMBER is
+/// src[ps[ZI_MA] .. ps[ZI_MB]]. An item that runs past hi belongs to a broken file: no answer.
+pub fn z_ext_const(ext: []const u8, lo: usize, hi: usize, src: []const u8, ps: []usize) -> bool {
+ var p : usize = skip_ws(ext, lo);
+ while (p < hi) {
+ var end : usize = z_item_end(ext, p);
+ if (end <= p) { end = p + 1; }
+ if (end > hi) { return false; }
+ var q : usize = p;
+ if (z_is(ext, q, "pub")) {
+ q = skip_ws(ext, z_tok_end(ext, q));
+ if (z_is(ext, q, "const")) {
+ const na : usize = skip_ws(ext, z_tok_end(ext, q));
+ const nb : usize = z_tok_end(ext, na);
+ if (word_is(ext, na, nb, src[ps[ZI_MA] .. ps[ZI_MB]])) { return z_ext_value(ext, nb, ps); }
+ }
+ }
+ p = skip_ws(ext, end);
+ }
+ return false;
+}
+
+/// Where the text of the file that starts at ext[from] ends: at the next Z_B_REC, or at the end of the bundle.
+pub fn z_seg_end(ext: []const u8, from: usize) -> usize {
+ var k : usize = from;
+ while (k < ext.len and ext[k] != Z_B_REC) { k = k + 1; }
+ return k;
+}
+
+/// Where the text of the file imported as src[a .. b] starts in the bundle: after its record's header. ext.len when the
+/// bundle has no record of that path.
+pub fn z_rec_text(ext: []const u8, src: []const u8, a: usize, b: usize) -> usize {
+ const n : usize = b - a;
+ var k : usize = 0;
+ while (k + n + 1 < ext.len) {
+ if (ext[k] == Z_B_REC and ext[k + 1 + n] == B_NL and word_is(ext, k + 1, k + 1 + n, src[a .. b])) { return k + n + 2; }
+ k = k + 1;
+ }
+ return ext.len;
+}
+
+/// Is the path src[a .. b] a line of the list out[0 .. w) already?
+pub fn z_listed(out: []const u8, w: usize, src: []const u8, a: usize, b: usize) -> bool {
+ const n : usize = b - a;
+ var k : usize = 0;
+ while (k + n < w and k + n < out.len) {
+ if ((k == 0 or out[k - 1] == B_NL) and out[k + n] == B_NL and word_is(out, k, k + n, src[a .. b])) { return true; }
+ k = k + 1;
+ }
+ return false;
+}
+
+/// Is there no line break in src[a .. b)?
+pub fn z_one_line(src: []const u8, a: usize, b: usize) -> bool {
+ var k : usize = a;
+ while (k < b and k < src.len) {
+ if (src[k] == B_NL or src[k] == B_CR) { return false; }
+ k = k + 1;
+ }
+ return true;
+}
+
+/// The paths `inline_imports` will want, one per line, each once, in the order they are first declared: the glue reads each
+/// and passes the texts on as records (Z_B_REC, the path, a newline, the text). The result is the size of the list; it is
+/// above out.len when the buffer was too small (a list is never longer than src).
+pub fn imports(src: []const u8, out: []u8, st: []usize) -> usize {
+ if (st.len < ZI_SLOTS) { return 0; }
+ st[W] = 0;
+ var p : usize = skip_ws(src, 0);
+ while (p < src.len) {
+ var end : usize = z_item_end(src, p);
+ if (end <= p) { end = p + 1; }
+ if (z_import_const(src, p, st) and !z_listed(out, st[W], src, st[ZI_PA], st[ZI_PB])) {
+ put_src(src, st, out, st[ZI_PA], st[ZI_PB]);
+ put(st, out, B_NL);
+ }
+ p = skip_ws(src, end);
+ }
+ return st[W];
+}
-/// Does a file name end in .zig? `tri t27o` sends such a file here.
-pub fn is_zig_name(name: []const u8) -> bool {
- if (name.len < 4) { return false; }
- const f : usize = name.len - 4;
- return name[f] == B_DOT and name[f + 1] == B_LOWER_Z and name[f + 2] == Z_B_I and name[f + 3] == Z_B_G;
+/// src with each import of a scalar literal written as the const it is: `pub const C = @import("x.zig").C;` and `pub
+/// const C: u32 = 5;` in x.zig make `pub const C: u32 = 5;`; the type written in the importing file wins over the
+/// imported one. ext holds the files `imports` listed, as records (see Z_B_REC). The result is the size of
+/// the output, above out.len when the buffer was too small (4 times src.len and 64 always suffice, see Z_LIT_MAX).
+pub fn inline_imports(src: []const u8, ext: []const u8, out: []u8, st: []usize) -> usize {
+ if (st.len < ZI_SLOTS) { return 0; }
+ st[W] = 0;
+ var done : usize = 0;
+ var p : usize = skip_ws(src, 0);
+ while (p < src.len) {
+ var end : usize = z_item_end(src, p);
+ if (end <= p) { end = p + 1; }
+ if (z_import_const(src, p, st)) {
+ const lo : usize = z_rec_text(ext, src, st[ZI_PA], st[ZI_PB]);
+ if (lo < ext.len and z_ext_const(ext, lo, z_seg_end(ext, lo), src, st) and z_one_line(src, st[ZI_NB], st[ZI_SEMI])) {
+ put_src(src, st, out, done, st[ZI_NB]);
+ if (st[ZI_TA] != 0) {
+ puts(st, out, ": ");
+ put_src(src, st, out, st[ZI_TA], st[ZI_TB]);
+ puts(st, out, " = ");
+ } else if (st[ZI_XA] != 0) {
+ puts(st, out, ": ");
+ put_src(ext, st, out, st[ZI_XA], st[ZI_XB]);
+ puts(st, out, " = ");
+ } else {
+ puts(st, out, " = ");
+ }
+ put_src(ext, st, out, st[ZI_LA], st[ZI_LB]);
+ done = st[ZI_SEMI];
+ }
+ }
+ p = skip_ws(src, end);
+ }
+ put_src(src, st, out, done, src.len);
+ return st[W];
}
+// ---------------------------------------------------------------- the file
+
/// Is the text s at src[i], whatever the case?
pub fn z_ci_at(src: []const u8, i: usize, s: []const u8) -> bool {
if (i + s.len > src.len) { return false; }
@@ -2947,6 +3242,31 @@ pub fn z_report(st: []usize, out: []u8) -> void {
puts(st, out, "%\n");
}
+/// Does out[a .. b) hold the text s?
+pub fn z_out_mentions(out: []const u8, a: usize, b: usize, s: []const u8) -> bool {
+ var j : usize = a;
+ while (j + s.len <= b) {
+ if (z_out_has(out, j, s)) { return true; }
+ j = j + 1;
+ }
+ return false;
+}
+
+/// The `use` lines of the output, moved to just after the header: zig_std.t27's std_math_pow_f64 when a fn or test that
+/// stayed in the output calls it (a refused fn's text was cut off, so a call there does not count). The output being too
+/// small to read, the line is counted all the same, so the size asked for is never short.
+pub fn z_put_uses(st: []usize, out: []u8) -> void {
+ const from : usize = st[Z_USEPOS];
+ const w0 : usize = st[W];
+ if (w0 <= out.len and !z_out_mentions(out, from, w0, "std_math_pow_f64(")) { return; }
+ puts(st, out, "use tools::t27o::zig_std::std_math_pow_f64;\n\n");
+ if (st[W] <= out.len) {
+ reverse(out, from, w0);
+ reverse(out, w0, st[W]);
+ reverse(out, from, st[W]);
+ }
+}
+
/// One pass over the items: the output starts over, the name table keeps its refusals.
pub fn z_pass(src: []const u8, name: []const u8, out: []u8, st: []usize, whole: bool) -> void {
st[W] = 0;
@@ -2975,9 +3295,13 @@ pub fn z_pass(src: []const u8, name: []const u8, out: []u8, st: []usize, whole:
}
}
if (whole) { z_header(st, out, name); }
+ st[Z_USEPOS] = st[W];
st[P] = skip_ws(src, 0);
while (st[P] < src.len) { z_item(src, st, out); }
- if (whole) { z_report(st, out); }
+ if (whole) {
+ z_put_uses(st, out);
+ z_report(st, out);
+ }
}
/// Passes until no fn or const is newly refused: the first learns the classes of the file's names, the next ones
@@ -3119,7 +3443,7 @@ test std_calls_with_a_measured_t27_form_and_the_rest_refused_by_name {
var out : [1280]u8 = undefined;
var st : [2048]usize = [0] ** 2048;
const n : usize = z_body_text("const std = @import(\"std\");\nconst math = std.math;\nconst mem = std.mem;\nfn consts() f64 {\n return std.math.pi + math.e + math.tau + math.phi;\n}\nfn limits() i64 {\n return std.math.maxInt(u32) + math.minInt(i8) + std.math.maxInt(i64);\n}\nfn same(a: []const u8, b: []const u8) bool {\n return mem.eql(u8, a, b);\n}\nfn root(x: f64) f64 {\n return math.sqrt(x) + math.floor(x) + std.math.cos(x);\n}\nfn special() bool {\n return std.math.isNan(std.math.nan(f64)) or std.math.isPositiveInf(std.math.inf(f32));\n}\nfn power(x: f64) f64 {\n return std.math.pow(f64, x, 2.0);\n}\nfn prefix(a: []const u8, b: []const u8) bool {\n return mem.startsWith(u8, a, b);\n}\nfn other(a: []const u16, b: []const u16) bool {\n return std.mem.eql(u16, a, b);\n}\nfn out() void {\n std.debug.print(\"x\", .{});\n}\nfn lit_root() f64 {\n return math.floor(2.5);\n}\n", &out, &st);
- assert(out_is(n, &out, 0, "fn consts() -> f64 {\n return std.math.pi + std.math.e + 6.283185307179586 + 1.618033988749895;\n}\n\nfn limits() -> i64 {\n return 4294967295 + -128 + 9223372036854775807;\n}\n\nfn same(a: []const u8, b: []const u8) -> bool {\n return std.mem.eql(u8, a, b);\n}\n\nfn root(x: f64) -> f64 {\n return @sqrt(x) + @floor(x) + @cos(x);\n}\n\nfn special() -> bool {\n return std.math.isNan(std.math.nan(f64)) or std.math.isPositiveInf(std.math.inf(f32));\n}\n\n// t27o: refused fn power (line 19): std call `std.math.pow` at line 20\n\n// t27o: refused fn prefix (line 22): std call `mem.startsWith` at line 23\n\n// t27o: refused fn other (line 25): std call `std.mem.eql` at line 26\n\n// t27o: refused fn out (line 28): std call `std.debug.print` at line 29\n\n// t27o: refused fn lit_root (line 31): builtin operand t27b cannot run `math.floor(2.5)` at line 32\n\n"));
+ assert(out_is(n, &out, 0, "fn consts() -> f64 {\n return std.math.pi + std.math.e + 6.283185307179586 + 1.618033988749895;\n}\n\nfn limits() -> i64 {\n return 4294967295 + -128 + 9223372036854775807;\n}\n\nfn same(a: []const u8, b: []const u8) -> bool {\n return std.mem.eql(u8, a, b);\n}\n\nfn root(x: f64) -> f64 {\n return @sqrt(x) + @floor(x) + @cos(x);\n}\n\nfn special() -> bool {\n return std.math.isNan(std.math.nan(f64)) or std.math.isPositiveInf(std.math.inf(f32));\n}\n\nfn power(x: f64) -> f64 {\n return std_math_pow_f64(x, 2.0);\n}\n\n// t27o: refused fn prefix (line 22): std call `mem.startsWith` at line 23\n\n// t27o: refused fn other (line 25): std call `std.mem.eql` at line 26\n\n// t27o: refused fn out (line 28): std call `std.debug.print` at line 29\n\n// t27o: refused fn lit_root (line 31): builtin operand t27b cannot run `math.floor(2.5)` at line 32\n\n"));
}
test test_blocks_become_tests_and_the_expectations_asserts {
@@ -3286,15 +3610,6 @@ test the_tokenizer_reads_zig_operators_whole {
assert(z_tok_end("\\\\line", 0) == 1);
}
-test a_file_name_ending_in_dot_zig_is_a_zig_file {
- assert(is_zig_name("a.zig"));
- assert(is_zig_name("src/x/y.zig"));
- assert(!is_zig_name("a.zig.rs"));
- assert(!is_zig_name("zig"));
- assert(!is_zig_name("a.rs"));
- assert(!is_zig_name("a.cir"));
-}
-
test a_generator_mark_in_the_first_20_lines_marks_the_file {
assert(z_generated("// Generated from specs/x.tri\nfn f() void {}\n"));
assert(z_generated("// DO NOT EDIT\n"));
@@ -3375,3 +3690,240 @@ test a_source_with_crlf_lines_reads_like_one_with_lf {
const n : usize = z_body_text(src[0..w], &out, &st);
assert(out_is(n, &out, 0, "fn f(x: u32) -> u32 {\n return x;\n}\n\ntest f {\n assert(f(1) == 1);\n}\n\n"));
}
+
+test the_counters_sit_where_rust_converts_report_reads_them_and_no_fn_is_a_stub {
+ var out : [512]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const n : usize = z_body_text("const std = @import(\"std\");\nfn ok(x: u32) u32 {\n return x + 1;\n}\nfn bad(p: *u32) u32 {\n return p.*;\n}\ntest \"good\" {\n try std.testing.expect(ok(1) == 2);\n}\ntest \"calls bad\" {\n try std.testing.expect(bad(1) == 2);\n}\n", &out, &st);
+ assert(n > 0);
+ assert(st[NFN] == 2);
+ assert(st[NOK] == 1);
+ assert(st[NTS] == 2);
+ assert(st[NTEST] == 1);
+ assert(st[NSTUB] == 0);
+ assert(Z_NFN == NFN);
+ assert(Z_NTEST == NTEST);
+}
+
+test negative_control_the_five_counters_are_five_different_slots_and_none_is_the_class_slot {
+ var st : [128]usize = [0] ** 128;
+ st[NFN] = 1;
+ st[NOK] = 2;
+ st[NTS] = 3;
+ st[NTEST] = 4;
+ st[NSTUB] = 5;
+ st[Z_CLS] = 6;
+ st[Z_STMT] = 7;
+ st[Z_GREW] = 8;
+ st[Z_USEPOS] = 9;
+ assert(st[NFN] == 1);
+ assert(st[NOK] == 2);
+ assert(st[NTS] == 3);
+ assert(st[NTEST] == 4);
+ assert(st[NSTUB] == 5);
+ assert(st[Z_CLS] == 6);
+ assert(st[Z_STMT] == 7);
+ assert(st[Z_GREW] == 8);
+ assert(st[Z_USEPOS] == 9);
+}
+
+// ---------------------------------------------------------------- tests: consts imported from another file (#10823)
+
+/// Test helper: the record of one imported file, Z_B_REC, the file's name, a newline, the text, appended to ext at w; the new w.
+pub fn z_ext_add(ext: []u8, w: usize, rel: []const u8, text: []const u8) -> usize {
+ var n : usize = w;
+ ext[n] = Z_B_REC;
+ n = n + 1;
+ var k : usize = 0;
+ while (k < rel.len) {
+ ext[n] = rel[k];
+ n = n + 1;
+ k = k + 1;
+ }
+ ext[n] = B_NL;
+ n = n + 1;
+ k = 0;
+ while (k < text.len) {
+ ext[n] = text[k];
+ n = n + 1;
+ k = k + 1;
+ }
+ return n;
+}
+
+test imports_lists_each_path_once_in_the_order_it_is_first_imported_as_a_member {
+ var st : [64]usize = [0] ** 64;
+ var out : [128]u8 = undefined;
+ const n : usize = imports("const std = @import(\"std\");\nconst x = @import(\"x.zig\");\npub const A = @import(\"gen_common.zig\").A;\nconst B: u32 = @import(\"./d/c.zig\").B;\nconst T = @import(\"x.zig\").T;\npub const C = @import(\"gen_common.zig\").C;\nfn f() u32 {\n return 1;\n}\n", &out, &st);
+ assert(out_is(n, &out, 0, "gen_common.zig\n./d/c.zig\nx.zig\n"));
+}
+
+test negative_control_a_path_above_the_tree_or_not_a_zig_file_or_not_a_member_is_not_listed {
+ var st : [64]usize = [0] ** 64;
+ var out : [128]u8 = undefined;
+ const n : usize = imports("const a = @import(\"../up.zig\").A;\nconst b = @import(\"/abs/p.zig\").B;\nconst c = @import(\"d/../e.zig\").C;\nconst d = @import(\"readme.txt\").D;\nconst e = @import(\"std\").E;\nconst f = @import(\"x.zig\").F.G;\nvar g = @import(\"y.zig\").G;\nexport const h = @import(\"z.zig\").H;\nconst i = @import(\"a\\b.zig\").I;\nconst j = @import(\"c:d.zig\").J;\nconst k: Foo = @import(\"k.zig\").K;\nconst l = @import(\".zig\").L;\n", &out, &st);
+ assert(n == 0);
+}
+
+test an_imported_scalar_literal_is_written_in_place_of_the_import {
+ var st : [64]usize = [0] ** 64;
+ var ext : [512]u8 = undefined;
+ var w : usize = z_ext_add(&ext, 0, "a.zig", "pub const SIZE: usize = 32;\npub const NEG: i32 = -1;\npub const RATIO = 1.585;\n");
+ w = z_ext_add(&ext, w, "d/b.zig", "pub const ON: bool = true;\npub const NAME = \"tri\";\n");
+ var out : [512]u8 = undefined;
+ const n : usize = inline_imports("pub const SIZE = @import(\"a.zig\").SIZE;\nconst N: i64 = @import(\"a.zig\").NEG;\npub const RATIO = @import(\"a.zig\").RATIO;\npub const ON = @import(\"d/b.zig\").ON;\nconst NAME = @import(\"d/b.zig\").NAME;\n", ext[0 .. w], &out, &st);
+ assert(out_is(n, &out, 0, "pub const SIZE: usize = 32;\nconst N: i64 = -1;\npub const RATIO = 1.585;\npub const ON: bool = true;\nconst NAME = \"tri\";\n"));
+}
+
+test negative_control_what_is_not_a_scalar_literal_of_a_pub_const_is_left_as_it_was {
+ var st : [64]usize = [0] ** 64;
+ var ext : [1024]u8 = undefined;
+ const theirs : []const u8 = "pub const T = struct { x: u32 };\npub fn f() u32 { return 1; }\nconst PRIV: u32 = 7;\npub const EXPR = 2 * 3;\npub const TY: Trit = -1;\npub const TEXT = \"a\\nb\";\npub const LONG = 1234567890123456789012345678901234567890123456789012345678901234567890;\npub const REF = other.X;\npub const ARR = [_]u8{ 1, 2 };\npub const NEG = -x;\npub const HEXEXPR = 0xFF - 1;\n";
+ var w : usize = z_ext_add(&ext, 0, "a.zig", theirs);
+ var out : [1024]u8 = undefined;
+ const src : []const u8 = "const A = @import(\"a.zig\").T;\nconst B = @import(\"a.zig\").f;\nconst C = @import(\"a.zig\").PRIV;\nconst D = @import(\"a.zig\").EXPR;\nconst E = @import(\"a.zig\").TY;\nconst F = @import(\"a.zig\").TEXT;\nconst G = @import(\"a.zig\").LONG;\nconst H = @import(\"a.zig\").REF;\nconst I = @import(\"a.zig\").ARR;\nconst J = @import(\"a.zig\").NEG;\nconst K = @import(\"a.zig\").HEXEXPR;\nconst L = @import(\"a.zig\").MISSING;\nconst M = @import(\"gone.zig\").M;\n";
+ const n : usize = inline_imports(src, ext[0 .. w], &out, &st);
+ assert(out_is(n, &out, 0, src));
+}
+
+test a_declaration_over_several_lines_or_a_bundle_with_no_record_is_left_as_it_was {
+ var st : [64]usize = [0] ** 64;
+ var ext : [128]u8 = undefined;
+ var w : usize = z_ext_add(&ext, 0, "a.zig", "pub const SIZE: usize = 32;\n");
+ var out : [256]u8 = undefined;
+ const spread : []const u8 = "pub const SIZE =\n @import(\"a.zig\").SIZE;\n";
+ const n : usize = inline_imports(spread, ext[0 .. w], &out, &st);
+ assert(out_is(n, &out, 0, spread));
+ const one : []const u8 = "pub const SIZE = @import(\"a.zig\").SIZE;\n";
+ const m : usize = inline_imports(one, ext[0 .. 0], &out, &st);
+ assert(out_is(m, &out, 0, one));
+ const k : usize = inline_imports(one, ext[0 .. w], &out, &st);
+ assert(out_is(k, &out, 0, "pub const SIZE: usize = 32;\n"));
+}
+
+test an_imported_const_is_found_by_its_name_among_the_items_of_its_file_and_not_inside_one {
+ var st : [64]usize = [0] ** 64;
+ var ext : [512]u8 = undefined;
+ var w : usize = z_ext_add(&ext, 0, "a.zig", "const std = @import(\"std\");\nfn local() u32 {\n const SIZE: u32 = 1;\n return SIZE;\n}\ntest \"t\" {\n const SIZE: u32 = 2;\n _ = SIZE;\n}\npub const SIZE: u32 = 3;\n");
+ var out : [128]u8 = undefined;
+ const n : usize = inline_imports("const SIZE = @import(\"a.zig\").SIZE;\n", ext[0 .. w], &out, &st);
+ assert(out_is(n, &out, 0, "const SIZE: u32 = 3;\n"));
+}
+
+test a_missing_record_in_the_middle_does_not_shift_the_next_import_and_the_line_count_never_changes {
+ var st : [64]usize = [0] ** 64;
+ var ext : [256]u8 = undefined;
+ var w : usize = z_ext_add(&ext, 0, "b.zig", "pub const B: u8 = 2;\n");
+ w = z_ext_add(&ext, w, "c.zig", "pub const C: u8 = 3;\n");
+ var out : [256]u8 = undefined;
+ const n : usize = inline_imports("const A = @import(\"a.zig\").A;\nconst B = @import(\"b.zig\").B;\n\n// kept\nconst C = @import(\"c.zig\").C;\n", ext[0 .. w], &out, &st);
+ assert(out_is(n, &out, 0, "const A = @import(\"a.zig\").A;\nconst B: u8 = 2;\n\n// kept\nconst C: u8 = 3;\n"));
+}
+
+test the_imported_value_makes_a_fn_that_used_it_convert_and_without_it_the_fn_stays_refused {
+ var ext : [256]u8 = undefined;
+ var w : usize = z_ext_add(&ext, 0, "gen_common.zig", "pub const SIMD_WIDTH: usize = 32;\n");
+ const src : []const u8 = "pub const SIMD_WIDTH = @import(\"gen_common.zig\").SIMD_WIDTH;\npub fn lanes(n: usize) usize {\n return n / SIMD_WIDTH;\n}\n";
+ var flat : [512]u8 = undefined;
+ var ist : [64]usize = [0] ** 64;
+ const m : usize = inline_imports(src, ext[0 .. w], &flat, &ist);
+ var out : [512]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const n : usize = z_body_text(flat[0 .. m], &out, &st);
+ assert(out_is(n, &out, 0, "pub const SIMD_WIDTH : usize = 32;\n\npub fn lanes(n: usize) -> usize {\n return n / SIMD_WIDTH;\n}\n\n"));
+ assert(st[NOK] == 1);
+ var out2 : [512]u8 = undefined;
+ var st2 : [2048]usize = [0] ** 2048;
+ const n2 : usize = z_body_text(src, &out2, &st2);
+ assert(out_is(n2, &out2, 0, "// t27o: refused fn lanes (line 2): uses external `SIMD_WIDTH` at line 3\n\n"));
+ assert(st2[NOK] == 0);
+}
+
+test the_output_is_never_more_than_four_times_the_source_and_64_bytes {
+ var st : [64]usize = [0] ** 64;
+ var text : [128]u8 = undefined;
+ var k : usize = 0;
+ while (k < 64) {
+ text[k] = 49;
+ k = k + 1;
+ }
+ var theirs : [128]u8 = undefined;
+ var t : usize = 0;
+ const head_text : []const u8 = "pub const B: usize = ";
+ while (t < head_text.len) {
+ theirs[t] = head_text[t];
+ t = t + 1;
+ }
+ var j : usize = 0;
+ while (j < 64) {
+ theirs[t + j] = 49;
+ j = j + 1;
+ }
+ theirs[t + 64] = 59;
+ var ext : [256]u8 = undefined;
+ const w : usize = z_ext_add(&ext, 0, "a.zig", theirs[0 .. t + 65]);
+ const src : []const u8 = "const A=@import(\"a.zig\").B;";
+ var out : [512]u8 = undefined;
+ const n : usize = inline_imports(src, ext[0 .. w], &out, &st);
+ assert(n <= 4 * src.len + 64);
+ assert(n == 82);
+}
+
+test negative_control_a_short_state_vector_gives_nothing_and_a_short_buffer_is_told_by_the_size {
+ var short : [8]usize = [0] ** 8;
+ var out : [64]u8 = undefined;
+ assert(imports("const A = @import(\"a.zig\").A;\n", &out, &short) == 0);
+ assert(inline_imports("const A = @import(\"a.zig\").A;\n", "", &out, &short) == 0);
+ var st : [64]usize = [0] ** 64;
+ var tiny : [4]u8 = undefined;
+ assert(imports("const A = @import(\"a.zig\").A;\n", &tiny, &st) == 6);
+ assert(inline_imports("const A = @import(\"a.zig\").A;\n", "", &tiny, &st) == 30);
+}
+
+// ---------------------------------------------------------------- tests: std.math.pow (#10823)
+
+test std_math_pow_of_an_f64_is_a_call_of_zig_std_and_the_spec_uses_it {
+ var out : [1024]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const n : usize = to_t27("const std = @import(\"std\");\nconst PHI = 1.618033988749895;\npub fn phi_n(n: f64) f64 {\n return std.math.pow(f64, PHI, n) * 2;\n}\npub fn gamma_8() f64 {\n return std.math.pow(f64, 0.2360679774997897, 8);\n}\ntest \"phi_n\" {\n try std.testing.expectApproxEqAbs(@as(f64, 2.0), phi_n(0.0), 0.0001);\n}\n", "demo", &out, &st);
+ assert(out_is(n, &out, 0, "// SPDX-License-Identifier: Apache-2.0\n; demo.t27 -- converted from Zig by t27o (Ouroboros), specs/tools/t27o/zig_convert.t27; read it before it lands.\n; ASCII only (L3)\n\nmodule demo;\n\nuse tools::t27o::zig_std::std_math_pow_f64;\n\nconst PHI = 1.618033988749895;\n\npub fn phi_n(n: f64) -> f64 {\n return std_math_pow_f64(PHI, n) * 2;\n}\n\npub fn gamma_8() -> f64 {\n return std_math_pow_f64(0.2360679774997897, 8);\n}\n\ntest phi_n {\n assert(@abs(phi_n(0.0) - @as(f64, 2.0)) <= 0.0001);\n}\n\n// t27o: 2 fn seen, 2 converted (1 of 1 tests), 0 refused (0 kept as stubs); coverage 100%\n"));
+}
+
+test negative_control_a_file_that_never_calls_pow_or_only_in_a_refused_fn_has_no_use_line {
+ var out : [1024]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const a : usize = to_t27("fn f(x: u32) u32 {\n return x + 1;\n}\n", "demo", &out, &st);
+ assert(!z_out_mentions(&out, 0, a, "use "));
+ var out2 : [1024]u8 = undefined;
+ var st2 : [2048]usize = [0] ** 2048;
+ const b : usize = to_t27("const std = @import(\"std\");\nfn g(x: f64, p: *u8) f64 {\n return std.math.pow(f64, x, 2.0) + p.*;\n}\n", "demo", &out2, &st2);
+ assert(!z_out_mentions(&out2, 0, b, "use "));
+ assert(!z_out_mentions(&out2, 0, b, "std_math_pow_f64("));
+ assert(z_out_mentions(&out2, 0, b, "refused fn g (line 2): pointer"));
+}
+
+test negative_control_pow_of_another_type_or_the_old_two_operand_form_is_refused_as_its_own_kind {
+ var out : [1024]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const n : usize = z_body_text("const std = @import(\"std\");\nfn single(x: f32) f32 {\n return std.math.pow(f32, x, 2.0);\n}\nfn old(x: f64) f64 {\n return std.math.pow(x, 1.5);\n}\nfn wide(n: u32) u32 {\n return std.math.pow(u32, n, 2);\n}\nfn arity(x: f64) f64 {\n return std.math.pow(f64, x);\n}\nfn user(x: f64) f64 {\n return std.math.log(f64, 2.0, x);\n}\n", &out, &st);
+ assert(out_is(n, &out, 0, "// t27o: refused fn single (line 2): pow of a type other than f64 `std.math.pow` at line 3\n\n// t27o: refused fn old (line 5): pow of a type other than f64 `std.math.pow` at line 6\n\n// t27o: refused fn wide (line 8): pow of a type other than f64 `std.math.pow` at line 9\n\n// t27o: refused fn arity (line 11): syntax `std.math.pow` at line 12\n\n// t27o: refused fn user (line 14): std call `std.math.log` at line 15\n\n"));
+}
+
+test a_pow_call_is_an_f64_so_it_meets_f64_operands_and_a_too_small_buffer_is_told_the_size_with_the_use_line {
+ var out : [1024]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const src : []const u8 = "const std = @import(\"std\");\npub fn f(x: f64) bool {\n return std.math.pow(f64, x, 2.0) > 1.0;\n}\n";
+ const n : usize = to_t27(src, "d", &out, &st);
+ assert(z_out_mentions(&out, 0, n, "use tools::t27o::zig_std::std_math_pow_f64;\n\npub fn f(x: f64) -> bool {\n return std_math_pow_f64(x, 2.0) > 1.0;\n}"));
+ var tiny : [64]u8 = undefined;
+ var st2 : [2048]usize = [0] ** 2048;
+ const m : usize = to_t27(src, "d", &tiny, &st2);
+ assert(m == n);
+}
+
+test negative_control_pow_in_a_file_level_const_is_refused_and_so_is_what_uses_it {
+ var out : [1024]u8 = undefined;
+ var st : [2048]usize = [0] ** 2048;
+ const n : usize = z_body_text("const std = @import(\"std\");\nconst PI = 3.14159;\npub const TAU4: f64 = 36.0 * std.math.pow(f64, PI, 4.0);\npub fn tau() f64 {\n return TAU4;\n}\npub fn local() f64 {\n const q = std.math.pow(f64, PI, 4.0);\n return q;\n}\n", &out, &st);
+ assert(out_is(n, &out, 0, "const PI = 3.14159;\n\n// t27o: refused const TAU4 (line 3): pow in a file-level const `std.math.pow` at line 3\n\n// t27o: refused fn tau (line 4): uses refused `TAU4` at line 5\n\npub fn local() -> f64 {\n const q = std_math_pow_f64(PI, 4.0);\n return q;\n}\n\n"));
+}
diff --git a/specs/tools/t27o/zig_std.t27 b/specs/tools/t27o/zig_std.t27
new file mode 100644
index 0000000000..bdbc7e13a5
--- /dev/null
+++ b/specs/tools/t27o/zig_std.t27
@@ -0,0 +1,953 @@
+// SPDX-License-Identifier: Apache-2.0
+; specs/tools/t27o/zig_std.t27 -- the t27 behind the Zig front end's std table (#10823): what a converted .zig spec `use`s
+; where Zig's std has no t27 builtin that means the same. It sits beside zig_convert.t27 as rust_std.t27 sits beside
+; rust_convert.t27; zig_convert.t27 writes a call of an entry here and a `use` line, and `t27b test` runs the file's own
+; tests against it.
+; --
+; std.math.pow(f64, x, y) (std_math_pow_f64). Zig 0.16's std/math/pow.zig is a port of Go's math.Pow, not libm's pow: the
+; integer part of y is taken by squaring the significand of x (frexp) and counting the exponent apart, the fractional part
+; is exp(yf * log(x)), and the result is scaled once at the end. So an integer power by plain repeated multiplication is
+; NOT Zig's result (the negative control below finds vectors where it differs in the last bits). This is that algorithm,
+; step for step, in operations t27b and t27c both have:
+; - `@exp` and `@log` of a run-time f64 are the routines Zig's compiler_rt has (t27b runs ports of them, specs/tri/t27b/
+; libm.t27, bit for bit; t27c writes Zig's own builtin); `@sqrt` is the IEEE square root; `@floor` of a non-negative f64
+; is Zig's `@trunc` there.
+; - `math.frexp` is an exact function of its operand (read off the bits here). `math.ldexp` (`scalbn`) is Zig's own
+; integer code, ported as it is: its rounding of a subnormal result is NOT the IEEE tie rule in every case (see
+; zs_ldexp), so an exact power-of-two product (musl's scalbn) is not Zig's result, and the recorded vectors include the
+; case that shows it.
+; The vectors below were recorded with Zig 0.16.0 (zig run, Debug, no libc): for each pair (x, y) the program in the
+; comment above `ZS_POW_VEC` printed the bits of x, of y and of `std.math.pow(f64, x, y)`. A result the test compares is
+; the bits, except a NaN, which has to be a NaN.
+; ASCII only (L3)
+; phi^2 + 1/phi^2 = 3 | TRINITY
+
+module T27oZigStd;
+
+// `@clz` of a u64, by a loop.
+pub fn zs_clz64(v: u64) -> i32 {
+ var n : i32 = 0;
+ var b : u64 = 0x8000000000000000;
+ while (b != 0 and (v & b) == 0) {
+ n = n + 1;
+ b = b >> 1;
+ }
+ return n;
+}
+
+// math.ldexp of an f64 (std/math/ldexp.zig, which math.scalbn is): x * 2^n on the bits. A subnormal result is rounded to
+// nearest on the shifted-out bit, and an exact tie is cleared to even only when `@ctz(repr) == shift - 1` -- a test on
+// the whole representation, exponent bits included. For a significand of 0.5 (all fraction bits zero) the exponent
+// field's own trailing zeros make that false, so 0.5 * 2^-1074 = 2^-1075, a tie, becomes 2^-1074 and not 0, where musl's
+// scalbn gives 0. Zig's result is the one a converted file saw, so this is Zig's code, not the IEEE rule: `@ctz(repr) ==
+// shift - 1` is written as `(repr & low) == half` (the low `shift` bits are 1 then zeros), as specs/tri/t27b/libm.t27 does.
+pub fn zs_ldexp(x: f64, n: i32) -> f64 {
+ const repr : u64 = @bitCast(x);
+ const sign : u64 = repr & 0x8000000000000000;
+ if (x != x or (repr & 0x7FF0000000000000) == 0x7FF0000000000000) {
+ return x;
+ }
+ var exponent : i32 = @intCast((repr & 0x7FFFFFFFFFFFFFFF) >> 52);
+ if (exponent == 0) {
+ exponent = exponent + 11 - zs_clz64((repr & 0x7FFFFFFFFFFFFFFF) << 1);
+ }
+ if (n >= 0) {
+ if (n > 2046 - exponent) {
+ return @bitCast(0x7FF0000000000000 | sign);
+ }
+ if (exponent + n <= 0) {
+ return @bitCast(((repr & 0x7FFFFFFFFFFFFFFF) << n) | sign);
+ }
+ if (exponent <= 0) {
+ const ne : u64 = @intCast(n + exponent);
+ const frac : u64 = ((repr & 0x7FFFFFFFFFFFFFFF) << (1 - exponent)) & 0x000FFFFFFFFFFFFF;
+ return @bitCast((ne << 52) | frac | sign);
+ }
+ const nu : u64 = @intCast(n);
+ return @bitCast(repr + (nu << 52));
+ }
+ if (n <= 0 - exponent) {
+ if (n < 0 - (52 + exponent)) {
+ return @bitCast(sign);
+ }
+ var s : i32 = 0 - n;
+ if (1 - (exponent + n) < s) {
+ s = 1 - (exponent + n);
+ }
+ const shift : u64 = @intCast(s);
+ const low : u64 = 0xFFFFFFFFFFFFFFFF >> (64 - shift);
+ const half : u64 = low ^ (low >> 1);
+ var result : u64 = repr & 0x000FFFFFFFFFFFFF;
+ if (exponent > 0) {
+ result = result | 0x0010000000000000;
+ }
+ result = result >> (shift - 1);
+ result = (result + 1) >> 1;
+ if ((repr & low) == half) {
+ result = result & 0xFFFFFFFFFFFFFFFE;
+ }
+ return @bitCast(result | sign);
+ }
+ const nn : u64 = @intCast(0 - n);
+ return @bitCast(repr - (nn << 52));
+}
+
+// math.frexp of a finite x that is not zero: x = significand * 2^exponent, |significand| in [0.5, 1). A subnormal is scaled
+// by 2^54 first (exact), so its exponent field is that of a normal number.
+pub fn zs_frexp_exp(x: f64) -> i32 {
+ const u : u64 = @bitCast(x);
+ const e : i32 = @intCast((u >> 52) & 0x7FF);
+ if (e == 0) {
+ const v : u64 = @bitCast(x * 18014398509481984.0);
+ const e2 : i32 = @intCast((v >> 52) & 0x7FF);
+ return e2 - 1022 - 54;
+ }
+ return e - 1022;
+}
+
+pub fn zs_frexp_sig(x: f64) -> f64 {
+ var u : u64 = @bitCast(x);
+ if (((u >> 52) & 0x7FF) == 0) {
+ u = @bitCast(x * 18014398509481984.0);
+ }
+ return @bitCast((u & 0x800FFFFFFFFFFFFF) | 0x3FE0000000000000);
+}
+
+// pow.zig `isOddInteger`: |x| >= 2^53 is even; else x has no fraction and an odd integer part.
+pub fn zs_is_odd_integer(x: f64) -> bool {
+ const a : f64 = @abs(x);
+ if (a >= 9007199254740992.0) {
+ return false;
+ }
+ const ip : f64 = @floor(a);
+ const i : i64 = @intFromFloat(ip);
+ return a - ip == 0.0 and (i & 1) == 1;
+}
+
+// The sign bit of x: 1 for -0.0 and the negatives, 0 for +0.0 and the positives.
+pub fn zs_sign(x: f64) -> u64 {
+ const u : u64 = @bitCast(x);
+ return u >> 63;
+}
+
+// std.math.pow(f64, x, y), Zig 0.16 std/math/pow.zig.
+pub fn std_math_pow_f64(x: f64, y: f64) -> f64 {
+ const inf : f64 = std.math.inf(f64);
+ if (y == 0.0 or x == 1.0) {
+ return 1.0;
+ }
+ if (x != x or y != y) {
+ return std.math.nan(f64);
+ }
+ if (y == 1.0) {
+ return x;
+ }
+ if (x == 0.0) {
+ if (y < 0.0) {
+ if (zs_is_odd_integer(y)) {
+ if (zs_sign(x) == 1) {
+ return -inf;
+ }
+ return inf;
+ }
+ return inf;
+ }
+ if (zs_is_odd_integer(y)) {
+ return x;
+ }
+ return 0.0;
+ }
+ if (y == inf or y == -inf) {
+ if (x == -1.0) {
+ return 1.0;
+ }
+ if ((@abs(x) < 1.0) == (y == inf)) {
+ return 0.0;
+ }
+ return inf;
+ }
+ if (x == inf or x == -inf) {
+ if (x == -inf) {
+ return std_math_pow_f64(1.0 / x, -y);
+ }
+ if (y < 0.0) {
+ return 0.0;
+ }
+ if (y > 0.0) {
+ return inf;
+ }
+ }
+ if (y == 0.5) {
+ return @sqrt(x);
+ }
+ if (y == -0.5) {
+ return 1.0 / @sqrt(x);
+ }
+ const ay : f64 = @abs(y);
+ var yi : f64 = @floor(ay);
+ var yf : f64 = ay - yi;
+ if (yf != 0.0 and x < 0.0) {
+ return std.math.nan(f64);
+ }
+ if (yi >= 9223372036854775808.0) {
+ return @exp(y * @log(@abs(x)));
+ }
+ var a1 : f64 = 1.0;
+ var ae : i32 = 0;
+ if (yf != 0.0) {
+ if (yf > 0.5) {
+ yf = yf - 1.0;
+ yi = yi + 1.0;
+ }
+ a1 = @exp(yf * @log(x));
+ }
+ var xe : i32 = zs_frexp_exp(x);
+ var x1 : f64 = zs_frexp_sig(x);
+ var i : i64 = @intFromFloat(yi);
+ while (i != 0) {
+ if (xe < -4096 or 4096 < xe) {
+ ae = ae + xe;
+ break;
+ }
+ if ((i & 1) == 1) {
+ a1 = a1 * x1;
+ ae = ae + xe;
+ }
+ x1 = x1 * x1;
+ xe = xe * 2;
+ if (x1 < 0.5) {
+ x1 = x1 + x1;
+ xe = xe - 1;
+ }
+ i = i >> 1;
+ }
+ if (y < 0.0) {
+ a1 = 1.0 / a1;
+ ae = 0 - ae;
+ }
+ return zs_ldexp(a1, ae);
+}
+
+
+// The vectors. Recorded with Zig 0.16.0 (`zig run`, Debug, no libc) by a program that read each (x, y) from a table of
+// bits and printed `{x:0>16}` of the bits of x, of y and of `std.math.pow(f64, x, y)`; the same for `std.math.ldexp(x, n)`
+// (n is stored as n + 4096) and `std.math.frexp(x)` (its exponent is stored as exponent + 2048):
+// const r = std.math.pow(f64, @bitCast(PIN[i]), @bitCast(PIN[i + 1]));
+// std.debug.print("P {x:0>16} {x:0>16} {x:0>16}\n", .{ PIN[i], PIN[i + 1], @as(u64, @bitCast(r)) });
+// What they cover: the constants the corpus raises (phi, pi, e, 3, 10, 2, 1/2, phi^-3) to integers from 0 to 100 and down
+// to -40; fractional exponents (1/phi, tenths, 3.7, -2.7); the special values (+-0, +-1, +-inf, NaN, a negative base) against
+// zero, odd and even integers, a half, an infinity and a NaN; exponents past 2^53 and 2^63; results that overflow, underflow
+// to zero or land in the subnormals; random pairs. A literal that ends in f32 or f64 is a float literal to t27, so those
+// entries are written in decimal.
+const ZS_POW_VEC : [1299]u64 = [
+ 0x3ff9e3779b97f4a8, 0x0000000000000000, 0x3ff0000000000000,
+ 0x3ff9e3779b97f4a8, 0x3ff0000000000000, 0x3ff9e3779b97f4a8,
+ 0x3ff9e3779b97f4a8, 0x4000000000000000, 0x4004f1bbcdcbfa54,
+ 0x3ff9e3779b97f4a8, 0x4008000000000000, 0x4010f1bbcdcbfa54,
+ 0x3ff9e3779b97f4a8, 0x4010000000000000, 0x401b6a99b4b1f77e,
+ 0x3ff9e3779b97f4a8, 0x4014000000000000, 0x40262e2ac13ef8e9,
+ 0x3ff9e3779b97f4a8, 0x4018000000000000, 0x4031f1bbcdcbfa54,
+ 0x3ff9e3779b97f4a8, 0x401c000000000000, 0x403d08d12e6b76c9,
+ 0x3ff9e3779b97f4a8, 0x4020000000000000, 0x40477d467e1bb88e,
+ 0x3ff9e3779b97f4a8, 0x4022000000000000, 0x405300d78aa8b9f9,
+ 0x3ff9e3779b97f4a8, 0x4024000000000000, 0x405ebf7ac9b69640,
+ 0x3ff9e3779b97f4a8, 0x4026000000000000, 0x4068e0292a2fa81d,
+ 0x3ff9e3779b97f4a8, 0x4028000000000000, 0x40741ff34785799e,
+ 0x3ff9e3779b97f4a8, 0x402a000000000000, 0x40804803ee4ea6d6,
+ 0x3ff9e3779b97f4a8, 0x4030000000000000, 0x40a13dffc49c5b88,
+ 0x3ff9e3779b97f4a8, 0x4034000000000000, 0x40cd8b7ffdd57461,
+ 0x3ff9e3779b97f4a8, 0x4038000000000000, 0x40f9501ffff5e2f9,
+ 0x3ff9e3779b97f4a8, 0x403f000000000000, 0x4146f796800002c9,
+ 0x3ff9e3779b97f4a8, 0x4040000000000000, 0x415294afbfffff23,
+ 0x3ff9e3779b97f4a8, 0x4049000000000000, 0x421a35fe5e8bffff,
+ 0x3ff9e3779b97f4a8, 0x404f800000000000, 0x42aaabf7c7b927ff,
+ 0x3ff9e3779b97f4a8, 0x4050000000000000, 0x42b593f12aea7eff,
+ 0x3ff9e3779b97f4a8, 0x4059000000000000, 0x444578187422adc4,
+ 0x3ff9e3779b97f4a8, 0xbff0000000000000, 0x3fe3c6ef372fe94f,
+ 0x3ff9e3779b97f4a8, 0xc000000000000000, 0x3fd8722191a02d61,
+ 0x3ff9e3779b97f4a8, 0xc008000000000000, 0x3fce3779b97f4a7c,
+ 0x3ff9e3779b97f4a8, 0xc014000000000000, 0x3fb715609f7c746c,
+ 0x3ff9e3779b97f4a8, 0xc020000000000000, 0x3f95cc0f223b8f49,
+ 0x3ff9e3779b97f4a8, 0xc02a000000000000, 0x3f5f727536b2bbff,
+ 0x3ff9e3779b97f4a8, 0xc034000000000000, 0x3f11545cf2bbbfa6,
+ 0x3ff9e3779b97f4a8, 0xc044000000000000, 0x3e32c50255dfa06e,
+ 0x400921fb54442d18, 0x0000000000000000, 0x3ff0000000000000,
+ 0x400921fb54442d18, 0x3ff0000000000000, 0x400921fb54442d18,
+ 0x400921fb54442d18, 0x4000000000000000, 0x4023bd3cc9be45de,
+ 0x400921fb54442d18, 0x4008000000000000, 0x403f019b59389d7b,
+ 0x400921fb54442d18, 0x4010000000000000, 0x40585a2e8c290825,
+ 0x400921fb54442d18, 0x4014000000000000, 0x40732050a0fe5033,
+ 0x400921fb54442d18, 0x4018000000000000, 0x408e0b1d11856df6,
+ 0x400921fb54442d18, 0x401c000000000000, 4658860110120189746,
+ 0x400921fb54442d18, 0x4020000000000000, 0x40c28843f855a861,
+ 0x400921fb54442d18, 0x4022000000000000, 0x40dd1c465b7aabb6,
+ 0x400921fb54442d18, 0x4024000000000000, 0x40f6dd00c27647fd,
+ 0x400921fb54442d18, 0x4026000000000000, 0x4111f4f01267bf60,
+ 0x400921fb54442d18, 0x4028000000000000, 0x412c34da5cf0a1b5,
+ 0x400921fb54442d18, 0x402a000000000000, 0x4146273ea2a374bf,
+ 0x400921fb54442d18, 0x4030000000000000, 0x41957721735f29e4,
+ 0x400921fb54442d18, 0x4034000000000000, 0x420055d75de0a95c,
+ 0x400921fb54442d18, 0x4038000000000000, 0x4268dcd56e253c66,
+ 0x400921fb54442d18, 0x403f000000000000, 0x43225547027f5478,
+ 0x400921fb54442d18, 0x4040000000000000, 0x433ccc2ed0b3e4ae,
+ 0x400921fb54442d18, 0x4049000000000000, 0x4517d4e683979e1c,
+ 0x400921fb54442d18, 0x404f800000000000, 0x46707f989906c6d3,
+ 0x400921fb54442d18, 0x4050000000000000, 0x4689ea68c264432b,
+ 0x400921fb54442d18, 0x4059000000000000, 0x4a41bf93d1f611f8,
+ 0x400921fb54442d18, 0xbff0000000000000, 0x3fd45f306dc9c883,
+ 0x400921fb54442d18, 0xc000000000000000, 0x3fb9f02f6222c720,
+ 0x400921fb54442d18, 0xc008000000000000, 0x3fa08345eb45d77f,
+ 0x400921fb54442d18, 0xc014000000000000, 0x3f6ac4ff3f4b8c2b,
+ 0x400921fb54442d18, 0xc020000000000000, 0x3f1ba0a12450c6b5,
+ 0x400921fb54442d18, 0xc02a000000000000, 0x3e971c972729a055,
+ 0x400921fb54442d18, 0xc034000000000000, 0x3ddf57d773267a67,
+ 0x400921fb54442d18, 0xc044000000000000, 0x3bceb32290474356,
+ 0x4008000000000000, 0x4000000000000000, 0x4022000000000000,
+ 0x4008000000000000, 0x4008000000000000, 0x403b000000000000,
+ 0x4008000000000000, 0x4018000000000000, 0x4086c80000000000,
+ 0x4008000000000000, 0x4020000000000000, 0x40b9a10000000000,
+ 0x4008000000000000, 0x402a000000000000, 0x413853d300000000,
+ 0x4008000000000000, 0x4035000000000000, 0x42037be295980000,
+ 0x4008000000000000, 0x4040000000000000, 0x431a553f8878fa04,
+ 0x4008000000000000, 0x4050000000000000, 0x4645ab6a57c7bc99,
+ 0x4008000000000000, 0xbff0000000000000, 0x3fd5555555555555,
+ 0x4008000000000000, 0xc010000000000000, 0x3f8948b0fcd6e9e0,
+ 0x4008000000000000, 0xc022000000000000, 0x3f0aa2f78f1b4cc6,
+ 0x4008000000000000, 0xc03e000000000000, 0x3cf5dfaa697ec6f7,
+ 0x4024000000000000, 0x4000000000000000, 0x4059000000000000,
+ 0x4024000000000000, 0x4008000000000000, 0x408f400000000000,
+ 0x4024000000000000, 0x4018000000000000, 0x412e848000000000,
+ 0x4024000000000000, 0x4020000000000000, 0x4197d78400000000,
+ 0x4024000000000000, 0x402a000000000000, 0x42a2309ce5400000,
+ 0x4024000000000000, 0x4035000000000000, 0x444b1ae4d6e2ef50,
+ 0x4024000000000000, 0x4040000000000000, 0x4693b8b5b5056e17,
+ 0x4024000000000000, 0x4050000000000000, 0x4d384f03e93ff9f6,
+ 0x4024000000000000, 0xbff0000000000000, 0x3fb999999999999a,
+ 0x4024000000000000, 0xc010000000000000, 0x3f1a36e2eb1c432d,
+ 0x4024000000000000, 0xc022000000000000, 0x3e112e0be826d695,
+ 0x4024000000000000, 0xc03e000000000000, 0x39b4484bfeebc29f,
+ 0x4000000000000000, 0x4000000000000000, 0x4010000000000000,
+ 0x4000000000000000, 0x4008000000000000, 0x4020000000000000,
+ 0x4000000000000000, 0x4018000000000000, 0x4050000000000000,
+ 0x4000000000000000, 0x4020000000000000, 0x4070000000000000,
+ 0x4000000000000000, 0x402a000000000000, 0x40c0000000000000,
+ 0x4000000000000000, 0x4035000000000000, 0x4140000000000000,
+ 0x4000000000000000, 0x4040000000000000, 0x41f0000000000000,
+ 0x4000000000000000, 0x4050000000000000, 0x43f0000000000000,
+ 0x4000000000000000, 0xbff0000000000000, 0x3fe0000000000000,
+ 0x4000000000000000, 0xc010000000000000, 0x3fb0000000000000,
+ 0x4000000000000000, 0xc022000000000000, 0x3f60000000000000,
+ 0x4000000000000000, 0xc03e000000000000, 0x3e10000000000000,
+ 0x3fe0000000000000, 0x4000000000000000, 0x3fd0000000000000,
+ 0x3fe0000000000000, 0x4008000000000000, 0x3fc0000000000000,
+ 0x3fe0000000000000, 0x4018000000000000, 0x3f90000000000000,
+ 0x3fe0000000000000, 0x4020000000000000, 0x3f70000000000000,
+ 0x3fe0000000000000, 0x402a000000000000, 0x3f20000000000000,
+ 0x3fe0000000000000, 0x4035000000000000, 0x3ea0000000000000,
+ 0x3fe0000000000000, 0x4040000000000000, 0x3df0000000000000,
+ 0x3fe0000000000000, 0x4050000000000000, 0x3bf0000000000000,
+ 0x3fe0000000000000, 0xbff0000000000000, 0x4000000000000000,
+ 0x3fe0000000000000, 0xc010000000000000, 0x4030000000000000,
+ 0x3fe0000000000000, 0xc022000000000000, 0x4080000000000000,
+ 0x3fe0000000000000, 0xc03e000000000000, 0x41d0000000000000,
+ 0x3fce3779b97f4a7c, 0x4000000000000000, 0x3fac8864680b583e,
+ 0x3fce3779b97f4a7c, 0x4008000000000000, 0x3f8af155173f23d7,
+ 0x3fce3779b97f4a7c, 0x4018000000000000, 0x3f26af46505704d9,
+ 0x3fce3779b97f4a7c, 0x4020000000000000, 0x3ee43a0d9e9f0076,
+ 0x3fce3779b97f4a7c, 0x402a000000000000, 0x3e3e5eab0717e6f2,
+ 0x3fce3779b97f4a7c, 0x4035000000000000, 0x3d333243676b99d0,
+ 0x3fce3779b97f4a7c, 0x4040000000000000, 0x3bc46ea80abc1362,
+ 0x3fce3779b97f4a7c, 0x4050000000000000, 0x379a17a1684eabf4,
+ 0x3fce3779b97f4a7c, 0xbff0000000000000, 0x4010f1bbcdcbfa54,
+ 0x3fce3779b97f4a7c, 0xc010000000000000, 0x40741ff34785799f,
+ 0x3fce3779b97f4a7c, 0xc022000000000000, 0x411ace90000098ce,
+ 0x3fce3779b97f4a7c, 0xc03e000000000000, 0x43d657e46337aa92,
+ 0xbfe3c6ef372fe950, 0x4000000000000000, 0x3fd8722191a02d62,
+ 0xbfe3c6ef372fe950, 0x4008000000000000, 0xbfce3779b97f4a7e,
+ 0xbfe3c6ef372fe950, 0x4018000000000000, 0x3fac8864680b5842,
+ 0xbfe3c6ef372fe950, 0x4020000000000000, 0x3f95cc0f223b8f4b,
+ 0xbfe3c6ef372fe950, 0x402a000000000000, 0xbf5f727536b2bc04,
+ 0xbfe3c6ef372fe950, 0x4035000000000000, 0xbf056ba5766d14d9,
+ 0xbfe3c6ef372fe950, 0x4040000000000000, 0x3e8b8e292f8a88c9,
+ 0xbfe3c6ef372fe950, 0x4050000000000000, 0x3d27ba5d0df4b66b,
+ 0xbfe3c6ef372fe950, 0xbff0000000000000, 0xbff9e3779b97f4a7,
+ 0xbfe3c6ef372fe950, 0xc010000000000000, 0x401b6a99b4b1f77c,
+ 0xbfe3c6ef372fe950, 0xc022000000000000, 0xc05300d78aa8b9f7,
+ 0xbfe3c6ef372fe950, 0xc03e000000000000, 0x413c6391fffff6f0,
+ 0xc000000000000000, 0x4000000000000000, 0x4010000000000000,
+ 0xc000000000000000, 0x4008000000000000, 0xc020000000000000,
+ 0xc000000000000000, 0x4018000000000000, 0x4050000000000000,
+ 0xc000000000000000, 0x4020000000000000, 0x4070000000000000,
+ 0xc000000000000000, 0x402a000000000000, 0xc0c0000000000000,
+ 0xc000000000000000, 0x4035000000000000, 0xc140000000000000,
+ 0xc000000000000000, 0x4040000000000000, 0x41f0000000000000,
+ 0xc000000000000000, 0x4050000000000000, 0x43f0000000000000,
+ 0xc000000000000000, 0xbff0000000000000, 0xbfe0000000000000,
+ 0xc000000000000000, 0xc010000000000000, 0x3fb0000000000000,
+ 0xc000000000000000, 0xc022000000000000, 0xbf60000000000000,
+ 0xc000000000000000, 0xc03e000000000000, 0x3e10000000000000,
+ 0x4005bf0a8b145769, 0x4000000000000000, 0x401d8e64b8d4ddad,
+ 0x4005bf0a8b145769, 0x4008000000000000, 0x403415e5bf6fb105,
+ 0x4005bf0a8b145769, 0x4018000000000000, 0x407936dc5690c08d,
+ 0x4005bf0a8b145769, 0x4020000000000000, 0x40a749ea7d470c6c,
+ 0x4005bf0a8b145769, 0x402a000000000000, 0x411b00b5916ac951,
+ 0x4005bf0a8b145769, 0x4035000000000000, 0x41d3a6e1fd9eecf8,
+ 0x4005bf0a8b145769, 0x4040000000000000, 0x42d1f43fcc4b6626,
+ 0x4005bf0a8b145769, 0x4050000000000000, 0x45b425982cf597bf,
+ 0x4005bf0a8b145769, 0xbff0000000000000, 0x3fd78b56362cef38,
+ 0x4005bf0a8b145769, 0xc010000000000000, 0x3f92c155b8213cf5,
+ 0x4005bf0a8b145769, 0xc022000000000000, 0x3f202cf22526545b,
+ 0x4005bf0a8b145769, 0xc03e000000000000, 0x3d3a56e0c2ac7f7e,
+ 0x3fe0000000000000, 0x3fe3c6ef372fe950, 0x3fe4d990a21abb54,
+ 0x3fe0000000000000, 0x3fb999999999999a, 0x3feddb680117ab12,
+ 0x3fe0000000000000, 0x3fd3333333333333, 0x3fe9fdf8bcce533e,
+ 0x3fe0000000000000, 0x3fe6666666666666, 0x3fe3b2c47bff8329,
+ 0x3fe0000000000000, 0x3ff8000000000000, 0x3fd6a09e667f3bcc,
+ 0x3fe0000000000000, 0x4004000000000000, 0x3fc6a09e667f3bcc,
+ 0x3fe0000000000000, 0xbff8000000000000, 0x4006a09e667f3bcd,
+ 0x3fe0000000000000, 0xc00599999999999a, 0x4019fdf8bcce533f,
+ 0x3fe0000000000000, 0x400d99999999999a, 0x3fb3b2c47bff8328,
+ 0x3fe0000000000000, 0x4024333333333333, 0x3f4ddb680117ab14,
+ 0x4000000000000000, 0x3fe3c6ef372fe950, 0x3ff88e77d62aa7b4,
+ 0x4000000000000000, 0x3fb999999999999a, 0x3ff125fbee250664,
+ 0x4000000000000000, 0x3fd3333333333333, 0x3ff3b2c47bff8329,
+ 0x4000000000000000, 0x3fe6666666666666, 0x3ff9fdf8bcce533d,
+ 0x4000000000000000, 0x3ff8000000000000, 0x4006a09e667f3bcc,
+ 0x4000000000000000, 0x4004000000000000, 0x4016a09e667f3bcc,
+ 0x4000000000000000, 0xbff8000000000000, 0x3fd6a09e667f3bcd,
+ 0x4000000000000000, 0xc00599999999999a, 0x3fc3b2c47bff8328,
+ 0x4000000000000000, 0x400d99999999999a, 0x4029fdf8bcce533e,
+ 0x4000000000000000, 0x4024333333333333, 0x409125fbee250663,
+ 0x4024000000000000, 0x3fe3c6ef372fe950, 0x4010997642ad3f6c,
+ 0x4024000000000000, 0x3fb999999999999a, 0x3ff4248ef8fc2604,
+ 0x4024000000000000, 0x3fd3333333333333, 0x3fffec982d5bb8b0,
+ 0x4024000000000000, 0x3fe6666666666666, 0x40140c28430012e6,
+ 0x4024000000000000, 0x3ff8000000000000, 0x403f9f6e4990f229,
+ 0x4024000000000000, 0x4004000000000000, 0x4073c3a4edfa975a,
+ 0x4024000000000000, 0xbff8000000000000, 0x3fa030dc4ea03a71,
+ 0x4024000000000000, 0xc00599999999999a, 0x3f60585e4c78b079,
+ 0x4024000000000000, 0x400d99999999999a, 0x40b393df516e1278,
+ 0x4024000000000000, 0x4024333333333333, 0x420773062f2f8886,
+ 0x3ff9e3779b97f4a8, 0x3fe3c6ef372fe950, 0x3ff58ab1a4aaa5ea,
+ 0x3ff9e3779b97f4a8, 0x3fb999999999999a, 0x3ff0c9ec7e89f1f0,
+ 0x3ff9e3779b97f4a8, 0x3fd3333333333333, 0x3ff27c2016d2edb0,
+ 0x3ff9e3779b97f4a8, 0x3fe6666666666666, 0x3ff6688e88c6d62b,
+ 0x3ff9e3779b97f4a8, 0x3ff8000000000000, 0x400077225f1da572,
+ 0x3ff9e3779b97f4a8, 0x4004000000000000, 0x400aa43b0271e79d,
+ 0x3ff9e3779b97f4a8, 0xbff8000000000000, 0x3fdf18773c56f721,
+ 0x3ff9e3779b97f4a8, 0xc00599999999999a, 0x3fd17469bd0d70d4,
+ 0x3ff9e3779b97f4a8, 0x400d99999999999a, 0x4017bb1c71ee371a,
+ 0x3ff9e3779b97f4a8, 0x4024333333333333, 0x406021c35dde5d5a,
+ 0x400921fb54442d18, 0x3fe3c6ef372fe950, 0x40003b235fe669ca,
+ 0x400921fb54442d18, 0x3fb999999999999a, 0x3ff1f0c5c3cb6784,
+ 0x400921fb54442d18, 0x3fd3333333333333, 0x3ff68e5fbeedc21f,
+ 0x400921fb54442d18, 0x3fe6666666666666, 0x4001d3e304d76ce5,
+ 0x400921fb54442d18, 0x3ff8000000000000, 0x401645f7c63f2c6b,
+ 0x400921fb54442d18, 0x4004000000000000, 0x40317e50a9dc6553,
+ 0x400921fb54442d18, 0xbff8000000000000, 0x3fc6fcb5f827b97f,
+ 0x400921fb54442d18, 0xc00599999999999a, 0x3fa7477000837831,
+ 0x400921fb54442d18, 0x400d99999999999a, 0x4051462917d1519d,
+ 0x400921fb54442d18, 0x4024333333333333, 0x40f9a2de72e41629,
+ 0x3fb999999999999a, 0x3fe3c6ef372fe950, 0x3fced828fd51b1fa,
+ 0x3fb999999999999a, 0x3fb999999999999a, 0x3fe96b230bcdc434,
+ 0x3fb999999999999a, 0x3fd3333333333333, 0x3fe009b9cf334253,
+ 0x3fb999999999999a, 0x3fe6666666666666, 0x3fc98a13577c93c0,
+ 0x3fb999999999999a, 0x3ff8000000000000, 0x3fa030dc4ea03a73,
+ 0x3fb999999999999a, 0x4004000000000000, 0x3f69e7c6e43390ba,
+ 0x3fb999999999999a, 0xbff8000000000000, 0x403f9f6e4990f226,
+ 0x3fb999999999999a, 0xc00599999999999a, 0x407f52fee8b01d8a,
+ 0x3fb999999999999a, 0x400d99999999999a, 0x3f2a26fd472780c5,
+ 0x3fb999999999999a, 0x4024333333333333, 0x3dd5d59689697962,
+ 0x3ff9e3779b97f4a8, 0x3fd3333333333334, 0x3ff27c2016d2edb0,
+ 0x3ff9e3779b97f4a8, 0x3fe6666666666667, 0x3ff6688e88c6d62c,
+ 0x3ff9e3779b97f4a8, 0x3ff199999999999a, 0x3ffb2a2fd20d51ab,
+ 0x3ff9e3779b97f4a8, 0x3ffe666666666667, 0x4003f5d488046c18,
+ 0x3ff9e3779b97f4a8, 0x4007333333333334, 0x401025f0812433b4,
+ 0x3ff9e3779b97f4a8, 0xbfd999999999999a, 0x3fea65a32f75330f,
+ 0x3ff9e3779b97f4a8, 0xbff3333333333334, 0x3fe1f6610e9fc1d7,
+ 0x3f847ae147ae147b, 0x3fe3c6ef372fe950, 0x3fadbb0104897dba,
+ 0x3fd0000000000000, 0x3fe3c6ef372fe950, 0x3fdb2b77fd8b55b6,
+ 0x3feccccccccccccd, 0x3fe3c6ef372fe950, 0x3fedfb9036416c8d,
+ 0x3ff8000000000000, 0x3fe3c6ef372fe950, 0x3ff48e7a7c52f918,
+ 0x408f400000000000, 0x3fe3c6ef372fe950, 0x4051ddd9a91c5dfb,
+ 0x3e112e0be826d695, 0x3fe3c6ef372fe950, 0x3ec6fb571bbd94f5,
+ 0x0000000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x0000000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x0000000000000000, 0x3ff0000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0x4000000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0xc008000000000000, 0x7ff0000000000000,
+ 0x0000000000000000, 0x4008000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0x3fe0000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0xbfe0000000000000, 0x7ff0000000000000,
+ 0x0000000000000000, 0x7ff0000000000000, 0x0000000000000000,
+ 0x0000000000000000, 0xfff0000000000000, 0x7ff0000000000000,
+ 0x0000000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0x0000000000000000, 0x3fd3333333333333, 0x0000000000000000,
+ 0x0000000000000000, 0x4340000000000001, 0x0000000000000000,
+ 0x0000000000000000, 0x43e0000000000000, 0x0000000000000000,
+ 0x8000000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x8000000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x8000000000000000, 0x3ff0000000000000, 0x8000000000000000,
+ 0x8000000000000000, 0x4000000000000000, 0x0000000000000000,
+ 0x8000000000000000, 0xc008000000000000, 0xfff0000000000000,
+ 0x8000000000000000, 0x4008000000000000, 0x8000000000000000,
+ 0x8000000000000000, 0x3fe0000000000000, 0x0000000000000000,
+ 0x8000000000000000, 0xbfe0000000000000, 0x7ff0000000000000,
+ 0x8000000000000000, 0x7ff0000000000000, 0x0000000000000000,
+ 0x8000000000000000, 0xfff0000000000000, 0x7ff0000000000000,
+ 0x8000000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0x8000000000000000, 0x3fd3333333333333, 0x0000000000000000,
+ 0x8000000000000000, 0x4340000000000001, 0x0000000000000000,
+ 0x8000000000000000, 0x43e0000000000000, 0x0000000000000000,
+ 0x3ff0000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x4000000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0xc008000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x4008000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x3fe0000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0xbfe0000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x7ff0000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0xfff0000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x7ff8000000000000, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x3fd3333333333333, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x4340000000000001, 0x3ff0000000000000,
+ 0x3ff0000000000000, 0x43e0000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0x3ff0000000000000, 0xbff0000000000000,
+ 0xbff0000000000000, 0x4000000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0xc008000000000000, 0xbff0000000000000,
+ 0xbff0000000000000, 0x4008000000000000, 0xbff0000000000000,
+ 0xbff0000000000000, 0x3fe0000000000000, 0x7ff8000000000000,
+ 0xbff0000000000000, 0xbfe0000000000000, 0x7ff8000000000000,
+ 0xbff0000000000000, 0x7ff0000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0xfff0000000000000, 0x3ff0000000000000,
+ 0xbff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0xbff0000000000000, 0x3fd3333333333333, 0x7ff8000000000000,
+ 0xbff0000000000000, 0x4340000000000001, 0x3ff0000000000000,
+ 0xbff0000000000000, 0x43e0000000000000, 0x3ff0000000000000,
+ 0x7ff0000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x7ff0000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0x4000000000000000, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0xc008000000000000, 0x0000000000000000,
+ 0x7ff0000000000000, 0x4008000000000000, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0x3fe0000000000000, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0xbfe0000000000000, 0x0000000000000000,
+ 0x7ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0xfff0000000000000, 0x0000000000000000,
+ 0x7ff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0x7ff0000000000000, 0x3fd3333333333333, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0x4340000000000001, 0x7ff0000000000000,
+ 0x7ff0000000000000, 0x43e0000000000000, 0x7ff0000000000000,
+ 0xfff0000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0xfff0000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0xfff0000000000000, 0x3ff0000000000000, 0xfff0000000000000,
+ 0xfff0000000000000, 0x4000000000000000, 0x7ff0000000000000,
+ 0xfff0000000000000, 0xc008000000000000, 0x8000000000000000,
+ 0xfff0000000000000, 0x4008000000000000, 0xfff0000000000000,
+ 0xfff0000000000000, 0x3fe0000000000000, 0x7ff0000000000000,
+ 0xfff0000000000000, 0xbfe0000000000000, 0x0000000000000000,
+ 0xfff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000,
+ 0xfff0000000000000, 0xfff0000000000000, 0x0000000000000000,
+ 0xfff0000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0xfff0000000000000, 0x3fd3333333333333, 0x7ff0000000000000,
+ 0xfff0000000000000, 0x4340000000000001, 0x7ff0000000000000,
+ 0xfff0000000000000, 0x43e0000000000000, 0x7ff0000000000000,
+ 0x7ff8000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x7ff8000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x7ff8000000000000, 0x3ff0000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x4000000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0xc008000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x4008000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x3fe0000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0xbfe0000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x7ff0000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0xfff0000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x3fd3333333333333, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x4340000000000001, 0x7ff8000000000000,
+ 0x7ff8000000000000, 0x43e0000000000000, 0x7ff8000000000000,
+ 0xc000000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0xc000000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0xc000000000000000, 0x3ff0000000000000, 0xc000000000000000,
+ 0xc000000000000000, 0xc008000000000000, 0xbfc0000000000000,
+ 0xc000000000000000, 0x3fe0000000000000, 0x7ff8000000000000,
+ 0xc000000000000000, 0xbfe0000000000000, 0x7ff8000000000000,
+ 0xc000000000000000, 0x7ff0000000000000, 0x7ff0000000000000,
+ 0xc000000000000000, 0xfff0000000000000, 0x0000000000000000,
+ 0xc000000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0xc000000000000000, 0x3fd3333333333333, 0x7ff8000000000000,
+ 0xc000000000000000, 0x4340000000000001, 0x7ff0000000000000,
+ 0xc000000000000000, 0x43e0000000000000, 0x7ff0000000000000,
+ 0x3fe0000000000000, 0x0000000000000000, 0x3ff0000000000000,
+ 0x3fe0000000000000, 0x8000000000000000, 0x3ff0000000000000,
+ 0x3fe0000000000000, 0x3ff0000000000000, 0x3fe0000000000000,
+ 0x3fe0000000000000, 0xc008000000000000, 0x4020000000000000,
+ 0x3fe0000000000000, 0x3fe0000000000000, 0x3fe6a09e667f3bcd,
+ 0x3fe0000000000000, 0xbfe0000000000000, 0x3ff6a09e667f3bcc,
+ 0x3fe0000000000000, 0x7ff0000000000000, 0x0000000000000000,
+ 0x3fe0000000000000, 0xfff0000000000000, 0x7ff0000000000000,
+ 0x3fe0000000000000, 0x7ff8000000000000, 0x7ff8000000000000,
+ 0x3fe0000000000000, 0x4340000000000001, 0x0000000000000000,
+ 0x3fe0000000000000, 0x43e0000000000000, 0x0000000000000000,
+ 0x6974e718d7d7625a, 0x4000000000000000, 0x7ff0000000000000,
+ 0x16687e92154ef7ac, 0x4000000000000000, 0x0000000000000000,
+ 0x4024000000000000, 0x4073400000000000, 0x7fe1ccf385ebc8a3,
+ 0x4024000000000000, 0x4073500000000000, 0x7ff0000000000000,
+ 0x4024000000000000, 0xc074300000000000, 0x0000000000000002,
+ 0x4024000000000000, 0xc074400000000000, 0x0000000000000000,
+ 0x4024000000000000, 0xc074500000000000, 0x0000000000000000,
+ 0x4000000000000000, 0x408ff80000000000, 0x7fe0000000000000,
+ 0x4000000000000000, 0x4090000000000000, 0x7ff0000000000000,
+ 0x4000000000000000, 0xc090c80000000000, 0x0000000000000001,
+ 0x4000000000000000, 0xc090cc0000000000, 0x0000000000000001,
+ 0x4000000000000000, 0xc08ff00000000000, 0x0010000000000000,
+ 0x4000000000000000, 0xc08ff80000000000, 0x0008000000000000,
+ 0x3ff000001ad7f29b, 0x41cdcd6500000000, 0x48f349445a543ab1,
+ 0x3fefffffca501acb, 0x41cdcd6500000000, 0x36ea8c1673a33933,
+ 0x3ff8000000000000, 0x40f86a0000000000, 0x7ff0000000000000,
+ 0x3ff8000000000000, 0xc0f86a0000000000, 0x0000000000000000,
+ 0x01a56e1fc2f8f359, 0x4008000000000000, 0x0000000000000000,
+ 0x01a56e1fc2f8f359, 0xc008000000000000, 0x7ff0000000000000,
+ 0x7e37e43c8800759c, 0xc000000000000000, 0x0000000000000000,
+ 0x7e37e43c8800759c, 0x3ff000000006df38, 0x7e37e43ca3b0be82,
+ 0x3ff0000000000001, 0x4340000000000000, 0x401d8e64b16f0b93,
+ 0x3fefffffffffffff, 0x4340000000000000, 0x3fd78b56333c7f23,
+ 0x4008000000000000, 0x43e0000000000000, 0x7ff0000000000000,
+ 0x3ff0000000000001, 0x43e0000000000000, 0x7ff0000000000000,
+ 0xbff0000000000001, 0x43d0000000000000, 0x7ff0000000000000,
+ 0xc008000000000000, 0x4044800000000000, 0xc3ffa2a1cf67b5fc,
+ 0xc008000000000000, 0xc044800000000000, 0xbbe02f38e097a78b,
+ 0xc202a05f20000000, 0x4014000000000000, 0xca511b0ec57e649a,
+ 0xbfb999999999999a, 0x4008000000000000, 0xbf50624dd2f1a9fd,
+ 0xbfb999999999999a, 0xc008000000000000, 0xc08f3ffffffffffe,
+ 0x3ee4f8b588e368f1, 0x405ec00000000000, 0x0000000000000000,
+ 0x0000000000000001, 0x3fe0000000000000, 0x1e60000000000000,
+ 0x0000000000000001, 0x3ff0000000000000, 0x0000000000000001,
+ 0x0000000000000001, 0x4000000000000000, 0x0000000000000000,
+ 0x0010000000000000, 0x3fe0000000000000, 0x2000000000000000,
+ 0x0010000000000000, 0x4000000000000000, 0x0000000000000000,
+ 0x7fefffffffffffff, 0x3fe0000000000000, 0x5fefffffffffffff,
+ 0x7fefffffffffffff, 0x3ff0000000000001, 0x7ff0000000000000,
+ 0x4000000000000000, 0x3fe199999999999a, 0x3ff76ce51f6a0bb8,
+ 0x4000000000000000, 0x3fe0000000000001, 0x3ff6a09e667f3bcd,
+ 0x4024000000000000, 0x4004000000000001, 0x4073c3a4edfa975e,
+ 0x3ff9e3779b97f4a8, 0x400c666666666667, 0x4016140d14cc09f0,
+ 0x400921fb54442d18, 0xc012333333333334, 0x3f766774df26d01d,
+ 0x3fe0000000000000, 0x401a666666666666, 0x3f851cb453b9536e,
+ 0x7e37e43c8800759c, 0x4020000000000000, 0x7ff0000000000000,
+ 0x7e37e43c8800759c, 0xc020000000000000, 0x0000000000000000,
+ 0x01a56e1fc2f8f359, 0x4020000000000000, 0x0000000000000000,
+ 0x01a56e1fc2f8f359, 0xc022000000000000, 0x7ff0000000000000,
+ 0x401c000000000000, 0x3fe1999999999999, 0x400754318ca907a0,
+ 0x3ff9e3779b97f4a8, 0x3ff9999999999999, 0x400146ee5e5ba891,
+ 0xc041a6a09a1bef47, 0x4028000000000000, 0x43c9fe17eee0423c,
+ 0x40ec58be76a9655f, 0xc032373f8cf20494, 0x2dea9706fa4addfe,
+ 0x3efeeeb3f5cd5820, 0x40337498188bf660, 0x2da295562f3ec8ac,
+ 0x3f92a2b3e3f18998, 0xc020000000000000, 0x42d2e5b83d89b2b9,
+ 0x409de6b13cd05067, 0xc032fffa5a242644, 0x32fd0cf24dc15c78,
+ 0x40d230b0ea99c2e9, 0xbfe0f45e8ae0c220, 0x3f7661f71bdfed60,
+ 0x3f01d9144e20091c, 0x4039000000000000, 0x28bebe40c49c3def,
+ 0x4017104cbbcb6fa2, 0xc03946acb26b459a, 0x3bf14f1f353a51d6,
+ 0x40aa69dd0888c0fa, 0x40307d28c5226182, 0x4c03bc8d923c01c8,
+ 0x4073ea3eaeba639a, 0x4022000000000000, 0x449cae8b94519ce7,
+ 0x4100ad3bc6cafeeb, 0xc03d4616f02990fd, 0x20b82feb84424bb8,
+ 0x40f582e4c5ae35dc, 0x402121389c2d7b38, 0x48b9e98a98e0bc66,
+ 0x3f65ca3965215082, 0x401c000000000000, 0x3c3160964200c50a,
+ 0x3f94e4c852ace73e, 0x402209a7a9697d8c, 0x3cc485861536122c,
+ 0x4060d192cb6b6652, 0x3ff743a9c0eaa390, 0x40937709755cee67,
+ 0x3f1139a2a38a8dec, 0xc018000000000000, 0x45248dca7d464a43,
+ 0x3f81b2d3148507fb, 0x402dede88feff85c, 0x39857d5a55beed9b,
+ 0x40de81eae036b773, 0x40308a08cb19484e, 0x4f5edf6a2aab8cbb,
+ 0x4000a0a51efe09af, 0xc034000000000000, 0x3e9da67f670a8088,
+ 0x40623392aa67a9f8, 0xc02c316f94e54f72, 0x399a091cc44858db,
+ 0x41029e867f7c9de8, 0xc033a01cdcaf1132, 0x2ad0da8b5264a4ef,
+ 0xc0f28a568b13d67f, 0xc03d000000000000, 0xa28c88c742ea1a8e,
+ 0x4089b8b228dc8f3f, 0xc0226fe64da7a872, 0x3a5a5731f8c6448c,
+ 0x4017ab00652b1462, 0xc0143483500cec4c, 0x3f207f4658d1a4da,
+ 0x3f84618d62ab78f7, 0xc010000000000000, 0x41984ee52fc88aed,
+ 0x409e946964342f63, 0xc021acdd54cf4950, 0x39e49af404b74f95,
+ 0x3fa22feff4a45b70, 0x4030e2d64e7d9330, 0x3ad9d4f4ba992810,
+ 0x3f3ca7e6a14c1586, 0xc022000000000000, 0x46359a6c43d45aa4,
+ 0x3ff7bfb9bf9906c4, 0x3ff0a8723de8cb70, 0x3ff823478418da54,
+ 0x3f37ca63482b9f82, 0x402fbb4cc506d200, 0x3499d21d47c814a9
+];
+
+const ZS_LDEXP_VEC : [372]u64 = [
+ 0x3fe0000000000000, 3022, 0x0000000000000001,
+ 0x3ff0000000000000, 3021, 0x0000000000000000,
+ 0x3ff0000000000000, 3022, 0x0000000000000001,
+ 0x3fe8000000000000, 3022, 0x0000000000000001,
+ 0x3ff8000000000000, 3021, 0x0000000000000001,
+ 0x3fe0000000000000, 3021, 0x0000000000000000,
+ 0x0000000000000003, 4095, 0x0000000000000002,
+ 0x0000000000000003, 4094, 0x0000000000000001,
+ 0x000fffffffffffff, 4095, 0x0008000000000000,
+ 0x0000000000000001, 5170, 0x3ff0000000000000,
+ 0x3ff0000000000000, 5119, 0x7fe0000000000000,
+ 0x3ff0000000000000, 5120, 0x7ff0000000000000,
+ 0x4000000000000000, 5119, 0x7ff0000000000000,
+ 0x0000000000000001, 4096, 0x0000000000000001,
+ 0x80003739a252b281, 5096, 0xbe2b9cd129594080,
+ 0x000fffffffffffff, 4097, 0x001ffffffffffffe,
+ 0x3fefffffffffffff, 4045, 0x3cbfffffffffffff,
+ 0xbff0000000000000, 4036, 0xbc30000000000000,
+ 0x0000000000000003, 6143, 0x7cd8000000000000,
+ 0x80003739a252b281, 5120, 0xbfab9cd129594080,
+ 0x80003739a252b281, 3023, 0x8000000000000000,
+ 0x3fe0000000000000, 4036, 0x3c20000000000000,
+ 0x3ff8000000000000, 4043, 0x3ca8000000000000,
+ 0x0010000000000000, 3016, 0x0000000000000000,
+ 0x3fefffffffffffff, 3021, 0x0000000000000000,
+ 0x40fe240c9fbe76c9, 5119, 0x7ff0000000000000,
+ 0x40fe240c9fbe76c9, 4095, 0x40ee240c9fbe76c9,
+ 0xbff0000000000000, 3022, 0x8000000000000001,
+ 0x3ff8000000000000, 3073, 0x000c000000000000,
+ 0x0000000000000001, 5119, 0x3cc0000000000000,
+ 0x0008000000000000, 5096, 0x3e80000000000000,
+ 0xbff0000000000000, 3073, 0x8008000000000000,
+ 0x7fefffffffffffff, 5096, 0x7ff0000000000000,
+ 0x000fffffffffffff, 4149, 0x035ffffffffffffe,
+ 0x40fe240c9fbe76c9, 4097, 0x410e240c9fbe76c9,
+ 0xbfe0000000000000, 3036, 0x8000000000002000,
+ 0x40fe240c9fbe76c9, 4043, 0x3dae240c9fbe76c9,
+ 0x0010000000000001, 4148, 0x0350000000000001,
+ 0x80003739a252b281, 4096, 0x80003739a252b281,
+ 0x3fe8000000000000, 3023, 0x0000000000000002,
+ 0x000fffffffffffff, 3075, 0x0000000000000000,
+ 0x80003739a252b281, 3074, 0x8000000000000000,
+ 0x3fe8000000000000, 4095, 0x3fd8000000000000,
+ 0x0010000000000001, 4149, 0x0360000000000001,
+ 0x7fefffffffffffff, 6143, 0x7ff0000000000000,
+ 0x3fe0000000000000, 4095, 0x3fd0000000000000,
+ 0x0010000000000001, 3074, 0x0000000000000000,
+ 0x000fffffffffffff, 3036, 0x0000000000000000,
+ 0x0000000000000001, 6143, 0x7cc0000000000000,
+ 0x3fefffffffffffff, 4149, 0x433fffffffffffff,
+ 0x3fefffffffffffff, 3022, 0x0000000000000001,
+ 0x3ff0000000000000, 4149, 0x4340000000000000,
+ 0x000fffffffffffff, 4044, 0x0000000000000001,
+ 0x80003739a252b281, 4044, 0x8000000000000000,
+ 0x3fe8000000000000, 6142, 0x7ff0000000000000,
+ 0x80003739a252b281, 4097, 0x80006e7344a56502,
+ 0xbff0000000000000, 4043, 0xbca0000000000000,
+ 0x000fffffffffffff, 5096, 0x3e8ffffffffffffe,
+ 0xbff0000000000000, 4045, 0xbcc0000000000000,
+ 0x0000000000000003, 4045, 0x0000000000000000,
+ 0x0010000000000001, 3036, 0x0000000000000000,
+ 0x0000000000000001, 5096, 0x3b50000000000000,
+ 0x0000000000000003, 6196, 0x7ff0000000000000,
+ 0x3fe0000000000000, 4097, 0x3ff0000000000000,
+ 0x000fffffffffffff, 6196, 0x7ff0000000000000,
+ 0x0010000000000000, 6143, 0x7ff0000000000000,
+ 0x3fefffffffffffff, 3016, 0x0000000000000000,
+ 0x3fe0000000000000, 3036, 0x0000000000002000,
+ 0x3ff0000000000000, 6142, 0x7ff0000000000000,
+ 0x0000000000000001, 4095, 0x0000000000000000,
+ 0xbfe0000000000000, 4148, 0xc320000000000000,
+ 0x3fe8000000000000, 4043, 0x3c98000000000000,
+ 0x80003739a252b281, 3016, 0x8000000000000000,
+ 0x7fefffffffffffff, 3074, 0x400fffffffffffff,
+ 0x3fefffffffffffff, 4096, 0x3fefffffffffffff,
+ 0x3ff0000000000000, 5121, 0x7ff0000000000000,
+ 0x0010000000000001, 6142, 0x7ff0000000000000,
+ 0x3fe8000000000000, 4044, 0x3ca8000000000000,
+ 0x3fe0000000000000, 4044, 0x3ca0000000000000,
+ 0x0010000000000000, 3022, 0x0000000000000000,
+ 0x3fe8000000000000, 4036, 0x3c28000000000000,
+ 0x40fe240c9fbe76c9, 3016, 0x0000000000000789,
+ 0x40fe240c9fbe76c9, 6143, 0x7ff0000000000000,
+ 0x3ff0000000000000, 4043, 0x3ca0000000000000,
+ 0x3ff0000000000000, 4044, 0x3cb0000000000000,
+ 0x3ff0000000000000, 3074, 0x0010000000000000,
+ 0x3fefffffffffffff, 4044, 0x3cafffffffffffff,
+ 0xbff0000000000000, 4097, 0xc000000000000000,
+ 0x40fe240c9fbe76c9, 4096, 0x40fe240c9fbe76c9,
+ 0x3fe0000000000000, 6196, 0x7ff0000000000000,
+ 0x3fefffffffffffff, 5121, 0x7ff0000000000000,
+ 0xbfe0000000000000, 5120, 0xffe0000000000000,
+ 0x0008000000000000, 3023, 0x0000000000000000,
+ 0x40fe240c9fbe76c9, 4044, 0x3dbe240c9fbe76c9,
+ 0x0010000000000001, 6196, 0x7ff0000000000000,
+ 0xbfe0000000000000, 4149, 0xc330000000000000,
+ 0x0000000000000001, 3075, 0x0000000000000000,
+ 0x3fe8000000000000, 6196, 0x7ff0000000000000,
+ 0xbfe0000000000000, 6143, 0xfff0000000000000,
+ 0x000fffffffffffff, 3016, 0x0000000000000000,
+ 0x40fe240c9fbe76c9, 3074, 0x011e240c9fbe76c9,
+ 0x0008000000000000, 3021, 0x0000000000000000,
+ 0x0010000000000001, 3020, 0x0000000000000000,
+ 0x3fefffffffffffff, 5119, 0x7fdfffffffffffff,
+ 0x000fffffffffffff, 5120, 0x400ffffffffffffe,
+ 0x000fffffffffffff, 3023, 0x0000000000000000,
+ 0x0010000000000000, 5120, 0x4010000000000000,
+ 0x80003739a252b281, 3073, 0x8000000000000000,
+ 0x40fe240c9fbe76c9, 4036, 0x3d3e240c9fbe76c9,
+ 0x3fe8000000000000, 3036, 0x0000000000003000,
+ 0x0000000000000001, 4097, 0x0000000000000002,
+ 0x0000000000000001, 4044, 0x0000000000000000,
+ 0x3ff8000000000000, 6196, 0x7ff0000000000000,
+ 0x7fefffffffffffff, 6196, 0x7ff0000000000000,
+ 0x0010000000000001, 4095, 0x0008000000000000,
+ 0x3ff0000000000000, 3075, 0x0020000000000000,
+ 0x40fe240c9fbe76c9, 3023, 0x000000000003c482,
+ 0x000fffffffffffff, 6143, 0x7ff0000000000000,
+ 0x0010000000000000, 4043, 0x0000000000000000,
+ 0x0010000000000001, 3021, 0x0000000000000000,
+ 0x3fe8000000000000, 6143, 0x7ff0000000000000,
+ 0x0008000000000000, 6143, 0x7ff0000000000000,
+ 0x3fe0000000000000, 3075, 0x0010000000000000,
+ 0x3fe8000000000000, 5096, 0x7e68000000000000
+];
+
+const ZS_FREXP_VEC : [48]u64 = [
+ 0x3ff0000000000000, 0x3fe0000000000000, 2049,
+ 0x3fe0000000000000, 0x3fe0000000000000, 2048,
+ 0x3fe8000000000000, 0x3fe8000000000000, 2048,
+ 0x4008000000000000, 0x3fe8000000000000, 2050,
+ 0xc008000000000000, 0xbfe8000000000000, 2050,
+ 0x7e37e43c8800759c, 0x3fe7e43c8800759c, 3045,
+ 0x01a56e1fc2f8f359, 0x3fe56e1fc2f8f359, 1052,
+ 0x0000000000000001, 0x3fe0000000000000, 975,
+ 0x0010000000000000, 0x3fe0000000000000, 1027,
+ 0x000fffffffffffff, 0x3feffffffffffffe, 1026,
+ 0x40c81cd6e631f8a1, 0x3fe81cd6e631f8a1, 2062,
+ 0x80003739a252b281, 0xbfeb9cd129594080, 1020,
+ 0x7fefffffffffffff, 0x3fefffffffffffff, 3072,
+ 0x4020000000000000, 0x3fe0000000000000, 2052,
+ 0x0010000000000000, 0x3fe0000000000000, 1027,
+ 0x0000000000000400, 0x3fe0000000000000, 985
+];
+
+test std_math_pow_f64_is_zigs_on_every_recorded_vector {
+ var i : usize = 0;
+ var bad : usize = 0;
+ while (i < 433) {
+ const xb : u64 = ZS_POW_VEC[3 * i];
+ const yb : u64 = ZS_POW_VEC[3 * i + 1];
+ const wb : u64 = ZS_POW_VEC[3 * i + 2];
+ const x : f64 = @bitCast(xb);
+ const y : f64 = @bitCast(yb);
+ const w : f64 = @bitCast(wb);
+ const r : f64 = std_math_pow_f64(x, y);
+ const rb : u64 = @bitCast(r);
+ var ok : bool = rb == wb;
+ if (w != w) {
+ ok = r != r;
+ }
+ if (ok == false) {
+ bad = bad + 1;
+ }
+ i = i + 1;
+ }
+ assert(bad == 0);
+}
+
+test zs_ldexp_is_zigs_on_every_recorded_vector_including_the_subnormal_ties {
+ var i : usize = 0;
+ var bad : usize = 0;
+ while (i < 124) {
+ const xb : u64 = ZS_LDEXP_VEC[3 * i];
+ const nb : u64 = ZS_LDEXP_VEC[3 * i + 1];
+ const wb : u64 = ZS_LDEXP_VEC[3 * i + 2];
+ const x : f64 = @bitCast(xb);
+ var n : i32 = @intCast(nb);
+ n = n - 4096;
+ const r : f64 = zs_ldexp(x, n);
+ const rb : u64 = @bitCast(r);
+ if (rb != wb) {
+ bad = bad + 1;
+ }
+ i = i + 1;
+ }
+ assert(bad == 0);
+}
+
+test zs_frexp_is_zigs_on_every_recorded_vector {
+ var i : usize = 0;
+ var bad : usize = 0;
+ while (i < 16) {
+ const xb : u64 = ZS_FREXP_VEC[3 * i];
+ const sb : u64 = ZS_FREXP_VEC[3 * i + 1];
+ const eb : u64 = ZS_FREXP_VEC[3 * i + 2];
+ const x : f64 = @bitCast(xb);
+ const s : f64 = zs_frexp_sig(x);
+ const sbits : u64 = @bitCast(s);
+ var e : i32 = @intCast(eb);
+ e = e - 2048;
+ if (sbits != sb or zs_frexp_exp(x) != e) {
+ bad = bad + 1;
+ }
+ i = i + 1;
+ }
+ assert(bad == 0);
+}
+
+test the_special_values_follow_pow_zig {
+ const inf : f64 = std.math.inf(f64);
+ const nzb : u64 = 0x8000000000000000;
+ const nzero : f64 = @bitCast(nzb);
+ assert(std_math_pow_f64(0.0, 0.0) == 1.0);
+ assert(std_math_pow_f64(std.math.nan(f64), 0.0) == 1.0);
+ assert(std_math_pow_f64(1.0, std.math.nan(f64)) == 1.0);
+ assert(std.math.isNan(std_math_pow_f64(std.math.nan(f64), 1.0)));
+ assert(std_math_pow_f64(nzero, -3.0) == -inf);
+ assert(std_math_pow_f64(nzero, -2.0) == inf);
+ assert(std_math_pow_f64(nzero, 3.0) == 0.0);
+ assert(zs_sign(std_math_pow_f64(nzero, 3.0)) == 1);
+ assert(zs_sign(std_math_pow_f64(nzero, 2.0)) == 0);
+ assert(std_math_pow_f64(-1.0, inf) == 1.0);
+ assert(std_math_pow_f64(2.0, inf) == inf);
+ assert(std_math_pow_f64(2.0, -inf) == 0.0);
+ assert(std_math_pow_f64(0.5, inf) == 0.0);
+ assert(std_math_pow_f64(-inf, 3.0) == -inf);
+ assert(std_math_pow_f64(-inf, 2.0) == inf);
+ assert(std_math_pow_f64(inf, -1.0) == 0.0);
+ assert(std_math_pow_f64(-8.0, 3.0) == -512.0);
+ assert(std_math_pow_f64(9.0, 0.5) == 3.0);
+ assert(std_math_pow_f64(4.0, -0.5) == 0.5);
+}
+
+test negative_control_a_negative_base_with_a_fraction_is_nan {
+ assert(std.math.isNan(std_math_pow_f64(-8.0, 1.5)));
+ assert(std.math.isNan(std_math_pow_f64(-2.0, 0.3)));
+ assert(std.math.isNan(std_math_pow_f64(-0.5, -2.5)));
+}
+
+// Plain repeated multiplication, the obvious port of an integer power: NOT Zig's result.
+pub fn zs_naive_powi(x: f64, n: u32) -> f64 {
+ var r : f64 = 1.0;
+ var k : u32 = 0;
+ while (k < n) {
+ r = r * x;
+ k = k + 1;
+ }
+ return r;
+}
+
+test negative_control_repeated_multiplication_is_not_zigs_pow_and_the_vectors_tell_them_apart {
+ // phi^8: 46.9787137637478 by multiplying eight times, 46.97871376374779 by Zig's pow
+ const phi : f64 = 1.618033988749895;
+ const naive : f64 = zs_naive_powi(phi, 8);
+ const naive_bits : u64 = @bitCast(naive);
+ const zig_bits : u64 = 0x40477D467E1BB88E;
+ const mine : f64 = std_math_pow_f64(phi, 8.0);
+ const mine_bits : u64 = @bitCast(mine);
+ assert(naive_bits != zig_bits);
+ assert(mine_bits == zig_bits);
+}
+
+test negative_control_an_exact_tie_below_the_subnormals_rounds_up_in_zig_where_ieee_rounds_to_even {
+ // 2^-1075 is half of the smallest subnormal. 0.5 * 2^-1074 rounds to even: 0. Zig's ldexp gives 2^-1074.
+ const one : u64 = 1;
+ const tiny : f64 = @bitCast(one);
+ const ieee : f64 = 0.5 * tiny;
+ const ieee_bits : u64 = @bitCast(ieee);
+ const zig : f64 = zs_ldexp(0.5, -1074);
+ const zig_bits : u64 = @bitCast(zig);
+ assert(ieee_bits == 0);
+ assert(zig_bits == 1);
+ assert(std_math_pow_f64(2.0, -1075.0) == tiny);
+}