-
Notifications
You must be signed in to change notification settings - Fork 0
0049 two gates per kernel tested where the width is known
Status: accepted · Date: 2026-08-21 · Amends: 0048
Settles what 0048 deliberately left open. That record establishes that the shared constant of 8 is wrong in three of its four cases; this one replaces it.
Decision 0048 measured four crossings over the banded buckets #409 added — Lcs at ≤ 2
on Latin and 6 on CJK, Myers at 5 and 10 — against one shared constant of 8. The
question it left is what shape replaces it, since the dispatch tests the gate on the
pattern's length before anything has looked at the pattern's characters.
Two constants per kernel, and the second is tested where the width has just been established rather than at the dispatch.
| dense gate, at the dispatch | wide gate, at the reroute | |
|---|---|---|
Lcs / BitParallelLcs
|
2 | 6 |
Levenshtein / Myers
|
5 | 10 |
The dispatch keeps one test, now valued at the Latin-1 crossing. Both kernels already discover that a pattern leaves Latin-1 while building their equality table, and both already branch there to a wide method; that branch is where the second gate goes, so a pattern that is wide and short returns false and the caller falls back to the dynamic program it was going to use anyway.
The refusal precedes the wide method's stackalloc, which 0043 records as zeroing
on entry to the method holding it whether or not the branch needing it is taken.
This is not a new shape in this codebase: MyersMinCodePointPatternLength is already a
second gate for a path that crosses later, and its own note gives this decision's
argument — "one constant would have to regress one of the two paths".
-
Four constants at the dispatch. It does not know the alphabet there, so it would
have to scan the pattern before choosing — work charged to the Latin-1 path, which is
what
fuzz.ratio,process.extractand blocking deduplication run. The JIT listing says how much is at stake: that path contains no comparison against0xFFat all today. - A gate reading the pattern's width. The same objection, and the same scan: the fact is produced anyway, but after the gate is tested, and moving the test forward is what costs.
- One shared constant, re-valued. Lowering the shared gate to 2 and 5 without a wide refusal was measurable rather than hypothetical: #409 priced a short wide pattern on the kernel at 1.53× the dynamic program for Myers at band 2 and 1.28× for LCS. The reach would have been bought by regressing the alphabet it was bought for.
- The Latin-1 path executes the same instructions. Diffing the JIT's output the way #302 did — dispatch and both single-word kernels, six methods — every loop is unchanged instruction for instruction. Two once-per-call instructions use a different register, the allocator having reshuffled around the new blocks, and 45 instructions are added: three refusals, their early-return epilogues and the stack checks those need. None is on a path a Latin-1 pattern reaches.
-
The two kernels do not benefit equally, and the corpus says why. On the shipped
scattered buckets,
Indelgains 15.4% at length 32 across three interleaved rounds;Levenshteinshows nothing, its sign flipping between rounds. The bucket has 94% of its pairs above band 4 and 86% above 8, so Myers' move from 8 to 5 touches the 8% that sit between, at 15–30% each — one to two percent overall, under this machine's noise floor. LCS's move from 8 to 2 recovers a far more populated range at up to 2.5× each. - Myers' change therefore rests on the banded measurement, not on the corpus. It is kept because the instrument built to answer the question answers it, and because the shipped corpus shows no cost; it is not kept on a demonstrated gain, and this record says so rather than letting a table imply one.
- A gate is now two numbers per kernel, so a later sweep has to move both. The property tests assert the route at each of the four values rather than the answers alone, which is what makes a silent edit to one of them fail.
- 0001-target-framework
- 0002-unicode-comparison-unit
- 0003-provenance-and-licensing
- 0004-levenshtein-myers-backlog
- 0005-hamming-jellyfish-divergence
- 0006-ratcliff-autojunk
- 0007-metaphone-scope
- 0008-italian-enza-nltk-divergence
- 0009-sample-consumes-a-local-feed
- 0010-stop-word-list-provenance
- 0011-persistence-format
- 0012-per-package-versioning
- 0013-sentencepiece-parity-scope
- 0014-precompiled-normalizer
- 0015-sonar-rules-in-the-build
- 0016-metrics-package-placement
- 0017-bpe-parity-scope
- 0018-multiclass-roc-auc-parallelism-is-opt-in
- 0019-the-net-analysers-run-in-the-build-too
- 0020-normalize-is-a-projection-not-a-parameter
- 0021-multioutput-is-a-method-not-an-enum
- 0022-added-token-matching-flags
- 0023-byte-level-decode-substitutes
- 0024-weighted-median-averages-within-scikit-learns-epsilon
- 0025-quickselect-replaces-a-full-sort-for-the-median
- 0026-r2-and-explainedvariance-split-their-undefined-cases-differently
- 0027-r2-and-explainedvariance-vectorize-only-a-single-output
- 0028-log1p-is-kahans-identity-not-math-log-1-plus-x
- 0029-balanced-accuracy-adjusted-is-left-to-ieee-754-at-the-edge
- 0030-cohen-kappa-keeps-scikit-learns-expected-matrix-orientation
- 0031-nosamplecorrect-mirrors-numpys-float64-upcast
- 0032-fbeta-substitutes-tp-predicted-and-support-algebraically
- 0033-compensated-sum-is-neumaiers-variant
- 0034-dropout-is-refused-for-want-of-a-user
- 0035-a-null-pre-split-is-removed-with-invert-not-isolated
- 0036-a-member-may-ship-without-an-oracle-if-it-says-so
- 0037-the-guards-run-before-the-commit
- 0038-the-gate-confronts-an-exception-tag-with-the-page-that-documents-it
- 0039-mutual-information-returns-zero-on-an-empty-input
- 0040-a-curve-is-a-sealed-class-per-curve
- 0041-one-sample-file-per-public-class
- 0042-phonetic-encoders-refuse-a-null-word
- 0043-the-equality-table-is-sized-to-the-pattern
- 0044-compression-belongs-to-the-caller
- 0045-a-console-call-carries-its-reason-on-the-line
- 0046-check-adr-immutable-runs-in-ci-only
- 0047-one-gate-per-kernel-not-one-per-alphabet
- 0048-the-gate-depends-on-the-kernel-and-the-alphabet
- 0049-two-gates-per-kernel-tested-where-the-width-is-known
- 0050-the-sentencepiece-bpe-lineage-stays-a-bpe-model
- 0051-the-save-paths-cost-is-the-buffer-not-the-encoding
- 0052-pre-sizing-the-artifact-file-buys-nothing-on-a-delayed-allocation-filesystem
- benchmark_latest
- decisions
- equivalence
- matplotlib
- migration
- nightly_run
- numpy
- pandas
- performance
- pytorch
- seaborn
- sklearn
- statsmodels