From 5c8a51482c94dede10b2d7cb224186c09de76420 Mon Sep 17 00:00:00 2001 From: Adam Getchell Date: Tue, 8 Sep 2026 13:49:55 -0700 Subject: [PATCH 1/2] fix(release)!: finalize v0.4.6 and preserve benchmark history - Complete the v0.4.6 release PR with updated crate and utility package versions, citation metadata, release documentation, and roadmap - Generate the release changelog with complete breaking-change descriptions, preserved Rust code formatting, and idempotent summary generation - Refresh README benchmark assets and the v0.4.6 versus v0.4.5 report - Preserve every measured local benchmark case in versioned CSV snapshots with means, medians, confidence intervals, sample counts, and provenance - Regenerate reports and README assets after cleanup or artifact-only commits without rerunning benchmarks - Publish reports, snapshots, and the latest pointer atomically; reject incomplete inputs, mismatched provenance, and overlapping output paths - Isolate nalgebra/faer dependencies in the comparison workspace package so exact benchmark builds do not compile peer libraries - Reuse baseline peer measurements and disable unused Criterion HTML generation to avoid missing-sample errors in filtered runs - Fix shared-harness target resolution and exact-solve compatibility with supported historical releases - Use faer's native dot-product kernel under a distinct benchmark identity - Remove v0.4.3 adapters, missing-row exemptions, and legacy benchmark-name substitutions while preserving historical reports - Archive the previous performance report and completed optimization studies - Fix cargo-upgrade version detection during setup BREAKING CHANGE: New release performance comparisons require v0.4.4 or newer on both sides. Direct Cargo invocations of vs_linalg must select -p la-stack-comparison; the just recipes handle this automatically. --- .github/workflows/benchmarks.yml | 2 - AGENTS.md | 11 +- CHANGELOG.md | 231 ++++- CITATION.cff | 4 +- Cargo.lock | 15 +- Cargo.toml | 26 +- README.md | 52 +- benches/common/exact.rs | 47 +- benches/common/vs_linalg.rs | 65 +- benches/comparison/Cargo.toml | 27 + .../comparison/tests}/vs_linalg_inputs.rs | 49 +- benches/exact.rs | 20 +- benches/vs_linalg.rs | 41 +- cliff.toml | 14 +- docs/BENCHMARKING.md | 132 ++- docs/RELEASING.md | 14 +- docs/archive/changelog/0.2.md | 12 +- docs/archive/changelog/0.3.md | 3 +- docs/archive/performance/README.md | 3 + docs/archive/performance/studies/README.md | 11 + .../studies}/rational-row-clearing.md | 4 +- .../studies}/solve-finalization.md | 2 +- docs/archive/performance/v0.4.5-vs-v0.4.4.md | 286 ++++++ .../bench/vs_linalg_lu_solve_median.csv | 16 +- .../vs_linalg_lu_solve_median.provenance.json | 37 +- .../bench/vs_linalg_lu_solve_median.svg | 146 +-- docs/code_organization.md | 24 +- docs/performance.md | 472 +++++---- docs/performance/README.md | 87 ++ docs/performance/latest.json | 4 + .../performance.csv | 226 +++++ .../performance.full.csv | 956 ++++++++++++++++++ .../performance.full.provenance.json | 132 +++ .../performance.provenance.json | 112 ++ docs/roadmap.md | 68 +- justfile | 36 +- pyproject.toml | 8 +- scripts/README.md | 37 +- scripts/archive_performance.py | 121 ++- scripts/bench_compare.py | 129 +-- scripts/benchmark_contract.py | 1 - scripts/benchmark_summaries.py | 260 +++++ scripts/criterion_dim_plot.py | 71 +- scripts/criterion_measurements.py | 48 + scripts/performance_artifacts.py | 9 +- scripts/postprocess_changelog.py | 61 +- scripts/release_baseline.py | 45 +- scripts/tests/test_archive_performance.py | 642 ++++++++---- scripts/tests/test_bench_compare.py | 333 ++---- scripts/tests/test_criterion_dim_plot.py | 174 +++- .../tests/test_justfile_discoverability.py | 45 + scripts/tests/test_performance_artifacts.py | 175 +++- scripts/tests/test_postprocess_changelog.py | 62 +- scripts/tests/test_release_baseline.py | 4 +- tests/exact_bench_config.rs | 22 +- uv.lock | 46 +- 56 files changed, 4302 insertions(+), 1378 deletions(-) create mode 100644 benches/comparison/Cargo.toml rename {tests => benches/comparison/tests}/vs_linalg_inputs.rs (93%) create mode 100644 docs/archive/performance/studies/README.md rename docs/{performance => archive/performance/studies}/rational-row-clearing.md (98%) rename docs/{performance => archive/performance/studies}/solve-finalization.md (94%) create mode 100644 docs/archive/performance/v0.4.5-vs-v0.4.4.md create mode 100644 docs/performance/README.md create mode 100644 docs/performance/latest.json create mode 100644 docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.csv create mode 100644 docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.csv create mode 100644 docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.provenance.json create mode 100644 docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.provenance.json create mode 100644 scripts/benchmark_summaries.py create mode 100644 scripts/criterion_measurements.py diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 1858803..a8d68ad 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -17,7 +17,6 @@ on: - "src/**" - "benches/**" - "tests/exact_bench_config.rs" - - "tests/vs_linalg_inputs.rs" - ".config/nextest.toml" - "Cargo.toml" - "Cargo.lock" @@ -32,7 +31,6 @@ on: - "src/**" - "benches/**" - "tests/exact_bench_config.rs" - - "tests/vs_linalg_inputs.rs" - ".config/nextest.toml" - "Cargo.toml" - "Cargo.lock" diff --git a/AGENTS.md b/AGENTS.md index 69ed400..9bf1f37 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -220,11 +220,12 @@ Favor the invariant over a convenient edit or faster implementation. ## Project Context -This is one Rust library crate, rooted at `src/lib.rs`. Core dimensions are -compile-time constants. The `exact` feature enables arbitrary-precision -arithmetic; `bench` gates benchmark targets while their dependencies remain -dev-only. The [Code organization guide](docs/code_organization.md) maps -modules, features, tests, and tooling. Update that guide when file ownership +The published Rust library is rooted at `src/lib.rs`. The unpublished +`benches/comparison` workspace member owns nalgebra/faer benchmark dependencies +and input tests. Core dimensions are compile-time constants. The `exact` feature +enables arbitrary-precision arithmetic; `bench` gates benchmark targets while +their dependencies remain dev-only. The [Code organization guide](docs/code_organization.md) +maps modules, features, tests, and tooling. Update that guide when file ownership or layout changes. ## Agent Expectations diff --git a/CHANGELOG.md b/CHANGELOG.md index 00f1d8d..b130384 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,224 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.4.6] - 2026-09-08 + +### ⚠️ Breaking Changes + +- Matrix::solve_exact now returns RationalVector<D> instead of [BigRational; D]. Use as_array() or into_array() when raw storage is required. +- rename Vector::norm2() to Vector::norm(), Vector::norm2_sq() to Vector::norm_squared(), and Matrix::inf_norm() + to Matrix::norm_inf(). No compatibility aliases are provided. +- la-stack now requires Rust 1.98.1. + +### Merged Pull Requests + +- Bump the github-actions group with 4 updates [#240](https://github.com/acgetchell/la-stack/pull/240) +- Bump the github-actions group with 3 updates [#223](https://github.com/acgetchell/la-stack/pull/223) +- Bump the github-actions group with 4 updates [#221](https://github.com/acgetchell/la-stack/pull/221) + +### Added + +- Accept rational matrix inputs [`703746e`](https://github.com/acgetchell/la-stack/commit/703746e576bf15cca6a4c1e259292b4334946409) + + - add fixed-size rational matrix and vector types with exact determinant signs, determinant values, and solves + - provide stable runtime dispatch through D=8 with explicit exact-to-f64 conversion + - preserve typed diagnostics while reusing row-cleared Bareiss elimination + - add release-tracked Criterion comparisons against BigRational Gaussian elimination + - document the two-domain scalar model and the f64 precision boundary +- Add certified determinant sign enclosures [`cd94ebb`](https://github.com/acgetchell/la-stack/commit/cd94ebbbfecccc1fc79887eec39f1e2b8a3fc56a) + - Add outward-rounded interval arithmetic with typed range and input errors. + - Certify determinant signs through D=7 with explicit inconclusive results. + - Provide runtime dimension dispatch, documentation, and benchmark coverage. + - Refresh pinned Python development tools and transitive dependencies. +- Add certified dot and affine error bounds [`973e662`](https://github.com/acgetchell/la-stack/commit/973e662bfa1bb85631f6826034f128b181a326c4) + - Add proof-bearing scalar certificates for dot products and unrounded axis · (left - right) reductions. + - Expose outward bounds for sign and threshold filtering, with inconclusive results when proof conditions fail. + - Document and benchmark the deterministic FMA error model. +- Add overflow-safe Euclidean norms [`f1f7b11`](https://github.com/acgetchell/la-stack/commit/f1f7b11d873db9c70c7db9920ee36efa7b4ed801) + - Add allocation-free Vector::norm2 with scaled accumulation for large and subnormal finite coordinates. + - Resolve upper-range rounding with exact stack-based square sums, preventing false or hidden overflow without the exact feature. + - Report VectorNorm-tagged NonFinite errors only when the exact norm rounds to infinity; preserve norm2_sq's distinct range contract. + - Avoid redundant first-coordinate arithmetic and share binary64 rounding primitives across vector and interval operations. + - Document approximation limits and add peer-crate norm benchmarks plus scenario comparisons with hypot and Delaunay reference kernels. +- Add const-generic Gram matrix construction [`a62e72a`](https://github.com/acgetchell/la-stack/commit/a62e72a0468ea13c7c5e851dbf195123d5bb0d38) + - Add allocation-free, const-evaluable `gram_matrix` with independent vector count and dimension + - Preserve bitwise symmetry and typed dot-product overflow diagnostics + - Document geometric uses, conditioning, and floating-point limitations + - Add benchmarks for square and rectangular vector collections + - Simplify exact rational scaling using canonical positive denominators + - Deduplicate factorization property-test fixtures and assertions + +### Changed + +- Assert legacy artifact fixture uses schema 2 [`4524f86`](https://github.com/acgetchell/la-stack/commit/4524f86cbdcb69cdd73e1299520c2ac36a145f02) +- Cover enclosure and range-exhaustion boundaries [`c2437b8`](https://github.com/acgetchell/la-stack/commit/c2437b80fabe6f549111512c9fce2499d4d67346) + + - Exercise binade-boundary multiplication and selected-extrema overflow cases. + - Cover determinant accumulation failures, square/addition exhaustion, and matrix access bounds. + - Clarify that lifting an already-rounded matrix encloses only its stored values. +- [**breaking**] Standardize vector and matrix norm names [`ab483d4`](https://github.com/acgetchell/la-stack/commit/ab483d4c4cb96b2d3f2ba0be38e96f5820b0de91) + - Distinguish Euclidean norm from squared norm with clearer vector APIs. + - Use norm_inf for the matrix maximum absolute row sum. + - Preserve numerical behavior and typed error contracts. + - Retain historical benchmark IDs and adapters for older releases. + - Document the v0.4.6 migration and clarify norm definitions. + +### Dependencies + +- Bump the github-actions group with 4 updates [#221](https://github.com/acgetchell/la-stack/pull/221) + [`fa501a8`](https://github.com/acgetchell/la-stack/commit/fa501a8d3ae068783f5e83f773ef979a843f14fb) +- Bump the github-actions group with 3 updates [#223](https://github.com/acgetchell/la-stack/pull/223) + [`c0d7c93`](https://github.com/acgetchell/la-stack/commit/c0d7c932c81267dbd780f6b3706f16341f1410c8) +- Bump the github-actions group with 4 updates [#240](https://github.com/acgetchell/la-stack/pull/240) + [`98e322c`](https://github.com/acgetchell/la-stack/commit/98e322c4e32081177c8d4c11aa7aaf7e23a77b4e) + +### Fixed + +- Advance exact Python dev pins with just update [`3616ae9`](https://github.com/acgetchell/la-stack/commit/3616ae97245952b4afd3247fca06cb5db9d3e6e0) + + - Resolve direct development tools as one compatible cross-platform set. + - Preserve runtime and build-system dependency requirements. + - Refresh Ruff, Semgrep, Ty, and their compatible transitive dependencies. +- Enforce the f64 algebraic-operation ban [`753179c`](https://github.com/acgetchell/la-stack/commit/753179c001ce750195b85bf7bc680cca0558eb34) + - Reject algebraic f64 calls and function items across repository-owned Rust while preserving ordinary operators and `mul_add`. + - Document the numerical contract, MSRV, release-pinned references, and native BLAS alternatives. + - Refresh contributor tool pins and adapt subprocess encoding to Ty 0.0.74. +- Detect qualified f64 algebraic operations [`31021f1`](https://github.com/acgetchell/la-stack/commit/31021f1322a9c443fa4df63e632e8038600b2461) + - Reject `<f64>::algebraic_*` calls and function items. + - Preserve qualified FMA calls and function items as allowed. +- Make just update reconcile all managed tools [`b1ca30a`](https://github.com/acgetchell/la-stack/commit/b1ca30a3f3977d3504b9383aff3907ce73f5a72a) + - Preflight update prerequisites before modifying dependency or lock state. + - Update Cargo and Python dependencies while preserving coupled exact-arithmetic requirements. + - Upgrade setup-owned Cargo tools and atomically reconcile their pins with the active uv version. + - Keep actionlint and zizmor compatible for local composite-action references. +- Validate uv before repository updates [`37a17ed`](https://github.com/acgetchell/la-stack/commit/37a17edc82488ff0f04ec5775fe1eb13760b0468) + - Require the active uv to report a stable X.Y.Z version before dependency or Cargo tool changes. + - Preserve pin reconciliation for newer stable uv installations. +- Reject ambiguous uv output before repository updates [`6bb2412`](https://github.com/acgetchell/la-stack/commit/6bb24127cca69f5029346b63fa9bb330381ae9c7) + - Validate uv output with the reconciler's single-stable-version parser before dependency or tool mutations. + - Accept newer stable uv releases while rejecting ambiguous, missing, prerelease, and embedded versions. + - Refresh managed tool pins and the Semgrep development dependency. +- Make Python automation portable on Windows [`2370cbf`](https://github.com/acgetchell/la-stack/commit/2370cbf819f893ca598f83394330a5936fd10c6b) + - Bind uv version validation to the exact launcher selected by update recipes + - Preserve byte-exact Git input and explicit text newline policies + - Guard repository scripts against platform-dependent subprocess and file I/O +- Enforce complete Python type annotations [`b2be4e7`](https://github.com/acgetchell/la-stack/commit/b2be4e73c19d0566efd9d7854e325375287c5e83) + - Enable missing-annotation checks for function parameters and methods + - Format and type-check repository-owned Python fixtures alongside scripts + - Preserve intentional negative fixtures with narrow lint suppressions +- Enforce Python type-only import linting [`dd3d399`](https://github.com/acgetchell/la-stack/commit/dd3d399bf181aea7697c0cca1b6a60f67a39cd2b) + - Apply Ruff's TC rules to Python static-analysis fixtures. + - Keep annotation-only dependencies out of runtime imports. +- Enforce complete Python fixture linting [`ebc45fe`](https://github.com/acgetchell/la-stack/commit/ebc45fefeb99eec72c13c939d3eb5c3505bf1114) + - Run the full configured Ruff policy over Python Semgrep fixtures in canonical CI. + - Isolate deliberate fixture violations with narrow per-file suppressions. + - Exclude static-analysis fixtures from CodeRabbit review and leave docstring policy to Ruff. +- [**breaking**] Harden rational APIs and release comparisons + [`d8f9897`](https://github.com/acgetchell/la-stack/commit/d8f9897f59cce0a220efdbbcbaaf9180861889e9) + - canonicalize signed and unreduced rational inputs at construction boundaries + - preserve invariant-bearing RationalVector solutions across both exact input domains + - retain typed singularity, conversion, and runtime-dispatch diagnostics + - make release comparisons capability-aware for pre-rational benchmark baselines + - clarify exact-input guarantees, f64 precision loss, and benchmark provenance +- Make rational comparisons fair and backward-compatible [`67afc8e`](https://github.com/acgetchell/la-stack/commit/67afc8e61345e1993680c315223e544ea1800937) + - Exclude input cloning from consuming BigRational reference timings. + - Support schema-1 artifacts that predate rational-input provenance. + - Omit unsupported rational-input rows from legacy coverage checks. +- Avoid false certificate logging alerts [`d8d21db`](https://github.com/acgetchell/la-stack/commit/d8d21dbf76d7a4fa3ba15f37a6086179e7394976) + - Rename numerical-bound locals so CodeQL does not mistake them for sensitive certificate data. + - Document finite bound invariants, the affine error formula, and typed failure contexts. + - Make proof-range and second-FMA overflow expectations explicit. +- Complete benchmark CI and improve documentation navigation [`ee1c60f`](https://github.com/acgetchell/la-stack/commit/ee1c60f72a7570deae10aa90e54141c9422e4322) + - Allow the full exact benchmark suite to finish while preserving normal sampling and skipping unused plots. + - Select successful main baselines and report incomplete comparisons accurately. + - Add a canonical 5×5 quickstart, linked feature summaries, Contents, and a Documentation Map. + - Move detailed examples and numerical contracts into rustdoc guides. + - Record README, docs.rs, and GitHub documentation conventions. + - Document numerical logging false positives and the outstanding paste maintenance advisory. + - Update cargo-llvm-cov and rumdl tool pins. +- Correct Windows Markdown checks and benchmark summaries [`e7ca1fe`](https://github.com/acgetchell/la-stack/commit/e7ca1fe2bcd172d4000434b87ce9d511ac7a1487) + - Count Unicode characters consistently to prevent false Markdown line-length failures on Windows. + - Report benchmark comparisons as unavailable when baseline coverage is missing or incomplete. + - Stabilize Documentation Map navigation across GitHub and rustdoc. + - Link exact determinant filtering to det_direct_with_errbound(). +- Align zizmor audits and harden release cache isolation [`ee091c3`](https://github.com/acgetchell/la-stack/commit/ee091c36e8c6bff299f3536aba6c05ec5c7f659d) + - Synchronize local and CI zizmor versions and personas, enable authenticated online audits, and clearly report offline fallback. + - Remove dependency and tool caches from release benchmark production while preserving separate producer and publisher permissions. + - Enforce scanner-version and release-cache policies with Semgrep. + - Reorganize README, references, and mathematical guidance with early API selection, alphabetized methods, and stable thematic citations. + - Expand algorithm references, determinant-bound derivations, and numerical contracts for exact conversion, intervals, and scaled products. + - Trim AGENTS.md into focused linked guides and document file ownership. + - Establish documentation filename conventions and align coverage navigation, performance-report links, and generator output paths. +- Verify zizmor version sources and clarify numerical docs [`421bcda`](https://github.com/acgetchell/la-stack/commit/421bcdae365145eb2e32e5087e4ef50d1989c43a) + - Require the zizmor resolver to read the canonical justfile pin and publish it without substituting a hard-coded or unrelated version. + - Point README mathematical-basis links to the main branch. + - Define roundoff-bound notation explicitly, including binary64 unit roundoff and the D and 2D reduction counts. + - Document non-finite factor rejection in ScaledProduct. + - Exempt intentional Semgrep fixtures from the algebraic-operation prohibition while retaining it for other repository-owned Rust. +- Budget and validate release Criterion baselines [`42a3e1f`](https://github.com/acgetchell/la-stack/commit/42a3e1fc2f4db0fee13e7ae2a72295ec7286934f) + - Allow 150 minutes for comparative benchmarks and 90 minutes for exact benchmarks within a 285-minute job, preserving full Criterion sampling. + - Require complete, valid raw measurements and matching saved baselines before packaging the archive with its benchmark inventory. + - Report suite runtimes and support manual runs without release publication. + - Specify the repository explicitly when uploading release assets. + - Document runtime estimates, headroom, and pre-release verification. +- Enforce benchmark setup limits and improve README navigation + [`d8382ea`](https://github.com/acgetchell/la-stack/commit/d8382eac0b6b467ea390ea04a5ec04fb4600bc8a) + - Limit checkout to 2 minutes and share a 28-minute timeout across tool installation, input validation, and benchmark inventory. + - Align budget documentation with the enforced setup limits. + - Place scalar types, API navigation, and features after Quickstart, move Examples before Benchmarks, and update the Contents list. + - Sort feature flags, scalar domains, documentation links, examples, and their run commands lexicographically. +- Attach benchmark baselines before publishing releases [`0ddf9cf`](https://github.com/acgetchell/la-stack/commit/0ddf9cf31e65a41ddeff2fc996f84222c1f19ebf) + - Require an explicit stable tag and a matching mutable draft release. + - Benchmark the resolved tag commit and verify the uploaded archive's size and SHA-256 digest before publishing the draft. + - Reuse matching draft assets on publisher retries without overwriting conflicting assets or modifying published releases. + - Require fresh draft checks when rerunning benchmarks. + - Document draft creation, workflow dispatch, and failed-run recovery. +- Isolate release benchmarks from default-branch caches [`d9434f2`](https://github.com/acgetchell/la-stack/commit/d9434f2cfcf20c05a898228e563fd0d1eee63632) + - Run benchmarks from the release tag and check out the workflow's own commit to keep execution in that tag's cache scope. + - Reject mismatched dispatch refs and tags moved since dispatch. + - Update release instructions to use --ref "$TAG" instead of main. +- Correct interval bounds and support mutable dispatch captures + [`3fb215b`](https://github.com/acgetchell/la-stack/commit/3fb215b6dcbc17d5ed209b4b35a6038d8e0362af) + - Use magnitude-ordered FastTwoSum to avoid spurious non-finite errors in interval addition and subtraction near f64::MAX. + - Allow dimension-dispatch macro bodies to mutate captures while preserving support for consuming closures. + - Skip redundant GCD work when clearing rational denominators. + - Clarify numerical certificates, error provenance, and mutation guarantees in API documentation. + - Sort README API entries and document the existing Gram benchmark suite. + +### Maintenance + +- Tighten dependency-update tooling and diagnostics [`7e845d1`](https://github.com/acgetchell/la-stack/commit/7e845d12c7ad4a9d4dffb01740b5016098aa09ef) + + - add `cargo-update` to pinned tool setup and include it in `just update` maintenance flow + - make archive, benchmark, and tag release scripts emit safer error handling with preserved sub-exception diagnostics + - strengthen SemVer and ordering validation paths in tool scripts to fail fast with clearer messages + - refresh contributor/release docs and exact-api docs for updated setup/update expectations + - normalize and simplify exact-module test structure without changing runtime behavior + +### Performance + +- Characterize rational row-clearing allocation costs [`2688964`](https://github.com/acgetchell/la-stack/commit/2688964817484f3466f1cff733eff04e1b26e857) + + - Add small and wide-component rational benchmark fixtures across D=2–8. + - Isolate component cloning and integer scaling costs from complete determinant, sign, and solve operations. + - Publish allocation and timing data with provenance and reproduction steps supporting the existing borrowed implementation. +- [**breaking**] Optimize exact conversion and dense 4D determinants + [`7fd6d8e`](https://github.com/acgetchell/la-stack/commit/7fd6d8efd3cf6c12be5a591d87addd6e4961fa82) + - Avoid redundant fraction reduction in strict RationalVector conversion. + - Share minors in dense exact 4×4 determinants while preserving the sparse fast path. + - Add adversarial solve benchmarks across D=2,3,4,5,8,16,32,64 and exact-arithmetic diagnostics. + - Include Gaussian reference working-copy costs in benchmark timings. + - Document the decision to retain existing LU/LDLT solve finalization after finding no repeatable speedup. + - Align tooling with Rust 1.98.1 and refresh dependency and tool pins. + ## [0.4.5] - 2026-08-21 ### ⚠️ Breaking Changes -- Unify local and release performance workflows -- Require Rust 1.97.1 -- Require Rust 1.98.0 +- la-stack now requires Rust 1.97.1. +- rename performance-rerender to performance-doc and performance-local-vs-linalg to performance-local-non-exact, replace --rerender with --promote-artifacts, + and remove performance-archive-published. +- la-stack now requires Rust 1.98.0. ### Merged Pull Requests @@ -120,8 +331,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### ⚠️ Breaking Changes -- Make numerical invariants and errors explicit -- Require Rust 1.97.0 +- Rename `Tolerance::new` to `Tolerance::try_new` and `Matrix::get_checked` to `Matrix::try_get` ; remove `Matrix::set_checked` in favor of `Matrix::set` . + `Vector::dot` and `Vector::norm2_sq` now borrow their operands. `det_sign_exact` is now infallible and returns `DeterminantSign` instead of + `Result` . `LaError` variants now use typed reason, location, and origin fields and require `..` in downstream matches. LDLT now requires exact + symmetry, determinant error bounds may be unavailable under gradual underflow, and `ERR_COEFF_2` , `ERR_COEFF_3` , and `ERR_COEFF_4` are no longer exported by + the prelude. +- Rust versions earlier than 1.97.0 are no longer supported. ### Added @@ -227,7 +442,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### ⚠️ Breaking Changes -- Make exact f64 conversions strict +- det_exact_f64 and solve_exact_f64 now return LaError::Unrepresentable instead of rounding or reporting Overflow for exact values that cannot be represented + exactly as finite f64. Call det_exact_rounded_f64 or solve_exact_rounded_f64 to opt into rounded finite f64 results. +- strict exact-to-f64 APIs now return LaError::Unrepresentable instead of silently rounding, public Matrix and Vector construction is fallible, and the previous + finite proof wrapper APIs are removed. ### Added @@ -891,6 +1109,7 @@ Older releases are archived by minor series: - [0.2.x](docs/archive/changelog/0.2.md) - [0.1.x](docs/archive/changelog/0.1.md) +[0.4.6]: https://github.com/acgetchell/la-stack/compare/v0.4.5...v0.4.6 [0.4.5]: https://github.com/acgetchell/la-stack/compare/v0.4.4...v0.4.5 [0.4.4]: https://github.com/acgetchell/la-stack/compare/v0.4.3...v0.4.4 [0.4.3]: https://github.com/acgetchell/la-stack/compare/v0.4.2...v0.4.3 diff --git a/CITATION.cff b/CITATION.cff index 05441db..b707a4e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,8 +2,8 @@ cff-version: 1.2.0 message: "If you use this software, please cite it as below." type: software title: "la-stack: Fast, stack-allocated linear algebra for fixed dimensions in Rust" -version: 0.4.5 -date-released: 2026-08-21 +version: 0.4.6 +date-released: 2026-09-08 url: "https://github.com/acgetchell/la-stack" repository-code: "https://github.com/acgetchell/la-stack" doi: "10.5281/zenodo.18158926" diff --git a/Cargo.lock b/Cargo.lock index 22ded94..8490fa6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,13 +645,11 @@ dependencies = [ [[package]] name = "la-stack" -version = "0.4.5" +version = "0.4.6" dependencies = [ "allocation-counter", "approx", "criterion", - "faer", - "nalgebra", "num-bigint", "num-rational", "num-traits", @@ -659,6 +657,17 @@ dependencies = [ "proptest", ] +[[package]] +name = "la-stack-comparison" +version = "0.0.0" +dependencies = [ + "approx", + "criterion", + "faer", + "la-stack", + "nalgebra", +] + [[package]] name = "libc" version = "0.2.189" diff --git a/Cargo.toml b/Cargo.toml index 540f037..eb78050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "la-stack" -version = "0.4.5" +version = "0.4.6" edition = "2024" rust-version = "1.98.1" +autobenches = false license = "BSD-3-Clause" description = "Fast, stack-allocated linear algebra for fixed dimensions" readme = "README.md" @@ -45,8 +46,6 @@ num-traits = { version = "0.2.19", optional = true } allocation-counter = "0.8.1" approx = "0.5.1" criterion = { version = "0.8.2", features = [ "html_reports" ] } -faer = { version = "0.24.4", default-features = false, features = [ "std", "linalg" ] } -nalgebra = { version = "0.35.0", default-features = false, features = [ "std" ] } pastey = "0.2.3" proptest = "1.11.0" @@ -72,11 +71,6 @@ required-features = [ "exact" ] name = "rational_input_5x5" required-features = [ "exact" ] -[[bench]] -name = "vs_linalg" -harness = false -required-features = [ "bench" ] - [[bench]] name = "exact" harness = false @@ -105,19 +99,27 @@ codegen-units = 1 features = [ "exact" ] rustdoc-args = [ "--cfg", "docsrs" ] -[lints.rust] +[workspace] +members = [ "benches/comparison" ] +default-members = [ "." ] +resolver = "3" + +[lints] +workspace = true + +[workspace.lints.rust] warnings = { level = "deny", priority = -1 } unsafe_code = "forbid" missing_docs = { level = "deny", priority = 0 } dead_code = { level = "deny", priority = 0 } unreachable_pub = { level = "deny", priority = 0 } -unexpected_cfgs = { level = "deny", priority = 0, check-cfg = [ 'cfg(docsrs)', 'cfg(la_stack_pre_rational_input_api)', 'cfg(la_stack_v0_4_3_api)' ] } +unexpected_cfgs = { level = "deny", priority = 0, check-cfg = [ 'cfg(docsrs)', 'cfg(la_stack_pre_rational_input_api)' ] } -[lints.rustdoc] +[workspace.lints.rustdoc] bare_urls = "deny" broken_intra_doc_links = "deny" -[lints.clippy] +[workspace.lints.clippy] cargo = { level = "warn", priority = -1 } extra_unused_type_parameters = "warn" nursery = { level = "warn", priority = -1 } diff --git a/README.md b/README.md index df47a8d..7adfbf1 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18158926.svg)](https://doi.org/10.5281/zenodo.18158926) [![Crates.io](https://badgen.net/crates/v/la-stack)](https://crates.io/crates/la-stack) [![Downloads](https://badgen.net/crates/d/la-stack)](https://crates.io/crates/la-stack) -[![License](https://badgen.net/github/license/acgetchell/la-stack)](https://github.com/acgetchell/la-stack/blob/v0.4.5/LICENSE) +[![License](https://badgen.net/github/license/acgetchell/la-stack)](https://github.com/acgetchell/la-stack/blob/v0.4.6/LICENSE) [![Docs.rs](https://docs.rs/la-stack/badge.svg)](https://docs.rs/la-stack) [![CI](https://github.com/acgetchell/la-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/acgetchell/la-stack/actions/workflows/ci.yml) [![rust-clippy analyze][clippy-badge]][clippy-workflow] @@ -92,7 +92,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -la-stack = "0.4.5" +la-stack = "0.4.6" ``` ### Solve a 5×5 system @@ -229,7 +229,7 @@ Enable exact determinant signs, determinant values, and solves: ```toml [dependencies] -la-stack = { version = "0.4.5", features = ["exact"] } +la-stack = { version = "0.4.6", features = ["exact"] } ``` `Matrix` / `Vector` exact methods preserve stored `f64` values; @@ -338,9 +338,9 @@ for the algorithms, validity boundaries, and supporting references. - ✅ No runtime dependencies by default (optional features may add deps) - ✅ `unsafe` forbidden -See [CHANGELOG.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/CHANGELOG.md) +See [CHANGELOG.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/CHANGELOG.md) for release history and -[docs/roadmap.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/roadmap.md) +[docs/roadmap.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/roadmap.md) for current release planning. ## 🚫 Anti-goals @@ -361,12 +361,12 @@ for current release planning. ## 🗺️ Documentation Map - [API guide][api-guide] — worked examples, API selection, storage, and error contracts. -- [Benchmarking](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/BENCHMARKING.md) — benchmark suites, comparison workflows, and measurement methodology. +- [Benchmarking](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/BENCHMARKING.md) — benchmark suites, comparison workflows, and measurement methodology. - [Coverage](https://github.com/acgetchell/la-stack/blob/main/docs/MEASURING_COVERAGE.md) — local and CI coverage commands and report locations. - [Mathematical basis](https://github.com/acgetchell/la-stack/blob/main/docs/mathematical_basis.md) — algorithms, numerical guarantees, and limitations. - [Performance reports](https://github.com/acgetchell/la-stack/blob/main/docs/performance.md) — release-to-release measurement results and provenance. -- [Releasing](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/RELEASING.md) — release preparation, validation, and publication. -- [Roadmap](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/roadmap.md) — release planning, future directions, and non-goals. +- [Releasing](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/RELEASING.md) — release preparation, validation, and publication. +- [Roadmap](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/roadmap.md) — release planning, future directions, and non-goals. ## 📋 Examples @@ -399,7 +399,7 @@ cargo run --example solve_5x5 ![LU solve (factor + solve): median time vs dimension][lu-solve-benchmark] Raw data: -[docs/assets/bench/vs_linalg_lu_solve_median.csv](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/assets/bench/vs_linalg_lu_solve_median.csv) +[docs/assets/bench/vs_linalg_lu_solve_median.csv](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/assets/bench/vs_linalg_lu_solve_median.csv) Measurement provenance: [docs/assets/bench/vs_linalg_lu_solve_median.provenance.json][benchmark-provenance] @@ -421,7 +421,7 @@ README table, and provenance together. For the full per-kernel comparison methodology, algorithm citations, input construction, and release-comparison workflow details, see -[docs/BENCHMARKING.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/BENCHMARKING.md). +[docs/BENCHMARKING.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/BENCHMARKING.md). For the current release-to-release performance snapshot, see [docs/performance.md](https://github.com/acgetchell/la-stack/blob/main/docs/performance.md). The exact release suite includes the already-exact rational-input groups for @@ -445,14 +445,14 @@ expectations are validated outside the timed closures. | D | la-stack median (ns) | nalgebra median (ns) | faer median (ns) | reduction vs nalgebra (point est.) | reduction vs faer (point est.) | |---:|--------------------:|--------------------:|----------------:|---------------------:|----------------:| -| 2 | 2.044 | 4.601 | 151.939 | +55.6% | +98.7% | -| 3 | 9.989 | 23.513 | 196.357 | +57.5% | +94.9% | -| 4 | 21.865 | 54.716 | 223.910 | +60.0% | +90.2% | -| 5 | 44.510 | 71.219 | 293.420 | +37.5% | +84.8% | -| 8 | 145.405 | 188.352 | 381.872 | +22.8% | +61.9% | -| 16 | 672.491 | 585.261 | 897.236 | -14.9% | +25.0% | -| 32 | 2,777.707 | 2,501.361 | 2,952.778 | -11.0% | +5.9% | -| 64 | 17,357.785 | 13,878.401 | 12,199.761 | -25.1% | -42.3% | +| 2 | 2.021 | 4.479 | 182.532 | +54.9% | +98.9% | +| 3 | 9.977 | 22.795 | 217.567 | +56.2% | +95.4% | +| 4 | 22.101 | 51.739 | 241.525 | +57.3% | +90.8% | +| 5 | 46.070 | 69.003 | 326.848 | +33.2% | +85.9% | +| 8 | 128.364 | 165.933 | 401.400 | +22.6% | +68.0% | +| 16 | 643.532 | 569.446 | 903.140 | -13.0% | +28.7% | +| 32 | 2,755.773 | 2,710.235 | 2,919.290 | -1.7% | +5.6% | +| 64 | 17,518.634 | 14,313.979 | 12,108.783 | -22.4% | -44.7% | @@ -486,12 +486,12 @@ aligned with the local comprehensive validation path. For coverage commands and report locations, see [`docs/MEASURING_COVERAGE.md`](https://github.com/acgetchell/la-stack/blob/main/docs/MEASURING_COVERAGE.md). For the full contributor workflow, see -[CONTRIBUTING.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/CONTRIBUTING.md). +[CONTRIBUTING.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/CONTRIBUTING.md). ## 📚 Citation If you use this library in academic work, please cite it using -[CITATION.cff](https://github.com/acgetchell/la-stack/blob/v0.4.5/CITATION.cff) +[CITATION.cff](https://github.com/acgetchell/la-stack/blob/v0.4.6/CITATION.cff) (or GitHub's "Cite this repository" feature). Tagged releases are archived on Zenodo under the [all-versions concept DOI](https://doi.org/10.5281/zenodo.18158926). @@ -499,26 +499,26 @@ Zenodo under the ## 🔎 References For canonical references to the algorithms used by this crate, see -[REFERENCES.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/REFERENCES.md). +[REFERENCES.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/REFERENCES.md). ## 🤖 AI Agents AI coding assistants should read -[AGENTS.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/AGENTS.md) +[AGENTS.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/AGENTS.md) before proposing or applying changes. See -[CONTRIBUTING.md](https://github.com/acgetchell/la-stack/blob/v0.4.5/CONTRIBUTING.md) +[CONTRIBUTING.md](https://github.com/acgetchell/la-stack/blob/v0.4.6/CONTRIBUTING.md) for the repository's AI-assisted development note. ## 📜 License -BSD 3-Clause License. See [LICENSE](https://github.com/acgetchell/la-stack/blob/v0.4.5/LICENSE). +BSD 3-Clause License. See [LICENSE](https://github.com/acgetchell/la-stack/blob/v0.4.6/LICENSE). [audit-badge]: https://github.com/acgetchell/la-stack/actions/workflows/audit.yml/badge.svg [audit-workflow]: https://github.com/acgetchell/la-stack/actions/workflows/audit.yml -[benchmark-provenance]: https://github.com/acgetchell/la-stack/blob/v0.4.5/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json +[benchmark-provenance]: https://github.com/acgetchell/la-stack/blob/v0.4.6/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json [clippy-badge]: https://github.com/acgetchell/la-stack/actions/workflows/rust-clippy.yml/badge.svg [clippy-workflow]: https://github.com/acgetchell/la-stack/actions/workflows/rust-clippy.yml -[lu-solve-benchmark]: https://raw.githubusercontent.com/acgetchell/la-stack/v0.4.5/docs/assets/bench/vs_linalg_lu_solve_median.svg +[lu-solve-benchmark]: https://raw.githubusercontent.com/acgetchell/la-stack/v0.4.6/docs/assets/bench/vs_linalg_lu_solve_median.svg [refs-det-bound]: https://github.com/acgetchell/la-stack/blob/main/REFERENCES.md#absolute-error-bound-for-closed-form-determinants [refs-exact-sign]: https://github.com/acgetchell/la-stack/blob/main/REFERENCES.md#exact-determinant-sign-adaptive-precision-integer-arithmetic [refs-exact-solve]: https://github.com/acgetchell/la-stack/blob/main/REFERENCES.md#exact-linear-system-solve-hybrid-bareiss--bigrational diff --git a/benches/common/exact.rs b/benches/common/exact.rs index 2ba383a..ebbcc15 100644 --- a/benches/common/exact.rs +++ b/benches/common/exact.rs @@ -149,28 +149,13 @@ impl ValidatedExactInput { } } -/// Return one matrix entry through the bounds-checked API shared by current and -/// v0.4.3 releases. +/// Return one matrix entry through the bounds-checked API. fn stored_matrix_entry(matrix: &Matrix, row: usize, col: usize) -> f64 { matrix .get(row, col) .unwrap_or_else(|| panic!("matrix entry ({row}, {col}) is outside dimension {D}")) } -/// Normalize the exact determinant-sign API across the v0.4.3 compatibility -/// boundary used only by historical benchmark worktrees. -#[cfg(not(la_stack_v0_4_3_api))] -fn checked_det_sign(matrix: &Matrix) -> i8 { - matrix.det_sign_exact().as_i8() -} - -#[cfg(la_stack_v0_4_3_api)] -fn checked_det_sign(matrix: &Matrix) -> i8 { - matrix - .det_sign_exact() - .or_abort("exact determinant sign oracle check") -} - /// Return a deterministic, strictly diagonally-dominant matrix entry. #[inline] #[expect( @@ -532,7 +517,6 @@ pub fn validate_f64_determinant_benchmarks(input: &ValidatedExac "direct determinant error {observed_error} exceeds standalone certified bound {certified_bound}", ); - #[cfg(not(la_stack_v0_4_3_api))] { let estimate = input .matrix() @@ -558,7 +542,6 @@ pub fn validate_f64_determinant_benchmarks(input: &ValidatedExac "det_errbound unexpectedly supports D={D}", ); - #[cfg(not(la_stack_v0_4_3_api))] assert!( input .matrix() @@ -603,7 +586,7 @@ pub fn validate_exact_fixture(input: ExactInput) -> Validated determinant ); assert_eq!( - checked_det_sign(&input.matrix), + input.matrix.det_sign_exact().as_i8(), determinant_sign(&determinant) ); assert_strict_scalar(input.matrix.det_exact_f64(), &determinant, None); @@ -613,21 +596,22 @@ pub fn validate_exact_fixture(input: ExactInput) -> Validated .matrix .solve_exact(input.rhs) .or_abort("exact solve oracle check"); - assert_exact_residual(&input, solution.as_array()); + // Historical releases return the rational array directly instead of a wrapper. + #[cfg(la_stack_pre_rational_input_api)] + let solution = &solution; + #[cfg(not(la_stack_pre_rational_input_api))] + let solution = solution.as_array(); + assert_exact_residual(&input, solution); let strict_solution = input.matrix.solve_exact_f64(input.rhs); - let first_failure = solution - .as_array() - .iter() - .enumerate() - .find_map(|(index, value)| { - expected_strict_f64(value) - .err() - .map(|reason| (index, reason)) - }); + let first_failure = solution.iter().enumerate().find_map(|(index, value)| { + expected_strict_f64(value) + .err() + .map(|reason| (index, reason)) + }); match (strict_solution, first_failure) { (Ok(actual), None) => { - for (index, exact) in solution.as_array().iter().enumerate() { + for (index, exact) in solution.iter().enumerate() { let Ok(expected) = expected_strict_f64(exact) else { panic!("strict solution component {index} unexpectedly requires rounding"); }; @@ -654,7 +638,6 @@ pub fn validate_exact_fixture(input: ExactInput) -> Validated let rounding_limit = finite_rounding_limit(); let first_rounded_failure = solution - .as_array() .iter() .position(|exact| exact.abs() >= rounding_limit); match ( @@ -662,7 +645,7 @@ pub fn validate_exact_fixture(input: ExactInput) -> Validated first_rounded_failure, ) { (Ok(rounded), None) => { - for (actual, exact) in rounded.as_array().iter().copied().zip(solution.as_array()) { + for (actual, exact) in rounded.as_array().iter().copied().zip(solution) { assert_nearest_even_f64(actual, exact); } } diff --git a/benches/common/vs_linalg.rs b/benches/common/vs_linalg.rs index bfadb5a..9d6f5d8 100644 --- a/benches/common/vs_linalg.rs +++ b/benches/common/vs_linalg.rs @@ -10,41 +10,14 @@ use nalgebra::SMatrix; use la_stack::{LaError, Matrix, Tolerance, Vector}; -#[cfg(not(la_stack_v0_4_3_api))] use crate::bench_utils::OrAbort; -/// Evaluate la-stack's dot product through the ownership contract used by the -/// selected library revision. -/// -/// # Errors -/// -/// Returns the selected revision's typed error if finite inputs overflow during -/// dot-product accumulation. -#[cfg(not(la_stack_v0_4_3_api))] -#[inline] -pub fn la_stack_dot(left: &Vector, right: &Vector) -> Result { - left.dot(right) -} - -/// Evaluate the v0.4.3 by-value dot-product API without changing benchmark -/// inputs or the mathematical operation. -/// -/// # Errors -/// -/// Returns v0.4.3's typed error if finite inputs overflow during dot-product -/// accumulation. -#[cfg(la_stack_v0_4_3_api)] -#[inline] -pub fn la_stack_dot(left: &Vector, right: &Vector) -> Result { - (*left).dot(*right) -} - /// Evaluate the squared norm through the current public API. /// /// # Errors /// /// Returns the library's typed error if squared-norm accumulation overflows. -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[inline] pub const fn la_stack_norm_squared(vector: &Vector) -> Result { vector.norm_squared() @@ -57,7 +30,7 @@ pub const fn la_stack_norm_squared(vector: &Vector) -> Result /// # Errors /// /// Returns the selected revision's typed error if squared-norm accumulation overflows. -#[cfg(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api))] +#[cfg(la_stack_pre_rational_input_api)] #[inline] pub const fn la_stack_norm_squared(vector: &Vector) -> Result { vector.norm2_sq() @@ -68,7 +41,7 @@ pub const fn la_stack_norm_squared(vector: &Vector) -> Result /// # Errors /// /// Returns the library's typed error if an absolute row sum overflows. -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[inline] pub const fn la_stack_norm_inf(matrix: &Matrix) -> Result { matrix.norm_inf() @@ -81,35 +54,12 @@ pub const fn la_stack_norm_inf(matrix: &Matrix) -> Result(matrix: &Matrix) -> Result { matrix.inf_norm() } -/// Parse a tolerance through the constructor exposed by the selected library -/// revision. -/// -/// # Errors -/// -/// Returns a typed error when `value` is negative or non-finite. -#[cfg(not(la_stack_v0_4_3_api))] -#[inline] -pub const fn la_stack_tolerance(value: f64) -> Result { - Tolerance::try_new(value) -} - -/// Parse a tolerance through v0.4.3's pre-`try_` constructor name. -/// -/// # Errors -/// -/// Returns a typed error when `value` is negative or non-finite. -#[cfg(la_stack_v0_4_3_api)] -#[inline] -pub const fn la_stack_tolerance(value: f64) -> Result { - Tolerance::new(value) -} - /// Return `det(P)` for faer's permutation representation. /// /// Sign(det(P)) is +1 for even permutations and -1 for odd. Parity is computed @@ -251,7 +201,6 @@ pub fn make_pivoting_matrix_rows() -> [[f64; D]; D] { /// Diagnostic solve families, separate from the headline comparison matrix. #[derive(Clone, Copy, Debug)] -#[cfg(not(la_stack_v0_4_3_api))] pub enum LuSolveScenario { /// Rotate the well-conditioned rows, requiring repeated LU row swaps. Pivoting, @@ -259,7 +208,6 @@ pub enum LuSolveScenario { DenseIllConditioned, } -#[cfg(not(la_stack_v0_4_3_api))] impl LuSolveScenario { /// Stable diagnostic group label. #[must_use] @@ -273,14 +221,12 @@ impl LuSolveScenario { /// A diagnostic system checked against a known solution and a scaled residual. #[must_use] -#[cfg(not(la_stack_v0_4_3_api))] pub struct ValidatedLuSolveInput { matrix: Matrix, rhs: Vector, expected: [f64; D], } -#[cfg(not(la_stack_v0_4_3_api))] impl ValidatedLuSolveInput { /// Borrow the finite matrix. pub const fn matrix(&self) -> &Matrix { @@ -326,7 +272,6 @@ impl ValidatedLuSolveInput { /// /// # Panics /// Panics for dimensions outside the diagnostic domain or a failed oracle check. -#[cfg(not(la_stack_v0_4_3_api))] pub fn validated_lu_solve_input( scenario: LuSolveScenario, ) -> ValidatedLuSolveInput { @@ -354,7 +299,7 @@ pub fn validated_lu_solve_input( }; let solution = input .matrix - .lu(la_stack_tolerance(0.0).or_abort("diagnostic tolerance")) + .lu(Tolerance::try_new(0.0).or_abort("diagnostic tolerance")) .or_abort("diagnostic LU") .solve(input.rhs) .or_abort("diagnostic solve"); diff --git a/benches/comparison/Cargo.toml b/benches/comparison/Cargo.toml new file mode 100644 index 0000000..e5dfce2 --- /dev/null +++ b/benches/comparison/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "la-stack-comparison" +version = "0.0.0" +edition = "2024" +rust-version = "1.98.1" +publish = false +autobenches = false + +[dev-dependencies] +approx = "0.5.1" +criterion = { version = "0.8.2", features = [ "html_reports" ] } +faer = { version = "0.24.4", default-features = false, features = [ "std", "linalg" ] } +la-stack = { path = "../.." } +nalgebra = { version = "0.35.0", default-features = false, features = [ "std" ] } + +[features] +bench = [ ] +exact = [ "la-stack/exact" ] + +[[bench]] +name = "vs_linalg" +path = "../vs_linalg.rs" +harness = false +required-features = [ "bench" ] + +[lints] +workspace = true diff --git a/tests/vs_linalg_inputs.rs b/benches/comparison/tests/vs_linalg_inputs.rs similarity index 93% rename from tests/vs_linalg_inputs.rs rename to benches/comparison/tests/vs_linalg_inputs.rs index 8340efa..d624cfe 100644 --- a/tests/vs_linalg_inputs.rs +++ b/benches/comparison/tests/vs_linalg_inputs.rs @@ -4,31 +4,32 @@ #![cfg(feature = "bench")] +use approx::assert_abs_diff_eq; +use faer::linalg::matmul::dot::inner_prod; use faer::linalg::solvers::Solve; use faer::mat::AsMatRef; use faer::perm::PermRef; -use faer::{Mat, Side}; +use faer::{Conj, Mat, Side}; use nalgebra::{Const, DimMin, SMatrix, SVector}; -#[cfg(all(feature = "exact", not(la_stack_v0_4_3_api)))] +#[cfg(feature = "exact")] use la_stack::ExactF64Conversion; -use la_stack::{DEFAULT_SINGULAR_TOL, Matrix, Vector}; +use la_stack::{DEFAULT_SINGULAR_TOL, Matrix, Tolerance, Vector}; -#[path = "../benches/common/bench_utils.rs"] +#[path = "../../common/bench_utils.rs"] mod bench_utils; -#[path = "../benches/common/vs_linalg.rs"] +#[path = "../../common/vs_linalg.rs"] pub mod vs_linalg_common; -#[cfg(not(la_stack_v0_4_3_api))] use vs_linalg_common::{ LuSolveScenario, make_balanced_dynamic_range_rows, validated_lu_solve_input, }; use vs_linalg_common::{ - PreparedFaerLuDet, faer_det_from_ldlt, faer_perm_sign, la_stack_dot, la_stack_norm_inf, - la_stack_norm_squared, la_stack_tolerance, make_ill_conditioned_matrix_rows, make_matrix_rows, + PreparedFaerLuDet, faer_det_from_ldlt, faer_perm_sign, la_stack_norm_inf, + la_stack_norm_squared, make_ill_conditioned_matrix_rows, make_matrix_rows, make_pivoting_matrix_rows, make_vector_array, matrix_entry, nalgebra_inf_norm, vector_entry, }; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use vs_linalg_common::{ delaunay_scaled_norm, iterative_hypot, make_norm_descending_array, make_norm_repeated_scale_array, make_norm_sparse_array, make_norm_wide_dynamic_range_array, @@ -77,7 +78,6 @@ fn assert_lu_agreement() where Const: DimMin, Output = Const>, { - #[cfg(not(la_stack_v0_4_3_api))] for scenario in [ LuSolveScenario::Pivoting, LuSolveScenario::DenseIllConditioned, @@ -208,13 +208,18 @@ fn assert_vector_operation_agreement() { let fv1 = Mat::::from_fn(D, 1, |i, _| vector_entry(i, 0.0)); let fv2 = Mat::::from_fn(D, 1, |i, _| vector_entry(i, 1.0)); - let la_dot = la_stack_dot(&v1, &v2).unwrap_or_else(|err| panic!("la_stack dot failed: {err}")); - assert_close("nalgebra_dot", nv1.dot(&nv2), la_dot); - let mut fa_dot = 0.0; - for i in 0..D { - fa_dot = fv1[(i, 0)].mul_add(fv2[(i, 0)], fa_dot); - } - assert_close("faer_dot", fa_dot, la_dot); + // The fixture is (1, ..., D) dotted with (2, ..., D + 1). + // Its exact integer value is sum k(k + 1) = D(D + 1)(D + 2)/3. + // All products and partial sums are exactly representable at D <= 64. + let dimension = i32::try_from(D).unwrap(); + let expected_dot = f64::from(dimension * (dimension + 1) * (dimension + 2) / 3); + let la_dot = v1 + .dot(&v2) + .unwrap_or_else(|err| panic!("la_stack dot failed: {err}")); + let fa_dot = inner_prod(fv1.col(0).transpose(), Conj::No, fv2.col(0), Conj::No); + assert_abs_diff_eq!(la_dot, expected_dot, epsilon = 0.0); + assert_abs_diff_eq!(nv1.dot(&nv2), expected_dot, epsilon = 0.0); + assert_abs_diff_eq!(fa_dot, expected_dot, epsilon = 0.0); let la_norm_squared = la_stack_norm_squared(&v1) .unwrap_or_else(|err| panic!("la_stack norm_squared failed: {err}")); @@ -222,7 +227,7 @@ fn assert_vector_operation_agreement() { let fa_norm_squared = fv1.as_mat_ref().squared_norm_l2(); assert_close("faer_norm2_sq", fa_norm_squared, la_norm_squared); - #[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] + #[cfg(not(la_stack_pre_rational_input_api))] { let la_norm = v1 .norm() @@ -253,7 +258,7 @@ fn assert_vector_operation_agreement() { } } -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[test] fn norm_scenario_inputs_cover_distinct_branch_and_range_profiles() { let descending = make_norm_descending_array::<8>(); @@ -366,7 +371,7 @@ fn ill_conditioned_fixture_is_fixed_positive_definite_d8() { #[test] fn stress_inputs_exercise_pivoting_conditioning_and_scaled_products() { - let zero_tolerance = la_stack_tolerance(0.0).unwrap(); + let zero_tolerance = Tolerance::try_new(0.0).unwrap(); let pivoting_rows = make_pivoting_matrix_rows::<8>(); assert!(pivoting_rows[1][0].abs() > pivoting_rows[0][0].abs()); @@ -382,9 +387,6 @@ fn stress_inputs_exercise_pivoting_conditioning_and_scaled_products() { // Bareiss-backed oracle is independent of the timed floating LU path. let baseline = Matrix::<8>::try_from_rows(make_matrix_rows::<8>()).unwrap(); let expected = -baseline.det_exact().unwrap(); - #[cfg(la_stack_v0_4_3_api)] - let expected_f64 = num_traits::ToPrimitive::to_f64(&expected).unwrap(); - #[cfg(not(la_stack_v0_4_3_api))] let expected_f64 = expected.to_rounded_f64().unwrap(); assert_close( "pivoting LU determinant against exact row-swap oracle", @@ -414,7 +416,6 @@ fn stress_inputs_exercise_pivoting_conditioning_and_scaled_products() { expected_ill_conditioned_det.to_bits() ); - #[cfg(not(la_stack_v0_4_3_api))] { let balanced = Matrix::<8>::try_from_rows(make_balanced_dynamic_range_rows()).unwrap(); assert_eq!(balanced.lu(zero_tolerance).unwrap().det(), Ok(1.0)); diff --git a/benches/exact.rs b/benches/exact.rs index d1ecb50..bbc57ca 100644 --- a/benches/exact.rs +++ b/benches/exact.rs @@ -35,7 +35,7 @@ use std::hint::black_box; use criterion::{BenchmarkGroup, Criterion, Throughput, measurement::WallTime}; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use la_stack::ExactF64Conversion; use la_stack::{Matrix, Vector}; @@ -44,11 +44,11 @@ mod bench_utils; #[path = "common/exact.rs"] pub mod exact_bench; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[path = "common/rational.rs"] pub mod rational_bench; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[path = "common/exact_diagnostics.rs"] pub mod exact_diagnostics; @@ -58,9 +58,9 @@ use exact_bench::{ large_entries_3x3_input, make_matrix_rows, make_random_input_corpus, make_vector_array, near_singular_3x3_input, validate_exact_fixture, validate_f64_determinant_benchmarks, }; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use exact_diagnostics::{ConversionKind, Det4Kind, canonical_conversion_input, exact_det4_input}; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use rational_bench::{ RationalInputKind, rational_determinant_gaussian, rational_input, rational_solve_gaussian, }; @@ -116,7 +116,7 @@ const CORPUS_AND_EXTREME_OPERATIONS: &[ExactOperation] = &[ /// Both algorithms measure a complete operation on borrowed, accepted input. /// The consuming Gaussian references therefore make their required working /// copies inside the timed closure, just as row clearing builds its workspace. -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] fn bench_rational_input(criterion: &mut Criterion, kind: RationalInputKind) { let input = rational_input::(kind); let group_name = match kind { @@ -299,7 +299,6 @@ fn bench_det_errbound( } /// Add the paired direct-determinant and certified-bound baseline. -#[cfg(not(la_stack_v0_4_3_api))] fn bench_det_direct_with_errbound( group: &mut BenchmarkGroup<'_, WallTime>, input: &ValidatedExactInput, @@ -324,7 +323,6 @@ fn bench_det_direct_with_errbound( macro_rules! register_det_filter_benchmarks { ($group:expr, $input:expr, supported) => {{ bench_det_direct(&mut $group, &$input); - #[cfg(not(la_stack_v0_4_3_api))] bench_det_direct_with_errbound(&mut $group, &$input); bench_det_errbound(&mut $group, &$input); }}; @@ -378,7 +376,7 @@ macro_rules! gen_random_corpus_benches_for_dim { }}; } -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] fn bench_canonical_conversion(c: &mut Criterion) { for kind in ConversionKind::ALL { let input = canonical_conversion_input::(kind); @@ -393,7 +391,7 @@ fn bench_canonical_conversion(c: &mut Criterion) { } } -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] fn bench_det4_diagnostics(c: &mut Criterion) { for kind in Det4Kind::ALL { let input = exact_det4_input(kind); @@ -436,7 +434,7 @@ fn main() { gen_random_corpus_benches_for_dim!(&mut c, 5); } - #[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] + #[cfg(not(la_stack_pre_rational_input_api))] { bench_canonical_conversion::<2>(&mut c); bench_canonical_conversion::<3>(&mut c); diff --git a/benches/vs_linalg.rs b/benches/vs_linalg.rs index 291286b..6432150 100644 --- a/benches/vs_linalg.rs +++ b/benches/vs_linalg.rs @@ -15,12 +15,13 @@ use std::hint::black_box; use criterion::measurement::WallTime; use criterion::{BenchmarkGroup, Criterion}; +use faer::linalg::matmul::dot::inner_prod; use faer::linalg::solvers::Solve; use faer::mat::AsMatRef; -use faer::{Mat, Side}; +use faer::{Conj, Mat, Side}; use nalgebra::{Const, DimMin, SMatrix, SVector}; -use la_stack::{DEFAULT_SINGULAR_TOL, Matrix, Vector}; +use la_stack::{DEFAULT_SINGULAR_TOL, Matrix, Tolerance, Vector}; #[path = "common/bench_utils.rs"] mod bench_utils; @@ -28,13 +29,12 @@ mod bench_utils; pub mod vs_linalg_common; use bench_utils::OrAbort; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use vs_linalg_common::norm_scenarios; -#[cfg(not(la_stack_v0_4_3_api))] use vs_linalg_common::{LuSolveScenario, validated_lu_solve_input}; use vs_linalg_common::{ - PreparedFaerLuDet, delaunay_scaled_norm, faer_det_from_ldlt, iterative_hypot, la_stack_dot, - la_stack_norm_inf, la_stack_norm_squared, la_stack_tolerance, make_balanced_dynamic_range_rows, + PreparedFaerLuDet, delaunay_scaled_norm, faer_det_from_ldlt, iterative_hypot, + la_stack_norm_inf, la_stack_norm_squared, make_balanced_dynamic_range_rows, make_ill_conditioned_matrix_rows, make_matrix_rows, make_pivoting_matrix_rows, make_vector_array, matrix_entry, nalgebra_inf_norm, vector_entry, }; @@ -423,7 +423,7 @@ fn register_vector_benchmarks(group: &mut BenchmarkGroup<'_, Wal group.bench_function("la_stack_dot", |bencher| { bencher.iter(|| { - let result = la_stack_dot(black_box(&v1), black_box(&v2)).or_abort("la_stack dot"); + let result = black_box(&v1).dot(black_box(&v2)).or_abort("la_stack dot"); black_box(result); }); }); @@ -435,15 +435,13 @@ fn register_vector_benchmarks(group: &mut BenchmarkGroup<'_, Wal }); }); - group.bench_function("faer_dot", |bencher| { + // Keep the native kernel distinct from historical scalar-loop measurements. + group.bench_function("faer_dot_native", |bencher| { bencher.iter(|| { - let mut sum = 0.0; let a = black_box(&fv1); let b = black_box(&fv2); - for i in 0..D { - sum = a[(i, 0)].mul_add(b[(i, 0)], sum); - } - black_box(sum); + let result = inner_prod(a.col(0).transpose(), Conj::No, b.col(0), Conj::No); + black_box(result); }); }); @@ -469,7 +467,7 @@ fn register_vector_benchmarks(group: &mut BenchmarkGroup<'_, Wal }); }); - #[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] + #[cfg(not(la_stack_pre_rational_input_api))] { group.bench_function("la_stack_norm2", |bencher| { bencher.iter(|| { @@ -509,7 +507,7 @@ fn register_vector_benchmarks(group: &mut BenchmarkGroup<'_, Wal } /// Validate and register safe Euclidean-norm kernels across branch and range profiles. -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] fn register_norm_scenario_benchmarks(group: &mut BenchmarkGroup<'_, WallTime>) { for (scenario, values) in norm_scenarios::() { let vector = Vector::try_new(values).or_abort("norm scenario vector construction"); @@ -598,12 +596,11 @@ fn register_matrix_norm_benchmarks(group: &mut BenchmarkGroup<'_ /// Register D=8 stress cases that exercise pivoting, conditioning, and scaled products. fn register_stress_benchmarks(group: &mut BenchmarkGroup<'_, WallTime>) { - let zero_tolerance = la_stack_tolerance(0.0).or_abort("zero benchmark tolerance"); + let zero_tolerance = Tolerance::try_new(0.0).or_abort("zero benchmark tolerance"); let pivoting = Matrix::<8>::try_from_rows(make_pivoting_matrix_rows()) .or_abort("pivoting benchmark matrix construction"); let ill_conditioned = Matrix::<8>::try_from_rows(make_ill_conditioned_matrix_rows()) .or_abort("ill-conditioned benchmark matrix construction"); - #[cfg(not(la_stack_v0_4_3_api))] let balanced = Matrix::<8>::try_from_rows(make_balanced_dynamic_range_rows()) .or_abort("balanced-range benchmark matrix construction"); @@ -634,16 +631,13 @@ fn register_stress_benchmarks(group: &mut BenchmarkGroup<'_, WallTime>) { }); }); - #[cfg(not(la_stack_v0_4_3_api))] let balanced_lu = balanced .lu(zero_tolerance) .or_abort("balanced-range LU factorization"); - #[cfg(not(la_stack_v0_4_3_api))] let balanced_ldlt = balanced .ldlt(zero_tolerance) .or_abort("balanced-range LDLT factorization"); - #[cfg(not(la_stack_v0_4_3_api))] group.bench_function("la_stack_det_from_lu_balanced_range", |bencher| { bencher.iter(|| { let det = black_box(&balanced_lu) @@ -653,7 +647,6 @@ fn register_stress_benchmarks(group: &mut BenchmarkGroup<'_, WallTime>) { }); }); - #[cfg(not(la_stack_v0_4_3_api))] group.bench_function("la_stack_det_from_ldlt_balanced_range", |bencher| { bencher.iter(|| { let det = black_box(&balanced_ldlt) @@ -665,7 +658,6 @@ fn register_stress_benchmarks(group: &mut BenchmarkGroup<'_, WallTime>) { } /// Complete and reusable-factor solves on validated diagnostic systems. -#[cfg(not(la_stack_v0_4_3_api))] fn register_lu_solve_diagnostics(c: &mut Criterion) where Const: DimMin, Output = Const>, @@ -677,7 +669,7 @@ where let input = validated_lu_solve_input::(scenario); let a = *input.matrix(); let rhs = input.rhs(); - let zero = la_stack_tolerance(0.0).or_abort("diagnostic tolerance"); + let zero = Tolerance::try_new(0.0).or_abort("diagnostic tolerance"); let lu = a.lu(zero).or_abort("diagnostic LU"); let na = SMatrix::::from_fn(|i, j| a.as_rows()[i][j]); let nrhs = SVector::::from_fn(|i, _| rhs.as_array()[i]); @@ -754,7 +746,7 @@ macro_rules! define_vs_linalg_benches_for_dim { register_precomputed_lu_determinant_benchmarks::<$d>(&mut group); register_precomputed_ldlt_determinant_benchmarks::<$d>(&mut group); register_vector_benchmarks::<$d>(&mut group); - #[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] + #[cfg(not(la_stack_pre_rational_input_api))] register_norm_scenario_benchmarks::<$d>(&mut group); register_matrix_norm_benchmarks::<$d>(&mut group); $( @@ -762,7 +754,6 @@ macro_rules! define_vs_linalg_benches_for_dim { )? group.finish(); } - #[cfg(not(la_stack_v0_4_3_api))] register_lu_solve_diagnostics::<$d>(c); } }; diff --git a/cliff.toml b/cliff.toml index 818d102..9c64064 100644 --- a/cliff.toml +++ b/cliff.toml @@ -15,13 +15,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # # Release sections are generated from commit ranges. Angle brackets in commit # text are escaped so Rust generics like Foo do not render as HTML tags on -# GitHub. +# GitHub. Breaking footers are separate from commit.body; render their full +# descriptions in the release summary before grouping ordinary entries. body = """ {% if version -%} ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} {% else -%} ## [Unreleased] {% endif -%} +{% set breaking_commits = commits | filter(attribute="breaking", value=true) %} +{% if breaking_commits | length > 0 %} + ### ⚠️ Breaking Changes + {% for commit in breaking_commits %} + {% if commit.breaking_description and commit.breaking_description != commit.message %} + - {{ commit.breaking_description | trim | indent(prefix=" ", first=false) }} + {% else %} + - {{ commit.message | split(pat="\n") | first | upper_first | trim }} + {% endif %} + {% endfor %} +{% endif %} {% for group, commits in commits | group_by(attribute="group") %} ### {{ group | upper_first }} {% for commit in commits %} diff --git a/docs/BENCHMARKING.md b/docs/BENCHMARKING.md index 6d745b9..7e8ff79 100644 --- a/docs/BENCHMARKING.md +++ b/docs/BENCHMARKING.md @@ -27,15 +27,15 @@ the commands measure and where their outputs go. | Goal | Recipe | |------|--------| | Latest-release local audit | `just performance-local` | -| Non-exact release-signal check against tags | `just performance-local-non-exact v0.4.5 v0.4.4` | +| Non-exact release-signal check against tags | `just performance-local-non-exact v0.4.6 v0.4.5` | | Fast saved-baseline loop | `just bench-save-baseline ` then `just bench-compare all-benches` | | Full crate comparison | `just bench-vs-linalg` | | Interval determinant filter | `just bench-interval` | | Certified dot/linear-form filter | `just bench-linear-form` | | README table and plot | `just performance-release` then `just performance-readme` | -| Release report | `just performance-release v0.4.5 v0.4.4` | +| Release report | `just performance-release v0.4.6 v0.4.5` | | Build docs from retained release inputs | `just performance-doc` | -| Published-asset comparison | `just performance-github-assets v0.4.5 v0.4.4` | +| Published-asset comparison | `just performance-github-assets v0.4.6 v0.4.5` | Rule of thumb: @@ -128,7 +128,9 @@ just performance-local This creates isolated temporary worktrees and runs both library revisions on the same machine with the current checkout's benchmark sources, manifests, lockfile, -benchmark-input tests, recipes, and Rust toolchain. Staged and unstaged changes +benchmark-input tests, recipes, and Rust toolchain. Current example sources are +also copied so Cargo can resolve every target declared by the shared manifest; +the comparison does not build or time those examples. Staged and unstaged changes to tracked files are applied to the current worktree. Untracked files are excluded; stage a new file before running the command if it must participate in the comparison. Only the baseline library implementation comes from the release @@ -143,24 +145,32 @@ digests, Criterion selection/commands, and both correctness-gate results. The report reader rejects malformed or mismatched provenance and incomplete selected-suite coverage. -The shared harness carries an explicit v0.4.3-only API adapter for renamed or -ownership-adjusted calls (`det_sign_exact`, `Tolerance`, and vector dot -products). The adapter changes only how the same operation is invoked; it does -not patch either library implementation. Comparison builds cap lint diagnostics -at warning for both revisions because the current manifest's lint policy may -reject historical source that predates a lint, even though that source remains -valid benchmark input. - -The paired `det_direct_with_errbound` API postdates v0.4.3, so its D=2-4 -baseline rows remain explicitly unavailable in that comparison. The older -bound-only `det_errbound` API is source-compatible and remains a required -shared-harness baseline. - -The v0.4.3 LU/LDLT balanced-range determinant paths return an incorrect zero, -so their two D=8 stress rows are deliberately not timed as baselines. Reports -leave those baselines explicitly unavailable rather than presenting invalid -performance evidence. The other v0.4.3 D=8 pivoting and ill-conditioned rows -remain in the comparison. +For the default `all` suite, timing runs occur in this order: + +1. Baseline la-stack, nalgebra, and faer comparison benchmarks. +2. Baseline la-stack exact benchmarks. +3. Current la-stack comparison benchmarks, filtered to `la_stack` names. +4. Current la-stack exact benchmarks. + +La-stack is measured once per revision; the nalgebra/faer measurements from the +baseline phase are reused as peer context. The filtered current run disables +Criterion HTML generation because skipped peer `new` samples are deliberately +removed before current measurements. The retained CSV/JSON inputs and Python +renderer provide the release report. Baseline-saving recipes also disable unused +Criterion plots and HTML without changing sampling. + +New release comparisons require v0.4.4 or newer on both sides. v0.4.3 and older +are unsupported: the workflow rejects them before benchmark setup. Historical +Markdown reports remain in the archive, but are not regenerated with the current +harness. There are no v0.4.3 API adapters or missing-row exemptions. + +v0.4.4 and v0.4.5 use adapters for renamed norm methods and the array return +type of `solve_exact`, and omit the later rational-input API. These adapters +preserve the same operations and mathematical checks without patching either +library implementation. Comparison builds cap lint diagnostics at warning for +both revisions because the current manifest's lint policy may reject historical +source that predates a lint, even though that source remains valid benchmark +input. This command does not depend on existing local `target/criterion/` baselines. It is slower than reusing a saved baseline, but less sensitive to stale local @@ -183,10 +193,10 @@ distinct release identifiers. For a narrower non-exact check against a known release pair, run: ```bash -just performance-local-non-exact v0.4.5 v0.4.4 +just performance-local-non-exact v0.4.6 v0.4.5 ``` -This generates a local `v0.4.4` `vs_linalg` baseline, measures the current +This generates a local `v0.4.5` `vs_linalg` baseline, measures the current la-stack `vs_linalg` rows, and renders a `vs_linalg` report. The report includes saved baseline nalgebra/faer timings as context where matching peer rows exist, without rerunning current peer crates. @@ -252,7 +262,8 @@ just performance-readme `performance-readme` does not run benchmarks. It loads the canonical `target/bench-reports/performance.csv` and adjacent provenance JSON retained by -`performance-release`, then uses the current la-stack result and the peer +`performance-release`, falling back to the latest committed local snapshot when +both scratch inputs are absent. It then uses the current la-stack result and the peer nalgebra/faer results measured by that same shared current harness. It requires all three timings for every canonical dimension (D=2, 3, 4, 5, 8, 16, 32, and 64) before updating: @@ -285,7 +296,7 @@ Release PRs promote one curated release-to-release comparison into committed docs: ```bash -just performance-release v0.4.5 v0.4.4 +just performance-release v0.4.6 v0.4.5 ``` With no arguments, `just performance-release` infers the current release tag @@ -303,6 +314,13 @@ intervals in nanoseconds. Those peer fields are the source for the release pair, source states, commands, toolchain, Criterion version, harness/configuration digests, host, and schema version. +Before deleting the temporary worktree, the workflow also exports +`performance.full.csv` and `performance.full.provenance.json`. These preserve +every recorded case from the baseline and current phases, including diagnostics +and peer measurements outside the curated report selection. Means, medians, +95% confidence intervals, and sample counts retain full timing precision. +No additional benchmark executions are needed for this export. + Before creating worktrees or running either benchmark revision, structured local and release-report workflows require an identifiable CPU model. Raw Criterion benchmark recipes may still record measurements when that metadata @@ -310,11 +328,15 @@ is unavailable, but those measurements cannot be promoted as reproducible release evidence. The pair is validated and published before the temporary worktree is removed. -`docs/performance.md` is then rendered from a validated reload of that retained -pair, and the previous committed report is archived under +All four inputs are preserved under `docs/performance///` +with `latest.json` pointing to that snapshot. `docs/performance.md` is rendered +from a validated reload of the selected pair, and the previous committed report is archived under `docs/archive/performance/`. Archive filenames are release-pair names such as `v0.4.2-vs-v0.4.1.md`. Serialization, validation, rendering, coverage, or -promotion failures preserve the previous valid report and artifact pair. +promotion failures preserve the previous valid report, inputs, and snapshot +pointer. Review and commit the complete snapshot along with the curated report. +See the [local summary index](performance/README.md) for the schema and +comparison limits. To reproduce and promote the report without running Cargo or creating Git worktrees, use: @@ -325,7 +347,9 @@ just performance-doc This command fails closed on a missing, partial, malformed, mismatched, or unsupported artifact pair. It consumes the default CSV/JSON pair retained by a -successful `performance-local` or `performance-release` run, rewrites the +successful `performance-local` or `performance-release` run, or follows +`docs/performance/latest.json` when both default scratch inputs are absent. +It rewrites the scratch Markdown, promotes it to `docs/performance.md`, and archives the previous committed report when the release pair changes. Promotion requires distinct current and baseline package versions, so a same-version local comparison is @@ -343,7 +367,7 @@ requirement applies even when both release tags are supplied explicitly because the recipe still downloads their GitHub Release assets: ```bash -just performance-github-assets v0.4.5 v0.4.4 +just performance-github-assets v0.4.6 v0.4.5 ``` With no arguments, the recipe discovers the latest and previous stable @@ -364,12 +388,15 @@ shared-harness workflow before attributing a difference solely to library code. | `target/bench-reports/performance.md` | No | `bench-compare`, `performance-local`, `performance-release`, `performance-doc` | Canonical local comparison report. | | `target/bench-reports/performance.csv` | No | `performance-local`, `performance-release` | Validated tabular inputs for the canonical comparison and README publisher. | | `target/bench-reports/performance.provenance.json` | No | `performance-local`, `performance-release` | Schema, package identifiers, source, command, toolchain, host, digest, and harness provenance consumed by the README publisher. | +| `target/bench-reports/performance.full.*` | No | `performance-local`, `performance-release` | Every recorded local case, with timing summaries and provenance. | | `target/bench-reports/performance-non-exact.*` | No | `performance-local-non-exact` | Narrowed non-exact report and retained peer-context comparison inputs. | | `target/bench-reports/github-assets-performance.md` | No | `performance-github-assets` | Local report from published release artifacts. | | `target/bench-reports/github-assets-performance.csv` | No | `performance-github-assets` | Tabular inputs derived from published native archives. | | `target/bench-reports/github-assets-performance.provenance.json` | No | `performance-github-assets` | Provenance for the published-asset report inputs. | | `docs/performance.md` | Yes | `performance-release`, `performance-doc` | Latest curated release-to-release comparison. | +| `docs/performance/` | Yes | `performance-release`, `performance-doc` | Complete local summary snapshots, selected report inputs, and latest pointer; survives `just clean`. | | `docs/archive/performance/` | Yes | `performance-release`, `performance-doc` | Older curated release-to-release comparisons. | +| `docs/archive/performance/studies/` | Yes | Maintainer investigations | Completed optimization studies and decisions. | | `docs/assets/bench/` | Yes | `performance-readme` | README benchmark CSV/SVG assets and JSON provenance. | | GitHub Release | Remote | `.github/workflows/release-benchmarks.yml` | Criterion baseline archive. | @@ -378,12 +405,12 @@ Published baseline assets use the filename Everything under `target/bench-reports/` is reproducible local scratch owned by the performance-report workflows. It survives temporary-worktree cleanup but -may be removed by `just clean` or `cargo clean`; retain or copy the CSV/JSON pair -while reviewing or re-rendering a release PR. The compact CSV is the analysis and -Markdown-reproduction layer for both local and release comparisons. It does not -replace the full native Criterion `.tar.gz` archive attached to each GitHub -Release, which remains the durable raw -baseline for post-release comparisons. +may be removed by `just clean` or `cargo clean`. Promoted local snapshots remain +under `docs/performance/`, so report and README regeneration do not require +another measurement run. Unpromoted local experiments remain scratch data. +The saved summaries do not replace the full native Criterion `.tar.gz` archive +attached to each GitHub Release. Hosted archives retain raw samples from a +different machine; local summary comparisons must use their recorded environment. ## `vs_linalg` Methodology @@ -408,11 +435,18 @@ adapter code computes the agreed mathematical kernel inside the timed closure: | LDLT/Cholesky factorization and solve rows | Native `Ldlt` APIs | Native `Cholesky` APIs | Native LDLT APIs | | `det_via_lu`, `det_from_lu` | Native `Lu::det` | Native `LU::determinant` | Harness adapter: product of the U diagonal and permutation sign | | `det_from_ldlt` / `det_from_cholesky` | Native `Ldlt::det` | Native `Cholesky::determinant` | Harness adapter: product of the D diagonal | -| `dot` | Native `Vector::dot` | Native `dot` | Harness adapter: left-to-right fused multiply-add loop | +| `dot` | Native `Vector::dot` | Native `dot` | Native `linalg::matmul::dot::inner_prod` | | `norm2_sq` | Native `Vector::norm_squared` | Native `norm_squared` | Native `squared_norm_l2` | | `norm2` | Native `Vector::norm` | Native `norm` | Native `norm_l2` | | `inf_norm` | Native `Matrix::norm_inf` | Harness adapter: maximum absolute row sum | Harness adapter: maximum absolute row sum | +Native faer dot products use the `faer_dot_native` benchmark ID. Historical +`faer_dot` samples measured a repository-owned scalar fused multiply-add loop; +report readers never substitute those samples for the native operation. A saved +baseline without `faer_dot_native` has no native faer dot context. The README +chart and table compare LU factorization plus one solve; the detailed release +report also includes dot products and other kernels. + The `norm2`, `norm2_sq`, and `inf_norm` benchmark IDs, including scenario suffixes, are retained for continuity with saved baselines. The current public methods are `Vector::norm()`, `Vector::norm_squared()`, and `Matrix::norm_inf()`; the historical @@ -462,7 +496,7 @@ compared implementations, documented beside the benchmark, and checked against direct `iter` in the same binary to show that batching does not materially alter the reported kernel time or cross-crate ratio. -The integration smoke test `tests/vs_linalg_inputs.rs` reuses the benchmark +The integration smoke test `benches/comparison/tests/vs_linalg_inputs.rs` reuses the benchmark input helpers and verifies that la-stack, nalgebra, and faer agree on the determinant, solve, dot, Euclidean-norm, squared-norm, and infinity-norm results for every measured dimension: D=2, 3, 4, 5, 8, 16, 32, and 64. The same focused recipe @@ -522,7 +556,7 @@ Cholesky: Read these as SPD factorization/solve/determinant comparisons, not as identical algorithm comparisons across all three crates. -The [solve finalization decision](performance/solve-finalization.md) records +The [solve finalization decision](archive/performance/studies/solve-finalization.md) records why #234 retained the existing result construction after testing all eight README dimensions. It links the regression tests and current benchmark command. @@ -558,7 +592,7 @@ random-corpus groups, and adversarial-input groups: - `rational_input_wide{256,1024}_d{2..8}` — diagnostic rational groups with large positive rational row factors. These retain exact solutions and strict diagonal dominance while exercising heap-backed numerator and denominator - storage. See the [row-clearing study](performance/rational-row-clearing.md) + storage. See the [row-clearing study](archive/performance/studies/rational-row-clearing.md) for fixtures, allocation evidence, focused timing commands, and limitations. Rational Gaussian determinant and solve references use direct `bencher.iter`, @@ -658,14 +692,14 @@ iteration, while the saved v0.4.2 samples used direct closures. The current shared harness borrows a prevalidated input for both revisions. It also verifies that the D=2–4 headline fixtures resolve through the floating-point filter, so those rows continue to measure the intended common path. Use a current -shared-harness comparison before attributing the historical D=2 or D=3 changes -to the library implementation. - -For exact-arithmetic comparisons against v0.4.2 or older baselines, rows such -as `det_exact_rounded_f64 (vs det_exact_f64)` mean the current rounded API is -being compared to the historical lossy `*_exact_f64` benchmark. Rows such as -`det_exact_f64_result (vs det_exact_f64)` intentionally show the overhead of the -new strict conversion contract against that same historical baseline. +shared-harness comparison between supported releases before attributing timing +changes to the library implementation. v0.4.3 and older cannot be rerun with the +current workflow. + +Archived reports may show rows such as `det_exact_rounded_f64 (vs det_exact_f64)` +or `det_exact_f64_result (vs det_exact_f64)`. Those used the historical lossy +`*_exact_f64` baseline. New comparisons require matching benchmark identifiers; +the pre-v0.4.3 name substitutions have been removed. The default `release-signal` scope includes the canonical exact-arithmetic groups because their inputs and execution order are fixed across revisions. Historical diff --git a/docs/RELEASING.md b/docs/RELEASING.md index ff611d3..d181c6a 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -111,13 +111,17 @@ just performance-release The no-argument form compares the current package version with the previous stable published release. Review `docs/performance.md`, any archived comparison -under `docs/archive/performance/`, and the retained CSV and provenance JSON under -`target/bench-reports/`. +under `docs/archive/performance/`, and the complete versioned local summary +snapshot and `latest.json` under `docs/performance/`. Include those CSV and JSON +files in the release commit; they preserve every recorded case, including the +measurements outside the readable report's selection. The temporary current worktree includes staged and unstaged changes to tracked files, but excludes untracked files. Stage any new benchmark-relevant file before -running the comparison. Do not run `just clean` or `cargo clean` until the -retained report inputs have been reviewed. +running the comparison. Successful release promotion preserves the selected +report inputs and complete summaries under `docs/performance/`, so cleanup no +longer removes the data needed to regenerate the reports. Local experiments +from `performance-local` remain scratch until explicitly promoted. ### 5. Refresh the README benchmark comparison @@ -130,6 +134,8 @@ This consumes the validated CSV and provenance JSON retained by updates the table and tag-pinned benchmark links in `README.md` with the CSV, SVG, and provenance JSON under `docs/assets/bench/`. Until it succeeds, those README links continue to reference the previous published artifacts. +If scratch inputs were cleaned, it uses the committed local snapshot. Existing +partial or corrupt scratch inputs remain errors and never trigger a fallback. See `docs/BENCHMARKING.md` for repair commands, local comparison modes, artifact ownership, and provenance details. diff --git a/docs/archive/changelog/0.2.md b/docs/archive/changelog/0.2.md index 466298d..fb89834 100644 --- a/docs/archive/changelog/0.2.md +++ b/docs/archive/changelog/0.2.md @@ -25,7 +25,17 @@ ### ⚠️ Breaking Changes -- Return Result from det_sign_exact, rename NonFinite field +- two public API changes to LaError and det_sign_exact. + + - `LaError::NonFinite { pivot_col }` renamed to `LaError::NonFinite { col }` + to reflect that NonFinite errors are not always pivot-related (e.g. + det_sign_exact, det). + - `Matrix::det_sign_exact()` now returns `Result` instead + of `i8`. Returns `Err(LaError::NonFinite { col })` for NaN/infinite + entries instead of panicking. This aligns with lu(), ldlt(), and det(). + - When det_direct() overflows to infinity but all entries are finite, + the fast filter is now skipped gracefully and Bareiss computes the + correct exact sign (previously panicked). ### Changed diff --git a/docs/archive/changelog/0.3.md b/docs/archive/changelog/0.3.md index 5c0ed16..baf6d16 100644 --- a/docs/archive/changelog/0.3.md +++ b/docs/archive/changelog/0.3.md @@ -4,7 +4,8 @@ ### ⚠️ Breaking Changes -- Expose exact determinant value (det_exact, det_exact_f64) +- `LaError` is now `#[non_exhaustive]` and has a new + `Overflow` variant. Exhaustive matches on `LaError` must add a wildcard arm. ### Added diff --git a/docs/archive/performance/README.md b/docs/archive/performance/README.md index b66572d..6456dbc 100644 --- a/docs/archive/performance/README.md +++ b/docs/archive/performance/README.md @@ -7,3 +7,6 @@ Older release-to-release benchmark comparisons are archived here. - [v0.4.2-vs-v0.4.1](v0.4.2-vs-v0.4.1.md) - [v0.4.3-vs-v0.4.2](v0.4.3-vs-v0.4.2.md) - [v0.4.4-vs-v0.4.3](v0.4.4-vs-v0.4.3.md) +- [v0.4.5-vs-v0.4.4](v0.4.5-vs-v0.4.4.md) + +Completed optimization investigations are in [archived studies](studies/README.md). diff --git a/docs/archive/performance/studies/README.md b/docs/archive/performance/studies/README.md new file mode 100644 index 0000000..f840601 --- /dev/null +++ b/docs/archive/performance/studies/README.md @@ -0,0 +1,11 @@ +# Archived Performance Studies + +Completed optimization investigations and their decisions are retained here. +These are historical experiments, with the environment and limitations stated +in each report. + +- [Rational row-clearing allocation study (#233)](rational-row-clearing.md) +- [Solve finalization decision (#234)](solve-finalization.md) + +[Release comparisons](../README.md) and [complete local benchmark summaries](../../../performance/README.md) +have separate owners. diff --git a/docs/performance/rational-row-clearing.md b/docs/archive/performance/studies/rational-row-clearing.md similarity index 98% rename from docs/performance/rational-row-clearing.md rename to docs/archive/performance/studies/rational-row-clearing.md index e095b29..cb5a408 100644 --- a/docs/performance/rational-row-clearing.md +++ b/docs/archive/performance/studies/rational-row-clearing.md @@ -52,7 +52,7 @@ do not establish performance for all exact-input workloads. ## Allocation evidence -The [complete allocation CSV](../assets/rational-row-clearing-allocations.csv) +The [complete allocation CSV](../../../assets/rational-row-clearing-allocations.csv) retains total allocation counts and requested bytes for both implementations. `det`, `det_sign`, and `solve` rows measure complete public calls, including dropping their results. The remaining rows isolate component cloning and @@ -95,7 +95,7 @@ guarantees or fixed cross-version test expectations. ## Timing evidence -The [complete timing CSV](../assets/rational-row-clearing-timings.csv) retains +The [complete timing CSV](../../../assets/rational-row-clearing-timings.csv) retains all 63 initial comparisons and two repeats, including Criterion mean estimates and their marginal 95% confidence intervals in nanoseconds. Percentage change is `100 × (borrowed mean / cloned mean - 1)`; negative values mean less time. diff --git a/docs/performance/solve-finalization.md b/docs/archive/performance/studies/solve-finalization.md similarity index 94% rename from docs/performance/solve-finalization.md rename to docs/archive/performance/studies/solve-finalization.md index dc4460d..8d3a765 100644 --- a/docs/performance/solve-finalization.md +++ b/docs/archive/performance/studies/solve-finalization.md @@ -13,7 +13,7 @@ This supports keeping the simpler implementation; it does not prove that finalization has zero cost in every compiler or calling context. The retained tests in -[`tests/solve_finalization.rs`](../../tests/solve_finalization.rs) exercise +[`tests/solve_finalization.rs`](../../../../tests/solve_finalization.rs) exercise division, forward-substitution, and back-substitution overflow across all eight dimensions, preserving the exact typed error and failing-step order. diff --git a/docs/archive/performance/v0.4.5-vs-v0.4.4.md b/docs/archive/performance/v0.4.5-vs-v0.4.4.md new file mode 100644 index 0000000..5a55d65 --- /dev/null +++ b/docs/archive/performance/v0.4.5-vs-v0.4.4.md @@ -0,0 +1,286 @@ +# Benchmark Performance + +**la-stack** v0.4.5 · `99d3392` (HEAD) +**Source revision timestamp**: 2026-08-20 21:16:55 UTC (deterministic report metadata; not the benchmark measurement time) +**Benchmark measurement timestamp**: not recorded by Criterion; use the provenance below to identify the measured revisions and environment. +**Statistic**: median +**Suite**: all +**Scope**: release-signal + +## Benchmark Results + +Comparison against baseline **v0.4.4**: + +Negative point-estimate change means the current point estimate is smaller; a baseline/current point-estimate ratio above 1.00 has the same meaning. +The CI-relation column reports only whether the two marginal Criterion intervals overlap. These are not paired confidence intervals +for the change, so the report makes no statistical-significance or performance-improvement claim from interval separation. + +### Reproducibility Provenance + +**Measurement environment**: recorded for both samples under one shared current harness. + +- CPU: `Apple M4 Max (arm64)` +- OS: `Darwin 25.6.0 arm64` +- rustc: `rustc 1.98.0 (88d9e12ae 2026-08-18)` +- Current commit: `99d33927e389018c599c009603a7eafffcc25089` +- Current Git clean: `false` +- Current source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007` +- Baseline commit: `03a6dc751b7bf7c69b833aeb4e20e2acb6da2e4c` +- Baseline Git clean: `false` +- Baseline source-state SHA-256: `227a2780c989352be2eacf3f32ca67032cc69fc843e596acc386a7c4f7d459f0` +- Cargo.lock SHA-256: `72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492` +- Benchmark harness SHA-256: `164d6bbac2e6cb19b85c81677e4ab4428c3abb130dcfd38a2f5f162a5dd8a905` + +**Publication and validation environment**: + +- Publication CPU: `Apple M4 Max (arm64)` +- Publication OS: `Darwin 25.6.0 arm64` +- Publication rustc: `rustc 1.98.0 (88d9e12ae 2026-08-18)` +- Publication commit: `99d33927e389018c599c009603a7eafffcc25089` +- Publication Git clean: `false` +- Publication source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007` +- Publication Cargo.lock SHA-256: `72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492` +- Publication harness SHA-256: `164d6bbac2e6cb19b85c81677e4ab4428c3abb130dcfd38a2f5f162a5dd8a905` +- Criterion suite/scope: `all` / `release-signal` +- Criterion statistic/sample: `median` / `new` +- Criterion dependency version: `0.8.2` +- Baseline command: `just bench-save-baseline v0.4.4` +- Current command: `just bench-latest` +- Correctness gate: `just test-bench-inputs` passed against both the current and baseline revisions using the shared current fixture harness. +- Validated current revision: `99d33927e389018c599c009603a7eafffcc25089` (Git clean: `false`; + source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007`) +- Validated baseline revision: `03a6dc751b7bf7c69b833aeb4e20e2acb6da2e4c` (Git clean: `false`; + source-state SHA-256: `227a2780c989352be2eacf3f32ca67032cc69fc843e596acc386a7c4f7d459f0`) + +## Exact arithmetic + +| Case | Benchmark | v0.4.4 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | +|:-----|:----------|-------:|-------:|-------:|:-----------|--------:| +| D=2 | det | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=2 | det_direct | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.5% | marginal CIs overlap | 1.02x | +| D=2 | det_direct_with_errbound | 1.7 ns [1.7 ns, 1.7 ns] | 1.7 ns [1.7 ns, 1.7 ns] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | +| D=2 | det_errbound | 1.6 ns [1.6 ns, 1.6 ns] | 1.6 ns [1.6 ns, 1.6 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | +| D=2 | det_exact | 91.7 ns [91.6 ns, 91.9 ns] | 91.3 ns [91.2 ns, 91.5 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | +| D=2 | det_exact_f64_result | 65.6 ns [65.3 ns, 65.8 ns] | 64.7 ns [64.6 ns, 64.7 ns] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | +| D=2 | det_exact_rounded_f64 | 66.7 ns [66.6 ns, 66.8 ns] | 66.6 ns [66.5 ns, 66.7 ns] | -0.1% | marginal CIs overlap | 1.00x | +| D=2 | det_sign_exact | 2.8 ns [2.7 ns, 2.8 ns] | 2.7 ns [2.7 ns, 2.7 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | +| D=2 | solve_exact | 6.90 µs [6.88 µs, 6.91 µs] | 6.78 µs [6.77 µs, 6.79 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | +| D=2 | solve_exact_f64_result | 8.14 µs [8.13 µs, 8.16 µs] | 7.91 µs [7.89 µs, 7.92 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | +| D=2 | solve_exact_rounded_f64 | 7.25 µs [7.23 µs, 7.27 µs] | 7.10 µs [7.10 µs, 7.11 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | +| D=3 | det | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | det_direct | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | det_direct_with_errbound | 3.3 ns [3.3 ns, 3.4 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -0.0% | marginal CIs overlap | 1.00x | +| D=3 | det_errbound | 3.3 ns [3.3 ns, 3.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | det_exact | 341.9 ns [340.5 ns, 343.5 ns] | 323.7 ns [323.2 ns, 324.3 ns] | -5.3% | faster point estimate; marginal CIs separated | 1.06x | +| D=3 | det_exact_f64_result | 300.9 ns [300.5 ns, 301.6 ns] | 293.7 ns [293.2 ns, 293.9 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | +| D=3 | det_exact_rounded_f64 | 300.5 ns [300.1 ns, 301.0 ns] | 293.7 ns [293.5 ns, 294.0 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | +| D=3 | det_sign_exact | 4.7 ns [4.7 ns, 4.7 ns] | 4.7 ns [4.7 ns, 4.7 ns] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | solve_exact | 30.23 µs [30.12 µs, 30.31 µs] | 29.93 µs [29.89 µs, 29.97 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | solve_exact_f64_result | 32.20 µs [32.13 µs, 32.26 µs] | 31.88 µs [31.83 µs, 31.95 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | solve_exact_rounded_f64 | 31.46 µs [31.19 µs, 31.53 µs] | 30.49 µs [30.44 µs, 30.52 µs] | -3.1% | faster point estimate; marginal CIs separated | 1.03x | +| D=4 | det | 3.3 ns [3.3 ns, 3.3 ns] | 3.2 ns [3.2 ns, 3.2 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | +| D=4 | det_direct | 2.4 ns [2.4 ns, 2.4 ns] | 2.4 ns [2.4 ns, 2.4 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | det_direct_with_errbound | 6.9 ns [6.9 ns, 6.9 ns] | 6.8 ns [6.8 ns, 6.8 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | det_errbound | 6.8 ns [6.8 ns, 6.8 ns] | 6.7 ns [6.7 ns, 6.7 ns] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | det_exact | 1.02 µs [1.02 µs, 1.03 µs] | 1.01 µs [1.01 µs, 1.01 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | det_exact_f64_result | 993.0 ns [990.5 ns, 996.0 ns] | 976.7 ns [974.5 ns, 978.7 ns] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | +| D=4 | det_exact_rounded_f64 | 991.3 ns [989.1 ns, 993.3 ns] | 973.8 ns [973.0 ns, 976.3 ns] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | +| D=4 | det_sign_exact | 7.8 ns [7.8 ns, 7.8 ns] | 7.7 ns [7.7 ns, 7.7 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | solve_exact | 78.81 µs [78.73 µs, 78.97 µs] | 77.91 µs [77.80 µs, 77.99 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | solve_exact_f64_result | 81.82 µs [81.72 µs, 81.92 µs] | 80.71 µs [80.62 µs, 80.79 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=4 | solve_exact_rounded_f64 | 79.66 µs [79.57 µs, 79.83 µs] | 78.66 µs [78.57 µs, 78.76 µs] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | det | 25.1 ns [25.1 ns, 25.2 ns] | 25.0 ns [24.9 ns, 25.1 ns] | -0.6% | marginal CIs overlap | 1.01x | +| D=5 | det_exact | 3.08 µs [3.06 µs, 3.12 µs] | 2.94 µs [2.94 µs, 2.95 µs] | -4.4% | faster point estimate; marginal CIs separated | 1.05x | +| D=5 | det_exact_f64_result | 3.02 µs [3.01 µs, 3.03 µs] | 2.91 µs [2.90 µs, 2.91 µs] | -3.7% | faster point estimate; marginal CIs separated | 1.04x | +| D=5 | det_exact_rounded_f64 | 2.98 µs [2.98 µs, 2.99 µs] | 2.96 µs [2.95 µs, 2.97 µs] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | det_sign_exact | 3.15 µs [3.14 µs, 3.17 µs] | 3.05 µs [3.04 µs, 3.05 µs] | -3.4% | faster point estimate; marginal CIs separated | 1.04x | +| D=5 | solve_exact | 156.87 µs [156.58 µs, 157.10 µs] | 155.34 µs [155.10 µs, 155.58 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | solve_exact_f64_result | 159.75 µs [159.55 µs, 160.17 µs] | 158.29 µs [158.09 µs, 158.43 µs] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | solve_exact_rounded_f64 | 159.08 µs [158.45 µs, 160.00 µs] | 156.37 µs [156.22 µs, 156.57 µs] | -1.7% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 4x4 | det_exact | 1.13 µs [1.12 µs, 1.13 µs] | 1.10 µs [1.09 µs, 1.10 µs] | -2.8% | faster point estimate; marginal CIs separated | 1.03x | +| Hilbert 4x4 | det_sign_exact | 8.0 ns [7.9 ns, 8.0 ns] | 7.7 ns [7.7 ns, 7.7 ns] | -3.2% | faster point estimate; marginal CIs separated | 1.03x | +| Hilbert 4x4 | solve_exact | 59.49 µs [59.37 µs, 59.59 µs] | 58.24 µs [58.12 µs, 58.35 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 4x4 | solve_exact_f64_result | 61.76 µs [61.70 µs, 61.84 µs] | 60.89 µs [60.80 µs, 60.95 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| Hilbert 4x4 | solve_exact_rounded_f64 | 60.17 µs [60.12 µs, 60.28 µs] | 58.88 µs [58.75 µs, 59.03 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 5x5 | det_exact | 3.13 µs [3.12 µs, 3.13 µs] | 3.05 µs [3.03 µs, 3.05 µs] | -2.6% | faster point estimate; marginal CIs separated | 1.03x | +| Hilbert 5x5 | det_sign_exact | 3.33 µs [3.32 µs, 3.34 µs] | 3.27 µs [3.26 µs, 3.28 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 5x5 | solve_exact | 122.74 µs [122.59 µs, 122.86 µs] | 120.11 µs [119.87 µs, 120.28 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 5x5 | solve_exact_f64_result | 125.85 µs [125.61 µs, 126.01 µs] | 123.42 µs [123.24 µs, 123.55 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 5x5 | solve_exact_rounded_f64 | 124.06 µs [123.87 µs, 124.28 µs] | 122.12 µs [121.79 µs, 122.49 µs] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | +| Large entries 3x3 | det_exact | 309.9 ns [308.3 ns, 310.7 ns] | 290.4 ns [290.0 ns, 291.4 ns] | -6.3% | faster point estimate; marginal CIs separated | 1.07x | +| Large entries 3x3 | det_sign_exact | 291.0 ns [289.7 ns, 292.2 ns] | 282.1 ns [281.0 ns, 283.3 ns] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | +| Large entries 3x3 | solve_exact | 95.06 µs [94.85 µs, 95.29 µs] | 92.60 µs [92.46 µs, 92.76 µs] | -2.6% | faster point estimate; marginal CIs separated | 1.03x | +| Large entries 3x3 | solve_exact_f64_result | 96.49 µs [96.09 µs, 97.15 µs] | 93.61 µs [93.42 µs, 93.81 µs] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | +| Large entries 3x3 | solve_exact_rounded_f64 | 95.16 µs [94.97 µs, 95.34 µs] | 93.36 µs [93.20 µs, 93.55 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | +| Near-singular 3x3 | det_exact | 322.6 ns [321.3 ns, 325.5 ns] | 303.0 ns [302.2 ns, 303.5 ns] | -6.1% | faster point estimate; marginal CIs separated | 1.06x | +| Near-singular 3x3 | det_sign_exact | 372.6 ns [370.5 ns, 374.2 ns] | 345.8 ns [344.2 ns, 347.4 ns] | -7.2% | faster point estimate; marginal CIs separated | 1.08x | +| Near-singular 3x3 | solve_exact | 2.42 µs [2.41 µs, 2.43 µs] | 2.34 µs [2.34 µs, 2.35 µs] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | +| Near-singular 3x3 | solve_exact_f64_result | 2.51 µs [2.49 µs, 2.52 µs] | 2.46 µs [2.45 µs, 2.47 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | +| Near-singular 3x3 | solve_exact_rounded_f64 | 2.42 µs [2.42 µs, 2.43 µs] | 2.35 µs [2.35 µs, 2.36 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=2 | det_exact | 3.20 µs [3.19 µs, 3.20 µs] | 3.13 µs [3.13 µs, 3.13 µs] | -2.0% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=2 | det_sign_exact | 141.6 ns [140.8 ns, 143.3 ns] | 136.5 ns [135.7 ns, 137.2 ns] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | +| Random corpus D=2 | solve_exact | 69.25 µs [69.09 µs, 69.50 µs] | 68.00 µs [67.75 µs, 68.99 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=2 | solve_exact_f64_result | 80.02 µs [79.86 µs, 80.24 µs] | 78.04 µs [77.88 µs, 78.24 µs] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=2 | solve_exact_rounded_f64 | 70.51 µs [70.05 µs, 70.90 µs] | 67.94 µs [67.89 µs, 68.00 µs] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | +| Random corpus D=3 | det_exact | 9.03 µs [8.95 µs, 9.10 µs] | 8.81 µs [8.24 µs, 8.89 µs] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=3 | det_sign_exact | 228.6 ns [228.3 ns, 228.8 ns] | 225.0 ns [224.8 ns, 225.1 ns] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=3 | solve_exact | 219.99 µs [219.73 µs, 220.21 µs] | 216.21 µs [215.83 µs, 216.36 µs] | -1.7% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=3 | solve_exact_f64_result | 235.73 µs [234.74 µs, 236.39 µs] | 230.14 µs [229.96 µs, 230.31 µs] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=3 | solve_exact_rounded_f64 | 222.81 µs [222.46 µs, 223.31 µs] | 217.76 µs [217.35 µs, 218.01 µs] | -2.3% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=4 | det_exact | 25.74 µs [25.66 µs, 25.87 µs] | 24.87 µs [24.84 µs, 24.98 µs] | -3.4% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=4 | det_sign_exact | 434.0 ns [432.4 ns, 435.8 ns] | 424.5 ns [423.9 ns, 425.6 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=4 | solve_exact | 511.24 µs [509.70 µs, 513.54 µs] | 493.20 µs [492.65 µs, 493.60 µs] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | +| Random corpus D=4 | solve_exact_f64_result | 531.44 µs [528.39 µs, 535.08 µs] | 513.06 µs [512.52 µs, 513.31 µs] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | +| Random corpus D=4 | solve_exact_rounded_f64 | 502.60 µs [502.00 µs, 503.33 µs] | 494.39 µs [493.41 µs, 495.23 µs] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=5 | det_exact | 47.95 µs [47.47 µs, 48.29 µs] | 46.58 µs [46.42 µs, 46.65 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=5 | det_sign_exact | 48.52 µs [47.83 µs, 48.94 µs] | 51.72 µs [50.78 µs, 52.35 µs] | +6.6% | slower point estimate; marginal CIs separated | 0.94x | +| Random corpus D=5 | solve_exact | 994.36 µs [993.76 µs, 995.50 µs] | 972.74 µs [971.25 µs, 974.13 µs] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | +| Random corpus D=5 | solve_exact_f64_result | 1.02 ms [1.02 ms, 1.02 ms] | 992.23 µs [990.24 µs, 993.69 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | +| Random corpus D=5 | solve_exact_rounded_f64 | 1.03 ms [1.03 ms, 1.04 ms] | 972.11 µs [970.46 µs, 973.74 µs] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | + +## vs_linalg + +| Case | Benchmark | v0.4.4 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | v0.4.4 nalgebra | v0.4.4 faer | +|:-----|:----------|-------:|-------:|-------:|:-----------|--------:|-------:|-------:| +| D=16 | la_stack_det | 432.1 ns [428.1 ns, 433.9 ns] | 436.8 ns [435.3 ns, 438.7 ns] | +1.1% | slower point estimate; marginal CIs separated | 0.99x | — | — | +| D=16 | la_stack_det_from_ldlt | 3.5 ns [3.4 ns, 3.6 ns] | 2.9 ns [2.9 ns, 2.9 ns] | -17.7% | faster point estimate; marginal CIs separated | 1.21x | 1.7 ns [1.7 ns, 1.7 ns] | 4.5 ns [4.5 ns, 4.6 ns] | +| D=16 | la_stack_det_from_lu | 4.2 ns [4.1 ns, 4.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -22.4% | faster point estimate; marginal CIs separated | 1.29x | 1.8 ns [1.8 ns, 1.8 ns] | 5.0 ns [4.9 ns, 5.0 ns] | +| D=16 | la_stack_det_via_lu | 423.2 ns [418.2 ns, 427.0 ns] | 422.8 ns [420.8 ns, 424.7 ns] | -0.1% | marginal CIs overlap | 1.00x | 458.2 ns [457.0 ns, 458.6 ns] | 679.3 ns [672.2 ns, 683.9 ns] | +| D=16 | la_stack_dot | 2.4 ns [2.4 ns, 2.4 ns] | 2.3 ns [2.3 ns, 2.3 ns] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | 1.9 ns [1.9 ns, 1.9 ns] | 4.6 ns [4.6 ns, 4.6 ns] | +| D=16 | la_stack_inf_norm | 33.5 ns [33.3 ns, 33.6 ns] | 32.7 ns [32.7 ns, 32.7 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | 33.4 ns [33.2 ns, 33.6 ns] | 33.4 ns [33.3 ns, 33.5 ns] | +| D=16 | la_stack_ldlt | 394.2 ns [392.7 ns, 395.9 ns] | 390.6 ns [389.5 ns, 391.2 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 408.4 ns [407.3 ns, 410.1 ns] | 446.8 ns [443.5 ns, 448.3 ns] | +| D=16 | la_stack_ldlt_solve | 433.6 ns [432.5 ns, 434.6 ns] | 436.1 ns [435.2 ns, 437.4 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | 638.5 ns [637.9 ns, 640.1 ns] | 624.6 ns [623.7 ns, 626.6 ns] | +| D=16 | la_stack_lu | 398.6 ns [397.3 ns, 400.9 ns] | 403.5 ns [401.3 ns, 405.9 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 465.6 ns [464.7 ns, 466.9 ns] | 658.8 ns [654.2 ns, 665.1 ns] | +| D=16 | la_stack_lu_solve | 667.8 ns [665.2 ns, 672.5 ns] | 672.5 ns [670.9 ns, 674.0 ns] | +0.7% | marginal CIs overlap | 0.99x | 585.3 ns [584.6 ns, 586.3 ns] | 897.2 ns [895.5 ns, 900.9 ns] | +| D=16 | la_stack_norm2_sq | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | 1.5 ns [1.5 ns, 1.5 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=16 | la_stack_solve_from_ldlt | 28.0 ns [28.0 ns, 28.1 ns] | 27.7 ns [27.7 ns, 27.8 ns] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | 126.5 ns [126.1 ns, 127.1 ns] | 179.6 ns [178.8 ns, 180.2 ns] | +| D=16 | la_stack_solve_from_lu | 204.7 ns [204.0 ns, 205.2 ns] | 203.1 ns [202.5 ns, 204.0 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 95.3 ns [95.2 ns, 95.5 ns] | 245.0 ns [244.1 ns, 247.1 ns] | +| D=2 | la_stack_det | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +2.3% | slower point estimate; marginal CIs separated | 0.98x | — | — | +| D=2 | la_stack_det_from_ldlt | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +| D=2 | la_stack_det_from_lu | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -0.1% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +| D=2 | la_stack_det_via_lu | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | 0.8 ns [0.8 ns, 0.8 ns] | 98.3 ns [97.9 ns, 99.0 ns] | +| D=2 | la_stack_dot | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +5.3% | slower point estimate; marginal CIs separated | 0.95x | 0.6 ns [0.6 ns, 0.6 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +| D=2 | la_stack_inf_norm | 0.7 ns [0.7 ns, 0.7 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -8.9% | faster point estimate; marginal CIs separated | 1.10x | 0.5 ns [0.5 ns, 0.5 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +| D=2 | la_stack_ldlt | 6.8 ns [6.8 ns, 6.9 ns] | 7.1 ns [7.1 ns, 7.1 ns] | +3.7% | slower point estimate; marginal CIs separated | 0.96x | 1.7 ns [1.7 ns, 1.7 ns] | 81.6 ns [81.4 ns, 81.8 ns] | +| D=2 | la_stack_ldlt_solve | 9.9 ns [9.9 ns, 9.9 ns] | 10.1 ns [10.0 ns, 10.1 ns] | +2.1% | slower point estimate; marginal CIs separated | 0.98x | 2.7 ns [2.7 ns, 2.7 ns] | 124.6 ns [124.2 ns, 125.1 ns] | +| D=2 | la_stack_lu | 1.6 ns [1.6 ns, 1.6 ns] | 1.6 ns [1.6 ns, 1.6 ns] | +2.4% | slower point estimate; marginal CIs separated | 0.98x | 1.6 ns [1.6 ns, 1.6 ns] | 95.9 ns [95.2 ns, 96.3 ns] | +| D=2 | la_stack_lu_solve | 2.1 ns [2.0 ns, 2.1 ns] | 2.0 ns [2.0 ns, 2.0 ns] | -0.6% | marginal CIs overlap | 1.01x | 4.6 ns [4.6 ns, 4.6 ns] | 151.9 ns [151.7 ns, 152.5 ns] | +| D=2 | la_stack_norm2_sq | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | +1.0% | slower point estimate; marginal CIs separated | 0.99x | 0.4 ns [0.4 ns, 0.4 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=2 | la_stack_solve_from_ldlt | 1.2 ns [1.2 ns, 1.2 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +1.3% | slower point estimate; marginal CIs separated | 0.99x | 1.3 ns [1.3 ns, 1.3 ns] | 37.6 ns [37.4 ns, 37.9 ns] | +| D=2 | la_stack_solve_from_lu | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +2.6% | slower point estimate; marginal CIs separated | 0.98x | 2.9 ns [2.9 ns, 2.9 ns] | 48.8 ns [48.6 ns, 49.1 ns] | +| D=3 | la_stack_det | 1.4 ns [1.3 ns, 1.4 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | — | — | +| D=3 | la_stack_det_from_ldlt | 0.7 ns [0.7 ns, 0.7 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -19.6% | faster point estimate; marginal CIs separated | 1.24x | 0.5 ns [0.5 ns, 0.5 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +| D=3 | la_stack_det_from_lu | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | +| D=3 | la_stack_det_via_lu | 8.8 ns [8.7 ns, 8.8 ns] | 8.8 ns [8.8 ns, 8.9 ns] | +0.7% | slower point estimate; marginal CIs separated | 0.99x | 16.9 ns [16.8 ns, 17.0 ns] | 141.6 ns [140.9 ns, 142.3 ns] | +| D=3 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 0.9 ns [0.9 ns, 0.9 ns] | +| D=3 | la_stack_inf_norm | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | 1.1 ns [1.1 ns, 1.1 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +| D=3 | la_stack_ldlt | 14.8 ns [14.5 ns, 15.1 ns] | 14.1 ns [14.1 ns, 14.2 ns] | -4.5% | faster point estimate; marginal CIs separated | 1.05x | 4.0 ns [4.0 ns, 4.0 ns] | 97.8 ns [97.6 ns, 98.2 ns] | +| D=3 | la_stack_ldlt_solve | 11.6 ns [11.6 ns, 11.7 ns] | 11.7 ns [11.7 ns, 11.8 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | 6.0 ns [6.0 ns, 6.0 ns] | 142.4 ns [141.9 ns, 143.0 ns] | +| D=3 | la_stack_lu | 8.5 ns [8.4 ns, 8.5 ns] | 8.4 ns [8.4 ns, 8.4 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 15.4 ns [15.3 ns, 15.5 ns] | 138.0 ns [137.4 ns, 138.6 ns] | +| D=3 | la_stack_lu_solve | 9.9 ns [9.9 ns, 10.0 ns] | 10.0 ns [10.0 ns, 10.0 ns] | +0.5% | marginal CIs overlap | 1.00x | 23.5 ns [23.4 ns, 23.6 ns] | 196.4 ns [194.9 ns, 198.8 ns] | +| D=3 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.5% | faster point estimate; marginal CIs separated | 1.01x | 0.4 ns [0.4 ns, 0.4 ns] | 4.2 ns [4.1 ns, 4.2 ns] | +| D=3 | la_stack_solve_from_ldlt | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 2.9 ns [2.9 ns, 2.9 ns] | 40.6 ns [40.1 ns, 41.0 ns] | +| D=3 | la_stack_solve_from_lu | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | +0.5% | marginal CIs overlap | 1.00x | 4.6 ns [4.6 ns, 4.6 ns] | 48.6 ns [48.5 ns, 48.7 ns] | +| D=32 | la_stack_det | 2.22 µs [2.21 µs, 2.23 µs] | 2.17 µs [2.17 µs, 2.18 µs] | -2.3% | faster point estimate; marginal CIs separated | 1.02x | — | — | +| D=32 | la_stack_det_from_ldlt | 14.1 ns [14.1 ns, 14.1 ns] | 7.9 ns [7.9 ns, 7.9 ns] | -44.0% | faster point estimate; marginal CIs separated | 1.79x | 3.0 ns [3.0 ns, 3.0 ns] | 8.7 ns [8.7 ns, 8.8 ns] | +| D=32 | la_stack_det_from_lu | 14.1 ns [14.0 ns, 14.1 ns] | 9.1 ns [9.1 ns, 9.1 ns] | -35.2% | faster point estimate; marginal CIs separated | 1.54x | 3.1 ns [3.1 ns, 3.1 ns] | 9.0 ns [8.9 ns, 9.0 ns] | +| D=32 | la_stack_det_via_lu | 2.23 µs [2.21 µs, 2.23 µs] | 2.04 µs [2.03 µs, 2.04 µs] | -8.4% | faster point estimate; marginal CIs separated | 1.09x | 2.53 µs [2.52 µs, 2.54 µs] | 2.37 µs [2.36 µs, 2.38 µs] | +| D=32 | la_stack_dot | 4.1 ns [4.1 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 4.8 ns [4.8 ns, 4.8 ns] | 15.2 ns [15.2 ns, 15.2 ns] | +| D=32 | la_stack_inf_norm | 131.6 ns [131.4 ns, 131.8 ns] | 130.4 ns [130.0 ns, 130.7 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 157.7 ns [157.2 ns, 158.1 ns] | 167.1 ns [166.9 ns, 167.3 ns] | +| D=32 | la_stack_ldlt | 2.47 µs [2.46 µs, 2.47 µs] | 2.52 µs [2.51 µs, 2.52 µs] | +2.0% | slower point estimate; marginal CIs separated | 0.98x | 2.13 µs [2.12 µs, 2.13 µs] | 1.50 µs [1.49 µs, 1.51 µs] | +| D=32 | la_stack_ldlt_solve | 2.83 µs [2.82 µs, 2.84 µs] | 2.84 µs [2.83 µs, 2.86 µs] | +0.4% | marginal CIs overlap | 1.00x | 2.78 µs [2.77 µs, 2.79 µs] | 1.97 µs [1.97 µs, 1.98 µs] | +| D=32 | la_stack_lu | 2.15 µs [2.14 µs, 2.15 µs] | 2.07 µs [2.07 µs, 2.08 µs] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | 2.21 µs [2.20 µs, 2.22 µs] | 2.30 µs [2.29 µs, 2.30 µs] | +| D=32 | la_stack_lu_solve | 2.87 µs [2.85 µs, 2.89 µs] | 2.78 µs [2.77 µs, 2.78 µs] | -3.3% | faster point estimate; marginal CIs separated | 1.03x | 2.50 µs [2.49 µs, 2.51 µs] | 2.95 µs [2.95 µs, 2.96 µs] | +| D=32 | la_stack_norm2_sq | 4.0 ns [4.0 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 3.9 ns [3.9 ns, 3.9 ns] | 4.3 ns [4.3 ns, 4.3 ns] | +| D=32 | la_stack_solve_from_ldlt | 316.1 ns [315.9 ns, 316.5 ns] | 313.6 ns [313.2 ns, 314.1 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 568.0 ns [566.1 ns, 569.7 ns] | 466.2 ns [464.8 ns, 467.1 ns] | +| D=32 | la_stack_solve_from_lu | 728.4 ns [724.4 ns, 732.7 ns] | 686.0 ns [684.4 ns, 687.3 ns] | -5.8% | faster point estimate; marginal CIs separated | 1.06x | 335.2 ns [334.7 ns, 336.0 ns] | 620.9 ns [619.3 ns, 621.8 ns] | +| D=4 | la_stack_det | 2.6 ns [2.5 ns, 2.6 ns] | 2.6 ns [2.6 ns, 2.6 ns] | +1.3% | slower point estimate; marginal CIs separated | 0.99x | — | — | +| D=4 | la_stack_det_from_ldlt | 1.0 ns [1.0 ns, 1.0 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -20.3% | faster point estimate; marginal CIs separated | 1.25x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | +| D=4 | la_stack_det_from_lu | 1.0 ns [1.0 ns, 1.0 ns] | 0.9 ns [0.9 ns, 0.9 ns] | -13.1% | faster point estimate; marginal CIs separated | 1.15x | 0.6 ns [0.6 ns, 0.6 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +| D=4 | la_stack_det_via_lu | 14.3 ns [14.2 ns, 14.3 ns] | 14.4 ns [14.4 ns, 14.4 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 31.3 ns [31.2 ns, 31.4 ns] | 172.0 ns [169.9 ns, 177.8 ns] | +| D=4 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -0.2% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 1.2 ns [1.2 ns, 1.2 ns] | +| D=4 | la_stack_inf_norm | 2.3 ns [2.2 ns, 2.3 ns] | 2.3 ns [2.3 ns, 2.3 ns] | +0.3% | slower point estimate; marginal CIs separated | 1.00x | 2.0 ns [2.0 ns, 2.0 ns] | 2.0 ns [2.0 ns, 2.0 ns] | +| D=4 | la_stack_ldlt | 22.2 ns [22.2 ns, 22.2 ns] | 22.0 ns [22.0 ns, 22.1 ns] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | 8.0 ns [8.0 ns, 8.0 ns] | 121.3 ns [121.0 ns, 122.0 ns] | +| D=4 | la_stack_ldlt_solve | 24.1 ns [24.1 ns, 24.2 ns] | 24.0 ns [24.0 ns, 24.1 ns] | -0.4% | marginal CIs overlap | 1.00x | 11.6 ns [11.6 ns, 11.6 ns] | 169.0 ns [168.3 ns, 169.4 ns] | +| D=4 | la_stack_lu | 14.0 ns [13.9 ns, 14.0 ns] | 13.9 ns [13.8 ns, 13.9 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 30.0 ns [29.9 ns, 30.1 ns] | 165.5 ns [164.6 ns, 168.1 ns] | +| D=4 | la_stack_lu_solve | 22.0 ns [21.9 ns, 22.0 ns] | 21.9 ns [21.8 ns, 21.9 ns] | -0.5% | faster point estimate; marginal CIs separated | 1.00x | 54.7 ns [54.6 ns, 54.9 ns] | 223.9 ns [222.6 ns, 225.8 ns] | +| D=4 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | +0.5% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=4 | la_stack_solve_from_ldlt | 2.6 ns [2.5 ns, 2.6 ns] | 2.5 ns [2.5 ns, 2.5 ns] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | 5.9 ns [5.9 ns, 5.9 ns] | 41.5 ns [41.0 ns, 41.9 ns] | +| D=4 | la_stack_solve_from_lu | 4.0 ns [4.0 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | 5.9 ns [5.9 ns, 5.9 ns] | 59.5 ns [57.6 ns, 61.1 ns] | +| D=5 | la_stack_det | 41.0 ns [40.8 ns, 41.2 ns] | 62.2 ns [41.0 ns, 62.6 ns] | +51.6% | marginal CIs overlap | 0.66x | — | — | +| D=5 | la_stack_det_from_ldlt | 1.3 ns [1.3 ns, 1.3 ns] | 1.0 ns [1.0 ns, 1.0 ns] | -24.3% | faster point estimate; marginal CIs separated | 1.32x | 0.6 ns [0.6 ns, 0.6 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +| D=5 | la_stack_det_from_lu | 2.0 ns [1.9 ns, 2.0 ns] | 1.1 ns [1.1 ns, 1.1 ns] | -42.9% | faster point estimate; marginal CIs separated | 1.75x | 0.7 ns [0.7 ns, 0.7 ns] | 1.5 ns [1.5 ns, 1.5 ns] | +| D=5 | la_stack_det_via_lu | 33.3 ns [33.2 ns, 33.5 ns] | 32.6 ns [32.6 ns, 32.8 ns] | -2.0% | faster point estimate; marginal CIs separated | 1.02x | 57.6 ns [57.5 ns, 57.8 ns] | 206.8 ns [206.4 ns, 207.7 ns] | +| D=5 | la_stack_dot | 0.9 ns [0.8 ns, 0.9 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 0.7 ns [0.7 ns, 0.8 ns] | 1.5 ns [1.5 ns, 1.5 ns] | +| D=5 | la_stack_inf_norm | 3.5 ns [3.5 ns, 3.5 ns] | 3.5 ns [3.5 ns, 3.5 ns] | +1.1% | slower point estimate; marginal CIs separated | 0.99x | 3.3 ns [3.3 ns, 3.3 ns] | 3.2 ns [3.2 ns, 3.2 ns] | +| D=5 | la_stack_ldlt | 43.8 ns [43.7 ns, 43.9 ns] | 43.5 ns [43.4 ns, 43.5 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 27.7 ns [26.9 ns, 28.7 ns] | 150.0 ns [149.1 ns, 150.8 ns] | +| D=5 | la_stack_ldlt_solve | 47.2 ns [47.1 ns, 47.3 ns] | 47.1 ns [47.0 ns, 47.1 ns] | -0.2% | marginal CIs overlap | 1.00x | 42.3 ns [42.1 ns, 42.4 ns] | 210.3 ns [209.8 ns, 210.9 ns] | +| D=5 | la_stack_lu | 32.8 ns [32.7 ns, 32.9 ns] | 33.0 ns [32.6 ns, 33.2 ns] | +0.6% | marginal CIs overlap | 0.99x | 57.7 ns [57.5 ns, 57.9 ns] | 199.0 ns [198.0 ns, 200.1 ns] | +| D=5 | la_stack_lu_solve | 44.9 ns [44.4 ns, 45.9 ns] | 44.5 ns [44.3 ns, 44.7 ns] | -0.8% | marginal CIs overlap | 1.01x | 71.2 ns [71.1 ns, 71.3 ns] | 293.4 ns [290.1 ns, 306.4 ns] | +| D=5 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 0.6 ns [0.6 ns, 0.6 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=5 | la_stack_solve_from_ldlt | 3.9 ns [3.9 ns, 3.9 ns] | 4.0 ns [3.9 ns, 4.0 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 9.7 ns [9.7 ns, 9.8 ns] | 66.3 ns [63.8 ns, 67.5 ns] | +| D=5 | la_stack_solve_from_lu | 6.1 ns [6.1 ns, 6.1 ns] | 6.1 ns [6.1 ns, 6.1 ns] | -0.0% | marginal CIs overlap | 1.00x | 9.4 ns [9.4 ns, 9.4 ns] | 89.2 ns [88.9 ns, 89.5 ns] | +| D=64 | la_stack_det | 14.99 µs [14.95 µs, 15.03 µs] | 14.95 µs [14.88 µs, 14.98 µs] | -0.3% | marginal CIs overlap | 1.00x | — | — | +| D=64 | la_stack_det_from_ldlt | 32.5 ns [32.4 ns, 32.5 ns] | 23.4 ns [23.4 ns, 23.4 ns] | -27.9% | faster point estimate; marginal CIs separated | 1.39x | 8.7 ns [8.7 ns, 8.7 ns] | 21.6 ns [21.5 ns, 21.6 ns] | +| D=64 | la_stack_det_from_lu | 33.5 ns [33.1 ns, 33.5 ns] | 23.6 ns [23.6 ns, 23.7 ns] | -29.3% | faster point estimate; marginal CIs separated | 1.41x | 8.9 ns [8.9 ns, 9.0 ns] | 22.4 ns [22.4 ns, 22.5 ns] | +| D=64 | la_stack_det_via_lu | 15.03 µs [15.01 µs, 15.06 µs] | 14.86 µs [14.84 µs, 14.88 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 13.17 µs [13.14 µs, 13.19 µs] | 10.70 µs [10.68 µs, 10.71 µs] | +| D=64 | la_stack_dot | 11.2 ns [11.2 ns, 11.3 ns] | 11.0 ns [11.0 ns, 11.0 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | 9.1 ns [9.1 ns, 9.1 ns] | 38.2 ns [38.1 ns, 38.3 ns] | +| D=64 | la_stack_inf_norm | 643.8 ns [642.5 ns, 645.5 ns] | 630.3 ns [628.7 ns, 631.3 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | 1.31 µs [1.30 µs, 1.31 µs] | 1.59 µs [1.58 µs, 1.59 µs] | +| D=64 | la_stack_ldlt | 21.88 µs [21.82 µs, 22.01 µs] | 19.83 µs [19.80 µs, 19.85 µs] | -9.3% | faster point estimate; marginal CIs separated | 1.10x | 10.93 µs [10.92 µs, 10.94 µs] | 9.03 µs [9.02 µs, 9.04 µs] | +| D=64 | la_stack_ldlt_solve | 24.52 µs [24.39 µs, 24.60 µs] | 22.45 µs [22.22 µs, 22.49 µs] | -8.5% | faster point estimate; marginal CIs separated | 1.09x | 12.91 µs [12.89 µs, 12.94 µs] | 10.37 µs [10.35 µs, 10.40 µs] | +| D=64 | la_stack_lu | 14.45 µs [14.42 µs, 14.52 µs] | 14.75 µs [14.74 µs, 14.76 µs] | +2.1% | slower point estimate; marginal CIs separated | 0.98x | 12.98 µs [12.94 µs, 13.01 µs] | 10.56 µs [10.55 µs, 10.58 µs] | +| D=64 | la_stack_lu_solve | 17.51 µs [17.47 µs, 17.55 µs] | 17.36 µs [17.26 µs, 17.41 µs] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 13.88 µs [13.85 µs, 13.90 µs] | 12.20 µs [12.18 µs, 12.22 µs] | +| D=64 | la_stack_norm2_sq | 11.2 ns [11.2 ns, 11.3 ns] | 11.0 ns [10.9 ns, 11.0 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | 7.4 ns [7.4 ns, 7.4 ns] | 6.3 ns [6.3 ns, 6.3 ns] | +| D=64 | la_stack_solve_from_ldlt | 1.11 µs [1.11 µs, 1.12 µs] | 1.09 µs [1.09 µs, 1.10 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | 1.32 µs [1.31 µs, 1.32 µs] | 1.24 µs [1.24 µs, 1.24 µs] | +| D=64 | la_stack_solve_from_lu | 2.72 µs [2.72 µs, 2.74 µs] | 2.76 µs [2.70 µs, 2.79 µs] | +1.3% | marginal CIs overlap | 0.99x | 796.6 ns [795.2 ns, 797.9 ns] | 1.65 µs [1.65 µs, 1.66 µs] | +| D=8 | la_stack_det | 94.9 ns [94.2 ns, 95.9 ns] | 94.7 ns [94.4 ns, 95.1 ns] | -0.2% | marginal CIs overlap | 1.00x | — | — | +| D=8 | la_stack_det_from_ldlt | 2.7 ns [2.7 ns, 2.7 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -51.7% | faster point estimate; marginal CIs separated | 2.07x | 0.9 ns [0.9 ns, 0.9 ns] | 2.0 ns [2.0 ns, 2.0 ns] | +| D=8 | la_stack_det_from_ldlt_balanced_range | 9.3 ns [9.3 ns, 9.4 ns] | 8.8 ns [8.8 ns, 8.8 ns] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | — | — | +| D=8 | la_stack_det_from_lu | 2.8 ns [2.8 ns, 2.9 ns] | 1.5 ns [1.5 ns, 1.5 ns] | -47.4% | faster point estimate; marginal CIs separated | 1.90x | 1.0 ns [1.0 ns, 1.0 ns] | 2.3 ns [2.3 ns, 2.3 ns] | +| D=8 | la_stack_det_from_lu_balanced_range | 9.3 ns [9.3 ns, 9.3 ns] | 9.3 ns [9.3 ns, 9.4 ns] | +0.3% | marginal CIs overlap | 1.00x | — | — | +| D=8 | la_stack_det_via_lu | 88.0 ns [87.4 ns, 88.7 ns] | 85.2 ns [84.9 ns, 85.3 ns] | -3.2% | faster point estimate; marginal CIs separated | 1.03x | 143.3 ns [143.0 ns, 143.7 ns] | 295.2 ns [293.3 ns, 297.7 ns] | +| D=8 | la_stack_dot | 1.0 ns [1.0 ns, 1.0 ns] | 0.9 ns [0.9 ns, 0.9 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 1.1 ns [1.1 ns, 1.1 ns] | 2.3 ns [2.3 ns, 2.3 ns] | +| D=8 | la_stack_inf_norm | 8.5 ns [8.5 ns, 8.5 ns] | 8.5 ns [8.5 ns, 8.5 ns] | -0.3% | faster point estimate; marginal CIs separated | 1.00x | 8.1 ns [8.1 ns, 8.1 ns] | 8.2 ns [8.1 ns, 8.2 ns] | +| D=8 | la_stack_ldlt | 94.1 ns [93.1 ns, 94.7 ns] | 92.3 ns [91.4 ns, 93.2 ns] | -1.8% | marginal CIs overlap | 1.02x | 107.4 ns [106.7 ns, 107.9 ns] | 230.5 ns [226.0 ns, 233.4 ns] | +| D=8 | la_stack_ldlt_ill_conditioned | 93.3 ns [91.8 ns, 94.6 ns] | 91.9 ns [90.9 ns, 92.7 ns] | -1.5% | marginal CIs overlap | 1.02x | — | — | +| D=8 | la_stack_ldlt_solve | 103.4 ns [103.1 ns, 103.8 ns] | 100.8 ns [100.6 ns, 101.1 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | 147.7 ns [141.5 ns, 150.9 ns] | 289.2 ns [288.4 ns, 290.9 ns] | +| D=8 | la_stack_lu | 85.6 ns [85.3 ns, 86.0 ns] | 83.5 ns [83.1 ns, 83.7 ns] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | 143.1 ns [141.4 ns, 145.1 ns] | 278.4 ns [277.5 ns, 280.4 ns] | +| D=8 | la_stack_lu_ill_conditioned | 86.4 ns [85.9 ns, 87.0 ns] | 83.1 ns [82.9 ns, 83.2 ns] | -3.9% | faster point estimate; marginal CIs separated | 1.04x | — | — | +| D=8 | la_stack_lu_pivoting | 94.6 ns [94.4 ns, 94.8 ns] | 90.5 ns [90.4 ns, 90.7 ns] | -4.3% | faster point estimate; marginal CIs separated | 1.05x | — | — | +| D=8 | la_stack_lu_solve | 149.5 ns [149.1 ns, 150.1 ns] | 145.4 ns [138.0 ns, 146.6 ns] | -2.7% | faster point estimate; marginal CIs separated | 1.03x | 188.4 ns [187.4 ns, 189.0 ns] | 381.9 ns [380.5 ns, 383.1 ns] | +| D=8 | la_stack_norm2_sq | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=8 | la_stack_solve_from_ldlt | 8.1 ns [8.1 ns, 8.2 ns] | 8.1 ns [8.1 ns, 8.2 ns] | +0.3% | marginal CIs overlap | 1.00x | 23.5 ns [23.4 ns, 23.7 ns] | 71.9 ns [71.4 ns, 72.2 ns] | +| D=8 | la_stack_solve_from_lu | 13.8 ns [13.7 ns, 13.8 ns] | 13.7 ns [13.6 ns, 13.7 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 16.8 ns [16.8 ns, 16.8 ns] | 96.9 ns [96.7 ns, 97.4 ns] | + +## How to Update + +Local performance reports are generated in isolated temporary worktrees: + +```bash +# Local development: compare the current tree with the latest release +just performance-local + +# Release PR: update docs/performance.md and archive the previous report +just performance-release + +# Build release docs from retained CSV/JSON inputs (no benchmarks) +just performance-doc + +# GitHub Actions release assets +just performance-github-assets + +# Explicit repair +just performance-release +``` + +`just performance-local` writes `performance.md` plus retained `performance.csv` and +`performance.provenance.json` comparison inputs under `target/bench-reports/` without promoting documentation. +It applies staged and unstaged tracked changes; untracked files are excluded. +`just performance-github-assets` writes `target/bench-reports/github-assets-performance.md`. +`just performance-release` performs the same measurement and retention work, then promotes distinct-release documentation. +`just performance-doc` consumes the retained pair from either workflow without benchmarking and promotes it when the package versions differ. +For a distinct pair, `performance-local` followed by `performance-doc` is equivalent to the atomic `performance-release` workflow. + +Older curated release-to-release reports are archived in `docs/archive/performance/`. + +See `docs/BENCHMARKING.md` for the full comparison workflow. diff --git a/docs/assets/bench/vs_linalg_lu_solve_median.csv b/docs/assets/bench/vs_linalg_lu_solve_median.csv index ddb7cac..fba3cbc 100644 --- a/docs/assets/bench/vs_linalg_lu_solve_median.csv +++ b/docs/assets/bench/vs_linalg_lu_solve_median.csv @@ -1,9 +1,9 @@ D,la_stack,la_lo,la_hi,nalgebra,na_lo,na_hi,faer,fa_lo,fa_hi -2,2.043762626268518,2.0422827651419597,2.0447790116664555,4.601323421841004,4.595197301082463,4.608615047162932,151.9390190878473,151.6931342810127,152.54018630708097 -3,9.988548111179517,9.954187559495038,10.007125510422096,23.5131208253108,23.43355332339501,23.614648949741298,196.35702867954777,194.94348729609408,198.75049539724168 -4,21.864804649962238,21.84202072931614,21.880570636063183,54.71614688761136,54.62726895942409,54.87756778849946,223.91031993204984,222.61421792794988,225.8474926387316 -5,44.51008358188431,44.275702584061186,44.717608725166315,71.21900306190079,71.11478152577844,71.30045978657881,293.419765051395,290.0661591010662,306.3860360233699 -8,145.40528452059866,137.96532664767477,146.62531265833474,188.35193148966346,187.44649013949015,188.9754735930736,381.871856125649,380.45259170993273,383.1446190133525 -16,672.490775828649,670.9416553595659,674.0398009950248,585.26069324284,584.5897428943372,586.349779695245,897.2363083497698,895.5233830096844,900.8699633699633 -32,2777.70695399973,2774.6190957703316,2782.4841693051158,2501.3607828952654,2494.2493848743848,2506.2687459411595,2952.7779305246913,2948.077163491427,2959.1092519128833 -64,17357.784731525782,17261.484363636362,17414.59595959596,13878.401216108454,13851.678987455198,13898.104803240742,12199.761458333334,12175.740131578947,12222.186667448404 +2,2.0211314276372025,2.018479942281156,2.0445438481191816,4.4787720282632115,4.471223731681299,4.488903340683946,182.53202843068811,182.06757130922546,183.01508533237856 +3,9.976848651948877,9.898381116607712,10.025906395438968,22.79479095228905,22.713611901221796,22.98916653289352,217.56680047835044,216.1785685588016,219.0290055716943 +4,22.101084470745356,22.061056744915724,22.141461025001234,51.73926857369151,51.47900780022614,51.91779016092275,241.52526920712,239.31700735578784,243.22749256395002 +5,46.069581545860736,45.98934031334168,46.10755327054004,69.0025585241594,68.86491194918514,69.16905109997215,326.84830597342926,324.0143975251199,361.58151429914557 +8,128.36396548733447,128.19900330404025,128.65769248327663,165.93327075645942,164.8158130758386,168.9136037004555,401.4003419166195,396.02358647682604,407.0685093415357 +16,643.5320021938804,641.4668189353472,644.9028128940731,569.4458712557102,568.9098484848485,569.9060010943388,903.140053398982,900.3068397120121,905.2987334534953 +32,2755.7729402136074,2752.579773568824,2761.0723724010572,2710.234582397889,2703.7424869037773,2717.3389959916017,2919.2900818850267,2913.423424369748,2925.1436105476673 +64,17518.63433908046,17364.270300333705,17558.53448275862,14313.979335187058,14297.097222222223,14348.511153198653,12108.782627752282,12092.033074648929,12120.978128313891 diff --git a/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json b/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json index a42a47d..603e870 100644 --- a/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json +++ b/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json @@ -4,7 +4,7 @@ "baseline_command": [ "just", "bench-save-baseline", - "v0.4.4" + "v0.4.5" ], "criterion_dependency": "0.8.2", "current_command": [ @@ -27,40 +27,41 @@ "statistic": "median" }, "measurement": { - "baseline_api_compatibility": "none", - "baseline_commit": "03a6dc751b7bf7c69b833aeb4e20e2acb6da2e4c", + "baseline_api_compatibility": "la_stack_pre_rational_input_api", + "baseline_commit": "78ba1c25beaed7321e175113e0876aac6d763a59", "baseline_git_clean": false, - "baseline_source_state_sha256": "227a2780c989352be2eacf3f32ca67032cc69fc843e596acc386a7c4f7d459f0", - "cargo_lock_sha256": "72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492", + "baseline_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", + "benchmark_contract_sha256": "02a2228e7c2150d4c9c2dc125063a6e3eec03be82e8f7262c341099f2517132d", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", "cpu": "Apple M4 Max (arm64)", - "current_commit": "99d33927e389018c599c009603a7eafffcc25089", + "current_commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", "current_git_clean": false, - "current_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", - "harness_sha256": "164d6bbac2e6cb19b85c81677e4ab4428c3abb130dcfd38a2f5f162a5dd8a905", + "current_source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336", + "harness_sha256": "27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3", "la_stack_sample": "current", "os": "Darwin 25.6.0 arm64", - "peer_release_context": "v0.4.4", + "peer_release_context": "v0.4.5", "peer_sample": "baseline phase under shared current harness", - "rustc": "rustc 1.98.0 (88d9e12ae 2026-08-18)", + "rustc": "rustc 1.98.1 (48a229cea 2026-09-01)", "source": "retained performance-release artifact", "status": "recorded" }, "performance_artifact": { "csv": "target/bench-reports/performance.csv", - "csv_sha256": "4d4f02188ce78414d6018fe0ce23dcc7da07a23b05026843698c2ad32be7d0c8", + "csv_sha256": "b263bb34bcfd43b8fc8109110db9f2e908516aef6c01ce16f70f5ac18dc7ef2d", "provenance": "target/bench-reports/performance.provenance.json", - "provenance_sha256": "fec902d3b444dd3be67255637f56bdb53b7b6a5368a8b2410c963a4e40b6ba5c", + "provenance_sha256": "89144a2899ba73f55d009da4fa20b4e6477600902b93cde469383f719c497508", "release": { - "baseline": "v0.4.4", - "current": "v0.4.5" + "baseline": "v0.4.5", + "current": "v0.4.6" } }, "publication": { - "benchmark_contract": "legacy-retained-artifact", - "cargo_lock_sha256": "72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492", - "commit": "99d33927e389018c599c009603a7eafffcc25089", + "benchmark_contract": "matched", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", + "commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", "correctness_gate": "validated-performance-release-artifact", - "source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007" + "source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336" }, "schema": 2 } diff --git a/docs/assets/bench/vs_linalg_lu_solve_median.svg b/docs/assets/bench/vs_linalg_lu_solve_median.svg index c3cc6f0..66e0022 100644 --- a/docs/assets/bench/vs_linalg_lu_solve_median.svg +++ b/docs/assets/bench/vs_linalg_lu_solve_median.svg @@ -244,51 +244,51 @@ - la-stack v0.4.5 + la-stack v0.4.6 - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -302,47 +302,47 @@ - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -356,47 +356,47 @@ - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/docs/code_organization.md b/docs/code_organization.md index d5ab553..e440f29 100644 --- a/docs/code_organization.md +++ b/docs/code_organization.md @@ -1,6 +1,7 @@ # Code Organization -Module, feature, and file-placement guidance for the single Rust library crate. +Module, feature, and file-placement guidance for the published Rust library and +its unpublished comparison-benchmark package. Read [AGENTS.md](../AGENTS.md) for agent rules and use the [contributor workflow](../CONTRIBUTING.md) for setup and validation commands. @@ -65,8 +66,10 @@ The [Cargo manifest](../Cargo.toml) owns feature and dependency declarations. filter for D≤4. Exact solves use fraction-free forward elimination with first-non-zero pivoting and `BigRational` back-substitution. Rational inputs clear denominators before reusing the integer backend. -- **`bench`** is a cfg-only gate for benchmark targets and - `tests/vs_linalg_inputs.rs`; benchmark libraries remain dev-dependencies. +- **`bench`** is a cfg-only gate for benchmark targets. Benchmark libraries + remain dev-dependencies. Nalgebra and faer belong only to the unpublished + `la-stack-comparison` package under `benches/comparison`, so exact benchmark + builds do not compile either peer library. ## Tests and examples @@ -76,6 +79,9 @@ The [Cargo manifest](../Cargo.toml) owns feature and dependency declarations. - Other `tests/*.rs` suites cover regressions, API contracts, allocation behavior, conversion boundaries, and benchmark inputs. Shared property-test configuration lives in `tests/common/`. +- `benches/comparison/tests/vs_linalg_inputs.rs` checks the shared comparison + fixtures. `just test-bench-inputs` and the full CI test pass include both + workspace packages. - `tests/semgrep/` contains deliberate static-analysis fixtures, not ordinary runnable API examples. - Python tests live under `scripts/tests/` and run with pytest through @@ -94,6 +100,11 @@ intervals, linear forms, and nalgebra/faer comparisons. Helpers under accept only `ValidatedExactInput`, after independent validation outside timing. Adversarial groups include near-singular, large-entry, and Hilbert inputs. +The root package is the default workspace member. `benches/comparison/Cargo.toml` +owns the `vs_linalg` target at `benches/vs_linalg.rs` and its input test. Select +it with `just bench-vs-linalg` or Cargo's `-p la-stack-comparison`. Both packages +inherit the root workspace lints and share the lockfile and target directory. + The [Benchmarking guide](BENCHMARKING.md) owns benchmark commands, methodology, baselines, output locations, and report promotion. The [Scripts guide](../scripts/README.md) owns the Python script inventory and entry points for comparisons, plotting, @@ -105,6 +116,10 @@ Criterion validation. The release workflow packages only datasets that pass that gate; its regression and archive tests live in `scripts/tests/test_release_baseline.py`. +`scripts/criterion_measurements.py` owns raw sample validation shared by hosted +archives and local summaries. `scripts/benchmark_summaries.py` owns complete +local summary serialization, snapshot identity, and lookup after cleanup. + `.github/actions/prepare-release-benchmarks/action.yml` groups tool installation, input validation, and inventory under the release workflow's shared setup timeout. @@ -120,6 +135,9 @@ live in `docs/dev/`; human setup and validation guidance lives in [Measuring coverage](MEASURING_COVERAGE.md) owns local and CI coverage execution. The generated [performance report](performance.md) records measured results; [Benchmarking](BENCHMARKING.md) owns the commands that produce and compare them. +[Local benchmark summaries](performance/README.md) owns complete versioned local +datasets. Completed optimization studies belong under +[archived performance studies](archive/performance/studies/README.md). When adding, removing, renaming, or moving files, update the applicable ownership rows here. Prefer links to the detailed owner over copying its procedure into diff --git a/docs/performance.md b/docs/performance.md index 5a55d65..e49e34f 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -1,7 +1,7 @@ # Benchmark Performance -**la-stack** v0.4.5 · `99d3392` (HEAD) -**Source revision timestamp**: 2026-08-20 21:16:55 UTC (deterministic report metadata; not the benchmark measurement time) +**la-stack** v0.4.6 · `d36a9e9` (HEAD) +**Source revision timestamp**: 2026-09-08 01:59:08 UTC (deterministic report metadata; not the benchmark measurement time) **Benchmark measurement timestamp**: not recorded by Criterion; use the provenance below to identify the measured revisions and environment. **Statistic**: median **Suite**: all @@ -9,7 +9,7 @@ ## Benchmark Results -Comparison against baseline **v0.4.4**: +Comparison against baseline **v0.4.5**: Negative point-estimate change means the current point estimate is smaller; a baseline/current point-estimate ratio above 1.00 has the same meaning. The CI-relation column reports only whether the two marginal Criterion intervals overlap. These are not paired confidence intervals @@ -21,236 +21,280 @@ for the change, so the report makes no statistical-significance or performance-i - CPU: `Apple M4 Max (arm64)` - OS: `Darwin 25.6.0 arm64` -- rustc: `rustc 1.98.0 (88d9e12ae 2026-08-18)` -- Current commit: `99d33927e389018c599c009603a7eafffcc25089` +- rustc: `rustc 1.98.1 (48a229cea 2026-09-01)` +- Current commit: `d36a9e99ec223c4cbbf8a9191818f186159c27f7` - Current Git clean: `false` -- Current source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007` -- Baseline commit: `03a6dc751b7bf7c69b833aeb4e20e2acb6da2e4c` +- Current source-state SHA-256: `b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336` +- Baseline commit: `78ba1c25beaed7321e175113e0876aac6d763a59` - Baseline Git clean: `false` -- Baseline source-state SHA-256: `227a2780c989352be2eacf3f32ca67032cc69fc843e596acc386a7c4f7d459f0` -- Cargo.lock SHA-256: `72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492` -- Benchmark harness SHA-256: `164d6bbac2e6cb19b85c81677e4ab4428c3abb130dcfd38a2f5f162a5dd8a905` +- Baseline source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007` +- Cargo.lock SHA-256: `37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb` +- Benchmark harness SHA-256: `27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3` **Publication and validation environment**: - Publication CPU: `Apple M4 Max (arm64)` - Publication OS: `Darwin 25.6.0 arm64` -- Publication rustc: `rustc 1.98.0 (88d9e12ae 2026-08-18)` -- Publication commit: `99d33927e389018c599c009603a7eafffcc25089` +- Publication rustc: `rustc 1.98.1 (48a229cea 2026-09-01)` +- Publication commit: `d36a9e99ec223c4cbbf8a9191818f186159c27f7` - Publication Git clean: `false` -- Publication source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007` -- Publication Cargo.lock SHA-256: `72b99b4f7f3917d668bb71448198d5d496334684097eac282c859d08d8cf4492` -- Publication harness SHA-256: `164d6bbac2e6cb19b85c81677e4ab4428c3abb130dcfd38a2f5f162a5dd8a905` +- Publication source-state SHA-256: `b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336` +- Publication Cargo.lock SHA-256: `37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb` +- Publication harness SHA-256: `27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3` - Criterion suite/scope: `all` / `release-signal` - Criterion statistic/sample: `median` / `new` - Criterion dependency version: `0.8.2` -- Baseline command: `just bench-save-baseline v0.4.4` +- Baseline command: `just bench-save-baseline v0.4.5` - Current command: `just bench-latest` - Correctness gate: `just test-bench-inputs` passed against both the current and baseline revisions using the shared current fixture harness. -- Validated current revision: `99d33927e389018c599c009603a7eafffcc25089` (Git clean: `false`; +- Validated current revision: `d36a9e99ec223c4cbbf8a9191818f186159c27f7` (Git clean: `false`; + source-state SHA-256: `b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336`) +- Validated baseline revision: `78ba1c25beaed7321e175113e0876aac6d763a59` (Git clean: `false`; source-state SHA-256: `7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007`) -- Validated baseline revision: `03a6dc751b7bf7c69b833aeb4e20e2acb6da2e4c` (Git clean: `false`; - source-state SHA-256: `227a2780c989352be2eacf3f32ca67032cc69fc843e596acc386a7c4f7d459f0`) +- Baseline API compatibility: `la_stack_pre_rational_input_api` selects only source-compatible benchmark calls; + one-sided rows outside the baseline's correctness domain are identified by the retained CSV coverage status and note. ## Exact arithmetic -| Case | Benchmark | v0.4.4 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | +| Case | Benchmark | v0.4.5 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | |:-----|:----------|-------:|-------:|-------:|:-----------|--------:| -| D=2 | det | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | -| D=2 | det_direct | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.5% | marginal CIs overlap | 1.02x | -| D=2 | det_direct_with_errbound | 1.7 ns [1.7 ns, 1.7 ns] | 1.7 ns [1.7 ns, 1.7 ns] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | -| D=2 | det_errbound | 1.6 ns [1.6 ns, 1.6 ns] | 1.6 ns [1.6 ns, 1.6 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | -| D=2 | det_exact | 91.7 ns [91.6 ns, 91.9 ns] | 91.3 ns [91.2 ns, 91.5 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | -| D=2 | det_exact_f64_result | 65.6 ns [65.3 ns, 65.8 ns] | 64.7 ns [64.6 ns, 64.7 ns] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | -| D=2 | det_exact_rounded_f64 | 66.7 ns [66.6 ns, 66.8 ns] | 66.6 ns [66.5 ns, 66.7 ns] | -0.1% | marginal CIs overlap | 1.00x | -| D=2 | det_sign_exact | 2.8 ns [2.7 ns, 2.8 ns] | 2.7 ns [2.7 ns, 2.7 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | -| D=2 | solve_exact | 6.90 µs [6.88 µs, 6.91 µs] | 6.78 µs [6.77 µs, 6.79 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | -| D=2 | solve_exact_f64_result | 8.14 µs [8.13 µs, 8.16 µs] | 7.91 µs [7.89 µs, 7.92 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | -| D=2 | solve_exact_rounded_f64 | 7.25 µs [7.23 µs, 7.27 µs] | 7.10 µs [7.10 µs, 7.11 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | -| D=3 | det | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | det_direct | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | det_direct_with_errbound | 3.3 ns [3.3 ns, 3.4 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -0.0% | marginal CIs overlap | 1.00x | -| D=3 | det_errbound | 3.3 ns [3.3 ns, 3.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | det_exact | 341.9 ns [340.5 ns, 343.5 ns] | 323.7 ns [323.2 ns, 324.3 ns] | -5.3% | faster point estimate; marginal CIs separated | 1.06x | -| D=3 | det_exact_f64_result | 300.9 ns [300.5 ns, 301.6 ns] | 293.7 ns [293.2 ns, 293.9 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | -| D=3 | det_exact_rounded_f64 | 300.5 ns [300.1 ns, 301.0 ns] | 293.7 ns [293.5 ns, 294.0 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | -| D=3 | det_sign_exact | 4.7 ns [4.7 ns, 4.7 ns] | 4.7 ns [4.7 ns, 4.7 ns] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | solve_exact | 30.23 µs [30.12 µs, 30.31 µs] | 29.93 µs [29.89 µs, 29.97 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | solve_exact_f64_result | 32.20 µs [32.13 µs, 32.26 µs] | 31.88 µs [31.83 µs, 31.95 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | -| D=3 | solve_exact_rounded_f64 | 31.46 µs [31.19 µs, 31.53 µs] | 30.49 µs [30.44 µs, 30.52 µs] | -3.1% | faster point estimate; marginal CIs separated | 1.03x | -| D=4 | det | 3.3 ns [3.3 ns, 3.3 ns] | 3.2 ns [3.2 ns, 3.2 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | -| D=4 | det_direct | 2.4 ns [2.4 ns, 2.4 ns] | 2.4 ns [2.4 ns, 2.4 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | det_direct_with_errbound | 6.9 ns [6.9 ns, 6.9 ns] | 6.8 ns [6.8 ns, 6.8 ns] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | det_errbound | 6.8 ns [6.8 ns, 6.8 ns] | 6.7 ns [6.7 ns, 6.7 ns] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | det_exact | 1.02 µs [1.02 µs, 1.03 µs] | 1.01 µs [1.01 µs, 1.01 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | det_exact_f64_result | 993.0 ns [990.5 ns, 996.0 ns] | 976.7 ns [974.5 ns, 978.7 ns] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | -| D=4 | det_exact_rounded_f64 | 991.3 ns [989.1 ns, 993.3 ns] | 973.8 ns [973.0 ns, 976.3 ns] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | -| D=4 | det_sign_exact | 7.8 ns [7.8 ns, 7.8 ns] | 7.7 ns [7.7 ns, 7.7 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | solve_exact | 78.81 µs [78.73 µs, 78.97 µs] | 77.91 µs [77.80 µs, 77.99 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | solve_exact_f64_result | 81.82 µs [81.72 µs, 81.92 µs] | 80.71 µs [80.62 µs, 80.79 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | -| D=4 | solve_exact_rounded_f64 | 79.66 µs [79.57 µs, 79.83 µs] | 78.66 µs [78.57 µs, 78.76 µs] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | -| D=5 | det | 25.1 ns [25.1 ns, 25.2 ns] | 25.0 ns [24.9 ns, 25.1 ns] | -0.6% | marginal CIs overlap | 1.01x | -| D=5 | det_exact | 3.08 µs [3.06 µs, 3.12 µs] | 2.94 µs [2.94 µs, 2.95 µs] | -4.4% | faster point estimate; marginal CIs separated | 1.05x | -| D=5 | det_exact_f64_result | 3.02 µs [3.01 µs, 3.03 µs] | 2.91 µs [2.90 µs, 2.91 µs] | -3.7% | faster point estimate; marginal CIs separated | 1.04x | -| D=5 | det_exact_rounded_f64 | 2.98 µs [2.98 µs, 2.99 µs] | 2.96 µs [2.95 µs, 2.97 µs] | -0.6% | faster point estimate; marginal CIs separated | 1.01x | -| D=5 | det_sign_exact | 3.15 µs [3.14 µs, 3.17 µs] | 3.05 µs [3.04 µs, 3.05 µs] | -3.4% | faster point estimate; marginal CIs separated | 1.04x | -| D=5 | solve_exact | 156.87 µs [156.58 µs, 157.10 µs] | 155.34 µs [155.10 µs, 155.58 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | -| D=5 | solve_exact_f64_result | 159.75 µs [159.55 µs, 160.17 µs] | 158.29 µs [158.09 µs, 158.43 µs] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | -| D=5 | solve_exact_rounded_f64 | 159.08 µs [158.45 µs, 160.00 µs] | 156.37 µs [156.22 µs, 156.57 µs] | -1.7% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 4x4 | det_exact | 1.13 µs [1.12 µs, 1.13 µs] | 1.10 µs [1.09 µs, 1.10 µs] | -2.8% | faster point estimate; marginal CIs separated | 1.03x | -| Hilbert 4x4 | det_sign_exact | 8.0 ns [7.9 ns, 8.0 ns] | 7.7 ns [7.7 ns, 7.7 ns] | -3.2% | faster point estimate; marginal CIs separated | 1.03x | -| Hilbert 4x4 | solve_exact | 59.49 µs [59.37 µs, 59.59 µs] | 58.24 µs [58.12 µs, 58.35 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 4x4 | solve_exact_f64_result | 61.76 µs [61.70 µs, 61.84 µs] | 60.89 µs [60.80 µs, 60.95 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | -| Hilbert 4x4 | solve_exact_rounded_f64 | 60.17 µs [60.12 µs, 60.28 µs] | 58.88 µs [58.75 µs, 59.03 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 5x5 | det_exact | 3.13 µs [3.12 µs, 3.13 µs] | 3.05 µs [3.03 µs, 3.05 µs] | -2.6% | faster point estimate; marginal CIs separated | 1.03x | -| Hilbert 5x5 | det_sign_exact | 3.33 µs [3.32 µs, 3.34 µs] | 3.27 µs [3.26 µs, 3.28 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 5x5 | solve_exact | 122.74 µs [122.59 µs, 122.86 µs] | 120.11 µs [119.87 µs, 120.28 µs] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 5x5 | solve_exact_f64_result | 125.85 µs [125.61 µs, 126.01 µs] | 123.42 µs [123.24 µs, 123.55 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | -| Hilbert 5x5 | solve_exact_rounded_f64 | 124.06 µs [123.87 µs, 124.28 µs] | 122.12 µs [121.79 µs, 122.49 µs] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | -| Large entries 3x3 | det_exact | 309.9 ns [308.3 ns, 310.7 ns] | 290.4 ns [290.0 ns, 291.4 ns] | -6.3% | faster point estimate; marginal CIs separated | 1.07x | -| Large entries 3x3 | det_sign_exact | 291.0 ns [289.7 ns, 292.2 ns] | 282.1 ns [281.0 ns, 283.3 ns] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | -| Large entries 3x3 | solve_exact | 95.06 µs [94.85 µs, 95.29 µs] | 92.60 µs [92.46 µs, 92.76 µs] | -2.6% | faster point estimate; marginal CIs separated | 1.03x | -| Large entries 3x3 | solve_exact_f64_result | 96.49 µs [96.09 µs, 97.15 µs] | 93.61 µs [93.42 µs, 93.81 µs] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | -| Large entries 3x3 | solve_exact_rounded_f64 | 95.16 µs [94.97 µs, 95.34 µs] | 93.36 µs [93.20 µs, 93.55 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | -| Near-singular 3x3 | det_exact | 322.6 ns [321.3 ns, 325.5 ns] | 303.0 ns [302.2 ns, 303.5 ns] | -6.1% | faster point estimate; marginal CIs separated | 1.06x | -| Near-singular 3x3 | det_sign_exact | 372.6 ns [370.5 ns, 374.2 ns] | 345.8 ns [344.2 ns, 347.4 ns] | -7.2% | faster point estimate; marginal CIs separated | 1.08x | -| Near-singular 3x3 | solve_exact | 2.42 µs [2.41 µs, 2.43 µs] | 2.34 µs [2.34 µs, 2.35 µs] | -3.0% | faster point estimate; marginal CIs separated | 1.03x | -| Near-singular 3x3 | solve_exact_f64_result | 2.51 µs [2.49 µs, 2.52 µs] | 2.46 µs [2.45 µs, 2.47 µs] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | -| Near-singular 3x3 | solve_exact_rounded_f64 | 2.42 µs [2.42 µs, 2.43 µs] | 2.35 µs [2.35 µs, 2.36 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=2 | det_exact | 3.20 µs [3.19 µs, 3.20 µs] | 3.13 µs [3.13 µs, 3.13 µs] | -2.0% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=2 | det_sign_exact | 141.6 ns [140.8 ns, 143.3 ns] | 136.5 ns [135.7 ns, 137.2 ns] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | -| Random corpus D=2 | solve_exact | 69.25 µs [69.09 µs, 69.50 µs] | 68.00 µs [67.75 µs, 68.99 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=2 | solve_exact_f64_result | 80.02 µs [79.86 µs, 80.24 µs] | 78.04 µs [77.88 µs, 78.24 µs] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=2 | solve_exact_rounded_f64 | 70.51 µs [70.05 µs, 70.90 µs] | 67.94 µs [67.89 µs, 68.00 µs] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | -| Random corpus D=3 | det_exact | 9.03 µs [8.95 µs, 9.10 µs] | 8.81 µs [8.24 µs, 8.89 µs] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=3 | det_sign_exact | 228.6 ns [228.3 ns, 228.8 ns] | 225.0 ns [224.8 ns, 225.1 ns] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=3 | solve_exact | 219.99 µs [219.73 µs, 220.21 µs] | 216.21 µs [215.83 µs, 216.36 µs] | -1.7% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=3 | solve_exact_f64_result | 235.73 µs [234.74 µs, 236.39 µs] | 230.14 µs [229.96 µs, 230.31 µs] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=3 | solve_exact_rounded_f64 | 222.81 µs [222.46 µs, 223.31 µs] | 217.76 µs [217.35 µs, 218.01 µs] | -2.3% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=4 | det_exact | 25.74 µs [25.66 µs, 25.87 µs] | 24.87 µs [24.84 µs, 24.98 µs] | -3.4% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=4 | det_sign_exact | 434.0 ns [432.4 ns, 435.8 ns] | 424.5 ns [423.9 ns, 425.6 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=4 | solve_exact | 511.24 µs [509.70 µs, 513.54 µs] | 493.20 µs [492.65 µs, 493.60 µs] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | -| Random corpus D=4 | solve_exact_f64_result | 531.44 µs [528.39 µs, 535.08 µs] | 513.06 µs [512.52 µs, 513.31 µs] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | -| Random corpus D=4 | solve_exact_rounded_f64 | 502.60 µs [502.00 µs, 503.33 µs] | 494.39 µs [493.41 µs, 495.23 µs] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=5 | det_exact | 47.95 µs [47.47 µs, 48.29 µs] | 46.58 µs [46.42 µs, 46.65 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=5 | det_sign_exact | 48.52 µs [47.83 µs, 48.94 µs] | 51.72 µs [50.78 µs, 52.35 µs] | +6.6% | slower point estimate; marginal CIs separated | 0.94x | -| Random corpus D=5 | solve_exact | 994.36 µs [993.76 µs, 995.50 µs] | 972.74 µs [971.25 µs, 974.13 µs] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | -| Random corpus D=5 | solve_exact_f64_result | 1.02 ms [1.02 ms, 1.02 ms] | 992.23 µs [990.24 µs, 993.69 µs] | -2.9% | faster point estimate; marginal CIs separated | 1.03x | -| Random corpus D=5 | solve_exact_rounded_f64 | 1.03 ms [1.03 ms, 1.04 ms] | 972.11 µs [970.46 µs, 973.74 µs] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | +| D=2 | det | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -0.2% | marginal CIs overlap | 1.00x | +| D=2 | det_direct | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -0.3% | marginal CIs overlap | 1.00x | +| D=2 | det_direct_with_errbound | 1.7 ns [1.7 ns, 1.7 ns] | 1.7 ns [1.7 ns, 1.7 ns] | -0.0% | marginal CIs overlap | 1.00x | +| D=2 | det_errbound | 1.7 ns [1.6 ns, 1.7 ns] | 1.6 ns [1.6 ns, 1.6 ns] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | +| D=2 | det_exact | 110.5 ns [110.4 ns, 110.7 ns] | 100.4 ns [100.3 ns, 100.5 ns] | -9.2% | faster point estimate; marginal CIs separated | 1.10x | +| D=2 | det_exact_f64_result | 71.3 ns [71.2 ns, 71.5 ns] | 73.1 ns [72.9 ns, 73.2 ns] | +2.5% | slower point estimate; marginal CIs separated | 0.98x | +| D=2 | det_exact_rounded_f64 | 72.7 ns [72.6 ns, 72.7 ns] | 73.3 ns [73.2 ns, 73.4 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | +| D=2 | det_sign_exact | 2.7 ns [2.7 ns, 2.7 ns] | 3.0 ns [3.0 ns, 3.0 ns] | +9.1% | slower point estimate; marginal CIs separated | 0.92x | +| D=2 | solve_exact | 7.06 µs [7.05 µs, 7.07 µs] | 7.10 µs [7.09 µs, 7.12 µs] | +0.7% | slower point estimate; marginal CIs separated | 0.99x | +| D=2 | solve_exact_f64_result | 8.28 µs [8.26 µs, 8.28 µs] | 7.33 µs [7.32 µs, 7.34 µs] | -11.5% | faster point estimate; marginal CIs separated | 1.13x | +| D=2 | solve_exact_rounded_f64 | 7.48 µs [7.47 µs, 7.49 µs] | 7.55 µs [7.54 µs, 7.56 µs] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | +| D=3 | det | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +0.1% | marginal CIs overlap | 1.00x | +| D=3 | det_direct | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +2.9% | slower point estimate; marginal CIs separated | 0.97x | +| D=3 | det_direct_with_errbound | 3.4 ns [3.3 ns, 3.4 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -0.5% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | det_errbound | 3.3 ns [3.3 ns, 3.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | +0.1% | slower point estimate; marginal CIs separated | 1.00x | +| D=3 | det_exact | 370.6 ns [369.9 ns, 371.5 ns] | 338.9 ns [338.5 ns, 339.4 ns] | -8.6% | faster point estimate; marginal CIs separated | 1.09x | +| D=3 | det_exact_f64_result | 338.5 ns [338.0 ns, 339.2 ns] | 313.9 ns [313.2 ns, 314.4 ns] | -7.3% | faster point estimate; marginal CIs separated | 1.08x | +| D=3 | det_exact_rounded_f64 | 340.1 ns [338.8 ns, 341.2 ns] | 317.2 ns [316.0 ns, 318.2 ns] | -6.7% | faster point estimate; marginal CIs separated | 1.07x | +| D=3 | det_sign_exact | 4.7 ns [4.7 ns, 4.7 ns] | 4.7 ns [4.7 ns, 4.7 ns] | -0.0% | marginal CIs overlap | 1.00x | +| D=3 | solve_exact | 30.84 µs [30.78 µs, 30.89 µs] | 30.60 µs [30.51 µs, 30.67 µs] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | +| D=3 | solve_exact_f64_result | 32.80 µs [32.76 µs, 32.87 µs] | 30.92 µs [30.86 µs, 30.96 µs] | -5.7% | faster point estimate; marginal CIs separated | 1.06x | +| D=3 | solve_exact_rounded_f64 | 31.46 µs [31.35 µs, 31.60 µs] | 31.60 µs [31.55 µs, 31.72 µs] | +0.5% | marginal CIs overlap | 1.00x | +| D=4 | det | 3.2 ns [3.2 ns, 3.2 ns] | 3.2 ns [3.2 ns, 3.2 ns] | -0.1% | marginal CIs overlap | 1.00x | +| D=4 | det_direct | 2.4 ns [2.4 ns, 2.4 ns] | 2.4 ns [2.4 ns, 2.4 ns] | -0.0% | marginal CIs overlap | 1.00x | +| D=4 | det_direct_with_errbound | 6.8 ns [6.8 ns, 6.8 ns] | 6.8 ns [6.8 ns, 6.8 ns] | +0.2% | slower point estimate; marginal CIs separated | 1.00x | +| D=4 | det_errbound | 6.7 ns [6.7 ns, 6.7 ns] | 6.7 ns [6.7 ns, 6.7 ns] | +0.1% | slower point estimate; marginal CIs separated | 1.00x | +| D=4 | det_exact | 1.22 µs [1.21 µs, 1.22 µs] | 1.01 µs [1.01 µs, 1.01 µs] | -17.0% | faster point estimate; marginal CIs separated | 1.20x | +| D=4 | det_exact_f64_result | 1.17 µs [1.16 µs, 1.17 µs] | 1.06 µs [1.05 µs, 1.06 µs] | -9.6% | faster point estimate; marginal CIs separated | 1.11x | +| D=4 | det_exact_rounded_f64 | 1.17 µs [1.17 µs, 1.17 µs] | 1.01 µs [1.01 µs, 1.01 µs] | -13.8% | faster point estimate; marginal CIs separated | 1.16x | +| D=4 | det_sign_exact | 7.7 ns [7.7 ns, 7.7 ns] | 8.0 ns [8.0 ns, 8.0 ns] | +3.6% | slower point estimate; marginal CIs separated | 0.97x | +| D=4 | solve_exact | 80.39 µs [80.27 µs, 80.49 µs] | 79.18 µs [79.08 µs, 79.34 µs] | -1.5% | faster point estimate; marginal CIs separated | 1.02x | +| D=4 | solve_exact_f64_result | 83.39 µs [83.24 µs, 83.63 µs] | 79.34 µs [79.13 µs, 79.50 µs] | -4.9% | faster point estimate; marginal CIs separated | 1.05x | +| D=4 | solve_exact_rounded_f64 | 81.02 µs [80.74 µs, 81.52 µs] | 79.86 µs [79.66 µs, 80.05 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | det | 24.7 ns [24.7 ns, 24.8 ns] | 25.0 ns [25.0 ns, 25.1 ns] | +1.4% | slower point estimate; marginal CIs separated | 0.99x | +| D=5 | det_exact | 3.54 µs [3.52 µs, 3.54 µs] | 3.74 µs [3.71 µs, 3.79 µs] | +5.7% | slower point estimate; marginal CIs separated | 0.95x | +| D=5 | det_exact_f64_result | 3.49 µs [3.48 µs, 3.50 µs] | 3.54 µs [3.54 µs, 3.55 µs] | +1.7% | slower point estimate; marginal CIs separated | 0.98x | +| D=5 | det_exact_rounded_f64 | 3.47 µs [3.46 µs, 3.48 µs] | 3.61 µs [3.60 µs, 3.61 µs] | +3.8% | slower point estimate; marginal CIs separated | 0.96x | +| D=5 | det_sign_exact | 3.58 µs [3.57 µs, 3.59 µs] | 3.70 µs [3.70 µs, 3.71 µs] | +3.5% | slower point estimate; marginal CIs separated | 0.97x | +| D=5 | solve_exact | 159.88 µs [159.63 µs, 160.24 µs] | 157.60 µs [157.28 µs, 157.89 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| D=5 | solve_exact_f64_result | 163.37 µs [162.91 µs, 163.71 µs] | 157.72 µs [157.38 µs, 157.93 µs] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | +| D=5 | solve_exact_rounded_f64 | 161.50 µs [161.20 µs, 161.73 µs] | 164.26 µs [163.54 µs, 164.87 µs] | +1.7% | slower point estimate; marginal CIs separated | 0.98x | +| Hilbert 4x4 | det_exact | 1.34 µs [1.33 µs, 1.35 µs] | 1.04 µs [1.04 µs, 1.05 µs] | -22.3% | faster point estimate; marginal CIs separated | 1.29x | +| Hilbert 4x4 | det_sign_exact | 7.7 ns [7.7 ns, 7.7 ns] | 8.0 ns [8.0 ns, 8.0 ns] | +3.4% | slower point estimate; marginal CIs separated | 0.97x | +| Hilbert 4x4 | solve_exact | 60.21 µs [60.13 µs, 60.29 µs] | 59.56 µs [59.47 µs, 59.63 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | +| Hilbert 4x4 | solve_exact_f64_result | 62.75 µs [62.65 µs, 62.89 µs] | 59.74 µs [59.59 µs, 59.79 µs] | -4.8% | faster point estimate; marginal CIs separated | 1.05x | +| Hilbert 4x4 | solve_exact_rounded_f64 | 61.09 µs [60.95 µs, 61.18 µs] | 60.47 µs [60.26 µs, 60.62 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | +| Hilbert 5x5 | det_exact | 3.68 µs [3.66 µs, 3.69 µs] | 3.75 µs [3.74 µs, 3.76 µs] | +1.9% | slower point estimate; marginal CIs separated | 0.98x | +| Hilbert 5x5 | det_sign_exact | 3.87 µs [3.87 µs, 3.88 µs] | 3.92 µs [3.92 µs, 3.93 µs] | +1.1% | slower point estimate; marginal CIs separated | 0.99x | +| Hilbert 5x5 | solve_exact | 124.69 µs [124.44 µs, 124.97 µs] | 122.82 µs [122.53 µs, 122.95 µs] | -1.5% | faster point estimate; marginal CIs separated | 1.02x | +| Hilbert 5x5 | solve_exact_f64_result | 127.73 µs [127.44 µs, 128.19 µs] | 122.06 µs [121.91 µs, 122.40 µs] | -4.4% | faster point estimate; marginal CIs separated | 1.05x | +| Hilbert 5x5 | solve_exact_rounded_f64 | 126.57 µs [126.11 µs, 126.93 µs] | 124.52 µs [124.21 µs, 124.64 µs] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | +| Large entries 3x3 | det_exact | 338.5 ns [337.7 ns, 339.5 ns] | 341.6 ns [340.6 ns, 343.9 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | +| Large entries 3x3 | det_sign_exact | 320.8 ns [319.6 ns, 323.0 ns] | 334.9 ns [334.1 ns, 337.0 ns] | +4.4% | slower point estimate; marginal CIs separated | 0.96x | +| Large entries 3x3 | solve_exact | 93.99 µs [93.81 µs, 94.26 µs] | 93.14 µs [92.93 µs, 93.30 µs] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | +| Large entries 3x3 | solve_exact_f64_result | 94.71 µs [94.65 µs, 94.80 µs] | 93.37 µs [93.24 µs, 93.46 µs] | -1.4% | faster point estimate; marginal CIs separated | 1.01x | +| Large entries 3x3 | solve_exact_rounded_f64 | 94.49 µs [94.43 µs, 94.61 µs] | 93.32 µs [93.20 µs, 93.38 µs] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | +| Near-singular 3x3 | det_exact | 342.0 ns [341.2 ns, 342.8 ns] | 334.5 ns [333.8 ns, 336.3 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | +| Near-singular 3x3 | det_sign_exact | 398.3 ns [394.8 ns, 401.2 ns] | 360.9 ns [360.5 ns, 361.6 ns] | -9.4% | faster point estimate; marginal CIs separated | 1.10x | +| Near-singular 3x3 | solve_exact | 2.60 µs [2.60 µs, 2.61 µs] | 2.81 µs [2.80 µs, 2.81 µs] | +7.9% | slower point estimate; marginal CIs separated | 0.93x | +| Near-singular 3x3 | solve_exact_f64_result | 2.70 µs [2.70 µs, 2.71 µs] | 2.81 µs [2.80 µs, 2.81 µs] | +3.8% | slower point estimate; marginal CIs separated | 0.96x | +| Near-singular 3x3 | solve_exact_rounded_f64 | 2.60 µs [2.60 µs, 2.61 µs] | 2.78 µs [2.77 µs, 2.80 µs] | +6.9% | slower point estimate; marginal CIs separated | 0.94x | +| Random corpus D=2 | det_exact | 3.12 µs [3.12 µs, 3.12 µs] | 3.16 µs [3.14 µs, 3.18 µs] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | +| Random corpus D=2 | det_sign_exact | 136.4 ns [135.6 ns, 137.0 ns] | 149.9 ns [148.9 ns, 150.9 ns] | +9.9% | slower point estimate; marginal CIs separated | 0.91x | +| Random corpus D=2 | solve_exact | 67.47 µs [67.33 µs, 67.59 µs] | 78.46 µs [78.37 µs, 78.65 µs] | +16.3% | slower point estimate; marginal CIs separated | 0.86x | +| Random corpus D=2 | solve_exact_f64_result | 78.30 µs [77.84 µs, 78.74 µs] | 79.81 µs [79.67 µs, 79.96 µs] | +1.9% | slower point estimate; marginal CIs separated | 0.98x | +| Random corpus D=2 | solve_exact_rounded_f64 | 68.56 µs [68.41 µs, 68.68 µs] | 82.23 µs [82.02 µs, 82.37 µs] | +19.9% | slower point estimate; marginal CIs separated | 0.83x | +| Random corpus D=3 | det_exact | 8.35 µs [8.08 µs, 8.64 µs] | 8.47 µs [8.44 µs, 8.49 µs] | +1.5% | marginal CIs overlap | 0.99x | +| Random corpus D=3 | det_sign_exact | 225.1 ns [225.0 ns, 225.2 ns] | 227.9 ns [227.4 ns, 228.3 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | +| Random corpus D=3 | solve_exact | 214.24 µs [213.80 µs, 214.55 µs] | 239.62 µs [239.14 µs, 240.19 µs] | +11.9% | slower point estimate; marginal CIs separated | 0.89x | +| Random corpus D=3 | solve_exact_f64_result | 229.92 µs [229.52 µs, 230.51 µs] | 240.54 µs [240.00 µs, 241.28 µs] | +4.6% | slower point estimate; marginal CIs separated | 0.96x | +| Random corpus D=3 | solve_exact_rounded_f64 | 217.63 µs [217.29 µs, 217.94 µs] | 242.67 µs [242.06 µs, 243.32 µs] | +11.5% | slower point estimate; marginal CIs separated | 0.90x | +| Random corpus D=4 | det_exact | 25.26 µs [25.21 µs, 25.30 µs] | 21.20 µs [21.16 µs, 21.27 µs] | -16.1% | faster point estimate; marginal CIs separated | 1.19x | +| Random corpus D=4 | det_sign_exact | 424.5 ns [423.1 ns, 425.6 ns] | 454.6 ns [452.7 ns, 456.0 ns] | +7.1% | slower point estimate; marginal CIs separated | 0.93x | +| Random corpus D=4 | solve_exact | 489.45 µs [488.84 µs, 490.29 µs] | 535.37 µs [533.84 µs, 537.11 µs] | +9.4% | slower point estimate; marginal CIs separated | 0.91x | +| Random corpus D=4 | solve_exact_f64_result | 507.75 µs [507.05 µs, 508.51 µs] | 534.53 µs [533.89 µs, 535.33 µs] | +5.3% | slower point estimate; marginal CIs separated | 0.95x | +| Random corpus D=4 | solve_exact_rounded_f64 | 491.51 µs [490.45 µs, 491.98 µs] | 535.39 µs [535.09 µs, 535.96 µs] | +8.9% | slower point estimate; marginal CIs separated | 0.92x | +| Random corpus D=5 | det_exact | 47.41 µs [47.34 µs, 47.50 µs] | 55.99 µs [55.88 µs, 56.13 µs] | +18.1% | slower point estimate; marginal CIs separated | 0.85x | +| Random corpus D=5 | det_sign_exact | 49.54 µs [48.76 µs, 50.88 µs] | 61.93 µs [61.88 µs, 62.04 µs] | +25.0% | slower point estimate; marginal CIs separated | 0.80x | +| Random corpus D=5 | solve_exact | 965.82 µs [964.45 µs, 966.73 µs] | 1.04 ms [1.04 ms, 1.04 ms] | +8.1% | slower point estimate; marginal CIs separated | 0.92x | +| Random corpus D=5 | solve_exact_f64_result | 987.58 µs [986.29 µs, 989.22 µs] | 1.04 ms [1.04 ms, 1.04 ms] | +5.5% | slower point estimate; marginal CIs separated | 0.95x | +| Random corpus D=5 | solve_exact_rounded_f64 | 966.85 µs [965.47 µs, 968.31 µs] | 1.04 ms [1.04 ms, 1.05 ms] | +8.1% | slower point estimate; marginal CIs separated | 0.93x | ## vs_linalg -| Case | Benchmark | v0.4.4 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | v0.4.4 nalgebra | v0.4.4 faer | +| Case | Benchmark | v0.4.5 (point + CI) | Latest (point + CI) | Point-estimate change | CI relation | Point-estimate ratio | v0.4.5 nalgebra | v0.4.5 faer | |:-----|:----------|-------:|-------:|-------:|:-----------|--------:|-------:|-------:| -| D=16 | la_stack_det | 432.1 ns [428.1 ns, 433.9 ns] | 436.8 ns [435.3 ns, 438.7 ns] | +1.1% | slower point estimate; marginal CIs separated | 0.99x | — | — | -| D=16 | la_stack_det_from_ldlt | 3.5 ns [3.4 ns, 3.6 ns] | 2.9 ns [2.9 ns, 2.9 ns] | -17.7% | faster point estimate; marginal CIs separated | 1.21x | 1.7 ns [1.7 ns, 1.7 ns] | 4.5 ns [4.5 ns, 4.6 ns] | -| D=16 | la_stack_det_from_lu | 4.2 ns [4.1 ns, 4.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | -22.4% | faster point estimate; marginal CIs separated | 1.29x | 1.8 ns [1.8 ns, 1.8 ns] | 5.0 ns [4.9 ns, 5.0 ns] | -| D=16 | la_stack_det_via_lu | 423.2 ns [418.2 ns, 427.0 ns] | 422.8 ns [420.8 ns, 424.7 ns] | -0.1% | marginal CIs overlap | 1.00x | 458.2 ns [457.0 ns, 458.6 ns] | 679.3 ns [672.2 ns, 683.9 ns] | -| D=16 | la_stack_dot | 2.4 ns [2.4 ns, 2.4 ns] | 2.3 ns [2.3 ns, 2.3 ns] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | 1.9 ns [1.9 ns, 1.9 ns] | 4.6 ns [4.6 ns, 4.6 ns] | -| D=16 | la_stack_inf_norm | 33.5 ns [33.3 ns, 33.6 ns] | 32.7 ns [32.7 ns, 32.7 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | 33.4 ns [33.2 ns, 33.6 ns] | 33.4 ns [33.3 ns, 33.5 ns] | -| D=16 | la_stack_ldlt | 394.2 ns [392.7 ns, 395.9 ns] | 390.6 ns [389.5 ns, 391.2 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 408.4 ns [407.3 ns, 410.1 ns] | 446.8 ns [443.5 ns, 448.3 ns] | -| D=16 | la_stack_ldlt_solve | 433.6 ns [432.5 ns, 434.6 ns] | 436.1 ns [435.2 ns, 437.4 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | 638.5 ns [637.9 ns, 640.1 ns] | 624.6 ns [623.7 ns, 626.6 ns] | -| D=16 | la_stack_lu | 398.6 ns [397.3 ns, 400.9 ns] | 403.5 ns [401.3 ns, 405.9 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 465.6 ns [464.7 ns, 466.9 ns] | 658.8 ns [654.2 ns, 665.1 ns] | -| D=16 | la_stack_lu_solve | 667.8 ns [665.2 ns, 672.5 ns] | 672.5 ns [670.9 ns, 674.0 ns] | +0.7% | marginal CIs overlap | 0.99x | 585.3 ns [584.6 ns, 586.3 ns] | 897.2 ns [895.5 ns, 900.9 ns] | -| D=16 | la_stack_norm2_sq | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | -3.5% | faster point estimate; marginal CIs separated | 1.04x | 1.5 ns [1.5 ns, 1.5 ns] | 4.2 ns [4.2 ns, 4.2 ns] | -| D=16 | la_stack_solve_from_ldlt | 28.0 ns [28.0 ns, 28.1 ns] | 27.7 ns [27.7 ns, 27.8 ns] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | 126.5 ns [126.1 ns, 127.1 ns] | 179.6 ns [178.8 ns, 180.2 ns] | -| D=16 | la_stack_solve_from_lu | 204.7 ns [204.0 ns, 205.2 ns] | 203.1 ns [202.5 ns, 204.0 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 95.3 ns [95.2 ns, 95.5 ns] | 245.0 ns [244.1 ns, 247.1 ns] | -| D=2 | la_stack_det | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +2.3% | slower point estimate; marginal CIs separated | 0.98x | — | — | -| D=2 | la_stack_det_from_ldlt | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -| D=2 | la_stack_det_from_lu | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -0.1% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -| D=2 | la_stack_det_via_lu | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | 0.8 ns [0.8 ns, 0.8 ns] | 98.3 ns [97.9 ns, 99.0 ns] | -| D=2 | la_stack_dot | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +5.3% | slower point estimate; marginal CIs separated | 0.95x | 0.6 ns [0.6 ns, 0.6 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -| D=2 | la_stack_inf_norm | 0.7 ns [0.7 ns, 0.7 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -8.9% | faster point estimate; marginal CIs separated | 1.10x | 0.5 ns [0.5 ns, 0.5 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -| D=2 | la_stack_ldlt | 6.8 ns [6.8 ns, 6.9 ns] | 7.1 ns [7.1 ns, 7.1 ns] | +3.7% | slower point estimate; marginal CIs separated | 0.96x | 1.7 ns [1.7 ns, 1.7 ns] | 81.6 ns [81.4 ns, 81.8 ns] | -| D=2 | la_stack_ldlt_solve | 9.9 ns [9.9 ns, 9.9 ns] | 10.1 ns [10.0 ns, 10.1 ns] | +2.1% | slower point estimate; marginal CIs separated | 0.98x | 2.7 ns [2.7 ns, 2.7 ns] | 124.6 ns [124.2 ns, 125.1 ns] | -| D=2 | la_stack_lu | 1.6 ns [1.6 ns, 1.6 ns] | 1.6 ns [1.6 ns, 1.6 ns] | +2.4% | slower point estimate; marginal CIs separated | 0.98x | 1.6 ns [1.6 ns, 1.6 ns] | 95.9 ns [95.2 ns, 96.3 ns] | -| D=2 | la_stack_lu_solve | 2.1 ns [2.0 ns, 2.1 ns] | 2.0 ns [2.0 ns, 2.0 ns] | -0.6% | marginal CIs overlap | 1.01x | 4.6 ns [4.6 ns, 4.6 ns] | 151.9 ns [151.7 ns, 152.5 ns] | -| D=2 | la_stack_norm2_sq | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | +1.0% | slower point estimate; marginal CIs separated | 0.99x | 0.4 ns [0.4 ns, 0.4 ns] | 4.2 ns [4.2 ns, 4.2 ns] | -| D=2 | la_stack_solve_from_ldlt | 1.2 ns [1.2 ns, 1.2 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +1.3% | slower point estimate; marginal CIs separated | 0.99x | 1.3 ns [1.3 ns, 1.3 ns] | 37.6 ns [37.4 ns, 37.9 ns] | -| D=2 | la_stack_solve_from_lu | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +2.6% | slower point estimate; marginal CIs separated | 0.98x | 2.9 ns [2.9 ns, 2.9 ns] | 48.8 ns [48.6 ns, 49.1 ns] | -| D=3 | la_stack_det | 1.4 ns [1.3 ns, 1.4 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | — | — | -| D=3 | la_stack_det_from_ldlt | 0.7 ns [0.7 ns, 0.7 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -19.6% | faster point estimate; marginal CIs separated | 1.24x | 0.5 ns [0.5 ns, 0.5 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -| D=3 | la_stack_det_from_lu | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | -| D=3 | la_stack_det_via_lu | 8.8 ns [8.7 ns, 8.8 ns] | 8.8 ns [8.8 ns, 8.9 ns] | +0.7% | slower point estimate; marginal CIs separated | 0.99x | 16.9 ns [16.8 ns, 17.0 ns] | 141.6 ns [140.9 ns, 142.3 ns] | -| D=3 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 0.9 ns [0.9 ns, 0.9 ns] | -| D=3 | la_stack_inf_norm | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | 1.1 ns [1.1 ns, 1.1 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -| D=3 | la_stack_ldlt | 14.8 ns [14.5 ns, 15.1 ns] | 14.1 ns [14.1 ns, 14.2 ns] | -4.5% | faster point estimate; marginal CIs separated | 1.05x | 4.0 ns [4.0 ns, 4.0 ns] | 97.8 ns [97.6 ns, 98.2 ns] | -| D=3 | la_stack_ldlt_solve | 11.6 ns [11.6 ns, 11.7 ns] | 11.7 ns [11.7 ns, 11.8 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | 6.0 ns [6.0 ns, 6.0 ns] | 142.4 ns [141.9 ns, 143.0 ns] | -| D=3 | la_stack_lu | 8.5 ns [8.4 ns, 8.5 ns] | 8.4 ns [8.4 ns, 8.4 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 15.4 ns [15.3 ns, 15.5 ns] | 138.0 ns [137.4 ns, 138.6 ns] | -| D=3 | la_stack_lu_solve | 9.9 ns [9.9 ns, 10.0 ns] | 10.0 ns [10.0 ns, 10.0 ns] | +0.5% | marginal CIs overlap | 1.00x | 23.5 ns [23.4 ns, 23.6 ns] | 196.4 ns [194.9 ns, 198.8 ns] | -| D=3 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -1.5% | faster point estimate; marginal CIs separated | 1.01x | 0.4 ns [0.4 ns, 0.4 ns] | 4.2 ns [4.1 ns, 4.2 ns] | -| D=3 | la_stack_solve_from_ldlt | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 2.9 ns [2.9 ns, 2.9 ns] | 40.6 ns [40.1 ns, 41.0 ns] | -| D=3 | la_stack_solve_from_lu | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | +0.5% | marginal CIs overlap | 1.00x | 4.6 ns [4.6 ns, 4.6 ns] | 48.6 ns [48.5 ns, 48.7 ns] | -| D=32 | la_stack_det | 2.22 µs [2.21 µs, 2.23 µs] | 2.17 µs [2.17 µs, 2.18 µs] | -2.3% | faster point estimate; marginal CIs separated | 1.02x | — | — | -| D=32 | la_stack_det_from_ldlt | 14.1 ns [14.1 ns, 14.1 ns] | 7.9 ns [7.9 ns, 7.9 ns] | -44.0% | faster point estimate; marginal CIs separated | 1.79x | 3.0 ns [3.0 ns, 3.0 ns] | 8.7 ns [8.7 ns, 8.8 ns] | -| D=32 | la_stack_det_from_lu | 14.1 ns [14.0 ns, 14.1 ns] | 9.1 ns [9.1 ns, 9.1 ns] | -35.2% | faster point estimate; marginal CIs separated | 1.54x | 3.1 ns [3.1 ns, 3.1 ns] | 9.0 ns [8.9 ns, 9.0 ns] | -| D=32 | la_stack_det_via_lu | 2.23 µs [2.21 µs, 2.23 µs] | 2.04 µs [2.03 µs, 2.04 µs] | -8.4% | faster point estimate; marginal CIs separated | 1.09x | 2.53 µs [2.52 µs, 2.54 µs] | 2.37 µs [2.36 µs, 2.38 µs] | -| D=32 | la_stack_dot | 4.1 ns [4.1 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 4.8 ns [4.8 ns, 4.8 ns] | 15.2 ns [15.2 ns, 15.2 ns] | -| D=32 | la_stack_inf_norm | 131.6 ns [131.4 ns, 131.8 ns] | 130.4 ns [130.0 ns, 130.7 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 157.7 ns [157.2 ns, 158.1 ns] | 167.1 ns [166.9 ns, 167.3 ns] | -| D=32 | la_stack_ldlt | 2.47 µs [2.46 µs, 2.47 µs] | 2.52 µs [2.51 µs, 2.52 µs] | +2.0% | slower point estimate; marginal CIs separated | 0.98x | 2.13 µs [2.12 µs, 2.13 µs] | 1.50 µs [1.49 µs, 1.51 µs] | -| D=32 | la_stack_ldlt_solve | 2.83 µs [2.82 µs, 2.84 µs] | 2.84 µs [2.83 µs, 2.86 µs] | +0.4% | marginal CIs overlap | 1.00x | 2.78 µs [2.77 µs, 2.79 µs] | 1.97 µs [1.97 µs, 1.98 µs] | -| D=32 | la_stack_lu | 2.15 µs [2.14 µs, 2.15 µs] | 2.07 µs [2.07 µs, 2.08 µs] | -3.6% | faster point estimate; marginal CIs separated | 1.04x | 2.21 µs [2.20 µs, 2.22 µs] | 2.30 µs [2.29 µs, 2.30 µs] | -| D=32 | la_stack_lu_solve | 2.87 µs [2.85 µs, 2.89 µs] | 2.78 µs [2.77 µs, 2.78 µs] | -3.3% | faster point estimate; marginal CIs separated | 1.03x | 2.50 µs [2.49 µs, 2.51 µs] | 2.95 µs [2.95 µs, 2.96 µs] | -| D=32 | la_stack_norm2_sq | 4.0 ns [4.0 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.2% | faster point estimate; marginal CIs separated | 1.01x | 3.9 ns [3.9 ns, 3.9 ns] | 4.3 ns [4.3 ns, 4.3 ns] | -| D=32 | la_stack_solve_from_ldlt | 316.1 ns [315.9 ns, 316.5 ns] | 313.6 ns [313.2 ns, 314.1 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 568.0 ns [566.1 ns, 569.7 ns] | 466.2 ns [464.8 ns, 467.1 ns] | -| D=32 | la_stack_solve_from_lu | 728.4 ns [724.4 ns, 732.7 ns] | 686.0 ns [684.4 ns, 687.3 ns] | -5.8% | faster point estimate; marginal CIs separated | 1.06x | 335.2 ns [334.7 ns, 336.0 ns] | 620.9 ns [619.3 ns, 621.8 ns] | -| D=4 | la_stack_det | 2.6 ns [2.5 ns, 2.6 ns] | 2.6 ns [2.6 ns, 2.6 ns] | +1.3% | slower point estimate; marginal CIs separated | 0.99x | — | — | -| D=4 | la_stack_det_from_ldlt | 1.0 ns [1.0 ns, 1.0 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -20.3% | faster point estimate; marginal CIs separated | 1.25x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | -| D=4 | la_stack_det_from_lu | 1.0 ns [1.0 ns, 1.0 ns] | 0.9 ns [0.9 ns, 0.9 ns] | -13.1% | faster point estimate; marginal CIs separated | 1.15x | 0.6 ns [0.6 ns, 0.6 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -| D=4 | la_stack_det_via_lu | 14.3 ns [14.2 ns, 14.3 ns] | 14.4 ns [14.4 ns, 14.4 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 31.3 ns [31.2 ns, 31.4 ns] | 172.0 ns [169.9 ns, 177.8 ns] | -| D=4 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | -0.2% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 1.2 ns [1.2 ns, 1.2 ns] | -| D=4 | la_stack_inf_norm | 2.3 ns [2.2 ns, 2.3 ns] | 2.3 ns [2.3 ns, 2.3 ns] | +0.3% | slower point estimate; marginal CIs separated | 1.00x | 2.0 ns [2.0 ns, 2.0 ns] | 2.0 ns [2.0 ns, 2.0 ns] | -| D=4 | la_stack_ldlt | 22.2 ns [22.2 ns, 22.2 ns] | 22.0 ns [22.0 ns, 22.1 ns] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | 8.0 ns [8.0 ns, 8.0 ns] | 121.3 ns [121.0 ns, 122.0 ns] | -| D=4 | la_stack_ldlt_solve | 24.1 ns [24.1 ns, 24.2 ns] | 24.0 ns [24.0 ns, 24.1 ns] | -0.4% | marginal CIs overlap | 1.00x | 11.6 ns [11.6 ns, 11.6 ns] | 169.0 ns [168.3 ns, 169.4 ns] | -| D=4 | la_stack_lu | 14.0 ns [13.9 ns, 14.0 ns] | 13.9 ns [13.8 ns, 13.9 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 30.0 ns [29.9 ns, 30.1 ns] | 165.5 ns [164.6 ns, 168.1 ns] | -| D=4 | la_stack_lu_solve | 22.0 ns [21.9 ns, 22.0 ns] | 21.9 ns [21.8 ns, 21.9 ns] | -0.5% | faster point estimate; marginal CIs separated | 1.00x | 54.7 ns [54.6 ns, 54.9 ns] | 223.9 ns [222.6 ns, 225.8 ns] | -| D=4 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | +0.5% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 4.2 ns [4.2 ns, 4.2 ns] | -| D=4 | la_stack_solve_from_ldlt | 2.6 ns [2.5 ns, 2.6 ns] | 2.5 ns [2.5 ns, 2.5 ns] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | 5.9 ns [5.9 ns, 5.9 ns] | 41.5 ns [41.0 ns, 41.9 ns] | -| D=4 | la_stack_solve_from_lu | 4.0 ns [4.0 ns, 4.1 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -1.9% | faster point estimate; marginal CIs separated | 1.02x | 5.9 ns [5.9 ns, 5.9 ns] | 59.5 ns [57.6 ns, 61.1 ns] | -| D=5 | la_stack_det | 41.0 ns [40.8 ns, 41.2 ns] | 62.2 ns [41.0 ns, 62.6 ns] | +51.6% | marginal CIs overlap | 0.66x | — | — | -| D=5 | la_stack_det_from_ldlt | 1.3 ns [1.3 ns, 1.3 ns] | 1.0 ns [1.0 ns, 1.0 ns] | -24.3% | faster point estimate; marginal CIs separated | 1.32x | 0.6 ns [0.6 ns, 0.6 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -| D=5 | la_stack_det_from_lu | 2.0 ns [1.9 ns, 2.0 ns] | 1.1 ns [1.1 ns, 1.1 ns] | -42.9% | faster point estimate; marginal CIs separated | 1.75x | 0.7 ns [0.7 ns, 0.7 ns] | 1.5 ns [1.5 ns, 1.5 ns] | -| D=5 | la_stack_det_via_lu | 33.3 ns [33.2 ns, 33.5 ns] | 32.6 ns [32.6 ns, 32.8 ns] | -2.0% | faster point estimate; marginal CIs separated | 1.02x | 57.6 ns [57.5 ns, 57.8 ns] | 206.8 ns [206.4 ns, 207.7 ns] | -| D=5 | la_stack_dot | 0.9 ns [0.8 ns, 0.9 ns] | 0.8 ns [0.8 ns, 0.8 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 0.7 ns [0.7 ns, 0.8 ns] | 1.5 ns [1.5 ns, 1.5 ns] | -| D=5 | la_stack_inf_norm | 3.5 ns [3.5 ns, 3.5 ns] | 3.5 ns [3.5 ns, 3.5 ns] | +1.1% | slower point estimate; marginal CIs separated | 0.99x | 3.3 ns [3.3 ns, 3.3 ns] | 3.2 ns [3.2 ns, 3.2 ns] | -| D=5 | la_stack_ldlt | 43.8 ns [43.7 ns, 43.9 ns] | 43.5 ns [43.4 ns, 43.5 ns] | -0.8% | faster point estimate; marginal CIs separated | 1.01x | 27.7 ns [26.9 ns, 28.7 ns] | 150.0 ns [149.1 ns, 150.8 ns] | -| D=5 | la_stack_ldlt_solve | 47.2 ns [47.1 ns, 47.3 ns] | 47.1 ns [47.0 ns, 47.1 ns] | -0.2% | marginal CIs overlap | 1.00x | 42.3 ns [42.1 ns, 42.4 ns] | 210.3 ns [209.8 ns, 210.9 ns] | -| D=5 | la_stack_lu | 32.8 ns [32.7 ns, 32.9 ns] | 33.0 ns [32.6 ns, 33.2 ns] | +0.6% | marginal CIs overlap | 0.99x | 57.7 ns [57.5 ns, 57.9 ns] | 199.0 ns [198.0 ns, 200.1 ns] | -| D=5 | la_stack_lu_solve | 44.9 ns [44.4 ns, 45.9 ns] | 44.5 ns [44.3 ns, 44.7 ns] | -0.8% | marginal CIs overlap | 1.01x | 71.2 ns [71.1 ns, 71.3 ns] | 293.4 ns [290.1 ns, 306.4 ns] | -| D=5 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 0.6 ns [0.6 ns, 0.6 ns] | 4.2 ns [4.2 ns, 4.2 ns] | -| D=5 | la_stack_solve_from_ldlt | 3.9 ns [3.9 ns, 3.9 ns] | 4.0 ns [3.9 ns, 4.0 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 9.7 ns [9.7 ns, 9.8 ns] | 66.3 ns [63.8 ns, 67.5 ns] | -| D=5 | la_stack_solve_from_lu | 6.1 ns [6.1 ns, 6.1 ns] | 6.1 ns [6.1 ns, 6.1 ns] | -0.0% | marginal CIs overlap | 1.00x | 9.4 ns [9.4 ns, 9.4 ns] | 89.2 ns [88.9 ns, 89.5 ns] | -| D=64 | la_stack_det | 14.99 µs [14.95 µs, 15.03 µs] | 14.95 µs [14.88 µs, 14.98 µs] | -0.3% | marginal CIs overlap | 1.00x | — | — | -| D=64 | la_stack_det_from_ldlt | 32.5 ns [32.4 ns, 32.5 ns] | 23.4 ns [23.4 ns, 23.4 ns] | -27.9% | faster point estimate; marginal CIs separated | 1.39x | 8.7 ns [8.7 ns, 8.7 ns] | 21.6 ns [21.5 ns, 21.6 ns] | -| D=64 | la_stack_det_from_lu | 33.5 ns [33.1 ns, 33.5 ns] | 23.6 ns [23.6 ns, 23.7 ns] | -29.3% | faster point estimate; marginal CIs separated | 1.41x | 8.9 ns [8.9 ns, 9.0 ns] | 22.4 ns [22.4 ns, 22.5 ns] | -| D=64 | la_stack_det_via_lu | 15.03 µs [15.01 µs, 15.06 µs] | 14.86 µs [14.84 µs, 14.88 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 13.17 µs [13.14 µs, 13.19 µs] | 10.70 µs [10.68 µs, 10.71 µs] | -| D=64 | la_stack_dot | 11.2 ns [11.2 ns, 11.3 ns] | 11.0 ns [11.0 ns, 11.0 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | 9.1 ns [9.1 ns, 9.1 ns] | 38.2 ns [38.1 ns, 38.3 ns] | -| D=64 | la_stack_inf_norm | 643.8 ns [642.5 ns, 645.5 ns] | 630.3 ns [628.7 ns, 631.3 ns] | -2.1% | faster point estimate; marginal CIs separated | 1.02x | 1.31 µs [1.30 µs, 1.31 µs] | 1.59 µs [1.58 µs, 1.59 µs] | -| D=64 | la_stack_ldlt | 21.88 µs [21.82 µs, 22.01 µs] | 19.83 µs [19.80 µs, 19.85 µs] | -9.3% | faster point estimate; marginal CIs separated | 1.10x | 10.93 µs [10.92 µs, 10.94 µs] | 9.03 µs [9.02 µs, 9.04 µs] | -| D=64 | la_stack_ldlt_solve | 24.52 µs [24.39 µs, 24.60 µs] | 22.45 µs [22.22 µs, 22.49 µs] | -8.5% | faster point estimate; marginal CIs separated | 1.09x | 12.91 µs [12.89 µs, 12.94 µs] | 10.37 µs [10.35 µs, 10.40 µs] | -| D=64 | la_stack_lu | 14.45 µs [14.42 µs, 14.52 µs] | 14.75 µs [14.74 µs, 14.76 µs] | +2.1% | slower point estimate; marginal CIs separated | 0.98x | 12.98 µs [12.94 µs, 13.01 µs] | 10.56 µs [10.55 µs, 10.58 µs] | -| D=64 | la_stack_lu_solve | 17.51 µs [17.47 µs, 17.55 µs] | 17.36 µs [17.26 µs, 17.41 µs] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 13.88 µs [13.85 µs, 13.90 µs] | 12.20 µs [12.18 µs, 12.22 µs] | -| D=64 | la_stack_norm2_sq | 11.2 ns [11.2 ns, 11.3 ns] | 11.0 ns [10.9 ns, 11.0 ns] | -2.2% | faster point estimate; marginal CIs separated | 1.02x | 7.4 ns [7.4 ns, 7.4 ns] | 6.3 ns [6.3 ns, 6.3 ns] | -| D=64 | la_stack_solve_from_ldlt | 1.11 µs [1.11 µs, 1.12 µs] | 1.09 µs [1.09 µs, 1.10 µs] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | 1.32 µs [1.31 µs, 1.32 µs] | 1.24 µs [1.24 µs, 1.24 µs] | -| D=64 | la_stack_solve_from_lu | 2.72 µs [2.72 µs, 2.74 µs] | 2.76 µs [2.70 µs, 2.79 µs] | +1.3% | marginal CIs overlap | 0.99x | 796.6 ns [795.2 ns, 797.9 ns] | 1.65 µs [1.65 µs, 1.66 µs] | -| D=8 | la_stack_det | 94.9 ns [94.2 ns, 95.9 ns] | 94.7 ns [94.4 ns, 95.1 ns] | -0.2% | marginal CIs overlap | 1.00x | — | — | -| D=8 | la_stack_det_from_ldlt | 2.7 ns [2.7 ns, 2.7 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -51.7% | faster point estimate; marginal CIs separated | 2.07x | 0.9 ns [0.9 ns, 0.9 ns] | 2.0 ns [2.0 ns, 2.0 ns] | -| D=8 | la_stack_det_from_ldlt_balanced_range | 9.3 ns [9.3 ns, 9.4 ns] | 8.8 ns [8.8 ns, 8.8 ns] | -6.0% | faster point estimate; marginal CIs separated | 1.06x | — | — | -| D=8 | la_stack_det_from_lu | 2.8 ns [2.8 ns, 2.9 ns] | 1.5 ns [1.5 ns, 1.5 ns] | -47.4% | faster point estimate; marginal CIs separated | 1.90x | 1.0 ns [1.0 ns, 1.0 ns] | 2.3 ns [2.3 ns, 2.3 ns] | -| D=8 | la_stack_det_from_lu_balanced_range | 9.3 ns [9.3 ns, 9.3 ns] | 9.3 ns [9.3 ns, 9.4 ns] | +0.3% | marginal CIs overlap | 1.00x | — | — | -| D=8 | la_stack_det_via_lu | 88.0 ns [87.4 ns, 88.7 ns] | 85.2 ns [84.9 ns, 85.3 ns] | -3.2% | faster point estimate; marginal CIs separated | 1.03x | 143.3 ns [143.0 ns, 143.7 ns] | 295.2 ns [293.3 ns, 297.7 ns] | -| D=8 | la_stack_dot | 1.0 ns [1.0 ns, 1.0 ns] | 0.9 ns [0.9 ns, 0.9 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 1.1 ns [1.1 ns, 1.1 ns] | 2.3 ns [2.3 ns, 2.3 ns] | -| D=8 | la_stack_inf_norm | 8.5 ns [8.5 ns, 8.5 ns] | 8.5 ns [8.5 ns, 8.5 ns] | -0.3% | faster point estimate; marginal CIs separated | 1.00x | 8.1 ns [8.1 ns, 8.1 ns] | 8.2 ns [8.1 ns, 8.2 ns] | -| D=8 | la_stack_ldlt | 94.1 ns [93.1 ns, 94.7 ns] | 92.3 ns [91.4 ns, 93.2 ns] | -1.8% | marginal CIs overlap | 1.02x | 107.4 ns [106.7 ns, 107.9 ns] | 230.5 ns [226.0 ns, 233.4 ns] | -| D=8 | la_stack_ldlt_ill_conditioned | 93.3 ns [91.8 ns, 94.6 ns] | 91.9 ns [90.9 ns, 92.7 ns] | -1.5% | marginal CIs overlap | 1.02x | — | — | -| D=8 | la_stack_ldlt_solve | 103.4 ns [103.1 ns, 103.8 ns] | 100.8 ns [100.6 ns, 101.1 ns] | -2.4% | faster point estimate; marginal CIs separated | 1.02x | 147.7 ns [141.5 ns, 150.9 ns] | 289.2 ns [288.4 ns, 290.9 ns] | -| D=8 | la_stack_lu | 85.6 ns [85.3 ns, 86.0 ns] | 83.5 ns [83.1 ns, 83.7 ns] | -2.5% | faster point estimate; marginal CIs separated | 1.03x | 143.1 ns [141.4 ns, 145.1 ns] | 278.4 ns [277.5 ns, 280.4 ns] | -| D=8 | la_stack_lu_ill_conditioned | 86.4 ns [85.9 ns, 87.0 ns] | 83.1 ns [82.9 ns, 83.2 ns] | -3.9% | faster point estimate; marginal CIs separated | 1.04x | — | — | -| D=8 | la_stack_lu_pivoting | 94.6 ns [94.4 ns, 94.8 ns] | 90.5 ns [90.4 ns, 90.7 ns] | -4.3% | faster point estimate; marginal CIs separated | 1.05x | — | — | -| D=8 | la_stack_lu_solve | 149.5 ns [149.1 ns, 150.1 ns] | 145.4 ns [138.0 ns, 146.6 ns] | -2.7% | faster point estimate; marginal CIs separated | 1.03x | 188.4 ns [187.4 ns, 189.0 ns] | 381.9 ns [380.5 ns, 383.1 ns] | -| D=8 | la_stack_norm2_sq | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 4.2 ns [4.2 ns, 4.2 ns] | -| D=8 | la_stack_solve_from_ldlt | 8.1 ns [8.1 ns, 8.2 ns] | 8.1 ns [8.1 ns, 8.2 ns] | +0.3% | marginal CIs overlap | 1.00x | 23.5 ns [23.4 ns, 23.7 ns] | 71.9 ns [71.4 ns, 72.2 ns] | -| D=8 | la_stack_solve_from_lu | 13.8 ns [13.7 ns, 13.8 ns] | 13.7 ns [13.6 ns, 13.7 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 16.8 ns [16.8 ns, 16.8 ns] | 96.9 ns [96.7 ns, 97.4 ns] | +| D=16 | la_stack_det | 433.3 ns [431.0 ns, 435.4 ns] | 463.8 ns [460.4 ns, 472.3 ns] | +7.0% | slower point estimate; marginal CIs separated | 0.93x | — | — | +| D=16 | la_stack_det_from_ldlt | 2.9 ns [2.9 ns, 2.9 ns] | 2.9 ns [2.9 ns, 2.9 ns] | -0.1% | marginal CIs overlap | 1.00x | 1.7 ns [1.7 ns, 1.7 ns] | 4.3 ns [4.3 ns, 4.4 ns] | +| D=16 | la_stack_det_from_lu | 3.3 ns [3.3 ns, 3.3 ns] | 3.3 ns [3.3 ns, 3.3 ns] | +0.2% | marginal CIs overlap | 1.00x | 1.8 ns [1.8 ns, 1.8 ns] | 4.8 ns [4.7 ns, 4.8 ns] | +| D=16 | la_stack_det_via_lu | 403.1 ns [402.1 ns, 405.0 ns] | 405.2 ns [403.8 ns, 406.9 ns] | +0.5% | marginal CIs overlap | 0.99x | 449.5 ns [448.4 ns, 450.3 ns] | 671.6 ns [665.6 ns, 677.2 ns] | +| D=16 | la_stack_dot | 2.3 ns [2.3 ns, 2.3 ns] | 2.3 ns [2.3 ns, 2.3 ns] | +0.5% | slower point estimate; marginal CIs separated | 1.00x | 1.9 ns [1.9 ns, 1.9 ns] | 3.3 ns [3.3 ns, 3.3 ns] | +| D=16 | la_stack_inf_norm | 32.2 ns [32.2 ns, 32.3 ns] | 32.2 ns [32.1 ns, 32.2 ns] | -0.3% | marginal CIs overlap | 1.00x | 31.4 ns [31.3 ns, 31.4 ns] | 32.7 ns [32.5 ns, 32.7 ns] | +| D=16 | la_stack_ldlt | 383.4 ns [382.4 ns, 383.9 ns] | 403.8 ns [403.4 ns, 404.5 ns] | +5.3% | slower point estimate; marginal CIs separated | 0.95x | 397.0 ns [396.6 ns, 397.6 ns] | 428.2 ns [426.1 ns, 430.8 ns] | +| D=16 | la_stack_ldlt_solve | 425.4 ns [424.9 ns, 425.8 ns] | 447.6 ns [446.3 ns, 448.1 ns] | +5.2% | slower point estimate; marginal CIs separated | 0.95x | 607.4 ns [606.6 ns, 608.8 ns] | 626.1 ns [624.9 ns, 627.1 ns] | +| D=16 | la_stack_lu | 393.8 ns [392.8 ns, 395.0 ns] | 395.6 ns [394.4 ns, 397.1 ns] | +0.5% | marginal CIs overlap | 1.00x | 453.8 ns [452.9 ns, 454.1 ns] | 641.8 ns [639.4 ns, 645.7 ns] | +| D=16 | la_stack_lu_solve | 640.8 ns [639.4 ns, 641.5 ns] | 643.5 ns [641.5 ns, 644.9 ns] | +0.4% | slower point estimate; marginal CIs separated | 1.00x | 569.4 ns [568.9 ns, 569.9 ns] | 903.1 ns [900.3 ns, 905.3 ns] | +| D=16 | la_stack_norm2_sq | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | +0.0% | marginal CIs overlap | 1.00x | 1.5 ns [1.5 ns, 1.5 ns] | 4.1 ns [4.1 ns, 4.1 ns] | +| D=16 | la_stack_solve_from_ldlt | 27.7 ns [27.7 ns, 27.8 ns] | 27.7 ns [27.7 ns, 27.7 ns] | -0.1% | marginal CIs overlap | 1.00x | 116.1 ns [115.7 ns, 116.2 ns] | 181.7 ns [181.4 ns, 182.2 ns] | +| D=16 | la_stack_solve_from_lu | 188.0 ns [187.6 ns, 188.6 ns] | 188.8 ns [188.3 ns, 189.4 ns] | +0.4% | marginal CIs overlap | 1.00x | 92.2 ns [92.1 ns, 92.3 ns] | 258.8 ns [255.7 ns, 262.5 ns] | +| D=2 | la_stack_det | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +0.0% | marginal CIs overlap | 1.00x | — | — | +| D=2 | la_stack_det_from_ldlt | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 0.5 ns [0.5 ns, 0.6 ns] | +| D=2 | la_stack_det_from_lu | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | -0.1% | marginal CIs overlap | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +| D=2 | la_stack_det_via_lu | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.3% | slower point estimate; marginal CIs separated | 1.00x | 0.8 ns [0.8 ns, 0.8 ns] | 131.7 ns [131.1 ns, 132.0 ns] | +| D=2 | la_stack_dot | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -0.2% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 2.5 ns [2.5 ns, 2.7 ns] | +| D=2 | la_stack_inf_norm | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | -0.0% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +| D=2 | la_stack_ldlt | 6.5 ns [6.5 ns, 6.5 ns] | 6.6 ns [6.6 ns, 6.6 ns] | +2.6% | slower point estimate; marginal CIs separated | 0.97x | 1.7 ns [1.7 ns, 1.7 ns] | 98.0 ns [97.6 ns, 98.4 ns] | +| D=2 | la_stack_ldlt_solve | 9.3 ns [9.3 ns, 9.3 ns] | 9.4 ns [9.4 ns, 9.5 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 2.5 ns [2.5 ns, 2.5 ns] | 145.9 ns [143.5 ns, 147.3 ns] | +| D=2 | la_stack_lu | 1.6 ns [1.6 ns, 1.6 ns] | 1.6 ns [1.6 ns, 1.6 ns] | -0.3% | faster point estimate; marginal CIs separated | 1.00x | 1.6 ns [1.6 ns, 1.6 ns] | 120.9 ns [120.0 ns, 121.7 ns] | +| D=2 | la_stack_lu_solve | 2.0 ns [2.0 ns, 2.0 ns] | 2.0 ns [2.0 ns, 2.0 ns] | -0.5% | marginal CIs overlap | 1.01x | 4.5 ns [4.5 ns, 4.5 ns] | 182.5 ns [182.1 ns, 183.0 ns] | +| D=2 | la_stack_norm2_sq | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | -0.0% | marginal CIs overlap | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 4.1 ns [4.1 ns, 4.1 ns] | +| D=2 | la_stack_solve_from_ldlt | 1.2 ns [1.2 ns, 1.2 ns] | 1.2 ns [1.2 ns, 1.2 ns] | +1.6% | slower point estimate; marginal CIs separated | 0.98x | 1.2 ns [1.2 ns, 1.2 ns] | 44.0 ns [43.7 ns, 44.2 ns] | +| D=2 | la_stack_solve_from_lu | 1.2 ns [1.2 ns, 1.2 ns] | 1.2 ns [1.2 ns, 1.2 ns] | -0.0% | marginal CIs overlap | 1.00x | 2.9 ns [2.9 ns, 2.9 ns] | 54.8 ns [54.6 ns, 54.9 ns] | +| D=3 | la_stack_det | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.2% | marginal CIs overlap | 1.00x | — | — | +| D=3 | la_stack_det_from_ldlt | 0.6 ns [0.6 ns, 0.6 ns] | 0.6 ns [0.6 ns, 0.6 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +| D=3 | la_stack_det_from_lu | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | +| D=3 | la_stack_det_via_lu | 8.7 ns [8.7 ns, 8.7 ns] | 8.7 ns [8.7 ns, 8.8 ns] | +0.4% | marginal CIs overlap | 1.00x | 17.8 ns [17.7 ns, 17.9 ns] | 162.9 ns [161.8 ns, 164.2 ns] | +| D=3 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 3.0 ns [3.0 ns, 3.0 ns] | +| D=3 | la_stack_inf_norm | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | +0.0% | marginal CIs overlap | 1.00x | 1.1 ns [1.1 ns, 1.1 ns] | 1.3 ns [1.2 ns, 1.3 ns] | +| D=3 | la_stack_ldlt | 13.4 ns [13.3 ns, 13.4 ns] | 13.6 ns [13.5 ns, 13.7 ns] | +1.6% | slower point estimate; marginal CIs separated | 0.98x | 3.9 ns [3.8 ns, 3.9 ns] | 108.2 ns [107.8 ns, 109.1 ns] | +| D=3 | la_stack_ldlt_solve | 12.5 ns [12.5 ns, 12.6 ns] | 18.3 ns [17.8 ns, 20.3 ns] | +45.7% | slower point estimate; marginal CIs separated | 0.69x | 5.6 ns [5.6 ns, 5.6 ns] | 155.4 ns [154.6 ns, 155.9 ns] | +| D=3 | la_stack_lu | 8.3 ns [8.3 ns, 8.3 ns] | 17.7 ns [16.7 ns, 18.4 ns] | +114.1% | slower point estimate; marginal CIs separated | 0.47x | 14.8 ns [14.7 ns, 14.8 ns] | 156.6 ns [155.4 ns, 158.0 ns] | +| D=3 | la_stack_lu_solve | 10.1 ns [10.0 ns, 10.2 ns] | 10.0 ns [9.9 ns, 10.0 ns] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 22.8 ns [22.7 ns, 23.0 ns] | 217.6 ns [216.2 ns, 219.0 ns] | +| D=3 | la_stack_norm2_sq | 0.4 ns [0.4 ns, 0.4 ns] | 0.4 ns [0.4 ns, 0.4 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.4 ns [0.4 ns, 0.4 ns] | 4.1 ns [4.1 ns, 4.1 ns] | +| D=3 | la_stack_solve_from_ldlt | 1.8 ns [1.8 ns, 1.8 ns] | 1.8 ns [1.8 ns, 1.8 ns] | +0.0% | marginal CIs overlap | 1.00x | 2.7 ns [2.7 ns, 2.8 ns] | 45.8 ns [45.4 ns, 46.5 ns] | +| D=3 | la_stack_solve_from_lu | 2.1 ns [2.1 ns, 2.1 ns] | 2.1 ns [2.1 ns, 2.1 ns] | +0.1% | marginal CIs overlap | 1.00x | 4.5 ns [4.5 ns, 4.5 ns] | 56.7 ns [56.5 ns, 57.0 ns] | +| D=32 | la_stack_det | 2.18 µs [2.17 µs, 2.18 µs] | 2.17 µs [2.16 µs, 2.18 µs] | -0.5% | marginal CIs overlap | 1.01x | — | — | +| D=32 | la_stack_det_from_ldlt | 7.7 ns [7.7 ns, 7.7 ns] | 7.8 ns [7.7 ns, 7.8 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | 3.0 ns [3.0 ns, 3.0 ns] | 8.3 ns [8.2 ns, 8.3 ns] | +| D=32 | la_stack_det_from_lu | 9.1 ns [9.0 ns, 9.1 ns] | 9.0 ns [9.0 ns, 9.0 ns] | -0.1% | marginal CIs overlap | 1.00x | 3.1 ns [3.1 ns, 3.1 ns] | 8.6 ns [8.6 ns, 8.7 ns] | +| D=32 | la_stack_det_via_lu | 2.05 µs [2.04 µs, 2.05 µs] | 2.05 µs [2.04 µs, 2.06 µs] | +0.3% | marginal CIs overlap | 1.00x | 2.19 µs [2.19 µs, 2.20 µs] | 2.31 µs [2.30 µs, 2.32 µs] | +| D=32 | la_stack_dot | 4.0 ns [4.0 ns, 4.0 ns] | 4.0 ns [4.0 ns, 4.0 ns] | -0.1% | marginal CIs overlap | 1.00x | 4.7 ns [4.7 ns, 4.7 ns] | 4.9 ns [4.9 ns, 4.9 ns] | +| D=32 | la_stack_inf_norm | 127.0 ns [126.9 ns, 127.2 ns] | 127.6 ns [127.4 ns, 127.7 ns] | +0.5% | slower point estimate; marginal CIs separated | 0.99x | 158.5 ns [154.9 ns, 159.6 ns] | 163.6 ns [163.4 ns, 164.2 ns] | +| D=32 | la_stack_ldlt | 2.44 µs [2.43 µs, 2.44 µs] | 2.45 µs [2.45 µs, 2.45 µs] | +0.5% | slower point estimate; marginal CIs separated | 0.99x | 2.06 µs [2.05 µs, 2.06 µs] | 1.45 µs [1.45 µs, 1.46 µs] | +| D=32 | la_stack_ldlt_solve | 2.78 µs [2.77 µs, 2.79 µs] | 2.77 µs [2.76 µs, 2.79 µs] | -0.4% | marginal CIs overlap | 1.00x | 2.69 µs [2.69 µs, 2.69 µs] | 1.94 µs [1.94 µs, 1.94 µs] | +| D=32 | la_stack_lu | 2.11 µs [2.10 µs, 2.12 µs] | 2.12 µs [2.11 µs, 2.13 µs] | +0.4% | marginal CIs overlap | 1.00x | 2.14 µs [2.13 µs, 2.14 µs] | 2.26 µs [2.26 µs, 2.27 µs] | +| D=32 | la_stack_lu_solve | 2.78 µs [2.77 µs, 2.80 µs] | 2.76 µs [2.75 µs, 2.76 µs] | -1.0% | faster point estimate; marginal CIs separated | 1.01x | 2.71 µs [2.70 µs, 2.72 µs] | 2.92 µs [2.91 µs, 2.93 µs] | +| D=32 | la_stack_norm2_sq | 4.0 ns [4.0 ns, 4.0 ns] | 4.0 ns [4.0 ns, 4.0 ns] | +0.0% | marginal CIs overlap | 1.00x | 3.8 ns [3.8 ns, 3.8 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=32 | la_stack_solve_from_ldlt | 307.5 ns [307.0 ns, 307.8 ns] | 310.4 ns [309.5 ns, 311.1 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | 533.2 ns [531.2 ns, 534.3 ns] | 466.9 ns [466.3 ns, 467.6 ns] | +| D=32 | la_stack_solve_from_lu | 661.0 ns [660.0 ns, 662.2 ns] | 652.5 ns [650.7 ns, 653.7 ns] | -1.3% | faster point estimate; marginal CIs separated | 1.01x | 327.4 ns [327.0 ns, 327.8 ns] | 631.0 ns [629.5 ns, 632.5 ns] | +| D=4 | la_stack_det | 2.6 ns [2.6 ns, 2.6 ns] | 2.6 ns [2.6 ns, 2.6 ns] | +0.1% | slower point estimate; marginal CIs separated | 1.00x | — | — | +| D=4 | la_stack_det_from_ldlt | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 1.0 ns [1.0 ns, 1.0 ns] | +| D=4 | la_stack_det_from_lu | 0.9 ns [0.9 ns, 0.9 ns] | 0.9 ns [0.9 ns, 0.9 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 1.2 ns [1.2 ns, 1.2 ns] | +| D=4 | la_stack_det_via_lu | 14.4 ns [14.4 ns, 14.5 ns] | 14.5 ns [14.4 ns, 14.5 ns] | +0.1% | marginal CIs overlap | 1.00x | 30.0 ns [30.0 ns, 30.0 ns] | 179.5 ns [179.0 ns, 180.9 ns] | +| D=4 | la_stack_dot | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.0% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 2.6 ns [2.6 ns, 2.7 ns] | +| D=4 | la_stack_inf_norm | 2.2 ns [2.2 ns, 2.2 ns] | 2.2 ns [2.2 ns, 2.2 ns] | +0.1% | marginal CIs overlap | 1.00x | 2.0 ns [2.0 ns, 2.0 ns] | 2.0 ns [2.0 ns, 2.0 ns] | +| D=4 | la_stack_ldlt | 21.1 ns [21.1 ns, 21.2 ns] | 21.3 ns [21.3 ns, 21.4 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 7.5 ns [7.4 ns, 7.5 ns] | 126.4 ns [126.1 ns, 126.9 ns] | +| D=4 | la_stack_ldlt_solve | 22.9 ns [22.9 ns, 23.0 ns] | 38.6 ns [38.0 ns, 39.7 ns] | +68.2% | slower point estimate; marginal CIs separated | 0.59x | 10.4 ns [10.4 ns, 10.4 ns] | 172.6 ns [172.4 ns, 173.2 ns] | +| D=4 | la_stack_lu | 14.0 ns [13.9 ns, 14.0 ns] | 13.9 ns [13.8 ns, 13.9 ns] | -0.9% | faster point estimate; marginal CIs separated | 1.01x | 29.1 ns [29.1 ns, 29.2 ns] | 175.5 ns [174.3 ns, 176.3 ns] | +| D=4 | la_stack_lu_solve | 21.9 ns [21.9 ns, 22.0 ns] | 22.1 ns [22.1 ns, 22.1 ns] | +0.8% | slower point estimate; marginal CIs separated | 0.99x | 51.7 ns [51.5 ns, 51.9 ns] | 241.5 ns [239.3 ns, 243.2 ns] | +| D=4 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.5 ns [0.5 ns, 0.5 ns] | 4.1 ns [4.1 ns, 4.1 ns] | +| D=4 | la_stack_solve_from_ldlt | 2.5 ns [2.5 ns, 2.5 ns] | 2.5 ns [2.5 ns, 2.5 ns] | -0.0% | marginal CIs overlap | 1.00x | 5.3 ns [5.2 ns, 5.3 ns] | 44.8 ns [44.6 ns, 44.9 ns] | +| D=4 | la_stack_solve_from_lu | 4.0 ns [4.0 ns, 4.0 ns] | 3.9 ns [3.9 ns, 3.9 ns] | -1.8% | faster point estimate; marginal CIs separated | 1.02x | 5.7 ns [5.6 ns, 5.7 ns] | 59.9 ns [59.5 ns, 60.2 ns] | +| D=5 | la_stack_det | 39.4 ns [39.3 ns, 39.6 ns] | 40.6 ns [40.0 ns, 58.5 ns] | +2.9% | slower point estimate; marginal CIs separated | 0.97x | — | — | +| D=5 | la_stack_det_from_ldlt | 0.9 ns [0.9 ns, 0.9 ns] | 0.9 ns [0.9 ns, 0.9 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 1.2 ns [1.2 ns, 1.2 ns] | +| D=5 | la_stack_det_from_lu | 1.1 ns [1.1 ns, 1.1 ns] | 1.1 ns [1.1 ns, 1.1 ns] | +0.1% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 1.5 ns [1.5 ns, 1.5 ns] | +| D=5 | la_stack_det_via_lu | 32.1 ns [32.0 ns, 32.3 ns] | 32.7 ns [32.6 ns, 32.7 ns] | +1.7% | slower point estimate; marginal CIs separated | 0.98x | 54.8 ns [54.7 ns, 54.9 ns] | 223.3 ns [221.9 ns, 224.9 ns] | +| D=5 | la_stack_dot | 0.8 ns [0.8 ns, 0.8 ns] | 0.8 ns [0.8 ns, 0.8 ns] | +5.2% | slower point estimate; marginal CIs separated | 0.95x | 0.7 ns [0.7 ns, 0.8 ns] | 2.8 ns [2.8 ns, 2.8 ns] | +| D=5 | la_stack_inf_norm | 3.4 ns [3.4 ns, 3.4 ns] | 3.5 ns [3.5 ns, 3.5 ns] | +1.9% | slower point estimate; marginal CIs separated | 0.98x | 3.2 ns [3.2 ns, 3.2 ns] | 3.2 ns [3.2 ns, 3.2 ns] | +| D=5 | la_stack_ldlt | 40.5 ns [40.4 ns, 40.6 ns] | 41.9 ns [41.6 ns, 42.3 ns] | +3.6% | slower point estimate; marginal CIs separated | 0.97x | 26.1 ns [25.1 ns, 26.5 ns] | 144.0 ns [143.6 ns, 144.6 ns] | +| D=5 | la_stack_ldlt_solve | 52.3 ns [51.9 ns, 52.5 ns] | 45.4 ns [45.3 ns, 45.5 ns] | -13.3% | faster point estimate; marginal CIs separated | 1.15x | 40.4 ns [40.3 ns, 40.4 ns] | 234.3 ns [231.2 ns, 246.0 ns] | +| D=5 | la_stack_lu | 32.0 ns [31.9 ns, 32.1 ns] | 32.3 ns [32.3 ns, 32.4 ns] | +1.0% | slower point estimate; marginal CIs separated | 0.99x | 55.1 ns [54.9 ns, 55.2 ns] | 217.7 ns [214.6 ns, 220.0 ns] | +| D=5 | la_stack_lu_solve | 44.3 ns [43.9 ns, 44.8 ns] | 46.1 ns [46.0 ns, 46.1 ns] | +4.0% | slower point estimate; marginal CIs separated | 0.96x | 69.0 ns [68.9 ns, 69.2 ns] | 326.8 ns [324.0 ns, 361.6 ns] | +| D=5 | la_stack_norm2_sq | 0.5 ns [0.5 ns, 0.5 ns] | 0.5 ns [0.5 ns, 0.5 ns] | +0.1% | slower point estimate; marginal CIs separated | 1.00x | 0.6 ns [0.6 ns, 0.6 ns] | 4.1 ns [4.1 ns, 4.1 ns] | +| D=5 | la_stack_solve_from_ldlt | 3.9 ns [3.9 ns, 3.9 ns] | 3.9 ns [3.9 ns, 3.9 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | 8.9 ns [8.8 ns, 8.9 ns] | 63.4 ns [63.3 ns, 63.6 ns] | +| D=5 | la_stack_solve_from_lu | 6.0 ns [6.0 ns, 6.0 ns] | 6.0 ns [6.0 ns, 6.0 ns] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | 8.8 ns [8.8 ns, 8.8 ns] | 93.6 ns [91.6 ns, 95.0 ns] | +| D=64 | la_stack_det | 15.21 µs [15.17 µs, 15.25 µs] | 15.11 µs [15.05 µs, 15.16 µs] | -0.7% | faster point estimate; marginal CIs separated | 1.01x | — | — | +| D=64 | la_stack_det_from_ldlt | 22.6 ns [22.5 ns, 22.6 ns] | 22.8 ns [22.8 ns, 22.8 ns] | +1.0% | slower point estimate; marginal CIs separated | 0.99x | 8.2 ns [8.2 ns, 8.3 ns] | 20.2 ns [20.2 ns, 20.3 ns] | +| D=64 | la_stack_det_from_lu | 23.0 ns [22.9 ns, 23.0 ns] | 22.9 ns [22.9 ns, 23.0 ns] | -0.2% | marginal CIs overlap | 1.00x | 8.5 ns [8.5 ns, 8.6 ns] | 21.1 ns [21.1 ns, 21.2 ns] | +| D=64 | la_stack_det_via_lu | 15.21 µs [15.17 µs, 15.23 µs] | 15.03 µs [14.99 µs, 15.06 µs] | -1.1% | faster point estimate; marginal CIs separated | 1.01x | 13.41 µs [13.40 µs, 13.43 µs] | 10.55 µs [10.55 µs, 10.56 µs] | +| D=64 | la_stack_dot | 10.7 ns [10.6 ns, 10.7 ns] | 10.8 ns [10.8 ns, 10.8 ns] | +1.4% | slower point estimate; marginal CIs separated | 0.99x | 8.9 ns [8.9 ns, 8.9 ns] | 8.3 ns [8.3 ns, 8.3 ns] | +| D=64 | la_stack_inf_norm | 612.7 ns [612.2 ns, 614.1 ns] | 611.1 ns [610.2 ns, 613.2 ns] | -0.3% | marginal CIs overlap | 1.00x | 1.09 µs [1.08 µs, 1.09 µs] | 1.54 µs [1.54 µs, 1.54 µs] | +| D=64 | la_stack_ldlt | 19.64 µs [19.60 µs, 19.65 µs] | 20.87 µs [20.81 µs, 20.91 µs] | +6.3% | slower point estimate; marginal CIs separated | 0.94x | 11.48 µs [11.46 µs, 11.50 µs] | 8.81 µs [8.79 µs, 8.82 µs] | +| D=64 | la_stack_ldlt_solve | 21.85 µs [21.79 µs, 21.90 µs] | 23.16 µs [23.08 µs, 23.26 µs] | +6.0% | slower point estimate; marginal CIs separated | 0.94x | 12.12 µs [12.09 µs, 12.14 µs] | 10.15 µs [10.13 µs, 10.16 µs] | +| D=64 | la_stack_lu | 15.02 µs [14.99 µs, 15.03 µs] | 14.42 µs [14.40 µs, 14.44 µs] | -4.0% | faster point estimate; marginal CIs separated | 1.04x | 12.93 µs [12.91 µs, 12.94 µs] | 10.41 µs [10.40 µs, 10.43 µs] | +| D=64 | la_stack_lu_solve | 17.22 µs [17.16 µs, 17.44 µs] | 17.52 µs [17.36 µs, 17.56 µs] | +1.7% | marginal CIs overlap | 0.98x | 14.31 µs [14.30 µs, 14.35 µs] | 12.11 µs [12.09 µs, 12.12 µs] | +| D=64 | la_stack_norm2_sq | 10.6 ns [10.6 ns, 10.7 ns] | 10.8 ns [10.7 ns, 10.8 ns] | +1.3% | slower point estimate; marginal CIs separated | 0.99x | 7.5 ns [7.5 ns, 7.5 ns] | 6.2 ns [6.2 ns, 6.2 ns] | +| D=64 | la_stack_solve_from_ldlt | 1.46 µs [1.45 µs, 1.46 µs] | 1.08 µs [1.07 µs, 1.08 µs] | -26.1% | faster point estimate; marginal CIs separated | 1.35x | 1.25 µs [1.24 µs, 1.25 µs] | 1.26 µs [1.26 µs, 1.27 µs] | +| D=64 | la_stack_solve_from_lu | 2.52 µs [2.51 µs, 2.52 µs] | 2.47 µs [2.47 µs, 2.48 µs] | -1.7% | faster point estimate; marginal CIs separated | 1.02x | 793.3 ns [792.9 ns, 793.9 ns] | 1.67 µs [1.67 µs, 1.68 µs] | +| D=8 | la_stack_det | 90.7 ns [90.5 ns, 91.0 ns] | 90.5 ns [90.3 ns, 90.6 ns] | -0.3% | marginal CIs overlap | 1.00x | — | — | +| D=8 | la_stack_det_from_ldlt | 1.3 ns [1.3 ns, 1.3 ns] | 1.3 ns [1.3 ns, 1.3 ns] | -0.0% | marginal CIs overlap | 1.00x | 0.9 ns [0.9 ns, 0.9 ns] | 1.9 ns [1.9 ns, 1.9 ns] | +| D=8 | la_stack_det_from_ldlt_balanced_range | 8.9 ns [8.9 ns, 8.9 ns] | 8.9 ns [8.9 ns, 9.0 ns] | +0.4% | slower point estimate; marginal CIs separated | 1.00x | — | — | +| D=8 | la_stack_det_from_lu | 1.5 ns [1.5 ns, 1.5 ns] | 1.5 ns [1.5 ns, 1.5 ns] | +0.3% | slower point estimate; marginal CIs separated | 1.00x | 1.0 ns [1.0 ns, 1.0 ns] | 2.2 ns [2.2 ns, 2.2 ns] | +| D=8 | la_stack_det_from_lu_balanced_range | 9.7 ns [9.7 ns, 9.8 ns] | 9.1 ns [9.0 ns, 9.2 ns] | -6.4% | faster point estimate; marginal CIs separated | 1.07x | — | — | +| D=8 | la_stack_det_via_lu | 84.1 ns [83.9 ns, 84.4 ns] | 84.6 ns [84.3 ns, 85.0 ns] | +0.6% | marginal CIs overlap | 0.99x | 144.2 ns [143.9 ns, 144.6 ns] | 294.0 ns [292.1 ns, 294.7 ns] | +| D=8 | la_stack_dot | 0.9 ns [0.9 ns, 0.9 ns] | 1.0 ns [1.0 ns, 1.0 ns] | +3.2% | slower point estimate; marginal CIs separated | 0.97x | 1.1 ns [1.1 ns, 1.1 ns] | 2.6 ns [2.6 ns, 2.7 ns] | +| D=8 | la_stack_inf_norm | 8.4 ns [8.4 ns, 8.4 ns] | 8.4 ns [8.4 ns, 8.4 ns] | -0.1% | marginal CIs overlap | 1.00x | 8.0 ns [8.0 ns, 8.0 ns] | 8.0 ns [8.0 ns, 8.1 ns] | +| D=8 | la_stack_ldlt | 90.7 ns [89.7 ns, 92.3 ns] | 90.5 ns [88.6 ns, 91.4 ns] | -0.2% | marginal CIs overlap | 1.00x | 97.7 ns [97.3 ns, 98.1 ns] | 215.2 ns [214.5 ns, 216.1 ns] | +| D=8 | la_stack_ldlt_ill_conditioned | 91.2 ns [89.9 ns, 92.6 ns] | 90.3 ns [88.8 ns, 91.4 ns] | -1.0% | marginal CIs overlap | 1.01x | — | — | +| D=8 | la_stack_ldlt_solve | 100.9 ns [100.6 ns, 101.1 ns] | 99.3 ns [98.9 ns, 99.5 ns] | -1.6% | faster point estimate; marginal CIs separated | 1.02x | 142.0 ns [134.5 ns, 144.4 ns] | 296.7 ns [291.9 ns, 300.7 ns] | +| D=8 | la_stack_lu | 82.2 ns [82.0 ns, 82.4 ns] | 82.9 ns [82.6 ns, 83.3 ns] | +0.9% | slower point estimate; marginal CIs separated | 0.99x | 144.0 ns [143.7 ns, 144.5 ns] | 275.8 ns [273.4 ns, 277.3 ns] | +| D=8 | la_stack_lu_ill_conditioned | 81.9 ns [81.5 ns, 82.1 ns] | 82.3 ns [82.2 ns, 82.6 ns] | +0.6% | slower point estimate; marginal CIs separated | 0.99x | — | — | +| D=8 | la_stack_lu_pivoting | 90.8 ns [90.6 ns, 90.9 ns] | 90.4 ns [90.2 ns, 90.7 ns] | -0.4% | marginal CIs overlap | 1.00x | — | — | +| D=8 | la_stack_lu_solve | 137.4 ns [135.7 ns, 143.1 ns] | 128.4 ns [128.2 ns, 128.7 ns] | -6.5% | faster point estimate; marginal CIs separated | 1.07x | 165.9 ns [164.8 ns, 168.9 ns] | 401.4 ns [396.0 ns, 407.1 ns] | +| D=8 | la_stack_norm2_sq | 0.7 ns [0.7 ns, 0.7 ns] | 0.7 ns [0.7 ns, 0.7 ns] | +0.4% | marginal CIs overlap | 1.00x | 0.7 ns [0.7 ns, 0.7 ns] | 4.2 ns [4.2 ns, 4.2 ns] | +| D=8 | la_stack_solve_from_ldlt | 8.1 ns [8.1 ns, 8.1 ns] | 8.0 ns [8.0 ns, 8.1 ns] | -0.4% | faster point estimate; marginal CIs separated | 1.00x | 21.0 ns [21.0 ns, 21.0 ns] | 71.1 ns [70.8 ns, 71.1 ns] | +| D=8 | la_stack_solve_from_lu | 13.3 ns [13.3 ns, 13.3 ns] | 13.5 ns [13.5 ns, 13.5 ns] | +1.2% | slower point estimate; marginal CIs separated | 0.99x | 16.0 ns [15.9 ns, 16.0 ns] | 99.5 ns [99.0 ns, 99.6 ns] | + +## Coverage Notes + +One-sided rows retain the available measurement but are excluded from point-estimate change and ratio calculations. + +| Benchmark | Coverage | v0.4.5 (point + CI) | Latest (point + CI) | Note | +|:----------|:---------|-----------------------------:|--------------------:|:-----| +| rational_input_d2/det_big_rational_gaussian | current-only | — | 1.18 µs [1.18 µs, 1.18 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d2/det_row_cleared_bareiss | current-only | — | 191.3 ns [190.9 ns, 192.0 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d2/det_sign_row_cleared_bareiss | current-only | — | 82.3 ns [82.2 ns, 82.4 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d2/solve_big_rational_gaussian | current-only | — | 2.22 µs [2.22 µs, 2.22 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d2/solve_row_cleared_bareiss | current-only | — | 967.5 ns [966.5 ns, 968.2 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d3/det_big_rational_gaussian | current-only | — | 4.89 µs [4.88 µs, 4.90 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d3/det_row_cleared_bareiss | current-only | — | 578.6 ns [578.0 ns, 579.1 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d3/det_sign_row_cleared_bareiss | current-only | — | 368.6 ns [367.8 ns, 369.6 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d3/solve_big_rational_gaussian | current-only | — | 8.44 µs [8.43 µs, 8.46 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d3/solve_row_cleared_bareiss | current-only | — | 2.50 µs [2.49 µs, 2.51 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d4/det_big_rational_gaussian | current-only | — | 14.16 µs [14.14 µs, 14.19 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d4/det_row_cleared_bareiss | current-only | — | 1.17 µs [1.16 µs, 1.17 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d4/det_sign_row_cleared_bareiss | current-only | — | 769.1 ns [767.2 ns, 770.7 ns] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d4/solve_big_rational_gaussian | current-only | — | 24.94 µs [24.90 µs, 24.98 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d4/solve_row_cleared_bareiss | current-only | — | 5.51 µs [5.51 µs, 5.52 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d5/det_big_rational_gaussian | current-only | — | 24.97 µs [24.55 µs, 25.75 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d5/det_row_cleared_bareiss | current-only | — | 2.15 µs [2.15 µs, 2.16 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d5/det_sign_row_cleared_bareiss | current-only | — | 1.58 µs [1.58 µs, 1.59 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d5/solve_big_rational_gaussian | current-only | — | 41.11 µs [41.07 µs, 41.14 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d5/solve_row_cleared_bareiss | current-only | — | 9.67 µs [9.64 µs, 9.72 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d6/det_big_rational_gaussian | current-only | — | 57.91 µs [57.84 µs, 58.02 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d6/det_row_cleared_bareiss | current-only | — | 3.75 µs [3.75 µs, 3.76 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d6/det_sign_row_cleared_bareiss | current-only | — | 3.10 µs [3.09 µs, 3.10 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d6/solve_big_rational_gaussian | current-only | — | 92.50 µs [92.35 µs, 92.60 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d6/solve_row_cleared_bareiss | current-only | — | 18.03 µs [18.01 µs, 18.05 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d7/det_big_rational_gaussian | current-only | — | 112.35 µs [112.25 µs, 112.50 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d7/det_row_cleared_bareiss | current-only | — | 6.15 µs [6.14 µs, 6.16 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d7/det_sign_row_cleared_bareiss | current-only | — | 5.30 µs [5.29 µs, 5.31 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d7/solve_big_rational_gaussian | current-only | — | 165.07 µs [164.88 µs, 165.48 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d7/solve_row_cleared_bareiss | current-only | — | 29.46 µs [29.44 µs, 29.50 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d8/det_big_rational_gaussian | current-only | — | 194.98 µs [193.24 µs, 197.90 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d8/det_row_cleared_bareiss | current-only | — | 9.31 µs [9.29 µs, 9.33 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d8/det_sign_row_cleared_bareiss | current-only | — | 8.47 µs [8.46 µs, 8.48 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d8/solve_big_rational_gaussian | current-only | — | 272.40 µs [272.07 µs, 272.65 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | +| rational_input_d8/solve_row_cleared_bareiss | current-only | — | 43.37 µs [43.31 µs, 43.43 µs] | Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api. | ## How to Update @@ -277,10 +321,14 @@ just performance-release `performance.provenance.json` comparison inputs under `target/bench-reports/` without promoting documentation. It applies staged and unstaged tracked changes; untracked files are excluded. `just performance-github-assets` writes `target/bench-reports/github-assets-performance.md`. -`just performance-release` performs the same measurement and retention work, then promotes distinct-release documentation. +`just performance-release` also preserves every recorded local benchmark summary and the report inputs under +`docs/performance/-vs-//`, then promotes distinct-release documentation. `just performance-doc` consumes the retained pair from either workflow without benchmarking and promotes it when the package versions differ. +After `just clean`, `performance-doc` and `performance-readme` use the latest complete snapshot in `docs/performance/`. For a distinct pair, `performance-local` followed by `performance-doc` is equivalent to the atomic `performance-release` workflow. +See the [local summary index](https://github.com/acgetchell/la-stack/tree/main/docs/performance) +for the saved-data schema, provenance, and historical availability. Older curated release-to-release reports are archived in `docs/archive/performance/`. See `docs/BENCHMARKING.md` for the full comparison workflow. diff --git a/docs/performance/README.md b/docs/performance/README.md new file mode 100644 index 0000000..4cd2824 --- /dev/null +++ b/docs/performance/README.md @@ -0,0 +1,87 @@ +# Local Benchmark Summaries + +This directory preserves complete local measurement summaries across releases +and `just clean`. The generated [performance report](../performance.md) is a +selected view of those measurements; the README chart uses its LU-solve subset. + +## Contents + +- [Saved runs](#saved-runs) +- [Regenerating reports](#regenerating-reports) +- [Comparing measurements](#comparing-measurements) +- [Historical availability](#historical-availability) + +## Saved runs + +`just performance-release` saves each successful local comparison under +`-vs-//`. The digest identifies the complete +contents, so another run or machine creates a separate snapshot. Identical +promotion is idempotent. Earlier snapshots remain available. + +Each snapshot contains: + +| File | Contents | +| --- | --- | +| `performance.full.csv` | Every recorded baseline and current benchmark, including diagnostic and peer cases outside the report selection | +| `performance.full.provenance.json` | Full-summary schema, CSV digest, phase counts, and the source, harness, dependency, CPU, OS, toolchain, command, and validation provenance | +| `performance.csv` | Selected report inputs, including peer context | +| `performance.provenance.json` | Validated metadata and digest for the selected report inputs | + +The full CSV stores the Criterion benchmark ID, measurement phase, mean and +median in nanoseconds, their 95% confidence intervals, and sample count. Numbers +retain floating-point precision rather than the rounded values displayed in +Markdown. Each recorded case must have valid metadata, estimates, and 100 raw +samples before publication. Baseline-only peers remain explicitly baseline +measurements; missing current measurements are never filled from an older run. + +`latest.json` points to the most recently promoted complete snapshot. It is +updated with the report in the same rollback-protected publication operation. +Review and commit the snapshot and pointer along with the release report. + +## Regenerating reports + +After a successful release promotion, these commands can use the committed +snapshot when the scratch report inputs are absent: + +```bash +just performance-doc +just performance-readme +``` + +Neither command reruns benchmarks. Existing scratch inputs take precedence; +partial or corrupt inputs fail validation rather than silently selecting an +older snapshot. README publication still checks the measured source and +benchmark contract against the current checkout, along with the lockfile and +release version. Committing only the saved artifacts does not invalidate a +snapshot: its original measurement commit remains in provenance. Legacy inputs +without a benchmark-contract digest also require the original commit. + +`performance-local` initially keeps complete summaries beside its selected +inputs under `target/bench-reports/`. Promote a distinct-release comparison with +`performance-doc` before cleaning if it should become committed release history. +Same-version local experiments remain scratch output. + +## Comparing measurements + +Compare rows by benchmark identity and measurement phase, with the recorded +environment and harness held comparable. Baseline and current rows come from +separate executions. New cases can have only a current measurement, and peer +measurements reused by the report can have only a baseline measurement. + +These CSVs support comparisons of recorded point estimates and intervals. +Recomputing Criterion statistics requires the raw samples, which are not stored +here. The GitHub release workflow separately publishes full raw Criterion +archives from its hosted runner; those are a different measurement environment +and do not substitute for local results. + +## Historical availability + +This retention workflow cannot recover measurements previously discarded with +temporary worktrees. If `latest.json` is absent, no complete local snapshot has +been promoted yet. Existing [archived Markdown reports](../archive/performance/README.md) +retain their selected summaries, but do not establish complete historical +coverage. A new authorized measurement run is required to fill that gap. + +Completed optimization investigations and decisions are in +[archived studies](../archive/performance/studies/README.md). +The [Benchmarking guide](../BENCHMARKING.md) owns execution procedures. diff --git a/docs/performance/latest.json b/docs/performance/latest.json new file mode 100644 index 0000000..bf9ec4a --- /dev/null +++ b/docs/performance/latest.json @@ -0,0 +1,4 @@ +{ + "schema_version": 1, + "run": "v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841" +} diff --git a/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.csv b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.csv new file mode 100644 index 0000000..5f87606 --- /dev/null +++ b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.csv @@ -0,0 +1,226 @@ +schema_version,suite,scope,benchmark_id,group,benchmark,baseline_benchmark,coverage_status,coverage_note,baseline_median_ns,baseline_ci_lower_ns,baseline_ci_upper_ns,current_median_ns,current_ci_lower_ns,current_ci_upper_ns,baseline_nalgebra_median_ns,baseline_nalgebra_ci_lower_ns,baseline_nalgebra_ci_upper_ns,baseline_faer_median_ns,baseline_faer_ci_lower_ns,baseline_faer_ci_upper_ns +1,exact,release-signal,exact_d2/det,exact_d2,det,det,comparable,,0.43847576051642734,0.43771116413319694,0.44014508325985335,0.43781032284173355,0.43749994941412362,0.43847175207245848,,,,,, +1,exact,release-signal,exact_d2/det_direct,exact_d2,det_direct,det_direct,comparable,,0.43890208644314921,0.43801797286422228,0.44270725973824282,0.43764312485011625,0.43733467617422683,0.43807259563263068,,,,,, +1,exact,release-signal,exact_d2/det_direct_with_errbound,exact_d2,det_direct_with_errbound,det_direct_with_errbound,comparable,,1.7075903619994319,1.7070745586021363,1.7081829879281933,1.7073013705766971,1.7063923650432029,1.7079640536051874,,,,,, +1,exact,release-signal,exact_d2/det_errbound,exact_d2,det_errbound,det_errbound,comparable,,1.6517834250166323,1.6332174430567585,1.6587981067136037,1.61087434662331,1.6106233733633932,1.6110668547700691,,,,,, +1,exact,release-signal,exact_d2/det_exact,exact_d2,det_exact,det_exact,comparable,,110.54949764112055,110.4165319475389,110.67008305854891,100.38341954181654,100.25860606191442,100.45874695478162,,,,,, +1,exact,release-signal,exact_d2/det_exact_f64_result,exact_d2,det_exact_f64_result,det_exact_f64_result,comparable,,71.304186348617947,71.229325899010149,71.450055510936835,73.121377825013496,72.948086424304989,73.239383718656114,,,,,, +1,exact,release-signal,exact_d2/det_exact_rounded_f64,exact_d2,det_exact_rounded_f64,det_exact_rounded_f64,comparable,,72.703499508377547,72.59951086170598,72.749777314686838,73.289869358037024,73.203820533307535,73.427008474114103,,,,,, +1,exact,release-signal,exact_d2/det_sign_exact,exact_d2,det_sign_exact,det_sign_exact,comparable,,2.7246048207347155,2.7235218703696562,2.7252852108085879,2.9727448009384552,2.9711808333049001,2.9736586699857512,,,,,, +1,exact,release-signal,exact_d2/solve_exact,exact_d2,solve_exact,solve_exact,comparable,,7056.9531728461234,7048.471785248601,7067.7650925445423,7103.2365596963427,7091.384964514652,7121.5409461814279,,,,,, +1,exact,release-signal,exact_d2/solve_exact_f64_result,exact_d2,solve_exact_f64_result,solve_exact_f64_result,comparable,,8275.0384273636992,8263.9776154401152,8283.7041208791197,7326.9728648190048,7315.6998400054472,7338.1031082887703,,,,,, +1,exact,release-signal,exact_d2/solve_exact_rounded_f64,exact_d2,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,7483.8547297822024,7465.4149807508456,7492.6400165646473,7545.5059447379363,7536.4208012502068,7556.2741779497101,,,,,, +1,exact,release-signal,exact_d3/det,exact_d3,det,det,comparable,,0.81990981412770791,0.81972115749594165,0.82028127659417371,0.82052624144033937,0.81997993744612674,0.82958445547905235,,,,,, +1,exact,release-signal,exact_d3/det_direct,exact_d3,det_direct,det_direct,comparable,,0.81964968537900218,0.81945001634242298,0.81991535627519985,0.84324142759762211,0.84303959411399643,0.84358495741055417,,,,,, +1,exact,release-signal,exact_d3/det_direct_with_errbound,exact_d3,det_direct_with_errbound,det_direct_with_errbound,comparable,,3.3512944612203119,3.3497211362415991,3.3519037902029045,3.3336258051064513,3.3312802100185195,3.3352301728199736,,,,,, +1,exact,release-signal,exact_d3/det_errbound,exact_d3,det_errbound,det_errbound,comparable,,3.2973827287459319,3.2966626351444424,3.2988260711232167,3.301854619913609,3.3007505129873378,3.3025672634616923,,,,,, +1,exact,release-signal,exact_d3/det_exact,exact_d3,det_exact,det_exact,comparable,,370.62103034529622,369.86403420087237,371.50005831882476,338.86892309707798,338.46532875716184,339.38967754065999,,,,,, +1,exact,release-signal,exact_d3/det_exact_f64_result,exact_d3,det_exact_f64_result,det_exact_f64_result,comparable,,338.50625261868208,337.96742945629734,339.20691278680931,313.94135072672867,313.19842787807761,314.39031247687871,,,,,, +1,exact,release-signal,exact_d3/det_exact_rounded_f64,exact_d3,det_exact_rounded_f64,det_exact_rounded_f64,comparable,,340.13469534949354,338.83811393849339,341.23260685502839,317.19259036516161,315.97447107081172,318.18263939812238,,,,,, +1,exact,release-signal,exact_d3/det_sign_exact,exact_d3,det_sign_exact,det_sign_exact,comparable,,4.7070801729224563,4.7034109482681714,4.7087691290113822,4.7057575953196054,4.7022504631143072,4.7075229235872253,,,,,, +1,exact,release-signal,exact_d3/solve_exact,exact_d3,solve_exact,solve_exact,comparable,,30841.786697160282,30782.165945165943,30891.305627705628,30602.107463524131,30507.733471074382,30673.99090909091,,,,,, +1,exact,release-signal,exact_d3/solve_exact_f64_result,exact_d3,solve_exact_f64_result,solve_exact_f64_result,comparable,,32798.861609901651,32755.004207024998,32869.908113391983,30919.162885539889,30857.226107226106,30964.459374999999,,,,,, +1,exact,release-signal,exact_d3/solve_exact_rounded_f64,exact_d3,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,31458.357638888891,31348.545350609755,31602.896874999999,31603.564459930312,31551.840401785714,31717.042520491803,,,,,, +1,exact,release-signal,exact_d4/det,exact_d4,det,det,comparable,,3.2107365390289107,3.2073757625246007,3.2123307424659502,3.2078095214172038,3.207275625470412,3.2084480682172294,,,,,, +1,exact,release-signal,exact_d4/det_direct,exact_d4,det_direct,det_direct,comparable,,2.3814746678490781,2.3799999033543298,2.3827086124641079,2.3803328914201023,2.3785431672403856,2.381988121518936,,,,,, +1,exact,release-signal,exact_d4/det_direct_with_errbound,exact_d4,det_direct_with_errbound,det_direct_with_errbound,comparable,,6.8088526372894673,6.8048633104768035,6.8122325535580108,6.8210282612150346,6.8155599899080253,6.8248932760945085,,,,,, +1,exact,release-signal,exact_d4/det_errbound,exact_d4,det_errbound,det_errbound,comparable,,6.7250463620252106,6.7209925754319819,6.7265735516195919,6.7298367344158674,6.7276257639948414,6.7337182030083707,,,,,, +1,exact,release-signal,exact_d4/det_exact,exact_d4,det_exact,det_exact,comparable,,1215.8668534223154,1213.1349449204406,1219.8847409220725,1009.5950009915389,1006.5170470604861,1011.3975830359977,,,,,, +1,exact,release-signal,exact_d4/det_exact_f64_result,exact_d4,det_exact_f64_result,det_exact_f64_result,comparable,,1167.6428712048482,1161.2254407063178,1173.5005889281508,1055.9986747178903,1051.7988398630657,1058.7444400467414,,,,,, +1,exact,release-signal,exact_d4/det_exact_rounded_f64,exact_d4,det_exact_rounded_f64,det_exact_rounded_f64,comparable,,1171.4858209981605,1169.1150100692432,1174.6918181526723,1009.2358341763912,1006.8119404466618,1011.4477925130099,,,,,, +1,exact,release-signal,exact_d4/det_sign_exact,exact_d4,det_sign_exact,det_sign_exact,comparable,,7.7101569447655809,7.7049162037511714,7.7126271970046645,7.9855731158043337,7.9823084066610352,7.9869209777758066,,,,,, +1,exact,release-signal,exact_d4/solve_exact,exact_d4,solve_exact,solve_exact,comparable,,80394.593147906708,80267.512195121948,80493.112213225366,79178.462307692302,79081.101265822785,79340.804668913566,,,,,, +1,exact,release-signal,exact_d4/solve_exact_f64_result,exact_d4,solve_exact_f64_result,solve_exact_f64_result,comparable,,83385.528472222213,83236.689814814818,83625.909226190473,79336.071891630389,79125.994694960216,79496.144230769234,,,,,, +1,exact,release-signal,exact_d4/solve_exact_rounded_f64,exact_d4,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,81020.185447936208,80744.581501831504,81523.866337792642,79863.496311907278,79656.368205128209,80046.132107023412,,,,,, +1,exact,release-signal,exact_d5/det,exact_d5,det,det,comparable,,24.706097978590183,24.655587555199386,24.791548754935597,25.043344471514565,24.995479405101708,25.135772398764903,,,,,, +1,exact,release-signal,exact_d5/det_exact,exact_d5,det_exact,det_exact,comparable,,3535.3914879218037,3515.0212893514972,3543.5009720495332,3738.1248015873016,3705.1132756132756,3794.3482912104237,,,,,, +1,exact,release-signal,exact_d5/det_exact_f64_result,exact_d5,det_exact_f64_result,det_exact_f64_result,comparable,,3485.8665144577712,3476.1224682823622,3495.0472987355784,3544.652719389012,3538.9087391774892,3552.1158175750834,,,,,, +1,exact,release-signal,exact_d5/det_exact_rounded_f64,exact_d5,det_exact_rounded_f64,det_exact_rounded_f64,comparable,,3473.9049837486455,3463.680897503592,3483.5478387566782,3605.8623239750445,3595.8873132586368,3610.7112494821872,,,,,, +1,exact,release-signal,exact_d5/det_sign_exact,exact_d5,det_sign_exact,det_sign_exact,comparable,,3580.4706842559199,3569.2386709245743,3589.6393233692506,3704.8721509769766,3697.9076282866836,3710.828306845201,,,,,, +1,exact,release-signal,exact_d5/solve_exact,exact_d5,solve_exact,solve_exact,comparable,,159876.9784053156,159632.96205357142,160238.92712355213,157602.50661810779,157283.09714285715,157888.85194805195,,,,,, +1,exact,release-signal,exact_d5/solve_exact_f64_result,exact_d5,solve_exact_f64_result,solve_exact_f64_result,comparable,,163373.71251822723,162906.96709401708,163708.71428571429,157719.63926056339,157381.78413907666,157932.54017857142,,,,,, +1,exact,release-signal,exact_d5/solve_exact_rounded_f64,exact_d5,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,161497.72549019608,161195.44624447718,161731.31150793651,164264.16929499072,163539.79060665361,164868.8833161912,,,,,, +1,exact,release-signal,exact_hilbert_4x4/det_exact,exact_hilbert_4x4,det_exact,det_exact,comparable,,1343.9629729729731,1326.0616085491088,1349.5065170008718,1044.8245046831648,1042.7718832891246,1046.4298433048434,,,,,, +1,exact,release-signal,exact_hilbert_4x4/det_sign_exact,exact_hilbert_4x4,det_sign_exact,det_sign_exact,comparable,,7.7099758023549052,7.7033203757229574,7.7116810442677046,7.9749134894270171,7.972913379580798,7.9763215903555968,,,,,, +1,exact,release-signal,exact_hilbert_4x4/solve_exact,exact_hilbert_4x4,solve_exact,solve_exact,comparable,,60212.504002233807,60125.525210084037,60288.124183006534,59562.646813725485,59472.567873303167,59626.236974789921,,,,,, +1,exact,release-signal,exact_hilbert_4x4/solve_exact_f64_result,exact_hilbert_4x4,solve_exact_f64_result,solve_exact_f64_result,comparable,,62745.329296875003,62653.01067073171,62890.501488095237,59742.618455882359,59589.820713391739,59791.276464619332,,,,,, +1,exact,release-signal,exact_hilbert_4x4/solve_exact_rounded_f64,exact_hilbert_4x4,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,61090.857168844777,60948.11294117647,61183.744241053064,60472.540909090909,60259.436470588233,60619.009150326798,,,,,, +1,exact,release-signal,exact_hilbert_5x5/det_exact,exact_hilbert_5x5,det_exact,det_exact,comparable,,3678.9161175072823,3660.1433136369824,3687.5988028606967,3750.008168828238,3738.7509505703424,3755.165599359616,,,,,, +1,exact,release-signal,exact_hilbert_5x5/det_sign_exact,exact_hilbert_5x5,det_sign_exact,det_sign_exact,comparable,,3874.8137319711541,3866.2763923134648,3883.6263427734375,3918.5907546644389,3915.3213383838383,3927.1650396825398,,,,,, +1,exact,release-signal,exact_hilbert_5x5/solve_exact,exact_hilbert_5x5,solve_exact,solve_exact,comparable,,124693.28132387708,124443.84693548387,124966.27499999999,122818.14453584018,122529.32592592592,122952.81481481482,,,,,, +1,exact,release-signal,exact_hilbert_5x5/solve_exact_f64_result,exact_hilbert_5x5,solve_exact_f64_result,solve_exact_f64_result,comparable,,127731.90600755411,127443.08035714286,128189.74266154453,122061.4738379684,121913.71124018705,122401.70015220701,,,,,, +1,exact,release-signal,exact_hilbert_5x5/solve_exact_rounded_f64,exact_hilbert_5x5,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,126570.84456663764,126106.27380952382,126930.64945652174,124521.45811362209,124212.54322292695,124643.6507936508,,,,,, +1,exact,release-signal,exact_large_entries_3x3/det_exact,exact_large_entries_3x3,det_exact,det_exact,comparable,,338.46964670112493,337.74453561253563,339.51962945696278,341.60984342356278,340.56924856846678,343.93572909467866,,,,,, +1,exact,release-signal,exact_large_entries_3x3/det_sign_exact,exact_large_entries_3x3,det_sign_exact,det_sign_exact,comparable,,320.81136421991346,319.60410234571845,323.00216143144695,334.89716789992951,334.13514600454624,337.04329802912594,,,,,, +1,exact,release-signal,exact_large_entries_3x3/solve_exact,exact_large_entries_3x3,solve_exact,solve_exact,comparable,,93994.31235047846,93805.538370720184,94257.299334811527,93137.352404352408,92931.473829201102,93303.571428571435,,,,,, +1,exact,release-signal,exact_large_entries_3x3/solve_exact_f64_result,exact_large_entries_3x3,solve_exact_f64_result,solve_exact_f64_result,comparable,,94712.194055944055,94653.409090909088,94795.466324373294,93374.058082477117,93240.587695133145,93459.250338808473,,,,,, +1,exact,release-signal,exact_large_entries_3x3/solve_exact_rounded_f64,exact_large_entries_3x3,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,94493.95784163753,94433.555449229127,94605.490621680714,93318.680422647521,93204.670329670334,93376.482345001743,,,,,, +1,exact,release-signal,exact_near_singular_3x3/det_exact,exact_near_singular_3x3,det_exact,det_exact,comparable,,341.96981679675184,341.18232136632975,342.76592927638586,334.52039226635588,333.82858197073244,336.31929809653298,,,,,, +1,exact,release-signal,exact_near_singular_3x3/det_sign_exact,exact_near_singular_3x3,det_sign_exact,det_sign_exact,comparable,,398.25755147433938,394.77626794258373,401.15012291450603,360.9107574552844,360.52249904290721,361.64935837971552,,,,,, +1,exact,release-signal,exact_near_singular_3x3/solve_exact,exact_near_singular_3x3,solve_exact,solve_exact,comparable,,2604.670967959782,2599.2047933943322,2610.9410177894429,2809.473142563902,2799.9518226600985,2813.585387945388,,,,,, +1,exact,release-signal,exact_near_singular_3x3/solve_exact_f64_result,exact_near_singular_3x3,solve_exact_f64_result,solve_exact_f64_result,comparable,,2703.6300498772039,2697.649796195652,2709.8011333510076,2806.3639808864723,2799.1107401864856,2814.8926511781183,,,,,, +1,exact,release-signal,exact_near_singular_3x3/solve_exact_rounded_f64,exact_near_singular_3x3,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,2604.1845499181672,2597.2533244680849,2611.2813367252543,2784.0627799740009,2772.294225321421,2800.5754249291786,,,,,, +1,exact,release-signal,exact_random_corpus_d2/det_exact,exact_random_corpus_d2,det_exact,det_exact,comparable,,3119.5967090007298,3116.1174990399131,3122.6309492980781,3157.536648462783,3142.4911003236248,3184.1920967467213,,,,,, +1,exact,release-signal,exact_random_corpus_d2/det_sign_exact,exact_random_corpus_d2,det_sign_exact,det_sign_exact,comparable,,136.37221632196758,135.62830106889038,136.9651415513103,149.87567316277119,148.86689827636766,150.89118172537007,,,,,, +1,exact,release-signal,exact_random_corpus_d2/solve_exact,exact_random_corpus_d2,solve_exact,solve_exact,comparable,,67472.584074074082,67329.504878048785,67587.888888888891,78458.425167224079,78373.113122171941,78647.399646330683,,,,,, +1,exact,release-signal,exact_random_corpus_d2/solve_exact_f64_result,exact_random_corpus_d2,solve_exact_f64_result,solve_exact_f64_result,comparable,,78304.638009049784,77844.556304520229,78737.268634466309,79810.540974650343,79665.217948717953,79956.221719457011,,,,,, +1,exact,release-signal,exact_random_corpus_d2/solve_exact_rounded_f64,exact_random_corpus_d2,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,68555.185555555552,68410.072754716981,68680.157142857148,82228.788968174689,82016.566119273979,82365.146248812918,,,,,, +1,exact,release-signal,exact_random_corpus_d3/det_exact,exact_random_corpus_d3,det_exact,det_exact,comparable,,8346.2073986194991,8075.079751923844,8636.4508196721308,8469.8414305447641,8444.4969860548808,8491.3909327387591,,,,,, +1,exact,release-signal,exact_random_corpus_d3/det_sign_exact,exact_random_corpus_d3,det_sign_exact,det_sign_exact,comparable,,225.10667868649509,224.97792444242148,225.20942844138111,227.85050023693248,227.4222421578753,228.3404107611729,,,,,, +1,exact,release-signal,exact_random_corpus_d3/solve_exact,exact_random_corpus_d3,solve_exact,solve_exact,comparable,,214235.25767112512,213804.48615384614,214549.53333333333,239624.88788907754,239139.02666666667,240192.04545454544,,,,,, +1,exact,release-signal,exact_random_corpus_d3/solve_exact_f64_result,exact_random_corpus_d3,solve_exact_f64_result,solve_exact_f64_result,comparable,,229915.88374999998,229519.60784313726,230509.14096334187,240544.78857142857,240004.46471264368,241284.83412698412,,,,,, +1,exact,release-signal,exact_random_corpus_d3/solve_exact_rounded_f64,exact_random_corpus_d3,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,217630.98739495798,217287.00882352941,217935.71428571429,242671.08039215687,242062.56701754386,243321.69186256779,,,,,, +1,exact,release-signal,exact_random_corpus_d4/det_exact,exact_random_corpus_d4,det_exact,det_exact,comparable,,25256.297443181818,25208.91449244164,25295.912240210841,21196.339806629563,21163.533822039455,21270.829787234041,,,,,, +1,exact,release-signal,exact_random_corpus_d4/det_sign_exact,exact_random_corpus_d4,det_sign_exact,det_sign_exact,comparable,,424.52204562697165,423.12559207502329,425.64562260524139,454.5566540631005,452.65036491023204,456.01809954751133,,,,,, +1,exact,release-signal,exact_random_corpus_d4/solve_exact,exact_random_corpus_d4,solve_exact,solve_exact,comparable,,489451.64080744656,488840.64912280702,490288.25136612024,535371.3718434344,533843.75,537107.06187500001,,,,,, +1,exact,release-signal,exact_random_corpus_d4/solve_exact_f64_result,exact_random_corpus_d4,solve_exact_f64_result,solve_exact_f64_result,comparable,,507754.39404761908,507048.99725274724,508511.27380952379,534530.00837628869,533886.68498006207,535332.88043478259,,,,,, +1,exact,release-signal,exact_random_corpus_d4/solve_exact_rounded_f64,exact_random_corpus_d4,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,491513.02591500862,490452.26760563382,491979.98039215687,535394.39473684202,535087.6551724138,535958.79775280901,,,,,, +1,exact,release-signal,exact_random_corpus_d5/det_exact,exact_random_corpus_d5,det_exact,det_exact,comparable,,47405.791320311226,47335.994187675067,47504.00425170068,55994.694210032816,55881.401891252957,56126.517283950619,,,,,, +1,exact,release-signal,exact_random_corpus_d5/det_sign_exact,exact_random_corpus_d5,det_sign_exact,det_sign_exact,comparable,,49538.776462825699,48757.712610428789,50884.692642881215,61934.375744853736,61875.220352564102,62040.815934065933,,,,,, +1,exact,release-signal,exact_random_corpus_d5/solve_exact,exact_random_corpus_d5,solve_exact,solve_exact,comparable,,965824.68979013991,964445.03498931625,966729.16666666663,1044342.0280864197,1042954.4758064516,1044963.9105263158,,,,,, +1,exact,release-signal,exact_random_corpus_d5/solve_exact_f64_result,exact_random_corpus_d5,solve_exact_f64_result,solve_exact_f64_result,comparable,,987575.63884379505,986287.68274853798,989217.70499999996,1041768.932346723,1041145.4042553192,1043707.0707070708,,,,,, +1,exact,release-signal,exact_random_corpus_d5/solve_exact_rounded_f64,exact_random_corpus_d5,solve_exact_rounded_f64,solve_exact_rounded_f64,comparable,,966847.55221111618,965474.390625,968312.61416330643,1044969.8439878235,1044289.2083333333,1046173.4258241758,,,,,, +1,exact,release-signal,rational_input_d2/det_big_rational_gaussian,rational_input_d2,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,1179.7816707466341,1178.8611471070353,1180.5365686944635,,,,,, +1,exact,release-signal,rational_input_d2/det_row_cleared_bareiss,rational_input_d2,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,191.30687653285804,190.8536299834349,191.99277375769552,,,,,, +1,exact,release-signal,rational_input_d2/det_sign_row_cleared_bareiss,rational_input_d2,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,82.264763235647905,82.178092387585593,82.426791952752481,,,,,, +1,exact,release-signal,rational_input_d2/solve_big_rational_gaussian,rational_input_d2,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,2220.7723679667379,2219.1226229817771,2224.8722311396468,,,,,, +1,exact,release-signal,rational_input_d2/solve_row_cleared_bareiss,rational_input_d2,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,967.46468552443685,966.4846857506941,968.15035877364642,,,,,, +1,exact,release-signal,rational_input_d3/det_big_rational_gaussian,rational_input_d3,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,4886.0586458892194,4875.0461799911336,4898.5236502816952,,,,,, +1,exact,release-signal,rational_input_d3/det_row_cleared_bareiss,rational_input_d3,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,578.59852199755881,577.98428488032687,579.10216936896222,,,,,, +1,exact,release-signal,rational_input_d3/det_sign_row_cleared_bareiss,rational_input_d3,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,368.64189398809697,367.84755843660724,369.61462103470302,,,,,, +1,exact,release-signal,rational_input_d3/solve_big_rational_gaussian,rational_input_d3,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,8443.0325802546286,8434.2444067796605,8457.8037466547721,,,,,, +1,exact,release-signal,rational_input_d3/solve_row_cleared_bareiss,rational_input_d3,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,2500.4996124161148,2494.8609034560004,2505.5873462735221,,,,,, +1,exact,release-signal,rational_input_d4/det_big_rational_gaussian,rational_input_d4,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,14158.317917888562,14137.330102040816,14187.385531135531,,,,,, +1,exact,release-signal,rational_input_d4/det_row_cleared_bareiss,rational_input_d4,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,1165.5311528391426,1163.9019594471722,1166.7706199106908,,,,,, +1,exact,release-signal,rational_input_d4/det_sign_row_cleared_bareiss,rational_input_d4,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,769.07893541058093,767.20858977370608,770.66537467700255,,,,,, +1,exact,release-signal,rational_input_d4/solve_big_rational_gaussian,rational_input_d4,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,24939.264128599803,24895.645317782284,24977.715657013396,,,,,, +1,exact,release-signal,rational_input_d4/solve_row_cleared_bareiss,rational_input_d4,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,5510.7462502484959,5505.7048786099058,5522.2001433401947,,,,,, +1,exact,release-signal,rational_input_d5/det_big_rational_gaussian,rational_input_d5,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,24971.810975609755,24546.333333333332,25750.66056910569,,,,,, +1,exact,release-signal,rational_input_d5/det_row_cleared_bareiss,rational_input_d5,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,2149.3190837601251,2145.5409961409146,2155.3939471440749,,,,,, +1,exact,release-signal,rational_input_d5/det_sign_row_cleared_bareiss,rational_input_d5,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,1584.107474509711,1580.4311137268091,1587.3894778864872,,,,,, +1,exact,release-signal,rational_input_d5/solve_big_rational_gaussian,rational_input_d5,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,41109.809793459557,41065.769230769234,41144.208018617021,,,,,, +1,exact,release-signal,rational_input_d5/solve_row_cleared_bareiss,rational_input_d5,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,9673.317355757481,9644.8922710110819,9717.7021359223309,,,,,, +1,exact,release-signal,rational_input_d6/det_big_rational_gaussian,rational_input_d6,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,57912.001736111109,57836.388888888891,58015.860082304527,,,,,, +1,exact,release-signal,rational_input_d6/det_row_cleared_bareiss,rational_input_d6,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,3753.0803145963455,3747.6153508059574,3761.3367701001289,,,,,, +1,exact,release-signal,rational_input_d6/det_sign_row_cleared_bareiss,rational_input_d6,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,3095.7158085258397,3087.1125444329778,3104.3652139542537,,,,,, +1,exact,release-signal,rational_input_d6/solve_big_rational_gaussian,rational_input_d6,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,92495.048953027726,92347.221212121207,92598.130681818177,,,,,, +1,exact,release-signal,rational_input_d6/solve_row_cleared_bareiss,rational_input_d6,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,18029.857435977454,18013.576710929519,18047.453384912958,,,,,, +1,exact,release-signal,rational_input_d7/det_big_rational_gaussian,rational_input_d7,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,112353.15160139647,112247.51490514904,112501.75061728395,,,,,, +1,exact,release-signal,rational_input_d7/det_row_cleared_bareiss,rational_input_d7,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,6146.4556925819497,6136.912735339507,6161.7824207685317,,,,,, +1,exact,release-signal,rational_input_d7/det_sign_row_cleared_bareiss,rational_input_d7,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,5301.6227628610613,5290.0314420803779,5312.8317503784383,,,,,, +1,exact,release-signal,rational_input_d7/solve_big_rational_gaussian,rational_input_d7,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,165068.65763546797,164882.5628524436,165480.42579365079,,,,,, +1,exact,release-signal,rational_input_d7/solve_row_cleared_bareiss,rational_input_d7,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,29461.859337068163,29440.257352941175,29500.74031563845,,,,,, +1,exact,release-signal,rational_input_d8/det_big_rational_gaussian,rational_input_d8,det_big_rational_gaussian,det_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,194975.51470588235,193238.88771929825,197899.14772727274,,,,,, +1,exact,release-signal,rational_input_d8/det_row_cleared_bareiss,rational_input_d8,det_row_cleared_bareiss,det_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,9307.4771617411807,9293.2876548576405,9327.7830877373308,,,,,, +1,exact,release-signal,rational_input_d8/det_sign_row_cleared_bareiss,rational_input_d8,det_sign_row_cleared_bareiss,det_sign_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,8471.4478740214035,8463.6758089133091,8479.0832878705223,,,,,, +1,exact,release-signal,rational_input_d8/solve_big_rational_gaussian,rational_input_d8,solve_big_rational_gaussian,solve_big_rational_gaussian,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,272399.82469223486,272067.51851851854,272646.1037745098,,,,,, +1,exact,release-signal,rational_input_d8/solve_row_cleared_bareiss,rational_input_d8,solve_row_cleared_bareiss,solve_row_cleared_bareiss,current-only,Baseline v0.4.5 has no correctness-compatible benchmark row under la_stack_pre_rational_input_api.,,,,43365.191706517515,43314.056298773692,43432.587615283264,,,,,, +1,vs_linalg,release-signal,d16/la_stack_det,d16,la_stack_det,la_stack_det,comparable,,433.34066784459731,430.973731884058,435.38348741418764,463.80296127265103,460.39603261763409,472.33012103603517,,,,,, +1,vs_linalg,release-signal,d16/la_stack_det_from_ldlt,d16,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,2.8806776055144336,2.8754279232906268,2.8841543768439752,2.8777542592908709,2.8710064229678891,2.8807725628498964,1.6869694530351844,1.6820282940336735,1.691833066370803,4.3127503089869572,4.2651866314898168,4.3742375315145363 +1,vs_linalg,release-signal,d16/la_stack_det_from_lu,d16,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,3.2763865769638247,3.2700444936448689,3.2825737845844216,3.2844233910509777,3.2802626051210346,3.2871763604294144,1.7665460642590141,1.7584242199581148,1.7734081843208913,4.7570820233729147,4.671861282890748,4.8081859889349179 +1,vs_linalg,release-signal,d16/la_stack_det_via_lu,d16,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,403.09882780082989,402.14042726795117,404.99118257261409,405.19400426939444,403.78158014582004,406.94594977973304,449.45610344381532,448.40147721045486,450.32172213191768,671.62870464618504,665.5611022272783,677.16293754289632 +1,vs_linalg,release-signal,d16/la_stack_dot,d16,la_stack_dot,la_stack_dot,comparable,,2.3285682228239102,2.3236962534881798,2.3352830278097318,2.3393023607778165,2.3353744484042807,2.3411556649656324,1.8602276927511512,1.8592289616619428,1.860930162217945,3.2925578685885055,3.2864943265647324,3.2982809563299242 +1,vs_linalg,release-signal,d16/la_stack_inf_norm,d16,la_stack_inf_norm,la_stack_inf_norm,comparable,,32.247878749407249,32.177616799609311,32.295151906624312,32.166430085281227,32.105962930584468,32.205136284534682,31.353979063243642,31.335346507565713,31.379620025715106,32.662963494709501,32.486805834181773,32.710889618485297 +1,vs_linalg,release-signal,d16/la_stack_ldlt,d16,la_stack_ldlt,la_stack_ldlt,comparable,,383.39640085370581,382.42033372138144,383.92751159648333,403.795192343709,403.4035573047982,404.47298172993465,396.99672650578373,396.61820885279656,397.59528956498531,428.15073922457987,426.13695561157681,430.76722723721201 +1,vs_linalg,release-signal,d16/la_stack_ldlt_solve,d16,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,425.37468019119581,424.94756970145573,425.8154739209009,447.59429870422946,446.33635357254593,448.10668388068535,607.43266898892762,606.59620959156018,608.84317513755673,626.0651040751543,624.88839840128867,627.14058323532561 +1,vs_linalg,release-signal,d16/la_stack_lu,d16,la_stack_lu,la_stack_lu,comparable,,393.77315426110658,392.78551372414188,394.9719213798636,395.56550265131182,394.39822642691001,397.09790485192184,453.80245729277374,452.93815178884068,454.14459179327349,641.77348233772523,639.35413044287407,645.66004020945923 +1,vs_linalg,release-signal,d16/la_stack_lu_solve,d16,la_stack_lu_solve,la_stack_lu_solve,comparable,,640.81753364968517,639.38963319785239,641.45248773025196,643.53200219388043,641.46681893534719,644.90281289407312,569.44587125571024,568.90984848484845,569.90600109433876,903.14005339898199,900.30683971201211,905.29873345349529 +1,vs_linalg,release-signal,d16/la_stack_norm2_sq,d16,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,2.0630009315813131,2.0585849830533745,2.0654378654830685,2.0639409227602474,2.0589625074537787,2.0688900357838289,1.4771868874299177,1.4761062369740032,1.4780276761745883,4.0614189101656706,4.0578672072064634,4.0633610625063241 +1,vs_linalg,release-signal,d16/la_stack_solve_from_ldlt,d16,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,27.749733517289869,27.716402195047927,27.791723998444603,27.715558726917436,27.697078439756556,27.727102224379838,116.06720734784034,115.68642951109564,116.22006269896731,181.70095034620658,181.44538356380463,182.20675387148222 +1,vs_linalg,release-signal,d16/la_stack_solve_from_lu,d16,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,187.96262283493763,187.58889885483666,188.61136663524977,188.77251827626009,188.33652062599413,189.38605435288875,92.249347718694992,92.111293320933214,92.349650269397728,258.75075528378977,255.7202506995387,262.49754720310568 +1,vs_linalg,release-signal,d2/la_stack_det,d2,la_stack_det,la_stack_det,comparable,,0.57392739152992112,0.57371985158868033,0.5740274980375597,0.57414829406867218,0.57401404317957327,0.57433630871032315,,,,,, +1,vs_linalg,release-signal,d2/la_stack_det_from_ldlt,d2,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,0.49605866835964646,0.49596753848167108,0.49618662196432084,0.49616588060011557,0.4960249936577053,0.49627378935091071,0.43621764800254126,0.43495731463247422,0.43706837309646013,0.54850477620066351,0.54770269780089442,0.55044496344874783 +1,vs_linalg,release-signal,d2/la_stack_det_from_lu,d2,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,0.52093248021331351,0.52037403985539621,0.52462094123531511,0.52042957376516219,0.52036642201000127,0.52051977655544635,0.44852288390755124,0.4483276192218324,0.44907305991161456,0.74324662394908336,0.74318456904907815,0.74342276889246706 +1,vs_linalg,release-signal,d2/la_stack_det_via_lu,d2,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,1.7679449006571393,1.7671939097260814,1.7688273448767438,1.7737368324374865,1.7713974906331558,1.7775340107838542,0.82457530187660444,0.82209533468955243,0.82656166060626657,131.68361099747773,131.10937944410747,132.03241713110734 +1,vs_linalg,release-signal,d2/la_stack_dot,d2,la_stack_dot,la_stack_dot,comparable,,0.61352760044398202,0.61276543774328207,0.61402707088077435,0.61251214878747562,0.61121777769114505,0.61313524788753404,0.56064257789982586,0.56017946329290891,0.56097182708131266,2.5021469296259262,2.4890871213058778,2.6830380933221991 +1,vs_linalg,release-signal,d2/la_stack_inf_norm,d2,la_stack_inf_norm,la_stack_inf_norm,comparable,,0.62287066143716074,0.62252140559815905,0.62322622860202548,0.62282252492893175,0.62250789635979775,0.62326953215304082,0.49827173555514842,0.49814894563945694,0.49836580472015024,0.67215306236778116,0.67177684015805494,0.67268671440604155 +1,vs_linalg,release-signal,d2/la_stack_ldlt,d2,la_stack_ldlt,la_stack_ldlt,comparable,,6.4679174044891763,6.4630566559028733,6.4750959096428309,6.6346326699278517,6.6112283224827619,6.649096105104241,1.703673051936607,1.7021045904007399,1.7063749118829425,97.973415045822435,97.646445326555181,98.355253986804115 +1,vs_linalg,release-signal,d2/la_stack_ldlt_solve,d2,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,9.3267282424810158,9.3156591275904717,9.3335921061528513,9.4342065671166218,9.4176318822760976,9.4644835930358866,2.5197203598411502,2.516149021065984,2.5265791815742578,145.85553820310949,143.47317705398399,147.26974942140896 +1,vs_linalg,release-signal,d2/la_stack_lu,d2,la_stack_lu,la_stack_lu,comparable,,1.5601441095260733,1.5581005650018285,1.5620621774871468,1.5550328069395349,1.5541639439771986,1.5557607183929154,1.6088793413144622,1.6055014356953712,1.6118402294784371,120.85079986178687,120.03323306309831,121.7131579520799 +1,vs_linalg,release-signal,d2/la_stack_lu_solve,d2,la_stack_lu_solve,la_stack_lu_solve,comparable,,2.0314092974806748,2.0302198287717603,2.0345467303122184,2.0211314276372025,2.0184799422811559,2.0445438481191816,4.4787720282632115,4.4712237316812988,4.4889033406839456,182.53202843068811,182.06757130922546,183.01508533237856 +1,vs_linalg,release-signal,d2/la_stack_norm2_sq,d2,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,0.39504092052906009,0.39487957979719801,0.39537735031681998,0.39496812928467495,0.39436059686825969,0.39517097974099941,0.38868026110683163,0.38822521649033631,0.38906554841001673,4.0552777729831924,4.0527518915090699,4.0584808377522643 +1,vs_linalg,release-signal,d2/la_stack_solve_from_ldlt,d2,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,1.2190136869369586,1.2025643334946778,1.2355617067423554,1.2384772206664705,1.2373876587522723,1.2387014979624249,1.2368166338341426,1.2348758039826044,1.2413110353601422,43.964540343301408,43.734783115314087,44.192072676585951 +1,vs_linalg,release-signal,d2/la_stack_solve_from_lu,d2,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,1.2453167718999847,1.2426647173570333,1.2489582164418285,1.2447139930689859,1.2424024222304724,1.2477969796655017,2.8650984215665636,2.8624578315899427,2.8727196959612029,54.804211447567418,54.612902758502798,54.870250629434651 +1,vs_linalg,release-signal,d3/la_stack_det,d3,la_stack_det,la_stack_det,comparable,,1.3248260462690267,1.3241936110286718,1.325669453672313,1.3219835208630162,1.3187665729784837,1.3242570292917186,,,,,, +1,vs_linalg,release-signal,d3/la_stack_det_from_ldlt,d3,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,0.59477992281505032,0.59472219116780245,0.59492421185552224,0.59496997125556228,0.59480219751870333,0.59514975667769421,0.48174818812547809,0.48126926100771028,0.48234366542385021,0.7429406902916269,0.74215865144126136,0.74316840092920089 +1,vs_linalg,release-signal,d3/la_stack_det_from_lu,d3,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,0.69382906994751337,0.69372455541071265,0.693955281660387,0.6938382932649928,0.69371543412299963,0.69401222588717393,0.48748885143063264,0.48666491806252388,0.4884768781028227,0.9908795673907953,0.99043984044654099,0.99118019693272874 +1,vs_linalg,release-signal,d3/la_stack_det_via_lu,d3,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,8.6987283573495908,8.6820481344215388,8.7195939182762601,8.7330760339022611,8.7164490312478264,8.7519581507139819,17.78206896534542,17.683878473352575,17.866720242518589,162.86610685841279,161.84255350690262,164.18815092570892 +1,vs_linalg,release-signal,d3/la_stack_dot,d3,la_stack_dot,la_stack_dot,comparable,,0.66466006269657352,0.66449872189993564,0.66493841553420274,0.66529453349876766,0.66471116669493679,0.66594917480025939,0.68254323774247383,0.68174781597407752,0.68397071323272807,2.9721043004090149,2.9672636668026549,2.9737072044585546 +1,vs_linalg,release-signal,d3/la_stack_inf_norm,d3,la_stack_inf_norm,la_stack_inf_norm,comparable,,1.3018736049200941,1.3012035317105675,1.3022769209393514,1.3022204280027463,1.3019503775557604,1.3025409334706468,1.1111305491166579,1.1071917895656265,1.1131111255161568,1.2543560581510862,1.2485904067302944,1.2574672016871224 +1,vs_linalg,release-signal,d3/la_stack_ldlt,d3,la_stack_ldlt,la_stack_ldlt,comparable,,13.365571137774044,13.32666856698679,13.388654282023392,13.578777245617996,13.518208039128293,13.660511854186652,3.854880152140328,3.8496021469670976,3.8614449677231759,108.22496781137824,107.80687397708674,109.0961018676262 +1,vs_linalg,release-signal,d3/la_stack_ldlt_solve,d3,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,12.539766048291,12.47990558126806,12.576982845534463,18.271606214141041,17.80685111570045,20.33914360837819,5.57965224227463,5.5669118207312955,5.6126545272101183,155.3584554027743,154.6383401275217,155.90266889655413 +1,vs_linalg,release-signal,d3/la_stack_lu,d3,la_stack_lu,la_stack_lu,comparable,,8.2753403949589917,8.2622389396778484,8.302681989155797,17.720017343411151,16.719375128108371,18.448514051541753,14.751846435975526,14.71103012926266,14.778186260671214,156.64884372337724,155.37278578448223,158.01224418140694 +1,vs_linalg,release-signal,d3/la_stack_lu_solve,d3,la_stack_lu_solve,la_stack_lu_solve,comparable,,10.088217111140551,10.041843004661228,10.159124028084907,9.9768486519488775,9.8983811166077125,10.025906395438968,22.794790952289048,22.713611901221796,22.98916653289352,217.56680047835044,216.1785685588016,219.02900557169431 +1,vs_linalg,release-signal,d3/la_stack_norm2_sq,d3,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,0.44433102804392299,0.44362843706784982,0.44490517874170721,0.44492109425017012,0.44446960832512455,0.44534723732947157,0.43707950239910859,0.43667205113888041,0.43740679552668504,4.0917796805949926,4.0870148530788608,4.0952880000727614 +1,vs_linalg,release-signal,d3/la_stack_solve_from_ldlt,d3,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,1.7797906835768509,1.7792510114171358,1.7811215449638009,1.7800479595458731,1.7795798536856575,1.7807743797736573,2.7491770764902128,2.7409270248937236,2.7596003983742241,45.820103833034061,45.419346186712907,46.512106282423062 +1,vs_linalg,release-signal,d3/la_stack_solve_from_lu,d3,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,2.0533085097381019,2.0515242639054314,2.0560913182004255,2.0545412990479761,2.0532042866735472,2.056574592257737,4.4865178210568821,4.4752780759106567,4.4988558406251711,56.686173567119951,56.484327764812235,56.979242838971345 +1,vs_linalg,release-signal,d32/la_stack_det,d32,la_stack_det,la_stack_det,comparable,,2179.691354657688,2172.6720760453109,2184.6388888888887,2168.5406336323022,2163.2463921620547,2178.788811188811,,,,,, +1,vs_linalg,release-signal,d32/la_stack_det_from_ldlt,d32,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,7.7151198458582089,7.6991340302699331,7.7370374257209829,7.7617086675781959,7.7371566936650238,7.783815867105325,2.9575668764860588,2.9533704308656255,2.9612696377300076,8.2541190527740653,8.2276212383937839,8.2980897276881009 +1,vs_linalg,release-signal,d32/la_stack_det_from_lu,d32,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,9.0557646083605654,9.0434752432105618,9.0818144030154446,9.0425497903633172,9.0270617151132946,9.0485748020212959,3.0632310730041938,3.058571115995306,3.0667491876998865,8.6378126376298816,8.5923907486053945,8.6585745819032667 +1,vs_linalg,release-signal,d32/la_stack_det_via_lu,d32,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,2046.0624938536557,2041.3038606747048,2051.0636373542552,2052.0108969513731,2038.2267602457862,2057.7743209876544,2194.7460702161725,2188.8989397699074,2200.5841731395121,2310.7510427515745,2304.8958130989381,2316.1990997508237 +1,vs_linalg,release-signal,d32/la_stack_dot,d32,la_stack_dot,la_stack_dot,comparable,,4.005044008903182,4.0012220974534545,4.0083585622839255,4.0022794786302978,3.9971985367801794,4.0041341307292377,4.7174753890800005,4.7111610181446473,4.7227958792063474,4.940159341901305,4.9388835725206226,4.9472784425006946 +1,vs_linalg,release-signal,d32/la_stack_inf_norm,d32,la_stack_inf_norm,la_stack_inf_norm,comparable,,126.96311798060728,126.86053717923132,127.17461129179991,127.60310823622962,127.36826902491643,127.74566473988439,158.53327140255777,154.91656977880257,159.5608448432649,163.63962038379032,163.39937414926791,164.21209669997975 +1,vs_linalg,release-signal,d32/la_stack_ldlt,d32,la_stack_ldlt,la_stack_ldlt,comparable,,2435.5209888946501,2429.6358198451794,2441.070978335717,2448.6469021101429,2445.8710120524638,2454.5002297582942,2058.36521827155,2054.0214333999779,2064.9730621576155,1454.7438107869143,1449.6722607631095,1458.0513655551765 +1,vs_linalg,release-signal,d32/la_stack_ldlt_solve,d32,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,2779.6149964463393,2770.8428694158074,2790.4230555555555,2768.5652427637724,2762.1808749815718,2794.1459783913565,2689.9108787607984,2685.7882037533514,2693.2391730253657,1938.3953822178478,1937.6810118562767,1940.7293257376919 +1,vs_linalg,release-signal,d32/la_stack_lu,d32,la_stack_lu,la_stack_lu,comparable,,2111.0872659501733,2100.5552685950415,2123.7427206533016,2119.9552244130509,2112.9599375487901,2129.7553187980343,2135.819073466625,2126.3990384615386,2142.1202967711301,2261.2271180447083,2256.120443272006,2269.3012987012985 +1,vs_linalg,release-signal,d32/la_stack_lu_solve,d32,la_stack_lu_solve,la_stack_lu_solve,comparable,,2782.3214668031242,2768.6283143939395,2798.4843447775629,2755.7729402136074,2752.5797735688238,2761.0723724010572,2710.234582397889,2703.7424869037773,2717.3389959916017,2919.2900818850267,2913.4234243697479,2925.1436105476673 +1,vs_linalg,release-signal,d32/la_stack_norm2_sq,d32,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,3.9536483462889596,3.9507604826267237,3.955358586507939,3.9554034762752313,3.9528403327902115,3.9570583687753969,3.7842635532354545,3.7772728379042992,3.7883241613028007,4.2116034737188563,4.2108010605858066,4.212400350451281 +1,vs_linalg,release-signal,d32/la_stack_solve_from_ldlt,d32,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,307.53942374499667,306.97339170392451,307.84513160166335,310.37037098884753,309.49069355760207,311.12826463184393,533.19213866795212,531.19972515104098,534.33935005111334,466.93149123865453,466.28313945034171,467.56257876496534 +1,vs_linalg,release-signal,d32/la_stack_solve_from_lu,d32,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,661.04544671394797,659.95196527777773,662.22138666666672,652.52973532875762,650.69688056314544,653.69664167548922,327.4233276786394,327.04018825645124,327.75330304914723,631.02917789327603,629.46467196744163,632.47189106420217 +1,vs_linalg,release-signal,d4/la_stack_det,d4,la_stack_det,la_stack_det,comparable,,2.5537463679528294,2.5519270947417345,2.555683558826972,2.557517682131166,2.5558274677675454,2.5593567733711935,,,,,, +1,vs_linalg,release-signal,d4/la_stack_det_from_ldlt,d4,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,0.76796836395640611,0.76783753660252574,0.76808604993738983,0.76815302862367463,0.76801416287451307,0.76822111168879548,0.49015277366406668,0.48919111688314537,0.49104120441711785,0.98043187519850727,0.97939547658448001,0.98219598925915663 +1,vs_linalg,release-signal,d4/la_stack_det_from_lu,d4,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,0.86721070021018498,0.8670549715475353,0.86737661263813026,0.86723518491472962,0.86709972488638098,0.86745095443485609,0.58137895726552391,0.58071656856057219,0.5816483012835133,1.237809172948956,1.2364530940897243,1.2384676373205219 +1,vs_linalg,release-signal,d4/la_stack_det_via_lu,d4,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,14.448818945101834,14.429619465413968,14.475714099575811,14.459848995691477,14.445280172050332,14.472798593243407,30.000059894391974,29.96215892046709,30.044589670874757,179.46078924202118,179.00082239292504,180.91031823971531 +1,vs_linalg,release-signal,d4/la_stack_dot,d4,la_stack_dot,la_stack_dot,comparable,,0.67959572647198141,0.67941073520922279,0.68003197517963443,0.67965821720258401,0.67936901276145223,0.67994650417628699,0.62581060702843583,0.62481365426489865,0.62663403396942985,2.6374727019075666,2.6247867528100004,2.6951789636682482 +1,vs_linalg,release-signal,d4/la_stack_inf_norm,d4,la_stack_inf_norm,la_stack_inf_norm,comparable,,2.2292751061254998,2.2253914105964778,2.2305879814125582,2.2307594494106713,2.2280305784618752,2.2313826501606622,1.9611369334591018,1.9594062897261626,1.9629540266408929,2.0450691977276332,2.0444716629706225,2.0455664219748027 +1,vs_linalg,release-signal,d4/la_stack_ldlt,d4,la_stack_ldlt,la_stack_ldlt,comparable,,21.137642787347982,21.098168018449119,21.171484657471375,21.313902652833498,21.261446636270481,21.360234691181692,7.4701380069258523,7.4474412297394448,7.4812695895170123,126.39093941990799,126.10741358337755,126.85194721964729 +1,vs_linalg,release-signal,d4/la_stack_ldlt_solve,d4,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,22.931503235979068,22.900540704307687,22.973165550179878,38.573182474947643,37.966452324972835,39.705685804297737,10.378239304933004,10.370538524252426,10.385190063997275,172.5801836169029,172.35986604196796,173.19864161065419 +1,vs_linalg,release-signal,d4/la_stack_lu,d4,la_stack_lu,la_stack_lu,comparable,,13.977633449875297,13.942079264132545,13.993157900570505,13.851550872115498,13.818557225822083,13.896676976534705,29.113518976083931,29.055764792996943,29.15906954005866,175.537450709913,174.26180812893358,176.32963983863019 +1,vs_linalg,release-signal,d4/la_stack_lu_solve,d4,la_stack_lu_solve,la_stack_lu_solve,comparable,,21.929507218887309,21.900285785590249,21.967722620134321,22.101084470745356,22.061056744915724,22.141461025001234,51.739268573691511,51.479007800226142,51.917790160922749,241.52526920712,239.31700735578784,243.22749256395002 +1,vs_linalg,release-signal,d4/la_stack_norm2_sq,d4,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,0.46055136772730737,0.45937336215932911,0.46102559501788137,0.46098710971834556,0.4596169676182012,0.46184721578489674,0.50425948898010986,0.50065038993157529,0.50578615444615382,4.137783381158898,4.1362097256486781,4.1394627993180357 +1,vs_linalg,release-signal,d4/la_stack_solve_from_ldlt,d4,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,2.4663434277095782,2.4649002744516775,2.4692107987241578,2.466292004820466,2.4653287724875375,2.4692981152227502,5.2623071102714931,5.2483264039035182,5.2769688602382541,44.822910230429628,44.573073436861492,44.949929161016485 +1,vs_linalg,release-signal,d4/la_stack_solve_from_lu,d4,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,3.9733737740840294,3.9636710042761587,3.9772183465587223,3.901012688961746,3.8951465539297843,3.9114985627114556,5.6927159129111846,5.6283988039939121,5.7104406887491246,59.876878630833765,59.475495314144965,60.226079962922071 +1,vs_linalg,release-signal,d5/la_stack_det,d5,la_stack_det,la_stack_det,comparable,,39.40608349392491,39.331896586305106,39.576091752751729,40.567011082659839,39.960970632951906,58.523420120829002,,,,,, +1,vs_linalg,release-signal,d5/la_stack_det_from_ldlt,d5,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,0.94599849938700598,0.94568243508526195,0.94626319782680213,0.94655301135325032,0.94616184308008511,0.94689145985800993,0.57937889603942083,0.57870167562661634,0.58043969224609437,1.2190249196316412,1.2168381801729677,1.2214995883916588 +1,vs_linalg,release-signal,d5/la_stack_det_from_lu,d5,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,1.1015983796470554,1.101183127274346,1.1021064106416207,1.1022258882248441,1.1018066626065501,1.1026267970329189,0.65427805826919683,0.653837969806359,0.65524447576090461,1.4770256550268943,1.4751936389856528,1.4797912596850908 +1,vs_linalg,release-signal,d5/la_stack_det_via_lu,d5,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,32.127657952618883,32.038993547380372,32.281886790833774,32.670987246083968,32.617566505314542,32.726126444630403,54.755718107252662,54.652969245995081,54.897429070927785,223.2819380094337,221.9447913467211,224.89249099599579 +1,vs_linalg,release-signal,d5/la_stack_dot,d5,la_stack_dot,la_stack_dot,comparable,,0.79936816435956315,0.79834845354981732,0.79978314216714508,0.8406735747771239,0.83844172789185933,0.84139156394285708,0.73727849817061941,0.73261449876639073,0.76137881564141774,2.7651797104965938,2.7579389823434375,2.8363339176613782 +1,vs_linalg,release-signal,d5/la_stack_inf_norm,d5,la_stack_inf_norm,la_stack_inf_norm,comparable,,3.4052080297268601,3.4008913852134062,3.4074695098138945,3.4684617394646611,3.4643543188091828,3.4699115725837606,3.1673625039640854,3.1642272055221903,3.1721395397266439,3.1590451380396192,3.1576778704478699,3.1606941315928827 +1,vs_linalg,release-signal,d5/la_stack_ldlt,d5,la_stack_ldlt,la_stack_ldlt,comparable,,40.470410957484475,40.36550055366444,40.600816328813295,41.920528362435114,41.565775051124746,42.281696523517383,26.101170756467255,25.119010115582,26.503605799574927,144.03046440227303,143.60505960867613,144.57351766832062 +1,vs_linalg,release-signal,d5/la_stack_ldlt_solve,d5,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,52.33981344478012,51.943685420419001,52.541915337341649,45.392000960485049,45.317111178076743,45.518174177959871,40.351447796923352,40.305128310577395,40.397862514646022,234.29381594515309,231.2199383949384,245.99130708001675 +1,vs_linalg,release-signal,d5/la_stack_lu,d5,la_stack_lu,la_stack_lu,comparable,,32.014093610389182,31.933497341330771,32.055757361450432,32.348290773011733,32.279072439154078,32.449564416712704,55.05506793569608,54.939011361822146,55.159798185153967,217.68227899454712,214.5903155983801,219.9681050132663 +1,vs_linalg,release-signal,d5/la_stack_lu_solve,d5,la_stack_lu_solve,la_stack_lu_solve,comparable,,44.3075005748926,43.902225822039881,44.798514530883182,46.069581545860736,45.989340313341678,46.107553270540038,69.002558524159397,68.864911949185142,69.169051099972151,326.84830597342926,324.01439752511988,361.58151429914557 +1,vs_linalg,release-signal,d5/la_stack_norm2_sq,d5,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,0.52412405074294355,0.52396726246572145,0.52456140234443782,0.52479372700869265,0.52460949765693132,0.52486715516251292,0.56358968881892391,0.56333496102642555,0.56371158163709256,4.1278402837829091,4.1253847302733666,4.1310534804390331 +1,vs_linalg,release-signal,d5/la_stack_solve_from_ldlt,d5,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,3.8811172441569823,3.8725555178656603,3.8876545928150299,3.9153183777127269,3.9068641749465898,3.9202612167427335,8.8544779083015364,8.845236263909241,8.8648101055136674,63.4258308050956,63.273790579248889,63.647973689794185 +1,vs_linalg,release-signal,d5/la_stack_solve_from_lu,d5,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,6.0070016296550497,6.0010640132266273,6.012031768250008,5.963079103195744,5.9613885689072124,5.965567315223554,8.815281644877496,8.8057420551853394,8.8388545618755021,93.590339488935797,91.593949640566308,94.999063083956614 +1,vs_linalg,release-signal,d64/la_stack_det,d64,la_stack_det,la_stack_det,comparable,,15207.69527540361,15170.642301392301,15247.474747474747,15106.018503004918,15054.057734204793,15163.643811274509,,,,,, +1,vs_linalg,release-signal,d64/la_stack_det_from_ldlt,d64,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,22.571496369881537,22.535721624350693,22.618762215789605,22.808443865618703,22.770255276355574,22.843487595675725,8.249940396615429,8.2233049972294303,8.2763312005474106,20.202288044945689,20.150360948167666,20.259886966535355 +1,vs_linalg,release-signal,d64/la_stack_det_from_lu,d64,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,22.983714321254389,22.949642913604933,23.023720654340735,22.930058618891245,22.880707670540719,23.014567167080276,8.5364425090841056,8.5119479774182345,8.5520505558430724,21.115244063421947,21.091019064312448,21.161360474026498 +1,vs_linalg,release-signal,d64/la_stack_det_via_lu,d64,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,15205.365616884133,15174.982733391864,15233.227392449517,15030.810513404089,14991.915780396666,15063.112156249435,13413.817640677491,13399.535013810404,13429.996992481203,10554.939784243217,10546.162218045112,10562.82456140351 +1,vs_linalg,release-signal,d64/la_stack_dot,d64,la_stack_dot,la_stack_dot,comparable,,10.667295877605513,10.632608020187991,10.6903019269308,10.812098556844106,10.792249974842171,10.82771477003118,8.9239290453232591,8.9079747959564735,8.9333250859687183,8.3034188431980862,8.2965849601282589,8.3063472935811529 +1,vs_linalg,release-signal,d64/la_stack_inf_norm,d64,la_stack_inf_norm,la_stack_inf_norm,comparable,,612.67706166136998,612.23822920395241,614.05090700603205,611.07792166337299,610.19545445829954,613.20009629209483,1087.784251947252,1084.2400709526694,1089.311591928752,1539.8378636835646,1535.3455770484677,1543.1198646806854 +1,vs_linalg,release-signal,d64/la_stack_ldlt,d64,la_stack_ldlt,la_stack_ldlt,comparable,,19636.022176659128,19598.416289592758,19652.870674288526,20869.835112127563,20806.83412014231,20910.114247311827,11475.384627998501,11460.926773455378,11503.222408026755,8809.0857784435757,8787.9351136107853,8815.610759938194 +1,vs_linalg,release-signal,d64/la_stack_ldlt_solve,d64,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,21849.512989267678,21787.999415204678,21901.756535947712,23163.83081672644,23075.668076109938,23257.08228980322,12116.365725802745,12089.861920516192,12144.257486878667,10147.293425804055,10130.908397841895,10156.142857142857 +1,vs_linalg,release-signal,d64/la_stack_lu,d64,la_stack_lu,la_stack_lu,comparable,,15020.950565610859,14988.802871148459,15033.46310851927,14416.577154101076,14397.024373638345,14437.318331643002,12926.12658877558,12913.189102564102,12940.517556534105,10410.050684079601,10395.806976010101,10431.587258454107 +1,vs_linalg,release-signal,d64/la_stack_lu_solve,d64,la_stack_lu_solve,la_stack_lu_solve,comparable,,17224.654903709925,17163.15221167673,17438.465935672517,17518.634339080461,17364.270300333705,17558.53448275862,14313.979335187058,14297.097222222223,14348.511153198653,12108.782627752282,12092.033074648929,12120.978128313891 +1,vs_linalg,release-signal,d64/la_stack_norm2_sq,d64,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,10.631014261815825,10.60027164012773,10.654554905395898,10.769371237225805,10.746926744318502,10.796910052000516,7.4578412026441825,7.4502590727671709,7.464919856559348,6.1918431286193352,6.1874536836146694,6.1944147573155339 +1,vs_linalg,release-signal,d64/la_stack_solve_from_ldlt,d64,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,1456.2225372793134,1452.6942392909896,1458.2102412604629,1075.5276946728513,1072.8316278250918,1079.2417264819958,1246.7030362260193,1242.6154081337691,1248.6174969939229,1264.6735002483326,1263.7592867246185,1266.3605380643012 +1,vs_linalg,release-signal,d64/la_stack_solve_from_lu,d64,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,2516.2626009619089,2512.1679488023165,2522.4009663797306,2473.9569243953529,2468.4816860465116,2477.0960897435898,793.31583294767699,792.86420461332091,793.89543920419226,1674.5171623643846,1671.6792929292928,1677.1226979217042 +1,vs_linalg,release-signal,d8/la_stack_det,d8,la_stack_det,la_stack_det,comparable,,90.719235033223271,90.462151679642261,90.962236009157294,90.467213413962952,90.291189700163471,90.64666257620658,,,,,, +1,vs_linalg,release-signal,d8/la_stack_det_from_ldlt,d8,la_stack_det_from_ldlt,la_stack_det_from_ldlt,comparable,,1.308435840033225,1.3061941017349838,1.3114203797861312,1.3080130158456464,1.3045225997759817,1.311677276182412,0.87234592841648606,0.86324747848159444,0.88325867123242841,1.9384033907082956,1.9328117064118919,1.9413545659412752 +1,vs_linalg,release-signal,d8/la_stack_det_from_ldlt_balanced_range,d8,la_stack_det_from_ldlt_balanced_range,la_stack_det_from_ldlt_balanced_range,comparable,,8.8883455909542448,8.8721478365676045,8.9136741220246947,8.9270169583701318,8.9196163123647914,8.9616343193929406,,,,,, +1,vs_linalg,release-signal,d8/la_stack_det_from_lu,d8,la_stack_det_from_lu,la_stack_det_from_lu,comparable,,1.4598180622196517,1.4583592408232178,1.4628869833591596,1.4641517639853654,1.4635468937960789,1.4678499618302665,0.98535975343514814,0.98242327253929662,0.99104895252705216,2.2038859562363911,2.2019173139860415,2.2055803639884513 +1,vs_linalg,release-signal,d8/la_stack_det_from_lu_balanced_range,d8,la_stack_det_from_lu_balanced_range,la_stack_det_from_lu_balanced_range,comparable,,9.7436031007159176,9.6960020712123551,9.8107707548470877,9.1185971673032995,8.9801989021188575,9.1545293519720623,,,,,, +1,vs_linalg,release-signal,d8/la_stack_det_via_lu,d8,la_stack_det_via_lu,la_stack_det_via_lu,comparable,,84.112698585908106,83.881894307270926,84.38582891736803,84.631303533081493,84.314938772443838,85.036987759910218,144.21997130210244,143.92196117644377,144.64664707311118,294.01942957120872,292.08674362951575,294.74423111437136 +1,vs_linalg,release-signal,d8/la_stack_dot,d8,la_stack_dot,la_stack_dot,comparable,,0.93937221818409977,0.93722760782645642,0.94169594880741492,0.96918402356973299,0.95055395536547094,0.98005076228991794,1.1173173909201215,1.117102926176363,1.1175329092884168,2.6425050473708547,2.6349563107055469,2.6520939194157696 +1,vs_linalg,release-signal,d8/la_stack_inf_norm,d8,la_stack_inf_norm,la_stack_inf_norm,comparable,,8.3830526828212015,8.3669134392449003,8.3944938886345142,8.3748414158707334,8.3526447111347757,8.3847523781992734,7.9843761752068714,7.9651141297285157,7.9966696917505287,8.0474286676406432,8.0382374300570945,8.0530700367401504 +1,vs_linalg,release-signal,d8/la_stack_ldlt,d8,la_stack_ldlt,la_stack_ldlt,comparable,,90.686252137269946,89.687846654034459,92.30551049255547,90.537505381958766,88.606591639871382,91.391898041817655,97.690419454187236,97.251753702260331,98.139106127642009,215.18860561660563,214.53889463477699,216.06437869822486 +1,vs_linalg,release-signal,d8/la_stack_ldlt_ill_conditioned,d8,la_stack_ldlt_ill_conditioned,la_stack_ldlt_ill_conditioned,comparable,,91.159842747353395,89.915177605258464,92.642076235049231,90.287424180014469,88.776374310620881,91.405170172293467,,,,,, +1,vs_linalg,release-signal,d8/la_stack_ldlt_solve,d8,la_stack_ldlt_solve,la_stack_ldlt_solve,comparable,,100.8861444627193,100.56537828947368,101.13264152352748,99.313379057762248,98.889911630259249,99.459419129804616,142.04424782382623,134.52634083628061,144.41083625415655,296.70276521178465,291.94465177890953,300.73671458209839 +1,vs_linalg,release-signal,d8/la_stack_lu,d8,la_stack_lu,la_stack_lu,comparable,,82.167530073796883,81.98027203149698,82.441800159476486,82.946446919227597,82.626058245223518,83.294220671814969,144.0248023325081,143.67071514222289,144.46397985552076,275.81565750813945,273.37038569407247,277.33431767648693 +1,vs_linalg,release-signal,d8/la_stack_lu_ill_conditioned,d8,la_stack_lu_ill_conditioned,la_stack_lu_ill_conditioned,comparable,,81.877170274862507,81.503847198601662,82.070371551398338,82.328248996857525,82.221830763901096,82.578222512413262,,,,,, +1,vs_linalg,release-signal,d8/la_stack_lu_pivoting,d8,la_stack_lu_pivoting,la_stack_lu_pivoting,comparable,,90.756932367149759,90.579648526077094,90.889373611111111,90.392132667828889,90.15913095725648,90.698515939904723,,,,,, +1,vs_linalg,release-signal,d8/la_stack_lu_solve,d8,la_stack_lu_solve,la_stack_lu_solve,comparable,,137.36038883699405,135.69560047895078,143.11210418485115,128.36396548733447,128.19900330404025,128.65769248327663,165.93327075645942,164.81581307583861,168.9136037004555,401.40034191661948,396.02358647682604,407.06850934153567 +1,vs_linalg,release-signal,d8/la_stack_norm2_sq,d8,la_stack_norm2_sq,la_stack_norm2_sq,comparable,,0.66300251273488808,0.66235143999066981,0.67068970285250595,0.66533532122302286,0.66493701036590735,0.66603860856580943,0.68346027762789074,0.68297289827892504,0.68492790540600901,4.2061410588498775,4.1736997788766326,4.2265823801092743 +1,vs_linalg,release-signal,d8/la_stack_solve_from_ldlt,d8,la_stack_solve_from_ldlt,la_stack_solve_from_ldlt,comparable,,8.0779518258595306,8.0711252555691839,8.0851973528908996,8.0495144449770883,8.0421017592553561,8.0555728018980233,21.003959880033349,20.975846187285221,21.022343920380187,71.061433500354653,70.841204754903146,71.133628204819175 +1,vs_linalg,release-signal,d8/la_stack_solve_from_lu,d8,la_stack_solve_from_lu,la_stack_solve_from_lu,comparable,,13.324863047565813,13.303189665207153,13.339757410396965,13.485412752904509,13.460706408754657,13.51681439600249,15.952043012868877,15.929072854588167,15.996979269078821,99.488997365968032,99.028214398910634,99.620785741955928 diff --git a/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.csv b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.csv new file mode 100644 index 0000000..d4f6903 --- /dev/null +++ b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.csv @@ -0,0 +1,956 @@ +phase,benchmark_id,sample_count,mean_ns,mean_ci_lower_ns,mean_ci_upper_ns,median_ns,median_ci_lower_ns,median_ci_upper_ns,confidence_level +baseline,d16/delaunay_scaled_norm,100,10.417475887218266,10.374427178651713,10.469299012112142,10.38207506282761,10.35543221087632,10.413645510422295,0.95 +baseline,d16/faer_det_from_ldlt,100,4.3469355351106085,4.320074990297426,4.3751497295343444,4.312750308986957,4.265186631489817,4.374237531514536,0.95 +baseline,d16/faer_det_from_lu,100,4.758521834556962,4.726418712191502,4.792341146280208,4.757082023372915,4.671861282890748,4.808185988934918,0.95 +baseline,d16/faer_det_via_lu,100,671.2463516363882,667.8436638321087,674.6504945443444,671.628704646185,665.5611022272783,677.1629375428963,0.95 +baseline,d16/faer_dot_native,100,3.2946914845900994,3.2901160476316162,3.2998804360448117,3.2925578685885055,3.2864943265647324,3.2982809563299242,0.95 +baseline,d16/faer_inf_norm,100,32.59951158318898,32.54691533460005,32.6553949883153,32.6629634947095,32.48680583418177,32.7108896184853,0.95 +baseline,d16/faer_ldlt,100,428.64730307149,427.25759267478145,430.04277239425244,428.15073922457987,426.1369556115768,430.767227237212,0.95 +baseline,d16/faer_ldlt_solve,100,626.3573719931959,624.8012725322253,628.0627963048279,626.0651040751543,624.8883984012887,627.1405832353256,0.95 +baseline,d16/faer_lu,100,643.2433893700411,640.4292006158604,646.123834752141,641.7734823377252,639.3541304428741,645.6600402094592,0.95 +baseline,d16/faer_lu_solve,100,905.7676851876499,903.3428909810007,908.3825793017039,903.140053398982,900.3068397120121,905.2987334534953,0.95 +baseline,d16/faer_norm2_sq,100,4.0581608986134565,4.053633677536744,4.0626865649751815,4.061418910165671,4.057867207206463,4.063361062506324,0.95 +baseline,d16/faer_norm_l2,100,19.64197620005565,19.558864503190378,19.736390769485716,19.512559621658163,19.483844428950857,19.578376021687426,0.95 +baseline,d16/faer_solve_from_ldlt,100,182.23005868621942,181.78169340173395,182.7066618833016,181.70095034620658,181.44538356380463,182.20675387148222,0.95 +baseline,d16/faer_solve_from_lu,100,261.2119456649973,259.7699679009463,262.7026806820103,258.7507552837898,255.7202506995387,262.4975472031057,0.95 +baseline,d16/iterative_f64_hypot,100,52.25955375006112,51.76841553543191,52.821223769969876,51.3083376439492,51.29612063430919,51.31785204303364,0.95 +baseline,d16/la_stack_det,100,434.91988073750355,432.72259342538285,437.28621071696205,433.3406678445973,430.973731884058,435.38348741418764,0.95 +baseline,d16/la_stack_det_from_ldlt,100,2.8811837342068594,2.8744535362168544,2.8888149472989344,2.8806776055144336,2.875427923290627,2.8841543768439752,0.95 +baseline,d16/la_stack_det_from_lu,100,3.2843009239718963,3.273603733360911,3.300238372673016,3.2763865769638247,3.270044493644869,3.2825737845844216,0.95 +baseline,d16/la_stack_det_via_lu,100,406.6463906828061,404.64456021779046,408.8381983571841,403.0988278008299,402.14042726795117,404.9911825726141,0.95 +baseline,d16/la_stack_dot,100,2.336413145378541,2.3308155123057896,2.342807753839651,2.32856822282391,2.3236962534881798,2.335283027809732,0.95 +baseline,d16/la_stack_inf_norm,100,32.19446364846091,32.13411881914991,32.25425526079304,32.24787874940725,32.17761679960931,32.29515190662431,0.95 +baseline,d16/la_stack_ldlt,100,384.3994013083504,383.5413225655956,385.35837497427025,383.3964008537058,382.42033372138144,383.9275115964833,0.95 +baseline,d16/la_stack_ldlt_solve,100,425.3757332799403,424.8476263834726,425.9331455719121,425.3746801911958,424.94756970145573,425.8154739209009,0.95 +baseline,d16/la_stack_lu,100,395.1824833219339,393.93534147970405,396.5554304584479,393.7731542611066,392.7855137241419,394.9719213798636,0.95 +baseline,d16/la_stack_lu_solve,100,642.6996891047229,640.9560761119145,644.645918477699,640.8175336496852,639.3896331978524,641.452487730252,0.95 +baseline,d16/la_stack_norm2_sq,100,2.058466784153448,2.0541839563498567,2.0625997841364017,2.063000931581313,2.0585849830533745,2.0654378654830685,0.95 +baseline,d16/la_stack_solve_from_ldlt,100,27.772205713843505,27.744027217406177,27.801945050202423,27.74973351728987,27.716402195047927,27.791723998444603,0.95 +baseline,d16/la_stack_solve_from_lu,100,190.56455421217993,189.3781290322276,191.88157471652417,187.96262283493763,187.58889885483666,188.61136663524977,0.95 +baseline,d16/nalgebra_cholesky,100,397.4180159552681,396.5023017802842,398.4579608305587,396.9967265057837,396.61820885279656,397.5952895649853,0.95 +baseline,d16/nalgebra_cholesky_solve,100,608.533909860143,606.6756869100828,610.7213806021009,607.4326689889276,606.5962095915602,608.8431751375567,0.95 +baseline,d16/nalgebra_det_from_cholesky,100,1.6819286515264893,1.6767980145429948,1.6871627489596714,1.6869694530351844,1.6820282940336735,1.691833066370803,0.95 +baseline,d16/nalgebra_det_from_lu,100,1.7732255639612253,1.7643432227192395,1.7823716371677432,1.766546064259014,1.7584242199581148,1.7734081843208913,0.95 +baseline,d16/nalgebra_det_via_lu,100,448.58680705749117,447.7575067363704,449.3938294622854,449.4561034438153,448.40147721045486,450.3217221319177,0.95 +baseline,d16/nalgebra_dot,100,1.8607524958653157,1.8569338108426903,1.8646678974762771,1.8602276927511512,1.8592289616619428,1.860930162217945,0.95 +baseline,d16/nalgebra_inf_norm,100,31.34992142755309,31.31074716750352,31.392431992102487,31.353979063243642,31.335346507565713,31.379620025715106,0.95 +baseline,d16/nalgebra_lu,100,454.2665123588504,453.5603905983032,455.0266374262889,453.80245729277374,452.9381517888407,454.1445917932735,0.95 +baseline,d16/nalgebra_lu_solve,100,569.4667514879011,568.4065742091103,570.5566900458234,569.4458712557102,568.9098484848485,569.9060010943388,0.95 +baseline,d16/nalgebra_norm,100,1.5961999317242423,1.5921770701216604,1.6006862076995303,1.5928659947807657,1.5873881379211365,1.5942739457275321,0.95 +baseline,d16/nalgebra_norm_squared,100,1.4762011241141872,1.474209955052152,1.4782982431202705,1.4771868874299177,1.4761062369740032,1.4780276761745883,0.95 +baseline,d16/nalgebra_solve_from_cholesky,100,115.86677312477583,115.65766721737809,116.094141750232,116.06720734784034,115.68642951109564,116.22006269896731,0.95 +baseline,d16/nalgebra_solve_from_lu,100,92.17464670212759,91.9917781696586,92.36699966858508,92.24934771869499,92.11129332093321,92.34965026939773,0.95 +baseline,d2/delaunay_scaled_norm,100,1.236210798930626,1.233415505411079,1.2391914590147952,1.236581835099707,1.2340266566028177,1.2379444975666487,0.95 +baseline,d2/faer_det_from_ldlt,100,0.5519276334566036,0.5502585682236006,0.5537126717764276,0.5485047762006635,0.5477026978008944,0.5504449634487478,0.95 +baseline,d2/faer_det_from_lu,100,0.7533553846916005,0.7478377469617464,0.7596675648657162,0.7432466239490834,0.7431845690490781,0.7434227688924671,0.95 +baseline,d2/faer_det_via_lu,100,135.55614677248602,133.57092427300532,137.71157065406442,131.68361099747773,131.10937944410747,132.03241713110734,0.95 +baseline,d2/faer_dot_native,100,2.595818104035834,2.572532931536192,2.6198117060900317,2.502146929625926,2.489087121305878,2.683038093322199,0.95 +baseline,d2/faer_inf_norm,100,0.6828974532250275,0.6797832670362977,0.6861859010988165,0.6721530623677812,0.6717768401580549,0.6726867144060416,0.95 +baseline,d2/faer_ldlt,100,98.3439334459175,98.0208996778536,98.68276773169498,97.97341504582243,97.64644532655518,98.35525398680412,0.95 +baseline,d2/faer_ldlt_solve,100,145.782899469564,145.06197831814015,146.50604882106114,145.8555382031095,143.473177053984,147.26974942140896,0.95 +baseline,d2/faer_lu,100,123.08118999896455,122.03525493685353,124.17988820383604,120.85079986178687,120.03323306309831,121.7131579520799,0.95 +baseline,d2/faer_lu_solve,100,182.89347321546978,182.34074480316477,183.51918773542286,182.53202843068811,182.06757130922546,183.01508533237856,0.95 +baseline,d2/faer_norm2_sq,100,4.078357182523085,4.066264965606266,4.0917278262492465,4.055277772983192,4.05275189150907,4.058480837752264,0.95 +baseline,d2/faer_norm_l2,100,5.5188819902436,5.445615702767088,5.593095602342489,5.514531735831568,5.420923716733103,5.605929420320704,0.95 +baseline,d2/faer_solve_from_ldlt,100,44.64384346207491,44.25398776517769,45.07553900591245,43.96454034330141,43.73478311531409,44.19207267658595,0.95 +baseline,d2/faer_solve_from_lu,100,54.87304780188503,54.68903972828382,55.0663329292458,54.80421144756742,54.6129027585028,54.87025062943465,0.95 +baseline,d2/iterative_f64_hypot,100,2.3478798872512643,2.307976083649161,2.388796804328237,2.202377908964832,2.1973158796415926,2.272463099182789,0.95 +baseline,d2/la_stack_det,100,0.5739596127967669,0.5736074230698368,0.5745036831637719,0.5739273915299211,0.5737198515886803,0.5740274980375597,0.95 +baseline,d2/la_stack_det_from_ldlt,100,0.5020025603206307,0.49937782772454087,0.504921388994688,0.49605866835964646,0.4959675384816711,0.49618662196432084,0.95 +baseline,d2/la_stack_det_from_lu,100,0.5228116651658896,0.5221912462607772,0.5234465294650839,0.5209324802133135,0.5203740398553962,0.5246209412353151,0.95 +baseline,d2/la_stack_det_via_lu,100,1.7628343270443692,1.7583214879187987,1.7670943945123272,1.7679449006571393,1.7671939097260814,1.7688273448767438,0.95 +baseline,d2/la_stack_dot,100,0.6136417903504011,0.611700744457083,0.6156333174820264,0.613527600443982,0.6127654377432821,0.6140270708807744,0.95 +baseline,d2/la_stack_inf_norm,100,0.6243546005549312,0.6233269925545921,0.6256483684217803,0.6228706614371607,0.622521405598159,0.6232262286020255,0.95 +baseline,d2/la_stack_ldlt,100,6.4722799187981535,6.45815735926964,6.490917606656688,6.467917404489176,6.463056655902873,6.475095909642831,0.95 +baseline,d2/la_stack_ldlt_solve,100,9.392475780164661,9.345347048813851,9.452587085862648,9.326728242481016,9.315659127590472,9.333592106152851,0.95 +baseline,d2/la_stack_lu,100,1.5566833406843132,1.5536860294782795,1.5595728992601898,1.5601441095260733,1.5581005650018285,1.5620621774871468,0.95 +baseline,d2/la_stack_lu_solve,100,2.062327389146348,2.051268454956453,2.074073567834016,2.031409297480675,2.0302198287717603,2.0345467303122184,0.95 +baseline,d2/la_stack_norm2_sq,100,0.395829779206593,0.39481124001002516,0.3969768329240359,0.3950409205290601,0.394879579797198,0.39537735031682,0.95 +baseline,d2/la_stack_solve_from_ldlt,100,1.2060303284448306,1.1961338728385824,1.2155458527589178,1.2190136869369586,1.2025643334946778,1.2355617067423554,0.95 +baseline,d2/la_stack_solve_from_lu,100,1.250905606602393,1.2479515409302138,1.2541526597343897,1.2453167718999847,1.2426647173570333,1.2489582164418285,0.95 +baseline,d2/nalgebra_cholesky,100,1.7035858575970346,1.7011538484197526,1.706201679636906,1.703673051936607,1.70210459040074,1.7063749118829425,0.95 +baseline,d2/nalgebra_cholesky_solve,100,2.5317739244974353,2.52184930139083,2.5436735318433974,2.51972035984115,2.516149021065984,2.5265791815742578,0.95 +baseline,d2/nalgebra_det_from_cholesky,100,0.435623958697735,0.43478681151400805,0.43646590328291107,0.43621764800254126,0.4349573146324742,0.4370683730964601,0.95 +baseline,d2/nalgebra_det_from_lu,100,0.4506568036364796,0.44952328836133615,0.45194911290264783,0.44852288390755124,0.4483276192218324,0.44907305991161456,0.95 +baseline,d2/nalgebra_det_via_lu,100,0.8268624445031371,0.8246315112324291,0.8294120436446354,0.8245753018766044,0.8220953346895524,0.8265616606062666,0.95 +baseline,d2/nalgebra_dot,100,0.5602218960215589,0.5595616219846061,0.5609469824723579,0.5606425778998259,0.5601794632929089,0.5609718270813127,0.95 +baseline,d2/nalgebra_inf_norm,100,0.4996628249238132,0.49886992975693517,0.5005690941213791,0.4982717355551484,0.49814894563945694,0.49836580472015024,0.95 +baseline,d2/nalgebra_lu,100,1.6082102428309863,1.6058316694136174,1.6106093952092202,1.6088793413144622,1.6055014356953712,1.611840229478437,0.95 +baseline,d2/nalgebra_lu_solve,100,4.495822969818482,4.479176778689656,4.515032369754365,4.4787720282632115,4.471223731681299,4.488903340683946,0.95 +baseline,d2/nalgebra_norm,100,0.49486653513797374,0.49411007269069296,0.4956445491033438,0.49481495575971174,0.49414234424631676,0.49543795461417867,0.95 +baseline,d2/nalgebra_norm_squared,100,0.3882181365541804,0.38776522677495784,0.3887111703135428,0.3886802611068316,0.3882252164903363,0.3890655484100167,0.95 +baseline,d2/nalgebra_solve_from_cholesky,100,1.244308239662325,1.239492252600095,1.249786577533368,1.2368166338341426,1.2348758039826044,1.2413110353601422,0.95 +baseline,d2/nalgebra_solve_from_lu,100,2.867630268419893,2.8636855905539482,2.87181782328281,2.8650984215665636,2.8624578315899427,2.872719695961203,0.95 +baseline,d3/delaunay_scaled_norm,100,1.750161109180815,1.7473977048702352,1.7530577585208795,1.752699757206758,1.7493297149824178,1.7550120867055317,0.95 +baseline,d3/faer_det_from_ldlt,100,0.7423293769266407,0.7416182731048302,0.7432300285607399,0.7429406902916269,0.7421586514412614,0.7431684009292009,0.95 +baseline,d3/faer_det_from_lu,100,0.9913127488786686,0.9901778528196276,0.9927141993274645,0.9908795673907953,0.990439840446541,0.9911801969327287,0.95 +baseline,d3/faer_det_via_lu,100,172.56641107643568,169.37985613659734,175.84339733910258,162.8661068584128,161.84255350690262,164.18815092570892,0.95 +baseline,d3/faer_dot_native,100,2.937859185989457,2.9044212192916805,2.971667642731076,2.972104300409015,2.967263666802655,2.9737072044585546,0.95 +baseline,d3/faer_inf_norm,100,1.2541225569653875,1.2513879026909074,1.2571186057812795,1.2543560581510862,1.2485904067302944,1.2574672016871224,0.95 +baseline,d3/faer_ldlt,100,108.9165322384862,108.38963682802394,109.47248943611366,108.22496781137824,107.80687397708674,109.0961018676262,0.95 +baseline,d3/faer_ldlt_solve,100,155.71712204225128,155.22384463784158,156.25537386660935,155.3584554027743,154.6383401275217,155.90266889655413,0.95 +baseline,d3/faer_lu,100,166.45798828289614,163.20093930806482,169.89002822965125,156.64884372337724,155.37278578448223,158.01224418140694,0.95 +baseline,d3/faer_lu_solve,100,221.66472794445986,219.9587622687004,223.4432762342371,217.56680047835044,216.1785685588016,219.0290055716943,0.95 +baseline,d3/faer_norm2_sq,100,4.091006645114607,4.085694023399089,4.096370045173409,4.091779680594993,4.087014853078861,4.095288000072761,0.95 +baseline,d3/faer_norm_l2,100,5.931758969182319,5.886093998370566,5.977788236849495,5.925549915397632,5.84797861706615,6.02123897995774,0.95 +baseline,d3/faer_solve_from_ldlt,100,46.352638063907314,45.87138635091703,46.84913199669809,45.82010383303406,45.41934618671291,46.51210628242306,0.95 +baseline,d3/faer_solve_from_lu,100,62.69152087226169,60.84448302063916,64.58782016087729,56.68617356711995,56.484327764812235,56.979242838971345,0.95 +baseline,d3/iterative_f64_hypot,100,3.2586765954666648,3.2499079564293107,3.267537917940882,3.254424402770945,3.248101951781245,3.265186935747645,0.95 +baseline,d3/la_stack_det,100,1.3285972893913174,1.3258508013101336,1.331862393039634,1.3248260462690267,1.3241936110286718,1.325669453672313,0.95 +baseline,d3/la_stack_det_from_ldlt,100,0.5960179801292316,0.59512258887296,0.5971246723827968,0.5947799228150503,0.5947221911678024,0.5949242118555222,0.95 +baseline,d3/la_stack_det_from_lu,100,0.6963748799438075,0.6950866120653313,0.6978368265853888,0.6938290699475134,0.6937245554107127,0.693955281660387,0.95 +baseline,d3/la_stack_det_via_lu,100,8.711527438237063,8.69388994938024,8.7298300149336,8.69872835734959,8.682048134421539,8.71959391827626,0.95 +baseline,d3/la_stack_dot,100,0.6662908847228785,0.6649176536389523,0.6679147069724322,0.6646600626965735,0.6644987218999356,0.6649384155342027,0.95 +baseline,d3/la_stack_inf_norm,100,1.3040133365411637,1.3016804844977037,1.3068603652742379,1.301873604920094,1.3012035317105675,1.3022769209393514,0.95 +baseline,d3/la_stack_ldlt,100,13.365816447293973,13.331365161385657,13.40392596023791,13.365571137774044,13.32666856698679,13.388654282023392,0.95 +baseline,d3/la_stack_ldlt_solve,100,12.77784178911875,12.682776216719498,12.877644389040508,12.539766048291,12.47990558126806,12.576982845534463,0.95 +baseline,d3/la_stack_lu,100,8.287676741791886,8.269850628400713,8.306239653620512,8.275340394958992,8.262238939677848,8.302681989155797,0.95 +baseline,d3/la_stack_lu_solve,100,10.104647429499098,10.066384381742175,10.145437585513116,10.088217111140551,10.041843004661228,10.159124028084907,0.95 +baseline,d3/la_stack_norm2_sq,100,0.44409234125242997,0.4433613110042286,0.44483662700045523,0.444331028043923,0.4436284370678498,0.4449051787417072,0.95 +baseline,d3/la_stack_solve_from_ldlt,100,1.7832112466099295,1.7811099816274125,1.7855611612598288,1.7797906835768509,1.7792510114171358,1.781121544963801,0.95 +baseline,d3/la_stack_solve_from_lu,100,2.068404446965435,2.0623861247584494,2.074761171138555,2.053308509738102,2.0515242639054314,2.0560913182004255,0.95 +baseline,d3/nalgebra_cholesky,100,3.8550182445196093,3.8483218627842586,3.861984884823517,3.854880152140328,3.8496021469670976,3.861444967723176,0.95 +baseline,d3/nalgebra_cholesky_solve,100,5.610144970630155,5.584103961867068,5.640255415884389,5.57965224227463,5.5669118207312955,5.612654527210118,0.95 +baseline,d3/nalgebra_det_from_cholesky,100,0.4882712888552312,0.48152647615876404,0.5010929225155558,0.4817481881254781,0.4812692610077103,0.4823436654238502,0.95 +baseline,d3/nalgebra_det_from_lu,100,0.49208192220135444,0.48920319804134027,0.4951409492965499,0.48748885143063264,0.4866649180625239,0.4884768781028227,0.95 +baseline,d3/nalgebra_det_via_lu,100,18.047927460550866,17.755827560213678,18.532874522372243,17.78206896534542,17.683878473352575,17.86672024251859,0.95 +baseline,d3/nalgebra_dot,100,0.6849912293583036,0.6829828655539375,0.6871539489812194,0.6825432377424738,0.6817478159740775,0.6839707132327281,0.95 +baseline,d3/nalgebra_inf_norm,100,1.1185735101118566,1.1145607207847628,1.1227040454519228,1.1111305491166579,1.1071917895656265,1.1131111255161568,0.95 +baseline,d3/nalgebra_lu,100,14.821111831037182,14.768161396306041,14.876611272350761,14.751846435975526,14.71103012926266,14.778186260671214,0.95 +baseline,d3/nalgebra_lu_solve,100,23.09211153580554,22.975861469778078,23.214687508231606,22.79479095228905,22.713611901221796,22.98916653289352,0.95 +baseline,d3/nalgebra_norm,100,0.6846529941510916,0.6831257079623637,0.686497047298163,0.6839842650198276,0.6832046699527402,0.6852238739805452,0.95 +baseline,d3/nalgebra_norm_squared,100,0.4383525741416584,0.43739790904463416,0.439449414857438,0.4370795023991086,0.4366720511388804,0.43740679552668504,0.95 +baseline,d3/nalgebra_solve_from_cholesky,100,2.759363277226054,2.7484218366963478,2.77209042954754,2.749177076490213,2.7409270248937236,2.759600398374224,0.95 +baseline,d3/nalgebra_solve_from_lu,100,4.486019912027611,4.4791577268718505,4.49300209795684,4.486517821056882,4.475278075910657,4.498855840625171,0.95 +baseline,d32/delaunay_scaled_norm,100,24.529857287085875,24.478325943328194,24.592514184908794,24.51104172824909,24.459501159988893,24.547436687508174,0.95 +baseline,d32/faer_det_from_ldlt,100,8.404159798906232,8.315670007787391,8.509577532497136,8.254119052774065,8.227621238393784,8.298089727688101,0.95 +baseline,d32/faer_det_from_lu,100,8.61849448214076,8.59181060446196,8.645312735188107,8.637812637629882,8.592390748605395,8.658574581903267,0.95 +baseline,d32/faer_det_via_lu,100,2324.0615190157723,2314.6444012571646,2334.1398202394694,2310.7510427515745,2304.895813098938,2316.1990997508237,0.95 +baseline,d32/faer_dot_native,100,4.951879153180673,4.942287212748514,4.962748490207521,4.940159341901305,4.938883572520623,4.947278442500695,0.95 +baseline,d32/faer_inf_norm,100,164.07286842522183,163.64890744120754,164.55135852368636,163.63962038379032,163.3993741492679,164.21209669997975,0.95 +baseline,d32/faer_ldlt,100,1455.8472722744395,1453.2181997109444,1458.5310483509588,1454.7438107869143,1449.6722607631095,1458.0513655551765,0.95 +baseline,d32/faer_ldlt_solve,100,1939.4823184021525,1937.035905364143,1942.135455382638,1938.3953822178478,1937.6810118562767,1940.7293257376919,0.95 +baseline,d32/faer_lu,100,2267.6804713422,2261.797000704607,2274.119516551795,2261.2271180447083,2256.120443272006,2269.3012987012985,0.95 +baseline,d32/faer_lu_solve,100,2926.266233681761,2918.1771528849486,2934.785201989108,2919.2900818850267,2913.423424369748,2925.1436105476673,0.95 +baseline,d32/faer_norm2_sq,100,4.2157612896177685,4.210808328354203,4.221805106514484,4.211603473718856,4.210801060585807,4.212400350451281,0.95 +baseline,d32/faer_norm_l2,100,27.544981060912168,27.367026864114266,27.724862984001675,27.159745158469647,26.95739717266136,28.071305048228126,0.95 +baseline,d32/faer_solve_from_ldlt,100,467.3909785087201,466.7478003512543,468.05507641985986,466.93149123865453,466.2831394503417,467.56257876496534,0.95 +baseline,d32/faer_solve_from_lu,100,632.9497733568282,631.3195048874355,634.7885522371843,631.029177893276,629.4646719674416,632.4718910642022,0.95 +baseline,d32/iterative_f64_hypot,100,170.5429087455763,167.84922562063082,173.3081405042824,160.27642809302776,159.62723322675646,163.02517354042203,0.95 +baseline,d32/la_stack_det,100,2183.42260155854,2177.9507228185034,2189.236956710946,2179.691354657688,2172.672076045311,2184.6388888888887,0.95 +baseline,d32/la_stack_det_from_ldlt,100,7.737181691048175,7.715420074145149,7.761784896091903,7.715119845858209,7.699134030269933,7.737037425720983,0.95 +baseline,d32/la_stack_det_from_lu,100,9.107103929120239,9.08113956545228,9.13462172396679,9.055764608360565,9.043475243210562,9.081814403015445,0.95 +baseline,d32/la_stack_det_via_lu,100,2047.9076218899284,2044.594171399755,2051.4123920872717,2046.0624938536557,2041.3038606747048,2051.063637354255,0.95 +baseline,d32/la_stack_dot,100,4.005594745792157,3.9990547983889573,4.0129766268542,4.005044008903182,4.0012220974534545,4.0083585622839255,0.95 +baseline,d32/la_stack_inf_norm,100,126.90308223583301,126.64717179554845,127.1803101356457,126.96311798060728,126.86053717923132,127.1746112917999,0.95 +baseline,d32/la_stack_ldlt,100,2443.086353329656,2437.550954851939,2449.231707354483,2435.52098889465,2429.6358198451794,2441.070978335717,0.95 +baseline,d32/la_stack_ldlt_solve,100,2796.5724208753354,2784.24450594989,2809.8832354084416,2779.6149964463393,2770.8428694158074,2790.4230555555555,0.95 +baseline,d32/la_stack_lu,100,2113.534584588985,2103.6599150823995,2124.230350441618,2111.0872659501733,2100.5552685950415,2123.7427206533016,0.95 +baseline,d32/la_stack_lu_solve,100,2793.9508415451774,2783.7078597214468,2805.111292976623,2782.321466803124,2768.6283143939395,2798.484344777563,0.95 +baseline,d32/la_stack_norm2_sq,100,3.9593506811979666,3.950753390222079,3.9691294097762695,3.9536483462889596,3.9507604826267237,3.955358586507939,0.95 +baseline,d32/la_stack_solve_from_ldlt,100,309.3770540397471,308.1096661840626,310.7822810641639,307.53942374499667,306.9733917039245,307.84513160166335,0.95 +baseline,d32/la_stack_solve_from_lu,100,664.8933619679057,661.249899792479,669.1505794446448,661.045446713948,659.9519652777777,662.2213866666667,0.95 +baseline,d32/nalgebra_cholesky,100,2066.750766424077,2060.33773682606,2073.629098964109,2058.36521827155,2054.021433399978,2064.9730621576155,0.95 +baseline,d32/nalgebra_cholesky_solve,100,2697.5550187490944,2689.8391969414306,2705.980714357074,2689.9108787607984,2685.7882037533514,2693.2391730253657,0.95 +baseline,d32/nalgebra_det_from_cholesky,100,2.9572685449828824,2.953186532820127,2.9616341995688016,2.9575668764860588,2.9533704308656255,2.9612696377300076,0.95 +baseline,d32/nalgebra_det_from_lu,100,3.0659822463030126,3.0592350297046886,3.073864110262808,3.063231073004194,3.058571115995306,3.0667491876998865,0.95 +baseline,d32/nalgebra_det_via_lu,100,2199.4549024004864,2193.3968851834775,2205.9918754316495,2194.7460702161725,2188.8989397699074,2200.584173139512,0.95 +baseline,d32/nalgebra_dot,100,4.7174268788148135,4.70747513471785,4.7284081043335435,4.7174753890800005,4.711161018144647,4.722795879206347,0.95 +baseline,d32/nalgebra_inf_norm,100,157.11108624966437,155.73053878684428,158.49403829389834,158.53327140255777,154.91656977880257,159.5608448432649,0.95 +baseline,d32/nalgebra_lu,100,2140.739334275078,2134.8702288936274,2147.0965119462235,2135.819073466625,2126.3990384615386,2142.12029677113,0.95 +baseline,d32/nalgebra_lu_solve,100,2721.4875569719125,2714.333503231828,2729.5349579621557,2710.234582397889,2703.7424869037773,2717.3389959916017,0.95 +baseline,d32/nalgebra_norm,100,3.9101125780203363,3.9007965920340006,3.920963599757572,3.9071822755022425,3.8998697642766933,3.9102493904496547,0.95 +baseline,d32/nalgebra_norm_squared,100,3.7801886434610323,3.7724615497442793,3.7877674726171318,3.7842635532354545,3.7772728379042992,3.7883241613028007,0.95 +baseline,d32/nalgebra_solve_from_cholesky,100,536.2401552398085,533.6066891304733,539.2279787353921,533.1921386679521,531.199725151041,534.3393500511133,0.95 +baseline,d32/nalgebra_solve_from_lu,100,327.6707433822347,327.01782252853815,328.4118215176349,327.4233276786394,327.04018825645124,327.75330304914723,0.95 +baseline,d4/delaunay_scaled_norm,100,2.399670708973643,2.3921996715929286,2.4082207735855614,2.3966188347732675,2.391592223030098,2.400629581064185,0.95 +baseline,d4/faer_det_from_ldlt,100,0.9826246201220973,0.9803187666775859,0.9851464574960156,0.9804318751985073,0.97939547658448,0.9821959892591566,0.95 +baseline,d4/faer_det_from_lu,100,1.239230955466436,1.2369150129789162,1.2418806018082666,1.237809172948956,1.2364530940897243,1.238467637320522,0.95 +baseline,d4/faer_det_via_lu,100,181.01403607043608,180.0712557401763,182.10435028497267,179.46078924202118,179.00082239292504,180.9103182397153,0.95 +baseline,d4/faer_dot_native,100,2.6715535373554484,2.6600276855049563,2.683669745651624,2.6374727019075666,2.6247867528100004,2.695178963668248,0.95 +baseline,d4/faer_inf_norm,100,2.046070044230367,2.0439314054262687,2.0487763734721214,2.045069197727633,2.0444716629706225,2.0455664219748027,0.95 +baseline,d4/faer_ldlt,100,126.40850208150405,126.12550791390947,126.69099970269271,126.390939419908,126.10741358337755,126.85194721964729,0.95 +baseline,d4/faer_ldlt_solve,100,173.40713709779374,172.86268623070066,173.97464412442142,172.5801836169029,172.35986604196796,173.1986416106542,0.95 +baseline,d4/faer_lu,100,176.77204945606573,175.68584982625987,177.95680140082976,175.537450709913,174.26180812893358,176.3296398386302,0.95 +baseline,d4/faer_lu_solve,100,248.44282971821883,245.79196397522307,251.22606570985192,241.52526920712,239.31700735578784,243.22749256395002,0.95 +baseline,d4/faer_norm2_sq,100,4.136002612806061,4.132161383037027,4.1402714240734735,4.137783381158898,4.136209725648678,4.139462799318036,0.95 +baseline,d4/faer_norm_l2,100,13.874876552113845,13.822774070486087,13.93017583006199,13.879420133193047,13.80308947003747,13.921256449509555,0.95 +baseline,d4/faer_solve_from_ldlt,100,44.967396760234706,44.769896654102276,45.17754120465734,44.82291023042963,44.57307343686149,44.949929161016485,0.95 +baseline,d4/faer_solve_from_lu,100,61.85596915246217,61.12307039207172,62.61650172254662,59.876878630833765,59.475495314144965,60.22607996292207,0.95 +baseline,d4/iterative_f64_hypot,100,5.433425848599435,5.418275017025367,5.450684682190387,5.430736956878281,5.418899834111014,5.4407949055021625,0.95 +baseline,d4/la_stack_det,100,2.5467645397700958,2.540227082824392,2.553552656927978,2.5537463679528294,2.5519270947417345,2.555683558826972,0.95 +baseline,d4/la_stack_det_from_ldlt,100,0.7681714491867778,0.7678127800815829,0.7686954769905305,0.7679683639564061,0.7678375366025257,0.7680860499373898,0.95 +baseline,d4/la_stack_det_from_lu,100,0.8676277264499827,0.8670659131468257,0.8684389654891475,0.867210700210185,0.8670549715475353,0.8673766126381303,0.95 +baseline,d4/la_stack_det_via_lu,100,14.411485964646623,14.376803863967712,14.442563630125983,14.448818945101834,14.429619465413968,14.47571409957581,0.95 +baseline,d4/la_stack_dot,100,0.6811659026068848,0.6798127177198138,0.6827198570679541,0.6795957264719814,0.6794107352092228,0.6800319751796344,0.95 +baseline,d4/la_stack_inf_norm,100,2.2291492857943562,2.224747407764926,2.234310047945247,2.2292751061255,2.225391410596478,2.230587981412558,0.95 +baseline,d4/la_stack_ldlt,100,21.268810802474047,21.160268677505197,21.3911921801984,21.137642787347982,21.09816801844912,21.171484657471375,0.95 +baseline,d4/la_stack_ldlt_solve,100,22.941680614699425,22.899401579857365,22.98331057044305,22.93150323597907,22.900540704307687,22.97316555017988,0.95 +baseline,d4/la_stack_lu,100,13.94647574898939,13.924356191782746,13.966864754218147,13.977633449875297,13.942079264132545,13.993157900570505,0.95 +baseline,d4/la_stack_lu_solve,100,21.988326693875003,21.932303231252437,22.052976673769116,21.92950721888731,21.90028578559025,21.96772262013432,0.95 +baseline,d4/la_stack_norm2_sq,100,0.46116081771787415,0.45975159131021487,0.46272492134634363,0.46055136772730737,0.4593733621593291,0.4610255950178814,0.95 +baseline,d4/la_stack_solve_from_ldlt,100,2.5090571378222792,2.49396713267376,2.5255515710854195,2.466343427709578,2.4649002744516775,2.469210798724158,0.95 +baseline,d4/la_stack_solve_from_lu,100,3.9674308924806683,3.9610160010344133,3.9737660894827553,3.9733737740840294,3.9636710042761587,3.9772183465587223,0.95 +baseline,d4/nalgebra_cholesky,100,7.467294914805713,7.445140156253455,7.493287492769935,7.470138006925852,7.447441229739445,7.481269589517012,0.95 +baseline,d4/nalgebra_cholesky_solve,100,10.44036152418999,10.39151038004791,10.501022461379717,10.378239304933004,10.370538524252426,10.385190063997275,0.95 +baseline,d4/nalgebra_det_from_cholesky,100,0.49434248596817204,0.4913924264478061,0.4974498437090022,0.4901527736640667,0.48919111688314537,0.49104120441711785,0.95 +baseline,d4/nalgebra_det_from_lu,100,0.5853081326625731,0.5830083758240558,0.587734859278859,0.5813789572655239,0.5807165685605722,0.5816483012835133,0.95 +baseline,d4/nalgebra_det_via_lu,100,30.01883904902533,29.95913604511082,30.083396296973984,30.000059894391974,29.96215892046709,30.044589670874757,0.95 +baseline,d4/nalgebra_dot,100,0.6270319801361545,0.6256050238192301,0.628653356130069,0.6258106070284358,0.6248136542648987,0.6266340339694298,0.95 +baseline,d4/nalgebra_inf_norm,100,1.956122515045959,1.951161490763146,1.9601886998155242,1.9611369334591018,1.9594062897261626,1.962954026640893,0.95 +baseline,d4/nalgebra_lu,100,29.1407140728728,29.085730816297872,29.2026296478797,29.11351897608393,29.055764792996943,29.15906954005866,0.95 +baseline,d4/nalgebra_lu_solve,100,51.62204137769297,51.42501855009974,51.82284021753105,51.73926857369151,51.47900780022614,51.91779016092275,0.95 +baseline,d4/nalgebra_norm,100,0.6411304213121218,0.6389564841757249,0.6438056271298148,0.6386929097131409,0.6376423865991362,0.6404612525781493,0.95 +baseline,d4/nalgebra_norm_squared,100,0.5045974238058539,0.5023272638560268,0.5071405094960857,0.5042594889801099,0.5006503899315753,0.5057861544461538,0.95 +baseline,d4/nalgebra_solve_from_cholesky,100,5.312093604935163,5.281380970191955,5.348007245005562,5.262307110271493,5.248326403903518,5.276968860238254,0.95 +baseline,d4/nalgebra_solve_from_lu,100,5.670320322926594,5.655226520120907,5.685497091186039,5.692715912911185,5.628398803993912,5.710440688749125,0.95 +baseline,d5/delaunay_scaled_norm,100,3.059305781712364,3.050092799662158,3.069310668031259,3.0608343091646604,3.0506850315438863,3.0673266694714534,0.95 +baseline,d5/faer_det_from_ldlt,100,1.2196755960414405,1.2162897040051301,1.22334468877329,1.2190249196316412,1.2168381801729677,1.2214995883916588,0.95 +baseline,d5/faer_det_from_lu,100,1.4783243052438795,1.473299494121114,1.4861073839760335,1.4770256550268943,1.4751936389856528,1.4797912596850908,0.95 +baseline,d5/faer_det_via_lu,100,230.43645149227416,227.39123967789777,233.67592534666014,223.2819380094337,221.9447913467211,224.8924909959958,0.95 +baseline,d5/faer_dot_native,100,2.8284212451517483,2.807736599628324,2.8494656405194907,2.765179710496594,2.7579389823434375,2.836333917661378,0.95 +baseline,d5/faer_inf_norm,100,3.158061229552098,3.1547222143443836,3.161604290585087,3.159045138039619,3.15767787044787,3.1606941315928827,0.95 +baseline,d5/faer_ldlt,100,144.74196424636978,144.21417665808514,145.29442682242413,144.03046440227303,143.60505960867613,144.57351766832062,0.95 +baseline,d5/faer_ldlt_solve,100,234.70797668415295,231.26605606862168,238.15653081715467,234.29381594515309,231.2199383949384,245.99130708001675,0.95 +baseline,d5/faer_lu,100,222.86447077711307,219.7894634437068,226.06910405078693,217.68227899454712,214.5903155983801,219.9681050132663,0.95 +baseline,d5/faer_lu_solve,100,356.6929798292104,348.04540182662515,365.55405798288535,326.84830597342926,324.0143975251199,361.58151429914557,0.95 +baseline,d5/faer_norm2_sq,100,4.130954485603865,4.125495986682615,4.13781808462883,4.127840283782909,4.125384730273367,4.131053480439033,0.95 +baseline,d5/faer_norm_l2,100,14.383485809043071,14.306911519866802,14.464481514971508,14.317726458445534,14.23910557494516,14.395529063381058,0.95 +baseline,d5/faer_solve_from_ldlt,100,85.47540696630296,79.2068421658364,91.88862190954988,63.4258308050956,63.27379057924889,63.647973689794185,0.95 +baseline,d5/faer_solve_from_lu,100,93.4936042389602,92.54021931331191,94.44537004992762,93.5903394889358,91.59394964056631,94.99906308395661,0.95 +baseline,d5/iterative_f64_hypot,100,8.146056269537178,8.128019224864648,8.164079077521315,8.16259285529635,8.14834976752699,8.174736964299571,0.95 +baseline,d5/la_stack_det,100,39.47990262958914,39.38622183365855,39.57923940244671,39.40608349392491,39.331896586305106,39.57609175275173,0.95 +baseline,d5/la_stack_det_from_ldlt,100,0.9463485229393993,0.9453453216932153,0.9475594520916046,0.945998499387006,0.945682435085262,0.9462631978268021,0.95 +baseline,d5/la_stack_det_from_lu,100,1.1022807491342284,1.100991371295518,1.103925565405003,1.1015983796470554,1.101183127274346,1.1021064106416207,0.95 +baseline,d5/la_stack_det_via_lu,100,44.810532233799876,41.21775024808369,48.44785587538459,32.12765795261888,32.03899354738037,32.281886790833774,0.95 +baseline,d5/la_stack_dot,100,0.7942864291331091,0.7903444694616747,0.7982258494597455,0.7993681643595631,0.7983484535498173,0.7997831421671451,0.95 +baseline,d5/la_stack_inf_norm,100,3.3994097413934043,3.3947227543083436,3.4042115086176628,3.40520802972686,3.400891385213406,3.4074695098138945,0.95 +baseline,d5/la_stack_ldlt,100,40.62475264269503,40.43948685056485,40.83696310775769,40.470410957484475,40.36550055366444,40.600816328813295,0.95 +baseline,d5/la_stack_ldlt_solve,100,55.25320110426328,53.95713728013855,56.6489575478474,52.33981344478012,51.943685420419,52.54191533734165,0.95 +baseline,d5/la_stack_lu,100,32.11745589296096,32.010612428887654,32.23005846955458,32.01409361038918,31.93349734133077,32.05575736145043,0.95 +baseline,d5/la_stack_lu_solve,100,57.921040535265405,53.82856294994825,62.19635963656261,44.3075005748926,43.90222582203988,44.79851453088318,0.95 +baseline,d5/la_stack_norm2_sq,100,0.5247607484186609,0.5242960537493687,0.5253422130440236,0.5241240507429435,0.5239672624657215,0.5245614023444378,0.95 +baseline,d5/la_stack_solve_from_ldlt,100,3.8879495191644495,3.8797918248334256,3.896608909325678,3.8811172441569823,3.8725555178656603,3.88765459281503,0.95 +baseline,d5/la_stack_solve_from_lu,100,6.016741243371613,6.004449502416999,6.031427804453652,6.00700162965505,6.001064013226627,6.012031768250008,0.95 +baseline,d5/nalgebra_cholesky,100,25.68336407128611,25.203599850741057,26.157194386340656,26.101170756467255,25.119010115582,26.503605799574927,0.95 +baseline,d5/nalgebra_cholesky_solve,100,42.39326253796646,41.52676969553603,43.3653498995818,40.35144779692335,40.305128310577395,40.39786251464602,0.95 +baseline,d5/nalgebra_det_from_cholesky,100,0.5792197542937748,0.5775267042298566,0.5809283588463652,0.5793788960394208,0.5787016756266163,0.5804396922460944,0.95 +baseline,d5/nalgebra_det_from_lu,100,0.6641716773947103,0.6600486266745745,0.6687803624379107,0.6542780582691968,0.653837969806359,0.6552444757609046,0.95 +baseline,d5/nalgebra_det_via_lu,100,54.767863508911944,54.67874505492917,54.85809735954635,54.75571810725266,54.65296924599508,54.897429070927785,0.95 +baseline,d5/nalgebra_dot,100,0.7504496300827277,0.7460974005504986,0.7549304445702828,0.7372784981706194,0.7326144987663907,0.7613788156414177,0.95 +baseline,d5/nalgebra_inf_norm,100,3.1625413704918115,3.1567612140327843,3.168152320412406,3.1673625039640854,3.1642272055221903,3.172139539726644,0.95 +baseline,d5/nalgebra_lu,100,55.06662609500352,54.95364241445004,55.18194077931638,55.05506793569608,54.939011361822146,55.15979818515397,0.95 +baseline,d5/nalgebra_lu_solve,100,72.68086559798051,71.04207979773082,74.47069203080767,69.0025585241594,68.86491194918514,69.16905109997215,0.95 +baseline,d5/nalgebra_norm,100,0.7589806036731747,0.757698332414917,0.7603612179515189,0.759365256885302,0.7584044521818387,0.7599739226658506,0.95 +baseline,d5/nalgebra_norm_squared,100,0.5636749636630933,0.5632396547764389,0.5642456676811949,0.5635896888189239,0.5633349610264256,0.5637115816370926,0.95 +baseline,d5/nalgebra_solve_from_cholesky,100,8.888439280566196,8.864129094562209,8.91762000143338,8.854477908301536,8.845236263909241,8.864810105513667,0.95 +baseline,d5/nalgebra_solve_from_lu,100,8.818487185585504,8.802364471244948,8.835072922306562,8.815281644877496,8.80574205518534,8.838854561875502,0.95 +baseline,d64/delaunay_scaled_norm,100,47.29827841727225,46.9846079818715,47.62780527084714,47.02377056876857,46.4444124657938,47.84346634259915,0.95 +baseline,d64/faer_det_from_ldlt,100,20.313892228753335,20.216104296427588,20.433966948987567,20.20228804494569,20.150360948167666,20.259886966535355,0.95 +baseline,d64/faer_det_from_lu,100,21.225101440010484,21.134949145848275,21.336598052026815,21.115244063421947,21.091019064312448,21.1613604740265,0.95 +baseline,d64/faer_det_via_lu,100,10561.570646307058,10541.459219044507,10584.041493966679,10554.939784243217,10546.162218045112,10562.82456140351,0.95 +baseline,d64/faer_dot_native,100,8.335283039949044,8.31466571207252,8.358971444805423,8.303418843198086,8.296584960128259,8.306347293581153,0.95 +baseline,d64/faer_inf_norm,100,1538.1298376525526,1535.2710864436262,1540.9074245145182,1539.8378636835646,1535.3455770484677,1543.1198646806854,0.95 +baseline,d64/faer_ldlt,100,8801.82014357323,8790.887233515736,8813.545668481058,8809.085778443576,8787.935113610785,8815.610759938194,0.95 +baseline,d64/faer_ldlt_solve,100,10154.555776011699,10133.747004695266,10178.972600754154,10147.293425804055,10130.908397841895,10156.142857142857,0.95 +baseline,d64/faer_lu,100,10420.4636829647,10397.318790690553,10447.668706007202,10410.0506840796,10395.8069760101,10431.587258454107,0.95 +baseline,d64/faer_lu_solve,100,12103.518785588583,12086.445462116411,12120.094960459975,12108.782627752282,12092.033074648929,12120.978128313891,0.95 +baseline,d64/faer_norm2_sq,100,6.188516549194564,6.1817983879815905,6.197412302505369,6.191843128619335,6.187453683614669,6.194414757315534,0.95 +baseline,d64/faer_norm_l2,100,41.230603773884006,41.05142953342401,41.45181552328675,41.06962877704015,40.9434183819085,41.190242705058196,0.95 +baseline,d64/faer_solve_from_ldlt,100,1267.795770624091,1264.7231376707032,1271.2272138797643,1264.6735002483326,1263.7592867246185,1266.3605380643012,0.95 +baseline,d64/faer_solve_from_lu,100,1674.062098500166,1671.497035999547,1676.6539134191664,1674.5171623643846,1671.6792929292928,1677.1226979217042,0.95 +baseline,d64/iterative_f64_hypot,100,460.03383425684666,457.63348723848384,462.37612022043,467.24489331201124,467.1209072489869,467.311236296242,0.95 +baseline,d64/la_stack_det,100,15103.56762087606,15054.021704032142,15152.03102654723,15207.69527540361,15170.642301392301,15247.474747474747,0.95 +baseline,d64/la_stack_det_from_ldlt,100,22.52324998308297,22.46006466137772,22.58071707516919,22.571496369881537,22.535721624350693,22.618762215789605,0.95 +baseline,d64/la_stack_det_from_lu,100,22.987634081313715,22.923477972997652,23.05827403159569,22.98371432125439,22.949642913604933,23.023720654340735,0.95 +baseline,d64/la_stack_det_via_lu,100,15081.012052903094,15015.878551065987,15142.913804522968,15205.365616884133,15174.982733391864,15233.227392449517,0.95 +baseline,d64/la_stack_dot,100,10.679565393578212,10.64059215143797,10.725290946008757,10.667295877605513,10.632608020187991,10.6903019269308,0.95 +baseline,d64/la_stack_inf_norm,100,614.7868679005405,612.6533816099796,617.3781798957438,612.67706166137,612.2382292039524,614.050907006032,0.95 +baseline,d64/la_stack_ldlt,100,19624.105102051053,19576.166983925184,19675.94131110345,19636.022176659128,19598.41628959276,19652.870674288526,0.95 +baseline,d64/la_stack_ldlt_solve,100,21917.162957923116,21859.20075273606,21979.745446418678,21849.512989267678,21787.99941520468,21901.756535947712,0.95 +baseline,d64/la_stack_lu,100,15017.53931797962,14998.924482949209,15037.278879097325,15020.95056561086,14988.802871148459,15033.46310851927,0.95 +baseline,d64/la_stack_lu_solve,100,17290.372474932858,17222.320029369406,17358.03302620136,17224.654903709925,17163.15221167673,17438.465935672517,0.95 +baseline,d64/la_stack_norm2_sq,100,10.651354111055646,10.610804016746416,10.697152803009324,10.631014261815825,10.60027164012773,10.654554905395898,0.95 +baseline,d64/la_stack_solve_from_ldlt,100,1458.2021854423415,1453.7236569068089,1463.8154721774195,1456.2225372793134,1452.6942392909896,1458.210241260463,0.95 +baseline,d64/la_stack_solve_from_lu,100,2535.544234712632,2522.7099169631306,2550.451206479083,2516.262600961909,2512.1679488023165,2522.4009663797306,0.95 +baseline,d64/nalgebra_cholesky,100,11493.192883100342,11469.878253100462,11519.565259733112,11475.384627998501,11460.926773455378,11503.222408026755,0.95 +baseline,d64/nalgebra_cholesky_solve,100,12118.551419660276,12100.970079510069,12137.73385402073,12116.365725802745,12089.861920516192,12144.257486878667,0.95 +baseline,d64/nalgebra_det_from_cholesky,100,8.241386273370722,8.221217745593226,8.262545382760052,8.249940396615429,8.22330499722943,8.27633120054741,0.95 +baseline,d64/nalgebra_det_from_lu,100,8.521805550579444,8.499375581891004,8.543313905479902,8.536442509084106,8.511947977418235,8.552050555843072,0.95 +baseline,d64/nalgebra_det_via_lu,100,13434.056373044348,13412.257711024857,13458.153805660593,13413.817640677491,13399.535013810404,13429.996992481203,0.95 +baseline,d64/nalgebra_dot,100,8.913877327445476,8.899292311319922,8.928507379169838,8.92392904532326,8.907974795956473,8.933325085968718,0.95 +baseline,d64/nalgebra_inf_norm,100,1094.8680192734917,1088.2384313941861,1102.4568105550945,1087.784251947252,1084.2400709526694,1089.311591928752,0.95 +baseline,d64/nalgebra_lu,100,12976.720680840519,12947.558019368964,13008.792556462204,12926.12658877558,12913.189102564102,12940.517556534105,0.95 +baseline,d64/nalgebra_lu_solve,100,14352.795146859136,14318.948727841667,14389.235387200357,14313.979335187058,14297.097222222223,14348.511153198653,0.95 +baseline,d64/nalgebra_norm,100,7.5668951381133365,7.557088116824472,7.577249419153876,7.5729203386772985,7.562389242045517,7.576199459480035,0.95 +baseline,d64/nalgebra_norm_squared,100,7.4554184189053965,7.443996162547655,7.468022548938956,7.4578412026441825,7.450259072767171,7.464919856559348,0.95 +baseline,d64/nalgebra_solve_from_cholesky,100,1249.0380047998456,1244.3903503697265,1254.385211921089,1246.7030362260193,1242.615408133769,1248.617496993923,0.95 +baseline,d64/nalgebra_solve_from_lu,100,795.4409230512227,793.7780574984387,797.1592987708259,793.315832947677,792.8642046133209,793.8954392041923,0.95 +baseline,d8/delaunay_scaled_norm,100,5.251314547895496,5.234569346654188,5.270811197426597,5.237992721308114,5.225824256267386,5.2505654753739535,0.95 +baseline,d8/faer_det_from_ldlt,100,1.976315344024613,1.9518739960287554,2.0070742412660905,1.9384033907082956,1.932811706411892,1.9413545659412752,0.95 +baseline,d8/faer_det_from_lu,100,2.233924979119171,2.2128174788827275,2.2596179974956163,2.203885956236391,2.2019173139860415,2.2055803639884513,0.95 +baseline,d8/faer_det_via_lu,100,293.1932375251413,292.3157892902726,294.0656086489961,294.0194295712087,292.08674362951575,294.74423111437136,0.95 +baseline,d8/faer_dot_native,100,2.6441338221563826,2.637176896968933,2.6512680461506037,2.6425050473708547,2.634956310705547,2.6520939194157696,0.95 +baseline,d8/faer_inf_norm,100,8.04638496816908,8.033522261633449,8.061779418438311,8.047428667640643,8.038237430057094,8.05307003674015,0.95 +baseline,d8/faer_ldlt,100,215.48762040913465,214.90662905507583,216.0760852822629,215.18860561660563,214.538894634777,216.06437869822486,0.95 +baseline,d8/faer_ldlt_solve,100,296.60251336473726,294.9934594729206,298.2203757987653,296.70276521178465,291.94465177890953,300.7367145820984,0.95 +baseline,d8/faer_lu,100,275.82765493556826,274.8821195322635,276.7748293998451,275.81565750813945,273.37038569407247,277.33431767648693,0.95 +baseline,d8/faer_lu_solve,100,401.8920081868432,399.40278195837743,404.4324521280376,401.4003419166195,396.02358647682604,407.0685093415357,0.95 +baseline,d8/faer_norm2_sq,100,4.209942563470207,4.1956477591529655,4.2246068563599435,4.2061410588498775,4.173699778876633,4.226582380109274,0.95 +baseline,d8/faer_norm_l2,100,16.10706599741056,16.058032962539045,16.15640258892435,16.10116869787211,16.046861099028263,16.161633979722968,0.95 +baseline,d8/faer_solve_from_ldlt,100,71.20650706889825,71.04049877508051,71.38874245267064,71.06143350035465,70.84120475490315,71.13362820481917,0.95 +baseline,d8/faer_solve_from_lu,100,99.22860270108822,98.94373693438773,99.51374072234114,99.48899736596803,99.02821439891063,99.62078574195593,0.95 +baseline,d8/iterative_f64_hypot,100,18.884250209846368,18.81393669442806,18.968663276295917,18.828470726516088,18.779789298953975,18.865798713881816,0.95 +baseline,d8/la_stack_det,100,91.09548977000495,90.7893715257033,91.41764993942806,90.71923503322327,90.46215167964226,90.9622360091573,0.95 +baseline,d8/la_stack_det_from_ldlt,100,1.3118844143754267,1.3089776814524774,1.3150712442933696,1.308435840033225,1.3061941017349838,1.3114203797861312,0.95 +baseline,d8/la_stack_det_from_ldlt_balanced_range,100,8.899669457466995,8.872848364388707,8.926511666558486,8.888345590954245,8.872147836567605,8.913674122024695,0.95 +baseline,d8/la_stack_det_from_lu,100,1.4607665067929088,1.4587013478230597,1.4629473742177648,1.4598180622196517,1.4583592408232178,1.4628869833591596,0.95 +baseline,d8/la_stack_det_from_lu_balanced_range,100,9.760830542658878,9.71027641925685,9.810889651812026,9.743603100715918,9.696002071212355,9.810770754847088,0.95 +baseline,d8/la_stack_det_via_lu,100,84.46166402536709,84.20914665036634,84.7360200023806,84.1126985859081,83.88189430727093,84.38582891736803,0.95 +baseline,d8/la_stack_dot,100,0.9403532672171698,0.9373454473901759,0.9439304774194069,0.9393722181840998,0.9372276078264564,0.9416959488074149,0.95 +baseline,d8/la_stack_inf_norm,100,8.377454957386357,8.365276991237735,8.390009753317145,8.383052682821202,8.3669134392449,8.394493888634514,0.95 +baseline,d8/la_stack_ldlt,100,91.09988212781231,90.66333355592117,91.53838612917907,90.68625213726995,89.68784665403446,92.30551049255547,0.95 +baseline,d8/la_stack_ldlt_ill_conditioned,100,91.27329899368246,90.85897329782718,91.69140872425041,91.1598427473534,89.91517760525846,92.64207623504923,0.95 +baseline,d8/la_stack_ldlt_solve,100,100.95958358948465,100.64807553436681,101.2758451668084,100.8861444627193,100.56537828947368,101.13264152352748,0.95 +baseline,d8/la_stack_lu,100,82.15860770422522,81.94387899061861,82.38006047185073,82.16753007379688,81.98027203149698,82.44180015947649,0.95 +baseline,d8/la_stack_lu_ill_conditioned,100,82.00670583380678,81.69580403288907,82.33446011554801,81.87717027486251,81.50384719860166,82.07037155139834,0.95 +baseline,d8/la_stack_lu_pivoting,100,90.9690776595279,90.67512733983527,91.29648791632555,90.75693236714976,90.5796485260771,90.88937361111111,0.95 +baseline,d8/la_stack_lu_solve,100,137.61292101539775,136.0478142180918,139.16396379423009,137.36038883699405,135.69560047895078,143.11210418485115,0.95 +baseline,d8/la_stack_norm2_sq,100,0.6751845958168944,0.669460064723117,0.6823065393253076,0.6630025127348881,0.6623514399906698,0.670689702852506,0.95 +baseline,d8/la_stack_solve_from_ldlt,100,8.077434173961286,8.064185965952369,8.092553307337077,8.07795182585953,8.071125255569184,8.0851973528909,0.95 +baseline,d8/la_stack_solve_from_lu,100,13.39217580831289,13.300822897360044,13.53799146619626,13.324863047565813,13.303189665207153,13.339757410396965,0.95 +baseline,d8/nalgebra_cholesky,100,98.20295651180214,97.76808098984232,98.71129976381631,97.69041945418724,97.25175370226033,98.13910612764201,0.95 +baseline,d8/nalgebra_cholesky_solve,100,139.56099641972224,138.41123581920434,140.7109983280902,142.04424782382623,134.5263408362806,144.41083625415655,0.95 +baseline,d8/nalgebra_det_from_cholesky,100,0.8788561864057141,0.8745908312589147,0.8832355824378265,0.8723459284164861,0.8632474784815944,0.8832586712324284,0.95 +baseline,d8/nalgebra_det_from_lu,100,0.9758250884100497,0.9704659949010729,0.9809841438535388,0.9853597534351481,0.9824232725392966,0.9910489525270522,0.95 +baseline,d8/nalgebra_det_via_lu,100,144.4191749445642,144.14007911793593,144.70686730062744,144.21997130210244,143.92196117644377,144.64664707311118,0.95 +baseline,d8/nalgebra_dot,100,1.1173070435463444,1.116527028796019,1.1184476058421389,1.1173173909201215,1.117102926176363,1.1175329092884168,0.95 +baseline,d8/nalgebra_inf_norm,100,7.97540392338305,7.963309837699601,7.987628416023831,7.984376175206871,7.965114129728516,7.996669691750529,0.95 +baseline,d8/nalgebra_lu,100,144.36709386534167,143.92203551187126,144.83043223573193,144.0248023325081,143.6707151422229,144.46397985552076,0.95 +baseline,d8/nalgebra_lu_solve,100,168.86944911334567,167.46664764322065,170.31372933103205,165.93327075645942,164.8158130758386,168.9136037004555,0.95 +baseline,d8/nalgebra_norm,100,1.0493482452508216,1.0348699213970203,1.0624700312112312,1.0697679712765735,1.0677796518278944,1.0717116364958421,0.95 +baseline,d8/nalgebra_norm_squared,100,0.689170555263054,0.687230475059272,0.6912301436514376,0.6834602776278907,0.682972898278925,0.684927905406009,0.95 +baseline,d8/nalgebra_solve_from_cholesky,100,21.13249230834867,21.03596731512316,21.25450252438861,21.00395988003335,20.97584618728522,21.022343920380187,0.95 +baseline,d8/nalgebra_solve_from_lu,100,15.96431553998279,15.929939457239374,16.00015121784687,15.952043012868877,15.929072854588167,15.996979269078821,0.95 +baseline,exact_d2/det,100,0.4588392866841711,0.4530378178005241,0.4649112356289649,0.43847576051642734,0.43771116413319694,0.44014508325985335,0.95 +baseline,exact_d2/det_direct,100,0.45997463122714977,0.454028068792735,0.46616706823525483,0.4389020864431492,0.4380179728642223,0.4427072597382428,0.95 +baseline,exact_d2/det_direct_with_errbound,100,1.7083001879781616,1.7067871286490677,1.7103428099389302,1.707590361999432,1.7070745586021363,1.7081829879281933,0.95 +baseline,exact_d2/det_errbound,100,1.6603284229914985,1.643247053909174,1.686030653092138,1.6517834250166323,1.6332174430567585,1.6587981067136037,0.95 +baseline,exact_d2/det_exact,100,110.90537385735237,110.6038104779258,111.26404769418212,110.54949764112055,110.4165319475389,110.67008305854891,0.95 +baseline,exact_d2/det_exact_f64_result,100,71.56612378490145,71.33570883601266,71.8536503288328,71.30418634861795,71.22932589901015,71.45005551093683,0.95 +baseline,exact_d2/det_exact_rounded_f64,100,72.91648102209612,72.76384629749927,73.08635706173234,72.70349950837755,72.59951086170598,72.74977731468684,0.95 +baseline,exact_d2/det_sign_exact,100,2.728144312502053,2.7232394799812454,2.73404826251118,2.7246048207347155,2.723521870369656,2.725285210808588,0.95 +baseline,exact_d2/solve_exact,100,7054.969368063486,7044.809563054287,7065.211174722395,7056.953172846123,7048.471785248601,7067.765092544542,0.95 +baseline,exact_d2/solve_exact_f64_result,100,8273.423228596615,8264.900530723253,8282.219351728932,8275.0384273637,8263.977615440115,8283.70412087912,0.95 +baseline,exact_d2/solve_exact_rounded_f64,100,7477.146824714707,7469.0851113356,7485.112091009183,7483.854729782202,7465.414980750846,7492.640016564647,0.95 +baseline,exact_d3/det,100,0.8249594979377731,0.8230638171337528,0.8270413744238723,0.8199098141277079,0.8197211574959417,0.8202812765941737,0.95 +baseline,exact_d3/det_direct,100,0.8235149002354899,0.8217498850359183,0.8256719582085388,0.8196496853790022,0.819450016342423,0.8199153562751998,0.95 +baseline,exact_d3/det_direct_with_errbound,100,3.351786980218337,3.3487027806950755,3.3559210138906073,3.351294461220312,3.349721136241599,3.3519037902029045,0.95 +baseline,exact_d3/det_errbound,100,3.299084627653103,3.2967993736405043,3.3024955321927973,3.297382728745932,3.2966626351444424,3.2988260711232167,0.95 +baseline,exact_d3/det_exact,100,370.88317011837796,370.18066920306046,371.63251625405405,370.6210303452962,369.86403420087237,371.50005831882476,0.95 +baseline,exact_d3/det_exact_f64_result,100,339.17248454443353,338.34584337460757,340.07008553509723,338.5062526186821,337.96742945629734,339.2069127868093,0.95 +baseline,exact_d3/det_exact_rounded_f64,100,340.7787889320448,339.94741734333627,341.65555709179455,340.13469534949354,338.8381139384934,341.2326068550284,0.95 +baseline,exact_d3/det_sign_exact,100,4.71998213079706,4.710437436588219,4.731191013455751,4.707080172922456,4.703410948268171,4.708769129011382,0.95 +baseline,exact_d3/solve_exact,100,30905.319783004932,30831.61798547033,30984.405395480462,30841.78669716028,30782.165945165943,30891.305627705628,0.95 +baseline,exact_d3/solve_exact_f64_result,100,32801.03486379174,32757.181990056524,32844.56991456908,32798.86160990165,32755.004207025,32869.90811339198,0.95 +baseline,exact_d3/solve_exact_rounded_f64,100,31478.142126400922,31410.94395901844,31545.96528194714,31458.35763888889,31348.545350609755,31602.896875,0.95 +baseline,exact_d4/det,100,3.209103882817725,3.2049085972705686,3.214526742223024,3.2107365390289107,3.2073757625246007,3.21233074246595,0.95 +baseline,exact_d4/det_direct,100,2.384046366546539,2.3801874730405155,2.388863702354106,2.381474667849078,2.3799999033543298,2.382708612464108,0.95 +baseline,exact_d4/det_direct_with_errbound,100,6.819226276559658,6.807915812904829,6.832283416180191,6.808852637289467,6.8048633104768035,6.812232553558011,0.95 +baseline,exact_d4/det_errbound,100,6.722335935514702,6.717373380874751,6.729297148452395,6.7250463620252106,6.720992575431982,6.726573551619592,0.95 +baseline,exact_d4/det_exact,100,1216.9394803882176,1213.3919741493355,1220.691762893526,1215.8668534223154,1213.1349449204406,1219.8847409220725,0.95 +baseline,exact_d4/det_exact_f64_result,100,1170.0736387558784,1166.221873404025,1173.9731145908638,1167.6428712048482,1161.2254407063178,1173.5005889281508,0.95 +baseline,exact_d4/det_exact_rounded_f64,100,1178.1153599286736,1173.8804771448104,1182.6823042332271,1171.4858209981605,1169.1150100692432,1174.6918181526723,0.95 +baseline,exact_d4/det_sign_exact,100,7.705737807471204,7.69612426732867,7.71581469027619,7.710156944765581,7.704916203751171,7.7126271970046645,0.95 +baseline,exact_d4/solve_exact,100,80460.17924024795,80245.7126488253,80693.69953986515,80394.59314790671,80267.51219512195,80493.11221322537,0.95 +baseline,exact_d4/solve_exact_f64_result,100,83515.87660053423,83325.14585930109,83723.63858136184,83385.52847222221,83236.68981481482,83625.90922619047,0.95 +baseline,exact_d4/solve_exact_rounded_f64,100,81382.40060449918,81132.11652841879,81659.40299566783,81020.18544793621,80744.5815018315,81523.86633779264,0.95 +baseline,exact_d5/det,100,24.754912636981388,24.708178590496114,24.803258543233042,24.706097978590183,24.655587555199386,24.791548754935597,0.95 +baseline,exact_d5/det_exact,100,3537.0224821091692,3524.943384456219,3549.2003679120767,3535.3914879218037,3515.021289351497,3543.500972049533,0.95 +baseline,exact_d5/det_exact_f64_result,100,3482.173978224554,3476.118138648899,3488.039018942074,3485.8665144577712,3476.122468282362,3495.0472987355784,0.95 +baseline,exact_d5/det_exact_rounded_f64,100,3471.027892830491,3460.152949876379,3481.22917812033,3473.9049837486455,3463.680897503592,3483.547838756678,0.95 +baseline,exact_d5/det_sign_exact,100,3587.5832181110636,3578.090261025698,3597.3998046740185,3580.47068425592,3569.2386709245743,3589.6393233692506,0.95 +baseline,exact_d5/solve_exact,100,160583.8295274329,160088.06463243338,161129.5119818363,159876.9784053156,159632.96205357142,160238.92712355213,0.95 +baseline,exact_d5/solve_exact_f64_result,100,163568.33920023488,163200.18804617348,163977.38449658235,163373.71251822723,162906.96709401708,163708.7142857143,0.95 +baseline,exact_d5/solve_exact_rounded_f64,100,161679.9695285742,161332.23626986548,162077.18403335148,161497.72549019608,161195.44624447718,161731.3115079365,0.95 +baseline,exact_hilbert_4x4/det_exact,100,1351.9318196621614,1341.7070446420291,1362.7450091027613,1343.9629729729731,1326.0616085491088,1349.5065170008718,0.95 +baseline,exact_hilbert_4x4/det_sign_exact,100,7.7076244872023105,7.700210853348349,7.71597666806474,7.709975802354905,7.703320375722957,7.711681044267705,0.95 +baseline,exact_hilbert_4x4/solve_exact,100,60218.462692003006,60106.72987535677,60328.64931475474,60212.50400223381,60125.52521008404,60288.124183006534,0.95 +baseline,exact_hilbert_4x4/solve_exact_f64_result,100,63132.203151734044,62910.43126456011,63374.32465689583,62745.329296875,62653.01067073171,62890.50148809524,0.95 +baseline,exact_hilbert_4x4/solve_exact_rounded_f64,100,61055.50815726734,60949.17570113125,61161.302086191885,61090.85716884478,60948.11294117647,61183.744241053064,0.95 +baseline,exact_hilbert_5x5/det_exact,100,3675.431895868686,3666.531763112087,3684.488681636326,3678.9161175072823,3660.1433136369824,3687.5988028606967,0.95 +baseline,exact_hilbert_5x5/det_sign_exact,100,3877.7141973721314,3866.79992851765,3888.7065911498103,3874.813731971154,3866.276392313465,3883.6263427734375,0.95 +baseline,exact_hilbert_5x5/solve_exact,100,124821.0167260267,124588.36245552052,125056.5586401304,124693.28132387708,124443.84693548387,124966.275,0.95 +baseline,exact_hilbert_5x5/solve_exact_f64_result,100,128665.11293294327,128054.3150877374,129342.8478360137,127731.9060075541,127443.08035714286,128189.74266154453,0.95 +baseline,exact_hilbert_5x5/solve_exact_rounded_f64,100,126481.03600676611,126201.4014587931,126771.93221652582,126570.84456663764,126106.27380952382,126930.64945652174,0.95 +baseline,exact_large_entries_3x3/det_exact,100,339.52793895759737,338.3788384363675,340.7544375788275,338.46964670112493,337.7445356125356,339.5196294569628,0.95 +baseline,exact_large_entries_3x3/det_sign_exact,100,323.3939393378555,321.81010610027084,325.11643270153667,320.81136421991346,319.60410234571845,323.00216143144695,0.95 +baseline,exact_large_entries_3x3/solve_exact,100,94021.50877729456,93869.73419628771,94178.98680969949,93994.31235047846,93805.53837072018,94257.29933481153,0.95 +baseline,exact_large_entries_3x3/solve_exact_f64_result,100,94885.31238876122,94758.04181684103,95017.19726895978,94712.19405594406,94653.40909090909,94795.4663243733,0.95 +baseline,exact_large_entries_3x3/solve_exact_rounded_f64,100,94551.6771792897,94404.82218243799,94704.5977938374,94493.95784163753,94433.55544922913,94605.49062168071,0.95 +baseline,exact_near_singular_3x3/det_exact,100,342.3680465563537,341.4175651730294,343.4065789547439,341.96981679675184,341.18232136632975,342.76592927638586,0.95 +baseline,exact_near_singular_3x3/det_sign_exact,100,398.0444391758523,395.8775152901023,400.1244211524398,398.2575514743394,394.77626794258373,401.150122914506,0.95 +baseline,exact_near_singular_3x3/solve_exact,100,2612.0159759036187,2605.596644630547,2619.0594600440427,2604.670967959782,2599.2047933943322,2610.941017789443,0.95 +baseline,exact_near_singular_3x3/solve_exact_f64_result,100,2709.879038410192,2702.395357526126,2718.1836333183887,2703.630049877204,2697.649796195652,2709.8011333510076,0.95 +baseline,exact_near_singular_3x3/solve_exact_rounded_f64,100,2607.895342292855,2602.455237350324,2613.688950549314,2604.1845499181672,2597.253324468085,2611.2813367252543,0.95 +baseline,exact_random_corpus_d2/det_exact,100,3118.216116468386,3115.663084354392,3121.039552995571,3119.59670900073,3116.117499039913,3122.630949298078,0.95 +baseline,exact_random_corpus_d2/det_sign_exact,100,136.63603707115809,136.14960515045536,137.13386975341103,136.37221632196758,135.62830106889038,136.9651415513103,0.95 +baseline,exact_random_corpus_d2/solve_exact,100,67709.92202368822,67514.64023515244,67918.50242422131,67472.58407407408,67329.50487804879,67587.88888888889,0.95 +baseline,exact_random_corpus_d2/solve_exact_f64_result,100,78686.36048868227,78352.71288397095,79039.20526524463,78304.63800904978,77844.55630452023,78737.26863446631,0.95 +baseline,exact_random_corpus_d2/solve_exact_rounded_f64,100,68675.52411842858,68520.26928586708,68838.12157617371,68555.18555555555,68410.07275471698,68680.15714285715,0.95 +baseline,exact_random_corpus_d3/det_exact,100,8363.093286248817,8279.559399024358,8447.38965796527,8346.2073986195,8075.079751923844,8636.45081967213,0.95 +baseline,exact_random_corpus_d3/det_sign_exact,100,225.19214860435227,224.95952723753143,225.53019832176582,225.1066786864951,224.97792444242148,225.2094284413811,0.95 +baseline,exact_random_corpus_d3/solve_exact,100,214312.7598011514,214008.33207972205,214660.1467882057,214235.25767112512,213804.48615384614,214549.53333333333,0.95 +baseline,exact_random_corpus_d3/solve_exact_f64_result,100,232029.80876150593,231019.2898427248,233135.33816064312,229915.88374999998,229519.60784313726,230509.14096334187,0.95 +baseline,exact_random_corpus_d3/solve_exact_rounded_f64,100,218309.74327398872,217802.15816739644,218868.33167790246,217630.98739495798,217287.0088235294,217935.7142857143,0.95 +baseline,exact_random_corpus_d4/det_exact,100,25309.27764112511,25258.111929085055,25365.242103133623,25256.29744318182,25208.91449244164,25295.91224021084,0.95 +baseline,exact_random_corpus_d4/det_sign_exact,100,425.81791445239105,424.76187357423345,426.99363696194234,424.52204562697165,423.1255920750233,425.6456226052414,0.95 +baseline,exact_random_corpus_d4/solve_exact,100,489730.19514601893,489017.2487844846,490501.03053617605,489451.64080744656,488840.649122807,490288.25136612024,0.95 +baseline,exact_random_corpus_d4/solve_exact_f64_result,100,507806.00089630106,507154.51669837546,508502.3130812206,507754.3940476191,507048.99725274724,508511.2738095238,0.95 +baseline,exact_random_corpus_d4/solve_exact_rounded_f64,100,491685.63437782874,490631.8290109176,492859.56275443116,491513.0259150086,490452.2676056338,491979.98039215687,0.95 +baseline,exact_random_corpus_d5/det_exact,100,47495.06455948542,47379.382529470626,47611.557336582664,47405.791320311226,47335.99418767507,47504.00425170068,0.95 +baseline,exact_random_corpus_d5/det_sign_exact,100,50335.17733088678,49759.93092972215,50919.63003137287,49538.7764628257,48757.71261042879,50884.692642881215,0.95 +baseline,exact_random_corpus_d5/solve_exact,100,965121.3266125056,964056.0792050618,966178.1098548188,965824.6897901399,964445.0349893162,966729.1666666666,0.95 +baseline,exact_random_corpus_d5/solve_exact_f64_result,100,987963.6123347994,986411.0778234303,989676.7943537231,987575.638843795,986287.682748538,989217.705,0.95 +baseline,exact_random_corpus_d5/solve_exact_rounded_f64,100,969321.8416509356,967725.0133737603,971193.5350165456,966847.5522111162,965474.390625,968312.6141633064,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/faer_lu_solve,100,910.3880247594826,908.1092728703187,912.7323110695444,909.543275453828,907.4692420580111,912.8745818769497,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/faer_solve_from_lu,100,259.81167943885254,259.3197133334727,260.30687493915354,259.50949563582174,258.93154364128327,260.3203364646856,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/la_stack_lu_solve,100,660.7124081112684,656.9971411872828,664.553476798563,656.7384386226117,651.884334229283,664.671829678617,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/la_stack_solve_from_lu,100,187.29705071743635,186.73222117410594,187.9382118089668,186.91684515188078,186.45589089542295,187.3603088498084,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/nalgebra_lu_solve,100,621.1438480633965,609.8104375600001,632.9916172984169,582.7011442228539,580.1127224674999,588.2216730954677,0.95 +baseline,lu_solve_dense_ill_conditioned_d16/nalgebra_solve_from_lu,100,96.49710793229582,96.32011238315944,96.68862911385135,96.41990170522428,96.27672423156294,96.67676825603706,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/faer_lu_solve,100,179.3896429362463,178.74347958110997,180.05938160726652,178.71613424898712,177.9453820291384,179.5942619928467,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/faer_solve_from_lu,100,55.11616279431234,54.96115681609079,55.30846240037924,55.02177430068956,54.92939782210438,55.117423342745965,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/la_stack_lu_solve,100,2.0637261731204863,2.0572929812153373,2.070981791488363,2.050515959100182,2.0490653113887665,2.0518361675652366,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/la_stack_solve_from_lu,100,1.3748730007684764,1.3693940378801106,1.3804288676379206,1.3827490835870204,1.3759626288908695,1.3846024904875296,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/nalgebra_lu_solve,100,4.646245277817839,4.633342839650979,4.661181948877046,4.63670528810246,4.625867682947854,4.640369774282793,0.95 +baseline,lu_solve_dense_ill_conditioned_d2/nalgebra_solve_from_lu,100,3.0190930017556767,3.0045421915418955,3.0338259215099757,3.024785485207922,3.011816279621973,3.0366680247803512,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/faer_lu_solve,100,214.6805406369559,213.92534265560172,215.46428111592402,213.86203226129015,212.96646017699115,214.83994857689547,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/faer_solve_from_lu,100,56.08174268547257,55.933029742432254,56.23874253146848,55.76406115896785,55.67033563511109,56.08259260166185,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/la_stack_lu_solve,100,10.93291464536585,10.904648579894104,10.9633366984143,10.92099475404558,10.89108393757977,10.942053330801423,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/la_stack_solve_from_lu,100,2.725769744396985,2.716202925248374,2.7359208147986767,2.7291748056933205,2.7157140285695847,2.734371774084769,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/nalgebra_lu_solve,100,23.82827780252514,23.755227771190338,23.90329362805316,23.72223123660823,23.685822782803097,23.7945220295894,0.95 +baseline,lu_solve_dense_ill_conditioned_d3/nalgebra_solve_from_lu,100,4.969944212403317,4.955340405842598,4.98536114598672,4.963374340645359,4.954273325387706,4.969605261409244,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/faer_lu_solve,100,2907.556739288617,2902.253086735735,2913.0029849287826,2901.5163652426554,2896.125122189638,2906.209490802453,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/faer_solve_from_lu,100,635.3294631521624,633.8444270649553,637.0181298965693,633.868099715884,632.4460240587408,634.7267508159333,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/la_stack_lu_solve,100,2918.612343638353,2895.477129038106,2949.418816067649,2923.247423579649,2897.23063583815,2934.3019245927485,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/la_stack_solve_from_lu,100,785.071345696604,781.8314590361371,788.4161242653875,786.9890450919554,784.8057356924573,788.3419777279694,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/nalgebra_lu_solve,100,2681.4394174867407,2668.8211262764935,2693.7036251265636,2708.994105373793,2705.6087035771247,2713.227695721207,0.95 +baseline,lu_solve_dense_ill_conditioned_d32/nalgebra_solve_from_lu,100,331.6656295082988,330.6244165212295,332.850823038259,330.441700026966,329.9150168541993,330.79498022276186,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/faer_lu_solve,100,242.2684011788202,241.56302003120888,242.99766636535142,241.65825092775714,240.76684943399727,242.55752667861861,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/faer_solve_from_lu,100,58.7596062783434,58.53872391269945,58.975711676239,59.035660598269786,58.716332867674964,59.256050194203766,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/la_stack_lu_solve,100,22.96049013897266,22.905944361933688,23.015715714363942,22.98960304134259,22.957563064105532,23.02527252119939,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/la_stack_solve_from_lu,100,4.824726870640919,4.805982049011688,4.843331948870181,4.8523973224980415,4.830617888576342,4.874044247615718,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/nalgebra_lu_solve,100,50.41616899082062,50.26297981138376,50.59271527793691,50.23718226827276,50.129744945026694,50.39310007246756,0.95 +baseline,lu_solve_dense_ill_conditioned_d4/nalgebra_solve_from_lu,100,5.977434288180729,5.958095022663444,5.996984156109035,5.959425704344433,5.9392558004120755,5.990728528540944,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/faer_lu_solve,100,326.85860131704686,322.24130999820517,331.4926575241756,330.016704401968,306.7736161822242,344.7218001874716,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/faer_solve_from_lu,100,89.1241418258569,88.85273430115149,89.40489774484297,89.21041666065071,88.96586556355979,89.45500943357924,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/la_stack_lu_solve,100,45.901629344200394,45.833435218955955,45.975207108126135,45.8123560921872,45.75530206644354,45.83123474071355,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/la_stack_solve_from_lu,100,7.311879771608091,7.301141439591337,7.3233400792915395,7.322349855347062,7.302751195291032,7.330715341102313,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/nalgebra_lu_solve,100,69.89869841912629,69.76037196296281,70.04313641538735,69.90916740682711,69.78935308051581,70.04514021733544,0.95 +baseline,lu_solve_dense_ill_conditioned_d5/nalgebra_solve_from_lu,100,10.670913151786857,10.411221404182736,11.003765195641162,10.255598017292574,10.24079167009834,10.286396260833708,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/faer_lu_solve,100,12098.082149330503,12075.062525005755,12121.384097519955,12086.118504772003,12066.94277673546,12106.179643527204,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/faer_solve_from_lu,100,1661.5021667929648,1658.6741722475228,1664.5162287923695,1663.4978310243016,1660.049656226127,1665.4492484993998,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/la_stack_lu_solve,100,17183.546476191943,17147.18573530701,17222.027329224366,17140.615198967902,17116.19702665755,17175.106165377176,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/la_stack_solve_from_lu,100,2529.430400478899,2513.3367003939143,2547.5015244499446,2504.419695609785,2494.540802764487,2512.2033068783066,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/nalgebra_lu_solve,100,14191.323722564424,14157.043710149215,14227.274638427622,14160.87336269196,14149.36247723133,14179.141865079366,0.95 +baseline,lu_solve_dense_ill_conditioned_d64/nalgebra_solve_from_lu,100,795.6740171140851,794.8597490678757,796.5666873305099,795.9829119165936,795.290719087986,796.7537269804151,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/faer_lu_solve,100,392.7935014347922,391.90086637373656,393.7043861649589,392.7346322166675,391.27696584590944,393.64973854911307,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/faer_solve_from_lu,100,100.09022360791192,99.73688289332486,100.45496331111255,99.45650952276816,99.27014169627179,100.0040684973288,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/la_stack_lu_solve,100,128.58312669823593,128.34014154177305,128.8420147150464,128.69123535169115,128.2897504501321,128.85303261007488,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/la_stack_solve_from_lu,100,14.389865193327305,14.126733147296601,14.877250889001985,14.109087632273138,14.080070276666838,14.13810753052848,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/nalgebra_lu_solve,100,170.1599737962724,169.3372302094068,171.0478792072627,169.1365040564357,168.51000979648592,170.0512419416003,0.95 +baseline,lu_solve_dense_ill_conditioned_d8/nalgebra_solve_from_lu,100,17.84373665540478,17.751781076046885,17.93828110849332,17.600769312118658,17.520899116625753,17.810439144150685,0.95 +baseline,lu_solve_pivoting_d16/faer_lu_solve,100,1216.237212374114,1211.5147627398178,1221.0176130905743,1219.6490991370256,1212.4035782496348,1224.933916689454,0.95 +baseline,lu_solve_pivoting_d16/faer_solve_from_lu,100,267.639188687269,263.9265293510672,271.7397398587844,260.22638284384107,259.568188782024,261.47418104323117,0.95 +baseline,lu_solve_pivoting_d16/la_stack_lu_solve,100,774.1889207457948,772.4972799181776,776.025649363314,774.1355439317131,773.069579865017,775.7331726090418,0.95 +baseline,lu_solve_pivoting_d16/la_stack_solve_from_lu,100,189.24516069254034,188.41294560355334,190.18661049112066,188.15516111934286,187.5826299495634,188.71131344759394,0.95 +baseline,lu_solve_pivoting_d16/nalgebra_lu_solve,100,725.8254389098213,713.0771038734791,739.1811996974781,683.4520272466791,679.7146494320407,689.9953899698654,0.95 +baseline,lu_solve_pivoting_d16/nalgebra_solve_from_lu,100,120.79668378409458,120.49596005725633,121.09638692350248,120.97148473698076,120.68203383361522,121.18355477379569,0.95 +baseline,lu_solve_pivoting_d2/faer_lu_solve,100,195.6193658920761,194.95690571992517,196.31350513719747,195.43238076277495,194.7642818223731,195.9550671002953,0.95 +baseline,lu_solve_pivoting_d2/faer_solve_from_lu,100,65.00140302525116,64.39653078962033,65.5513996954055,65.88928931451613,65.06284318666982,66.37840140999793,0.95 +baseline,lu_solve_pivoting_d2/la_stack_lu_solve,100,2.099388470442919,2.086739157756866,2.112840885731645,2.0548082856555707,2.051609900597233,2.094765785394059,0.95 +baseline,lu_solve_pivoting_d2/la_stack_solve_from_lu,100,1.3766702432874245,1.3715572639924873,1.3818104288659645,1.3835430179020167,1.3826626409040754,1.385357306831989,0.95 +baseline,lu_solve_pivoting_d2/nalgebra_lu_solve,100,10.949029836688732,10.844051322709936,11.045555052279695,10.955322403301475,10.927889174260686,10.983689621924627,0.95 +baseline,lu_solve_pivoting_d2/nalgebra_solve_from_lu,100,10.322808518317716,10.170220665730108,10.475724784778931,10.50874097392921,10.264048507194504,10.630435904106925,0.95 +baseline,lu_solve_pivoting_d3/faer_lu_solve,100,253.07117817074348,252.3566851579437,253.80888198209564,252.49821434656073,252.2490346226266,252.98136520264725,0.95 +baseline,lu_solve_pivoting_d3/faer_solve_from_lu,100,64.57199568127636,63.67726762865116,65.43217851698387,65.27928915888675,64.5054500009029,67.08037909800976,0.95 +baseline,lu_solve_pivoting_d3/la_stack_lu_solve,100,23.37418922318903,23.242186488084414,23.511919601719192,23.391958759733086,23.260019081866936,23.51515718985635,0.95 +baseline,lu_solve_pivoting_d3/la_stack_solve_from_lu,100,2.7269582516476727,2.7189206554329015,2.735443103422878,2.7338291253743625,2.726445299455972,2.7363134288536033,0.95 +baseline,lu_solve_pivoting_d3/nalgebra_lu_solve,100,32.298806210431515,32.17642304949638,32.42180087454743,32.31085463350519,32.17628005335371,32.382143563953015,0.95 +baseline,lu_solve_pivoting_d3/nalgebra_solve_from_lu,100,14.183854674096283,14.136628165018188,14.236587211139947,14.20449546695276,14.154678023899631,14.258136048065865,0.95 +baseline,lu_solve_pivoting_d32/faer_lu_solve,100,3722.1411079919963,3716.461084124975,3728.0505066699066,3719.623295367388,3715.441188057226,3723.572779432859,0.95 +baseline,lu_solve_pivoting_d32/faer_solve_from_lu,100,634.6326729212843,633.0916936172872,636.303016977138,633.2843251253335,631.509211131887,634.8774934016402,0.95 +baseline,lu_solve_pivoting_d32/la_stack_lu_solve,100,3122.7747885161366,3118.1020125662762,3127.6585518096763,3120.624906113865,3117.4266104449976,3125.5587539432177,0.95 +baseline,lu_solve_pivoting_d32/la_stack_solve_from_lu,100,766.3260791236607,763.7646812738411,768.9708799263963,767.7074459083074,765.197991564035,771.1026152630404,0.95 +baseline,lu_solve_pivoting_d32/nalgebra_lu_solve,100,3124.9016131079306,3106.616990443578,3142.317451349245,3175.832099783527,3162.9827726809376,3181.818741269302,0.95 +baseline,lu_solve_pivoting_d32/nalgebra_solve_from_lu,100,352.56820668658713,351.43155381790234,353.82873892146404,350.9783527119668,350.4478624829875,351.4492082560511,0.95 +baseline,lu_solve_pivoting_d4/faer_lu_solve,100,298.5944710908557,297.28339650860346,299.95228790007485,297.57039725035054,295.53686594169017,298.8730639070621,0.95 +baseline,lu_solve_pivoting_d4/faer_solve_from_lu,100,65.85640556874938,64.9421098976835,66.75362297046651,67.0037682896097,66.0582265652766,68.2585316001108,0.95 +baseline,lu_solve_pivoting_d4/la_stack_lu_solve,100,38.815086331872095,38.70140342074268,38.94218956148151,38.789042798189314,38.696213734580795,38.84742854914805,0.95 +baseline,lu_solve_pivoting_d4/la_stack_solve_from_lu,100,4.7974956519415874,4.779121251216055,4.8160560400039785,4.820172261402094,4.7865284477206815,4.854427588531521,0.95 +baseline,lu_solve_pivoting_d4/nalgebra_lu_solve,100,53.78782142968442,53.63623510256206,53.93915991611398,53.7393816874949,53.48485377433114,54.141467611939305,0.95 +baseline,lu_solve_pivoting_d4/nalgebra_solve_from_lu,100,19.376875090814437,19.26193044850192,19.510036386593114,19.230755781445136,19.13872260506739,19.298437520106642,0.95 +baseline,lu_solve_pivoting_d5/faer_lu_solve,100,379.1731061257418,378.2048634989124,380.15218933546294,379.4937478698023,378.71251601159577,380.35391572191463,0.95 +baseline,lu_solve_pivoting_d5/faer_solve_from_lu,100,93.25529648859622,92.79476354702803,93.71525244984193,93.05927521980564,92.82238742285017,93.76845767563029,0.95 +baseline,lu_solve_pivoting_d5/la_stack_lu_solve,100,82.83016788947613,82.55651699862455,83.12618104906154,82.56255814519149,82.34306503557008,82.80840084377265,0.95 +baseline,lu_solve_pivoting_d5/la_stack_solve_from_lu,100,7.301021071401738,7.283122242243988,7.320257443695598,7.300327387080642,7.283211178310214,7.312533613517475,0.95 +baseline,lu_solve_pivoting_d5/nalgebra_lu_solve,100,84.74100571583898,84.48885377650944,85.01219710962361,84.44871562952244,84.28874545476657,84.77006768049162,0.95 +baseline,lu_solve_pivoting_d5/nalgebra_solve_from_lu,100,23.516699834264706,23.437498814853846,23.601289713393328,23.49733027512618,23.415964940987084,23.550120174450704,0.95 +baseline,lu_solve_pivoting_d64/faer_lu_solve,100,14376.563411864143,14357.080541580264,14397.436822576678,14371.405386904762,14356.141114982578,14398.580690737834,0.95 +baseline,lu_solve_pivoting_d64/faer_solve_from_lu,100,1662.8157853204364,1660.2642750826292,1665.4127459508436,1663.9818613451378,1661.4203384884738,1666.6880818358952,0.95 +baseline,lu_solve_pivoting_d64/la_stack_lu_solve,100,18644.962043499705,18577.06090259773,18719.615527463455,18543.513079108394,18486.023125608568,18601.315428983416,0.95 +baseline,lu_solve_pivoting_d64/la_stack_solve_from_lu,100,2512.393242052932,2498.094985144268,2528.7993919437054,2484.398474671145,2480.3676055868755,2493.213476070529,0.95 +baseline,lu_solve_pivoting_d64/nalgebra_lu_solve,100,16471.042905738057,16454.915397221157,16487.891423284567,16469.69269949066,16459.380137089258,16484.93052109181,0.95 +baseline,lu_solve_pivoting_d64/nalgebra_solve_from_lu,100,840.814059103292,839.5529966969531,842.4336066398024,840.7508177222718,840.0264329738059,840.9919455386506,0.95 +baseline,lu_solve_pivoting_d8/faer_lu_solve,100,514.3337682145633,512.8383044550104,515.9129923705806,512.9483966924398,512.016643639069,513.5301116838489,0.95 +baseline,lu_solve_pivoting_d8/faer_solve_from_lu,100,99.78704509782379,99.51787276829079,100.06225030178392,99.77987785278046,99.33912965722801,100.02949955327004,0.95 +baseline,lu_solve_pivoting_d8/la_stack_lu_solve,100,200.93423463991476,199.96526736652038,201.91256348792456,198.88364133795952,197.87932350793335,200.228940415771,0.95 +baseline,lu_solve_pivoting_d8/la_stack_solve_from_lu,100,14.040048537498793,14.018027296327864,14.06123671669754,14.051401061238948,14.03692110832226,14.067977073176376,0.95 +baseline,lu_solve_pivoting_d8/nalgebra_lu_solve,100,200.46459529547198,199.80545982037097,201.13602668589928,199.36695519322637,198.97069948360271,199.90094269370584,0.95 +baseline,lu_solve_pivoting_d8/nalgebra_solve_from_lu,100,35.47029873322475,35.36366486950787,35.58237674680099,35.40523373332681,35.29766977949914,35.516250502424406,0.95 +current,canonical_conversion_below_overflow_d2/rounded_result,100,219.6041918046675,219.2232199458668,219.98852926567295,219.55789537565238,218.98613355819455,220.12049399198932,0.95 +current,canonical_conversion_below_overflow_d2/strict_result,100,222.61883925100636,221.67434962264124,223.69593957667635,221.73920358928063,221.0172171617216,222.79878134840635,0.95 +current,canonical_conversion_below_overflow_d3/rounded_result,100,228.6063048497852,227.58616373117368,229.85779546735003,227.88967442262935,227.32090414356662,228.36527813818816,0.95 +current,canonical_conversion_below_overflow_d3/strict_result,100,226.95296225740194,226.18543640160715,227.72956917903943,227.0127455090581,226.59827385242681,227.76622368638363,0.95 +current,canonical_conversion_below_overflow_d4/rounded_result,100,235.6319063369018,234.98771736501027,236.27799254980152,235.59340175039398,235.19310035842295,236.1191624499262,0.95 +current,canonical_conversion_below_overflow_d4/strict_result,100,233.17703049352153,232.5835048666459,233.77588313971071,233.21009247761756,232.19291019415488,233.76230149306616,0.95 +current,canonical_conversion_below_overflow_d5/rounded_result,100,258.07063005689315,248.02906656956281,272.5437040387557,249.0108334610864,245.9613262144734,251.4616721263979,0.95 +current,canonical_conversion_below_overflow_d5/strict_result,100,235.64184133399402,234.74237985966064,236.68202905725116,235.34060941566747,234.13949453095097,235.9604517184481,0.95 +current,canonical_conversion_dyadic_d2/rounded_result,100,11.775860682907991,11.75946420213827,11.798521779467967,11.748880763605339,11.745430469217428,11.758149126196766,0.95 +current,canonical_conversion_dyadic_d2/strict_result,100,8.249219101832528,8.208563786027087,8.28919255930911,8.284240603227365,8.214477367437423,8.35424227574003,0.95 +current,canonical_conversion_dyadic_d3/rounded_result,100,17.72673491835302,17.71639224040246,17.737597805649756,17.72276269865357,17.71211920133907,17.73712265888557,0.95 +current,canonical_conversion_dyadic_d3/strict_result,100,11.975518294494913,11.912363004148716,12.041039209106614,11.896661838824361,11.816092402349064,11.97108648668651,0.95 +current,canonical_conversion_dyadic_d4/rounded_result,100,23.44257349411081,23.404133171264355,23.49399025378867,23.387414446575118,23.37852966726206,23.396248150759593,0.95 +current,canonical_conversion_dyadic_d4/strict_result,100,15.948850200146644,15.819707459324203,16.076119130239373,16.12011471716906,15.815574899464647,16.367881348704795,0.95 +current,canonical_conversion_dyadic_d5/rounded_result,100,28.364191378321483,28.34574564133947,28.38930983094225,28.345627806014882,28.337477849305706,28.35369190619547,0.95 +current,canonical_conversion_dyadic_d5/strict_result,100,19.886360862597734,19.727181230550595,20.044539014895978,19.596524553775794,19.396642446784124,20.584038426754024,0.95 +current,canonical_conversion_min_subnormal_d2/rounded_result,100,230.68568550168092,228.9684805080863,232.90705281082006,227.8893498886072,227.23940740548383,229.03798823516502,0.95 +current,canonical_conversion_min_subnormal_d2/strict_result,100,12.608521098969357,12.530692354982197,12.689035094265629,12.598095938539283,12.528698789567006,12.684855535570778,0.95 +current,canonical_conversion_min_subnormal_d3/rounded_result,100,237.9159782172544,237.52536699753634,238.30674519609508,237.69165256286266,237.36427378231053,238.37924976310495,0.95 +current,canonical_conversion_min_subnormal_d3/strict_result,100,17.373463805583082,17.239544499226188,17.508090556358436,17.421601042611744,17.299129526256813,17.580500329558006,0.95 +current,canonical_conversion_min_subnormal_d4/rounded_result,100,254.87907693450288,248.1389318205514,264.58225148088724,243.71103739680723,243.23765364162801,248.4726522587553,0.95 +current,canonical_conversion_min_subnormal_d4/strict_result,100,21.53924201336105,21.37383562054632,21.707511865519272,21.43802492066749,21.179723669403035,21.714160875833606,0.95 +current,canonical_conversion_min_subnormal_d5/rounded_result,100,248.07169296085416,247.50556266490273,248.6492879750953,248.14816278535773,247.45074152978046,248.730817294493,0.95 +current,canonical_conversion_min_subnormal_d5/strict_result,100,25.767745495828564,25.582346162782706,25.95730107690061,25.706951722004316,25.448710165849256,25.966965660210185,0.95 +current,canonical_conversion_negative_underflow_d2/rounded_result,100,228.31260677742532,227.88138275615876,228.75486379690577,227.91322399246275,227.66632999781788,228.56192810457517,0.95 +current,canonical_conversion_negative_underflow_d2/strict_result,100,12.686272398966446,12.617949629111333,12.756761607452367,12.633146737114128,12.556784338890033,12.706325104559141,0.95 +current,canonical_conversion_negative_underflow_d3/rounded_result,100,234.4865061436256,234.04417640966355,234.94939086084693,234.28179434410748,234.02543862994963,234.58048553857844,0.95 +current,canonical_conversion_negative_underflow_d3/strict_result,100,17.41070227928069,17.345450823231992,17.478112499234037,17.3749973971973,17.305866892353407,17.44388838968468,0.95 +current,canonical_conversion_negative_underflow_d4/rounded_result,100,245.1949153772863,243.91525429110587,246.5518959242676,243.42287398794116,242.8272543170483,244.23721990832306,0.95 +current,canonical_conversion_negative_underflow_d4/strict_result,100,20.53275353156555,20.416264049924727,20.658824338859276,20.491278051624157,20.400085846849667,20.5893291586452,0.95 +current,canonical_conversion_negative_underflow_d5/rounded_result,100,246.72536141626685,246.2694201654212,247.21005827784236,246.30677905944987,245.95111737537826,246.7493795093795,0.95 +current,canonical_conversion_negative_underflow_d5/strict_result,100,24.88890044600164,24.72585342374502,25.053943431672934,24.87694771501036,24.638660703075956,25.223441618017887,0.95 +current,canonical_conversion_non_dyadic_d2/rounded_result,100,11.824860684015544,11.8027791334158,11.849726725594559,11.784922044395461,11.779831935324896,11.798258163581723,0.95 +current,canonical_conversion_non_dyadic_d2/strict_result,100,11.831485639053572,11.809473976157083,11.855085290118131,11.79645238104057,11.776180119904941,11.81716964253766,0.95 +current,canonical_conversion_non_dyadic_d3/rounded_result,100,18.002333207925872,17.937544704059206,18.073273670869593,17.843229744133566,17.828065436368686,17.873363202615614,0.95 +current,canonical_conversion_non_dyadic_d3/strict_result,100,15.895920249139634,15.852711370090185,15.94100298384271,15.905841063032963,15.884283479365,15.943999651349394,0.95 +current,canonical_conversion_non_dyadic_d4/rounded_result,100,23.542849442306462,23.495753188182782,23.59693392051146,23.447326480125696,23.436605631055336,23.46594526627219,0.95 +current,canonical_conversion_non_dyadic_d4/strict_result,100,19.531297500098148,19.45423445061707,19.607292494857916,19.59382740690873,19.499558297583903,19.669887304063828,0.95 +current,canonical_conversion_non_dyadic_d5/rounded_result,100,28.455621072209905,28.405863378391544,28.533680922128454,28.401804436651688,28.38620733104981,28.410607782047304,0.95 +current,canonical_conversion_non_dyadic_d5/strict_result,100,23.293739525335024,23.199007953772877,23.38646731502139,23.471838120045856,23.1547700558207,23.582878483811076,0.95 +current,canonical_conversion_overflow_midpoint_d2/rounded_result,100,221.90120786392237,221.52063000221364,222.28699754344285,221.8675261628613,221.43014513842252,222.27190653267996,0.95 +current,canonical_conversion_overflow_midpoint_d2/strict_result,100,228.3381015057913,227.9141638239115,228.77705736369893,228.30790462421123,227.71008963456677,228.6877729257642,0.95 +current,canonical_conversion_overflow_midpoint_d3/rounded_result,100,227.97286339312126,227.26208486760294,228.72748489561513,227.43046360996004,226.66312646645497,228.6010689905287,0.95 +current,canonical_conversion_overflow_midpoint_d3/strict_result,100,232.59448067842675,232.06484072071953,233.13219141150375,232.45109460835937,231.75831613174287,233.3251829401151,0.95 +current,canonical_conversion_overflow_midpoint_d4/rounded_result,100,235.83554385720205,235.00591959347042,236.67575132642838,236.0234659026935,235.03823660591846,236.99833610648918,0.95 +current,canonical_conversion_overflow_midpoint_d4/strict_result,100,241.42060884859077,240.35233012459875,242.53959195387102,240.3430714638752,239.39462613843997,241.7035259459122,0.95 +current,canonical_conversion_overflow_midpoint_d5/rounded_result,100,240.1561494756009,239.48438010219675,240.8247049235622,240.30531786683844,239.51804113614105,241.51586985798235,0.95 +current,canonical_conversion_overflow_midpoint_d5/strict_result,100,243.46188275991062,242.71943100263184,244.24094031501681,243.0988253246972,242.55181667716172,243.63646068826927,0.95 +current,canonical_conversion_wide1024_d2/rounded_result,100,266.70865111372893,266.175791991245,267.273747096772,266.30017877766244,266.0377174447724,266.68727241366093,0.95 +current,canonical_conversion_wide1024_d2/strict_result,100,266.69370165720755,266.3282114003358,267.06902859948275,266.5256573694919,266.1841129324122,267.18565791318633,0.95 +current,canonical_conversion_wide1024_d3/rounded_result,100,279.5774496694729,278.7297377334431,280.4488533740771,279.53193734633413,278.81248234961873,280.01256873266107,0.95 +current,canonical_conversion_wide1024_d3/strict_result,100,278.58318512518053,277.0645394666541,280.45935193548326,278.169138739037,276.9206538595225,278.8431785840545,0.95 +current,canonical_conversion_wide1024_d4/rounded_result,100,280.443138947643,279.8953592210943,281.0595896117601,280.07419121515966,279.2802974147792,280.5829888551165,0.95 +current,canonical_conversion_wide1024_d4/strict_result,100,275.92644367284066,275.1394112079409,276.7313441469127,276.51924240598686,275.3764095836067,277.0867499635235,0.95 +current,canonical_conversion_wide1024_d5/rounded_result,100,290.95666596344273,289.2099056269494,292.87430466870006,288.12686904066936,287.48525977816695,289.94571712834806,0.95 +current,canonical_conversion_wide1024_d5/strict_result,100,287.9222859700385,285.3123495733652,290.72626932082454,283.191100315993,281.5334785988788,284.2061217020993,0.95 +current,canonical_conversion_wide256_d2/rounded_result,100,253.00752785784482,251.73825555647875,254.41681566975484,252.12362981094986,251.23428261823062,252.9697735892426,0.95 +current,canonical_conversion_wide256_d2/strict_result,100,252.39167182990954,251.67765095911625,253.1190602001321,252.51306815968843,251.39620253164557,253.271001150748,0.95 +current,canonical_conversion_wide256_d3/rounded_result,100,253.2983390063813,252.61187604889028,254.0368359725676,252.80782409730742,252.01798278509946,253.67055325792683,0.95 +current,canonical_conversion_wide256_d3/strict_result,100,254.24582805238438,253.04487001820834,255.5737393176873,253.09436627465772,252.20677024920306,253.8444003811509,0.95 +current,canonical_conversion_wide256_d4/rounded_result,100,263.5091253594286,262.28271884570455,264.79953772513596,262.8599101504759,260.98851059344366,264.87398789912754,0.95 +current,canonical_conversion_wide256_d4/strict_result,100,255.33725030942557,254.6222156790141,256.07522145054446,254.95434783517481,254.10691876752804,256.26837568393734,0.95 +current,canonical_conversion_wide256_d5/rounded_result,100,271.44338665860255,270.12848035180446,272.9150905356008,271.2024198482251,270.2726254419364,272.37357482061043,0.95 +current,canonical_conversion_wide256_d5/strict_result,100,265.44091122806464,264.63183173586043,266.2334626829588,265.581163063525,264.0056104728827,266.34861634190275,0.95 +current,d16/la_stack_det,100,469.5871526448627,464.15785856119146,475.1091951798135,463.80296127265103,460.3960326176341,472.33012103603517,0.95 +current,d16/la_stack_det_from_ldlt,100,2.8755783105066737,2.871480516850472,2.8794434875172157,2.877754259290871,2.871006422967889,2.8807725628498964,0.95 +current,d16/la_stack_det_from_lu,100,3.281855953459262,3.276872533329061,3.2871823267312057,3.2844233910509777,3.2802626051210346,3.2871763604294144,0.95 +current,d16/la_stack_det_via_lu,100,406.50860883724323,405.63185590150164,407.43369690911356,405.19400426939444,403.78158014582004,406.94594977973304,0.95 +current,d16/la_stack_dot,100,2.3445919740216485,2.339155465970549,2.3505961746195174,2.3393023607778165,2.3353744484042807,2.3411556649656324,0.95 +current,d16/la_stack_inf_norm,100,32.124707889157136,32.058747782511276,32.19601353839705,32.16643008528123,32.10596293058447,32.20513628453468,0.95 +current,d16/la_stack_ldlt,100,405.3708935425617,404.3564908620939,406.5529371897525,403.795192343709,403.4035573047982,404.47298172993465,0.95 +current,d16/la_stack_ldlt_solve,100,448.6316220738692,447.60600169849886,449.74396839560836,447.59429870422946,446.33635357254593,448.10668388068535,0.95 +current,d16/la_stack_lu,100,397.2652511573521,396.1238556889343,398.4665123186324,395.5655026513118,394.39822642691,397.09790485192184,0.95 +current,d16/la_stack_lu_solve,100,647.2768820255613,645.0620006706728,649.6906284666746,643.5320021938804,641.4668189353472,644.9028128940731,0.95 +current,d16/la_stack_norm2,100,10.074821045282292,10.015533568222432,10.137296889186374,10.085580976521914,9.881800967630472,10.181846832231617,0.95 +current,d16/la_stack_norm2_scenario_descending,100,9.373223532281786,9.337621790261323,9.4140790251993,9.352561908973325,9.318583959781849,9.375331730972174,0.95 +current,d16/la_stack_norm2_scenario_repeated_scale,100,9.371307112357737,9.334110523675058,9.410258617625612,9.34738964858287,9.31550461970904,9.388228561183272,0.95 +current,d16/la_stack_norm2_scenario_sparse,100,4.695870509831993,4.6321672130617735,4.759425337469813,4.8857883994576685,4.514444368740206,4.97196944667051,0.95 +current,d16/la_stack_norm2_scenario_wide_dynamic_range,100,8.155216212044936,8.12834837453266,8.185027491062618,8.13159059910919,8.112383487863063,8.157612982585157,0.95 +current,d16/la_stack_norm2_sq,100,2.0622460664705677,2.0581277135499834,2.066277328036344,2.0639409227602474,2.0589625074537787,2.068890035783829,0.95 +current,d16/la_stack_solve_from_ldlt,100,27.712083273395606,27.690910326062248,27.735048192227683,27.715558726917436,27.697078439756556,27.727102224379838,0.95 +current,d16/la_stack_solve_from_lu,100,188.8753786540353,188.44120941175385,189.3254880845008,188.7725182762601,188.33652062599413,189.38605435288875,0.95 +current,d2/la_stack_det,100,0.5756183521605707,0.5746936971600127,0.5767009188145265,0.5741482940686722,0.5740140431795733,0.5743363087103232,0.95 +current,d2/la_stack_det_from_ldlt,100,0.5027864176666338,0.49998037080036417,0.5058611531250365,0.49616588060011557,0.4960249936577053,0.4962737893509107,0.95 +current,d2/la_stack_det_from_lu,100,0.5206977243239892,0.5204522998312283,0.5210901340858354,0.5204295737651622,0.5203664220100013,0.5205197765554463,0.95 +current,d2/la_stack_det_via_lu,100,1.770190303000009,1.7642901120292764,1.7760164350528584,1.7737368324374865,1.7713974906331558,1.7775340107838542,0.95 +current,d2/la_stack_dot,100,0.605875048281926,0.6029082005744474,0.6087989881102597,0.6125121487874756,0.611217777691145,0.613135247887534,0.95 +current,d2/la_stack_inf_norm,100,0.6242239040694547,0.6232226656909707,0.6254749284344953,0.6228225249289318,0.6225078963597978,0.6232695321530408,0.95 +current,d2/la_stack_ldlt,100,6.651340746887415,6.6151042906018835,6.689224602386477,6.634632669927852,6.611228322482762,6.649096105104241,0.95 +current,d2/la_stack_ldlt_solve,100,9.480404775129863,9.436878673106214,9.534810693894986,9.434206567116622,9.417631882276098,9.464483593035887,0.95 +current,d2/la_stack_lu,100,1.5546319693922017,1.5535647246299953,1.5556516223721206,1.555032806939535,1.5541639439771986,1.5557607183929154,0.95 +current,d2/la_stack_lu_solve,100,2.0654067373562306,2.0522982153792837,2.0792981569431435,2.0211314276372025,2.018479942281156,2.0445438481191816,0.95 +current,d2/la_stack_norm2,100,1.190882506267541,1.1835907517993525,1.198229230508108,1.2027430445218819,1.171992508138802,1.2163330958829988,0.95 +current,d2/la_stack_norm2_scenario_descending,100,1.3401319025058056,1.336332126726681,1.344273376391739,1.3368976213260773,1.3335375140252987,1.3397730742932756,0.95 +current,d2/la_stack_norm2_scenario_repeated_scale,100,1.335890377742934,1.3316932133528179,1.3404283767358938,1.3351579288556978,1.3327431380656685,1.3379837110068196,0.95 +current,d2/la_stack_norm2_scenario_sparse,100,1.1703090020566862,1.1648882529689464,1.1759238371547729,1.159969296207054,1.156315959823193,1.162363839272694,0.95 +current,d2/la_stack_norm2_scenario_wide_dynamic_range,100,1.343452400985219,1.3396768107019483,1.3476373088262192,1.341809540054549,1.3375394406984786,1.3442648549785015,0.95 +current,d2/la_stack_norm2_sq,100,0.3934279092494954,0.3927929735190348,0.39404644793603094,0.39496812928467495,0.3943605968682597,0.3951709797409994,0.95 +current,d2/la_stack_solve_from_ldlt,100,1.2245440353935804,1.2151369214034358,1.2345316737997223,1.2384772206664705,1.2373876587522723,1.238701497962425,0.95 +current,d2/la_stack_solve_from_lu,100,1.2528935016998404,1.248704331260613,1.2577830362473603,1.244713993068986,1.2424024222304724,1.2477969796655017,0.95 +current,d3/la_stack_det,100,1.3245355707242066,1.3219712466881217,1.327464468528216,1.3219835208630162,1.3187665729784837,1.3242570292917186,0.95 +current,d3/la_stack_det_from_ldlt,100,0.5972830729314077,0.5960721839182488,0.5987349817884089,0.5949699712555623,0.5948021975187033,0.5951497566776942,0.95 +current,d3/la_stack_det_from_lu,100,0.6946135578712955,0.6940409732476729,0.6953270864196018,0.6938382932649928,0.6937154341229996,0.6940122258871739,0.95 +current,d3/la_stack_det_via_lu,100,8.913009247820732,8.720291594879063,9.290094650890827,8.733076033902261,8.716449031247826,8.751958150713982,0.95 +current,d3/la_stack_dot,100,0.666988901980296,0.6658001140871104,0.6684269231278213,0.6652945334987677,0.6647111666949368,0.6659491748002594,0.95 +current,d3/la_stack_inf_norm,100,1.3046654787829948,1.3025925489737378,1.3072377847912933,1.3022204280027463,1.3019503775557604,1.3025409334706468,0.95 +current,d3/la_stack_ldlt,100,13.663997185824833,13.597103115117564,13.738449847396998,13.578777245617996,13.518208039128293,13.660511854186652,0.95 +current,d3/la_stack_ldlt_solve,100,17.05098216089634,16.253868166858364,17.821355116220165,18.27160621414104,17.80685111570045,20.33914360837819,0.95 +current,d3/la_stack_lu,100,16.946944600700878,15.529875997885206,18.372102532413162,17.72001734341115,16.71937512810837,18.448514051541753,0.95 +current,d3/la_stack_lu_solve,100,9.971282112325017,9.932869379554209,10.011823477505681,9.976848651948877,9.898381116607712,10.025906395438968,0.95 +current,d3/la_stack_norm2,100,1.9136180526154822,1.8611465196122294,1.968298273302822,1.760797365183992,1.7161871421500636,1.836073726950029,0.95 +current,d3/la_stack_norm2_scenario_descending,100,1.8155087597781,1.8118034150325861,1.8195794202972835,1.8152689690782942,1.810372853210235,1.8202093504324828,0.95 +current,d3/la_stack_norm2_scenario_repeated_scale,100,1.8156101436555574,1.8115292519425106,1.820316369430406,1.8134298217010243,1.810550659815571,1.8157603032600707,0.95 +current,d3/la_stack_norm2_scenario_sparse,100,1.4228944516364113,1.4127330976165946,1.4329714027765108,1.449952614304035,1.3888715835827745,1.4591047525781982,0.95 +current,d3/la_stack_norm2_scenario_wide_dynamic_range,100,1.8368800000515524,1.8279355138078361,1.8465978045168472,1.8286160942188565,1.8226330081109674,1.8326320951723232,0.95 +current,d3/la_stack_norm2_sq,100,0.4463034091851394,0.4451080079995303,0.4477980930916009,0.4449210942501701,0.44446960832512455,0.44534723732947157,0.95 +current,d3/la_stack_solve_from_ldlt,100,1.7814630774131774,1.7801561104710195,1.7831748199348287,1.7800479595458731,1.7795798536856575,1.7807743797736573,0.95 +current,d3/la_stack_solve_from_lu,100,2.068034912691297,2.0624043844405473,2.0740576362075123,2.054541299047976,2.053204286673547,2.056574592257737,0.95 +current,d32/la_stack_det,100,2173.511715962495,2168.182777042834,2179.009304325981,2168.540633632302,2163.2463921620547,2178.788811188811,0.95 +current,d32/la_stack_det_from_ldlt,100,7.761084657330838,7.741071319845294,7.78172972820826,7.761708667578196,7.737156693665024,7.783815867105325,0.95 +current,d32/la_stack_det_from_lu,100,9.062986747179776,9.044027889482104,9.083391943771492,9.042549790363317,9.027061715113295,9.048574802021296,0.95 +current,d32/la_stack_det_via_lu,100,2048.316813693135,2044.259508338525,2052.3478198574585,2052.010896951373,2038.2267602457862,2057.7743209876544,0.95 +current,d32/la_stack_dot,100,4.001717474493551,3.996033405378256,4.00821674964597,4.002279478630298,3.9971985367801794,4.004134130729238,0.95 +current,d32/la_stack_inf_norm,100,128.37655872250718,127.69099377093097,129.17261907763913,127.60310823622962,127.36826902491643,127.74566473988439,0.95 +current,d32/la_stack_ldlt,100,2459.3704778224987,2453.8626685931367,2465.325665415841,2448.646902110143,2445.871012052464,2454.500229758294,0.95 +current,d32/la_stack_ldlt_solve,100,2788.0945784141286,2778.9463726805525,2797.8141654002366,2768.5652427637724,2762.180874981572,2794.1459783913565,0.95 +current,d32/la_stack_lu,100,2134.7989854454604,2123.712930669762,2146.331734166774,2119.955224413051,2112.95993754879,2129.7553187980343,0.95 +current,d32/la_stack_lu_solve,100,2759.911839950857,2753.567323792885,2767.07710460142,2755.7729402136074,2752.579773568824,2761.0723724010572,0.95 +current,d32/la_stack_norm2,100,22.867483462615905,22.77386151923901,22.97211337943726,22.751551729243644,22.70271402767946,22.82613076825247,0.95 +current,d32/la_stack_norm2_scenario_descending,100,18.372314249375368,18.298446452297515,18.457721533340774,18.28778379677201,18.23960313001269,18.355352879497133,0.95 +current,d32/la_stack_norm2_scenario_repeated_scale,100,18.39734596799386,18.334045192966343,18.466472340414274,18.332307210118216,18.31212904145235,18.373001254753333,0.95 +current,d32/la_stack_norm2_scenario_sparse,100,9.123647045063343,9.088525389305522,9.158602530708576,9.147520792239048,9.112779865060132,9.182712058343926,0.95 +current,d32/la_stack_norm2_scenario_wide_dynamic_range,100,16.026209458690655,15.99795868719477,16.05342914925465,16.039899053970515,16.018045042143125,16.074110162667097,0.95 +current,d32/la_stack_norm2_sq,100,3.953034365082905,3.9476551511670666,3.9587722843169826,3.9554034762752313,3.9528403327902115,3.957058368775397,0.95 +current,d32/la_stack_solve_from_ldlt,100,312.2607580101537,310.97692419461686,313.71184363687155,310.3703709888475,309.49069355760207,311.12826463184393,0.95 +current,d32/la_stack_solve_from_lu,100,656.5595419770285,653.0899602729287,660.5983675887479,652.5297353287576,650.6968805631454,653.6966416754892,0.95 +current,d4/la_stack_det,100,2.5633515700561595,2.5585982297054772,2.568537016990773,2.557517682131166,2.5558274677675454,2.5593567733711935,0.95 +current,d4/la_stack_det_from_ldlt,100,0.7685440462012781,0.7681047470091654,0.7691639823844156,0.7681530286236746,0.7680141628745131,0.7682211116887955,0.95 +current,d4/la_stack_det_from_lu,100,0.8687614185440896,0.8677676848155907,0.8700090281839584,0.8672351849147296,0.867099724886381,0.8674509544348561,0.95 +current,d4/la_stack_det_via_lu,100,14.450004916455654,14.420372882039016,14.48235855618271,14.459848995691477,14.445280172050332,14.472798593243407,0.95 +current,d4/la_stack_dot,100,0.6818293314288705,0.6803298465625255,0.6835355601580319,0.679658217202584,0.6793690127614522,0.679946504176287,0.95 +current,d4/la_stack_inf_norm,100,2.2286522320283804,2.2259723510268774,2.231466437924713,2.2307594494106713,2.2280305784618752,2.231382650160662,0.95 +current,d4/la_stack_ldlt,100,21.331450601946145,21.271905032554162,21.388272084130687,21.313902652833498,21.26144663627048,21.36023469118169,0.95 +current,d4/la_stack_ldlt_solve,100,35.649794328793035,34.035772814293885,37.21468033289019,38.57318247494764,37.966452324972835,39.70568580429774,0.95 +current,d4/la_stack_lu,100,13.97411191698666,13.83537547307445,14.221526674179367,13.851550872115498,13.818557225822083,13.896676976534705,0.95 +current,d4/la_stack_lu_solve,100,22.141993600372803,22.086528102014313,22.20460704178199,22.101084470745356,22.061056744915724,22.141461025001234,0.95 +current,d4/la_stack_norm2,100,2.4498901520360055,2.4012320544840424,2.500335498201258,2.4365539488890704,2.3493763016831686,2.4573743410159707,0.95 +current,d4/la_stack_norm2_scenario_descending,100,2.3635113333366418,2.356167278936432,2.371677938132111,2.3646045666239432,2.3516526823950303,2.368245157986678,0.95 +current,d4/la_stack_norm2_scenario_repeated_scale,100,2.3691807630990307,2.362280239515821,2.377360044280275,2.3672056055553954,2.3617409110368017,2.3706202374854897,0.95 +current,d4/la_stack_norm2_scenario_sparse,100,1.624189581844343,1.5772389621710567,1.6744707600244706,1.4798441131718305,1.47722116390706,1.4931000290575378,0.95 +current,d4/la_stack_norm2_scenario_wide_dynamic_range,100,2.126492987115436,2.12270222569899,2.130467553846789,2.125905700358224,2.123039660778538,2.1296354139825495,0.95 +current,d4/la_stack_norm2_sq,100,0.46094071621010635,0.4597216271494595,0.4622424032635898,0.46098710971834556,0.4596169676182012,0.46184721578489674,0.95 +current,d4/la_stack_solve_from_ldlt,100,2.5082228117153935,2.4952161791197374,2.5219748357289746,2.466292004820466,2.4653287724875375,2.4692981152227502,0.95 +current,d4/la_stack_solve_from_lu,100,3.912003592106022,3.905105785468615,3.9192185439642384,3.901012688961746,3.8951465539297843,3.9114985627114556,0.95 +current,d5/la_stack_det,100,49.32757507790552,47.347542555016716,51.29575655003345,40.56701108265984,39.960970632951906,58.523420120829,0.95 +current,d5/la_stack_det_from_ldlt,100,0.949372239379726,0.9475938160502473,0.951539315009794,0.9465530113532503,0.9461618430800851,0.9468914598580099,0.95 +current,d5/la_stack_det_from_lu,100,1.1034202477770036,1.1021000628992697,1.1051014299875088,1.1022258882248441,1.1018066626065501,1.1026267970329189,0.95 +current,d5/la_stack_det_via_lu,100,32.63990982263214,32.56909802026734,32.71001639003037,32.67098724608397,32.61756650531454,32.7261264446304,0.95 +current,d5/la_stack_dot,100,0.8357861108657434,0.8330445949765594,0.8382514986740821,0.8406735747771239,0.8384417278918593,0.8413915639428571,0.95 +current,d5/la_stack_inf_norm,100,3.4633889914977924,3.4590162278772985,3.4680948209445757,3.468461739464661,3.4643543188091828,3.4699115725837606,0.95 +current,d5/la_stack_ldlt,100,42.00552025906497,41.82582556649126,42.18922494821766,41.920528362435114,41.565775051124746,42.28169652351738,0.95 +current,d5/la_stack_ldlt_solve,100,45.394599601473786,45.301879377724944,45.49270946922369,45.39200096048505,45.31711117807674,45.51817417795987,0.95 +current,d5/la_stack_lu,100,32.41546051543117,32.33374068457798,32.49980565135961,32.34829077301173,32.27907243915408,32.449564416712704,0.95 +current,d5/la_stack_lu_solve,100,46.06233885646482,45.98585575361773,46.15231986813667,46.069581545860736,45.98934031334168,46.10755327054004,0.95 +current,d5/la_stack_norm2,100,2.8204307805024134,2.789228729225705,2.8529399114850094,2.7398356479963235,2.69768545484654,2.8402021166331455,0.95 +current,d5/la_stack_norm2_scenario_descending,100,3.0170744862508236,3.0113028205136496,3.022795914621755,3.0242748633788845,3.0198163473370556,3.0282694964674706,0.95 +current,d5/la_stack_norm2_scenario_repeated_scale,100,3.00697436811118,3.0003461575086714,3.013644138125355,3.0138668654931875,3.0037765648026924,3.018208802831971,0.95 +current,d5/la_stack_norm2_scenario_sparse,100,1.7566942112993618,1.7313980631153107,1.7870728050811286,1.7173934649287785,1.7148588814138903,1.7198706421653167,0.95 +current,d5/la_stack_norm2_scenario_wide_dynamic_range,100,2.5611489636080433,2.5488588289343923,2.5742506883350775,2.5471259873478207,2.5345991531622096,2.5518926661343997,0.95 +current,d5/la_stack_norm2_sq,100,0.5251244877374556,0.5247822126790619,0.52558817807047,0.5247937270086926,0.5246094976569313,0.5248671551625129,0.95 +current,d5/la_stack_solve_from_ldlt,100,3.9073125485666105,3.899481732789066,3.9151887147212214,3.915318377712727,3.9068641749465898,3.9202612167427335,0.95 +current,d5/la_stack_solve_from_lu,100,5.968132938121012,5.96377179263364,5.973767604586228,5.963079103195744,5.961388568907212,5.965567315223554,0.95 +current,d64/la_stack_det,100,15078.409406328814,15036.285258884513,15119.526020690719,15106.018503004918,15054.057734204793,15163.643811274509,0.95 +current,d64/la_stack_det_from_ldlt,100,22.777673101903794,22.72782439138394,22.825324401024307,22.808443865618703,22.770255276355574,22.843487595675725,0.95 +current,d64/la_stack_det_from_lu,100,22.950957384907582,22.90051675942311,23.00245357314444,22.930058618891245,22.88070767054072,23.014567167080276,0.95 +current,d64/la_stack_det_via_lu,100,15008.84302424785,14968.714912851507,15045.160456926149,15030.810513404089,14991.915780396666,15063.112156249435,0.95 +current,d64/la_stack_dot,100,10.862320842308845,10.818147997916887,10.911609486022517,10.812098556844106,10.792249974842171,10.82771477003118,0.95 +current,d64/la_stack_inf_norm,100,614.697278803718,612.1162776479085,617.6255689609404,611.077921663373,610.1954544582995,613.2000962920948,0.95 +current,d64/la_stack_ldlt,100,20827.934106671873,20763.18558772249,20895.63924588828,20869.835112127563,20806.83412014231,20910.114247311827,0.95 +current,d64/la_stack_ldlt_solve,100,23148.298032877654,23060.41639253489,23238.38182153738,23163.83081672644,23075.668076109938,23257.08228980322,0.95 +current,d64/la_stack_lu,100,14410.279989613817,14387.075754375015,14432.604014531165,14416.577154101076,14397.024373638345,14437.318331643002,0.95 +current,d64/la_stack_lu_solve,100,17474.24523104705,17427.199245644566,17521.548757008597,17518.63433908046,17364.270300333705,17558.53448275862,0.95 +current,d64/la_stack_norm2,100,57.16571711905317,56.999744966375964,57.354370311527106,57.248328289144965,57.070922404207465,57.453359397625256,0.95 +current,d64/la_stack_norm2_scenario_descending,100,38.75508437759564,38.63036288920794,38.90248544981816,38.74566298028928,38.6200212117342,38.81885269127398,0.95 +current,d64/la_stack_norm2_scenario_repeated_scale,100,38.6739678504246,38.536642693182266,38.83357713792538,38.59461554826143,38.511821343299076,38.66859923507232,0.95 +current,d64/la_stack_norm2_scenario_sparse,100,32.86413701999638,32.51717039301879,33.22655533695935,31.722069518443575,31.599739113472012,32.944062236053306,0.95 +current,d64/la_stack_norm2_scenario_wide_dynamic_range,100,35.07143181108106,34.9451205717848,35.2159039069312,34.92960855974506,34.8595716577042,34.982624002836374,0.95 +current,d64/la_stack_norm2_sq,100,10.877548896453945,10.820771586578722,10.937002038536967,10.769371237225805,10.746926744318502,10.796910052000516,0.95 +current,d64/la_stack_solve_from_ldlt,100,1077.9675912940745,1074.760505311113,1081.7055345926315,1075.5276946728513,1072.8316278250918,1079.2417264819958,0.95 +current,d64/la_stack_solve_from_lu,100,2485.445810704269,2473.066123446329,2500.5910187042587,2473.956924395353,2468.4816860465116,2477.09608974359,0.95 +current,d8/la_stack_det,100,90.31606985598826,90.16206484533792,90.46713311749845,90.46721341396295,90.29118970016347,90.64666257620658,0.95 +current,d8/la_stack_det_from_ldlt,100,1.3162808140865563,1.3104039212992111,1.3237500338976695,1.3080130158456464,1.3045225997759817,1.311677276182412,0.95 +current,d8/la_stack_det_from_ldlt_balanced_range,100,9.020300745879338,8.988065854108273,9.053617277908408,8.927016958370132,8.919616312364791,8.96163431939294,0.95 +current,d8/la_stack_det_from_lu,100,1.4672415461970933,1.464410119950535,1.4709761680649314,1.4641517639853654,1.463546893796079,1.4678499618302665,0.95 +current,d8/la_stack_det_from_lu_balanced_range,100,9.10973764802443,9.06521184122659,9.158566337493133,9.1185971673033,8.980198902118858,9.154529351972062,0.95 +current,d8/la_stack_det_via_lu,100,84.96029502509003,84.64616678107916,85.29241398327176,84.63130353308149,84.31493877244384,85.03698775991022,0.95 +current,d8/la_stack_dot,100,0.9684566444354645,0.9620850015034564,0.975327674529973,0.969184023569733,0.9505539553654709,0.9800507622899179,0.95 +current,d8/la_stack_inf_norm,100,8.364476544883047,8.346898961965346,8.38302591837851,8.374841415870733,8.352644711134776,8.384752378199273,0.95 +current,d8/la_stack_ldlt,100,90.67346714063581,90.05689170932969,91.3409451575666,90.53750538195877,88.60659163987138,91.39189804181765,0.95 +current,d8/la_stack_ldlt_ill_conditioned,100,90.14634626181329,89.72900024063115,90.57257188699678,90.28742418001447,88.77637431062088,91.40517017229347,0.95 +current,d8/la_stack_ldlt_solve,100,99.20663657524015,98.95157132056926,99.47729342935729,99.31337905776225,98.88991163025925,99.45941912980462,0.95 +current,d8/la_stack_lu,100,83.2231114990113,82.93013602032384,83.52645438246986,82.9464469192276,82.62605824522352,83.29422067181497,0.95 +current,d8/la_stack_lu_ill_conditioned,100,82.88255344417266,82.59603186468198,83.19208557963924,82.32824899685752,82.2218307639011,82.57822251241326,0.95 +current,d8/la_stack_lu_pivoting,100,90.41878583234511,90.21764587717345,90.61567152440257,90.39213266782889,90.15913095725648,90.69851593990472,0.95 +current,d8/la_stack_lu_solve,100,128.58196932381617,128.33484875722627,128.85500670998877,128.36396548733447,128.19900330404025,128.65769248327663,0.95 +current,d8/la_stack_norm2,100,4.784714506151764,4.733568340589944,4.841199514474892,4.695370093202566,4.6542130949115315,4.827849734142444,0.95 +current,d8/la_stack_norm2_scenario_descending,100,4.840497925123319,4.82552992762712,4.857746611400221,4.826341062923728,4.818881333958061,4.832997357988833,0.95 +current,d8/la_stack_norm2_scenario_repeated_scale,100,4.8314047961900615,4.817151380834234,4.847352688846977,4.822445169881478,4.812812068366978,4.828417297763505,0.95 +current,d8/la_stack_norm2_scenario_sparse,100,2.5675455057262964,2.5256327537712475,2.613263836235371,2.4666056498880256,2.462686800481667,2.469178231799872,0.95 +current,d8/la_stack_norm2_scenario_wide_dynamic_range,100,4.213304368263902,4.205640065134331,4.221299874051221,4.217204719757027,4.212700775325741,4.222426143509827,0.95 +current,d8/la_stack_norm2_sq,100,0.6675132030349328,0.6660082239791488,0.6692025818196075,0.6653353212230229,0.6649370103659074,0.6660386085658094,0.95 +current,d8/la_stack_solve_from_ldlt,100,8.059693879493825,8.045494380791135,8.076199436881287,8.049514444977088,8.042101759255356,8.055572801898023,0.95 +current,d8/la_stack_solve_from_lu,100,13.494807802112032,13.47244052643705,13.517584909576179,13.485412752904509,13.460706408754657,13.51681439600249,0.95 +current,det4_diagnostic_dense/det_exact,100,375.44474521642786,374.6645939960575,376.36567653031926,374.69198917166074,374.13528213217654,375.3318542780624,0.95 +current,det4_diagnostic_dense/det_sign_exact,100,6.96292261248623,6.958734756845786,6.968009728841178,6.960286235114561,6.958237786118748,6.96179471478062,0.95 +current,det4_diagnostic_large_entries/det_exact,100,858.7448655581128,856.5410283226663,861.1878815590944,857.2817559740872,854.173636325696,860.0681624306164,0.95 +current,det4_diagnostic_large_entries/det_sign_exact,100,844.3044736770871,840.287289080327,848.7018698914317,835.8910995316321,834.5748876629443,838.1651243493349,0.95 +current,det4_diagnostic_mixed_exponents/det_exact,100,1752.9796811345004,1750.3203619135943,1755.6128973096158,1754.5654627985,1751.698236488201,1756.9046922462135,0.95 +current,det4_diagnostic_mixed_exponents/det_sign_exact,100,29.028904375375387,29.0036118285566,29.060063009924846,29.001418565359785,28.979501373183826,29.015717481630457,0.95 +current,det4_diagnostic_near_singular_negative/det_exact,100,1122.848211919686,1120.6328825200349,1125.147575937757,1122.0429188231062,1118.8579127508992,1124.5955879139242,0.95 +current,det4_diagnostic_near_singular_negative/det_sign_exact,100,1197.645006764904,1194.2849521064504,1201.1793196405383,1196.178961309141,1193.2477587612061,1201.5064416024074,0.95 +current,det4_diagnostic_near_singular_positive/det_exact,100,1123.4861629147724,1121.521797362029,1125.4934847357433,1122.3911868215025,1120.6812358437146,1124.0977013253344,0.95 +current,det4_diagnostic_near_singular_positive/det_sign_exact,100,1197.0018321458922,1194.5967722905145,1199.4206415178658,1198.8081127085811,1196.9131483715319,1200.1987361369422,0.95 +current,det4_diagnostic_singular/det_exact,100,372.716603577122,371.9855872258021,373.4729498138388,372.80193878712424,371.5158296826584,373.73512720969717,0.95 +current,det4_diagnostic_singular/det_sign_exact,100,410.4108009957511,407.8150570608698,413.1730276481214,409.14424552574945,406.5084068936528,411.59140517951994,0.95 +current,det4_diagnostic_sparse/det_exact,100,208.86804553777358,208.63172050113502,209.12575794646835,208.5449168592707,208.3639336158192,208.9347294827947,0.95 +current,det4_diagnostic_sparse/det_sign_exact,100,6.500125058469727,6.486621224401996,6.515388426456045,6.475218281357395,6.468586906442241,6.483094931921171,0.95 +current,exact_d2/det,100,0.448334327787944,0.44392661479360357,0.4532602303843013,0.43781032284173355,0.4374999494141236,0.4384717520724585,0.95 +current,exact_d2/det_direct,100,0.4494573476318893,0.4445735868182595,0.45483530548805606,0.43764312485011625,0.43733467617422683,0.4380725956326307,0.95 +current,exact_d2/det_direct_with_errbound,100,1.7093910963015742,1.7071874799796893,1.7120081816384691,1.707301370576697,1.706392365043203,1.7079640536051874,0.95 +current,exact_d2/det_errbound,100,1.6116689136490263,1.6108952832564634,1.6129705816836764,1.61087434662331,1.6106233733633932,1.611066854770069,0.95 +current,exact_d2/det_exact,100,100.58953028748263,100.40235353622207,100.8062677106659,100.38341954181654,100.25860606191442,100.45874695478162,0.95 +current,exact_d2/det_exact_f64_result,100,73.36749039755806,73.16846934580003,73.59232149152719,73.1213778250135,72.94808642430499,73.23938371865611,0.95 +current,exact_d2/det_exact_rounded_f64,100,73.52411702129139,73.35858417894762,73.71334163264616,73.28986935803702,73.20382053330754,73.4270084741141,0.95 +current,exact_d2/det_sign_exact,100,2.9735092658808533,2.9707948785298086,2.976536616068005,2.972744800938455,2.9711808333049,2.9736586699857512,0.95 +current,exact_d2/solve_exact,100,7107.171588024752,7095.1122687357965,7119.3692477886425,7103.236559696343,7091.384964514652,7121.540946181428,0.95 +current,exact_d2/solve_exact_f64_result,100,7336.128031366701,7324.304973011941,7348.844521173024,7326.972864819005,7315.699840005447,7338.10310828877,0.95 +current,exact_d2/solve_exact_rounded_f64,100,7561.381168038106,7547.065175152501,7577.909401613494,7545.505944737936,7536.420801250207,7556.27417794971,0.95 +current,exact_d3/det,100,0.8316242084393357,0.8287080870134977,0.8346712699234563,0.8205262414403394,0.8199799374461267,0.8295844554790524,0.95 +current,exact_d3/det_direct,100,0.8468389797591033,0.8455008257133515,0.8482535464254791,0.8432414275976221,0.8430395941139964,0.8435849574105542,0.95 +current,exact_d3/det_direct_with_errbound,100,3.3406769080107743,3.3357716248023705,3.3467473160639436,3.3336258051064513,3.3312802100185195,3.3352301728199736,0.95 +current,exact_d3/det_errbound,100,3.3053428259809237,3.301734327220677,3.3098882464350075,3.301854619913609,3.300750512987338,3.3025672634616923,0.95 +current,exact_d3/det_exact,100,339.9586870966679,339.2510571195371,340.7293183220157,338.868923097078,338.46532875716184,339.38967754066,0.95 +current,exact_d3/det_exact_f64_result,100,315.80458320078816,314.5293608054513,317.23527167964306,313.9413507267287,313.1984278780776,314.3903124768787,0.95 +current,exact_d3/det_exact_rounded_f64,100,318.0521336272898,317.15237892806044,319.0257167945184,317.1925903651616,315.9744710708117,318.1826393981224,0.95 +current,exact_d3/det_sign_exact,100,4.713300766695529,4.70513899439692,4.7232868561931785,4.705757595319605,4.702250463114307,4.707522923587225,0.95 +current,exact_d3/solve_exact,100,30582.771929509352,30533.624764517113,30632.789943791457,30602.10746352413,30507.73347107438,30673.99090909091,0.95 +current,exact_d3/solve_exact_f64_result,100,30928.93679551704,30871.554996005274,30989.3271512046,30919.16288553989,30857.226107226106,30964.459375,0.95 +current,exact_d3/solve_exact_rounded_f64,100,31642.871874113272,31575.89853266038,31715.448854709135,31603.564459930312,31551.840401785714,31717.042520491803,0.95 +current,exact_d4/det,100,3.2075210940073493,3.205606029069311,3.209960550461681,3.2078095214172038,3.207275625470412,3.2084480682172294,0.95 +current,exact_d4/det_direct,100,2.383840981174678,2.3795042518276794,2.388728882827854,2.3803328914201023,2.3785431672403856,2.381988121518936,0.95 +current,exact_d4/det_direct_with_errbound,100,6.835687398428239,6.824533530383488,6.848231013627901,6.821028261215035,6.815559989908025,6.8248932760945085,0.95 +current,exact_d4/det_errbound,100,6.741558519761019,6.733852855278231,6.750437883886153,6.729836734415867,6.727625763994841,6.733718203008371,0.95 +current,exact_d4/det_exact,100,1009.7674337409617,1007.7992155284875,1011.8042078739339,1009.5950009915389,1006.5170470604861,1011.3975830359977,0.95 +current,exact_d4/det_exact_f64_result,100,1056.486652470474,1048.7663217638283,1067.0991210493626,1055.9986747178903,1051.7988398630657,1058.7444400467414,0.95 +current,exact_d4/det_exact_rounded_f64,100,1011.4731450330395,1009.4583845277967,1013.5703566241278,1009.2358341763912,1006.8119404466618,1011.4477925130099,0.95 +current,exact_d4/det_sign_exact,100,8.002961406053776,7.990348241243119,8.018195688501132,7.985573115804334,7.982308406661035,7.986920977775807,0.95 +current,exact_d4/solve_exact,100,79333.37282609925,79185.7759094004,79491.977739461,79178.4623076923,79081.10126582278,79340.80466891357,0.95 +current,exact_d4/solve_exact_f64_result,100,79407.44710261577,79208.15832085327,79634.07966036651,79336.07189163039,79125.99469496022,79496.14423076923,0.95 +current,exact_d4/solve_exact_rounded_f64,100,80023.92074302095,79847.24423250287,80216.4717629966,79863.49631190728,79656.36820512821,80046.13210702341,0.95 +current,exact_d5/det,100,25.0350494847865,24.968434583042455,25.10151459604931,25.043344471514565,24.995479405101708,25.135772398764903,0.95 +current,exact_d5/det_exact,100,3753.960068674431,3734.727517045418,3773.5943422265614,3738.1248015873016,3705.1132756132756,3794.3482912104237,0.95 +current,exact_d5/det_exact_f64_result,100,3561.56694684171,3550.9210438569066,3574.1926581265398,3544.652719389012,3538.908739177489,3552.1158175750834,0.95 +current,exact_d5/det_exact_rounded_f64,100,3603.268289720171,3595.9825487833577,3610.7356736387615,3605.8623239750445,3595.887313258637,3610.711249482187,0.95 +current,exact_d5/det_sign_exact,100,3766.0394361869835,3737.0161103195173,3797.4310579737685,3704.8721509769766,3697.9076282866836,3710.828306845201,0.95 +current,exact_d5/solve_exact,100,157902.8432773604,157563.10523133018,158291.09431214596,157602.5066181078,157283.09714285715,157888.85194805195,0.95 +current,exact_d5/solve_exact_f64_result,100,157835.27235861847,157513.4831217454,158192.48447554576,157719.6392605634,157381.78413907666,157932.54017857142,0.95 +current,exact_d5/solve_exact_rounded_f64,100,166131.58910639054,164033.871041037,169278.04206813427,164264.16929499072,163539.7906066536,164868.8833161912,0.95 +current,exact_hilbert_4x4/det_exact,100,1044.9636074495884,1043.2811759589113,1046.7688629336094,1044.8245046831648,1042.7718832891246,1046.4298433048434,0.95 +current,exact_hilbert_4x4/det_sign_exact,100,7.983051122332573,7.975180614425884,7.994137250456467,7.974913489427017,7.972913379580798,7.976321590355597,0.95 +current,exact_hilbert_4x4/solve_exact,100,59617.23939717109,59525.70170276097,59720.98367228197,59562.646813725485,59472.56787330317,59626.23697478992,0.95 +current,exact_hilbert_4x4/solve_exact_f64_result,100,59687.48655137636,59557.41311693218,59827.32783645422,59742.61845588236,59589.82071339174,59791.27646461933,0.95 +current,exact_hilbert_4x4/solve_exact_rounded_f64,100,60615.54613886002,60437.09146835908,60804.75313665774,60472.54090909091,60259.43647058823,60619.0091503268,0.95 +current,exact_hilbert_5x5/det_exact,100,3756.432309846849,3745.0153451498186,3769.464639277731,3750.008168828238,3738.7509505703424,3755.165599359616,0.95 +current,exact_hilbert_5x5/det_sign_exact,100,3925.7189134077826,3918.8763319899786,3932.6054614183445,3918.590754664439,3915.3213383838383,3927.16503968254,0.95 +current,exact_hilbert_5x5/solve_exact,100,123006.06662845088,122739.0931884471,123320.30992883784,122818.14453584018,122529.32592592592,122952.81481481482,0.95 +current,exact_hilbert_5x5/solve_exact_f64_result,100,122283.83820805306,122099.05542302792,122483.5607924633,122061.4738379684,121913.71124018705,122401.700152207,0.95 +current,exact_hilbert_5x5/solve_exact_rounded_f64,100,125133.10972923864,124700.60098363015,125616.02154620198,124521.4581136221,124212.54322292695,124643.6507936508,0.95 +current,exact_large_entries_3x3/det_exact,100,345.5511697865632,343.30877598036625,347.96562434736,341.6098434235628,340.5692485684668,343.93572909467866,0.95 +current,exact_large_entries_3x3/det_sign_exact,100,336.280364900678,334.9919982395395,337.6503847852954,334.8971678999295,334.13514600454624,337.04329802912594,0.95 +current,exact_large_entries_3x3/solve_exact,100,93269.52377960134,93059.13297794665,93498.3868562154,93137.35240435241,92931.4738292011,93303.57142857143,0.95 +current,exact_large_entries_3x3/solve_exact_f64_result,100,93520.87889039196,93385.97784018132,93674.97395655897,93374.05808247712,93240.58769513314,93459.25033880847,0.95 +current,exact_large_entries_3x3/solve_exact_rounded_f64,100,93392.50503125998,93305.7062359648,93501.30199366035,93318.68042264752,93204.67032967033,93376.48234500174,0.95 +current,exact_near_singular_3x3/det_exact,100,334.8998365764963,333.8022039007333,336.05840340234926,334.5203922663559,333.82858197073244,336.319298096533,0.95 +current,exact_near_singular_3x3/det_sign_exact,100,363.36429950123585,362.0627321611485,364.79891512655087,360.9107574552844,360.5224990429072,361.6493583797155,0.95 +current,exact_near_singular_3x3/solve_exact,100,2807.805069711636,2797.3315025438587,2819.8020973539415,2809.473142563902,2799.9518226600985,2813.585387945388,0.95 +current,exact_near_singular_3x3/solve_exact_f64_result,100,2816.2945587162076,2808.100600746016,2825.0489322991893,2806.3639808864723,2799.1107401864856,2814.8926511781183,0.95 +current,exact_near_singular_3x3/solve_exact_rounded_f64,100,2804.0986771997455,2792.6747522879077,2816.4566651973178,2784.062779974001,2772.294225321421,2800.5754249291786,0.95 +current,exact_random_corpus_d2/det_exact,100,3200.9400977861433,3172.1491121864656,3246.931789048983,3157.536648462783,3142.491100323625,3184.1920967467213,0.95 +current,exact_random_corpus_d2/det_sign_exact,100,150.18942657950697,149.313271780776,151.17505588916504,149.8756731627712,148.86689827636766,150.89118172537007,0.95 +current,exact_random_corpus_d2/solve_exact,100,78712.15808376804,78546.43104221263,78896.39077848685,78458.42516722408,78373.11312217194,78647.39964633068,0.95 +current,exact_random_corpus_d2/solve_exact_f64_result,100,80298.54951019395,79982.65175827578,80683.15974418505,79810.54097465034,79665.21794871795,79956.22171945701,0.95 +current,exact_random_corpus_d2/solve_exact_rounded_f64,100,82237.71306384573,82078.45040581276,82402.7632296221,82228.78896817469,82016.56611927398,82365.14624881292,0.95 +current,exact_random_corpus_d3/det_exact,100,8517.421423809817,8488.027932537374,8548.461303738595,8469.841430544764,8444.49698605488,8491.39093273876,0.95 +current,exact_random_corpus_d3/det_sign_exact,100,229.1039871781915,228.52299934037543,229.7251910735557,227.85050023693248,227.4222421578753,228.3404107611729,0.95 +current,exact_random_corpus_d3/solve_exact,100,241150.40738424516,240403.907426232,241958.2374879105,239624.88788907754,239139.02666666667,240192.04545454544,0.95 +current,exact_random_corpus_d3/solve_exact_f64_result,100,241872.9310748343,241178.00268269947,242627.78371212832,240544.78857142857,240004.46471264368,241284.83412698412,0.95 +current,exact_random_corpus_d3/solve_exact_rounded_f64,100,243829.13815502153,243132.11904824647,244559.00834991594,242671.08039215687,242062.56701754386,243321.6918625678,0.95 +current,exact_random_corpus_d4/det_exact,100,21303.0742780812,21225.098513891535,21390.762339035216,21196.339806629563,21163.533822039455,21270.82978723404,0.95 +current,exact_random_corpus_d4/det_sign_exact,100,457.578430954531,455.37520410357627,459.9955127958968,454.5566540631005,452.65036491023204,456.0180995475113,0.95 +current,exact_random_corpus_d4/solve_exact,100,539699.6658421434,537562.1343562746,542057.4899392949,535371.3718434344,533843.75,537107.061875,0.95 +current,exact_random_corpus_d4/solve_exact_f64_result,100,535105.5738367602,534359.9834086625,535899.1553133661,534530.0083762887,533886.6849800621,535332.8804347826,0.95 +current,exact_random_corpus_d4/solve_exact_rounded_f64,100,535823.0637890326,535340.640936159,536382.921467213,535394.394736842,535087.6551724138,535958.797752809,0.95 +current,exact_random_corpus_d5/det_exact,100,56217.81422738757,56035.685442528156,56425.098726639,55994.694210032816,55881.40189125296,56126.51728395062,0.95 +current,exact_random_corpus_d5/det_sign_exact,100,61947.00858486408,61794.008576708504,62078.018199548555,61934.375744853736,61875.2203525641,62040.81593406593,0.95 +current,exact_random_corpus_d5/solve_exact,100,1046646.3067633905,1044681.421375756,1049078.694479602,1044342.0280864197,1042954.4758064516,1044963.9105263158,0.95 +current,exact_random_corpus_d5/solve_exact_f64_result,100,1045420.7193984773,1043424.5859941589,1047655.8213844076,1041768.932346723,1041145.4042553192,1043707.0707070708,0.95 +current,exact_random_corpus_d5/solve_exact_rounded_f64,100,1047206.1978465404,1045449.4518814485,1049278.1503789267,1044969.8439878235,1044289.2083333333,1046173.4258241758,0.95 +current,lu_solve_dense_ill_conditioned_d16/la_stack_lu_solve,100,650.1169328147862,648.3583918009582,652.0430012419333,648.133567232376,646.2967264397261,649.4945642779815,0.95 +current,lu_solve_dense_ill_conditioned_d16/la_stack_solve_from_lu,100,187.5302327280541,187.0985542146961,188.01056004697972,187.79626293125415,187.14721020351269,188.08348002708192,0.95 +current,lu_solve_dense_ill_conditioned_d2/la_stack_lu_solve,100,2.0716493703778687,2.06393742800012,2.0802977681141224,2.0531381541650093,2.0523501452388047,2.054629027188926,0.95 +current,lu_solve_dense_ill_conditioned_d2/la_stack_solve_from_lu,100,1.3813824817812932,1.3775055171306285,1.3851126100333617,1.3872926880616978,1.3854843298300028,1.3888481955004435,0.95 +current,lu_solve_dense_ill_conditioned_d3/la_stack_lu_solve,100,10.941320183620142,10.919519403181416,10.964345508282825,10.923312877457043,10.907849978143805,10.948270793970122,0.95 +current,lu_solve_dense_ill_conditioned_d3/la_stack_solve_from_lu,100,2.692035868033128,2.6851908930235475,2.6992008167734562,2.691061520968627,2.6789518382360002,2.7024183138224487,0.95 +current,lu_solve_dense_ill_conditioned_d32/la_stack_lu_solve,100,2819.369995323307,2811.844792650096,2827.323194118464,2812.8207037894535,2802.76303641119,2824.41076368122,0.95 +current,lu_solve_dense_ill_conditioned_d32/la_stack_solve_from_lu,100,787.0959055332482,784.5724322388662,790.1209716327868,786.1094462740161,782.6816340905089,788.0677496038035,0.95 +current,lu_solve_dense_ill_conditioned_d4/la_stack_lu_solve,100,23.12362971493078,23.084095973713737,23.16599215985602,23.110302734375,23.071622248211824,23.145314659844406,0.95 +current,lu_solve_dense_ill_conditioned_d4/la_stack_solve_from_lu,100,4.853724615243992,4.842271198684249,4.86552943866771,4.856077738739995,4.850419154769683,4.859076425266606,0.95 +current,lu_solve_dense_ill_conditioned_d5/la_stack_lu_solve,100,46.31676748317887,46.24607007455032,46.39456764989695,46.30715504812136,46.238879920475505,46.342611633274245,0.95 +current,lu_solve_dense_ill_conditioned_d5/la_stack_solve_from_lu,100,7.323448716522401,7.304850202995579,7.343731229686461,7.306305494676991,7.299819194989201,7.313499240841497,0.95 +current,lu_solve_dense_ill_conditioned_d64/la_stack_lu_solve,100,17075.42621353481,17039.74526537537,17113.777006812572,17051.00580118411,17025.564430980725,17080.347842261905,0.95 +current,lu_solve_dense_ill_conditioned_d64/la_stack_solve_from_lu,100,2496.600140669142,2485.434140807319,2510.188700559227,2484.3722622833957,2480.9875,2490.6845,0.95 +current,lu_solve_dense_ill_conditioned_d8/la_stack_lu_solve,100,130.09843006988848,129.73955973109645,130.48185870967757,129.75699671063845,129.46037870266215,130.0270557720689,0.95 +current,lu_solve_dense_ill_conditioned_d8/la_stack_solve_from_lu,100,14.159039719692421,14.139801585548867,14.17963563667696,14.161150520703275,14.137177203786896,14.179195530428775,0.95 +current,lu_solve_pivoting_d16/la_stack_lu_solve,100,772.8778375988276,771.394168639116,774.437249954249,771.008723485877,770.2456420195081,772.8070960535528,0.95 +current,lu_solve_pivoting_d16/la_stack_solve_from_lu,100,189.32851617984724,188.93422052850158,189.7585383633278,189.18747850169552,188.84258369391435,189.6727082041786,0.95 +current,lu_solve_pivoting_d2/la_stack_lu_solve,100,2.092406060738136,2.0817086416682944,2.103812061263381,2.0629499325219216,2.057337517222705,2.0731879511218922,0.95 +current,lu_solve_pivoting_d2/la_stack_solve_from_lu,100,1.3651069885847031,1.360231116860327,1.3701500399033884,1.3553761525379082,1.350397948716227,1.3673334497156866,0.95 +current,lu_solve_pivoting_d3/la_stack_lu_solve,100,22.972467022609184,22.82639380976437,23.12114490724972,22.89767356952229,22.721150474669216,23.023192598555404,0.95 +current,lu_solve_pivoting_d3/la_stack_solve_from_lu,100,2.704159876574264,2.6978315086075293,2.7110192345602244,2.707793829245041,2.703911011069322,2.7103347080020526,0.95 +current,lu_solve_pivoting_d32/la_stack_lu_solve,100,3138.024825109782,3132.509932187873,3143.8569121128403,3135.2960378734265,3131.7244359674296,3140.4225053078558,0.95 +current,lu_solve_pivoting_d32/la_stack_solve_from_lu,100,788.3766454374793,784.7104160785822,792.5903037017378,785.1929714445121,782.8409092686936,788.1604865222073,0.95 +current,lu_solve_pivoting_d4/la_stack_lu_solve,100,39.36896192327785,39.234639513261385,39.51448716532799,39.184138941992096,39.12771016799552,39.29972914048219,0.95 +current,lu_solve_pivoting_d4/la_stack_solve_from_lu,100,4.8649225654493,4.856744625604045,4.874915762593233,4.855571566408048,4.8512780171744865,4.860303259880972,0.95 +current,lu_solve_pivoting_d5/la_stack_lu_solve,100,83.66795676911599,83.41545784196019,83.93889664242725,83.50623108056216,83.27900427487825,83.8860379651875,0.95 +current,lu_solve_pivoting_d5/la_stack_solve_from_lu,100,7.319195973533782,7.299535315930821,7.343237135316903,7.282466065887508,7.273069364052765,7.307097373883106,0.95 +current,lu_solve_pivoting_d64/la_stack_lu_solve,100,18379.570767331923,18329.830142088165,18436.23284062064,18317.671126087225,18280.58754273504,18375.929423076923,0.95 +current,lu_solve_pivoting_d64/la_stack_solve_from_lu,100,2491.655470004219,2480.3801356934323,2505.0348929551024,2480.1778564057204,2473.6073426460207,2487.613690524314,0.95 +current,lu_solve_pivoting_d8/la_stack_lu_solve,100,198.17739881960892,197.85750455575032,198.50513248280126,198.12133622645337,197.77808423648517,198.2932202062905,0.95 +current,lu_solve_pivoting_d8/la_stack_solve_from_lu,100,14.123505258637683,14.096102823830234,14.1524914319982,14.13080005364339,14.113941449579002,14.142265089976355,0.95 +current,rational_input_d2/det_big_rational_gaussian,100,1183.7425011254534,1181.2503370095587,1186.644456502572,1179.781670746634,1178.8611471070353,1180.5365686944635,0.95 +current,rational_input_d2/det_row_cleared_bareiss,100,191.43276304507566,191.16425745484176,191.70324783505401,191.30687653285804,190.8536299834349,191.99277375769552,0.95 +current,rational_input_d2/det_sign_row_cleared_bareiss,100,82.45027369696477,82.2805000199284,82.6449627341068,82.2647632356479,82.1780923875856,82.42679195275248,0.95 +current,rational_input_d2/solve_big_rational_gaussian,100,2232.033401774756,2225.09793806209,2241.5092248281717,2220.772367966738,2219.122622981777,2224.872231139647,0.95 +current,rational_input_d2/solve_row_cleared_bareiss,100,968.6827523888079,967.3729624061455,970.2926900250034,967.4646855244368,966.4846857506941,968.1503587736464,0.95 +current,rational_input_d3/det_big_rational_gaussian,100,4900.487579716576,4888.841548107599,4914.502330861419,4886.058645889219,4875.046179991134,4898.523650281695,0.95 +current,rational_input_d3/det_row_cleared_bareiss,100,579.7316758080707,578.7263671200396,580.9387394516743,578.5985219975588,577.9842848803269,579.1021693689622,0.95 +current,rational_input_d3/det_sign_row_cleared_bareiss,100,369.0871027971696,368.2695050339321,369.92429167069713,368.64189398809697,367.84755843660724,369.614621034703,0.95 +current,rational_input_d3/solve_big_rational_gaussian,100,8448.041370329787,8438.916405026626,8457.338336434568,8443.032580254629,8434.24440677966,8457.803746654772,0.95 +current,rational_input_d3/solve_row_cleared_bareiss,100,2513.367894166846,2504.906375854786,2523.1701057409173,2500.499612416115,2494.8609034560004,2505.587346273522,0.95 +current,rational_input_d4/det_big_rational_gaussian,100,14183.274086828154,14159.99849702394,14207.954978463204,14158.317917888562,14137.330102040816,14187.385531135531,0.95 +current,rational_input_d4/det_row_cleared_bareiss,100,1167.1212243982886,1164.842271814393,1169.842390076096,1165.5311528391426,1163.9019594471722,1166.7706199106908,0.95 +current,rational_input_d4/det_sign_row_cleared_bareiss,100,770.276077463477,768.7490358092755,771.9717264845486,769.0789354105809,767.2085897737061,770.6653746770025,0.95 +current,rational_input_d4/solve_big_rational_gaussian,100,24970.995259123243,24928.85981634472,25016.838074453815,24939.264128599803,24895.645317782284,24977.715657013396,0.95 +current,rational_input_d4/solve_row_cleared_bareiss,100,5528.811930540862,5517.953469576899,5541.030335119973,5510.746250248496,5505.704878609906,5522.200143340195,0.95 +current,rational_input_d5/det_big_rational_gaussian,100,28193.74107005983,26918.196140213196,29573.722068250296,24971.810975609755,24546.333333333332,25750.66056910569,0.95 +current,rational_input_d5/det_row_cleared_bareiss,100,2155.677887168661,2151.6583109341136,2159.820351253343,2149.319083760125,2145.5409961409146,2155.393947144075,0.95 +current,rational_input_d5/det_sign_row_cleared_bareiss,100,1588.7988401370114,1585.1831160060979,1592.5043308508166,1584.107474509711,1580.4311137268091,1587.3894778864872,0.95 +current,rational_input_d5/solve_big_rational_gaussian,100,41216.73193862263,41134.596285631356,41318.33917562136,41109.80979345956,41065.769230769234,41144.20801861702,0.95 +current,rational_input_d5/solve_row_cleared_bareiss,100,9724.332928040885,9693.480797637892,9758.113672593661,9673.317355757481,9644.892271011082,9717.70213592233,0.95 +current,rational_input_d6/det_big_rational_gaussian,100,57891.50832335691,57810.57365750598,57971.92396750667,57912.00173611111,57836.38888888889,58015.86008230453,0.95 +current,rational_input_d6/det_row_cleared_bareiss,100,3757.867711261072,3746.788304000867,3771.928918999995,3753.0803145963455,3747.6153508059574,3761.336770100129,0.95 +current,rational_input_d6/det_sign_row_cleared_bareiss,100,3096.965169424275,3090.7769068620046,3103.2121301375146,3095.7158085258397,3087.1125444329778,3104.3652139542537,0.95 +current,rational_input_d6/solve_big_rational_gaussian,100,92475.99558151547,92375.91049246475,92577.84527584727,92495.04895302773,92347.2212121212,92598.13068181818,0.95 +current,rational_input_d6/solve_row_cleared_bareiss,100,18054.403518854873,18032.567515337658,18079.546234373604,18029.857435977454,18013.57671092952,18047.45338491296,0.95 +current,rational_input_d7/det_big_rational_gaussian,100,112714.59476290218,112453.0983221397,113004.87160266025,112353.15160139647,112247.51490514904,112501.75061728395,0.95 +current,rational_input_d7/det_row_cleared_bareiss,100,6187.712933471385,6158.1447061729505,6222.186674826605,6146.45569258195,6136.912735339507,6161.782420768532,0.95 +current,rational_input_d7/det_sign_row_cleared_bareiss,100,5319.210841777289,5299.69646107898,5345.778480923848,5301.622762861061,5290.031442080378,5312.831750378438,0.95 +current,rational_input_d7/solve_big_rational_gaussian,100,165761.299170393,165322.02922935685,166246.74859992482,165068.65763546797,164882.5628524436,165480.4257936508,0.95 +current,rational_input_d7/solve_row_cleared_bareiss,100,29471.250551854424,29436.445392101527,29507.98832958493,29461.859337068163,29440.257352941175,29500.74031563845,0.95 +current,rational_input_d8/det_big_rational_gaussian,100,208098.7769328558,202644.32733845172,214053.69426593362,194975.51470588235,193238.88771929825,197899.14772727274,0.95 +current,rational_input_d8/det_row_cleared_bareiss,100,9335.145633559106,9310.09512024837,9362.425746369658,9307.47716174118,9293.28765485764,9327.78308773733,0.95 +current,rational_input_d8/det_sign_row_cleared_bareiss,100,8489.130207161908,8463.867657454026,8520.5407891869,8471.447874021404,8463.675808913309,8479.083287870522,0.95 +current,rational_input_d8/solve_big_rational_gaussian,100,273056.9641901282,272358.0486318337,274043.94000353024,272399.82469223486,272067.51851851854,272646.1037745098,0.95 +current,rational_input_d8/solve_row_cleared_bareiss,100,43678.7235343862,43523.5340873408,43854.22714612346,43365.191706517515,43314.05629877369,43432.587615283264,0.95 +current,rational_input_wide1024_d2/det_big_rational_gaussian,100,196468.70479447898,196077.8450584045,196902.67426820617,195953.3276771163,195746.31022970087,196205.78644688646,0.95 +current,rational_input_wide1024_d2/det_row_cleared_bareiss,100,42472.45372210485,42393.99883102421,42562.27892490248,42378.76142473118,42282.319645398486,42468.905303030304,0.95 +current,rational_input_wide1024_d2/det_sign_row_cleared_bareiss,100,1160.3628122184668,1154.3896985939034,1166.865684221742,1146.7892954704057,1145.02962398495,1148.1467598551649,0.95 +current,rational_input_wide1024_d2/solve_big_rational_gaussian,100,203614.84685429544,203283.11215266635,204017.71729797556,203338.8208080808,202928.2258064516,203652.07291666666,0.95 +current,rational_input_wide1024_d2/solve_row_cleared_bareiss,100,3930.5816114889403,3926.018199967716,3935.4884697641637,3931.3894707883155,3922.9910714285716,3934.975040942303,0.95 +current,rational_input_wide1024_d3/det_big_rational_gaussian,100,615079.881154909,613822.8152707092,616492.9603304204,613538.8357638059,612853.8582089553,614398.483974359,0.95 +current,rational_input_wide1024_d3/det_row_cleared_bareiss,100,70235.84182344162,70171.07802044073,70309.88794187926,70155.60124320124,70112.64,70212.5,0.95 +current,rational_input_wide1024_d3/det_sign_row_cleared_bareiss,100,5004.310864246352,4981.0004686904695,5029.649866404101,4952.514789511062,4942.16288338243,4975.8750244730145,0.95 +current,rational_input_wide1024_d3/solve_big_rational_gaussian,100,708664.1991283088,707123.6229594586,710365.2480068383,707525.4030720339,705507.6710526316,709460.5535714285,0.95 +current,rational_input_wide1024_d3/solve_row_cleared_bareiss,100,15746.26736570302,15688.287825233047,15808.299375541801,15662.974551491723,15586.372312638136,15713.209150326797,0.95 +current,rational_input_wide1024_d4/det_big_rational_gaussian,100,1471148.383778773,1468037.250994542,1474635.82083455,1468165.7322222223,1465292.9992668622,1470313.121212121,0.95 +current,rational_input_wide1024_d4/det_row_cleared_bareiss,100,112438.35867157731,112342.95611227133,112559.11656331601,112344.33333333334,112262.51526251527,112437.11111111111,0.95 +current,rational_input_wide1024_d4/det_sign_row_cleared_bareiss,100,11199.20554851038,11124.02312716721,11279.273655090758,11041.839900231347,10989.087128154028,11149.922645981469,0.95 +current,rational_input_wide1024_d4/solve_big_rational_gaussian,100,1703801.6774582493,1701153.503412941,1706753.0525263676,1703047.1674107143,1697651.0416666667,1705616.8347569956,0.95 +current,rational_input_wide1024_d4/solve_row_cleared_bareiss,100,46525.83362987272,46370.33200162997,46691.17612865581,46137.23870778813,46080.38192904656,46206.57076118326,0.95 +current,rational_input_wide1024_d5/det_big_rational_gaussian,100,2650197.189565217,2493003.6495869556,2821148.5384673914,2242718.304347826,2238474.6304347827,2267360.4782608696,0.95 +current,rational_input_wide1024_d5/det_row_cleared_bareiss,100,189630.480076288,189426.43422339731,189882.48225740483,189298.3869047619,189212.1641599413,189445.54013480392,0.95 +current,rational_input_wide1024_d5/det_sign_row_cleared_bareiss,100,45298.43667820678,45227.74610973652,45367.81161644463,45392.76411931818,45309.1067616096,45440.92738464187,0.95 +current,rational_input_wide1024_d5/solve_big_rational_gaussian,100,2589614.1044999994,2585300.4184999997,2594393.1593875,2584494.8,2580709.4000000004,2586922.9,0.95 +current,rational_input_wide1024_d5/solve_row_cleared_bareiss,100,99326.1345570528,99110.056625808,99588.35578440878,99106.48181818181,99062.59130434782,99212.40777777777,0.95 +current,rational_input_wide1024_d6/det_big_rational_gaussian,100,4057155.7346153837,4051405.175519231,4063171.9544230765,4053189.076923077,4045362.153846154,4061708.3076923075,0.95 +current,rational_input_wide1024_d6/det_row_cleared_bareiss,100,308078.16564853693,307581.3947533202,308673.8498635387,307589.6798650568,307438.5080645161,307771.6979166667,0.95 +current,rational_input_wide1024_d6/det_sign_row_cleared_bareiss,100,108349.88061168011,108118.37378861768,108552.53378834018,108458.80404554264,108309.14032258064,108672.22222222222,0.95 +current,rational_input_wide1024_d6/solve_big_rational_gaussian,100,4657774.466363638,4648068.668772726,4669403.295159088,4648240.5,4644424.272727273,4652428.090909091,0.95 +current,rational_input_wide1024_d6/solve_row_cleared_bareiss,100,221049.31005129032,220211.47801716177,222146.8335598597,220382.94125615765,219966.69859068628,220569.66873040755,0.95 +current,rational_input_wide1024_d7/det_big_rational_gaussian,100,6677420.30875,6671186.2494375,6683619.1429375,6683390.625,6674552.125,6687427.125,0.95 +current,rational_input_wide1024_d7/det_row_cleared_bareiss,100,512932.29556433554,512469.8073140853,513423.3705654076,512914.70192307694,512460.5714285714,513490.13620448177,0.95 +current,rational_input_wide1024_d7/det_sign_row_cleared_bareiss,100,239371.37805995144,238929.24354760282,239825.026969891,238958.289498645,238517.21333333335,239342.70091036416,0.95 +current,rational_input_wide1024_d7/solve_big_rational_gaussian,100,7496077.792857141,7489020.581964286,7503058.949464289,7498595.285714285,7491375.0,7507235.142857143,0.95 +current,rational_input_wide1024_d7/solve_row_cleared_bareiss,100,452615.96961960726,451977.245060443,453349.4294244627,452967.51515151514,452191.25078468304,453225.8216156062,0.95 +current,rational_input_wide1024_d8/det_big_rational_gaussian,100,11151693.076,10779064.385150002,11547944.159000002,10281091.7,10272612.5,10293625.0,0.95 +current,rational_input_wide1024_d8/det_row_cleared_bareiss,100,846418.7426930038,843304.2491035553,850389.0360025405,840203.7490131579,839563.8125,841293.0927419355,0.95 +current,rational_input_wide1024_d8/det_sign_row_cleared_bareiss,100,486885.0468407199,484876.0848845517,488985.3307797821,483048.2032520325,481014.97781385283,486324.28643578646,0.95 +current,rational_input_wide1024_d8/solve_big_rational_gaussian,100,11273256.092,11260478.608699996,11286384.218150001,11274575.0,11252258.4,11285441.7,0.95 +current,rational_input_wide1024_d8/solve_row_cleared_bareiss,100,855177.3680407443,854418.6984566053,855974.187232201,854902.1010273972,854465.1951219512,855552.0833333333,0.95 +current,rational_input_wide256_d2/det_big_rational_gaussian,100,45782.14824461704,45730.317944846574,45838.46684540641,45734.679881198346,45693.30970724191,45770.22231182796,0.95 +current,rational_input_wide256_d2/det_row_cleared_bareiss,100,9463.235989354656,9422.50990869079,9504.000274115762,9515.2565073051,9382.292268479185,9560.294748553628,0.95 +current,rational_input_wide256_d2/det_sign_row_cleared_bareiss,100,983.3788145824038,978.1208299910112,989.0402114509035,978.3079032011332,974.0586645952244,985.2033918153558,0.95 +current,rational_input_wide256_d2/solve_big_rational_gaussian,100,50479.327373037544,50405.0563014678,50560.35982436801,50379.426875000005,50323.766343825664,50462.10372596154,0.95 +current,rational_input_wide256_d2/solve_row_cleared_bareiss,100,3285.6986196000553,3274.9629066178786,3300.2337879511165,3278.760148912608,3269.910506644518,3285.941837709917,0.95 +current,rational_input_wide256_d3/det_big_rational_gaussian,100,139138.23772422,138986.0887608544,139302.11792772365,138974.78518356645,138845.00578703702,139067.87109375,0.95 +current,rational_input_wide256_d3/det_row_cleared_bareiss,100,14794.041393066982,14775.058382833846,14813.083578791015,14792.754801920768,14773.34228776738,14805.592245989305,0.95 +current,rational_input_wide256_d3/det_sign_row_cleared_bareiss,100,4052.0751485084893,4044.124434053046,4060.026180422318,4054.7996323317047,4042.538041193779,4057.478293867638,0.95 +current,rational_input_wide256_d3/solve_big_rational_gaussian,100,173102.93026626296,172764.90446535303,173484.51813103413,172897.1749025341,172760.80929657124,173100.65979381444,0.95 +current,rational_input_wide256_d3/solve_row_cleared_bareiss,100,10463.617002337503,10440.07892783004,10490.774406935163,10448.38634672619,10437.222506830602,10457.728623670213,0.95 +current,rational_input_wide256_d4/det_big_rational_gaussian,100,342625.0064344684,341707.48532250675,343630.8599460969,341022.003875969,340608.4950918964,341896.47063358565,0.95 +current,rational_input_wide256_d4/det_row_cleared_bareiss,100,24342.84371189919,24316.581744980595,24370.312980254817,24325.875962772785,24296.18060415719,24353.288237886307,0.95 +current,rational_input_wide256_d4/det_sign_row_cleared_bareiss,100,8605.825822329663,8551.607487161566,8668.64296285179,8538.680766776746,8513.538461538461,8593.869731800767,0.95 +current,rational_input_wide256_d4/solve_big_rational_gaussian,100,427312.50493931654,426854.7650188405,427791.7683951142,427055.30202020204,426403.7738095238,427494.1403508772,0.95 +current,rational_input_wide256_d4/solve_row_cleared_bareiss,100,24959.663889950454,24930.937183651527,24989.693566764257,24951.090587460487,24913.99961050725,24989.316145833334,0.95 +current,rational_input_wide256_d5/det_big_rational_gaussian,100,621114.5694374666,580479.6321906921,664805.2317824921,516383.8348765432,515674.5648734177,519065.8880078773,0.95 +current,rational_input_wide256_d5/det_row_cleared_bareiss,100,41118.345118208345,40886.930276956766,41331.21526688436,41305.52491728701,41271.920814479636,41340.31295518839,0.95 +current,rational_input_wide256_d5/det_sign_row_cleared_bareiss,100,17447.47126105116,17392.0858330875,17506.324719843185,17369.459756459757,17295.561974789915,17435.252627712478,0.95 +current,rational_input_wide256_d5/solve_big_rational_gaussian,100,645591.1213229265,644633.5787197206,646709.9567786139,644606.1008522727,644355.0347222222,645226.8541666666,0.95 +current,rational_input_wide256_d5/solve_row_cleared_bareiss,100,45221.91351791252,45183.06804167478,45273.880783211825,45169.80664083816,45144.44202226345,45234.88058551618,0.95 +current,rational_input_wide256_d6/det_big_rational_gaussian,100,950377.7916940759,949406.6614589851,951385.6048549474,950624.8716653963,949434.5267857143,951451.5810810811,0.95 +current,rational_input_wide256_d6/det_row_cleared_bareiss,100,58209.072299775675,58122.054053423555,58297.72697615934,58181.68802521008,58096.25668449198,58254.67738970588,0.95 +current,rational_input_wide256_d6/det_sign_row_cleared_bareiss,100,31992.230209756577,31946.935788665276,32041.179076326633,31961.819894271226,31922.14945425473,32002.78870967742,0.95 +current,rational_input_wide256_d6/solve_big_rational_gaussian,100,1172980.4739742982,1169717.7335354579,1176722.1975143573,1168363.247368421,1167162.0444444444,1169617.2990196077,0.95 +current,rational_input_wide256_d6/solve_row_cleared_bareiss,100,86543.01235500889,86367.58857191575,86740.3642834307,86362.94418861669,86134.84093315183,86533.66060232872,0.95 +current,rational_input_wide256_d7/det_big_rational_gaussian,100,1599985.858798833,1598258.1059774437,1601801.2753211798,1600175.5001755003,1597186.46996997,1600978.8767123288,0.95 +current,rational_input_wide256_d7/det_row_cleared_bareiss,100,92486.66278657541,92215.01644520591,92795.05542896823,92180.41014869438,92003.07125307125,92317.8021149582,0.95 +current,rational_input_wide256_d7/det_sign_row_cleared_bareiss,100,59120.32005627835,58981.870479228026,59272.31051052008,59060.74442469295,58936.882352941175,59149.40033479732,0.95 +current,rational_input_wide256_d7/solve_big_rational_gaussian,100,1944060.5994251508,1941119.353545171,1947358.6595196067,1941311.887254902,1937525.4444444445,1947114.5,0.95 +current,rational_input_wide256_d7/solve_row_cleared_bareiss,100,160413.3947326216,159943.87173881003,160913.1269494092,160051.62441130297,159353.86256031934,160598.2142857143,0.95 +current,rational_input_wide256_d8/det_big_rational_gaussian,100,2770593.1025000005,2662289.1753500006,2887405.4459374985,2507776.025,2504433.3,2514862.5,0.95 +current,rational_input_wide256_d8/det_row_cleared_bareiss,100,145945.87585859385,145332.21219069586,146620.601095857,144563.46516290726,144306.25274725276,144774.8917748918,0.95 +current,rational_input_wide256_d8/det_sign_row_cleared_bareiss,100,103502.39896226855,103217.9719917848,103809.5857621113,103173.261065944,102978.99154929578,103336.51738735766,0.95 +current,rational_input_wide256_d8/solve_big_rational_gaussian,100,2968085.2205882347,2965157.099749999,2971004.5403088224,2969163.0,2965943.6470588236,2972621.323529412,0.95 +current,rational_input_wide256_d8/solve_row_cleared_bareiss,100,283023.1568032561,282603.0913978558,283503.401477486,282319.1734370281,282154.7815423977,282788.4972826087,0.95 diff --git a/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.provenance.json b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.provenance.json new file mode 100644 index 0000000..8a53493 --- /dev/null +++ b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.full.provenance.json @@ -0,0 +1,132 @@ +{ + "benchmark_provenance": { + "baseline": "v0.4.5", + "criterion": { + "baseline_command": [ + "just", + "bench-save-baseline", + "v0.4.5" + ], + "criterion_version": "0.8.2", + "current_command": [ + "just", + "bench-latest" + ], + "sample": "new", + "scope": "release-signal", + "statistic": "median", + "suite": "all" + }, + "current": "v0.4.6", + "measurement": { + "baseline_api_compatibility": "la_stack_pre_rational_input_api", + "baseline_commit": "78ba1c25beaed7321e175113e0876aac6d763a59", + "baseline_git_clean": false, + "baseline_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", + "benchmark_contract_sha256": "02a2228e7c2150d4c9c2dc125063a6e3eec03be82e8f7262c341099f2517132d", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", + "cpu": "Apple M4 Max (arm64)", + "current_commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "current_git_clean": false, + "current_source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336", + "harness_sha256": "27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3", + "os": "Darwin 25.6.0 arm64", + "rustc": "rustc 1.98.1 (48a229cea 2026-09-01)", + "status": "recorded" + }, + "mode": "shared-current-harness", + "publication": { + "benchmark_contract_sha256": "02a2228e7c2150d4c9c2dc125063a6e3eec03be82e8f7262c341099f2517132d", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", + "commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "correctness_gate": "passed", + "cpu": "Apple M4 Max (arm64)", + "git_clean": false, + "harness_sha256": "27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3", + "os": "Darwin 25.6.0 arm64", + "rustc": "rustc 1.98.1 (48a229cea 2026-09-01)", + "source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336" + }, + "schema": 2, + "validation": { + "baseline_api_compatibility": "la_stack_pre_rational_input_api", + "baseline_commit": "78ba1c25beaed7321e175113e0876aac6d763a59", + "baseline_git_clean": false, + "baseline_revision": "passed", + "baseline_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", + "command": [ + "just", + "test-bench-inputs" + ], + "current_commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "current_git_clean": false, + "current_revision": "passed", + "current_source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336", + "harness": "shared-current", + "shared_harness_rational_inputs": true + } + }, + "csv": { + "columns": [ + "schema_version", + "suite", + "scope", + "benchmark_id", + "group", + "benchmark", + "baseline_benchmark", + "coverage_status", + "coverage_note", + "baseline_median_ns", + "baseline_ci_lower_ns", + "baseline_ci_upper_ns", + "current_median_ns", + "current_ci_lower_ns", + "current_ci_upper_ns", + "baseline_nalgebra_median_ns", + "baseline_nalgebra_ci_lower_ns", + "baseline_nalgebra_ci_upper_ns", + "baseline_faer_median_ns", + "baseline_faer_ci_lower_ns", + "baseline_faer_ci_upper_ns" + ], + "row_count": 225, + "sha256": "b263bb34bcfd43b8fc8109110db9f2e908516aef6c01ce16f70f5ac18dc7ef2d" + }, + "measurements": { + "columns": [ + "phase", + "benchmark_id", + "sample_count", + "mean_ns", + "mean_ci_lower_ns", + "mean_ci_upper_ns", + "median_ns", + "median_ci_lower_ns", + "median_ci_upper_ns", + "confidence_level" + ], + "counts": { + "baseline": 510, + "current": 445 + }, + "schema_version": 1, + "sha256": "4fa5cc13159f5dc91e711ae67554845bcbd1ace2cfc3e31487fc85f75d3dc459" + }, + "release": { + "baseline": "v0.4.5", + "current": "v0.4.6" + }, + "report": { + "scope": "release-signal", + "source": { + "commit": "d36a9e9", + "ref": "HEAD", + "revision_timestamp": "2026-09-08 01:59:08 UTC", + "version": "0.4.6" + }, + "statistic": "median", + "suite": "all" + }, + "schema_version": 1 +} diff --git a/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.provenance.json b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.provenance.json new file mode 100644 index 0000000..9417dd9 --- /dev/null +++ b/docs/performance/v0.4.6-vs-v0.4.5/39719a1eb599d294dbbc1e46dc6fb0de2028ad2e59aab5f94fb48c7bf3d7f841/performance.provenance.json @@ -0,0 +1,112 @@ +{ + "benchmark_provenance": { + "baseline": "v0.4.5", + "criterion": { + "baseline_command": [ + "just", + "bench-save-baseline", + "v0.4.5" + ], + "criterion_version": "0.8.2", + "current_command": [ + "just", + "bench-latest" + ], + "sample": "new", + "scope": "release-signal", + "statistic": "median", + "suite": "all" + }, + "current": "v0.4.6", + "measurement": { + "baseline_api_compatibility": "la_stack_pre_rational_input_api", + "baseline_commit": "78ba1c25beaed7321e175113e0876aac6d763a59", + "baseline_git_clean": false, + "baseline_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", + "benchmark_contract_sha256": "02a2228e7c2150d4c9c2dc125063a6e3eec03be82e8f7262c341099f2517132d", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", + "cpu": "Apple M4 Max (arm64)", + "current_commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "current_git_clean": false, + "current_source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336", + "harness_sha256": "27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3", + "os": "Darwin 25.6.0 arm64", + "rustc": "rustc 1.98.1 (48a229cea 2026-09-01)", + "status": "recorded" + }, + "mode": "shared-current-harness", + "publication": { + "benchmark_contract_sha256": "02a2228e7c2150d4c9c2dc125063a6e3eec03be82e8f7262c341099f2517132d", + "cargo_lock_sha256": "37c6f3339dc4eedcc5587e44133a7d0299fef2bd9da52fc0464e2ceeb0138edb", + "commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "correctness_gate": "passed", + "cpu": "Apple M4 Max (arm64)", + "git_clean": false, + "harness_sha256": "27acd15e854e46899ff1c1f8e1b399ff240b0b9732e56a36cf8edb39c4a58db3", + "os": "Darwin 25.6.0 arm64", + "rustc": "rustc 1.98.1 (48a229cea 2026-09-01)", + "source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336" + }, + "schema": 2, + "validation": { + "baseline_api_compatibility": "la_stack_pre_rational_input_api", + "baseline_commit": "78ba1c25beaed7321e175113e0876aac6d763a59", + "baseline_git_clean": false, + "baseline_revision": "passed", + "baseline_source_state_sha256": "7d72086128b12e2a89d5ca78f0e8cc0cb393a44f1062d027a069722ff9dae007", + "command": [ + "just", + "test-bench-inputs" + ], + "current_commit": "d36a9e99ec223c4cbbf8a9191818f186159c27f7", + "current_git_clean": false, + "current_revision": "passed", + "current_source_state_sha256": "b8fcf706fa6e287ca6682a1ecef5a69576413b9c88040184a9b1ecb8f6e92336", + "harness": "shared-current", + "shared_harness_rational_inputs": true + } + }, + "csv": { + "columns": [ + "schema_version", + "suite", + "scope", + "benchmark_id", + "group", + "benchmark", + "baseline_benchmark", + "coverage_status", + "coverage_note", + "baseline_median_ns", + "baseline_ci_lower_ns", + "baseline_ci_upper_ns", + "current_median_ns", + "current_ci_lower_ns", + "current_ci_upper_ns", + "baseline_nalgebra_median_ns", + "baseline_nalgebra_ci_lower_ns", + "baseline_nalgebra_ci_upper_ns", + "baseline_faer_median_ns", + "baseline_faer_ci_lower_ns", + "baseline_faer_ci_upper_ns" + ], + "row_count": 225, + "sha256": "b263bb34bcfd43b8fc8109110db9f2e908516aef6c01ce16f70f5ac18dc7ef2d" + }, + "release": { + "baseline": "v0.4.5", + "current": "v0.4.6" + }, + "report": { + "scope": "release-signal", + "source": { + "commit": "d36a9e9", + "ref": "HEAD", + "revision_timestamp": "2026-09-08 01:59:08 UTC", + "version": "0.4.6" + }, + "statistic": "median", + "suite": "all" + }, + "schema_version": 1 +} diff --git a/docs/roadmap.md b/docs/roadmap.md index 0e8260c..f967dc9 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -7,10 +7,11 @@ is tracked as GitHub issues; keep this document focused on release direction, ordering, and non-goals. Until v1.0, API breaks are acceptable when they improve correctness, -performance, or orthogonality. The `v0.4.x` line should stay on stable Rust and -focus on documentation, downstream ergonomics, API-contract cleanup, validation, -invariant audits, benchmark coverage, and release/tooling hardening. The -`v0.5.0` line is reserved for work that depends on stabilized +performance, or orthogonality. The `v0.4.x` line stays on stable Rust and includes +focused robustness APIs, downstream ergonomics, API-contract cleanup, +documentation, validation, invariant audits, benchmark coverage, and +release/tooling hardening. The current release is `v0.4.6`. +The `v0.5.0` line is reserved for work that depends on stabilized `generic_const_exprs` or equivalent const-generic expressiveness. ## Scalar Scope @@ -174,6 +175,65 @@ bounds, exact fallbacks, and typed non-finite behavior remain authoritative. Any future approximate or fast-math API requires a separate opt-in design and correctness analysis. +### v0.4.6 Exact Inputs and Certified Bounds (released) + +This milestone extends robustness-sensitive workflows on stable Rust while +preserving fixed dimensions, `f64` floating-point storage, and feature-isolated +exact arithmetic. + +Completed capability work: + +- Certified dot-product and affine-difference bounds + ([#220](https://github.com/acgetchell/la-stack/issues/220)) support sign and + threshold decisions over stored coordinates, with explicit inconclusive + outcomes when a certificate is unavailable or overlaps the threshold. +- Exact rational matrix and vector inputs + ([#216](https://github.com/acgetchell/la-stack/issues/216)) preserve rational + expressions before `f64` rounding and provide exact determinants and solves + with explicit strict or rounded output conversion. +- Gram matrix construction + ([#219](https://github.com/acgetchell/la-stack/issues/219)) accepts fixed + vectors with independent const-generic input and output dimensions. The + floating-point result is symmetric but is not a definiteness certificate. +- Interval expressions and determinant signs + ([#218](https://github.com/acgetchell/la-stack/issues/218)) preserve outward + bounds through determinant evaluation up to D=7, distinguish exact zero from + inconclusive overlap, and report range exhaustion explicitly. +- Overflow-safe Euclidean norms + ([#217](https://github.com/acgetchell/la-stack/issues/217)) avoid unnecessary + overflow and underflow from squaring coordinates. Norm results remain + approximate, without a certified error bound. + +Performance and tooling outcomes: + +- Benchmark release budgets and baseline validation + ([#224](https://github.com/acgetchell/la-stack/issues/224)), attachment before + immutable publication ([#225](https://github.com/acgetchell/la-stack/issues/225)), + and cache isolation ([#226](https://github.com/acgetchell/la-stack/issues/226)) + now form one documented release workflow. +- Exact rational conversion and dense 4D determinant paths avoid redundant + arithmetic while preserving exact results and typed conversion errors. +- Rational row-clearing measurements + ([#233](https://github.com/acgetchell/la-stack/issues/233)) support retaining + the existing borrowed component access; see the + [allocation study](archive/performance/studies/rational-row-clearing.md). LU/LDLT solve + finalization remains unchanged because its proposed replacement showed no + repeatable speedup ([#234](https://github.com/acgetchell/la-stack/issues/234)); + see the [decision report](archive/performance/studies/solve-finalization.md). +- Tooling uses Rust 1.98.1 and Python 3.14, reconciles managed tool pins, rejects + ambiguous updater output, and verifies the installed Cargo upgrade tool + through its supported version command during setup. + +Intentional compatibility changes include requiring Rust 1.98.1, +`Vector::norm2_sq()` becoming `Vector::norm_squared()`, +`Matrix::inf_norm()` becoming `Matrix::norm_inf()`, +and `Matrix::solve_exact()` returning `RationalVector` instead of a raw +rational array. `Vector::norm()` names the new Euclidean norm; raw exact solution +storage remains available through `as_array()` and `into_array()`. + +Further stable-Rust maintenance can remain in `v0.4.x`; it does not depend on +the language stabilization reserved for `v0.5.0`. + ### v0.5.0 Generic Const Expressions `v0.5.0` is reserved for the post-stabilization const-generic API revision. diff --git a/justfile b/justfile index baa4246..0f370d7 100644 --- a/justfile +++ b/justfile @@ -249,7 +249,7 @@ action-lint: _ensure-actionlint # Benchmarks bench: - cargo bench --locked --features bench + cargo bench --locked --workspace --features bench # Compare latest measurements against a saved baseline. # Defaults to the `last` full-release baseline. @@ -263,7 +263,7 @@ bench-compare baseline="last" suite="all" scope="release-signal": python-sync # Cargo so warning policy does not create separate rustc cache artifacts. # This catches bench/release-profile-only warnings that won't show up in normal debug-profile runs. bench-compile: - CARGO_BUILD_WARNINGS=deny cargo bench --locked --no-run --features bench + CARGO_BUILD_WARNINGS=deny cargo bench --locked --workspace --no-run --features bench CARGO_BUILD_WARNINGS=deny cargo bench --locked --no-run --features bench,exact --bench exact # Run the exact-arithmetic benchmark suite. @@ -300,14 +300,14 @@ bench-save-baseline tag suite="all": suite={{ quote(suite) }} case "$suite" in all) - cargo bench --locked --features bench --bench vs_linalg -- --save-baseline {{ quote(tag) }} - cargo bench --locked --features bench,exact --bench exact -- --save-baseline {{ quote(tag) }} + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- --noplot --save-baseline {{ quote(tag) }} + cargo bench --locked --features bench,exact --bench exact -- --noplot --save-baseline {{ quote(tag) }} ;; exact) - cargo bench --locked --features bench,exact --bench exact -- --save-baseline {{ quote(tag) }} + cargo bench --locked --features bench,exact --bench exact -- --noplot --save-baseline {{ quote(tag) }} ;; vs_linalg) - cargo bench --locked --features bench --bench vs_linalg -- --save-baseline {{ quote(tag) }} + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- --noplot --save-baseline {{ quote(tag) }} ;; *) echo "unknown benchmark suite: $suite" >&2 @@ -325,14 +325,15 @@ bench-vs-linalg filter="": set -euo pipefail filter={{ quote(filter) }} if [ -n "$filter" ]; then - cargo bench --locked --features bench --bench vs_linalg -- "$filter" + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- "$filter" else - cargo bench --locked --features bench --bench vs_linalg + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg fi # Bench only la-stack rows from the vs_linalg suite for cheap latest-vs-last comparisons. +# Filtered runs omit peer samples, so disable Criterion's complete-group HTML reports. bench-vs-linalg-la-stack: - cargo bench --locked --features bench --bench vs_linalg -- la_stack + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- la_stack --noplot # Run only la-stack vs_linalg measurements and render a non-exact performance report. bench-vs-linalg-latest-vs baseline="last": bench-vs-linalg-la-stack python-sync @@ -344,9 +345,9 @@ bench-vs-linalg-quick filter="": set -euo pipefail filter={{ quote(filter) }} if [ -n "$filter" ]; then - cargo bench --locked --features bench --bench vs_linalg -- "$filter" --quick --noplot + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- "$filter" --quick --noplot else - cargo bench --locked --features bench --bench vs_linalg -- --quick --noplot + cargo bench --locked -p la-stack-comparison --features bench --bench vs_linalg -- --quick --noplot fi # Build commands @@ -622,7 +623,7 @@ markdown-fix: _ensure-rumdl markdown-lint: markdown-check -# Build and promote release performance docs from retained report inputs. +# Build release docs from retained scratch inputs or the latest docs/performance snapshot. performance-doc: python-sync uv run --locked archive-performance --promote-artifacts @@ -662,7 +663,7 @@ performance-local-non-exact current_tag="" baseline_tag="": _ensure-gh python-sy uv run --locked archive-performance --current-vs-latest --suite vs_linalg --generate-in-temp-worktree --output-only --local-report --output target/bench-reports/performance-non-exact.md --artifact-csv target/bench-reports/performance-non-exact.csv --artifact-provenance target/bench-reports/performance-non-exact.provenance.json fi -# Validate retained release measurements and atomically publish the canonical README assets/table. +# Publish README assets/table from retained measurements, including after target cleanup. performance-readme metric="lu_solve" stat="median" sample="new" log_y="true": python-sync #!/usr/bin/env bash set -euo pipefail @@ -672,7 +673,7 @@ performance-readme metric="lu_solve" stat="median" sample="new" log_y="true": py fi uv run --locked criterion-dim-plot "${args[@]}" -# Generate local release-signal measurements in a temp worktree, then promote/archive docs. +# Measure locally, preserve complete summaries in docs/performance, and promote/archive docs. performance-release current_tag="" baseline_tag="": _ensure-gh python-sync #!/usr/bin/env bash set -euo pipefail @@ -778,6 +779,9 @@ setup-tools: cargo-nextest) cargo nextest --version 2>/dev/null ;; + cargo-upgrade) + cargo upgrade --version 2>/dev/null + ;; *) "$1" --version 2>/dev/null ;; @@ -982,7 +986,7 @@ test-all: test-rust test-python # Smoke-test deterministic inputs and configuration shared with benchmark suites. test-bench-inputs: _ensure-cargo-nextest - cargo nextest run --profile ci --features bench,exact --test vs_linalg_inputs --test exact_bench_config --verbose + cargo nextest run --workspace --profile ci --features bench,exact --test vs_linalg_inputs --test exact_bench_config --verbose test-doc: cargo test --doc --verbose @@ -1012,7 +1016,7 @@ test-rust: test-rust-ci test-doc test-doc-exact # CI Rust bucket: all runnable unit/integration targets in one nextest pass. test-rust-ci: _ensure-cargo-nextest - cargo nextest run --release --profile ci --all-features --lib --tests --verbose + cargo nextest run --workspace --release --profile ci --all-features --lib --tests --verbose test-unit: test-lib diff --git a/pyproject.toml b/pyproject.toml index 9eb400a..69294c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "la-stack-scripts" -version = "0.4.5" +version = "0.4.6" description = "Python utility scripts for the la-stack Rust library" readme = "scripts/README.md" requires-python = ">=3.14" @@ -48,7 +48,7 @@ update-python-dev-pins = "update_python_dev_pins:main" # Configure setuptools to find modules in scripts/ directory. [tool.setuptools] package-dir = { "" = "scripts" } -py-modules = [ "archive_changelog", "archive_performance", "bench_compare", "benchmark_contract", "check_docs_version_sync", "check_semgrep_fixtures", "criterion_dim_plot", "performance_artifacts", "postprocess_changelog", "subprocess_utils", "tag_release", "update_cargo_tool_pins", "update_python_dev_pins", "update_release_version" ] +py-modules = [ "archive_changelog", "archive_performance", "bench_compare", "benchmark_contract", "benchmark_summaries", "check_docs_version_sync", "check_semgrep_fixtures", "criterion_dim_plot", "criterion_measurements", "performance_artifacts", "postprocess_changelog", "subprocess_utils", "tag_release", "update_cargo_tool_pins", "update_python_dev_pins", "update_release_version" ] [tool.ruff] line-length = 160 @@ -96,8 +96,10 @@ known-first-party = [ "archive_performance", "bench_compare", "benchmark_contract", + "benchmark_summaries", "check_semgrep_fixtures", "criterion_dim_plot", + "criterion_measurements", "performance_artifacts", "postprocess_changelog", "subprocess_utils", @@ -158,6 +160,6 @@ dev = [ "semgrep==1.176.1", "shellcheck-py==0.11.0.1", "shfmt-py==4.2.0", - "ty==0.0.78", + "ty==0.0.79", "yamllint==1.38.0", ] diff --git a/scripts/README.md b/scripts/README.md index 3bda321..31c316f 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -60,6 +60,9 @@ Use the top-level `just` workflows for routine release and local comparisons: for the repository because it downloads release assets. Local-generation recipes require `gh` only when discovering published release tags. +New release comparisons require v0.4.4 or newer on both sides. v0.4.3 and older +are excluded; historical Markdown reports remain available in the archive. + ```bash # Local development: compare the current tree with the latest release just performance-local @@ -88,17 +91,29 @@ harness. Reports record source-state, environment, toolchain, dependency, Criterion, harness, and validation provenance and fail on incomplete selected coverage. `performance-local` writes Markdown plus schema-versioned `performance.csv` and `performance.provenance.json` inputs under -`target/bench-reports/` without promoting documentation. `performance-release` -does the same measurement and retention work, requires distinct releases, and -promotes the validated result. `performance-doc` consumes the retained pair +`target/bench-reports/`, plus `performance.full.csv` and its provenance JSON +containing every recorded case from both measurement phases. +`performance-release` does the same measurement work, requires distinct releases, +and preserves all four files under `docs/performance///` +when promoting the validated result. `performance-doc` consumes the retained pair from either workflow without Cargo or temporary worktrees, then promotes the result into `docs/performance.md` and the archive. Same-version local artifacts remain valid comparison evidence but cannot be promoted as a release report. -These files are reproducible scratch and may be removed with `target/`; native -Criterion release archives remain the durable raw baselines. Direct comparisons +Scratch files may be removed with `target/`. After cleanup, `performance-doc` and +`performance-readme` resolve `docs/performance/latest.json` to the most recently +promoted complete snapshot. Existing partial scratch inputs fail validation. +The [local summary index](../docs/performance/README.md) owns the saved-data +schema and retention contract. Native Criterion release archives remain the +durable raw baselines from the GitHub runner. Direct comparisons of separately published artifacts retain their original per-release harnesses and label unavailable historical measurement metadata explicitly. +The comparison suite lives in the unpublished `benches/comparison` package, so +exact benchmark builds do not compile nalgebra/faer. Local release comparisons +measure la-stack on each revision and reuse peer measurements from the baseline +phase. The filtered current run skips Criterion HTML generation to avoid reading +missing `new` samples for peers that were not rerun. + Operationally, `performance-release` is the atomic composition of `performance-local` and `performance-doc`: measure, retain the common comparison inputs, render, and promote. The narrowed @@ -156,7 +171,8 @@ just performance-readme lu_solve median new true ``` The README recipe consumes `target/bench-reports/performance.csv` and its -adjacent provenance JSON; it does not run the benchmark-input gate or Criterion +adjacent provenance JSON, or the latest committed snapshot after cleanup; +it does not run the benchmark-input gate or Criterion again. It uses the current la-stack timing and retained same-current-harness nalgebra/faer timings, requires all three at every canonical dimension, and then publishes CSV, SVG, derived JSON provenance, the README table, and its tag-pinned @@ -262,7 +278,12 @@ just changelog-unreleased vX.Y.Z `just changelog` runs `git-cliff -o CHANGELOG.md`, strips trailing blank lines, archives completed changelog series, and formats the generated Markdown. -Configuration lives in `cliff.toml` at the repo root. +Configuration lives in `cliff.toml` at the repo root. The Breaking Changes +summary preserves full `BREAKING CHANGE` footer descriptions, including compiler +requirements and migration instructions; commits marked only with `!` fall back +to their subject. Post-processing escapes HTML in breaking-description prose +while preserving literal Rust syntax in Markdown code spans and fenced blocks, +and adds merged-PR summaries without replacing those descriptions. ### Creating a release tag @@ -283,8 +304,10 @@ validates SemVer, and handles GitHub's 125KB tag-annotation size limit. | `archive_performance.py` | Promote release performance docs and archive older comparisons | | `performance_artifacts.py` | Validate and publish schema-versioned performance-comparison CSV/JSON inputs | | `bench_compare.py` | Compare Criterion benchmark baselines and render Markdown reports | +| `benchmark_summaries.py` | Preserve every local case summary, bind provenance, and resolve saved report inputs after cleanup | | `check_docs_version_sync.py` | Verify versioned documentation links and snippets stay synchronized | | `criterion_dim_plot.py` | Plot Criterion benchmark results (CSV + SVG + README table) | +| `criterion_measurements.py` | Validate full Criterion sampling and estimates for local summaries and hosted archives | | `tag_release.py` | Create annotated git tags from CHANGELOG.md sections | | `postprocess_changelog.py` | Normalize and reflow generated git-cliff Markdown safely | | `release_baseline.py` | Inventory full Criterion suites and validate complete raw release baselines before packaging | diff --git a/scripts/archive_performance.py b/scripts/archive_performance.py index 253097f..755d0d4 100644 --- a/scripts/archive_performance.py +++ b/scripts/archive_performance.py @@ -1,13 +1,15 @@ #!/usr/bin/env -S uv run --locked """Generate, retain, render, and promote benchmark comparison reports. -Release performance docs have two different lifetimes: +Release performance outputs have distinct lifetimes: - ``target/bench-reports/performance.md`` is local scratch output for the current machine and branch. - ``target/bench-reports/performance.csv`` and the adjacent provenance JSON are validated, reproducible performance-comparison inputs. - ``docs/performance.md`` is the latest curated release-to-release comparison. + - ``docs/performance///`` preserves complete local + summaries and the selected report inputs across target cleanup. - ``docs/archive/performance/*.md`` stores older curated comparisons. This script renders from a validated artifact reload, copies the result into @@ -28,14 +30,15 @@ import tempfile import tomllib from collections.abc import Iterator, Mapping -from contextlib import contextmanager -from dataclasses import dataclass +from contextlib import ExitStack, contextmanager +from dataclasses import dataclass, replace from datetime import UTC, datetime from pathlib import Path from typing import Any, Literal, cast from bench_compare import HOW_TO_UPDATE_SECTION, render_release_artifacts from benchmark_contract import benchmark_contract_digest +from benchmark_summaries import report_input_paths, resolve_report_paths, retained_outputs, summary_outputs from performance_artifacts import ( NO_API_COMPATIBILITY, ArtifactPaths, @@ -75,7 +78,8 @@ _BENCH_TIMEOUT_SECONDS = 7200 _COMMAND_TIMEOUT_SECONDS = 600 _HOW_TO_UPDATE_RE = re.compile(r"(?ms)^## How to Update\n.*\Z") -_BENCHMARK_HARNESS_DIRS = ("benches",) +# Cargo validates declared example paths even when only benchmark tests are selected. +_BENCHMARK_HARNESS_DIRS = ("benches", "examples") _BENCHMARK_HARNESS_FILES = ( ".config/nextest.toml", "Cargo.toml", @@ -83,7 +87,6 @@ "rust-toolchain.toml", "justfile", "tests/exact_bench_config.rs", - "tests/vs_linalg_inputs.rs", ) _BENCHMARK_HARNESS_METADATA = ".la-stack-benchmark-harness.json" _BENCHMARK_INPUT_GATE = ("just", "test-bench-inputs") @@ -116,6 +119,7 @@ class PromotionRequest: source_path: Path | None = None output: Path | None = None reserved_paths: Mapping[str, Path] | None = None + retained_outputs: Mapping[Path, str] | None = None @dataclass(frozen=True) @@ -139,6 +143,11 @@ def __post_init__(self) -> None: if self.scope not in _SUPPORTED_SCOPES: msg = f"unsupported comparison scope: {self.scope}" raise ValueError(msg) + resolve_shared_harness_compatibility( + current=self.current_tag, + baseline=self.baseline_tag, + shared_harness_rational_inputs=False, + ) @dataclass(frozen=True, slots=True) @@ -436,8 +445,7 @@ def _replace_file(src: Path, dst: Path) -> None: def _write_text(path: Path, text: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) - tmp_path: Path | None = None - try: + with ExitStack() as cleanup: with tempfile.NamedTemporaryFile( "w", encoding="utf-8", @@ -448,13 +456,11 @@ def _write_text(path: Path, text: str) -> None: delete=False, ) as tmp: tmp_path = Path(tmp.name) + cleanup.callback(tmp_path.unlink, missing_ok=True) tmp.write(text) tmp.flush() os.fsync(tmp.fileno()) _replace_file(tmp_path, path) - finally: - if tmp_path is not None and tmp_path.exists(): - tmp_path.unlink() def _restore_file(path: Path, payload: bytes | None) -> None: @@ -463,8 +469,7 @@ def _restore_file(path: Path, payload: bytes | None) -> None: path.unlink(missing_ok=True) return path.parent.mkdir(parents=True, exist_ok=True) - restore_path: Path | None = None - try: + with ExitStack() as cleanup: with tempfile.NamedTemporaryFile( "wb", dir=path.parent, @@ -473,13 +478,11 @@ def _restore_file(path: Path, payload: bytes | None) -> None: delete=False, ) as tmp: restore_path = Path(tmp.name) + cleanup.callback(restore_path.unlink, missing_ok=True) tmp.write(payload) tmp.flush() os.fsync(tmp.fileno()) restore_path.replace(path) - finally: - if restore_path is not None: - restore_path.unlink(missing_ok=True) def _snapshot_regular_file(path: Path, *, label: str) -> bytes | None: @@ -511,6 +514,22 @@ def _restore_snapshots(snapshots: tuple[tuple[Path, bytes | None], ...]) -> tupl return tuple(errors) +@contextmanager +def _publish_text_outputs(outputs: Mapping[Path, str]) -> Iterator[None]: + """Retain complete scratch summaries with the report's rollback boundary.""" + snapshots = tuple((path, _snapshot_regular_file(path, label="benchmark summary")) for path in outputs) + try: + for path, text in outputs.items(): + _write_text(path, text) + yield + except BaseException as error: + failures = _restore_snapshots(snapshots) + if failures: + msg = "benchmark summary publication and rollback failed" + raise BaseExceptionGroup(msg, [error, *failures]) from None + raise + + def _archive_readme(archive_dir: Path) -> str: reports = sorted(path.name for path in archive_dir.glob("*.md") if path.name != "README.md") lines = [ @@ -524,6 +543,8 @@ def _archive_readme(archive_dir: Path) -> str: lines.extend(f"- [{name.removesuffix('.md')}]({name})" for name in reports) else: lines.append("- No archived performance reports yet.") + if (archive_dir / "studies").is_dir(): + lines.extend(("", "Completed optimization investigations are in [archived studies](studies/README.md).")) return "\n".join(lines) + "\n" @@ -1035,9 +1056,9 @@ def _selected_criterion_groups(criterion_dir: Path, *, suite: str) -> list[Path] for child in criterion_dir.iterdir(): if not child.is_dir(): continue - is_exact = child.name.startswith("exact_") or re.fullmatch(r"rational_input_d[0-9]+", child.name) is not None - is_vs_linalg = re.fullmatch(r"d[0-9]+", child.name) is not None - if (suite in {"all", "exact"} and is_exact) or (suite in {"all", "vs_linalg"} and is_vs_linalg): + is_exact = child.name.startswith(("exact_", "rational_input_", "canonical_conversion_", "det4_diagnostic_")) + is_vs_linalg = re.fullmatch(r"d[0-9]+", child.name) is not None or child.name.startswith("lu_solve_") + if suite == "all" or (suite == "exact" and is_exact) or (suite == "vs_linalg" and is_vs_linalg): groups.append(child) return sorted(groups, key=lambda path: path.name) @@ -1046,7 +1067,7 @@ def _purge_criterion_new_samples(*, criterion_dir: Path, suite: str) -> list[Pat """Remove stale selected-suite `new` samples while preserving named baselines.""" removed: list[Path] = [] for group in _selected_criterion_groups(criterion_dir, suite=suite): - for sample in sorted(group.glob("*/new")): + for sample in sorted(group.rglob("new")): if sample.is_dir(): shutil.rmtree(sample) removed.append(sample) @@ -1087,6 +1108,10 @@ def _benchmark_harness_digest(checkout: Path) -> str: def _install_shared_benchmark_harness(*, source: Path, destination: Path) -> str: """Replace a baseline checkout's harness with the current harness.""" source_files = _benchmark_harness_files(source) + # The comparison test moved into its own package; historical copies would + # otherwise still compile as a library test without the peer dependencies. + if (source / "benches/comparison/Cargo.toml").is_file(): + (destination / "tests/vs_linalg_inputs.rs").unlink(missing_ok=True) for relative in _BENCHMARK_HARNESS_DIRS: source_dir = source / relative destination_dir = destination / relative @@ -1189,7 +1214,8 @@ def _generate_release_baseline( # noqa: PLR0913 ) benchmark_env = _comparison_benchmark_env(repo_root, api_compatibility=api_compatibility) _run_benchmark_input_gate(baseline_worktree, env=benchmark_env) - _progress(f"running {suite} baseline benchmarks for {baseline_tag}") + peers = "; includes nalgebra/faer measurements" if suite != "exact" else "" + _progress(f"running {suite} baseline benchmarks for {baseline_tag}{peers}") _run_tool( baseline_command, baseline_args, @@ -1391,11 +1417,14 @@ def _run_benchmarks_and_render_report( criterion_dir=worktree / "target" / "criterion", suite=config.suite, ) + peers = "" if _has_current_release_signal_tooling(worktree): current_command = ("just", *_latest_recipe_args(suite=config.suite)) + if config.suite != "exact": + peers = "; la-stack only, reusing baseline nalgebra/faer measurements" else: current_command = _fallback_current_command(suite=config.suite) - _progress(f"running current {config.suite} benchmarks") + _progress(f"running current {config.suite} benchmarks for {config.current_tag}{peers}") _run_tool( current_command[0], list(current_command[1:]), @@ -1499,7 +1528,14 @@ def _generated_report_in_temp_worktree( ) report_text = _read_text(report) bundle = load_bundle(temporary_artifacts) - with publish_bundle(published_artifacts, bundle): + summaries = {} + if config.baseline_source == "local": + temporary_summaries = summary_outputs(worktree / "target/criterion", config.baseline_tag, temporary_artifacts) + summaries = { + published_artifacts.csv.with_suffix(".full.csv" if path.suffix == ".csv" else ".full.provenance.json"): text + for path, text in temporary_summaries.items() + } + with _publish_text_outputs(summaries), publish_bundle(published_artifacts, bundle): durable_text = render_release_artifacts(published_artifacts) if durable_text != report_text: msg = "durable performance-comparison artifacts did not reproduce the generated Markdown" @@ -1537,8 +1573,12 @@ def _validate_promotion_paths(request: PromotionRequest, *, index_path: Path, ar raise ValueError(msg) if archive_path is not None: named_paths["archived report"] = archive_path - if request.reserved_paths is not None: - named_paths.update(request.reserved_paths) + ensure_distinct_paths({**named_paths, **(request.reserved_paths or {})}) + if request.retained_outputs: + # Retained inputs may already occupy their own immutable destinations. + # Check destinations separately so this valid overlap cannot conceal an + # alias between a report output and either set of protected paths. + named_paths.update({f"retained summary {index}": path for index, path in enumerate(request.retained_outputs)}) ensure_distinct_paths(named_paths) @@ -1584,6 +1624,8 @@ def _promotion_snapshots( ) if request.output is not None: snapshots.append((request.output, _snapshot_regular_file(request.output, label="rendered output"))) + if request.retained_outputs: + snapshots.extend((path, _snapshot_regular_file(path, label="retained benchmark summary")) for path in request.retained_outputs) return tuple(snapshots) @@ -1621,6 +1663,9 @@ def _promote_report_text(*, source_text: str, request: PromotionRequest) -> Repo archive_exists=archive_exists, ) try: + for path, text in (request.retained_outputs or {}).items(): + if not path.exists() or _read_text(path) != text: + _write_text(path, text) if archive_path is not None and not archive_exists: if current_text is None: msg = "archive promotion invariant violated" @@ -1688,10 +1733,7 @@ def generate_and_promote_worktree_report( ) published_artifacts = artifacts or _default_artifact_paths(config.repo_root) expected = ReportId(current_tag=current_tag, baseline_tag=baseline_tag) - reserved_paths = { - "artifact CSV": published_artifacts.csv, - "artifact provenance": published_artifacts.provenance, - } + reserved_paths = report_input_paths(published_artifacts) request = PromotionRequest( current=current, archive_dir=archive_dir, @@ -1715,7 +1757,10 @@ def generate_and_promote_worktree_report( ) as generated: return _promote_report_text( source_text=generated.text, - request=request, + request=replace( + request, + retained_outputs=retained_outputs(current.parent / "performance", published_artifacts) if config.baseline_source == "local" else {}, + ), ) @@ -1745,8 +1790,7 @@ def generate_worktree_report( ensure_distinct_paths( { "rendered output": output, - "artifact CSV": published_artifacts.csv, - "artifact provenance": published_artifacts.provenance, + **report_input_paths(published_artifacts), } ) with _generated_report_in_temp_worktree( @@ -1799,10 +1843,8 @@ def render_and_promote_artifacts( archive_dir=archive_dir, expected=expected, output=output, - reserved_paths={ - "artifact CSV": artifacts.csv, - "artifact provenance": artifacts.provenance, - }, + retained_outputs=retained_outputs(current.parent / "performance", artifacts), + reserved_paths=report_input_paths(artifacts), ), ) @@ -1877,8 +1919,10 @@ def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( description="Generate local benchmark comparisons or promote validated comparison artifacts into release documentation.", ) - parser.add_argument("current_tag", nargs="?", help="Current package-version label, e.g. v0.4.3") - parser.add_argument("baseline_tag", nargs="?", help="Previous release tag used as the comparison baseline, e.g. v0.4.2") + parser.add_argument("current_tag", nargs="?", help="Current package-version label, e.g. v0.4.6; new comparisons require v0.4.4 or newer") + parser.add_argument( + "baseline_tag", nargs="?", help="Previous release tag used as the comparison baseline, e.g. v0.4.5; new comparisons require v0.4.4 or newer" + ) parser.add_argument( "--source", default=_DEFAULT_SOURCE, @@ -2050,8 +2094,8 @@ def _validate_generation_request( def _run_archive_request(*, args: argparse.Namespace, paths: ArchivePaths, request: ResolvedArchiveRequest, repo_root: Path) -> ArchiveResult: _validate_generation_request(args=args, request=request, repo_root=repo_root) if args.generate_in_temp_worktree: - _fetch_required_tags(request=request, repo_root=repo_root, include_current=args.github_assets) config = _generation_config(args=args, request=request, repo_root=repo_root) + _fetch_required_tags(request=request, repo_root=repo_root, include_current=args.github_assets) if args.output_only: return ArchiveResult( report_id=generate_worktree_report( @@ -2133,6 +2177,7 @@ def main(argv: list[str] | None = None) -> int: _validate_cli_preflight(args) paths = _resolve_cli_paths(root, args) if args.promote_artifacts: + paths = replace(paths, artifacts=resolve_report_paths(root, paths.artifacts)) result = ArchiveResult( report_id=render_and_promote_artifacts( artifacts=paths.artifacts, diff --git a/scripts/bench_compare.py b/scripts/bench_compare.py index 9183b2e..9301a9d 100644 --- a/scripts/bench_compare.py +++ b/scripts/bench_compare.py @@ -31,6 +31,7 @@ import tempfile import tomllib from collections.abc import Mapping +from contextlib import ExitStack from dataclasses import dataclass from datetime import UTC, datetime from pathlib import Path @@ -39,7 +40,6 @@ from criterion_dim_plot import METRICS from performance_artifacts import ( PRE_RATIONAL_INPUT_API_COMPATIBILITY, - V0_4_3_API_COMPATIBILITY, ArtifactContext, ArtifactPaths, PerformanceBundle, @@ -120,23 +120,6 @@ EXACT_RELEASE_SIGNAL_GROUPS: frozenset[str] = frozenset(EXACT_GROUPS) -# v0.4.2 and earlier named the lossy exact-to-f64 benches after the public -# `*_exact_f64` API. Current benches split that behavior into strict `*_result` -# and lossy `*_rounded_f64` variants. Use the old baseline when present so -# release reports show both compatibility-successor performance and strict -# conversion overhead instead of silently dropping the new rows. -EXACT_LEGACY_BASELINE_BENCHES: dict[str, str] = { - "det_exact_f64_result": "det_exact_f64", - "det_exact_rounded_f64": "det_exact_f64", - "solve_exact_f64_result": "solve_exact_f64", - "solve_exact_rounded_f64": "solve_exact_f64", -} - -_EXACT_LEGACY_PREFIX_BASELINE_BENCHES: tuple[tuple[str, str], ...] = ( - ("solve_exact_f64_result_", "solve_exact_f64_"), - ("solve_exact_rounded_f64_", "solve_exact_f64_"), -) - VS_LINALG_LA_STACK_ONLY_BENCHES_BY_METRIC: dict[str, list[str]] = { "det_via_lu": ["la_stack_det"], } @@ -167,23 +150,10 @@ "la_stack_det_from_lu_balanced_range", "la_stack_det_from_ldlt_balanced_range", ] -_V0_4_3_API_COMPATIBILITY = V0_4_3_API_COMPATIBILITY _PRE_RATIONAL_INPUT_API_COMPATIBILITY = PRE_RATIONAL_INPUT_API_COMPATIBILITY _RATIONAL_INPUT_ROWS: frozenset[tuple[str, str]] = frozenset( (group, bench) for group, benches in EXACT_GROUPS.items() if group.startswith("rational_input_d") for bench in benches ) -_V0_4_3_UNAVAILABLE_BASELINE_ROWS: frozenset[tuple[str, str]] = frozenset( - { - ("exact_d2", "det_direct_with_errbound"), - ("exact_d3", "det_direct_with_errbound"), - ("exact_d4", "det_direct_with_errbound"), - ("d8", "la_stack_det_from_lu_balanced_range"), - ("d8", "la_stack_det_from_ldlt_balanced_range"), - } -) -_UNAVAILABLE_BASELINE_ROWS_BY_COMPATIBILITY: dict[str, frozenset[tuple[str, str]]] = { - _V0_4_3_API_COMPATIBILITY: _V0_4_3_UNAVAILABLE_BASELINE_ROWS, -} VS_LINALG_RELEASE_SIGNAL_BENCHES_BY_DIM: dict[int, list[str]] = { 8: VS_LINALG_D8_RELEASE_SIGNAL_BENCHES, } @@ -231,10 +201,14 @@ `performance.provenance.json` comparison inputs under `target/bench-reports/` without promoting documentation. It applies staged and unstaged tracked changes; untracked files are excluded. `just performance-github-assets` writes `target/bench-reports/github-assets-performance.md`. -`just performance-release` performs the same measurement and retention work, then promotes distinct-release documentation. +`just performance-release` also preserves every recorded local benchmark summary and the report inputs under +`docs/performance/-vs-//`, then promotes distinct-release documentation. `just performance-doc` consumes the retained pair from either workflow without benchmarking and promotes it when the package versions differ. +After `just clean`, `performance-doc` and `performance-readme` use the latest complete snapshot in `docs/performance/`. For a distinct pair, `performance-local` followed by `performance-doc` is equivalent to the atomic `performance-release` workflow. +See the [local summary index](https://github.com/acgetchell/la-stack/tree/main/docs/performance) +for the saved-data schema, provenance, and historical availability. Older curated release-to-release reports are archived in `docs/archive/performance/`. See `docs/BENCHMARKING.md` for the full comparison workflow. @@ -923,36 +897,6 @@ def _collect_exact_results(criterion_dir: Path, sample: str, stat: str) -> list[ return results -def _legacy_exact_baseline_bench(bench: str) -> str | None: - """Return the legacy exact benchmark name for renamed rows.""" - legacy_bench = EXACT_LEGACY_BASELINE_BENCHES.get(bench) - if legacy_bench is not None: - return legacy_bench - - for current_prefix, legacy_prefix in _EXACT_LEGACY_PREFIX_BASELINE_BENCHES: - if bench.startswith(current_prefix): - return f"{legacy_prefix}{bench.removeprefix(current_prefix)}" - - return None - - -def _exact_baseline_path(group_dir: Path, bench: str, baseline_name: str) -> tuple[str, Path]: - """Return the exact benchmark baseline path, falling back to legacy names.""" - base_path = group_dir / bench / baseline_name / "estimates.json" - if base_path.exists(): - return (bench, base_path) - - legacy_bench = _legacy_exact_baseline_bench(bench) - if legacy_bench is None: - return (bench, base_path) - - legacy_path = group_dir / legacy_bench / baseline_name / "estimates.json" - if legacy_path.exists(): - return (legacy_bench, legacy_path) - - return (bench, base_path) - - def _ordered_vs_linalg_benches(group_dir: Path, sample: str) -> list[str]: """Return present vs_linalg benches in a stable, metric-aware order.""" present = {child.name for child in group_dir.iterdir() if child.is_dir() and (child / sample / "estimates.json").exists()} @@ -995,13 +939,9 @@ def _collect_results(criterion_dir: Path, sample: str, stat: str, suite: str = " def _unavailable_baseline_rows(policy: ComparisonPolicy) -> frozenset[tuple[str, str]]: """Return rows excluded by the baseline API under the installed shared harness.""" - unavailable: frozenset[tuple[str, str]] = _UNAVAILABLE_BASELINE_ROWS_BY_COMPATIBILITY.get( - policy.baseline_api_compatibility or "", - frozenset[tuple[str, str]](), - ) - if policy.shared_harness_rational_inputs and policy.baseline_api_compatibility in {_V0_4_3_API_COMPATIBILITY, _PRE_RATIONAL_INPUT_API_COMPATIBILITY}: - unavailable |= _RATIONAL_INPUT_ROWS - return unavailable + if policy.shared_harness_rational_inputs and policy.baseline_api_compatibility == _PRE_RATIONAL_INPUT_API_COMPATIBILITY: + return _RATIONAL_INPUT_ROWS + return frozenset[tuple[str, str]]() def _collect_exact_comparisons( @@ -1028,7 +968,7 @@ def _collect_exact_comparisons( group_dir = criterion_dir / group for bench in selected_benches: new_path = group_dir / bench / "new" / "estimates.json" - baseline_bench, base_path = _exact_baseline_path(group_dir, bench, baseline_name) + base_path = group_dir / bench / baseline_name / "estimates.json" missing_current = not new_path.exists() missing_baseline = not base_path.exists() baseline_unavailable = (group, bench) in unavailable_baseline_rows @@ -1040,7 +980,7 @@ def _collect_exact_comparisons( suite="exact", group=group, bench=bench, - baseline_bench=baseline_bench, + baseline_bench=bench, missing_current=True, missing_baseline=False, ) @@ -1055,7 +995,7 @@ def _collect_exact_comparisons( suite="exact", group=group, bench=bench, - baseline_bench=baseline_bench, + baseline_bench=bench, missing_current=missing_current, missing_baseline=missing_baseline, ) @@ -1073,7 +1013,6 @@ def _collect_exact_comparisons( baseline=baseline, current=current, assessment=_assess_change(baseline, current), - baseline_bench=baseline_bench if baseline_bench != bench else None, ) ) @@ -1165,7 +1104,6 @@ def _collect_vs_linalg_comparisons( """Compare vs_linalg results while retaining one-sided rows.""" comparisons: list[Comparison] = [] gaps: list[CoverageGap] = [] - unavailable_baseline_rows = _unavailable_baseline_rows(policy) dim_groups = _vs_linalg_dimension_groups(criterion_dir, policy.scope) for _dim, group_dir in sorted(dim_groups, key=lambda item: item[0]): @@ -1180,24 +1118,6 @@ def _collect_vs_linalg_comparisons( base_path = group_dir / bench / baseline_name / "estimates.json" missing_current = not new_path.exists() missing_baseline = not base_path.exists() - baseline_unavailable = (group_dir.name, bench) in unavailable_baseline_rows - - if baseline_unavailable: - if missing_current: - gaps.append( - CoverageGap( - suite="vs_linalg", - group=group_dir.name, - bench=bench, - baseline_bench=bench, - missing_current=True, - missing_baseline=False, - ) - ) - else: - _read_estimate(new_path, stat) - continue - if missing_current or missing_baseline: gaps.append( CoverageGap( @@ -1911,25 +1831,9 @@ def _provenance_markdown( " one-sided rows outside the baseline's correctness domain are identified by the retained CSV coverage status and note.", ] ) - if include_compatibility_rows and compatibility == _V0_4_3_API_COMPATIBILITY and criterion.suite in {"all", "vs_linalg"}: - lines.extend( - [ - "- Baseline-unavailable rows: `d8/la_stack_det_from_lu_balanced_range` and", - " `d8/la_stack_det_from_ldlt_balanced_range` were not timed because v0.4.3 returns zero for a", - " fixture whose exact determinant is one; current samples remain required, but no speedup is claimed.", - ] - ) - if include_compatibility_rows and compatibility == _V0_4_3_API_COMPATIBILITY and criterion.suite in {"all", "exact"}: - lines.extend( - [ - "- Baseline-unavailable rows: `exact_d2/det_direct_with_errbound`,", - " `exact_d3/det_direct_with_errbound`, and `exact_d4/det_direct_with_errbound` were not timed", - " because v0.4.3 predates the paired API; the comparable `det_errbound` baselines remain required.", - ] - ) if ( include_compatibility_rows - and compatibility in {_V0_4_3_API_COMPATIBILITY, _PRE_RATIONAL_INPUT_API_COMPATIBILITY} + and compatibility == _PRE_RATIONAL_INPUT_API_COMPATIBILITY and criterion.suite in {"all", "exact"} and validation.get("shared_harness_rational_inputs") is True ): @@ -2190,8 +2094,7 @@ def _write_and_render_artifacts( # noqa: PLR0913 def _write_text_atomic(path: Path, text: str) -> None: """Replace a UTF-8 text file only after its complete payload is durable.""" path.parent.mkdir(parents=True, exist_ok=True) - staged: Path | None = None - try: + with ExitStack() as cleanup: with tempfile.NamedTemporaryFile( "w", encoding="utf-8", @@ -2202,13 +2105,11 @@ def _write_text_atomic(path: Path, text: str) -> None: delete=False, ) as handle: staged = Path(handle.name) + cleanup.callback(staged.unlink, missing_ok=True) handle.write(text) handle.flush() os.fsync(handle.fileno()) staged.replace(path) - finally: - if staged is not None: - staged.unlink(missing_ok=True) def main(argv: list[str] | None = None) -> int: # noqa: C901, PLR0911, PLR0912, PLR0915 diff --git a/scripts/benchmark_contract.py b/scripts/benchmark_contract.py index 571531a..2caaabc 100644 --- a/scripts/benchmark_contract.py +++ b/scripts/benchmark_contract.py @@ -14,7 +14,6 @@ "justfile", "rust-toolchain.toml", "tests/exact_bench_config.rs", - "tests/vs_linalg_inputs.rs", ) diff --git a/scripts/benchmark_summaries.py b/scripts/benchmark_summaries.py new file mode 100644 index 0000000..77d174b --- /dev/null +++ b/scripts/benchmark_summaries.py @@ -0,0 +1,260 @@ +"""Preserve every recorded local benchmark summary outside disposable targets.""" + +import csv +import hashlib +import io +import json +import re +from dataclasses import dataclass +from pathlib import Path +from typing import Literal + +from criterion_measurements import positive_number, read_object, validate_measurement +from performance_artifacts import ArtifactPaths, TimingEstimate, load_bundle + +SCHEMA_VERSION = 1 +COLUMNS = ( + "phase", + "benchmark_id", + "sample_count", + "mean_ns", + "mean_ci_lower_ns", + "mean_ci_upper_ns", + "median_ns", + "median_ci_lower_ns", + "median_ci_upper_ns", + "confidence_level", +) + + +@dataclass(frozen=True, slots=True) +class Measurement: + """One independently identified baseline or current measurement.""" + + phase: Literal["baseline", "current"] + benchmark_id: str + mean: TimingEstimate + median: TimingEstimate + + def __post_init__(self) -> None: + """Require a phase and a portable, nonempty Criterion identity.""" + if self.phase not in {"baseline", "current"} or not self.benchmark_id.strip(): + msg = "measurement requires a phase and benchmark ID" + raise ValueError(msg) + + +def full_summary_paths(report: ArtifactPaths) -> ArtifactPaths: + """Keep the complete summary adjacent to the selected report inputs.""" + return ArtifactPaths( + csv=report.csv.with_suffix(".full.csv"), + provenance=report.csv.with_suffix(".full.provenance.json"), + ) + + +def report_input_paths(report: ArtifactPaths) -> dict[str, Path]: + """Reserve selected and complete inputs against publication-output aliases.""" + full = full_summary_paths(report) + return { + "artifact CSV": report.csv, + "artifact provenance": report.provenance, + "complete summary CSV": full.csv, + "complete summary provenance": full.provenance, + } + + +def _estimate(directory: Path, statistic: str) -> TimingEstimate: + estimates = read_object(directory / "estimates.json") + estimate = estimates[statistic] + if not isinstance(estimate, dict) or not isinstance(interval := estimate.get("confidence_interval"), dict): + raise TypeError(f"missing {statistic} confidence interval in {directory}") + return TimingEstimate( + median_ns=positive_number(estimate.get("point_estimate")), + ci_lower_ns=positive_number(interval.get("lower_bound")), + ci_upper_ns=positive_number(interval.get("upper_bound")), + ) + + +def collect_measurements(criterion: Path, baseline: str) -> tuple[Measurement, ...]: + """Read all recorded cases, including peers and groups outside the report registry. + + The caller must remove baseline ``new`` directories before current timing. + Named baseline samples survive that cleanup. Their phase is never inferred + from the benchmark's library name or substituted for an absent current run. + """ + rows: list[Measurement] = [] + for phase, sample in (("baseline", baseline), ("current", "new")): + for directory in sorted(path for path in criterion.rglob(sample) if path.is_dir()): + metadata = read_object(directory / "benchmark.json") + benchmark_id = metadata.get("full_id") + if not isinstance(benchmark_id, str) or not benchmark_id.strip(): + raise ValueError(f"missing Criterion full_id in {directory}") + validate_measurement(directory) + rows.append(Measurement(phase, benchmark_id, _estimate(directory, "mean"), _estimate(directory, "median"))) + _validate_rows(rows) + return tuple(sorted(rows, key=lambda row: (row.phase, row.benchmark_id))) + + +def _validate_rows(rows: list[Measurement] | tuple[Measurement, ...]) -> None: + if {row.phase for row in rows} != {"baseline", "current"}: + msg = "complete local summaries require both measurement phases" + raise ValueError(msg) + keys = {(row.phase, row.benchmark_id) for row in rows} + if len(keys) != len(rows): + msg = "duplicate phase/benchmark identity in local summaries" + raise ValueError(msg) + + +def _serialize_rows(rows: tuple[Measurement, ...]) -> str: + output = io.StringIO(newline="") + writer = csv.writer(output, lineterminator="\n") + writer.writerow(COLUMNS) + for row in rows: + writer.writerow( + ( + row.phase, + row.benchmark_id, + 100, + row.mean.median_ns, + row.mean.ci_lower_ns, + row.mean.ci_upper_ns, + row.median.median_ns, + row.median.ci_lower_ns, + row.median.ci_upper_ns, + 0.95, + ) + ) + return output.getvalue() + + +def _parse_rows(text: str) -> tuple[Measurement, ...]: + reader = csv.DictReader(io.StringIO(text, newline="")) + if reader.fieldnames != list(COLUMNS): + msg = "unsupported complete-summary CSV columns" + raise ValueError(msg) + rows: list[Measurement] = [] + for row in reader: + if None in row or any(value is None for value in row.values()): + msg = "malformed complete-summary CSV row" + raise ValueError(msg) + phase = row["phase"] + if phase not in {"baseline", "current"}: + raise ValueError(f"invalid measurement phase: {phase!r}") + if row["sample_count"] != "100" or row["confidence_level"] != "0.95": + msg = "local summaries require full release sampling and 95% intervals" + raise ValueError(msg) + estimates = [ + TimingEstimate(*(positive_number(float(row[field])) for field in fields)) + for fields in ( + ("mean_ns", "mean_ci_lower_ns", "mean_ci_upper_ns"), + ("median_ns", "median_ci_lower_ns", "median_ci_upper_ns"), + ) + ] + rows.append(Measurement(phase, row["benchmark_id"], *estimates)) + _validate_rows(rows) + return tuple(rows) + + +def summary_outputs(criterion: Path, baseline: str, report: ArtifactPaths) -> dict[Path, str]: + """Validate every measured case and bind its CSV to the selected report provenance.""" + bundle = load_bundle(report) + if bundle.context.benchmark_provenance["mode"] != "shared-current-harness": + msg = "local summaries require locally measured shared-harness results" + raise ValueError(msg) + rows = collect_measurements(criterion, baseline) + payload = _serialize_rows(rows) + if _parse_rows(payload) != rows: + msg = "local summary CSV did not preserve timing precision" + raise ValueError(msg) + provenance = read_object(report.provenance) + provenance["measurements"] = { + "schema_version": SCHEMA_VERSION, + "columns": COLUMNS, + "sha256": hashlib.sha256(payload.encode()).hexdigest(), + "counts": {phase: sum(row.phase == phase for row in rows) for phase in ("baseline", "current")}, + } + paths = full_summary_paths(report) + return {paths.csv: payload, paths.provenance: json.dumps(provenance, indent=2, sort_keys=True) + "\n"} + + +def _validate_saved_summary(report: ArtifactPaths) -> None: + full = full_summary_paths(report) + payload = full.csv.read_bytes() + rows = _parse_rows(payload.decode("utf-8")) + provenance = read_object(full.provenance) + expected = { + "schema_version": SCHEMA_VERSION, + "columns": list(COLUMNS), + "sha256": hashlib.sha256(payload).hexdigest(), + "counts": {phase: sum(row.phase == phase for row in rows) for phase in ("baseline", "current")}, + } + measurements = provenance.pop("measurements", None) + if not isinstance(measurements, dict) or type(measurements.get("schema_version")) is not int or measurements != expected: + msg = "complete-summary digest, schema, or phase counts do not match" + raise ValueError(msg) + if provenance != read_object(report.provenance): + msg = "complete summaries and selected report have different provenance" + raise ValueError(msg) + load_bundle(report) + + +def retained_outputs(performance_dir: Path, report: ArtifactPaths) -> dict[Path, str]: + """Build an immutable run directory and latest pointer for a release promotion. + + Legacy selected-only artifacts remain renderable, but cannot be presented + as complete histories or replace the latest complete-summary pointer. + Include unchanged destinations so promotion can protect every retained file + before deciding which payloads need writing. + """ + full = full_summary_paths(report) + if not full.csv.exists() and not full.provenance.exists(): + return {} + _validate_saved_summary(report) + bundle = load_bundle(report) + release = bundle.context.release + if any(re.fullmatch(r"v[0-9A-Za-z.+-]+", tag) is None for tag in (release.current, release.baseline)): + msg = "invalid release identifier for persistent summaries" + raise ValueError(msg) + payloads = { + "performance.csv": report.csv.read_text(encoding="utf-8"), + "performance.provenance.json": report.provenance.read_text(encoding="utf-8"), + "performance.full.csv": full.csv.read_text(encoding="utf-8"), + "performance.full.provenance.json": full.provenance.read_text(encoding="utf-8"), + } + digest = hashlib.sha256(json.dumps(payloads, sort_keys=True).encode()).hexdigest() + relative = Path(f"{release.current}-vs-{release.baseline}") / digest + if not (performance_dir / relative).resolve().is_relative_to(performance_dir.resolve()): + msg = "benchmark snapshot escapes the performance directory" + raise ValueError(msg) + outputs = {performance_dir / relative / name: text for name, text in payloads.items()} + for path, text in outputs.items(): + if path.exists() and path.read_text(encoding="utf-8") != text: + raise ValueError(f"existing benchmark snapshot differs: {path}") + outputs[performance_dir / "latest.json"] = json.dumps({"schema_version": SCHEMA_VERSION, "run": relative.as_posix()}, indent=2) + "\n" + return outputs + + +def resolve_report_paths(root: Path, report: ArtifactPaths) -> ArtifactPaths: + """Use committed summaries after clean, without hiding partial scratch artifacts.""" + default = root / "target/bench-reports/performance.csv" + if ( + report.csv.resolve() != default.resolve() + or report.provenance.resolve() != default.with_suffix(".provenance.json").resolve() + or any(path.exists() for path in report_input_paths(report).values()) + ): + return report + directory = root / "docs/performance" + pointer = directory / "latest.json" + if not pointer.exists(): + return report + metadata = read_object(pointer) + relative = metadata.get("run") + if type(metadata.get("schema_version")) is not int or metadata.get("schema_version") != SCHEMA_VERSION or not isinstance(relative, str): + msg = "invalid persistent benchmark pointer" + raise ValueError(msg) + run = (directory / relative).resolve() + if not run.is_relative_to(directory.resolve()) or len(Path(relative).parts) != 2: + msg = "persistent benchmark pointer escapes its run directory" + raise ValueError(msg) + retained = ArtifactPaths(csv=run / "performance.csv", provenance=run / "performance.provenance.json") + _validate_saved_summary(retained) + return retained diff --git a/scripts/criterion_dim_plot.py b/scripts/criterion_dim_plot.py index 0968e42..b4561b1 100644 --- a/scripts/criterion_dim_plot.py +++ b/scripts/criterion_dim_plot.py @@ -24,11 +24,13 @@ import tempfile import tomllib from collections.abc import Mapping +from contextlib import ExitStack from dataclasses import dataclass from pathlib import Path from typing import Final, Protocol, TypeGuard, cast from benchmark_contract import benchmark_contract_digest +from benchmark_summaries import report_input_paths, resolve_report_paths from performance_artifacts import ArtifactPaths, PerformanceBundle, TimingEstimate, ensure_distinct_paths, load_bundle from subprocess_utils import ExecutableNotFoundError, cpu_description, find_project_root, run_git_command, run_safe_command @@ -201,7 +203,7 @@ def no_plot(self) -> bool: ... "dot": Metric( la_bench="la_stack_dot", na_bench="nalgebra_dot", - fa_bench="faer_dot", + fa_bench="faer_dot_native", title="Vector dot product", ), # Different names between crates. @@ -229,7 +231,6 @@ def no_plot(self) -> bool: ... "rust-toolchain.toml", "justfile", "tests/exact_bench_config.rs", - "tests/vs_linalg_inputs.rs", ) @@ -313,6 +314,7 @@ def _detect_versions(root: Path) -> dict[str, str]: cargo_toml = root / "Cargo.toml" package_version = _read_cargo_package_version(cargo_toml) or "unknown" dep_versions = _read_cargo_dependency_versions(cargo_toml, {"nalgebra", "faer"}) + dep_versions.update(_read_cargo_dependency_versions(root / "benches/comparison/Cargo.toml", {"nalgebra", "faer"})) return { "la-stack": package_version, @@ -664,7 +666,7 @@ def _resolve_output_paths(root: Path, metric: str, stat: str, out_svg: str | Non def _resolve_performance_paths(root: Path, performance_csv: str) -> ArtifactPaths: """Resolve a retained performance CSV and its adjacent provenance JSON.""" csv = _resolve_under_root(root, performance_csv) - return ArtifactPaths(csv=csv, provenance=csv.with_suffix(".provenance.json")) + return resolve_report_paths(root, ArtifactPaths(csv=csv, provenance=csv.with_suffix(".provenance.json"))) def _collect_rows(criterion_dir: Path, dims: list[int], metric: Metric, stat: str, sample: str) -> tuple[list[Row], list[str]]: @@ -941,9 +943,11 @@ def _validate_current_measurement(root: Path, measurement: Mapping[str, object]) "commit": _git_value(root, ["--no-pager", "rev-parse", "HEAD"]), "source_state_sha256": current_source_state, } + if current["commit"] == "unavailable": + msg = "current checkout commit 'unavailable'; cannot record README publication provenance" + raise ValueError(msg) for retained_field, current_field in ( ("cargo_lock_sha256", "cargo_lock_sha256"), - ("current_commit", "commit"), ("current_source_state_sha256", "source_state_sha256"), ): retained = measurement.get(retained_field) @@ -957,6 +961,9 @@ def _validate_current_measurement(root: Path, measurement: Mapping[str, object]) retained_contract = measurement.get("benchmark_contract_sha256") contract_status = "legacy-retained-artifact" + if retained_contract is None and measurement.get("current_commit") != current["commit"]: + msg = "legacy retained benchmark measurement does not match the current commit; run just performance-release to refresh it" + raise ValueError(msg) if retained_contract is not None: current_contract = benchmark_contract_digest(root) if retained_contract != current_contract: @@ -1178,8 +1185,7 @@ def _validate_publication_paths(root: Path, args: PlotCliArgs, *, out_svg: Path, if args.update_readme: paths["README output"] = _resolve_under_root(root, args.readme) performance = _resolve_performance_paths(root, args.performance_csv) - paths["performance input CSV"] = performance.csv - paths["performance input provenance"] = performance.provenance + paths.update(report_input_paths(performance)) try: ensure_distinct_paths(paths) except (OSError, ValueError) as exc: @@ -1236,25 +1242,28 @@ def _replace_staged_files(pairs: list[tuple[Path, Path]], backup_dir: Path) -> N raise +def _remove_publication_backup(backup_dir: Path) -> None: + """Clean up an unneeded backup without masking the publication outcome.""" + try: + shutil.rmtree(backup_dir) + except OSError as exc: + print(f"Warning: could not remove artifact backup {backup_dir}: {exc}", file=sys.stderr) + + def _publish_staged_files(pairs: list[tuple[Path, Path]], root: Path) -> bool: """Publish staged files together, preserving backups after rollback failure.""" backup_dir = Path(tempfile.mkdtemp(prefix=".criterion-dim-plot-backup-", dir=root)) - preserve_backup = False - try: - _replace_staged_files(pairs, backup_dir) - except PublicationRollbackError as exc: - preserve_backup = True - print(f"could not publish benchmark artifacts atomically: {exc}", file=sys.stderr) - return False - except (OSError, ValueError) as exc: - print(f"could not publish benchmark artifacts atomically: {exc}", file=sys.stderr) - return False - finally: - if not preserve_backup: - try: - shutil.rmtree(backup_dir) - except OSError as exc: - print(f"Warning: could not remove artifact backup {backup_dir}: {exc}", file=sys.stderr) + with ExitStack() as cleanup: + cleanup.callback(_remove_publication_backup, backup_dir) + try: + _replace_staged_files(pairs, backup_dir) + except PublicationRollbackError as exc: + cleanup.pop_all() + print(f"could not publish benchmark artifacts atomically: {exc}", file=sys.stderr) + return False + except (OSError, ValueError) as exc: + print(f"could not publish benchmark artifacts atomically: {exc}", file=sys.stderr) + return False return True @@ -1406,11 +1415,15 @@ def main(argv: list[str] | None = None) -> int: # noqa: C901, PLR0911, PLR0912, root = _repo_root() - rc = _validate_readme_target(root, args) - if rc != 0: - return rc - out_svg, out_csv = _resolve_output_paths(root, args.metric, args.stat, args.out, args.csv) - rc = _validate_publication_paths(root, args, out_svg=out_svg, out_csv=out_csv) + try: + rc = _validate_readme_target(root, args) + if rc != 0: + return rc + out_svg, out_csv = _resolve_output_paths(root, args.metric, args.stat, args.out, args.csv) + rc = _validate_publication_paths(root, args, out_svg=out_svg, out_csv=out_csv) + except (OSError, TypeError, ValueError) as exc: + print(f"Invalid retained benchmark inputs: {exc}", file=sys.stderr) + return 2 if rc != 0: return rc versions = _detect_versions(root) @@ -1422,8 +1435,8 @@ def main(argv: list[str] | None = None) -> int: # noqa: C901, PLR0911, PLR0912, metric = METRICS[args.metric] if args.update_readme: - performance_paths = _resolve_performance_paths(root, args.performance_csv) try: + performance_paths = _resolve_performance_paths(root, args.performance_csv) performance_bundle = load_bundle(performance_paths) validation = _validate_performance_bundle(root, args, performance_bundle) rows = _collect_performance_rows(performance_bundle, metric) @@ -1446,7 +1459,7 @@ def main(argv: list[str] | None = None) -> int: # noqa: C901, PLR0911, PLR0912, dims = [] if not dims: print( - f"No Criterion results found under {criterion_dir}.\n\nRun benchmarks first, e.g.:\n cargo bench --bench vs_linalg\n", + f"No Criterion results found under {criterion_dir}.\n\nRun benchmarks first, e.g.:\n just bench-vs-linalg\n", file=sys.stderr, ) return 2 diff --git a/scripts/criterion_measurements.py b/scripts/criterion_measurements.py new file mode 100644 index 0000000..3ebe30f --- /dev/null +++ b/scripts/criterion_measurements.py @@ -0,0 +1,48 @@ +"""Validate raw Criterion measurements shared by local and hosted retention.""" + +import json +import math +from typing import TYPE_CHECKING, cast + +from performance_artifacts import TimingEstimate + +if TYPE_CHECKING: + from pathlib import Path + + +def read_object(path: Path) -> dict[str, object]: + """Require a JSON object at the raw artifact boundary.""" + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise TypeError(f"expected a JSON object in {path}") + return cast("dict[str, object]", data) + + +def positive_number(value: object) -> float: + """Reject booleans, nonnumeric values, and invalid timing numbers.""" + if isinstance(value, bool) or not isinstance(value, (float, int)) or not math.isfinite(value) or value <= 0: + raise ValueError(f"expected a finite positive timing value, got {value!r}") + return float(value) + + +def validate_measurement(directory: Path) -> None: + """Check full default sampling and the estimates used by report consumers.""" + samples = read_object(directory / "sample.json") + for field in ("iters", "times"): + values = samples.get(field) + if not isinstance(values, list) or len(values) != 100: + raise ValueError(f"{directory}: {field} must contain 100 samples") + for value in values: + positive_number(value) + estimates = read_object(directory / "estimates.json") + for statistic in ("mean", "median"): + estimate = estimates.get(statistic) + if not isinstance(estimate, dict) or not isinstance(interval := estimate.get("confidence_interval"), dict): + raise TypeError(f"{directory}: missing {statistic} estimate or confidence interval") + if interval.get("confidence_level") != 0.95: + raise ValueError(f"{directory}: expected a 95% confidence interval") + TimingEstimate( + median_ns=positive_number(estimate.get("point_estimate")), + ci_lower_ns=positive_number(interval.get("lower_bound")), + ci_upper_ns=positive_number(interval.get("upper_bound")), + ) diff --git a/scripts/performance_artifacts.py b/scripts/performance_artifacts.py index 149a1a4..bc4f428 100644 --- a/scripts/performance_artifacts.py +++ b/scripts/performance_artifacts.py @@ -24,10 +24,9 @@ COVERAGE_STATES = ("comparable", "current-only", "baseline-only") type CoverageState = Literal["comparable", "current-only", "baseline-only"] -type ReleaseApiCapability = Literal["legacy-v0.4.3", "pre-rational-input", "rational-input", "unknown"] +type ReleaseApiCapability = Literal["pre-rational-input", "rational-input", "unknown"] type RationalInputCoverage = Literal["excluded", "current-only", "comparable"] -V0_4_3_API_COMPATIBILITY = "la_stack_v0_4_3_api" PRE_RATIONAL_INPUT_API_COMPATIBILITY = "la_stack_pre_rational_input_api" NO_API_COMPATIBILITY = "none" @@ -55,7 +54,8 @@ def _release_api_capability(release: str) -> ReleaseApiCapability: return "unknown" version = tuple(int(match.group(part)) for part in ("major", "minor", "patch")) if version <= (0, 4, 3): - return "legacy-v0.4.3" + msg = f"unsupported performance comparison release {release!r}; comparisons require v0.4.4 or newer (v0.4.3 and older are excluded)" + raise ValueError(msg) if version <= (0, 4, 5): return "pre-rational-input" return "rational-input" @@ -71,14 +71,13 @@ def resolve_shared_harness_compatibility( current_capability = _release_api_capability(current) baseline_capability = _release_api_capability(baseline) baseline_adapter = { - "legacy-v0.4.3": V0_4_3_API_COMPATIBILITY, "pre-rational-input": PRE_RATIONAL_INPUT_API_COMPATIBILITY, "rational-input": NO_API_COMPATIBILITY, "unknown": NO_API_COMPATIBILITY, }[baseline_capability] if not shared_harness_rational_inputs: rational_coverage: RationalInputCoverage = "excluded" - elif baseline_capability in {"legacy-v0.4.3", "pre-rational-input"}: + elif baseline_capability == "pre-rational-input": rational_coverage = "current-only" else: rational_coverage = "comparable" diff --git a/scripts/postprocess_changelog.py b/scripts/postprocess_changelog.py index 7d00cdb..c7e6952 100644 --- a/scripts/postprocess_changelog.py +++ b/scripts/postprocess_changelog.py @@ -348,6 +348,19 @@ def _extract_section_summaries( return pr_entries, breaking_entries +def _summary_insertion_index(section: list[str]) -> int: + """Place new summaries after the version heading or an existing breaking summary.""" + if "### ⚠️ Breaking Changes" in section: + index = section.index("### ⚠️ Breaking Changes") + 1 + while index < len(section) and not section[index].startswith("### "): + index += 1 + else: + index = 1 + while index < len(section) and not section[index].strip(): + index += 1 + return index + + def _inject_summary_sections(text: str) -> str: """ Insert "Merged Pull Requests" and "Breaking Changes" summary sections into a changelog text. @@ -377,11 +390,14 @@ def _inject_summary_sections(text: str) -> str: end = boundaries[sec_idx + 1] if sec_idx + 1 < len(boundaries) else len(lines) section = lines[start:end] - # Guard against double-injection. - if any("### Merged Pull Requests" in s or "### ⚠️ Breaking Changes" in s for s in section): - continue - + # git-cliff renders full breaking descriptions; older input may have neither summary. + has_pr_summary = "### Merged Pull Requests" in section + has_breaking_summary = "### ⚠️ Breaking Changes" in section pr_entries, breaking_entries = _extract_section_summaries(section) + if has_pr_summary: + pr_entries = [] + if has_breaking_summary: + breaking_entries = [] if not pr_entries and not breaking_entries: continue @@ -389,10 +405,7 @@ def _inject_summary_sections(text: str) -> str: # Sort PRs by highest PR number, descending (newest first). pr_entries.sort(key=_max_pr_number, reverse=True) - # Insertion point: first non-blank line after the heading. - insert_at = start + 1 - while insert_at < end and lines[insert_at].strip() == "": - insert_at += 1 + insert_at = start + _summary_insertion_index(section) block: list[str] = [] if breaking_entries: @@ -834,9 +847,41 @@ def _strip_dependabot_metadata(text: str) -> str: return "\n".join(result) +def _escape_breaking_prose(text: str) -> str: + """Escape HTML in breaking descriptions while preserving Markdown code.""" + result: list[str] = [] + in_breaking = False + active_fence: _CodeFence | None = None + for line in text.split("\n"): + if active_fence is not None: + result.append(line) + if _closes_code_fence(line, active_fence): + active_fence = None + continue + if line.startswith(("## ", "### ")): + in_breaking = line == "### ⚠️ Breaking Changes" + active_fence = _opening_code_fence(line) + if not in_breaking or active_fence is not None: + result.append(line) + continue + position = 0 + escaped: list[str] = [] + while position < len(line): + end = _backtick_span_end(line, position) if line[position] == "`" else None + if end is not None: + escaped.append(line[position:end]) + position = end + else: + escaped.append({"<": "<", ">": ">"}.get(line[position], line[position])) + position += 1 + result.append("".join(escaped)) + return "\n".join(result) + + def postprocess_text(text: str) -> str: """Apply changelog markdown hygiene transforms to *text*.""" text = _strip_dependabot_metadata(text) + text = _escape_breaking_prose(text) # Inject PR / breaking-change summary sections before reflow. text = _inject_summary_sections(text) diff --git a/scripts/release_baseline.py b/scripts/release_baseline.py index 5c08c50..8ce34ce 100644 --- a/scripts/release_baseline.py +++ b/scripts/release_baseline.py @@ -2,13 +2,11 @@ import argparse import json -import math import os import re import subprocess import sys from pathlib import Path -from typing import cast from bench_compare import ( EXACT_GROUPS, @@ -16,7 +14,7 @@ VS_LINALG_RELEASE_SIGNAL_BENCHES_BY_DIM, VS_LINALG_STANDARD_BENCH_ORDER, ) -from performance_artifacts import TimingEstimate +from criterion_measurements import read_object, validate_measurement from subprocess_utils import ExecutableNotFoundError, format_exception_diagnostics, run_cargo_command SUITES = {"vs_linalg": "bench", "exact": "bench,exact"} @@ -69,8 +67,9 @@ def discover(root: Path, manifest: Path, criterion: Path) -> None: inventory: dict[str, list[str]] = {} for suite, features in SUITES.items(): print(f"[release-baseline] Discovering {suite}", flush=True) + package = ["-p", "la-stack-comparison"] if suite == "vs_linalg" else [] result = run_cargo_command( - ["bench", "--locked", "--features", features, "--bench", suite, "--", "--list"], + ["bench", "--locked", *package, "--features", features, "--bench", suite, "--", "--list"], cwd=root, capture_output=False, stdout=subprocess.PIPE, @@ -89,44 +88,6 @@ def discover(root: Path, manifest: Path, criterion: Path) -> None: manifest.write_text(json.dumps(inventory, indent=2) + "\n", encoding="utf-8", newline="\n") -def read_object(path: Path) -> dict[str, object]: - """Require a JSON object at the raw artifact boundary.""" - data = json.loads(path.read_text(encoding="utf-8")) - if not isinstance(data, dict): - raise TypeError(f"expected a JSON object in {path}") - return cast("dict[str, object]", data) # JSON objects always have string keys. - - -def positive_number(value: object) -> float: - """Reject booleans, nonnumeric values, and invalid timing numbers.""" - if isinstance(value, bool) or not isinstance(value, (float, int)) or not math.isfinite(value) or value <= 0: - raise ValueError(f"expected a finite positive timing value, got {value!r}") - return float(value) - - -def validate_measurement(directory: Path) -> None: - """Check full default sampling and the estimates used by report consumers.""" - samples = read_object(directory / "sample.json") - for field in ("iters", "times"): - values = samples.get(field) - if not isinstance(values, list) or len(values) != 100: - raise ValueError(f"{directory}: {field} must contain 100 samples") - for value in values: - positive_number(value) - estimates = read_object(directory / "estimates.json") - for statistic in ("mean", "median"): - estimate = estimates.get(statistic) - if not isinstance(estimate, dict) or not isinstance(interval := estimate.get("confidence_interval"), dict): - raise TypeError(f"{directory}: missing {statistic} estimate or confidence interval") - if interval.get("confidence_level") != 0.95: - raise ValueError(f"{directory}: expected a 95% confidence interval") - TimingEstimate( - median_ns=positive_number(estimate.get("point_estimate")), - ci_lower_ns=positive_number(interval.get("lower_bound")), - ci_upper_ns=positive_number(interval.get("upper_bound")), - ) - - def validate(criterion: Path, manifest: Path, baseline: str) -> int: """Fail closed on missing, corrupt, stale, or unexpected benchmark output.""" if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", baseline) or baseline in {"new", "base", "change", "report"}: diff --git a/scripts/tests/test_archive_performance.py b/scripts/tests/test_archive_performance.py index ce74c9e..afd5ada 100644 --- a/scripts/tests/test_archive_performance.py +++ b/scripts/tests/test_archive_performance.py @@ -1,7 +1,9 @@ """Tests for archive_performance.py.""" +import csv import io import json +import shutil import subprocess import tarfile from pathlib import Path @@ -20,6 +22,8 @@ parse_report_id, promote_report, ) +from benchmark_summaries import collect_measurements, full_summary_paths, resolve_report_paths +from criterion_dim_plot import _resolve_performance_paths from performance_artifacts import ( ArtifactContext, ArtifactPaths, @@ -30,6 +34,7 @@ TimingEstimate, write_bundle, ) +from subprocess_utils import run_cargo_command if TYPE_CHECKING: from collections.abc import Sequence @@ -122,6 +127,22 @@ def _write_fake_rendered_artifacts(args: Sequence[str], *, version: str, baselin ) write_bundle(paths, bundle) output.write_text(archive_performance.render_release_artifacts(paths), encoding="utf-8") + # The fake renderer stands in for validated timing output. Supply complete + # raw samples so the independent summary exporter exercises real parsing. + for sample, value in ((baseline, 10.0), ("new", 9.0)): + _write_measurement(criterion_dir, f"{group}/{benchmark}", sample, value) + + +def _write_measurement(criterion: Path, benchmark: str, sample: str, value: float) -> None: + directory = criterion / benchmark / sample + directory.mkdir(parents=True, exist_ok=True) + (directory / "benchmark.json").write_text(json.dumps({"full_id": benchmark}), encoding="utf-8") + estimate = { + "point_estimate": value, + "confidence_interval": {"confidence_level": 0.95, "lower_bound": value * 0.9, "upper_bound": value * 1.1}, + } + (directory / "estimates.json").write_text(json.dumps({"mean": estimate, "median": estimate}), encoding="utf-8") + (directory / "sample.json").write_text(json.dumps({"iters": [1.0] * 100, "times": [value] * 100}), encoding="utf-8") def _retained_report(root: Path, *, stem: str = "performance") -> str: @@ -133,7 +154,7 @@ def _retained_report(root: Path, *, stem: str = "performance") -> str: def test_normalized_report_uses_shared_how_to_update_section() -> None: - text = _normalized_report("0.4.3", "v0.4.2") + text = _normalized_report("0.4.6", "v0.4.5") assert text.endswith(archive_performance.HOW_TO_UPDATE_SECTION) @@ -189,13 +210,21 @@ def _write_current_benchmark_tooling(worktree: Path) -> None: (worktree / ".config").mkdir(parents=True, exist_ok=True) (worktree / "scripts").mkdir(parents=True, exist_ok=True) (worktree / "benches" / "common").mkdir(parents=True, exist_ok=True) + (worktree / "benches/comparison/tests").mkdir(parents=True, exist_ok=True) + (worktree / "examples").mkdir(parents=True, exist_ok=True) (worktree / "src").mkdir(parents=True, exist_ok=True) (worktree / "tests").mkdir(parents=True, exist_ok=True) (worktree / "benches" / "vs_linalg.rs").write_text("fn main() {}\n", encoding="utf-8") (worktree / "benches" / "common" / "inputs.rs").write_text("pub const INPUT: f64 = 1.0;\n", encoding="utf-8") (worktree / "src" / "lib.rs").write_text("pub fn fixture() {}\n", encoding="utf-8") (worktree / "tests" / "exact_bench_config.rs").write_text("// exact fixture\n", encoding="utf-8") - (worktree / "tests" / "vs_linalg_inputs.rs").write_text("// linalg fixture\n", encoding="utf-8") + (worktree / "benches/comparison/tests/vs_linalg_inputs.rs").write_text("// linalg fixture\n", encoding="utf-8") + (worktree / "benches/comparison/Cargo.toml").write_text( + '[package]\nname = "fixture-comparison"\nversion = "0.1.0"\nedition = "2024"\n' + '[dev-dependencies]\nfixture = { path = "../.." }\n' + '[features]\nbench = []\nexact = ["fixture/exact"]\n', + encoding="utf-8", + ) (worktree / ".config" / "nextest.toml").write_text("[profile.ci]\nretries = 1\n", encoding="utf-8") (worktree / "Cargo.toml").write_text( '[package]\nname = "fixture"\nversion = "0.1.0"\n[dev-dependencies]\ncriterion = "0.7.0"\n', @@ -223,6 +252,7 @@ def test_shared_benchmark_harness_replaces_baseline_content_and_has_stable_diges baseline.mkdir() _write_current_benchmark_tooling(current) _write_current_benchmark_tooling(baseline) + (baseline / "tests/vs_linalg_inputs.rs").write_text('compile_error!("obsolete comparison test");\n', encoding="utf-8") (baseline / "benches" / "vs_linalg.rs").write_text("fn obsolete() {}\n", encoding="utf-8") (baseline / "Cargo.lock").write_text("version = 3\n", encoding="utf-8") (baseline / "justfile").write_text("obsolete-benchmark-recipe:\n", encoding="utf-8") @@ -238,10 +268,69 @@ def test_shared_benchmark_harness_replaces_baseline_content_and_has_stable_diges assert (baseline / "benches" / "vs_linalg.rs").read_text(encoding="utf-8") == "fn main() {}\n" assert (baseline / "justfile").read_text(encoding="utf-8") == (current / "justfile").read_text(encoding="utf-8") assert (baseline / ".config" / "nextest.toml").read_text(encoding="utf-8") == (current / ".config" / "nextest.toml").read_text(encoding="utf-8") + assert not (baseline / "tests/vs_linalg_inputs.rs").exists() + + +@pytest.mark.parametrize("example_path", ["examples/rational_input_5x5.rs", "examples/rational_input_5x5/main.rs"]) +def test_shared_harness_preserves_manifest_example_targets(tmp_path: Path, example_path: str) -> None: + """Cargo must discover new examples before it can run historical benchmark tests.""" + current = tmp_path / "current" + baseline = tmp_path / "baseline" + _write_current_benchmark_tooling(current) + _write_current_benchmark_tooling(baseline) + baseline_source = baseline / "src" / "lib.rs" + baseline_source.write_text("pub fn historical_api() {}\n", encoding="utf-8") + (current / "src" / "lib.rs").write_text("pub fn current_api() {}\n", encoding="utf-8") + example = current / example_path + example.parent.mkdir(parents=True, exist_ok=True) + example.write_text("fn main() { fixture::current_api(); }\n", encoding="utf-8") + manifest = current / "Cargo.toml" + manifest.write_text( + '[package]\nname = "fixture"\nversion = "0.1.0"\nedition = "2024"\n' + "[features]\nbench = []\nexact = []\n" + '[[example]]\nname = "rational_input_5x5"\nrequired-features = ["exact"]\n' + '[workspace]\nmembers = ["benches/comparison"]\nresolver = "3"\n', + encoding="utf-8", + ) + + digest = archive_performance._install_shared_benchmark_harness(source=current, destination=baseline) + run_cargo_command( + [ + "test", + "--offline", + "--workspace", + "--no-run", + "--target-dir", + str(tmp_path / "target"), + "--features", + "bench,exact", + "--test", + "vs_linalg_inputs", + "--test", + "exact_bench_config", + "--manifest-path", + str(baseline / "Cargo.toml"), + ], + cwd=Path(__file__).resolve().parents[2], + ) + metadata = json.loads( + run_cargo_command( + ["metadata", "--offline", "--no-deps", "--format-version", "1", "--manifest-path", str(baseline / "Cargo.toml")], + cwd=Path(__file__).resolve().parents[2], + ).stdout + ) + + library = next(package for package in metadata["packages"] if package["name"] == "fixture") + examples = [target for target in library["targets"] if target["kind"] == ["example"]] + assert [target["name"] for target in examples] == ["rational_input_5x5"] + assert Path(examples[0]["src_path"]) == baseline / example_path + assert (baseline / example_path).read_bytes() == example.read_bytes() + assert baseline_source.read_text(encoding="utf-8") == "pub fn historical_api() {}\n" + assert digest == archive_performance._benchmark_harness_digest(current) def test_github_release_assets_discard_embedded_shared_harness_metadata(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: - for tag in ("v0.4.2", "v0.4.3"): + for tag in ("v0.4.5", "v0.4.6"): _write_baseline_archive( tmp_path / f"la-stack-{tag}-criterion-baseline.tar.gz", include_harness_metadata=True, @@ -256,8 +345,8 @@ def fake_download(*, baseline_tag: str, download_dir: Path, repo_root: Path) -> monkeypatch.setattr(archive_performance, "_download_release_baseline", fake_download) archive_performance._prepare_github_release_assets( - current_tag="v0.4.3", - baseline_tag="v0.4.2", + current_tag="v0.4.6", + baseline_tag="v0.4.5", repo_root=tmp_path, target_worktree=target_worktree, tmp_dir=tmp_path, @@ -271,7 +360,7 @@ def fake_download(*, baseline_tag: str, download_dir: Path, repo_root: Path) -> def test_purge_selected_new_samples_preserves_named_baselines_and_other_suites(tmp_path: Path) -> None: criterion_dir = tmp_path / "criterion" exact_new = criterion_dir / "exact_d2" / "det_exact" / "new" - exact_baseline = criterion_dir / "exact_d2" / "det_exact" / "v0.4.2" + exact_baseline = criterion_dir / "exact_d2" / "det_exact" / "v0.4.5" rational_new = criterion_dir / "rational_input_d8" / "det_row_cleared_bareiss" / "new" linalg_new = criterion_dir / "d2" / "la_stack_lu" / "new" for directory in (exact_new, exact_baseline, rational_new, linalg_new): @@ -290,6 +379,53 @@ def test_purge_selected_new_samples_preserves_named_baselines_and_other_suites(t assert linalg_new.is_dir() +def test_complete_summaries_preserve_diagnostic_phases_and_full_precision(tmp_path: Path) -> None: + baseline = "v0.4.5" + peer = "lu_solve_pivoting_d2/faer_lu_solve" + changed = "lu_solve_pivoting_d2/la_stack_lu_solve" + added = "canonical_conversion_non_dyadic_d2/convert" + precise = 1.2345678901234567 + for sample in (baseline, "new"): + _write_measurement(tmp_path, peer, sample, 20.0) + _write_measurement(tmp_path, changed, sample, 10.0) + archive_performance._purge_criterion_new_samples(criterion_dir=tmp_path, suite="all") + _write_measurement(tmp_path, changed, "new", precise) + _write_measurement(tmp_path, added, "new", 3.0) + + rows = collect_measurements(tmp_path, baseline) + + assert {(row.phase, row.benchmark_id) for row in rows} == { + ("baseline", peer), + ("baseline", changed), + ("current", changed), + ("current", added), + } + observed = next(row for row in rows if row.phase == "current" and row.benchmark_id == changed) + assert observed.mean.median_ns == precise + assert observed.median.median_ns == precise + + +@pytest.mark.parametrize("missing", ["benchmark.json", "estimates.json", "sample.json"]) +def test_complete_summaries_reject_incomplete_diagnostics(tmp_path: Path, missing: str) -> None: + case = "det4_diagnostic_dense/det" + for sample in ("v0.4.5", "new"): + _write_measurement(tmp_path, case, sample, 1.0) + (tmp_path / case / "new" / missing).unlink() + + with pytest.raises(FileNotFoundError): + collect_measurements(tmp_path, "v0.4.5") + + +def test_complete_summaries_reject_duplicate_criterion_identities(tmp_path: Path) -> None: + for sample in ("v0.4.5", "new"): + _write_measurement(tmp_path, "diagnostic/first", sample, 1.0) + _write_measurement(tmp_path, "diagnostic/second", "new", 2.0) + (tmp_path / "diagnostic/second/new/benchmark.json").write_text('{"full_id":"diagnostic/first"}', encoding="utf-8") + + with pytest.raises(ValueError, match="duplicate phase/benchmark"): + collect_measurements(tmp_path, "v0.4.5") + + def test_apply_current_diff_includes_only_tracked_changes_without_mutating_index(tmp_path: Path) -> None: repo_root = tmp_path / "repo" worktree = tmp_path / "worktree" @@ -524,8 +660,8 @@ def fail_operation() -> None: def test_normalize_tag_adds_leading_v() -> None: - assert normalize_tag("0.4.2") == "v0.4.2" - assert normalize_tag("v0.4.2") == "v0.4.2" + assert normalize_tag("0.4.5") == "v0.4.5" + assert normalize_tag("v0.4.5") == "v0.4.5" assert normalize_tag("v1.2.3-rc.1+build.7") == "v1.2.3-rc.1+build.7" @@ -535,23 +671,23 @@ def test_normalize_tag_rejects_non_semver_baseline_names() -> None: def test_parse_report_id_reads_current_and_baseline_tags() -> None: - report_id = parse_report_id(_report("0.4.2", "v0.4.1")) + report_id = parse_report_id(_report("0.4.5", "v0.4.4")) - assert report_id.current_tag == "v0.4.2" - assert report_id.baseline_tag == "v0.4.1" - assert report_id.archive_name == "v0.4.2-vs-v0.4.1.md" + assert report_id.current_tag == "v0.4.5" + assert report_id.baseline_tag == "v0.4.4" + assert report_id.archive_name == "v0.4.5-vs-v0.4.4.md" @pytest.mark.parametrize( ("extra", "message"), [ - ("\n**la-stack** v0.4.3 · `def5678` (release/test) · 2026-06-09 12:00:00 UTC\n", "la-stack version line"), + ("\n**la-stack** v0.4.6 · `def5678` (release/test) · 2026-06-09 12:00:00 UTC\n", "la-stack version line"), ("\nComparison against baseline **v0.4.0**:\n", "comparison baseline line"), ], ) def test_parse_report_id_rejects_duplicate_identity_lines(extra: str, message: str) -> None: with pytest.raises(ValueError, match=rf"exactly one {message}.*found 2"): - parse_report_id(_report("0.4.2", "v0.4.1") + extra) + parse_report_id(_report("0.4.5", "v0.4.4") + extra) def test_main_preserves_exception_group_diagnostics( @@ -567,7 +703,7 @@ def fail_request(_options: object) -> Never: monkeypatch.setattr(archive_performance, "resolve_archive_request", fail_request) - assert main(["v0.4.3", "v0.4.2"]) == 1 + assert main(["v0.4.6", "v0.4.5"]) == 1 captured = capsys.readouterr() assert "publication and rollback failed (2 sub-exceptions)" in captured.err assert "could not publish docs/performance.md" in captured.err @@ -588,12 +724,12 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert cwd == tmp_path return _result( "[" - '{"tagName":"v0.4.2","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' + '{"tagName":"v0.4.5","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' '{"tagName":"v0.4.10","isDraft":false,"isPrerelease":false,"publishedAt":"2026-04-01T00:00:00Z"},' '{"tagName":"v0.4.11-rc.1","isDraft":false,"isPrerelease":true,"publishedAt":"2026-06-01T00:00:00Z"},' '{"tagName":"v0.4.11","isDraft":true,"isPrerelease":false,"publishedAt":"2026-06-02T00:00:00Z"},' '{"tagName":"not-semver","isDraft":false,"isPrerelease":false,"publishedAt":"2026-06-03T00:00:00Z"},' - '{"tagName":"v0.4.3","isDraft":false,"isPrerelease":false,"publishedAt":"2026-03-01T00:00:00Z"}' + '{"tagName":"v0.4.6","isDraft":false,"isPrerelease":false,"publishedAt":"2026-03-01T00:00:00Z"}' "]" ) @@ -602,7 +738,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** report_id = archive_performance._published_release_pair(tmp_path) assert report_id.current_tag == "v0.4.10" - assert report_id.baseline_tag == "v0.4.3" + assert report_id.baseline_tag == "v0.4.6" def test_published_release_pair_uses_latest_published_release_not_highest_semver(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: @@ -635,7 +771,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** ) def test_stable_published_releases_requires_boolean_flags(field: str, value: object) -> None: release: dict[str, object] = { - "tagName": "v0.4.3", + "tagName": "v0.4.6", "isDraft": False, "isPrerelease": False, "publishedAt": "2026-02-01T00:00:00Z", @@ -649,7 +785,7 @@ def test_stable_published_releases_requires_boolean_flags(field: str, value: obj @pytest.mark.parametrize("published_at", ["2026-02-01T00:00:00", "not-a-timestamp", ""]) def test_stable_published_releases_requires_aware_timestamp(published_at: str) -> None: release = { - "tagName": "v0.4.3", + "tagName": "v0.4.6", "isDraft": False, "isPrerelease": False, "publishedAt": published_at, @@ -663,7 +799,7 @@ def test_stable_published_releases_normalizes_timestamp_to_utc() -> None: releases = archive_performance._stable_published_releases( [ { - "tagName": "v0.4.3", + "tagName": "v0.4.6", "isDraft": False, "isPrerelease": False, "publishedAt": "2026-02-01T01:00:00+01:00", @@ -675,7 +811,7 @@ def test_stable_published_releases_normalizes_timestamp_to_utc() -> None: def test_resolve_archive_request_infer_release_uses_package_version_and_previous_release(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: - (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.3"\n', encoding="utf-8") + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: assert command == "gh" @@ -683,8 +819,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert cwd == tmp_path return _result( "[" - '{"tagName":"v0.4.1","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' - '{"tagName":"v0.4.2","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' + '{"tagName":"v0.4.4","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' + '{"tagName":"v0.4.5","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' "]" ) @@ -702,13 +838,13 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** ) ) - assert request.current_tag == "v0.4.3" - assert request.baseline_tag == "v0.4.2" + assert request.current_tag == "v0.4.6" + assert request.baseline_tag == "v0.4.5" assert request.worktree_ref == "HEAD" - assert request.tags_to_fetch == ("v0.4.2",) + assert request.tags_to_fetch == ("v0.4.5",) -@pytest.mark.parametrize("package_version", ["0.4.4", "0.4.3"]) +@pytest.mark.parametrize("package_version", ["0.4.4", "0.4.6"]) def test_resolve_archive_request_infer_release_requires_unpublished_package_version( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -722,14 +858,14 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert cwd == tmp_path return _result( "[" - '{"tagName":"v0.4.3","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"},' + '{"tagName":"v0.4.6","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"},' '{"tagName":"v0.4.4","isDraft":false,"isPrerelease":false,"publishedAt":"2026-03-01T00:00:00Z"}' "]" ) monkeypatch.setattr(archive_performance, "run_safe_command", fake_run_safe) - with pytest.raises(ValueError, match=r"must be newer than latest published stable release v0\.4\.4"): + with pytest.raises(ValueError, match=r"must be newer than latest published stable release v0\.4\.6"): archive_performance.resolve_archive_request( archive_performance.ArchiveRequestOptions( current_tag=None, @@ -744,7 +880,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** def test_resolve_archive_request_current_vs_latest_uses_package_version_and_latest_release(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: - (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.3"\n', encoding="utf-8") + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: assert command == "gh" @@ -752,8 +888,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert cwd == tmp_path return _result( "[" - '{"tagName":"v0.4.1","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' - '{"tagName":"v0.4.2","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' + '{"tagName":"v0.4.4","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' + '{"tagName":"v0.4.5","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' "]" ) @@ -771,23 +907,23 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** ) ) - assert request.current_tag == "v0.4.3" - assert request.baseline_tag == "v0.4.2" + assert request.current_tag == "v0.4.6" + assert request.baseline_tag == "v0.4.5" assert request.worktree_ref == "HEAD" - assert request.tags_to_fetch == ("v0.4.2",) + assert request.tags_to_fetch == ("v0.4.5",) def test_resolve_archive_request_current_vs_latest_allows_equal_release_tags_for_local_reports( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: - (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.3"\n', encoding="utf-8") + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: assert command == "gh" assert args[:2] == ["release", "list"] assert cwd == tmp_path - return _result('[{"tagName":"v0.4.3","isDraft":false,"isPrerelease":false,"publishedAt":"2026-03-01T00:00:00Z"}]') + return _result('[{"tagName":"v0.4.6","isDraft":false,"isPrerelease":false,"publishedAt":"2026-03-01T00:00:00Z"}]') monkeypatch.setattr(archive_performance, "run_safe_command", fake_run_safe) @@ -803,10 +939,10 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** ) ) - assert request.current_tag == "v0.4.3" - assert request.baseline_tag == "v0.4.3" + assert request.current_tag == "v0.4.6" + assert request.baseline_tag == "v0.4.6" assert request.worktree_ref == "HEAD" - assert request.tags_to_fetch == ("v0.4.3",) + assert request.tags_to_fetch == ("v0.4.6",) def test_benchmark_env_uses_current_repo_toolchain(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: @@ -828,7 +964,7 @@ def test_benchmark_env_respects_existing_toolchain_override(tmp_path: Path, monk def test_parser_rejects_unsupported_scope() -> None: with pytest.raises(SystemExit): - archive_performance.build_parser().parse_args(["v0.4.3", "v0.4.2", "--scope", "quick"]) + archive_performance.build_parser().parse_args(["v0.4.6", "v0.4.5", "--scope", "quick"]) @pytest.mark.parametrize( @@ -846,8 +982,8 @@ def test_generation_config_rejects_unsupported_benchmark_selection( ) -> None: kwargs: dict[str, Any] = { "repo_root": tmp_path, - "current_tag": "v0.4.3", - "baseline_tag": "v0.4.2", + "current_tag": "v0.4.6", + "baseline_tag": "v0.4.5", "worktree_ref": "HEAD", } kwargs[field] = value @@ -856,7 +992,7 @@ def test_generation_config_rejects_unsupported_benchmark_selection( GenerationConfig(**kwargs) -def test_comparison_benchmark_env_preserves_flags_and_selects_v043_adapter( +def test_comparison_benchmark_env_preserves_flags_and_selects_pre_rational_adapter( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, ) -> None: @@ -871,11 +1007,11 @@ def test_comparison_benchmark_env_preserves_flags_and_selects_v043_adapter( current = archive_performance._comparison_benchmark_env(tmp_path) baseline = archive_performance._comparison_benchmark_env( tmp_path, - api_compatibility="la_stack_v0_4_3_api", + api_compatibility="la_stack_pre_rational_input_api", ) assert current["RUSTFLAGS"] == "-C target-cpu=native --cap-lints=warn" - assert baseline["RUSTFLAGS"] == ("-C target-cpu=native --cap-lints=warn --cfg=la_stack_v0_4_3_api") + assert baseline["RUSTFLAGS"] == ("-C target-cpu=native --cap-lints=warn --cfg=la_stack_pre_rational_input_api") assert current["RUSTUP_TOOLCHAIN"] == "1.97.0" @@ -914,10 +1050,10 @@ def test_comparison_benchmark_env_extends_encoded_rustflags( env = archive_performance._comparison_benchmark_env( tmp_path, - api_compatibility="la_stack_v0_4_3_api", + api_compatibility="la_stack_pre_rational_input_api", ) - assert env["CARGO_ENCODED_RUSTFLAGS"] == ("-C\x1ftarget-cpu=native\x1f--cap-lints=warn\x1f--cfg=la_stack_v0_4_3_api") + assert env["CARGO_ENCODED_RUSTFLAGS"] == ("-C\x1ftarget-cpu=native\x1f--cap-lints=warn\x1f--cfg=la_stack_pre_rational_input_api") assert env["RUSTUP_TOOLCHAIN"] == "nightly" @@ -931,7 +1067,7 @@ def test_fallback_baseline_cargo_commands_enforce_lockfile( _write_legacy_benchmark_tooling(worktree) command, args = archive_performance._baseline_tool_args( - baseline_tag="v0.4.2", + baseline_tag="v0.4.5", suite=suite, baseline_worktree=worktree, ) @@ -955,6 +1091,32 @@ def test_fallback_current_cargo_command_matches_suite( assert archive_performance._fallback_current_command(suite=suite) == expected +@pytest.mark.parametrize("github_assets", [False, True]) +@pytest.mark.parametrize("baseline", ["v0.4.3", "v0.4.2"]) +def test_unsupported_baseline_fails_before_fetch_or_worktree( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + capsys: pytest.CaptureFixture[str], + github_assets: bool, + baseline: str, +) -> None: + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") + monkeypatch.chdir(tmp_path) + + def fail_external_work(*_args: object, **_kwargs: object) -> None: + pytest.fail("unsupported baseline reached external work") + + monkeypatch.setattr(archive_performance, "run_git_command", fail_external_work) + monkeypatch.setattr(archive_performance, "run_safe_command", fail_external_work) + args = ["v0.4.6", baseline, "--generate-in-temp-worktree"] + if github_assets: + args.append("--github-assets") + + assert main(args) == 1 + assert "comparisons require v0.4.4 or newer" in capsys.readouterr().err + assert not (tmp_path / "target").exists() + + def test_promote_report_archives_previous_and_updates_sorted_index(tmp_path: Path) -> None: source = tmp_path / "target" / "bench-reports" / "performance.md" current = tmp_path / "docs" / "performance.md" @@ -963,27 +1125,27 @@ def test_promote_report_archives_previous_and_updates_sorted_index(tmp_path: Pat source.parent.mkdir(parents=True) current.parent.mkdir(parents=True) archive_dir.mkdir(parents=True) - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") - current.write_text(_report("0.4.1", "v0.4.0"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") + current.write_text(_report("0.4.4", "v0.4.0"), encoding="utf-8") (archive_dir / "v0.3.1-vs-v0.3.0.md").write_text(_report("0.3.1", "v0.3.0"), encoding="utf-8") promoted = promote_report( source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.2", - expected_baseline_tag="v0.4.1", + expected_current_tag="v0.4.5", + expected_baseline_tag="v0.4.4", ) - assert promoted.archive_name == "v0.4.2-vs-v0.4.1.md" - assert current.read_text(encoding="utf-8") == _normalized_report("0.4.2", "v0.4.1") - assert (archive_dir / "v0.4.1-vs-v0.4.0.md").read_text(encoding="utf-8") == _normalized_report("0.4.1", "v0.4.0") + assert promoted.archive_name == "v0.4.5-vs-v0.4.4.md" + assert current.read_text(encoding="utf-8") == _normalized_report("0.4.5", "v0.4.4") + assert (archive_dir / "v0.4.4-vs-v0.4.0.md").read_text(encoding="utf-8") == _normalized_report("0.4.4", "v0.4.0") assert (archive_dir / "README.md").read_text(encoding="utf-8") == ( "# Archived Performance Reports\n\n" "Older release-to-release benchmark comparisons are archived here.\n" "`docs/performance.md` contains the latest curated comparison.\n\n" "- [v0.3.1-vs-v0.3.0](v0.3.1-vs-v0.3.0.md)\n" - "- [v0.4.1-vs-v0.4.0](v0.4.1-vs-v0.4.0.md)\n" + "- [v0.4.4-vs-v0.4.0](v0.4.4-vs-v0.4.0.md)\n" ) @@ -992,19 +1154,19 @@ def test_promote_report_is_idempotent_for_same_release_pair(tmp_path: Path) -> N current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") current.parent.mkdir(parents=True) - current.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + current.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") promote_report( source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.2", - expected_baseline_tag="v0.4.1", + expected_current_tag="v0.4.5", + expected_baseline_tag="v0.4.4", ) - assert not (archive_dir / "v0.4.2-vs-v0.4.1.md").exists() + assert not (archive_dir / "v0.4.5-vs-v0.4.4.md").exists() assert "- No archived performance reports yet." in (archive_dir / "README.md").read_text(encoding="utf-8") @@ -1012,21 +1174,21 @@ def test_promote_report_does_not_overwrite_existing_archive(tmp_path: Path) -> N source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - archived = archive_dir / "v0.4.1-vs-v0.4.0.md" + archived = archive_dir / "v0.4.4-vs-v0.4.0.md" - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") current.parent.mkdir(parents=True) - current.write_text(_report("0.4.1", "v0.4.0"), encoding="utf-8") + current.write_text(_report("0.4.4", "v0.4.0"), encoding="utf-8") archive_dir.mkdir(parents=True) - archived_payload = _normalized_report("0.4.1", "v0.4.0").replace("\n", "\r\n").encode() + archived_payload = _normalized_report("0.4.4", "v0.4.0").replace("\n", "\r\n").encode() archived.write_bytes(archived_payload) promote_report( source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.2", - expected_baseline_tag="v0.4.1", + expected_current_tag="v0.4.5", + expected_baseline_tag="v0.4.4", ) assert archived.read_bytes() == archived_payload @@ -1036,11 +1198,11 @@ def test_promote_report_rejects_mismatched_existing_archive_without_mutation(tmp source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - archived = archive_dir / "v0.4.1-vs-v0.4.0.md" + archived = archive_dir / "v0.4.4-vs-v0.4.0.md" index = archive_dir / "README.md" - original = _report("0.4.1", "v0.4.0") + original = _report("0.4.4", "v0.4.0") - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") current.parent.mkdir(parents=True) current.write_text(original, encoding="utf-8") archive_dir.mkdir(parents=True) @@ -1052,8 +1214,8 @@ def test_promote_report_rejects_mismatched_existing_archive_without_mutation(tmp source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.2", - expected_baseline_tag="v0.4.1", + expected_current_tag="v0.4.5", + expected_baseline_tag="v0.4.4", ) assert current.read_text(encoding="utf-8") == original @@ -1066,10 +1228,10 @@ def test_promote_report_rejects_non_file_archive_collision_without_mutation(tmp_ source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - archived = archive_dir / "v0.4.1-vs-v0.4.0.md" - original = _report("0.4.1", "v0.4.0") + archived = archive_dir / "v0.4.4-vs-v0.4.0.md" + original = _report("0.4.4", "v0.4.0") - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") current.parent.mkdir(parents=True) current.write_text(original, encoding="utf-8") archive_dir.mkdir(parents=True) @@ -1085,8 +1247,8 @@ def test_promote_report_rejects_non_file_archive_collision_without_mutation(tmp_ source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.2", - expected_baseline_tag="v0.4.1", + expected_current_tag="v0.4.5", + expected_baseline_tag="v0.4.4", ) assert current.read_text(encoding="utf-8") == original @@ -1097,15 +1259,15 @@ def test_promote_report_rejects_unexpected_release_pair(tmp_path: Path) -> None: source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - source.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + source.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") with pytest.raises(ValueError, match="does not match requested release pair"): promote_report( source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.3", - expected_baseline_tag="v0.4.2", + expected_current_tag="v0.4.6", + expected_baseline_tag="v0.4.5", ) @@ -1113,20 +1275,20 @@ def test_promote_report_rewrites_legacy_update_instructions(tmp_path: Path) -> N source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - source.write_text(_legacy_report("0.4.3", "v0.4.2"), encoding="utf-8") + source.write_text(_legacy_report("0.4.6", "v0.4.5"), encoding="utf-8") current.parent.mkdir(parents=True) - current.write_text(_legacy_report("0.4.2", "v0.4.1"), encoding="utf-8") + current.write_text(_legacy_report("0.4.5", "v0.4.4"), encoding="utf-8") promote_report( source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.3", - expected_baseline_tag="v0.4.2", + expected_current_tag="v0.4.6", + expected_baseline_tag="v0.4.5", ) current_text = current.read_text(encoding="utf-8") - archived_text = (archive_dir / "v0.4.2-vs-v0.4.1.md").read_text(encoding="utf-8") + archived_text = (archive_dir / "v0.4.5-vs-v0.4.4.md").read_text(encoding="utf-8") assert "just performance-local" in current_text assert "just performance-release" in current_text assert "just performance-github-assets" in current_text @@ -1145,12 +1307,12 @@ def test_main_promotes_generated_report_to_docs_performance( source = tmp_path / "target" / "bench-reports" / "performance.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - generated = _report("0.4.3", "v0.4.2") + generated = _report("0.4.6", "v0.4.5") source.parent.mkdir(parents=True) source.write_text(generated, encoding="utf-8") current.parent.mkdir(parents=True) - current.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + current.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") gates: list[Path] = [] monkeypatch.chdir(tmp_path) monkeypatch.setattr( @@ -1161,8 +1323,8 @@ def test_main_promotes_generated_report_to_docs_performance( rc = main( [ - "v0.4.3", - "v0.4.2", + "v0.4.6", + "v0.4.5", "--source", str(source), "--current", @@ -1174,9 +1336,9 @@ def test_main_promotes_generated_report_to_docs_performance( assert rc == 0 assert current.read_text(encoding="utf-8") == archive_performance._normalize_how_to_update(generated) - assert (archive_dir / "v0.4.2-vs-v0.4.1.md").exists() + assert (archive_dir / "v0.4.5-vs-v0.4.4.md").exists() assert gates == [tmp_path] - assert "Current performance report: v0.4.3 vs v0.4.2" in capsys.readouterr().out + assert "Current performance report: v0.4.6 vs v0.4.5" in capsys.readouterr().out def test_main_reports_release_pair_mismatch_to_stderr( @@ -1188,13 +1350,13 @@ def test_main_reports_release_pair_mismatch_to_stderr( current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" source.parent.mkdir(parents=True) - source.write_text(_report("0.4.3", "v0.4.2"), encoding="utf-8") + source.write_text(_report("0.4.6", "v0.4.5"), encoding="utf-8") monkeypatch.setattr(archive_performance, "_run_benchmark_input_gate", lambda *_args, **_kwargs: None) rc = main( [ "v0.4.4", - "v0.4.3", + "v0.4.6", "--source", str(source), "--current", @@ -1361,7 +1523,7 @@ def fail_external_work(*_args: object, **_kwargs: object) -> None: config=GenerationConfig( repo_root=tmp_path, current_tag="v0.4.4", - baseline_tag="v0.4.3", + baseline_tag="v0.4.6", worktree_ref="HEAD", ), ) @@ -1369,7 +1531,7 @@ def fail_external_work(*_args: object, **_kwargs: object) -> None: assert not output.exists() -@pytest.mark.parametrize("alias", ["artifact-csv", "current-report"]) +@pytest.mark.parametrize("alias", ["artifact-csv", "full-csv", "full-json", "current-report"]) def test_main_promote_artifacts_rejects_output_alias_without_mutation( tmp_path: Path, capsys: pytest.CaptureFixture[str], @@ -1385,12 +1547,17 @@ def test_main_promote_artifacts_rejects_output_alias_without_mutation( artifacts.provenance.write_bytes(b"original provenance\n") current = tmp_path / "docs" / "performance.md" current.parent.mkdir(parents=True) - current.write_text(_report("0.4.3", "v0.4.2"), encoding="utf-8") + current.write_text(_report("0.4.6", "v0.4.5"), encoding="utf-8") archive_dir = tmp_path / "docs" / "archive" / "performance" - output = artifacts.csv if alias == "artifact-csv" else current + output = { + "artifact-csv": artifacts.csv, + "full-csv": full_summary_paths(artifacts).csv, + "full-json": full_summary_paths(artifacts).provenance, + "current-report": current, + }[alias] bundle = SimpleNamespace( context=SimpleNamespace( - release=SimpleNamespace(current="v0.4.4", baseline="v0.4.3"), + release=SimpleNamespace(current="v0.4.4", baseline="v0.4.6"), ) ) monkeypatch.chdir(tmp_path) @@ -1398,7 +1565,7 @@ def test_main_promote_artifacts_rejects_output_alias_without_mutation( monkeypatch.setattr( archive_performance, "render_release_artifacts", - lambda _paths: _report("0.4.4", "v0.4.3"), + lambda _paths: _report("0.4.4", "v0.4.6"), ) rc = main( @@ -1422,7 +1589,7 @@ def test_main_promote_artifacts_rejects_output_alias_without_mutation( assert "must use distinct paths" in captured.err assert artifacts.csv.read_bytes() == b"original csv\n" assert artifacts.provenance.read_bytes() == b"original provenance\n" - assert current.read_text(encoding="utf-8") == _report("0.4.3", "v0.4.2") + assert current.read_text(encoding="utf-8") == _report("0.4.6", "v0.4.5") assert not archive_dir.exists() @@ -1435,7 +1602,7 @@ def fail_unexpected(*, args: object, paths: object, request: object, repo_root: monkeypatch.setattr(archive_performance, "_run_archive_request", fail_unexpected) with pytest.raises(AssertionError, match="unexpected test failure"): - main(["v0.4.3", "v0.4.2"]) + main(["v0.4.6", "v0.4.5"]) def test_main_generates_report_in_temp_worktree(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: @@ -1457,13 +1624,13 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.2", "exact"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.5", "exact"]: assert cwd is not None criterion_dir = cwd / "target" / "criterion" criterion_dir.mkdir(parents=True) (criterion_dir / "baseline.txt").write_text("baseline\n", encoding="utf-8") if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.chdir(tmp_path) @@ -1473,15 +1640,15 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** rc = main( [ - "v0.4.3", - "v0.4.2", + "v0.4.6", + "v0.4.5", "--current", str(current), "--archive-dir", str(archive_dir), "--generate-in-temp-worktree", "--worktree-ref", - "v0.4.3", + "v0.4.6", "--no-apply-current-diff", "--suite", "exact", @@ -1497,7 +1664,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert output.read_text(encoding="utf-8") == current.read_text(encoding="utf-8") assert "Generated benchmark report in a temporary worktree" in captured.out assert str(output) in captured.out - assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.3" for kind, args, _ in calls) + assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.6" for kind, args, _ in calls) assert any(kind == "just" and args == ("bench-exact",) for kind, args, _ in calls) assert any(kind == "uv" and "--suite" in args and args[args.index("--suite") + 1] == "exact" for kind, args, _ in calls) assert any(kind == "uv" and args[:2] == ("run", "--locked") for kind, args, _ in calls) @@ -1522,7 +1689,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** def test_temp_worktree_is_removed_when_benchmark_command_fails(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: - (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.3"\n', encoding="utf-8") + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" calls: list[RunnerCall] = [] @@ -1546,7 +1713,7 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.2"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.5"]: assert cwd is not None criterion_dir = cwd / "target" / "criterion" criterion_dir.mkdir(parents=True) @@ -1562,8 +1729,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** rc = main( [ - "v0.4.3", - "v0.4.2", + "v0.4.6", + "v0.4.5", "--current", str(current), "--archive-dir", @@ -1615,8 +1782,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** rc = main( [ - "v0.4.3", - "v0.4.2", + "v0.4.6", + "v0.4.5", "--current", str(current), "--archive-dir", @@ -1644,7 +1811,7 @@ def test_generate_report_generates_release_baseline_locally( # noqa: PLR0915 capsys: pytest.CaptureFixture[str], ) -> None: monkeypatch.delenv("RUSTUP_TOOLCHAIN", raising=False) - (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.3"\n', encoding="utf-8") + (tmp_path / "Cargo.toml").write_text('[package]\nversion = "0.4.6"\n', encoding="utf-8") (tmp_path / "rust-toolchain.toml").write_text('[toolchain]\nchannel = "1.97.0"\n', encoding="utf-8") current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" @@ -1667,14 +1834,14 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.2"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.5"]: assert kwargs["env"]["RUSTUP_TOOLCHAIN"] == "1.97.0" assert cwd is not None assert "bench-latest" in (cwd / "justfile").read_text(encoding="utf-8") criterion_dir = cwd / "target" / "criterion" criterion_dir.mkdir(parents=True) (criterion_dir / "baseline.txt").write_text("baseline\n", encoding="utf-8") - for sample in ("new", "v0.4.2"): + for sample in ("new", "v0.4.5"): estimates = criterion_dir / "exact_d2" / "det_exact" / sample / "estimates.json" estimates.parent.mkdir(parents=True, exist_ok=True) estimates.write_text("{}\n", encoding="utf-8") @@ -1683,12 +1850,12 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert cwd is not None criterion_dir = cwd / "target" / "criterion" / "exact_d2" / "det_exact" assert not (criterion_dir / "new").exists() - assert (criterion_dir / "v0.4.2" / "estimates.json").is_file() + assert (criterion_dir / "v0.4.5" / "estimates.json").is_file() if command == "uv": report_root = Path(args[args.index("--repo-root") + 1]) criterion_root = Path(args[args.index("--criterion-dir") + 1]) metadata = json.loads((criterion_root / archive_performance._BENCHMARK_HARNESS_METADATA).read_text(encoding="utf-8")) - assert metadata["baseline"] == "v0.4.2" + assert metadata["baseline"] == "v0.4.5" assert metadata["mode"] == "shared-current-harness" assert metadata["schema"] == 2 assert metadata["measurement"]["harness_sha256"] == archive_performance._benchmark_harness_digest(report_root) @@ -1697,7 +1864,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert metadata["criterion"]["criterion_version"] == "manifest requirement 0.7.0" assert metadata["validation"]["baseline_revision"] == "passed" assert metadata["validation"]["current_revision"] == "passed" - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.chdir(tmp_path) @@ -1707,8 +1874,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** rc = main( [ - "v0.4.3", - "v0.4.2", + "v0.4.6", + "v0.4.5", "--current", str(current), "--archive-dir", @@ -1724,18 +1891,18 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert rc == 0 assert captured.err.splitlines() == [ "[performance] validating benchmark inputs in baseline-worktree", - "[performance] running all baseline benchmarks for v0.4.2", - "[performance] completed all baseline benchmarks for v0.4.2", + "[performance] running all baseline benchmarks for v0.4.5; includes nalgebra/faer measurements", + "[performance] completed all baseline benchmarks for v0.4.5", "[performance] validating benchmark inputs in worktree", - "[performance] running current all benchmarks", + "[performance] running current all benchmarks for v0.4.6; la-stack only, reusing baseline nalgebra/faer measurements", "[performance] completed current all benchmarks", ] assert current.read_text(encoding="utf-8") == _retained_report(tmp_path) assert not any(kind == "gh" for kind, _, _ in calls) - assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.2") for kind, args, _ in calls) + assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.5") for kind, args, _ in calls) assert any(kind == "just" and args == ("bench-latest",) for kind, args, _ in calls) assert any(kind == "uv" and "--suite" in args for kind, args, _ in calls) - baseline_timing_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "just" and args == ("bench-save-baseline", "v0.4.2")) + baseline_timing_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "just" and args == ("bench-save-baseline", "v0.4.5")) current_timing_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "just" and args == ("bench-latest",)) baseline_gate_index = next( index @@ -1778,7 +1945,7 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.3", "vs_linalg"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.6", "vs_linalg"]: assert kwargs["env"]["RUSTUP_TOOLCHAIN"] == "1.97.0" assert cwd is not None assert "bench-latest" in (cwd / "justfile").read_text(encoding="utf-8") @@ -1788,7 +1955,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** if command == "just" and args == ["bench-vs-linalg-la-stack"]: assert kwargs["env"]["RUSTUP_TOOLCHAIN"] == "1.97.0" if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.3") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.6") return _result() monkeypatch.setattr(archive_performance, "run_git_command", fake_run_git) @@ -1799,19 +1966,19 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** output=output, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.3", - baseline_tag="v0.4.3", + current_tag="v0.4.6", + baseline_tag="v0.4.6", worktree_ref="HEAD", suite="vs_linalg", apply_current_diff=False, ), ) - assert report_id.archive_name == "v0.4.3-vs-v0.4.3.md" + assert report_id.archive_name == "v0.4.6-vs-v0.4.6.md" assert output.read_text(encoding="utf-8") == _retained_report(tmp_path) assert output.with_suffix(".csv").is_file() assert output.with_suffix(".provenance.json").is_file() - assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.3", "vs_linalg") for kind, args, _ in calls) + assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.6", "vs_linalg") for kind, args, _ in calls) assert any(kind == "just" and args == ("bench-vs-linalg-la-stack",) for kind, args, _ in calls) assert any(kind == "uv" and "--csv-output" in args and "--provenance-output" in args for kind, args, _ in calls) assert not any(kind == "cargo" for kind, _, _ in calls) @@ -1832,7 +1999,18 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** assert not current.exists() -def test_generate_local_report_artifacts_can_be_rendered_and_promoted(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: +def _fail_retained_summary_index(_archive: Path) -> None: + msg = "simulated retained summary promotion failure" + raise OSError(msg) + + +@pytest.mark.parametrize("fail_promotion", [False, True]) +def test_generate_local_report_artifacts_can_be_rendered_and_promoted( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + *, + fail_promotion: bool, +) -> None: output = tmp_path / "target" / "bench-reports" / "performance.md" calls: list[RunnerCall] = [] @@ -1850,13 +2028,19 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.2", "vs_linalg"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.5", "vs_linalg"]: assert cwd is not None criterion_dir = cwd / "target" / "criterion" criterion_dir.mkdir(parents=True) (criterion_dir / "baseline.txt").write_text("baseline\n", encoding="utf-8") + for sample in ("v0.4.5", "new"): + _write_measurement(criterion_dir, "lu_solve_pivoting_d2/faer_lu_solve", sample, 20.0) + _write_measurement(criterion_dir, "lu_solve_pivoting_d2/la_stack_lu_solve", sample, 10.0) + if command == "just" and args == ["bench-vs-linalg-la-stack"]: + assert cwd is not None + _write_measurement(cwd / "target/criterion", "lu_solve_pivoting_d2/la_stack_lu_solve", "new", 8.123456789012345) if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.setattr(archive_performance, "run_git_command", fake_run_git) @@ -1867,21 +2051,34 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** output=output, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.3", - baseline_tag="v0.4.2", + current_tag="v0.4.6", + baseline_tag="v0.4.5", worktree_ref="HEAD", suite="vs_linalg", apply_current_diff=False, ), ) - assert report_id.archive_name == "v0.4.3-vs-v0.4.2.md" - assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.2", "vs_linalg") for kind, args, _ in calls) + assert report_id.archive_name == "v0.4.6-vs-v0.4.5.md" + assert any(kind == "just" and args == ("bench-save-baseline", "v0.4.5", "vs_linalg") for kind, args, _ in calls) assert any(kind == "just" and args == ("bench-vs-linalg-la-stack",) for kind, args, _ in calls) assert not any(kind == "cargo" for kind, _, _ in calls) assert not any(kind == "just" and args == ("bench-exact",) for kind, args, _ in calls) current = tmp_path / "docs" / "performance.md" + if fail_promotion: + monkeypatch.setattr(archive_performance, "update_archive_index", _fail_retained_summary_index) + with pytest.raises(OSError, match="simulated retained summary"): + archive_performance.render_and_promote_artifacts( + artifacts=ArtifactPaths(csv=output.with_suffix(".csv"), provenance=output.with_suffix(".provenance.json")), + output=output, + current=current, + archive_dir=tmp_path / "docs/archive/performance", + ) + assert not current.exists() + assert not list((tmp_path / "docs/performance").rglob("*.csv")) + assert not (tmp_path / "docs/performance/latest.json").exists() + return promoted = archive_performance.render_and_promote_artifacts( artifacts=ArtifactPaths( csv=output.with_suffix(".csv"), @@ -1893,6 +2090,32 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** ) assert promoted == report_id assert current.read_text(encoding="utf-8") == output.read_text(encoding="utf-8") + _assert_complete_retention_after_clean(tmp_path, calls, monkeypatch) + + +def _assert_complete_retention_after_clean(tmp_path: Path, calls: list[RunnerCall], monkeypatch: pytest.MonkeyPatch) -> None: + output = tmp_path / "target/bench-reports/performance.md" + current = tmp_path / "docs/performance.md" + original = current.read_bytes() + scratch = ArtifactPaths(csv=output.with_suffix(".csv"), provenance=output.with_suffix(".provenance.json")) + full_text = full_summary_paths(scratch).csv.read_text(encoding="utf-8") + rows = list(csv.DictReader(io.StringIO(full_text))) + assert len(rows) == 5 + assert {(row["phase"], row["benchmark_id"]) for row in rows if "faer" in row["benchmark_id"]} == { + ("baseline", "lu_solve_pivoting_d2/faer_lu_solve"), + } + precise = next(row for row in rows if row["phase"] == "current" and row["benchmark_id"].startswith("lu_solve_pivoting")) + assert float(precise["mean_ns"]) == 8.123456789012345 + shutil.rmtree(tmp_path / "target") + retained = resolve_report_paths(tmp_path, scratch) + assert full_summary_paths(retained).csv.read_text(encoding="utf-8") == full_text + assert _resolve_performance_paths(tmp_path, "target/bench-reports/performance.csv") == retained + calls.clear() + monkeypatch.chdir(tmp_path) + assert main(["--promote-artifacts"]) == 0 + assert not calls + assert current.read_bytes() == original + assert full_summary_paths(retained).csv.read_text(encoding="utf-8") == full_text def test_main_generates_latest_published_report_from_github_releases(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: @@ -1917,8 +2140,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** if command == "gh" and args[:2] == ["release", "list"]: return _result( "[" - '{"tagName":"v0.4.2","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' - '{"tagName":"v0.4.3","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' + '{"tagName":"v0.4.5","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' + '{"tagName":"v0.4.6","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' "]" ) if command == "gh": @@ -1926,7 +2149,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** tag = args[2] _write_baseline_archive(download_dir / f"la-stack-{tag}-criterion-baseline.tar.gz") if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.chdir(tmp_path) @@ -1955,15 +2178,15 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** == ( "fetch", "origin", - "refs/tags/v0.4.3:refs/tags/v0.4.3", - "refs/tags/v0.4.2:refs/tags/v0.4.2", + "refs/tags/v0.4.6:refs/tags/v0.4.6", + "refs/tags/v0.4.5:refs/tags/v0.4.5", ) for kind, args, _ in calls ) fetch_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "git" and args[:2] == ("fetch", "origin")) worktree_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "git" and args[:3] == ("worktree", "add", "--detach")) assert fetch_index < worktree_index - assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.3" for kind, args, _ in calls) + assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.6" for kind, args, _ in calls) def test_main_normalizes_explicit_bare_tags_before_fetching_and_checkout(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: @@ -1991,7 +2214,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** tag = args[2] _write_baseline_archive(download_dir / f"la-stack-{tag}-criterion-baseline.tar.gz") if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.chdir(tmp_path) @@ -2001,8 +2224,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** rc = main( [ - "0.4.3", - "0.4.2", + "0.4.6", + "0.4.5", "--current", str(current), "--archive-dir", @@ -2010,7 +2233,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** "--github-assets", "--generate-in-temp-worktree", "--worktree-ref", - "0.4.3", + "0.4.6", "--output-only", "--output", str(output), @@ -2026,17 +2249,17 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** == ( "fetch", "origin", - "refs/tags/v0.4.2:refs/tags/v0.4.2", - "refs/tags/v0.4.3:refs/tags/v0.4.3", + "refs/tags/v0.4.5:refs/tags/v0.4.5", + "refs/tags/v0.4.6:refs/tags/v0.4.6", ) for kind, args, _ in calls ) fetch_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "git" and args[:2] == ("fetch", "origin")) worktree_index = next(index for index, (kind, args, _) in enumerate(calls) if kind == "git" and args[:3] == ("worktree", "add", "--detach")) assert fetch_index < worktree_index - assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.3" for kind, args, _ in calls) - assert any(kind == "gh" and args[:3] == ("release", "download", "v0.4.2") for kind, args, _ in calls) - assert any(kind == "gh" and args[:3] == ("release", "download", "v0.4.3") for kind, args, _ in calls) + assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.6" for kind, args, _ in calls) + assert any(kind == "gh" and args[:3] == ("release", "download", "v0.4.5") for kind, args, _ in calls) + assert any(kind == "gh" and args[:3] == ("release", "download", "v0.4.6") for kind, args, _ in calls) def test_main_published_latest_fetch_failure_stops_before_worktree(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: @@ -2063,8 +2286,8 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** if command == "gh" and args[:2] == ["release", "list"]: return _result( "[" - '{"tagName":"v0.4.2","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' - '{"tagName":"v0.4.3","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' + '{"tagName":"v0.4.5","isDraft":false,"isPrerelease":false,"publishedAt":"2026-01-01T00:00:00Z"},' + '{"tagName":"v0.4.6","isDraft":false,"isPrerelease":false,"publishedAt":"2026-02-01T00:00:00Z"}' "]" ) return _result() @@ -2100,9 +2323,9 @@ def test_failed_atomic_replace_preserves_existing_report(tmp_path: Path, monkeyp source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - original = _report("0.4.2", "v0.4.1") + original = _report("0.4.5", "v0.4.4") - source.write_text(_report("0.4.3", "v0.4.2"), encoding="utf-8") + source.write_text(_report("0.4.6", "v0.4.5"), encoding="utf-8") current.parent.mkdir(parents=True) current.write_text(original, encoding="utf-8") @@ -2117,33 +2340,46 @@ def fail_replace(src: Path, dst: Path) -> None: source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.3", - expected_baseline_tag="v0.4.2", + expected_current_tag="v0.4.6", + expected_baseline_tag="v0.4.5", ) assert current.read_text(encoding="utf-8") == original assert not list(current.parent.glob(".performance.md.*.tmp")) -def test_restore_file_removes_temp_when_fsync_fails( +@pytest.mark.parametrize("operation", ["write", "restore"]) +@pytest.mark.parametrize("failure_point", ["create", "fsync", "replace"]) +def test_atomic_report_update_failure_preserves_original_and_cleans_temp( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, + operation: str, + failure_point: str, ) -> None: target = tmp_path / "docs" / "performance.md" target.parent.mkdir() target.write_text("current\n", encoding="utf-8") - def fail_fsync(_descriptor: int) -> None: - msg = "simulated fsync failure" + def fail(*_args: object, **_kwargs: object) -> Never: + msg = f"simulated {failure_point} failure" raise OSError(msg) - monkeypatch.setattr(archive_performance.os, "fsync", fail_fsync) + if failure_point == "create": + monkeypatch.setattr(archive_performance.tempfile, "NamedTemporaryFile", fail) + elif failure_point == "fsync": + monkeypatch.setattr(archive_performance.os, "fsync", fail) + else: + monkeypatch.setattr(archive_performance.Path, "replace", fail) - with pytest.raises(OSError, match="simulated fsync failure"): - archive_performance._restore_file(target, b"restored\n") + if operation == "write": + with pytest.raises(OSError, match=f"simulated {failure_point} failure"): + archive_performance._write_text(target, "updated\n") + else: + with pytest.raises(OSError, match=f"simulated {failure_point} failure"): + archive_performance._restore_file(target, b"restored\n") assert target.read_text(encoding="utf-8") == "current\n" - assert not list(target.parent.glob(".performance.md.*.restore")) + assert list(target.parent.iterdir()) == [target] def test_failed_archive_index_update_rolls_back_report_and_new_archive( @@ -2153,8 +2389,8 @@ def test_failed_archive_index_update_rolls_back_report_and_new_archive( source = tmp_path / "performance-new.md" current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" - original = _normalized_report("0.4.2", "v0.4.1") - source.write_text(_report("0.4.3", "v0.4.2"), encoding="utf-8") + original = _normalized_report("0.4.5", "v0.4.4") + source.write_text(_report("0.4.6", "v0.4.5"), encoding="utf-8") current.parent.mkdir(parents=True) current.write_text(original, encoding="utf-8") @@ -2169,12 +2405,12 @@ def fail_index(_archive_dir: Path) -> None: source=source, current=current, archive_dir=archive_dir, - expected_current_tag="v0.4.3", - expected_baseline_tag="v0.4.2", + expected_current_tag="v0.4.6", + expected_baseline_tag="v0.4.5", ) assert current.read_text(encoding="utf-8") == original - assert not (archive_dir / "v0.4.2-vs-v0.4.1.md").exists() + assert not (archive_dir / "v0.4.5-vs-v0.4.4.md").exists() assert not (archive_dir / "README.md").exists() @@ -2186,7 +2422,7 @@ def test_failed_artifact_promotion_output_write_rolls_back_report_archive_and_in archive_dir = tmp_path / "docs" / "archive" / "performance" index = archive_dir / "README.md" output = tmp_path / "target" / "bench-reports" / "performance.md" - original_current = _report("0.4.2", "v0.4.1") + original_current = _report("0.4.5", "v0.4.4") original_index = "original index\n" original_output = "original output\n" current.parent.mkdir(parents=True) @@ -2207,11 +2443,11 @@ def fail_output_write(path: Path, text: str) -> None: with pytest.raises(OSError, match="simulated artifact promotion output failure"): archive_performance._promote_report_text( - source_text=_report("0.4.3", "v0.4.2"), + source_text=_report("0.4.6", "v0.4.5"), request=archive_performance.PromotionRequest( current=current, archive_dir=archive_dir, - expected=archive_performance.ReportId(current_tag="v0.4.3", baseline_tag="v0.4.2"), + expected=archive_performance.ReportId(current_tag="v0.4.6", baseline_tag="v0.4.5"), output=output, ), ) @@ -2219,14 +2455,14 @@ def fail_output_write(path: Path, text: str) -> None: assert current.read_text(encoding="utf-8") == original_current assert index.read_text(encoding="utf-8") == original_index assert output.read_text(encoding="utf-8") == original_output - assert not (archive_dir / "v0.4.2-vs-v0.4.1.md").exists() + assert not (archive_dir / "v0.4.5-vs-v0.4.4.md").exists() def test_generate_and_promote_rejects_artifact_alias_before_worktree(tmp_path: Path) -> None: current = tmp_path / "docs" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" current.parent.mkdir(parents=True) - current.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + current.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") artifacts = ArtifactPaths( csv=current, provenance=current.with_suffix(".provenance.json"), @@ -2239,31 +2475,33 @@ def test_generate_and_promote_rejects_artifact_alias_before_worktree(tmp_path: P archive_dir=archive_dir, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.3", - baseline_tag="v0.4.2", + current_tag="v0.4.6", + baseline_tag="v0.4.5", worktree_ref="HEAD", ), artifacts=artifacts, ) - assert current.read_text(encoding="utf-8") == _report("0.4.2", "v0.4.1") + assert current.read_text(encoding="utf-8") == _report("0.4.5", "v0.4.4") assert not archive_dir.exists() -def test_generate_output_only_rejects_artifact_alias_before_worktree(tmp_path: Path) -> None: - output = tmp_path / "target" / "bench-reports" / "performance.md" +@pytest.mark.parametrize("alias", ["selected", "full-csv", "full-json"]) +def test_generate_output_only_rejects_artifact_alias_before_worktree(tmp_path: Path, alias: str) -> None: + report = tmp_path / "target" / "bench-reports" / "performance.csv" artifacts = ArtifactPaths( - csv=output, - provenance=output.with_suffix(".provenance.json"), + csv=report, + provenance=report.with_suffix(".provenance.json"), ) + output = {"selected": report, "full-csv": full_summary_paths(artifacts).csv, "full-json": full_summary_paths(artifacts).provenance}[alias] with pytest.raises(ValueError, match="must use distinct paths"): generate_worktree_report( output=output, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.3", - baseline_tag="v0.4.2", + current_tag="v0.4.6", + baseline_tag="v0.4.5", worktree_ref="HEAD", ), artifacts=artifacts, @@ -2283,7 +2521,7 @@ def test_generate_and_promote_uses_temp_worktree_and_current_diff( output = tmp_path / "target" / "bench-reports" / "performance.md" archive_dir = tmp_path / "docs" / "archive" / "performance" current.parent.mkdir(parents=True) - current.write_text(_report("0.4.2", "v0.4.1"), encoding="utf-8") + current.write_text(_report("0.4.5", "v0.4.4"), encoding="utf-8") calls: list[RunnerCall] = [] def fake_run_git(args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: @@ -2304,7 +2542,7 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str | bytes, cwd: P def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.2"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.5"]: assert kwargs["env"]["RUSTUP_TOOLCHAIN"] == "1.97.0" assert cwd is not None criterion_dir = cwd / "target" / "criterion" @@ -2313,7 +2551,7 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** if command == "just" and args == ["bench-latest"]: assert kwargs["env"]["RUSTUP_TOOLCHAIN"] == "1.97.0" if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.3", baseline="v0.4.2") + _write_fake_rendered_artifacts(args, version="0.4.6", baseline="v0.4.5") return _result() monkeypatch.setattr(archive_performance, "run_git_command", fake_run_git) @@ -2326,17 +2564,17 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** archive_dir=archive_dir, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.3", - baseline_tag="v0.4.2", + current_tag="v0.4.6", + baseline_tag="v0.4.5", worktree_ref="HEAD", apply_current_diff=True, ), ) - assert report_id.archive_name == "v0.4.3-vs-v0.4.2.md" + assert report_id.archive_name == "v0.4.6-vs-v0.4.5.md" assert current.read_text(encoding="utf-8") == _retained_report(tmp_path) assert output.read_text(encoding="utf-8") == current.read_text(encoding="utf-8") - assert (archive_dir / "v0.4.2-vs-v0.4.1.md").exists() + assert (archive_dir / "v0.4.5-vs-v0.4.4.md").exists() assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "HEAD" for kind, args, _ in calls) assert any(kind == "git-stdin" and args == ("apply", "--binary") for kind, args, _ in calls) assert any(kind == "just" and args == ("bench-latest",) for kind, args, _ in calls) @@ -2364,13 +2602,13 @@ def fake_run_git_with_input(args: Sequence[str], input_data: str, cwd: Path | No def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, **kwargs: Any) -> SimpleNamespace: calls.append((command, tuple(args), cwd)) - if command == "just" and args == ["bench-save-baseline", "v0.4.1"]: + if command == "just" and args == ["bench-save-baseline", "v0.4.4"]: assert cwd is not None criterion_dir = cwd / "target" / "criterion" criterion_dir.mkdir(parents=True) (criterion_dir / "baseline.txt").write_text("baseline\n", encoding="utf-8") if command == "uv": - _write_fake_rendered_artifacts(args, version="0.4.2", baseline="v0.4.1") + _write_fake_rendered_artifacts(args, version="0.4.5", baseline="v0.4.4") return _result() monkeypatch.setattr(archive_performance, "run_git_command", fake_run_git) @@ -2383,17 +2621,17 @@ def fake_run_safe(command: str, args: Sequence[str], cwd: Path | None = None, ** archive_dir=archive_dir, config=GenerationConfig( repo_root=tmp_path, - current_tag="v0.4.2", - baseline_tag="v0.4.1", - worktree_ref="v0.4.2", + current_tag="v0.4.5", + baseline_tag="v0.4.4", + worktree_ref="v0.4.5", apply_current_diff=False, ), ) - assert report_id.archive_name == "v0.4.2-vs-v0.4.1.md" + assert report_id.archive_name == "v0.4.5-vs-v0.4.4.md" assert current.read_text(encoding="utf-8") == _retained_report(tmp_path) assert output.read_text(encoding="utf-8") == current.read_text(encoding="utf-8") - assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.2" for kind, args, _ in calls) + assert any(kind == "git" and args[:3] == ("worktree", "add", "--detach") and args[4] == "v0.4.5" for kind, args, _ in calls) assert any(kind == "cargo" and args == ("bench", "--locked", "--features", "bench,exact") for kind, args, _ in calls) assert not any(kind == "just" and args == ("bench-exact",) for kind, args, _ in calls) assert not any(kind == "just" and args == ("bench-latest",) for kind, args, _ in calls) diff --git a/scripts/tests/test_bench_compare.py b/scripts/tests/test_bench_compare.py index 8324329..181c4e7 100644 --- a/scripts/tests/test_bench_compare.py +++ b/scripts/tests/test_bench_compare.py @@ -4,7 +4,7 @@ import re import subprocess from types import SimpleNamespace -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Never, cast import pytest @@ -45,7 +45,7 @@ def _write_harness_provenance( criterion_dir: Path, *, sha256: str = "a" * 64, - baseline: str = "v0.4.3", + baseline: str = "v0.4.5", ) -> None: """Write valid shared-harness provenance metadata.""" criterion_dir.mkdir(parents=True, exist_ok=True) @@ -75,10 +75,10 @@ def _schema2_provenance_data() -> dict[str, object]: "source_state_sha256": "c" * 64, } return { - "baseline": "v0.4.3", - "current": "v0.4.4", + "baseline": "v0.4.5", + "current": "v0.4.6", "criterion": { - "baseline_command": ["just", "bench-save-baseline", "v0.4.3"], + "baseline_command": ["just", "bench-save-baseline", "v0.4.5"], "criterion_version": "0.7.0", "current_command": ["just", "bench-latest"], "sample": "new", @@ -87,7 +87,7 @@ def _schema2_provenance_data() -> dict[str, object]: "suite": "all", }, "measurement": { - "baseline_api_compatibility": "la_stack_v0_4_3_api", + "baseline_api_compatibility": "la_stack_pre_rational_input_api", "baseline_commit": "baseline-commit", "baseline_git_clean": False, "baseline_source_state_sha256": "d" * 64, @@ -105,7 +105,7 @@ def _schema2_provenance_data() -> dict[str, object]: "publication": environment, "schema": 2, "validation": { - "baseline_api_compatibility": "la_stack_v0_4_3_api", + "baseline_api_compatibility": "la_stack_pre_rational_input_api", "baseline_commit": "baseline-commit", "baseline_git_clean": False, "baseline_revision": "passed", @@ -124,7 +124,7 @@ def _schema2_provenance_data() -> dict[str, object]: def _read_harness_provenance( # noqa: PLR0913 criterion_dir: Path, *, - baseline: str = "v0.4.3", + baseline: str = "v0.4.5", suite: bench_compare.BenchmarkSuite = "all", scope: bench_compare.ComparisonScope = "release-signal", stat: bench_compare.Statistic = "median", @@ -417,15 +417,18 @@ def test_collect_comparisons(tmp_path: Path) -> None: # Save the same data as a baseline for d, det, det_exact in [(2, 2.0, 8000.0), (3, 10.0, 42000.0)]: group = tmp_path / f"exact_d{d}" - _write_estimates(group / "det" / "v0.3.0" / "estimates.json", "median", det) - _write_estimates(group / "det_exact" / "v0.3.0" / "estimates.json", "median", det_exact) - _write_estimates(group / "det_exact_f64" / "v0.3.0" / "estimates.json", "median", det_exact * 1.1) - _write_estimates(group / "solve_exact_f64" / "v0.3.0" / "estimates.json", "median", det_exact * 1.3) + _write_estimates(group / "det" / "v0.4.4" / "estimates.json", "median", det) + _write_estimates(group / "det_exact" / "v0.4.4" / "estimates.json", "median", det_exact) + for bench in ("det_exact_f64_result", "det_exact_rounded_f64"): + _write_estimates(group / bench / "v0.4.4" / "estimates.json", "median", det_exact * 1.1) + for bench in ("solve_exact_f64_result", "solve_exact_rounded_f64"): + _write_estimates(group / bench / "v0.4.4" / "estimates.json", "median", det_exact * 1.3) random_group = tmp_path / "exact_random_corpus_d3" - _write_estimates(random_group / "det_exact" / "v0.3.0" / "estimates.json", "median", 66000.0) - _write_estimates(random_group / "solve_exact_f64" / "v0.3.0" / "estimates.json", "median", 108000.0) + _write_estimates(random_group / "det_exact" / "v0.4.4" / "estimates.json", "median", 66000.0) + for bench in ("solve_exact_f64_result", "solve_exact_rounded_f64"): + _write_estimates(random_group / bench / "v0.4.4" / "estimates.json", "median", 108000.0) - collection = bench_compare._collect_comparisons(tmp_path, "v0.3.0", "median") + collection = bench_compare._collect_comparisons(tmp_path, "v0.4.4", "median") comparisons = collection.comparisons assert len(comparisons) == 15 # fixed dimensions plus the stable random corpus assert {c.group for c in comparisons} == { @@ -435,16 +438,11 @@ def test_collect_comparisons(tmp_path: Path) -> None: } for c in comparisons: assert c.speedup == pytest.approx(c.baseline_ns / c.current_ns) - assert {(c.bench, c.baseline_bench) for c in comparisons if c.baseline_bench is not None} == { - ("det_exact_f64_result", "det_exact_f64"), - ("det_exact_rounded_f64", "det_exact_f64"), - ("solve_exact_f64_result", "solve_exact_f64"), - ("solve_exact_rounded_f64", "solve_exact_f64"), - } + assert all(c.baseline_bench is None for c in comparisons) all_collection = bench_compare._collect_comparisons( tmp_path, - "v0.3.0", + "v0.4.4", "median", policy=bench_compare.ComparisonPolicy(scope="all-benches"), ) @@ -453,14 +451,14 @@ def test_collect_comparisons(tmp_path: Path) -> None: random_comparisons = [c for c in all_comparisons if c.group == "exact_random_corpus_d3"] assert {(c.bench, c.baseline_bench) for c in random_comparisons} == { ("det_exact", None), - ("solve_exact_f64_result", "solve_exact_f64"), - ("solve_exact_rounded_f64", "solve_exact_f64"), + ("solve_exact_f64_result", None), + ("solve_exact_rounded_f64", None), } def test_collect_comparisons_missing_baseline(tmp_path: Path) -> None: _build_criterion_tree(tmp_path) - collection = bench_compare._collect_comparisons(tmp_path, "v0.3.0", "median", suite="exact") + collection = bench_compare._collect_comparisons(tmp_path, "v0.4.4", "median", suite="exact") assert collection.comparisons == [] det_gap = next(gap for gap in collection.gaps if gap.group == "exact_d2" and gap.bench == "det") assert not det_gap.missing_current @@ -480,59 +478,6 @@ def test_collect_comparisons_records_each_missing_side_in_registry_order(tmp_pat assert (first_three[2].missing_current, first_three[2].missing_baseline) == (True, True) -def _write_v043_exact_comparison_samples( - criterion_dir: Path, - *, - missing_current: frozenset[tuple[str, str]] = frozenset(), -) -> None: - unavailable = bench_compare._V0_4_3_UNAVAILABLE_BASELINE_ROWS - for group, benches in bench_compare.EXACT_GROUPS.items(): - for bench in benches: - row = (group, bench) - if row not in missing_current: - _write_estimates(criterion_dir / group / bench / "new" / "estimates.json", "median", 10.0) - if row not in unavailable: - _write_estimates(criterion_dir / group / bench / "v0.4.3" / "estimates.json", "median", 20.0) - - -def test_v043_adapter_requires_bound_only_baselines_but_allows_missing_paired_rows(tmp_path: Path) -> None: - _write_v043_exact_comparison_samples(tmp_path) - - collection = bench_compare._collect_comparisons( - tmp_path, - "v0.4.3", - "median", - suite="exact", - policy=bench_compare.ComparisonPolicy(baseline_api_compatibility="la_stack_v0_4_3_api"), - ) - - assert collection.gaps == [] - comparison_rows = {(comparison.group, comparison.bench) for comparison in collection.comparisons} - assert all((f"exact_d{dimension}", "det_errbound") in comparison_rows for dimension in (2, 3, 4)) - assert all((f"exact_d{dimension}", "det_direct_with_errbound") not in comparison_rows for dimension in (2, 3, 4)) - - -def test_v043_adapter_reports_missing_current_for_unavailable_paired_row(tmp_path: Path) -> None: - target = ("exact_d2", "det_direct_with_errbound") - _write_v043_exact_comparison_samples(tmp_path, missing_current=frozenset({target})) - - collection = bench_compare._collect_comparisons( - tmp_path, - "v0.4.3", - "median", - suite="exact", - policy=bench_compare.ComparisonPolicy(baseline_api_compatibility="la_stack_v0_4_3_api"), - ) - - assert len(collection.gaps) == 1 - gap = collection.gaps[0] - assert gap.suite == "exact" - assert gap.group == target[0] - assert gap.bench == target[1] - assert gap.missing_current - assert not gap.missing_baseline - - def test_pre_rational_adapter_retains_current_rational_rows_without_baselines(tmp_path: Path) -> None: for group, bench in bench_compare._RATIONAL_INPUT_ROWS: _write_estimates(tmp_path / group / bench / "new" / "estimates.json", "median", 10.0) @@ -568,7 +513,7 @@ def test_pre_rational_historical_harness_excludes_rational_registry_rows(tmp_pat collection = bench_compare._collect_comparisons( tmp_path, - "v0.4.4", + "v0.4.6", "median", suite="exact", policy=policy, @@ -663,69 +608,6 @@ def test_d8_release_signal_rows_are_explicit_and_report_missing_baselines( assert all(not gap.missing_current and gap.missing_baseline for gap in special_gaps) -def test_v043_adapter_allows_only_known_unavailable_d8_baselines(tmp_path: Path) -> None: - group = tmp_path / "d8" - for bench in bench_compare.VS_LINALG_D8_RELEASE_SIGNAL_BENCHES: - _write_estimates(group / bench / "new" / "estimates.json", "median", 10.0) - _write_estimates( - group / "la_stack_det_from_lu_balanced_range" / "v0.4.3" / "estimates.json", - "median", - 1.0, - ) - - collection = bench_compare._collect_comparisons( - tmp_path, - "v0.4.3", - "median", - suite="vs_linalg", - policy=bench_compare.ComparisonPolicy(baseline_api_compatibility="la_stack_v0_4_3_api"), - ) - - special_gaps = [gap for gap in collection.gaps if gap.bench in bench_compare.VS_LINALG_D8_RELEASE_SIGNAL_BENCHES] - assert [gap.bench for gap in special_gaps] == [ - "la_stack_lu_pivoting", - "la_stack_lu_ill_conditioned", - "la_stack_ldlt_ill_conditioned", - ] - assert all(not gap.missing_current and gap.missing_baseline for gap in special_gaps) - assert not any("balanced_range" in comparison.bench for comparison in collection.comparisons) - - -def test_v043_adapter_still_requires_current_balanced_range_sample(tmp_path: Path) -> None: - group = tmp_path / "d8" - _write_estimates( - group / "la_stack_det_from_lu_balanced_range" / "new" / "estimates.json", - "median", - 10.0, - ) - - collection = bench_compare._collect_comparisons( - tmp_path, - "v0.4.3", - "median", - suite="vs_linalg", - policy=bench_compare.ComparisonPolicy(baseline_api_compatibility="la_stack_v0_4_3_api"), - ) - - balanced_gaps = [gap for gap in collection.gaps if "balanced_range" in gap.bench] - assert [(gap.bench, gap.missing_current, gap.missing_baseline) for gap in balanced_gaps] == [("la_stack_det_from_ldlt_balanced_range", True, False)] - - -def test_v043_adapter_validates_current_balanced_range_sample(tmp_path: Path) -> None: - estimate = tmp_path / "d8" / "la_stack_det_from_lu_balanced_range" / "new" / "estimates.json" - estimate.parent.mkdir(parents=True) - estimate.write_text("{not json", encoding="utf-8") - - with pytest.raises(ValueError, match="malformed Criterion estimates JSON"): - bench_compare._collect_comparisons( - tmp_path, - "v0.4.3", - "median", - suite="vs_linalg", - policy=bench_compare.ComparisonPolicy(baseline_api_compatibility="la_stack_v0_4_3_api"), - ) - - def test_collect_vs_linalg_release_signal_uses_baseline_peer_context(tmp_path: Path) -> None: _build_vs_linalg_tree(tmp_path) collection = bench_compare._collect_comparisons(tmp_path, "last", "median", suite="vs_linalg") @@ -743,6 +625,24 @@ def test_collect_vs_linalg_release_signal_uses_baseline_peer_context(tmp_path: P assert ldlt.baseline_faer_ns == 48.0 +@pytest.mark.parametrize("native_ns", [None, 5.0]) +def test_dot_peer_context_never_substitutes_legacy_scalar_loop(tmp_path: Path, native_ns: float | None) -> None: + group = tmp_path / "d2" + _write_estimates(group / "la_stack_dot/last/estimates.json", "median", 20.0) + _write_estimates(group / "la_stack_dot/new/estimates.json", "median", 10.0) + _write_estimates(group / "nalgebra_dot/last/estimates.json", "median", 8.0) + _write_estimates(group / "faer_dot/last/estimates.json", "median", 1.0) + if native_ns is not None: + _write_estimates(group / "faer_dot_native/last/estimates.json", "median", native_ns) + + collection = bench_compare._collect_comparisons(tmp_path, "last", "median", suite="vs_linalg") + + [dot] = collection.comparisons + assert dot.bench == "la_stack_dot" + assert dot.baseline_nalgebra_ns == 8.0 + assert dot.baseline_faer_ns == native_ns + + def test_collect_vs_linalg_all_benches_includes_latest_peer_rows(tmp_path: Path) -> None: _build_vs_linalg_tree(tmp_path) collection = bench_compare._collect_comparisons( @@ -795,18 +695,20 @@ def test_comparison_uses_one_table_per_suite_with_case_column(tmp_path: Path) -> _build_criterion_tree(tmp_path) for d, det, det_exact in [(2, 2.0, 8000.0), (3, 10.0, 42000.0)]: group = tmp_path / f"exact_d{d}" - _write_estimates(group / "det" / "v0.3.0" / "estimates.json", "median", det) - _write_estimates(group / "det_exact" / "v0.3.0" / "estimates.json", "median", det_exact) - _write_estimates(group / "det_exact_f64" / "v0.3.0" / "estimates.json", "median", det_exact * 1.1) - _write_estimates(group / "solve_exact_f64" / "v0.3.0" / "estimates.json", "median", det_exact * 1.3) - - comparisons = bench_compare._collect_comparisons(tmp_path, "v0.3.0", "median").comparisons - tables = bench_compare._comparison_tables(comparisons, "v0.3.0") - assert tables.count("| Case | Benchmark | v0.3.0 (point + CI)") == 1 + _write_estimates(group / "det" / "v0.4.4" / "estimates.json", "median", det) + _write_estimates(group / "det_exact" / "v0.4.4" / "estimates.json", "median", det_exact) + for bench in ("det_exact_f64_result", "det_exact_rounded_f64"): + _write_estimates(group / bench / "v0.4.4" / "estimates.json", "median", det_exact * 1.1) + for bench in ("solve_exact_f64_result", "solve_exact_rounded_f64"): + _write_estimates(group / bench / "v0.4.4" / "estimates.json", "median", det_exact * 1.3) + + comparisons = bench_compare._collect_comparisons(tmp_path, "v0.4.4", "median").comparisons + tables = bench_compare._comparison_tables(comparisons, "v0.4.4") + assert tables.count("| Case | Benchmark | v0.4.4 (point + CI)") == 1 assert "| D=2 |" in tables assert "| D=3 |" in tables - assert "det_exact_rounded_f64 (vs det_exact_f64)" in tables - assert "solve_exact_f64_result (vs solve_exact_f64)" in tables + assert "| det_exact_rounded_f64 |" in tables + assert "| solve_exact_f64_result |" in tables def test_comparison_tables_include_vs_linalg_peer_context(tmp_path: Path) -> None: @@ -857,7 +759,7 @@ def test_read_harness_provenance_validates_shared_harness_metadata(tmp_path: Pat schema=1, mode="shared-current-harness", sha256="a" * 64, - baseline="v0.4.3", + baseline="v0.4.5", ) policy = bench_compare._comparison_policy("release-signal", provenance) assert policy == bench_compare.ComparisonPolicy( @@ -867,7 +769,7 @@ def test_read_harness_provenance_validates_shared_harness_metadata(tmp_path: Pat collection = bench_compare._collect_comparisons( tmp_path, - "v0.4.3", + "v0.4.5", "median", suite="exact", policy=policy, @@ -897,20 +799,13 @@ def test_read_schema2_provenance_records_versions_dirty_source_and_both_gates(tm assert "Criterion dependency version: `0.7.0`" in rendered assert "Current Git clean: `false`" in rendered assert "Validated baseline revision: `baseline-commit`" in rendered - assert "Baseline API compatibility: `la_stack_v0_4_3_api`" in rendered - assert "d8/la_stack_det_from_lu_balanced_range" in rendered - assert "d8/la_stack_det_from_ldlt_balanced_range" in rendered - assert "exact determinant is one" in rendered - assert "exact_d2/det_direct_with_errbound" in rendered - assert "exact_d3/det_direct_with_errbound" in rendered - assert "exact_d4/det_direct_with_errbound" in rendered + assert "Baseline API compatibility: `la_stack_pre_rational_input_api`" in rendered assert "rational_input_d{2..8}/*" in rendered assert "**Publication and validation environment**:" in rendered assert all(len(line) <= 160 for line in markdown) - assert "the comparable `det_errbound` baselines remain required" in rendered assert bench_compare._comparison_policy("release-signal", provenance) == bench_compare.ComparisonPolicy( scope="release-signal", - baseline_api_compatibility="la_stack_v0_4_3_api", + baseline_api_compatibility="la_stack_pre_rational_input_api", ) assert provenance.measurement is not None with pytest.raises(TypeError): @@ -968,7 +863,7 @@ def test_read_schema2_provenance_rejects_recorded_measurement_without_cpu_model( ("suite", "exact"), ("scope", "all-benches"), ("statistic", "mean"), - ("sample", "v0.4.3"), + ("sample", "v0.4.5"), ], ) def test_read_schema2_provenance_binds_criterion_settings_to_request( @@ -986,16 +881,16 @@ def test_read_schema2_provenance_binds_criterion_settings_to_request( _read_harness_provenance(tmp_path) -def test_read_schema2_provenance_rejects_v043_adapter_for_other_baseline(tmp_path: Path) -> None: +def test_read_schema2_provenance_rejects_pre_rational_adapter_for_newer_baseline(tmp_path: Path) -> None: data = _schema2_provenance_data() - data["baseline"] = "v0.4.4" + data["baseline"] = "v0.4.6" (tmp_path / ".la-stack-benchmark-harness.json").write_text(json.dumps(data), encoding="utf-8") with pytest.raises( ValueError, - match=r"must be 'la_stack_pre_rational_input_api' for baseline 'v0\.4\.4'", + match=r"must be 'none' for baseline 'v0\.4\.6'", ): - _read_harness_provenance(tmp_path, baseline="v0.4.4") + _read_harness_provenance(tmp_path, baseline="v0.4.6") def test_read_schema2_provenance_accepts_pre_rational_adapter_for_v045(tmp_path: Path) -> None: @@ -1037,7 +932,7 @@ def test_read_schema2_provenance_rejects_revision_contradiction(tmp_path: Path) def test_read_harness_provenance_rejects_different_requested_baseline(tmp_path: Path) -> None: - _write_harness_provenance(tmp_path, baseline="v0.4.3") + _write_harness_provenance(tmp_path, baseline="v0.4.5") with pytest.raises(ValueError, match="does not match requested Criterion baseline 'last'"): _read_harness_provenance(tmp_path, baseline="last") @@ -1065,7 +960,7 @@ def test_read_harness_provenance_rejects_malformed_fields( "schema": 1, "mode": "shared-current-harness", "sha256": "a" * 64, - "baseline": "v0.4.3", + "baseline": "v0.4.5", } data[field] = value tmp_path.mkdir(parents=True, exist_ok=True) @@ -1138,7 +1033,7 @@ def test_main_comparison_no_baseline(tmp_path: Path, capsys: pytest.CaptureFixtu criterion_dir = tmp_path / "criterion" _build_criterion_tree(criterion_dir) - rc = bench_compare.main(["v0.3.0", "--criterion-dir", str(criterion_dir), "--output", str(tmp_path / "out.md")]) + rc = bench_compare.main(["v0.4.4", "--criterion-dir", str(criterion_dir), "--output", str(tmp_path / "out.md")]) assert rc == 2 assert "No comparison data" in capsys.readouterr().err @@ -1147,11 +1042,11 @@ def test_main_comparison_refuses_incomplete_coverage_before_writing(tmp_path: Pa criterion_dir = tmp_path / "criterion" group = criterion_dir / "exact_d2" _write_estimates(group / "det" / "new" / "estimates.json", "median", 10.0) - _write_estimates(group / "det" / "v0.4.3" / "estimates.json", "median", 20.0) + _write_estimates(group / "det" / "v0.4.5" / "estimates.json", "median", 20.0) _write_harness_provenance(criterion_dir) output = tmp_path / "report.md" - rc = bench_compare.main(["v0.4.3", "--suite", "exact", "--criterion-dir", str(criterion_dir), "--output", str(output)]) + rc = bench_compare.main(["v0.4.5", "--suite", "exact", "--criterion-dir", str(criterion_dir), "--output", str(output)]) assert rc == 2 assert not output.exists() @@ -1219,7 +1114,7 @@ def test_main_rejects_invalid_artifact_paths_without_writing( rc = bench_compare.main( [ - "v0.4.3", + "v0.4.5", "--repo-root", str(tmp_path), "--output", @@ -1334,12 +1229,12 @@ def test_markdown_failure_rolls_back_release_artifact_pair(tmp_path: Path, monke timing = bench_compare.TimingEstimate(median_ns=10.0, ci_lower_ns=9.0, ci_upper_ns=11.0) bundle = bench_compare.PerformanceBundle( context=bench_compare.ArtifactContext( - release=bench_compare.ReleasePair(current="v0.4.4", baseline="v0.4.3"), + release=bench_compare.ReleasePair(current="v0.4.6", baseline="v0.4.5"), statistic="median", suite="all", scope="release-signal", source=bench_compare.ReportSource( - version="0.4.4", + version="0.4.6", commit="current-commit", ref="HEAD", revision_timestamp="2026-08-04 12:00:00 UTC", @@ -1376,7 +1271,7 @@ def fail_markdown(_path: Path, _text: str) -> None: root=tmp_path, criterion_dir=tmp_path, settings=bench_compare.ReportSettings( - baseline_name="v0.4.3", + baseline_name="v0.4.5", stat="median", suite="all", scope="release-signal", @@ -1389,87 +1284,31 @@ def fail_markdown(_path: Path, _text: str) -> None: assert output.read_text(encoding="utf-8") == "old markdown\n" -def test_atomic_markdown_write_removes_temp_when_fsync_fails( +@pytest.mark.parametrize("failure_point", ["create", "fsync", "replace"]) +def test_atomic_markdown_write_failure_preserves_original_and_cleans_temp( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, + failure_point: str, ) -> None: output = tmp_path / "performance.md" output.write_text("old\n", encoding="utf-8") - def fail_fsync(_descriptor: int) -> None: - msg = "simulated fsync failure" + def fail(*_args: object, **_kwargs: object) -> Never: + msg = f"simulated {failure_point} failure" raise OSError(msg) - monkeypatch.setattr(bench_compare.os, "fsync", fail_fsync) + if failure_point == "create": + monkeypatch.setattr(bench_compare.tempfile, "NamedTemporaryFile", fail) + elif failure_point == "fsync": + monkeypatch.setattr(bench_compare.os, "fsync", fail) + else: + monkeypatch.setattr(bench_compare.Path, "replace", fail) - with pytest.raises(OSError, match="simulated fsync failure"): + with pytest.raises(OSError, match=f"simulated {failure_point} failure"): bench_compare._write_text_atomic(output, "new\n") assert output.read_text(encoding="utf-8") == "old\n" - assert not list(tmp_path.glob(".performance.md.*.tmp")) - - -def test_main_v043_comparison_allows_only_unavailable_balanced_baselines( - tmp_path: Path, - monkeypatch: pytest.MonkeyPatch, -) -> None: - criterion_dir = tmp_path / "criterion" - unavailable = bench_compare._V0_4_3_UNAVAILABLE_BASELINE_ROWS - for dimension in bench_compare.VS_LINALG_CANONICAL_DIMS: - group = f"d{dimension}" - benches = { - *bench_compare.VS_LINALG_LA_STACK_BENCHES, - *bench_compare.VS_LINALG_RELEASE_SIGNAL_BENCHES_BY_DIM.get(dimension, []), - } - for bench in benches: - _write_estimates(criterion_dir / group / bench / "new" / "estimates.json", "median", 10.0) - if (group, bench) not in unavailable: - _write_estimates(criterion_dir / group / bench / "v0.4.3" / "estimates.json", "median", 20.0) - - provenance = _schema2_provenance_data() - criterion = provenance["criterion"] - assert isinstance(criterion, dict) - cast("dict[str, object]", criterion)["suite"] = "vs_linalg" - (criterion_dir / ".la-stack-benchmark-harness.json").write_text(json.dumps(provenance), encoding="utf-8") - output = tmp_path / "report.md" - artifact_paths = bench_compare.ArtifactPaths( - csv=tmp_path / "performance.csv", - provenance=tmp_path / "performance.provenance.json", - ) - monkeypatch.setattr( - bench_compare, - "_report_source", - lambda _root: bench_compare.ReportSource( - version="0.4.4", - commit="current-commit", - ref="test", - revision_timestamp="2026-08-04 12:00:00 UTC", - ), - ) - - rc = bench_compare.main( - [ - "v0.4.3", - "--suite", - "vs_linalg", - "--criterion-dir", - str(criterion_dir), - "--csv-output", - str(artifact_paths.csv), - "--provenance-output", - str(artifact_paths.provenance), - "--output", - str(output), - ] - ) - - assert rc == 0 - rendered = output.read_text(encoding="utf-8") - assert rendered == bench_compare.render_release_artifacts(artifact_paths) - assert "d8/la_stack_det_from_lu_balanced_range" in rendered - assert "d8/la_stack_det_from_ldlt_balanced_range" in rendered - assert "current-only" in rendered - assert "no correctness-compatible benchmark row" in rendered + assert list(tmp_path.iterdir()) == [output] def test_main_v045_comparison_publishes_current_only_rational_rows( @@ -1594,7 +1433,7 @@ def test_main_rejects_harness_provenance_for_a_different_baseline( group = criterion_dir / "exact_d2" _write_estimates(group / "det" / "new" / "estimates.json", "median", 10.0) _write_estimates(group / "det" / "last" / "estimates.json", "median", 20.0) - _write_harness_provenance(criterion_dir, baseline="v0.4.3") + _write_harness_provenance(criterion_dir, baseline="v0.4.5") output = tmp_path / "report.md" rc = bench_compare.main(["last", "--suite", "exact", "--criterion-dir", str(criterion_dir), "--output", str(output)]) diff --git a/scripts/tests/test_criterion_dim_plot.py b/scripts/tests/test_criterion_dim_plot.py index b1ddc80..977755c 100644 --- a/scripts/tests/test_criterion_dim_plot.py +++ b/scripts/tests/test_criterion_dim_plot.py @@ -4,6 +4,7 @@ import hashlib import json import re +import shutil import subprocess import tomllib from dataclasses import replace @@ -13,6 +14,7 @@ import pytest import criterion_dim_plot +from benchmark_summaries import retained_outputs, summary_outputs from performance_artifacts import ( ArtifactContext, ArtifactPaths, @@ -21,6 +23,7 @@ ReleasePair, ReportSource, TimingEstimate, + load_bundle, write_bundle, ) @@ -63,8 +66,9 @@ def test_detect_versions_matches_cargo_toml() -> None: package_version = version expected_la = package_version or "unknown" - expected_na = _toml_dependency_version(data, "nalgebra") or "unknown" - expected_fa = _toml_dependency_version(data, "faer") or "unknown" + comparison = tomllib.loads((root / "benches/comparison/Cargo.toml").read_text(encoding="utf-8")) + expected_na = _toml_dependency_version(comparison, "nalgebra") or "unknown" + expected_fa = _toml_dependency_version(comparison, "faer") or "unknown" versions = criterion_dim_plot._detect_versions(root) @@ -233,7 +237,7 @@ def test_update_readme_table_errors_on_non_unique_markers(tmp_path: Path) -> Non def _canonical_benchmark_readme(version: str) -> str: begin, end = criterion_dim_plot._readme_table_markers("lu_solve", "median", "new") return ( - "[docs](https://github.com/acgetchell/la-stack/blob/v0.0.9/README.md)\n" + "[docs](https://github.com/acgetchell/la-stack/blob/v0.4.5/README.md)\n" f"[csv](https://github.com/acgetchell/la-stack/blob/v{version}/docs/assets/bench/vs_linalg_lu_solve_median.csv)\n" f"[provenance](https://github.com/acgetchell/la-stack/blob/v{version}/docs/assets/bench/vs_linalg_lu_solve_median.provenance.json)\n" f"[svg](https://raw.githubusercontent.com/acgetchell/la-stack/v{version}/docs/assets/bench/vs_linalg_lu_solve_median.svg)\n" @@ -250,7 +254,7 @@ def test_replace_readme_benchmark_asset_versions_updates_only_complete_selected_ ) assert updated.count("v1.2.3/docs/assets/bench/") == 3 - assert "blob/v0.0.9/README.md" in updated + assert "blob/v0.4.5/README.md" in updated assert "old table" in updated @@ -370,7 +374,7 @@ def _timing(value: float) -> TimingEstimate: return TimingEstimate(median_ns=value, ci_lower_ns=value * 0.9, ci_upper_ns=value * 1.1) -def _write_benchmark_checkout(root: Path, *, version: str = "0.1.0") -> None: +def _write_benchmark_checkout(root: Path, *, version: str = "0.4.6") -> None: (root / "Cargo.toml").write_text( f'[package]\nname = "fixture"\nversion = "{version}"\n[dev-dependencies]\ncriterion = "0.7"\nnalgebra = "0.34"\nfaer = "0.22"\n', encoding="utf-8", @@ -381,7 +385,7 @@ def _write_benchmark_checkout(root: Path, *, version: str = "0.1.0") -> None: for relative in ( ".config/nextest.toml", "tests/exact_bench_config.rs", - "tests/vs_linalg_inputs.rs", + "benches/comparison/tests/vs_linalg_inputs.rs", "benches/vs_linalg.rs", "src/lib.rs", ): @@ -393,7 +397,7 @@ def _write_benchmark_checkout(root: Path, *, version: str = "0.1.0") -> None: def _write_performance_bundle( root: Path, *, - version: str = "0.1.0", + version: str = "0.4.6", omit_dim: int | None = None, omit_peer_dim: int | None = None, include_contract: bool = True, @@ -419,7 +423,7 @@ def _write_performance_bundle( if include_contract: environment["benchmark_contract_sha256"] = criterion_dim_plot.benchmark_contract_digest(root) current_tag = f"v{version}" - baseline_tag = "v0.0.9" + baseline_tag = "v0.4.5" bundle = PerformanceBundle( context=ArtifactContext( release=ReleasePair(current=current_tag, baseline=baseline_tag), @@ -445,7 +449,7 @@ def _write_performance_bundle( "suite": "all", }, "measurement": { - "baseline_api_compatibility": "la_stack_v0_4_3_api", + "baseline_api_compatibility": "la_stack_pre_rational_input_api", "baseline_commit": baseline_commit, "baseline_git_clean": False, "baseline_source_state_sha256": baseline_source_sha256, @@ -460,7 +464,7 @@ def _write_performance_bundle( "publication": environment, "schema": 2, "validation": { - "baseline_api_compatibility": "la_stack_v0_4_3_api", + "baseline_api_compatibility": "la_stack_pre_rational_input_api", "baseline_commit": baseline_commit, "baseline_git_clean": False, "baseline_revision": "passed", @@ -502,6 +506,34 @@ def _write_performance_bundle( return paths +def _retain_complete_plot_inputs(root: Path, paths: ArtifactPaths) -> None: + bundle = load_bundle(paths) + baseline = bundle.context.release.baseline + criterion = root / "target/criterion" + for row in bundle.rows: + for sample, name, timing in ( + (baseline, row.benchmark, row.baseline), + ("new", row.benchmark, row.current), + (baseline, "nalgebra_lu_solve", row.baseline_nalgebra), + (baseline, "faer_lu_solve", row.baseline_faer), + ): + assert timing is not None + directory = criterion / row.group / name / sample + directory.mkdir(parents=True) + estimate = { + "point_estimate": timing.median_ns, + "confidence_interval": {"confidence_level": 0.95, "lower_bound": timing.ci_lower_ns, "upper_bound": timing.ci_upper_ns}, + } + (directory / "benchmark.json").write_text(json.dumps({"full_id": f"{row.group}/{name}"}), encoding="utf-8") + (directory / "estimates.json").write_text(json.dumps({"mean": estimate, "median": estimate}), encoding="utf-8") + (directory / "sample.json").write_text(json.dumps({"iters": [1.0] * 100, "times": [timing.median_ns] * 100}), encoding="utf-8") + for path, payload in summary_outputs(criterion, baseline, paths).items(): + path.write_text(payload, encoding="utf-8") + for path, payload in retained_outputs(root / "docs/performance", paths).items(): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(payload, encoding="utf-8") + + def test_main_update_readme_happy_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: _write_benchmark_checkout(tmp_path) performance_paths = _write_performance_bundle(tmp_path) @@ -547,14 +579,14 @@ def fake_render(request: criterion_dim_plot.PlotRequest) -> None: assert "old table" not in readme_text assert "| 2 | 10.000 | 20.000 | 40.000 | +50.0% | +75.0% |" in readme_text assert "| 64 | 320.000 | 640.000 | 1,280.000 | +50.0% | +75.0% |" in readme_text - assert readme_text.count("v0.1.0/docs/assets/bench/") == 3 - assert "blob/v0.0.9/README.md" in readme_text + assert readme_text.count("v0.4.6/docs/assets/bench/") == 3 + assert "blob/v0.4.5/README.md" in readme_text provenance = json.loads(out_csv.with_suffix(".provenance.json").read_text(encoding="utf-8")) assert provenance["measurement"]["status"] == "recorded" assert provenance["measurement"]["source"] == "retained performance-release artifact" assert provenance["measurement"]["la_stack_sample"] == "current" - assert provenance["measurement"]["peer_release_context"] == "v0.0.9" + assert provenance["measurement"]["peer_release_context"] == "v0.4.5" assert provenance["measurement"]["peer_sample"] == "baseline phase under shared current harness" assert provenance["publication"]["correctness_gate"] == "validated-performance-release-artifact" assert provenance["publication"]["benchmark_contract"] == "matched" @@ -570,6 +602,33 @@ def fake_render(request: criterion_dim_plot.PlotRequest) -> None: assert {path: (path.read_bytes(), path.stat().st_mtime_ns) for path in published} == first +def test_main_readme_replays_saved_measurements_after_artifact_commit_and_cleanup(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + _write_benchmark_checkout(tmp_path) + performance_paths = _write_performance_bundle(tmp_path) + readme = tmp_path / "README.md" + readme.write_text(_canonical_benchmark_readme("0.0.8"), encoding="utf-8") + _mock_publication_environment(tmp_path, monkeypatch) + monkeypatch.setattr(criterion_dim_plot, "_render_svg_with_gnuplot", lambda request: request.out_svg.write_text("\n", encoding="utf-8")) + assert criterion_dim_plot.main(["--update-readme"]) == 0 + out_csv = tmp_path / "docs/assets/bench/vs_linalg_lu_solve_median.csv" + out_svg = out_csv.with_suffix(".svg") + first = {path: path.read_bytes() for path in (readme, out_csv, out_svg)} + provenance = json.loads(out_csv.with_suffix(".provenance.json").read_text(encoding="utf-8")) + _retain_complete_plot_inputs(tmp_path, performance_paths) + shutil.rmtree(tmp_path / "target") + # Committing only the saved results advances HEAD without changing the + # measured source, lockfile, release, or benchmark contract. + publication_commit = "b" * 40 + monkeypatch.setattr(criterion_dim_plot, "run_git_command", lambda *_args, **_kwargs: SimpleNamespace(stdout=f"{publication_commit}\n")) + assert criterion_dim_plot.main(["--update-readme"]) == 0 + assert {path: path.read_bytes() for path in first} == first + saved_provenance = json.loads(out_csv.with_suffix(".provenance.json").read_text(encoding="utf-8")) + assert saved_provenance["performance_artifact"]["csv"].startswith("docs/performance/v0.4.6-vs-v0.4.5/") + assert saved_provenance["performance_artifact"]["csv_sha256"] == provenance["performance_artifact"]["csv_sha256"] + assert saved_provenance["measurement"]["current_commit"] == _TEST_COMMIT + assert saved_provenance["publication"]["commit"] == publication_commit + + def test_dim_parsing_and_discovery(tmp_path: Path) -> None: assert criterion_dim_plot._dim_from_group_dir("d2") == 2 assert criterion_dim_plot._dim_from_group_dir("d10") == 10 @@ -608,7 +667,7 @@ def test_toml_helpers_read_versions(tmp_path: Path) -> None: def test_format_legend_label() -> None: - assert criterion_dim_plot._format_legend_label("la-stack", "0.1.0") == "la-stack v0.1.0" + assert criterion_dim_plot._format_legend_label("la-stack", "0.4.6") == "la-stack v0.4.6" assert criterion_dim_plot._format_legend_label("faer", "unknown") == "faer" @@ -1235,6 +1294,34 @@ def test_main_publication_labels_legacy_artifact_without_contract( assert provenance["publication"]["benchmark_contract"] == "legacy-retained-artifact" +@pytest.mark.parametrize("changed", ["source", "lockfile", "release", "legacy-commit"]) +def test_main_publication_rejects_stale_measurement_identity( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + changed: str, +) -> None: + _write_benchmark_checkout(tmp_path) + _write_performance_bundle(tmp_path, include_contract=changed != "legacy-commit") + readme = tmp_path / "README.md" + original = _canonical_benchmark_readme("0.0.8") + readme.write_text(original, encoding="utf-8") + _mock_publication_environment(tmp_path, monkeypatch) + if changed == "source": + (tmp_path / "src/lib.rs").write_text("// changed source\n", encoding="utf-8") + elif changed == "lockfile": + with (tmp_path / "Cargo.lock").open("a", encoding="utf-8") as lock: + lock.write("\n# changed lock\n") + elif changed == "release": + manifest = tmp_path / "Cargo.toml" + manifest.write_text(manifest.read_text(encoding="utf-8").replace("0.4.6", "0.4.7"), encoding="utf-8") + else: + monkeypatch.setattr(criterion_dim_plot, "run_git_command", lambda *_args, **_kwargs: SimpleNamespace(stdout="b" * 40)) + + assert criterion_dim_plot.main(["--update-readme"]) == 2 + assert readme.read_text(encoding="utf-8") == original + assert not (tmp_path / "docs/assets/bench/vs_linalg_lu_solve_median.csv").exists() + + def test_main_publication_rejects_tampered_performance_csv( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -1355,6 +1442,65 @@ def fail_replacement_and_rollback(source: Path, destination: Path) -> Path: assert destination_two.read_text(encoding="utf-8") == "old two\n" +@pytest.mark.parametrize("failure_point", [None, "replace", "rollback"]) +def test_publication_keeps_backups_only_when_rollback_fails( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, + capsys: pytest.CaptureFixture[str], + failure_point: str | None, +) -> None: + destination_one = tmp_path / "one.txt" + destination_two = tmp_path / "two.txt" + staged_one = tmp_path / "staged-one.txt" + staged_two = tmp_path / "staged-two.txt" + for path, text in ( + (destination_one, "old one\n"), + (destination_two, "old two\n"), + (staged_one, "new one\n"), + (staged_two, "new two\n"), + ): + path.write_text(text, encoding="utf-8") + original_replace = criterion_dim_plot.Path.replace + + def replace(source: Path, destination: Path) -> Path: + if failure_point is not None and source == staged_two: + msg = "simulated publish failure" + raise OSError(msg) + if failure_point == "rollback" and source.name == "backup-0": + msg = "simulated rollback failure" + raise OSError(msg) + return original_replace(source, destination) + + monkeypatch.setattr(criterion_dim_plot.Path, "replace", replace) + + published = criterion_dim_plot._publish_staged_files( + [(staged_one, destination_one), (staged_two, destination_two)], + tmp_path, + ) + + assert published is (failure_point is None) + backups = list(tmp_path.glob(".criterion-dim-plot-backup-*")) + stderr = capsys.readouterr().err + if failure_point == "rollback": + assert len(backups) == 1 + assert (backups[0] / "backup-0").read_text(encoding="utf-8") == "old one\n" + assert (backups[0] / "backup-1").read_text(encoding="utf-8") == "old two\n" + assert destination_one.read_text(encoding="utf-8") == "new one\n" + assert destination_two.read_text(encoding="utf-8") == "old two\n" + assert "simulated publish failure" in stderr + assert "simulated rollback failure" in stderr + assert f"backups preserved at {backups[0]}" in stderr + else: + assert backups == [] + expected = "new" if published else "old" + assert destination_one.read_text(encoding="utf-8") == f"{expected} one\n" + assert destination_two.read_text(encoding="utf-8") == f"{expected} two\n" + if published: + assert stderr == "" + else: + assert "simulated publish failure" in stderr + + def test_repo_root_resolution_uses_working_checkout_for_installed_entrypoint(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: nested = tmp_path / "nested" nested.mkdir() diff --git a/scripts/tests/test_justfile_discoverability.py b/scripts/tests/test_justfile_discoverability.py index 319e150..98ca533 100644 --- a/scripts/tests/test_justfile_discoverability.py +++ b/scripts/tests/test_justfile_discoverability.py @@ -13,6 +13,7 @@ import pytest import update_cargo_tool_pins +from subprocess_utils import run_cargo_command, run_safe_command REPO_ROOT = Path(__file__).resolve().parents[2] @@ -43,6 +44,50 @@ def just_recipes() -> dict[str, dict[str, Any]]: return recipes +def test_exact_benchmark_package_excludes_peer_libraries() -> None: + # No dependency resolution: this also runs before Cargo caches exist in CI. + metadata = json.loads( + run_cargo_command( + ["metadata", "--locked", "--offline", "--no-deps", "--format-version", "1"], + cwd=REPO_ROOT, + ).stdout + ) + packages = {package["name"]: package for package in metadata["packages"]} + library = packages["la-stack"] + comparison = packages["la-stack-comparison"] + dependencies = {dependency["name"] for dependency in library["dependencies"]} + + assert metadata["workspace_default_members"] == [library["id"]] + assert {"criterion", "num-rational"} <= dependencies + assert not {"nalgebra", "faer", "la-stack-comparison"} & dependencies + assert "exact" in {target["name"] for target in library["targets"]} + assert "vs_linalg" not in {target["name"] for target in library["targets"]} + assert {"nalgebra", "faer"} <= {dependency["name"] for dependency in comparison["dependencies"]} + assert "vs_linalg" in {target["name"] for target in comparison["targets"]} + + +def test_release_runs_each_suite_once_and_reuses_peer_measurements() -> None: + baseline = run_just("--dry-run", "bench-save-baseline", "v0.4.5", "all") + # Execute the real recipe's shell branching while replacing only Cargo. + script = 'cargo() { printf "%s\\n" "$*"; }\n' + baseline.stderr + baseline_run = run_safe_command("bash", ["--noprofile", "--norc", "-euc", script], cwd=REPO_ROOT) + baseline_commands = [shlex.split(line) for line in baseline_run.stdout.splitlines()] + current = run_just("--dry-run", "bench-latest") + current_commands = [shlex.split(line) for line in current.stderr.splitlines() if line.startswith("cargo bench ")] + + assert len(baseline_commands) == len(current_commands) == 2 + baseline_comparison, baseline_exact = baseline_commands + current_comparison, current_exact = current_commands + for command in (baseline_comparison, current_comparison): + assert command[command.index("-p") + 1] == "la-stack-comparison" + assert command[command.index("--bench") + 1] == "vs_linalg" + for command in (baseline_exact, current_exact): + assert "-p" not in command + assert command[command.index("--bench") + 1] == "exact" + assert baseline_comparison[baseline_comparison.index("--") + 1 :] == ["--noplot", "--save-baseline", "v0.4.5"] + assert current_comparison[current_comparison.index("--") + 1 :] == ["la_stack", "--noplot"] + + def write_fake_uv(directory: Path, version_output: str, *, windows_lookup_output: str | None = None) -> None: """Write a Bash uv shim and an optional conflicting native Windows shim.""" real_uv = shutil.which("uv") diff --git a/scripts/tests/test_performance_artifacts.py b/scripts/tests/test_performance_artifacts.py index a635ccb..775485d 100644 --- a/scripts/tests/test_performance_artifacts.py +++ b/scripts/tests/test_performance_artifacts.py @@ -12,6 +12,8 @@ import pytest import performance_artifacts +from archive_performance import render_and_promote_artifacts +from benchmark_summaries import full_summary_paths, resolve_report_paths, retained_outputs, summary_outputs from performance_artifacts import ( ArtifactContext, ArtifactPaths, @@ -48,15 +50,6 @@ def _timing(value: float) -> TimingEstimate: "la_stack_pre_rational_input_api", "excluded", ), - ( - "v0.4.4", - "v0.4.3", - False, - "pre-rational-input", - "legacy-v0.4.3", - "la_stack_v0_4_3_api", - "excluded", - ), ( "v0.4.5", "v0.4.5", @@ -68,20 +61,20 @@ def _timing(value: float) -> TimingEstimate: ), ( "v0.4.6-rc.1", - "v0.4.2", + "v0.4.4", True, "rational-input", - "legacy-v0.4.3", - "la_stack_v0_4_3_api", + "pre-rational-input", + "la_stack_pre_rational_input_api", "current-only", ), ( "v1.0.0-alpha.1", - "v0.3.9-beta.2", + "v0.4.5-beta.2", True, "rational-input", - "legacy-v0.4.3", - "la_stack_v0_4_3_api", + "pre-rational-input", + "la_stack_pre_rational_input_api", "current-only", ), ( @@ -111,18 +104,21 @@ def test_shared_harness_compatibility_uses_literal_release_capability_oracle( assert resolved.rational_input_coverage == coverage +@pytest.mark.parametrize("release", ["v0.4.3", "0.4.3", "v0.4.3-rc.1", "v0.4.2", "v0.3.9"]) +@pytest.mark.parametrize("side", ["current", "baseline"]) +def test_shared_harness_rejects_unsupported_releases(release: str, side: str) -> None: + pair = {"current": "v0.4.6", "baseline": "v0.4.5", side: release} + with pytest.raises(ValueError, match=r"comparisons require v0\.4\.4 or newer"): + performance_artifacts.resolve_shared_harness_compatibility(**pair, shared_harness_rational_inputs=True) + + def _context( *, - current: str = "v0.4.4", - baseline: str = "v0.4.3", + current: str = "v0.4.6", + baseline: str = "v0.4.5", shared_harness_rational_inputs: bool = True, ) -> ArtifactContext: - if baseline in {"v0.4.2", "v0.4.3"}: - compatibility = "la_stack_v0_4_3_api" - elif baseline in {"v0.4.4", "v0.4.5"}: - compatibility = "la_stack_pre_rational_input_api" - else: - compatibility = "none" + compatibility = "la_stack_pre_rational_input_api" if baseline in {"v0.4.4", "v0.4.5"} else "none" return ArtifactContext( release=ReleasePair(current=current, baseline=baseline), statistic="median", @@ -246,6 +242,139 @@ def _simulate_promotion_failure(paths: ArtifactPaths) -> None: raise RuntimeError(msg) +def _write_outputs(outputs: dict[Path, str]) -> None: + for path, payload in outputs.items(): + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(payload, encoding="utf-8") + + +def _complete_local_artifacts(root: Path, *, current_value: float = 8.0) -> ArtifactPaths: + bundle = _bundle(current_value=current_value) + paths = ArtifactPaths(csv=root / "target/bench-reports/performance.csv", provenance=root / "target/bench-reports/performance.provenance.json") + write_bundle(paths, bundle) + criterion = root / "raw" + for row in bundle.rows: + for sample, timing in ((bundle.context.release.baseline, row.baseline), ("new", row.current)): + if timing is None: + continue + directory = criterion / row.benchmark_id / sample + estimate = { + "point_estimate": timing.median_ns, + "confidence_interval": {"confidence_level": 0.95, "lower_bound": timing.ci_lower_ns, "upper_bound": timing.ci_upper_ns}, + } + _write_outputs( + { + directory / "benchmark.json": json.dumps({"full_id": row.benchmark_id}), + directory / "estimates.json": json.dumps({"mean": estimate, "median": estimate}), + directory / "sample.json": json.dumps({"iters": [1.0] * 100, "times": [timing.median_ns] * 100}), + } + ) + _write_outputs(summary_outputs(criterion, bundle.context.release.baseline, paths)) + return paths + + +def test_complete_local_snapshots_are_idempotent_and_preserve_previous_runs(tmp_path: Path) -> None: + report = _complete_local_artifacts(tmp_path) + directory = tmp_path / "docs/performance" + first = retained_outputs(directory, report) + _write_outputs(first) + assert retained_outputs(directory, report) == first + + _complete_local_artifacts(tmp_path, current_value=7.123456789012345) + second = retained_outputs(directory, report) + _write_outputs(second) + + assert len(list(directory.rglob("performance.full.csv"))) == 2 + for path, payload in first.items(): + if path.name != "latest.json": + assert path.read_text(encoding="utf-8") == payload + assert json.loads(first[directory / "latest.json"])["run"] != json.loads(second[directory / "latest.json"])["run"] + assert retained_outputs(directory, report) == second + + +@pytest.mark.parametrize("corruption", ["digest", "columns", "samples", "counts", "schema", "provenance", "missing"]) +def test_complete_local_snapshots_reject_corrupt_or_mismatched_inputs(tmp_path: Path, corruption: str) -> None: + report = _complete_local_artifacts(tmp_path) + full = full_summary_paths(report) + if corruption in {"digest", "columns", "samples"}: + old, new = {"digest": ("8.0", "8.01"), "columns": ("mean_ns", "unknown_ns"), "samples": (",100,", ",10,")}[corruption] + full.csv.write_text(full.csv.read_text(encoding="utf-8").replace(old, new), encoding="utf-8") + elif corruption == "missing": + full.provenance.unlink() + else: + metadata = json.loads(full.provenance.read_text(encoding="utf-8")) + if corruption == "counts": + metadata["measurements"]["counts"]["current"] += 1 + elif corruption == "schema": + metadata["measurements"]["schema_version"] = True + else: + metadata["benchmark_provenance"]["measurement"]["cpu"] = "Different CPU" + full.provenance.write_text(json.dumps(metadata), encoding="utf-8") + + with pytest.raises((ValueError, FileNotFoundError)): + retained_outputs(tmp_path / "docs/performance", report) + assert not (tmp_path / "docs/performance").exists() + + +@pytest.mark.parametrize( + "destination", + ["latest.json", "performance.csv", "performance.provenance.json", "performance.full.csv", "performance.full.provenance.json"], +) +def test_repeat_promotion_protects_unchanged_retained_destinations(tmp_path: Path, destination: str) -> None: + report = _complete_local_artifacts(tmp_path) + directory = tmp_path / "docs/performance" + output = tmp_path / "target/bench-reports/performance.md" + current = tmp_path / "docs/performance.md" + archive = tmp_path / "docs/archive/performance" + render_and_promote_artifacts(artifacts=report, output=output, current=current, archive_dir=archive) + retained = retained_outputs(directory, report) + protected = {path: path.read_bytes() for path in (*retained, output, current, archive / "README.md")} + alias = next(path for path in retained if path.name == destination) + + with pytest.raises(ValueError, match="distinct"): + render_and_promote_artifacts(artifacts=report, output=alias, current=current, archive_dir=archive) + + assert {path: path.read_bytes() for path in protected} == protected + + +@pytest.mark.parametrize("requested", ["partial-csv", "partial-json", "full-csv", "full-json", "full-pair", "custom-csv", "custom-json"]) +def test_saved_summary_fallback_does_not_hide_explicit_or_partial_inputs(tmp_path: Path, requested: str) -> None: + report = _complete_local_artifacts(tmp_path) + _write_outputs(retained_outputs(tmp_path / "docs/performance", report)) + if requested != "partial-csv": + report.csv.unlink() + if requested != "partial-json": + report.provenance.unlink() + full = full_summary_paths(report) + if requested not in {"full-csv", "full-pair"}: + full.csv.unlink() + if requested not in {"full-json", "full-pair"}: + full.provenance.unlink() + if requested == "custom-csv": + report = ArtifactPaths(csv=report.csv.with_name("custom.csv"), provenance=report.provenance) + elif requested == "custom-json": + report = ArtifactPaths(csv=report.csv, provenance=report.provenance.with_name("custom.json")) + + assert resolve_report_paths(tmp_path, report) == report + with pytest.raises(FileNotFoundError, match="incomplete"): + render_and_promote_artifacts( + artifacts=resolve_report_paths(tmp_path, report), + output=tmp_path / "target/bench-reports/performance.md", + current=tmp_path / "docs/performance.md", + archive_dir=tmp_path / "docs/archive/performance", + ) + assert not (tmp_path / "docs/performance.md").exists() + + +@pytest.mark.parametrize("run", ["../outside", "/outside", "v0.4.4-vs-v0.4.3/../../outside"]) +def test_saved_summary_pointer_cannot_escape_its_directory(tmp_path: Path, run: str) -> None: + report = ArtifactPaths(csv=tmp_path / "target/bench-reports/performance.csv", provenance=tmp_path / "target/bench-reports/performance.provenance.json") + _write_outputs({tmp_path / "docs/performance/latest.json": json.dumps({"schema_version": 1, "run": run})}) + + with pytest.raises(ValueError, match="escapes"): + resolve_report_paths(tmp_path, report) + + def test_artifact_round_trip_preserves_comparable_and_one_sided_rows() -> None: bundle = _bundle() diff --git a/scripts/tests/test_postprocess_changelog.py b/scripts/tests/test_postprocess_changelog.py index 77a770b..48f43e5 100644 --- a/scripts/tests/test_postprocess_changelog.py +++ b/scripts/tests/test_postprocess_changelog.py @@ -1,7 +1,8 @@ """Tests for postprocess_changelog.py — trailing blanks, reflow, code blocks, summaries.""" import os -from typing import TYPE_CHECKING, Never +from pathlib import Path +from typing import Never import pytest @@ -27,9 +28,7 @@ postprocess, postprocess_text, ) - -if TYPE_CHECKING: - from pathlib import Path +from subprocess_utils import run_safe_command class TestStripTrailingBlanks: @@ -544,6 +543,61 @@ def test_duplicate_summary_entries_are_collapsed(self) -> None: summary_block = _merged_pr_summary_block(result) assert summary_block.count(f"- Feature A {_pr(10)}") == 1 + @pytest.mark.parametrize( + ("message", "expected_summary"), + [ + ( + "perf!: tune kernels\n\nKeep arithmetic unchanged.\n\nBREAKING CHANGE: la-stack now requires Rust 1.98.1.", + "- la-stack now requires Rust 1.98.1.", + ), + ( + "fix: change result storage\n\nBREAKING CHANGE: Return `Vector`.\nUse `into_array()` for raw storage.\n\nKeep explicit conversions.", + "- Return `Vector`.\n Use `into_array()` for raw storage.\n\n Keep explicit conversions.", + ), + ("refactor!: remove legacy API", "- Remove legacy API"), + ( + "refactor!: change generic API\n\nBREAKING CHANGE: Replace with ``Vector`` and `Result`.", + "- Replace <Old> with ``Vector`` and `Result`.", + ), + ( + "refactor!: change generic API\n\nBREAKING CHANGE: Use this signature:\n\n```rust\nfn solve() -> Result;\n```", + "- Use this signature:\n\n ```rust\n fn solve() -> Result;\n ```", + ), + ( + "chore(deps): bump toolkit\n\nBREAKING CHANGE: Require a newer runtime.", + "- Require a newer runtime.", + ), + ], + ids=["msrv-footer", "multiline-footer", "bang-only", "code-spans", "fenced-code", "dependency-footer"], + ) + def test_template_preserves_breaking_descriptions(self, message: str, expected_summary: str) -> None: + """Render actual conventional footers without mutating Git history.""" + repo_root = Path(__file__).resolve().parents[2] + raw = run_safe_command( + "git-cliff", + [ + "--offline", + "--config", + str(repo_root / "cliff.toml"), + "--strip", + "footer", + "--with-commit", + message, + "--with-commit", + "fix: retain linked entry (#987)", + "HEAD..HEAD", + ], + cwd=repo_root, + ).stdout + + result = postprocess_text(raw) + + summary = result.split("### ⚠️ Breaking Changes\n\n", 1)[1].split("\n### ", 1)[0].strip() + assert summary == expected_summary + assert result.index("### ⚠️ Breaking Changes") < result.index("### Merged Pull Requests") + assert "- Retain linked entry [#987](https://github.com/acgetchell/la-stack/pull/987)" in _merged_pr_summary_block(result) + assert postprocess_text(result) == result + class TestListMarkerNormalization: """MD004: consistent ``-`` list markers.""" diff --git a/scripts/tests/test_release_baseline.py b/scripts/tests/test_release_baseline.py index f7e21a4..a332517 100644 --- a/scripts/tests/test_release_baseline.py +++ b/scripts/tests/test_release_baseline.py @@ -168,6 +168,8 @@ def test_invalid_baseline_is_rejected(dataset: tuple[Path, Path], baseline: str) def test_inventory_includes_release_consumers_and_peers() -> None: expected = release_baseline.required_report_ids() assert {"d64/faer_lu_solve", "d64/nalgebra_lu_solve", "exact_hilbert_5x5/solve_exact", "rational_input_d8/solve_big_rational_gaussian"} <= expected + assert "d64/faer_dot_native" in expected + assert "d64/faer_dot" not in expected with pytest.raises(ValueError, match="inventory omits report consumers"): release_baseline.inventory_ids(IDS) @@ -200,7 +202,7 @@ def run(args: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]: release_baseline.discover(tmp_path, manifest, tmp_path / "criterion") assert manifest.read_bytes() == (json.dumps(IDS, indent=2) + "\n").encode("utf-8") assert calls == [ - ["bench", "--locked", "--features", "bench", "--bench", "vs_linalg", "--", "--list"], + ["bench", "--locked", "-p", "la-stack-comparison", "--features", "bench", "--bench", "vs_linalg", "--", "--list"], ["bench", "--locked", "--features", "bench,exact", "--bench", "exact", "--", "--list"], ] diff --git a/tests/exact_bench_config.rs b/tests/exact_bench_config.rs index 254771b..7c3de77 100644 --- a/tests/exact_bench_config.rs +++ b/tests/exact_bench_config.rs @@ -8,10 +8,10 @@ mod bench_utils; #[path = "../benches/common/exact.rs"] pub mod exact_bench; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[path = "../benches/common/exact_diagnostics.rs"] pub mod exact_diagnostics; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[path = "../benches/common/rational.rs"] pub mod rational_bench; @@ -26,7 +26,7 @@ use exact_bench::{ large_entries_3x3_input, make_matrix_rows, make_random_input_corpus, make_vector_array, near_singular_3x3_input, validate_exact_fixture, validate_f64_determinant_benchmarks, }; -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] use exact_diagnostics::{ConversionKind, Det4Kind, canonical_conversion_input, exact_det4_input}; fn baseline_input() -> ExactInput { @@ -40,7 +40,7 @@ fn baseline_input() -> ExactInput { } fn validate_baseline_and_random_corpus() { - #[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] + #[cfg(not(la_stack_pre_rational_input_api))] for kind in ConversionKind::ALL { let _ = canonical_conversion_input::(kind); } @@ -51,7 +51,7 @@ fn validate_baseline_and_random_corpus() { } } -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[test] fn determinant_diagnostic_fixtures_are_correct() { for kind in Det4Kind::ALL { @@ -60,7 +60,7 @@ fn determinant_diagnostic_fixtures_are_correct() { } /// Keep the filter-resolved control and typed non-finite fallback distinct. -#[cfg(not(any(la_stack_pre_rational_input_api, la_stack_v0_4_3_api)))] +#[cfg(not(la_stack_pre_rational_input_api))] #[test] fn determinant_extreme_diagnostic_filter_paths_are_stable() { use la_stack::{ArithmeticOperation, LaError}; @@ -81,7 +81,6 @@ fn determinant_extreme_diagnostic_filter_paths_are_stable() { /// Report whether `det_sign_exact` can certify this fixture through its direct filter. /// /// Both a missing bound and a direct-path error select the exact fallback. -#[cfg(not(la_stack_v0_4_3_api))] fn fast_filter_is_conclusive(input: ExactInput) -> bool { match input.matrix.det_direct_with_errbound() { Ok(Some(estimate)) => estimate.determinant().abs() > estimate.absolute_error_bound(), @@ -89,15 +88,6 @@ fn fast_filter_is_conclusive(input: ExactInput) -> bool { } } -/// Use the separate v0.4.3 determinant and bound APIs for the same filter test. -#[cfg(la_stack_v0_4_3_api)] -fn fast_filter_is_conclusive(input: ExactInput) -> bool { - match (input.matrix.det_direct(), input.matrix.det_errbound()) { - (Ok(Some(determinant)), Ok(Some(bound))) => determinant.abs() > bound, - (Ok(None) | Err(_), _) | (_, Ok(None) | Err(_)) => false, - } -} - #[test] fn i16_range_rejects_unordered_bounds() { let Err(err) = I16Range::try_new(5, 4) else { diff --git a/uv.lock b/uv.lock index 6ba90eb..4f4f4fb 100644 --- a/uv.lock +++ b/uv.lock @@ -454,7 +454,7 @@ wheels = [ [[package]] name = "la-stack-scripts" -version = "0.4.5" +version = "0.4.6" source = { editable = "." } [package.dev-dependencies] @@ -479,7 +479,7 @@ dev = [ { name = "semgrep", specifier = "==1.176.1" }, { name = "shellcheck-py", specifier = "==0.11.0.1" }, { name = "shfmt-py", specifier = "==4.2.0" }, - { name = "ty", specifier = "==0.0.78" }, + { name = "ty", specifier = "==0.0.79" }, { name = "yamllint", specifier = "==1.38.0" }, ] @@ -1178,27 +1178,27 @@ wheels = [ [[package]] name = "ty" -version = "0.0.78" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/c7/2ba0861384c5b5097ac354383abb98188112cb330208c21d5197e98a29e5/ty-0.0.78.tar.gz", hash = "sha256:770b45854f85fa11595208f08c0f28df80943164d10a2832d86be6ac29f135b2", size = 7050609, upload-time = "2026-09-02T22:41:33.92Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ea/ed/f34cfc06a9ba72979df219e48dae1a0b6a6c74a340763ccd30a547edf913/ty-0.0.78-py3-none-linux_armv6l.whl", hash = "sha256:122700b98f9d45785c1ce91a9418154562e7f64f4bf34679f6f7b38c5b97453f", size = 13304624, upload-time = "2026-09-02T22:40:56.649Z" }, - { url = "https://files.pythonhosted.org/packages/1c/28/5576e2a08b57676d9b2a736d528f077a6c6e32c3d1de2d75dbbe28346966/ty-0.0.78-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cbe7e3709ccf29ef3d9f58f5914cc30ec36fb647008a5a4ff8483abe401bfe8d", size = 12928383, upload-time = "2026-09-02T22:40:59.162Z" }, - { url = "https://files.pythonhosted.org/packages/8e/e0/027d49c3da5235e634da3d3fc52c4874ec89f50830388c9c259f8fb71e0e/ty-0.0.78-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c3528897b3ab9d3589561bc2b5e61a4d5d686de527a4400bb09a439b922a6c70", size = 12730058, upload-time = "2026-09-02T22:41:01.235Z" }, - { url = "https://files.pythonhosted.org/packages/bb/bc/6bf8ffefd8063730a70ae889cf85def72bc155fd1453135ebf8a09c2f1c2/ty-0.0.78-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bfba4c44a06484093f527b8ef43a317abcf91395b49396170266629eedf74aa", size = 12813321, upload-time = "2026-09-02T22:41:03.251Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c0/b3cdf26f82108908d92fdb7ddb741019c446ceb666cf204d4dbf611bde33/ty-0.0.78-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f903c06fdee17baf8373173039ab28f1bce28e66b1c734929a5f50b37eb54d9", size = 13072219, upload-time = "2026-09-02T22:41:05.225Z" }, - { url = "https://files.pythonhosted.org/packages/4d/36/16bfb0abdd178dae11dbc4b57b9a86c2b62642a18c1103fd2c2930aa5879/ty-0.0.78-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd83e5fe3f07291d1bd4e591f8d2607c204f3eab53bcb1b8060c40e876e1aa61", size = 13903958, upload-time = "2026-09-02T22:41:07.333Z" }, - { url = "https://files.pythonhosted.org/packages/0f/0c/74d3b1f0344b13156c719dd68a7edf7e48c2051718c9f326ba3cbf45ea53/ty-0.0.78-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:325285377319cf7168a2b8b771ae5027f411530e3c7eab1faf4583cdd72fd7c9", size = 14355581, upload-time = "2026-09-02T22:41:09.56Z" }, - { url = "https://files.pythonhosted.org/packages/8d/d7/7ca0359e1e61b15b8b02328c8d120db3c507876b9b7c6bd9f26935353e0e/ty-0.0.78-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:54b7846a404da6492697b524a769755ee9bee157d67674063ecd9c5f69dc52ff", size = 14044749, upload-time = "2026-09-02T22:41:11.678Z" }, - { url = "https://files.pythonhosted.org/packages/3b/6a/731f16ff42c5fc96e742c2f4e0a6915356bae114ae02ae4af6f33502175f/ty-0.0.78-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:169d3b9d134c0b48fe1af8a844142d374655552054a9d6c15a4b6e51bb0382ea", size = 13391647, upload-time = "2026-09-02T22:41:13.928Z" }, - { url = "https://files.pythonhosted.org/packages/0c/af/250cc29daf310e837188509ea4d78460c495d8a74c4fb84b4152d9ef2d4f/ty-0.0.78-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:6108cb3b2d28dac5981d4e25008a0a5547d8c877a67f6da9e8c38e7e946be44f", size = 13945020, upload-time = "2026-09-02T22:41:15.968Z" }, - { url = "https://files.pythonhosted.org/packages/b8/f9/96aab1dee4535e66554e8dc7657c69f6c61c181d8e70b9c3527908e93ef4/ty-0.0.78-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:589ad03608d9d2975ef4b23c41c4f847e325bcc7686f51d4c66066b8dbc18a2a", size = 12851149, upload-time = "2026-09-02T22:41:18.06Z" }, - { url = "https://files.pythonhosted.org/packages/85/b0/53d8fe9a847534ef5fe2165c7d5292cb853b29dfd7011cbfb1cdb90a8012/ty-0.0.78-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b3fa0786edc1af06030f872d83499c0cea7c261dbbb651e0aee8306bf2c8a869", size = 13091464, upload-time = "2026-09-02T22:41:20.227Z" }, - { url = "https://files.pythonhosted.org/packages/21/65/94a4e5a02de559f6c6c0ee7a14b88660b4eee058ec6fec5c0ff6ecfbf5cc/ty-0.0.78-py3-none-musllinux_1_2_i686.whl", hash = "sha256:92c5639befc577578c8abd4e5a7fccf98d828db98b09e8d4dd81605dc0e54aef", size = 13389389, upload-time = "2026-09-02T22:41:22.27Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b6/d0c7fe6be64ca5a15100c4b1f0e39c19660d53bc544f609fa117b346e661/ty-0.0.78-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0dce70bc51652b2775debd1d1e422fb0179f5207c73deb4d5d0aca37e5f61695", size = 13691928, upload-time = "2026-09-02T22:41:24.292Z" }, - { url = "https://files.pythonhosted.org/packages/0a/5d/36081205611ba3fa802efc4ad63e4b1e949bda2f7bb37b34ac9bb6c00db0/ty-0.0.78-py3-none-win32.whl", hash = "sha256:1c80976ca9185d7a9d1baab1fb57240331b8dac58d3b11e46200284086a6de8d", size = 12647346, upload-time = "2026-09-02T22:41:26.699Z" }, - { url = "https://files.pythonhosted.org/packages/f1/89/b925fe1ea1bc56fc7f11d2496e29072fdd2ceb7b389884fc7b2d07cf0c41/ty-0.0.78-py3-none-win_amd64.whl", hash = "sha256:32e82b704471eab34f67b51c151660ca8a00815977b28278905d76fba54f7415", size = 13241810, upload-time = "2026-09-02T22:41:28.857Z" }, - { url = "https://files.pythonhosted.org/packages/91/f1/090ef7b52355bcedfbfbff6ce70fa81ba5bd5f6ed3f8d99ae05e6f2fe75b/ty-0.0.78-py3-none-win_arm64.whl", hash = "sha256:3a14d641a3c04fa9a80f2a46be1531d915f60d4fb79d4b894627bbe46bb35d64", size = 13077433, upload-time = "2026-09-02T22:41:31.525Z" }, +version = "0.0.79" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/d3/4fff47468a976c7a5ded9fe350734ca09b9e8460750327f2245ea3288d5d/ty-0.0.79.tar.gz", hash = "sha256:159a1aca70edebae32be08bfba2e5d543ffd8f9f380af160e0e713e85313b733", size = 7162150, upload-time = "2026-09-07T21:51:58.065Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/a3/2fa5b5495fe37351d77571eb0985476461be02c822bb39ad669b9fdb5bb8/ty-0.0.79-py3-none-linux_armv6l.whl", hash = "sha256:f60d968bbc6d52b663d3df4cae647d3cc68df4a7135bd9098e8d570bf9a5e0da", size = 13557478, upload-time = "2026-09-07T21:51:14.089Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f0/1659a926d2b19351839ca64787e1531c97fbe8bf35c3c47d20954f338428/ty-0.0.79-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4c95ae0ca67483c4f1231c4b2fd332b76f212e8d93154c385d77511d90dcbd8e", size = 13163780, upload-time = "2026-09-07T21:51:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b2/e0a8a8cf58b39f0d1f509a22550aed1e2cc12bb4a868170b43aede9fcd93/ty-0.0.79-py3-none-macosx_11_0_arm64.whl", hash = "sha256:685888adb29b6e732ee325c6b6db92a422f72f3e4031c12450728c846e5e93fe", size = 12964040, upload-time = "2026-09-07T21:51:19.818Z" }, + { url = "https://files.pythonhosted.org/packages/88/a7/7d8fb6c958d88a63ad932421eff8848267bb9229136ef65d9f372aa2be7a/ty-0.0.79-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0535640db5dc02f9e14bf419ad2cf3acdd49681e70f233c96e96d16cfcefc00", size = 13010025, upload-time = "2026-09-07T21:51:22.468Z" }, + { url = "https://files.pythonhosted.org/packages/e3/4c/94aee26446f058e67b2c8ef0b25bdc1cf555e40eb692112d7a609f30c238/ty-0.0.79-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:48cb24e21488f9d11cffa81d5a5f71f314c87383b7a5d28dabe6feaa3f3d7a34", size = 13332191, upload-time = "2026-09-07T21:51:25.031Z" }, + { url = "https://files.pythonhosted.org/packages/6c/21/9e7c0415fa6275500f10ce13f2bad62e03211ba5f3ea61a702d819328407/ty-0.0.79-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a35b3b116a591a68da5958c082247f0c3a50f134d0a60ff45d060eb3d2ad612", size = 14153955, upload-time = "2026-09-07T21:51:27.421Z" }, + { url = "https://files.pythonhosted.org/packages/0d/5f/b27b510f973a314200cfda4f0500de3c65f6caa45a590355f6acc5e96289/ty-0.0.79-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcb760f059d660dfd5c9c6c33609478a267c3185c7448d72e6f7ff4572796bae", size = 14594578, upload-time = "2026-09-07T21:51:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/a6/fa/0ccc2e510c1c24682ae21c836c09be6dcf0b1aacab071c51a297d301601f/ty-0.0.79-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fcdc1ae0c740f9b6d6536ffecf485616a8909bed5de88c6e870a65546a6a2d91", size = 14266409, upload-time = "2026-09-07T21:51:32.868Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c3/3a404d44e9768578daf7dfda06cba714eda6feac53272eda295947a8d4c7/ty-0.0.79-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c1e77d58e192c81b958783328b303ceda8706328a307c852ceb257505765458", size = 13658441, upload-time = "2026-09-07T21:51:35.283Z" }, + { url = "https://files.pythonhosted.org/packages/f6/23/b90a512055fdf6356e95c0f745cb9b443b9a4ac9d3a79f07ae6ed53ae9ca/ty-0.0.79-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a87f52183b976d9eda5fad28405b37621a265c3de5e9e279660556c715ed1805", size = 14195669, upload-time = "2026-09-07T21:51:37.848Z" }, + { url = "https://files.pythonhosted.org/packages/b0/05/d051248dcff852e8a3165a2feb164dc5b857ef237fa82e7ea2b3b7bac375/ty-0.0.79-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:fb429a44bc9e90649e69f739d70db4a305102a36586a810caee00c984c379997", size = 13127929, upload-time = "2026-09-07T21:51:40.431Z" }, + { url = "https://files.pythonhosted.org/packages/5a/d1/60b5c980df55b1d5010a41b10d7c8cf6111b5d02ec0807f6f782bb3d88aa/ty-0.0.79-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1d857fa34d60b0981cf12ca19180ae5de70dd46306a9277bee772bb09e82ae5c", size = 13334425, upload-time = "2026-09-07T21:51:42.956Z" }, + { url = "https://files.pythonhosted.org/packages/9b/3c/fcbfa731128f06b1c9be5074f51ce47da06842dc8f33c81e7c1c483b6e91/ty-0.0.79-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a95cffa2f30289b0b949db7611ae96ede0352f0f1d7ba07ea7cabb27616fccb9", size = 13629671, upload-time = "2026-09-07T21:51:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/0e/00/3004a1d375c2a835c7dbf01c480205a190f24b74c8b5c849fd2dbe078d69/ty-0.0.79-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d33df0f1bdee62dc366551d35b9830b1fa2e9ee2936a437abd435f71b3fce73e", size = 13939769, upload-time = "2026-09-07T21:51:48.033Z" }, + { url = "https://files.pythonhosted.org/packages/10/7d/f357f5768872ffa3a026707477a880aba7582af5f6c7c7eab74f61167f3d/ty-0.0.79-py3-none-win32.whl", hash = "sha256:ca266de079a187ed6f0f5b802f6fc3b26164753c7347a04daed21d86c938d33d", size = 12833644, upload-time = "2026-09-07T21:51:50.766Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f5/2a2d967be6286ee8fb626161e610fd48624ba5e6712cea932adb2d6b40b6/ty-0.0.79-py3-none-win_amd64.whl", hash = "sha256:88cb357d36ad79181015581365769fff4b1ec580cd12de83addfa98663214fd3", size = 13494258, upload-time = "2026-09-07T21:51:53.105Z" }, + { url = "https://files.pythonhosted.org/packages/8b/74/49b88f104f88d9757497758bf57ba53e3612442b49500d1092d4d6f1daa3/ty-0.0.79-py3-none-win_arm64.whl", hash = "sha256:d29da73f2840ae2631bc62ef8f8d509a94edea596e5b3072851f67e4729d744c", size = 13327517, upload-time = "2026-09-07T21:51:55.602Z" }, ] [[package]] From 4b6e7a15d44f4f3af6b84e5cd7dbd374e0c49f2e Mon Sep 17 00:00:00 2001 From: Adam Getchell Date: Tue, 8 Sep 2026 15:38:52 -0700 Subject: [PATCH 2/2] fix(ci): restore portable Python validation - Install git-cliff in CI using the justfile pin and require that version before running Python tests - Preserve LF line endings in benchmark fixtures to prevent checksum failures on Windows - Inspect parsed Just recipe bodies when checking benchmark runs so command prefixes and formatting cannot silently omit recipes --- .github/workflows/ci.yml | 7 +++++++ justfile | 2 +- scripts/tests/test_criterion_dim_plot.py | 4 ++-- scripts/tests/test_justfile_discoverability.py | 10 ++++++++-- scripts/tests/test_performance_artifacts.py | 2 +- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c89e79..1670128 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -91,6 +91,7 @@ jobs: cargo_machete_version="$(resolve_version cargo_machete_version)" cargo_nextest_version="$(resolve_version cargo_nextest_version)" dprint_version="$(resolve_version dprint_version)" + git_cliff_version="$(resolve_version git_cliff_version)" rumdl_version="$(resolve_version rumdl_version)" taplo_version="$(resolve_version taplo_version)" typos_version="$(resolve_version typos_version)" @@ -101,6 +102,7 @@ jobs: echo "CARGO_MACHETE_VERSION=$cargo_machete_version" echo "CARGO_NEXTEST_VERSION=$cargo_nextest_version" echo "DPRINT_VERSION=$dprint_version" + echo "GIT_CLIFF_VERSION=$git_cliff_version" echo "RUMDL_VERSION=$rumdl_version" echo "TAPLO_VERSION=$taplo_version" echo "TYPOS_VERSION=$typos_version" @@ -166,5 +168,10 @@ jobs: with: tool: cargo-nextest@${{ steps.tool_versions.outputs.CARGO_NEXTEST_VERSION }} + - name: Install git-cliff + uses: taiki-e/cache-cargo-install-action@9ee83daaa7b96a6fab930949ecf1122bba04a389 # v3.0.8 + with: + tool: git-cliff@${{ steps.tool_versions.outputs.GIT_CLIFF_VERSION }} + - name: Run CI checks run: just ci diff --git a/justfile b/justfile index 0f370d7..2c70c07 100644 --- a/justfile +++ b/justfile @@ -1008,7 +1008,7 @@ test-integration-compile: _ensure-cargo-nextest test-lib: _ensure-cargo-nextest cargo nextest run --profile ci --lib --verbose -test-python: python-sync +test-python: _ensure-git-cliff python-sync uv run --locked pytest -q test-rust: test-rust-ci test-doc test-doc-exact diff --git a/scripts/tests/test_criterion_dim_plot.py b/scripts/tests/test_criterion_dim_plot.py index 977755c..7c3f245 100644 --- a/scripts/tests/test_criterion_dim_plot.py +++ b/scripts/tests/test_criterion_dim_plot.py @@ -528,10 +528,10 @@ def _retain_complete_plot_inputs(root: Path, paths: ArtifactPaths) -> None: (directory / "estimates.json").write_text(json.dumps({"mean": estimate, "median": estimate}), encoding="utf-8") (directory / "sample.json").write_text(json.dumps({"iters": [1.0] * 100, "times": [timing.median_ns] * 100}), encoding="utf-8") for path, payload in summary_outputs(criterion, baseline, paths).items(): - path.write_text(payload, encoding="utf-8") + path.write_text(payload, encoding="utf-8", newline="\n") for path, payload in retained_outputs(root / "docs/performance", paths).items(): path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(payload, encoding="utf-8") + path.write_text(payload, encoding="utf-8", newline="\n") def test_main_update_readme_happy_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: diff --git a/scripts/tests/test_justfile_discoverability.py b/scripts/tests/test_justfile_discoverability.py index 98ca533..c6a055e 100644 --- a/scripts/tests/test_justfile_discoverability.py +++ b/scripts/tests/test_justfile_discoverability.py @@ -72,8 +72,14 @@ def test_release_runs_each_suite_once_and_reuses_peer_measurements() -> None: script = 'cargo() { printf "%s\\n" "$*"; }\n' + baseline.stderr baseline_run = run_safe_command("bash", ["--noprofile", "--norc", "-euc", script], cwd=REPO_ROOT) baseline_commands = [shlex.split(line) for line in baseline_run.stdout.splitlines()] - current = run_just("--dry-run", "bench-latest") - current_commands = [shlex.split(line) for line in current.stderr.splitlines() if line.startswith("cargo bench ")] + recipes = just_recipes() + current = recipes["bench-latest"] + assert not current["body"] + current_commands = [] + for dependency in current["dependencies"]: + recipe = recipes[dependency["recipe"]] + assert not recipe["dependencies"] + current_commands.extend(shlex.split("".join(line)) for line in recipe["body"]) assert len(baseline_commands) == len(current_commands) == 2 baseline_comparison, baseline_exact = baseline_commands diff --git a/scripts/tests/test_performance_artifacts.py b/scripts/tests/test_performance_artifacts.py index 775485d..6c68e40 100644 --- a/scripts/tests/test_performance_artifacts.py +++ b/scripts/tests/test_performance_artifacts.py @@ -245,7 +245,7 @@ def _simulate_promotion_failure(paths: ArtifactPaths) -> None: def _write_outputs(outputs: dict[Path, str]) -> None: for path, payload in outputs.items(): path.parent.mkdir(parents=True, exist_ok=True) - path.write_text(payload, encoding="utf-8") + path.write_text(payload, encoding="utf-8", newline="\n") def _complete_local_artifacts(root: Path, *, current_value: float = 8.0) -> ArtifactPaths: