# Parity tolerances This table records the documented per-pair tolerances between every two reference PLS implementations `pls4all` cross-checks against. Numbers in **bold** are the relaxations applied after Codex review of the Phase 0 roadmap. For cross-algorithm rows the comparator gates on `predictions`, `coefficients`, `intercept`, `x_mean`, `x_scale`, `y_mean`, `y_scale` only โ€” raw latent matrices (`weights_W`, `loadings_P`, `y_loadings_Q`, `rotations_R`, `scores_T`, `y_scores_U`) are diagnostic when algorithms differ. ## Truth-source legend - **๐Ÿ“** marks the column (A or B) whose implementation *produced the expected values* in the corresponding fixture under `parity/fixtures/`. The pls4all C++ kernel and other binding-side ports are tested for bit-equivalence against that side; the marked column is the *library-of-record* for the row. - For pairs where the producer is `pls4all` itself (e.g. `pls4all-refcpu-vs-pls4all-blas`, `pls4all-linux-vs-pls4all-macos-arm64`), the ๐Ÿ“ sits on column A (the REFERENCE_CPU build) โ€” that build is the deterministic baseline every other build is compared against. - For solver-parity rows generated by a NumPy / sklearn / R mirror (e.g. `pls4all-numpy-simpls`, `sklearn/PLSRegression/self_roundtrip`, `pls-r-oscorespls`), the ๐Ÿ“ sits on column A (the generator side). - For the `bench-AOM_v0-*` rows, the ๐Ÿ“ sits on column A โ€” the bench oracle is the canonical AOM reference per user policy. - **๐Ÿ“œ** flags rows whose A/B pair is *documented* but has no active fixture producer yet (e.g. R-generator stubs still on the roadmap). These rows describe the intended tolerance once the matching fixture is wired up; they are not gating any test today. - Unmarked rows are pair-tolerance specifications that don't yet correspond to a single canonical producer (typically cross-implementation comparisons where neither side is strictly *the* truth). This convention mirrors the ๐Ÿ“ icon used in the per-method benchmark dashboards under `docs/methods/`, sourced from `benchmarks/parity_timing/registry.py`. The two layers gate different surfaces โ€” JSON fixtures + C++ ctest here, live cross-binding runs there โ€” but both honour the same "registry-declared canonical reference" notion. | Row key | A | B | Variant | Algorithm | abs_tol | rel_tol | Comparison set | Notes | |---|---|---|---|---|---|---|---|---| | `sklearn/PLSRegression/self_roundtrip` | ๐Ÿ“ sklearn 1.4 `PLSRegression` | sklearn (round-trip) | regression | NIPALS | 1e-15 | 1e-15 | all | sanity | | `sklearn-vs-pls-kernelpls` | sklearn 1.4 `PLSRegression` | R pls 2.8 `plsr(method='kernel')` | regression | NIPALS vs kernel | 5e-7 | 1e-6 | predictions, coefficients, intercept, x/y mean+scale | cross-algorithm โ€” ๐Ÿ“œ documented pair (no active fixture producer) | | `sklearn-vs-pls-simpls` | sklearn 1.4 `PLSRegression` | R pls 2.8 `plsr(method='simpls')` | regression | NIPALS vs SIMPLS | 1e-5 | 1e-4 | predictions, coefficients, intercept, x/y mean+scale | cross-algorithm โ€” ๐Ÿ“œ documented pair (no active fixture producer) | | `sklearn-vs-mixomics-pls` | sklearn 1.4 `PLSRegression` | mixOmics 6.28 `pls` | regression | NIPALS | **1e-7** | **1e-7** | predictions, coefficients, intercept, x/y mean+scale | mixOmics scales differently โ€” predictions agree; ๐Ÿ“œ documented pair (no active fixture producer) | | `sklearn-vs-nirs4all-simpls` | sklearn 1.4 `PLSRegression` | nirs4all 0.8 `SIMPLS` | regression | SIMPLS | 1e-6 | 1e-5 | predictions, coefficients, intercept, x/y mean+scale | cross-algorithm โ€” ๐Ÿ“œ documented pair (no active fixture producer) | | `pls4all-numpy-preprocessing` | ๐Ÿ“ NumPy/SciPy preprocessing fixture | pls4all C++ `n4m_pipeline_*` | preprocessing | identity / center / autoscale / Pareto / SNV / MSC / EMSC / detrend / Savitzky-Golay / Norris-Williams / ASLS / Haar wavelet / OSC / EPO | 1e-12 | 1e-12 | transform outputs | operator parity | | `pls4all-numpy-aom-preprocessing` | ๐Ÿ“ NumPy soft/hard AOM preprocessing-bank fixture | pls4all C++ internal AOM preprocessing kernel | preprocessing | operator-bank output mixing | 1e-10 | 1e-10 | operator outputs, gating weights, mixed transform, operator kind trace | Phase 6a AOM preprocessing parity | | `bench-AOM_v0-aom-operators` | ๐Ÿ“ `nirs4all/bench/AOM_v0/aompls` strict-linear operators | pls4all C++ internal AOM strict operator kernels | AOM | identity / detrend / zero-padded SG / finite difference / Norris-Williams / Whittaker / FCK | 1e-10 | 1e-10 | operator transform outputs | Phase 6c/6d bench AOM_v0 operator parity | | `bench-AOM_v0-aom-selection` | ๐Ÿ“ `nirs4all/bench/AOM_v0/aompls` global AOM CV fixture | pls4all C++ internal AOM global-selection kernel | AOM | SIMPLS materialized global selection | 1e-8 | 1e-8 | per-operator RMSE curves, best scores, selected operator/component count, predictions | Phase 6b/6c/6d bench AOM_v0 parity; current tranche covers identity, detrend, zero-padded SG, finite difference, Norris-Williams, Whittaker and FCK strict-linear operators | | `bench-AOM_v0-pop-selection` | ๐Ÿ“ `nirs4all/bench/AOM_v0/aompls` POP per-component CV fixture | pls4all C++ internal POP selection kernel | POP | SIMPLS covariance per-component selection | 1e-8 | 1e-8 | component candidate scores, prefix scores, selected operator sequence, predictions | Phase 6e bench AOM_v0 parity; intentionally matches bench POP's historical PLS1 CV residual broadcasting | | `pls4all-numpy-regression-metrics` | ๐Ÿ“ NumPy regression metrics fixture | pls4all C++ internal metric kernels | validation | RMSE / MAE / bias / R2 / Q2 / slope / intercept / RPD / RPIQ | 1e-12 | 1e-12 | scalar metrics | metric parity | | `pls4all-numpy-binary-classification-metrics` | ๐Ÿ“ NumPy binary classification metrics fixture | pls4all C++ internal metric kernels | validation | sensitivity / specificity / balanced accuracy / precision / F1 / MCC / AUC | 1e-12 | 1e-12 | scalar metrics | metric parity | | `pls4all-numpy-classification-extensions` | ๐Ÿ“ NumPy classification extension fixtures | pls4all C++ internal metric kernels | validation | multiclass macro/micro metrics / one-vs-rest AUC / fixed-bin calibration | 1e-12 | 1e-12 | scalar metrics, confusion matrix, calibration bins | extension parity | | `sklearn/PLSRegression/variable-importance` | ๐Ÿ“ sklearn 1.4 `PLSRegression` score/loading formulas | pls4all C++ internal variable-importance kernels | validation | VIP / selectivity ratio | 1e-8 | 1e-8 | per-feature vectors | variable importance parity | | `sklearn/PLSRegression-variable-selection-rankers` | ๐Ÿ“ sklearn 1.4 `PLSRegression` score/loading/coefficient formulas | pls4all C++ internal variable-selection rankers | selection | VIP / coefficient magnitude / selectivity ratio | 1e-8 | 1e-8 | per-feature scores plus exact top-k indices | deterministic score-desc/index-asc ranker parity | | `sklearn/PLSRegression-interval-selection-cv` | ๐Ÿ“ sklearn 1.4 `PLSRegression` with deterministic k-fold intervals | pls4all C++ internal interval-selection kernel | selection | moving-window / interval CV | 1e-8 | 1e-8 | metrics by interval, RMSE vector, exact best interval | contiguous interval scan parity | | `sklearn/PLSRegression-biPLS-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic backward interval elimination | pls4all C++ internal biPLS-selection kernel | selection | backward interval PLS | 1e-8 | 1e-8 | interval partition, removal path, RMSE path, best step, selected interval/feature indices | deterministic biPLS parity | | `sklearn/PLSRegression-siPLS-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic exhaustive interval combinations | pls4all C++ internal siPLS-selection kernel | selection | synergy interval PLS | 1e-8 | 1e-8 | interval partition, candidate interval matrix, RMSE by combination, best combination, selected interval/feature indices | deterministic siPLS parity | | `sklearn/PLSRegression-coefficient-stability` | ๐Ÿ“ sklearn 1.4 `PLSRegression` over deterministic Monte-Carlo subsets | pls4all C++ internal stability-selection kernel | selection | MCUVE-style coefficient stability | 1e-8 | 1e-8 | mean/std coefficients, stability scores, exact top-k indices | Monte-Carlo subset parity | | `sklearn/PLSRegression-UVE` | ๐Ÿ“ sklearn 1.4 `PLSRegression` over deterministic Monte-Carlo subsets plus artificial variables | pls4all C++ internal UVE-selection kernel | selection | UVE artificial-variable threshold | 1e-8 | 1e-8 | real/noise stability scores, max-noise threshold, exact selected indices | deterministic SplitMix64 artificial-variable parity | | `sklearn/PLSRegression-EMCUVE` | ๐Ÿ“ sklearn 1.4 `PLSRegression` over deterministic ensemble MC-UVE members | pls4all C++ internal EMCUVE-selection kernel | selection | EMCUVE ensemble vote rule | 1e-8 | 1e-8 | mean real stability scores, vote frequencies, noise thresholds, exact selected indices | deterministic ensemble MC-UVE parity | | `sklearn/PLSRegression-randomization-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` coefficient scores with deterministic Y permutations | pls4all C++ internal randomization-selection kernel | selection | randomization-test PLS selector | 1e-8 | 1e-8 | observed scores, p-values, exceedance counts, exact selected indices | deterministic SplitMix64 permutation parity | | `sklearn/PLSRegression-SPA-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` coefficient seed plus NumPy successive projections | pls4all C++ internal SPA-selection kernel | selection | SPA-PLS projection selector | 1e-8 | 1e-8 | coefficient scores, selection step scores, exact selected indices | deterministic projection parity | | `sklearn/PLSRegression-CARS-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic exponential-retention CV | pls4all C++ internal CARS-selection kernel | selection | CARS-PLS competitive adaptive reweighted sampling | 1e-8 | 1e-8 | coefficient scores by iteration, RMSE path, retained counts, exact selected indices | deterministic CARS parity | | `sklearn/PLSRegression-RandomFrog-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic Random Frog subset walk | pls4all C++ internal Random-Frog-selection kernel | selection | Random Frog PLS inclusion-frequency selector | 1e-8 | 1e-8 | global scores, inclusion frequencies, RMSE path, subset sizes, exact selected indices | deterministic Random Frog parity | | `sklearn/PLSRegression-SCARS-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic stability-weighted subsampling CV | pls4all C++ internal SCARS-selection kernel | selection | SCARS-PLS stability competitive adaptive reweighted sampling | 1e-8 | 1e-8 | coefficient scores by iteration, stability scores, RMSE path, retained counts, exact selected indices | deterministic SCARS parity | | `sklearn/PLSRegression-GA-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic genetic subset search | pls4all C++ internal GA-selection kernel | selection | GA-PLS population search | 1e-8 | 1e-8 | global scores, inclusion frequencies, best/mean RMSE path, best subset sizes, exact selected indices | deterministic GA-PLS parity | | `sklearn/PLSRegression-Shaving-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic recursive coefficient shaving | pls4all C++ internal Shaving-selection kernel | selection | shaving PLS recursive elimination | 1e-8 | 1e-8 | coefficient scores by step, RMSE path, retained counts, exact selected indices | deterministic shaving parity | | `sklearn/PLSRegression-REP-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic fixed-count recursive elimination | pls4all C++ internal REP-selection kernel | selection | REP-PLS recursive elimination | 1e-8 | 1e-8 | coefficient scores by step, RMSE path, retained counts, removed counts/indices, exact selected indices | deterministic REP parity | | `sklearn/PLSRegression-IPW-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic coefficient reweighting | pls4all C++ internal IPW-selection kernel | selection | IPW-PLS iterative predictor weighting | 1e-8 | 1e-8 | score path, weight path, RMSE path, ranking indices, exact selected indices | deterministic IPW parity | | `sklearn/PLSRegression-ST-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic score thresholds | pls4all C++ internal ST-selection kernel | selection | ST-PLS score-threshold selector | 1e-8 | 1e-8 | normalized coefficient scores, threshold RMSE path, masks/counts, ranking indices, exact selected indices | deterministic ST-PLS parity | | `sklearn/PLSRegression-BVE-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` deterministic backward variable elimination | pls4all C++ internal BVE-selection kernel | selection | BVE-PLS backward elimination | 1e-8 | 1e-8 | candidate RMSE matrix, chosen RMSE path, retained counts, removed indices, exact selected indices | deterministic BVE parity | | `sklearn/PLSRegression-T2-selection` | ๐Ÿ“ sklearn 1.4 `PLSRegression` plus plsVarSel-style Hotelling T2 thresholds | pls4all C++ internal T2-selection kernel | selection | T2-PLS loading-weight selection | 1e-8 | 1e-8 | T2 scores, UCL per alpha, RMSE path, selected masks/counts, exact selected indices | deterministic T2-PLS parity | | `numpy/WVC-PLS-selection` | ๐Ÿ“ NumPy mirror of plsVarSel WVC-PLS numeric-regression WVC2 | pls4all C++ internal WVC-selection kernel | selection | WVC-PLS weighted variable contribution | 1e-8 | 1e-8 | weights, loadings, WVC score matrix, final scores, exact top-k indices | deterministic WVC-PLS parity | | `numpy/WVC-PLS-threshold-selection` | ๐Ÿ“ NumPy WVC-PLS threshold/factor rule over WVC2 scores | pls4all C++ internal WVC-threshold-selection kernel | selection | thresholded/factor WVC-PLS | 1e-8 | 1e-8 | final scores, ranked indices, mean score, effective threshold, selected indices | deterministic WVC threshold/factor parity | | `sklearn/PLSRegression/component-coefficients` | ๐Ÿ“ sklearn 1.4 `PLSRegression` prefix coefficient formulas | pls4all C++ internal component coefficient kernels | validation | original-scale coefficients per latent prefix | 1e-8 | 1e-8 | component-major coefficient blocks | component-count model selection support | | `pls4all-python-validation-splits` | ๐Ÿ“ Python deterministic split fixture | pls4all C++ internal split generators | validation | k-fold / LOO / holdout | exact | exact | train/test index plans | splitter parity | | `pls4all-python-advanced-validation-splits` | ๐Ÿ“ Python deterministic split fixture | pls4all C++ internal split generators | validation | external folds / repeated k-fold / Monte-Carlo / Kennard-Stone / SPXY | exact | exact | train/test index plans | advanced splitter parity | | `sklearn/PLSRegression/kfold-cv` | ๐Ÿ“ sklearn 1.4 `PLSRegression` with deterministic k-fold splits | pls4all C++ internal CV engine | validation | NIPALS PLS regression CV | 1e-8 | 1e-8 | out-of-sample predictions, aggregate metrics, test index plan | cross-validation parity | | `pls4all-numpy-simpls-component-cv` | ๐Ÿ“ NumPy SIMPLS with deterministic k-fold splits | pls4all C++ internal model-selection kernel | validation | SIMPLS component-count CV | 1e-8 | 1e-8 | metrics by component, best component count | component selection parity | | `pls4all-numpy-simpls` | ๐Ÿ“ pls4all NumPy SIMPLS fixture | pls4all C++ `N4M_SOLVER_SIMPLS` | regression | SIMPLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls4all-numpy-svd` | ๐Ÿ“ pls4all NumPy SVD fixture | pls4all C++ `N4M_SOLVER_SVD` | regression | SVD | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls4all-numpy-power` | ๐Ÿ“ pls4all NumPy power-iteration fixture | pls4all C++ `N4M_SOLVER_POWER` | regression | power PLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls4all-numpy-randomized-svd` | ๐Ÿ“ pls4all NumPy randomized-SVD fixture | pls4all C++ `N4M_SOLVER_RANDOMIZED_SVD` | regression | randomized SVD PLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `sklearn/PLSCanonical/nipals` | ๐Ÿ“ NumPy mirror of sklearn 1.4 `PLSCanonical(algorithm='nipals')` | pls4all C++ `N4M_ALGO_PLS_CANONICAL` + `N4M_SOLVER_NIPALS` | canonical | NIPALS + canonical deflation | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity | | `sklearn/PLSCanonical/svd` | ๐Ÿ“ NumPy mirror of sklearn 1.4 `PLSCanonical(algorithm='svd')` | pls4all C++ `N4M_ALGO_PLS_CANONICAL` + `N4M_SOLVER_SVD` | canonical | SVD + canonical deflation | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity | | `sklearn/PLSSVD` | ๐Ÿ“ NumPy mirror of sklearn 1.4 `PLSSVD` | pls4all C++ `N4M_ALGO_PLS_SVD` + `N4M_SOLVER_SVD` | cross-decomposition | direct cross-covariance SVD score model | 1e-9 | 1e-9 | transform scores, weights, projection predictions, preprocessing stats | algorithm parity; predict is pls4all latent projection | | `sklearn/PLSDA-dummy/PLSRegression` | ๐Ÿ“ sklearn 1.4 `PLSRegression` on dummy-coded Y | pls4all C++ `N4M_ALGO_PLS_DA` + `N4M_SOLVER_NIPALS` | discriminant | PLS-DA dummy-response scores | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity; predictions are continuous class scores | | `sklearn/PLSRegression-scores-plus-numpy-LDA` | ๐Ÿ“ sklearn 1.4 `PLSRegression` scores + NumPy pooled-covariance LDA | pls4all C++ internal PLS-LDA kernel | discriminant | PLS score-space LDA | 1e-8 | 1e-8 | predictions, decision scores | classifier parity | | `sklearn/PLSRegression-scores-plus-numpy-logistic` | ๐Ÿ“ sklearn 1.4 `PLSRegression` scores + NumPy baseline multinomial logistic Newton | pls4all C++ internal PLS-logistic kernel | discriminant | PLS score-space logistic | 1e-8 | 1e-8 | predictions, decision scores, probabilities, intercepts, coefficients | classifier parity | | `sklearn/PLSRegression-block-weighted-MBPLS` | ๐Ÿ“ NumPy block autoscaling + sklearn 1.4 `PLSRegression(scale=False)` | pls4all C++ internal MB-PLS kernel | regression | block-weighted MB-PLS | 1e-8 | 1e-8 | predictions, coefficients, intercept, block weights, x preprocessing stats | multi-block parity | | `sklearn/PLSRegression-local-window-LWPLS` | ๐Ÿ“ Gaussian-weighted local PLS on raw rows (ฮป = max(1, 0.5ยทn_neighbors)), mirroring nirs4all `lwpls.py::_lwpls_predict` | pls4all C++ internal LW-PLS kernel | regression | local-window LW-PLS | 1e-8 | 1e-8 | predictions, neighbor indices | local model parity; fixture agrees with the C++ core to ~7e-16 | | `pls4all-numpy-opls` | ๐Ÿ“ pls4all NumPy OPLS1 fixture | pls4all C++ `N4M_ALGO_OPLS` + `N4M_SOLVER_NIPALS` | orthogonal | OPLS1 + orthogonal corrections | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity; first score column is predictive, later columns are orthogonal | | `pls4all-numpy-opls-da-binary` | ๐Ÿ“ pls4all NumPy OPLS1 fixture on one-column dummy Y | pls4all C++ `N4M_ALGO_OPLS_DA` + `N4M_SOLVER_NIPALS` | discriminant | binary OPLS-DA dummy-response scores | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity | | `pls4all-numpy-opls-da-multiclass` | ๐Ÿ“ pls4all NumPy multivariate OPLS fixture on one-hot Y | pls4all C++ `N4M_ALGO_OPLS_DA` + `N4M_SOLVER_NIPALS` | discriminant | multi-class OPLS-DA common predictive score | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity; one shared predictive subspace | | `pls4all-numpy-kernelpls` | ๐Ÿ“ pls4all NumPy kernel PLS fixture | pls4all C++ `N4M_SOLVER_KERNEL_ALGORITHM` | regression | kernel PLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls4all-numpy-wide-kernelpls` | ๐Ÿ“ pls4all NumPy wide-kernel PLS fixture | pls4all C++ `N4M_SOLVER_WIDE_KERNEL` | regression | wide-kernel PLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls-r-oscorespls` | ๐Ÿ“ NumPy port of R pls `oscorespls.fit` | pls4all C++ `N4M_SOLVER_ORTHOGONAL_SCORES` | regression | orthogonal-scores PLS | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | solver parity | | `pls4all-numpy-pcr` | ๐Ÿ“ pls4all NumPy PCR fixture | pls4all C++ `N4M_ALGO_PCR` + `N4M_SOLVER_SVD` | regression | PCR | 1e-9 | 1e-9 | predictions, coefficients, intercept, x/y mean+scale, latent arrays | algorithm parity | | `sklearn-canonical-vs-mixomics-canonical` | sklearn 1.4 `PLSCanonical` | mixOmics 6.28 `pls(mode='canonical')` | canonical | NIPALS | 1e-7 | 1e-7 | predictions, coefficients, intercept, x/y mean+scale | cross-impl โ€” ๐Ÿ“œ documented pair (no active fixture producer) | | `ropls-opls-vs-nirs4all-opls` | ropls 1.34 `opls` | nirs4all 0.8 `OPLS` | orthogonal | OPLS-NIPALS | 1e-5 | 1e-4 | predictions only | OPLS sign + ordering vary; ๐Ÿ“œ documented pair (no active fixture producer) | | `bench-AOM_v0-vs-pls4all-aom` | ๐Ÿ“ `nirs4all/bench/AOM_v0/aompls` | pls4all (Phase 6) | AOM | SIMPLS + operator bank | **TBD**| **TBD**| selection curves, selected operators/components, predictions | Source-of-truth is the bench AOM_v0 reference, not the packaged `nirs4all` model API | | `pls4all-refcpu-vs-pls4all-blas` | ๐Ÿ“ pls4all REFERENCE_CPU | pls4all BLAS | any | any | **1e-10** | **1e-9** | all | same algorithm, different SGEMM path; fixed reduction order, no FMA | | `pls4all-refcpu-vs-pls4all-cuda` | ๐Ÿ“ pls4all REFERENCE_CPU | pls4all CUDA | any | any | 1e-9 | 1e-8 | predictions | fp64 GPU drift envelope | | `pls4all-linux-vs-pls4all-macos-arm64` | ๐Ÿ“ pls4all REFERENCE_CPU (Linux x86_64) | pls4all REFERENCE_CPU (macOS arm64) | any | any | **1e-11** | **1e-11** | all | cross-platform sanity | The `tolerance_table_row` key in each fixture's `comparison_policy` block points to a row by name. The comparator resolves missing per-field tolerances against this row.