test(applied): pin MatR::permute_side on both sides and its length guard (#298) - #369
Merged
Conversation
…ard (#298) Closes #298. `permute_side` had no non-square coverage: every pre-existing exercise is on a square matrix, so `rows != cols` never occurred and the `p.len() != expected` guard was never reached with a mismatch. Pinned on a 2 x 3 and a 3 x 2 `MatR<F64Rig>` with entries written out — the 3-cycle `rotation_left(3, 1)` on each side, and the unchanged matrix where the permutation's length matches the opposite side's arity. Both direction pins use a permutation that differs from its inverse, so each separates the braiding from its transpose. Both `matmul` results now go through `.expect` naming the guard, instead of an `if let Ok` that discarded the `Err`. The arms are unreachable: the guard makes `matmul`'s only failure condition impossible, so the issue's "reach both Err arms" cannot be satisfied by any test — a probe panicking in both arms ran 146/146 binaries green. Production diff 6 lines. Falsified against the perturbations, each red on the new test alone: guard deleted (panics at the codomain `.expect`, `expected: 3, actual: 2`); `expected` pinned to `self.cols` (domain case observes the unpermuted `[[1,2],[3,4],[5,6]]`); `expected` pinned to `self.rows` (codomain case observes the unpermuted `[[1,2,3],[4,5,6]]`); domain branch building `P` instead of `P^T` (observes `[[3,4],[5,6],[1,2]]` against `[[5,6],[1,2],[3,4]]`). Restoring `if let Ok` reddens nothing — the null that confirms the arms are dead. The issue's doc-truth rider was already discharged at #367: `mat.rs:11-12` points at `crate::mat_f64` behind the `f64-rig` feature. It is a code span rather than the intra-doc link the rider sketched, because the module is feature-gated and the link would not resolve without it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #298. Taskmap G4-T2.
Premise probe (before briefing): the issue's first claim holds, its second does not, and the doc rider is already done.
MatR::permute_sideon non-identity morphisms (hand_anchored_permute_side_values,permute_side_composes_the_braidings,permute_side_on_an_identity_matches_the_constructors,permute_side_functor_square_exhaustive_n3_and_n4), but every one is on a square matrix, sorows != colsnever occurs and thep.len() != expectedguard is never reached with a mismatch. The nearest guard pin,prop.rs:483 permute_side_length_mismatch_leaves_self_unchanged, is onPropExpr, notMatR.Errarms" cannot be reached by any test. The guard makesmatmul's only failure condition (self.cols != other.rows) impossible: the codomain side buildsperm_matasp.len() × p.len() == self.cols × self.cols, the domain side buildsp_transposeasn × nwithn == self.rows. Measured: a copy panicking in both arms ran 146/146 binaries green. Owner call: convert both to.expectnaming the invariant rather than leave the silent swallow (MatR::permute_side silently discards matmul errors (latent no-op path) #260's class).916ed5f) —mat.rs:11-12reads "The nalgebra bridge specialized toF64Rigiscrate::mat_f64, behind thef64-rigfeature". It is a code span rather than the intra-doc link the rider sketched, becausemat_f64is#[cfg(feature = "f64-rig")]and the link would not resolve without the feature. Lines 9-11 untouched.Shipped (production diff 6 lines; tests + CHANGELOG):
matmulresults go through.expectnaming the guard checked above, replacingif let Okarms that discarded theErr.{of_codomain} × {guard hit, guard missed}on non-square matrices with entries written out:wide2×3 underrotation_left(3,1)on the codomain →[[3,1,2],[6,4,5]];tall3×2 under the same 3-cycle on the domain →[[5,6],[1,2],[3,4]]; and the unchanged matrix where the permutation's length matches the opposite side's arity, so a mismatch is rejected by length alone and never because the permutation was an identity.Falsification (
--no-fail-fast,cp -rcopy; impl + two review rounds):.expect,CompositionSizeMismatch { expected: 3, actual: 2 }expected = self.colsalways[[1,2],[3,4],[5,6]]vs[[5,6],[1,2],[3,4]]expected = self.rowsalways[[1,2,3],[4,5,6]]vs[[3,1,2],[6,4,5]]of_codomain.expect,expected: 3, actual: 2MatR{2,3,…}vsMatR{3,2,…}on each sidePnotPᵀ[[3,4],[5,6],[1,2]]vs[[5,6],[1,2],[3,4]]permutation_matrix(&p.inv())[[2,3,1],[5,6,4]]vs[[3,1,2],[6,4,5]]if let Ok(both arms)Errarms are deadCoverage fact: six of the eight perturbations are caught by the new pin alone — no pre-existing test in the workspace detects the guard's existence, either
expectedselector, or either no-op branch.Reviews: executing adversarial (0 blocking / 1 important / 3 minor), all applied. The important one is the interesting one: the first draft pinned the domain side on the 2×3 with
transposition(2,0,1), an involution, soP == Pᵀand theβ(p)-vs-β(p⁻¹)perturbation left the new test green while reddening five pre-existing ones — sound but narrow. Fixed by moving that pin to a 3×2 fixture with a 3-cycle; the delta review reconstructed the superseded pin, confirmed it stays green under that perturbation while the new one goes red, and returned 0 findings. Minors: fourrows()/cols()assertions implied by the struct equality above them (removed), and a stale file header.Gates: 146 binaries / 2118 / 0 / 24; clippy
-D warningson default,--no-default-features,--all-features;RUSTDOCFLAGS=-D warnings cargo doc; fmt; version-refs, cc-pin/audit-count, rand-dev-only.🤖 Generated with Claude Code