Discharge E7: the record was a wrong-basis comparison, and a published performance claim is off by half - #43
Merged
Merged
Conversation
`driver.py`'s exclusion comment and its duplicate in `verification/README.md` described `g2/timings/` and `g3/timings/` as an earlier generation in which "every body differs", citing a different `ccs` layout (`ccs[2][3]` against `ccs[1][3][1]`), opposite signs on some terms, and a `nch23_splitG2_UTL.mag` the canonical tree does not have. All three are false, and false the same way: they compare the genus-2 timings **split** files against `negReduced`. That tree is `posReduced`, where `ccs[2][3]` and `dw := v0+vp0-u0*f4-upp0*upp1` are byte-identical to it; `ccs[1][3][1]` and the `+` signs are `negReduced`'s, which is the basis and is supposed to differ in sign. And `nch23_splitG2_UTL.mag` is a stale doc comment that the timings tree **shares** with `posReduced`, not a load: the real load is `nch2_splitG2_UTL.mag`, which canonical ships in both genus-2 bases and at genus 3. Two further corrections. The scope sentence said "the split formulas", but the filter it justifies excludes ramified files too. And "same function names as the canonical files" holds only at genus-2 split: genus-2 ramified has zero overlap, every name `_RAM`-suffixed, and at genus 3 the timings tree carries `Deg22ADD`/`Deg22ADDUP`/`Deg22ADDUP2` where canonical has `Deg2ADD`/`Deg2ADDUP`/`Deg2ADDUP2`, which is PR10's rename that this tree never received. What the trees actually are is now recorded: the frozen 2020 generation, repackaged for a chain-driving harness rather than derived differently -- packed-tuple dispatchers so a Fibonacci loop chains without repacking polynomials, tuple returns where the canonical files carry `*_DEBUG` guards, inline `ccs` reads where canonical hoists them, and `_RAM` suffixes so several implementations load in one Magma session. The exclusion itself stands, for the two reasons that survive: they are not the formulas of record, and half of them carry zero `*_DEBUG` labels, so the coverage half of a driver pass would be vacuous for them. Gates: `opcount.py --json` **byte-identical**, md5 2a93ffaa1e39fcbbe2bb3a1abfc878ce before and after; `driver.py --list` identical, still 15 families and the same 10 excluded paths; selftest 19 passed 0 failed 0 skipped; readme-paths 100/100; check_paths --strict 259/259; CI ruff selection and compileall clean. No .mag file touched.
E7 has been a reserved number deliberately absent from `ERRATA.md`, pending "the operation counter run over both trees". The measurement was made and it contradicted the record that reserved it, so E7 lands **downgraded: not a defect in the published figures.** What the timings trees are: the frozen 2020 generation, kept because the published timing figures were produced from it, repackaged for a chain-driving harness rather than derived differently. The old record's polarity was backwards -- it called them "a divergent generation", where in fact they are the frozen original and the canonical tree is what moved, by dated post-2020 improvements. Three limits are stated in the entry rather than left to be assumed. No differential was run under the gates, so the trees are *indicated* to compute the same group law, not shown to. 14 of 82 functions are uncovered by the census -- 10 dispatchers, 3 Precomputes, 1 curve generator -- and the dispatchers are exactly where operand order and the equal-divisor route live. And an operator census is structurally blind to a guard predicate, which matters because of the next paragraph. **E1 gains a cross-reference, and the timings copy fails the other way.** `nch2_ramifiedG2_ADD.mag:98` in the timings tree tests only `dw21` where the canonical file at `:284` tests `IsZero(dw20) and IsZero(dw21)`. Its return condition is *wider*: on `dw21 = 0, dw20 != 0` it returns the identity where canonical raises. A silent wrong value against a loud crash, neither correct, and no count, census or fingerprint could have found it -- a widened `and` adds no operator. Not fixed: that tree is the provenance of published figures and is not edited. Also recorded, not fixed: three latent `driver.py` defects that fire only if the timings tree becomes discoverable. The first is a real bug today -- `:125-126` keys families on `(model + basis, genus, kind)` with `basis` empty off the posReduced/negReduced paths, so a timings ramified file collides exactly with its canonical counterpart and one silently overwrites the other on `os.walk` order. **One file deleted:** `g3/timings/formulas/splitFormulas/nch2_splitG3_rad.mag`, byte-identical to `nch2_splitG3_onlyFreq.mag` (both md5 6cb5151a4272fa1cfbbb5ab549054231), declaring the same `*_onlyFreq` names, referenced by nothing anywhere in the repository, while named after another author's work and containing ours. Folded into this commit rather than a later one because E7 records the deletion and an entry asserting a deletion that had not happened would be false at that commit. `previousBest/lange_2005.mag`'s author line over Lange's formulas is recorded and left alone: the header is accurate about who wrote the transcription, and rewording published-adjacent provenance is the author's call. Gates: opcount.py --json byte-identical, md5 2a93ffaa1e39fcbbe2bb3a1abfc878ce; selftest 19 passed 0 failed 0 skipped; readme-paths 100/100; check_paths --strict 259/259; no reference to the deleted file remains. No canonical .mag file touched.
`chapter5.tex:2669-2671` claimed split model arithmetic is "about 20% slower than ramified arithmetic for genus 2 curves". Computed from the raw file the published genus-2 plots were produced from, `g2/timings/processing/poutg2_complete.raw`, columns OXAR/OXAS for addition and OXDR/OXDS for doubling: bits 2 4 8 16 32 64 128 256 512 1024 addition 0.7% 28.0% 33.2% 35.1% 37.5% 33.4% 31.8% 28.0% 24.4% 22.2% doubling 40.5% 52.8% 31.8% 31.8% 44.4% 38.7% 40.4% 33.9% 29.8% 28.0% "About 20%" holds at one cell of eighteen from 4 bits up, and the nearest is 22.2%. Corrected to give both ranges: addition 22% to 38%, doubling 28% to 53%, over 4 to 1024 bits. Ranges rather than a single revised figure, for three reasons recorded in `E-T15`. Doubling is worse than addition at nine of ten field sizes, and one number hides that. The trend is not flat -- addition peaks at 32 bits and falls monotonically to 1024, the signature of a fixed overhead being amortised as field arithmetic gets dearer, where a constant percentage asserts the opposite. And the corrected statement is *stronger* for the thesis's own argument, not weaker. The 2-bit column is excluded by an explicit scope, not discarded: there addition differs by 0.7% while doubling differs by 40.5%, which is a chain dominated by interpreter overhead rather than field arithmetic. **Both methodology sentences corrected too**, `chapter5.tex:2566` and `chapter6.tex:2604`. They described the doubling experiment as "series of thousands of additions" and gave no trial count. The committed raw records both: an identical schedule at both genera running from 500,000 chain steps at 2 bits down to 45,000 at 1024, every figure the mean of 5 trials. "Thousands" is true of none of them. A reader told "thousands" cannot tell that the 1024-bit points rest on a tenth the samples of the 2-bit ones, which is what they need before reading a trend off the tails of those plots. Recorded as `E-T16`. **And the genus-2 script cannot reproduce its own figures**, recorded as `ERRATA.md` **E25**. `g2/timings/nch2_g2_complete.mag:29-30` ships `length := 5000; trials := 1;` where its genus-3 sibling carries `500000; 5` and where every genus-2 raw header, its own included, records `# Average over: 5`. Not fixed: editing it would make it claim to reproduce a 2020 run on a 64-core Xeon 7550 that no current machine matches, and the thesis disclaims absolute timings. Recording the real parameters where a reader finds them is the useful half, and the seeds are `643202358` and `1362920179`. None of this is an E7 consequence. Both columns of the 20% comparison come from one tree, so it is internally valid whatever that tree's relation to the canonical one; the error was in reading the numbers, not in producing them. Not re-measured, deliberately: these are the published raw data recomputed, not a fresh run. Build: 266 pages, 0 errors, 0 undefined references, 0 undefined citations, 0 rerun requests. readme-paths 100/100, check_paths --strict 259/259. `ThesisPublished/` untouched; no .mag file touched.
…oking Ground rule 7: this PR corrects the thesis and establishes a result, so it owes an entry. N36 records the mechanism rather than just the correction. E7 was a comparison against the wrong sibling, written into a code comment, which then justified excluding the very files that would have exposed it. The exclusion made the record unfalsifiable and simultaneously froze the tree it described, which is why a two-year-old rename absent from that tree is the clearest evidence of what the tree actually is. A record that justifies not looking at its subject cannot decay gracefully. The companion finding is the opposite shape and equally cheap: a published performance claim contradicted by raw data committed alongside it, which nobody had recomputed. Limits stated inline per the file's own rule: no differential ran under the gates so the two trees are indicated rather than shown to agree; 14 of 82 functions are uncovered by the census, the dispatchers among them; and the widened `and` in the timings `Deg2ADD` guard is invisible to every instrument used, having been found by reading. Gates: readme-paths 100/100, check_paths --strict 259/259. No .mag file touched.
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.
E7 was the one erratum deliberately absent from
ERRATA.md, reserved for weeks pending "the operation counter run over both trees". The counter was run. The record did not survive it, and the more valuable finding turned out to have nothing to do with E7.E7's record was a comparison against the wrong sibling
The record was not merely stale in a plan file. It was a comment in
verification/driver.py, duplicated inverification/README.md, justifying a live exclusion filter.ccslayout (ccs[2][3]againstccs[1][3][1])"ccs[2][3]isposReduced's, byte-identical to the timings tree.ccs[1][3][1]isnegReduced'sdw := v0+vp0-u0*f4-upp0*upp1is byte-identical between the timings ADD:197andposReduced:394. The+form isnegReduced:387— it is the basis, and a basis is supposed to differ in signnch23_splitG2_UTL.magthat the canonical tree does not have"posReduced, not a load. The real load isnch2_splitG2_UTL.mag, which canonical ships in both genus-2 bases and at genus 3_RAM-suffixed. Genus 3 is 24/27All three specific claims fail the same way: they compare the genus-2 timings split files against
negReduced. That tree isposReduced— this repository's genus-2 basis of record, and what the thesis presents. Two other artifacts already said so, so the comment contradicted its own siblings.The polarity was backwards too. The record called the timings trees "a divergent generation". They are the frozen 2020 original; the canonical tree is what moved, by dated post-publication improvements.
How it stayed wrong, which is the part worth carrying
The record lived in a comment that justified excluding the very files that would have exposed it. That made it unfalsifiable, and it simultaneously froze the tree it described — which is why the clearest evidence of what that tree actually is turns out to be PR10's
Deg22ADD→Deg2ADDrename, absent there because the tree is excluded from every gate.The tell that would have caught it at any point in two years: the "missing" filename appears in
posReduced's own addition file.A record that justifies not looking at its subject cannot decay gracefully. That is
NEW_WORK.mdN36.The more valuable finding, and it is not E7
Thesis/chapter5.tex:2669-2671claimed split model arithmetic is "about 20% slower than ramified arithmetic for genus 2 curves". Recomputed from the raw file the published genus-2 plots were produced from,g2/timings/processing/poutg2_complete.raw:"About 20%" holds at one cell of eighteen from 4 bits up. Corrected to give both ranges: addition 22% to 38%, doubling 28% to 53%.
Ranges rather than a single revised figure, for reasons recorded in
E-T15:The 2-bit column is excluded by explicit scope rather than discarded: there addition differs by 0.7% while doubling differs by 40.5%, which is a chain dominated by interpreter overhead rather than field arithmetic.
This is not an E7 consequence. Both columns come from one tree, so the comparison is internally valid whatever that tree's relation to the canonical one. The error was in reading the numbers, not in producing them.
Also landed
E-T16— both chapters described the doubling experiment as "series of thousands of additions" and gave no trial count. The committed raw records an identical schedule at both genera, from 500,000 chain steps at 2 bits down to 45,000 at 1024, every figure the mean of 5 trials. "Thousands" is true of none of them, and a reader told "thousands" cannot tell that the 1024-bit points rest on a tenth the samples of the 2-bit ones — which is what they need before reading a trend off the tails of those plots.E25—g2/timings/nch2_g2_complete.mag:29-30shipslength := 5000; trials := 1;where its genus-3 sibling carries500000; 5and where every genus-2 raw header, its own included, records# Average over: 5. The committed genus-2 script cannot reproduce its own published figures. Not fixed: editing it would make it claim to reproduce a 2020 run on a 64-core Xeon 7550 that no current machine matches, and the thesis disclaims absolute timings. Recording the real parameters where a reader finds them is the useful half, and the seeds are643202358and1362920179.One file deleted —
g3/timings/formulas/splitFormulas/nch2_splitG3_rad.mag, byte-identical tonch2_splitG3_onlyFreq.mag(both md56cb5151a4272fa1cfbbb5ab549054231), declaring the same*_onlyFreqnames, referenced by nothing anywhere in the repository, while named after another author's work and containing ours.Recorded, not fixed — three items needing an editorial call
Three latent
driver.pydefects. They fire only if the timings tree becomes discoverable, which nothing does. The first is a real bug today::125-126keys families on(model + basis, genus, kind)withbasisempty off theposReduced/negReducedpaths, so a timings ramified file keys identically to its canonical counterpart andseen.setdefault(key, {})[op] = pathsilently overwrites, decided byos.walkorder. Whoever attempts the reach must fix it first.The guard-width difference, and it is worth repeating. The timings copy of
nch2_ramifiedG2_ADDtests onlydw21where canonical testsIsZero(dw20) and IsZero(dw21), so its return condition is wider: ondw21 = 0, dw20 ≠ 0it returns the identity where canonical raises. A silent wrong value against a loud crash, neither correct. This is E1's region and is cross-referenced there. A widenedandadds no operator, moves no count and changes no fingerprint, so every instrument in this PR is structurally blind to it — it was found by reading the two guards side by side.previousBest/lange_2005.mag:1-11carries an author line over an implementation of Lange's published formulas, where the other fivepreviousBest/files carry none. Left alone: the header is accurate about who wrote the transcription, and rewording published-adjacent provenance is the author's call.What is not claimed
No differential ran under the gates. The two trees are indicated to compute the same group law, not shown to. What supports it: an arithmetic operator census per shared function, identical in 22 of 24 genus-3 split additions and 8 of 11 genus-2 split additions against
posReduced, survivors differing by single operations; and againstnegReducednone match with the up/down adjustment pairs swapped, which is what opposite adjustment senses look like. Establishing agreement properly needs an opt-in reach and an adapter for the packed-tuple interface, deliberately scoped out.14 of 82 functions are uncovered by that census — 10 dispatchers, 3
Precomputes, 1 curve generator — and the dispatchers are exactly where operand order and the equal-divisor route live. E7 says so.A negative finding on this evidence is tolerable where a positive claim would not be, and the entry states that rather than leaving it to be inferred.
Nothing was re-measured by a fresh timing run. The 20% table is the published raw data recomputed.
No formula gate applies. No canonical
.magfile is touched, so Magma,blockcheckand the rest have nothing to say here. The only.magin the diff is the deleted duplicate in the excluded tree.Two deviations from the plan
The
rad.magdeletion moved from its own commit into the E7 commit, because E7's text records the deletion and an entry asserting a deletion that had not happened would be false at that commit. And the genus-2 irreproducibility went to the rootERRATA.mdas E25 rather thanThesis/ERRATA.md, that script not being part ofThesis/and the file's own header scoping it to thesis divergences.The plan's recorded acceptance criterion — "a normalising pre-pass validated by producing ZERO count change on the canonical tree" — is deleted, both its premises having been measured dead: the two
latexConverter.pyfaults it works around do not exist in the counter of record, andmaginterp.discoverparses every timings formula file cleanly with matching function counts.Gates
opcount.py --jsonbyte-identical, md52a93ffaa1e39fcbbe2bb3a1abfc878cebefore and after ·driver --strict13,746/13,746, 0 mismatched, matching the recorded baseline ·whiteboxPASS ·dominanceclean on 39 files ·selftest19 passed, 0 failed, 0 skipped · thesis build 266 pages, 0 errors, 0 undefined references, 0 undefined citations, 0 rerun requests ·readme-paths100/100 ·check_paths --strict259/259 · CI ruff selection andcompileallclean ·ThesisPublished/byte-identical · no canonical.magtouched.