open-standards/wai/wai-rs/clippy.toml
Transaction Science f96ce04da3
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
wai-rs: the JPEG AI exact decoder calls no platform math library, and its output is pinned
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]>
2026-09-28 18:30:35 -04:00

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" },
]