Some checks failed
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 1m48s
standards workspaces build + test / aac-rs (pull_request) Successful in 36s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 47s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 39s
standards workspaces build + test / map-rs (pull_request) Successful in 40s
standards workspaces build + test / mesh-rs (pull_request) Successful in 32s
standards workspaces build + test / openpay (pull_request) Successful in 1m50s
wai cross-architecture byte-equality / linux-aarch64 (pull_request) Successful in 21s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 1m0s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 14s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m52s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m21s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m16s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m10s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 2m30s
wai cross-architecture byte-equality / linux-x86_64 (pull_request) Successful in 16s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 1m13s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 14s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 40s
wai formal verification (integer core) / kani (pull_request) Successful in 3m59s
WAI neural decoders end-to-end / synthetic fixtures → Rust decode → reference (±4) (pull_request) Failing after 1m8s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 27s
standards workspaces build + test / arl-rs (pull_request) Successful in 2m54s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 2m19s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 2m45s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 2m26s
standards workspaces build + test / sense-rs (pull_request) Successful in 2m15s
standards workspaces build + test / macOS energy backend (jcp-energy) (pull_request) Failing after 2m23s
wai cross-architecture byte-equality / macos-arm64 (reference) (pull_request) Successful in 13s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 2m30s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 35s
wai cross-architecture byte-equality / windows-x86_64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · windows (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · windows (pull_request) Has been cancelled
The exact decoder's only math-library calls were `exp` in the gain scaler and, on some targets, the float-to-integer roundings. Those results could differ between platform math libraries, so the decoded bytes could differ between machines. - `float_repro` provides `exp` and the roundings built only from IEEE-754 basic operations, so their bits are the same on every conforming target. Its unit tests pin their bits over a fixed grid of inputs and compare them with the host's own functions. - Two guards keep the decode path free of math-library calls. Clippy's `disallowed_methods` (wai-rs/clippy.toml) is denied in each module on the path, however the call is spelled. tests/jpegai_decode_symbols.rs fails if the linked decoder imports a C math-library function. - tests/jpegai_cross_platform.rs pins the decoded bytes of the `jpegai/v1` inputs and the bits of the float values reported after each stage. They were measured identical on macOS arm64, wasm32-wasip2, Linux arm64 (glibc) and Linux x86_64 (glibc, under user-mode emulation). Not measured: macOS x86_64, Windows, x86_64 hardware, 32-bit targets. The test skips unless its inputs are supplied. - The gain-scaler margin tool now models the reference software's float32 arithmetic and corrects `log_k`. - determinism-tiers' evidence table records the measurement and its limits. The registry class of `wai.image.jpegai` is unchanged (NeuralEntropyExact). Co-Authored-By: Claude Opus 5.5 <[email protected]>
104 lines
7 KiB
TOML
104 lines
7 KiB
TOML
# The float functions the JPEG AI exact decoder must not call.
|
|
#
|
|
# The exact decoder (`src/jpegai_decode.rs` and the modules it runs through) reproduces
|
|
# bit for bit across platforms because its float stages use only IEEE-754 basic
|
|
# operations, with `exp` and rounding built from them in `src/float_repro.rs`. The
|
|
# methods below would put something else on that path: a platform math-library
|
|
# function, whose last bits are not fixed by any standard, or an operation whose
|
|
# lowering or result differs between targets.
|
|
#
|
|
# Clippy resolves each use by type, so it catches `x.exp()`, `f64::exp(x)` and
|
|
# `.map(f64::exp)` alike, and not `crate::float_repro::exp` or an integer `max`.
|
|
# The lint is allowed for the package (`[lints.clippy]` in Cargo.toml) and denied
|
|
# by each module on the decode path (`#![deny(clippy::disallowed_methods)]`), so the
|
|
# rest of the crate may use these methods. `.github/workflows/wai-conformance.yml`
|
|
# runs clippy on the library. What it does not see (an operator such as a float `%`,
|
|
# a call in a module without the attribute or in another crate) is covered by
|
|
# `tests/jpegai_decode_symbols.rs`, which inspects the linked executable.
|
|
disallowed-methods = [
|
|
# Transcendental and power functions: a platform math library is not required to
|
|
# round them correctly, so libraries disagree in the last bits.
|
|
{ path = "f64::exp", reason = "platform math library; use crate::float_repro::exp" },
|
|
{ path = "f32::exp", reason = "platform math library; use crate::float_repro::exp" },
|
|
{ path = "f64::exp2", reason = "platform math library" },
|
|
{ path = "f32::exp2", reason = "platform math library" },
|
|
{ path = "f64::exp_m1", reason = "platform math library" },
|
|
{ path = "f32::exp_m1", reason = "platform math library" },
|
|
{ path = "f64::ln", reason = "platform math library" },
|
|
{ path = "f32::ln", reason = "platform math library" },
|
|
{ path = "f64::ln_1p", reason = "platform math library" },
|
|
{ path = "f32::ln_1p", reason = "platform math library" },
|
|
{ path = "f64::log", reason = "platform math library" },
|
|
{ path = "f32::log", reason = "platform math library" },
|
|
{ path = "f64::log2", reason = "platform math library" },
|
|
{ path = "f32::log2", reason = "platform math library" },
|
|
{ path = "f64::log10", reason = "platform math library" },
|
|
{ path = "f32::log10", reason = "platform math library" },
|
|
{ path = "f64::powf", reason = "platform math library" },
|
|
{ path = "f32::powf", reason = "platform math library" },
|
|
{ path = "f64::powi", reason = "not correctly rounded, and its expansion depends on the optimiser" },
|
|
{ path = "f32::powi", reason = "not correctly rounded, and its expansion depends on the optimiser" },
|
|
{ path = "f64::sin", reason = "platform math library" },
|
|
{ path = "f32::sin", reason = "platform math library" },
|
|
{ path = "f64::cos", reason = "platform math library" },
|
|
{ path = "f32::cos", reason = "platform math library" },
|
|
{ path = "f64::tan", reason = "platform math library" },
|
|
{ path = "f32::tan", reason = "platform math library" },
|
|
{ path = "f64::sin_cos", reason = "platform math library" },
|
|
{ path = "f32::sin_cos", reason = "platform math library" },
|
|
{ path = "f64::asin", reason = "platform math library" },
|
|
{ path = "f32::asin", reason = "platform math library" },
|
|
{ path = "f64::acos", reason = "platform math library" },
|
|
{ path = "f32::acos", reason = "platform math library" },
|
|
{ path = "f64::atan", reason = "platform math library" },
|
|
{ path = "f32::atan", reason = "platform math library" },
|
|
{ path = "f64::atan2", reason = "platform math library" },
|
|
{ path = "f32::atan2", reason = "platform math library" },
|
|
{ path = "f64::sinh", reason = "platform math library" },
|
|
{ path = "f32::sinh", reason = "platform math library" },
|
|
{ path = "f64::cosh", reason = "platform math library" },
|
|
{ path = "f32::cosh", reason = "platform math library" },
|
|
{ path = "f64::tanh", reason = "platform math library" },
|
|
{ path = "f32::tanh", reason = "platform math library" },
|
|
{ path = "f64::asinh", reason = "platform math library" },
|
|
{ path = "f32::asinh", reason = "platform math library" },
|
|
{ path = "f64::acosh", reason = "platform math library" },
|
|
{ path = "f32::acosh", reason = "platform math library" },
|
|
{ path = "f64::atanh", reason = "platform math library" },
|
|
{ path = "f32::atanh", reason = "platform math library" },
|
|
{ path = "f64::cbrt", reason = "platform math library" },
|
|
{ path = "f32::cbrt", reason = "platform math library" },
|
|
{ path = "f64::hypot", reason = "platform math library" },
|
|
{ path = "f32::hypot", reason = "platform math library" },
|
|
{ path = "f64::abs_sub", reason = "platform math library (fdim)" },
|
|
{ path = "f32::abs_sub", reason = "platform math library (fdim)" },
|
|
# Rounding to an integer and remainders: exactly specified, but on some targets
|
|
# (baseline x86_64, wasm32) they compile to a call whose provider depends on the
|
|
# link. The decode takes rounding from crate::float_repro.
|
|
{ path = "f64::round", reason = "may compile to a library call; use crate::float_repro::round_half_away" },
|
|
{ path = "f32::round", reason = "may compile to a library call; use crate::float_repro::round_half_away_f32" },
|
|
{ path = "f64::round_ties_even", reason = "may compile to a library call; use crate::float_repro::round_half_even" },
|
|
{ path = "f32::round_ties_even", reason = "may compile to a library call" },
|
|
{ path = "f64::floor", reason = "may compile to a library call" },
|
|
{ path = "f32::floor", reason = "may compile to a library call" },
|
|
{ path = "f64::ceil", reason = "may compile to a library call" },
|
|
{ path = "f32::ceil", reason = "may compile to a library call" },
|
|
{ path = "f64::trunc", reason = "may compile to a library call" },
|
|
{ path = "f32::trunc", reason = "may compile to a library call" },
|
|
{ path = "f64::fract", reason = "may compile to a library call (trunc)" },
|
|
{ path = "f32::fract", reason = "may compile to a library call (trunc)" },
|
|
{ path = "f64::rem_euclid", reason = "compiles to a library call (fmod)" },
|
|
{ path = "f32::rem_euclid", reason = "compiles to a library call (fmod)" },
|
|
{ path = "f64::div_euclid", reason = "may compile to a library call (trunc)" },
|
|
{ path = "f32::div_euclid", reason = "may compile to a library call (trunc)" },
|
|
# Fused multiply-add rounds once where `a * b + c` rounds twice, and falls back to a
|
|
# library `fma` on targets without the instruction.
|
|
{ path = "f64::mul_add", reason = "fused: one rounding where the decode's arithmetic has two" },
|
|
{ path = "f32::mul_add", reason = "fused: one rounding where the decode's arithmetic has two" },
|
|
# IEEE maxNum/minNum leave the sign of a zero result unspecified, and some targets
|
|
# call the library's fmax/fmin. The decode clamps with `clamp`, which compares.
|
|
{ path = "f64::max", reason = "sign of a zero result unspecified; may call fmax" },
|
|
{ path = "f32::max", reason = "sign of a zero result unspecified; may call fmaxf" },
|
|
{ path = "f64::min", reason = "sign of a zero result unspecified; may call fmin" },
|
|
{ path = "f32::min", reason = "sign of a zero result unspecified; may call fminf" },
|
|
]
|