Split genus-3: carry the full adjugate, +1M -12A at all six sites - #39
Merged
Conversation
…ic path The T-block already cost 15M 0S 9A for three adjugate entries. Computing the bottom row from columns 1 and 2 of T and shifting it costs the SAME 15M 0S 9A and yields seven, because column 3 of T is x*(column 2) reduced mod up, so the six remaining entries are one multiplication each rather than a 2x2 minor. The determinant then reads m8 rather than m3, since t7*m3 = (-up0*t7)*m8 = t2*m8. So the block conversion is free and the saving is downstream. With the full adjugate in hand the generic path applies it as a matrix-vector product instead of forming q = m7x^2 + m4x + m1 and reducing vt*q mod up by Karatsuba twice: 12M 11A against 11M 23A. Deg3ADD generic 65M 3S 87A 12C -> 66M 3S 75A 12C. No other shape moves. The 1M:3A trade rule accepts +1M -12A comfortably. Established before the edit rather than after: the six shift identities and both determinant forms verified over 4000 trials on GF(10007); t9 shown never to appear below the prefix, t3 and t6 shown to be reused temps whose every read is preceded by its own local assignment, and every Karatsuba temp t0-t5 reassigned before being read in the rest of the generic path. adjugate.py keeps the pre-C4 route as split_q_col1, which measures the same 15M 0S 9A for four entries against the new block's seven, and its .mag anchor moves to the new determinant line. selftest.py's published pin for this cell is superseded with the reason recorded: the thesis is not wrong, the formula moved under it, and Thesis/ERRATA.md carries the divergence. Gates: hand count agreeing at +1M -12A independently of opcount, whitebox 7043/7043, driver --strict 55236/55236, dominance clean on 39 files, adjugate ok, selftest 19/0/0, Magma 30 testers 0 failures 0 skips in 5m13s.
Deg3ADD generic: nch2 65M 3S 85A 0C -> 66M 3S 73A 0C ch2 65M 3S 80A 0C -> 66M 3S 68A 0C Not a copy of the arb edit, because both files had already inlined t3 as -up0*t8*m7 and +up0*t8*m7. That spends two multiplications where arb's t3*m7 spends one, so their determinants cost 4M against arb's 3M and their prefixes reached the same 15M by a different route. The new determinant reads t2*m8 and wants neither t3 nor the inlined pair, so in these two files the conversion drops two multiplications at d and adds three shifts, arriving at the same +1M overall from the other side. No other shape moves in either family. The identities were re-verified with t1, t4, t7 and the modulus all free, 5000 trials over GF(10007), which covers the doublings as well since only the t-recurrence shape matters. Gates: opcount as above, whitebox 7043/7043, driver --strict 55236/55236, dominance clean on 39 files, adjugate ok, selftest 19/0/0, Magma 30 testers 0 failures 0 skips in 5m22s. Deviation from the plan's one-file-per-commit: both specialisations are in this one commit. opcount isolates each family, but whitebox, dominance and Magma cover them jointly, and splitting the commit would imply per-file evidence that was not gathered.
Deg3DBL typical: arb 73M 3S 101A 19C -> 74M 3S 89A 19C nch2 72M 4S 97A 0C -> 73M 4S 85A 0C ch2 71M 4S 86A 1C -> 72M 4S 74A 1C Same rewrite as the additions at the other modulus: the doubling reduces mod u where the addition reduces mod up, and its vector is kp rather than vt. The shift identities were re-verified with t1, t4 and t7 free and the modulus free, 5000 trials over GF(10007), so one check covers both operations rather than assuming the addition's result transfers. That completes C4 at all six sites, +6M -72A in total, with no unintended shape moving in any of the twelve families. The block conversion is free, which is worth stating because the plan predicted otherwise. adjugate.py measures both routes from their real .mag text and each costs 15M 0S 9A -- the old one yielding four adjugate entries, the new one seven, because column 3 of T is x*(column 2) reduced mod the modulus and six entries are therefore one multiplication each. The whole +1M is downstream, where applying the matrix costs 12M against Karatsuba's 11M, and the -12A is downstream too: 20A becomes 8A. selftest's published pin for 3DBL n=0 is superseded alongside 33ADD n=0,0, both hand-counted independently of opcount and both agreeing at +1M -12A. Gates: opcount as above, whitebox 7043/7043, driver --strict 55236/55236, dominance clean on 39 files, adjugate ok, selftest 19/0/0, Magma 30 testers 0 failures 0 skips in 4m51s.
Thesis/ERRATA.md E-T10 and the cells themselves in Thesis/chapter6.tex: the genus-3 split Degree-3 rows of tab:g3splitfcostsADD and tab:g3splitfcostsDBL, six cells, +1M -12A each. Not an error in the thesis -- the published counts were right for the formulas as published and the formulas moved under them, which is why Thesis/ must stop quoting a cost the code no longer has. ThesisPublished/ is untouched, verified. NEW_WORK.md N33 states the result as mathematics rather than an operation count. The adjugate of a multiplication matrix inherits the shift structure of the matrix, so with column 3 of T equal to x times column 2 reduced mod the modulus, the bottom row is a cross product needing no third column and the other six entries are shifts at one multiplication each. All nine entries therefore cost the same 15M 0S 9A as the three the old arrangement built, and the whole trade is downstream: 12M 8A to apply the matrix against Karatsuba's 11M 20A. It also records the refutation. The plan hand-counted the block conversion as losing 2M 1A and my own independent hand count said 0M; the measurement says the block is free and the total is +1M. adjugate.py settles it by executing both routes from their real .mag text, and keeps the pre-C4 route as split_q_col1 so the comparison keeps scoring what C4 measured itself against. ERRATA.md E23: the gates mutate formula files in place to provoke their own guards, so they cannot be run concurrently, nor alongside Magma which loads those files. Found by making the mistake: two selftest runs raced and left the ramified ADD missing the ledger comment adjugate anchors on, surfacing as a gate failure naming a file nothing had edited. Not fixed; the symptom is recorded so the next person does not debug a phantom formula defect. ERRATA.md E24: C5, dropped from this PR. The Bezout cofactor identity is proved -- the closed form is proportional to the true S*dw2^-1 mod unp in 400 of 400 constructed trials -- but the file's (b1,b0) is not that quantity up to scalar in any of them, so its normalisation is unknown and the substitution cannot be written. Recorded rather than applied, per the rule for a result proved before its oracle exists, with the two leads, the nine unexamined sibling sites, and a warning not to re-attempt the Python reproduction whose transcription is the thing in doubt. README: the six genus-3 split cells in Typical Case Operation Counts, the four in the Related Work genus-3 split table, and the two appendix rows, each re-measured by opcount rather than copied. The exactness claim now names its two deliberate exceptions instead of overstating. Gates: readme-paths 94/94, check_paths --strict 259/259, ruff clean on CI's ruleset, opcount confirming all six figures as written.
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.
Carries the full adjugate of the
3x3matrixTin the genus-3 split addition and doubling and applies it as a matrix-vector product, where the formulas previously built only its first column and reducedvt*q mod upby Karatsuba twice.+1M -12Aat every one of the six sites,+6M -72Ain total, accepted comfortably by the thesis's own1M : 3Arule.No other shape moved in any of the twelve families. That is the acceptance test, not a remark: the trade is confined to the generic path it targets.
The finding is that the adjugate is free, which is not what was predicted
The plan expected the extra multiplication to be paid at the
Tblock, on the reasoning that nine adjugate entries must cost more than three, and hand-counted the block conversion as losing 2M 1A. My own independent hand count said 0M. The measurement says the block costs15M 0S 9Aeither way.The reason is structural. Column 3 of
Tisxtimes column 2, reduced modulo the modulus, andadj(T)is itself a multiplication matrix, so it inherits that shift structure. The bottom row is the cross product of columns 1 and 2 and needs no third column at all; the remaining six entries are then shifts of that row at one multiplication each rather than2x2minors at two:Three minors plus six shifts is exactly what three minors plus the now-unneeded
t3,t6,t9used to cost. A further multiplication falls out oft7*m3 = t2*m8, so the determinant expands alongT's first column readingm8in place ofm3, andm3is left to the generic path that alone consumes it — no degenerate leaf pays for it.So the whole trade is downstream, where applying the matrix costs
12M 8Aagainst Karatsuba's11M 20A, and there is no reduction step because applying the multiplication matrix is the reduction.verification/adjugate.pysettles this by executing both routes from their real.magtext:split_q_col1at15M 0S 9Afor four entries,split_qat15M 0S 9Afor seven. The pre-C4 route is kept as a candidate rather than deleted, so the comparison keeps scoring what this work measured itself against.Established before the edit, not after
t1,t4,t7and the modulus free, so one check covers the additions (modulusup) and the doublings (modulusu) rather than assuming one transfers to the other.t9shown never to appear below the prefix,t3andt6shown to be reused temps whose every read is preceded by its own local assignment,m5/m6/m9shown to be unused names, and every Karatsuba tempt0–t5shown reassigned before being read. Onlym7's prefix value is consumed downstream, and the new arrangement still computes it.ADD29/ADD33saving the first time.Six published cells move, adjudicated
33ADD n=0,0and3DBL n=0across all three families. Per the standing rule,opcountmeasures the new figures by execution and a hand count of the changed region reproduces the same+1M -12A— two methods sharing no code.Thesis/ERRATA.mdE-T10 records it and the cells are updated inThesis/chapter6.tex. This is not an error in the thesis: the published counts were correct for the formulas as published, and the formulas moved under them.ThesisPublished/is untouched, verified.verification/selftest.py's published pins are superseded with the reason inline; every other pinned cell still matches its published value.C5 is dropped, and its result is recorded rather than lost
The redundant
2x2system was scoped into this PR and taken out of it. Not refuted — unfinished, and worth little: the leaf sits three zero-tests deep and is reached about once in ten thousand inputs, so its11M 6Ais a raw count on a path almost never taken, and it moves no published cell.The mathematics was settled on the way out and is in
ERRATA.mdE24. The closed form is proportional to the trueS*dw2^-1 mod unpin 400 of 400 constructed trials, which is stronger than the finding originally carried. What blocks it is that the file's(b1, b0)is not that quantity up to any scalar, 0 of 400, so its normalisation is unknown. The entry carries the two leads, the nine unexamined sibling sites, the measured fact that the corpus can see the leaf, and a warning not to re-attempt the Python reproduction whose transcription is precisely what is in doubt.NEW_WORK.mdN33 states the general rule, which outlives the leaf: wherever a formula computesr = a mod band later needs the Bezout cofactor ofbmoduloa, the quotient discarded by that division already is that cofactor, up tolc(r). The ramified model exploits this and split does not, and the reason is inversion scheduling rather than oversight — split must invert late because itsfis non-monic of degree2g+2, which is how it holds to a single inversion, and late inversion means every upstream quantity is weighted.A gate hazard found by tripping over it
ERRATA.mdE23. The gates provoke their own guards by editing formula files in place and restoring them. Two runs at once are not safe: a secondselftestrestored a file while the first held it mutated, leaving the ramified ADD missing the ledger commentadjugate.pyanchors on — a file neither run was testing. It surfaced as a gate failure naming a file nothing had edited, which is a confusing signal whose natural first hypothesis is wrong.The same applies to Magma, which loads those files as each tester starts. Not fixed, because the provocations must edit the real path to locate their targets by content. Recorded so the symptom is recognised rather than debugged as a phantom formula defect, with the rule: run the gates serially, never alongside Magma, and check
git statusbefore believing a failure that names a file you did not touch.Gates
Per formula commit:
opcountas tabled, hand count,whitebox7,043/7,043,driver --strict55,236/55,236,dominanceclean on 39 files,adjugate,selftest19/0/0, and Magma 30 testers, 0 failures, 0 skips — three separate full suite runs, 5m13s, 5m22s and 4m51s.Docs commit touches zero
.magfiles:readme-paths94/94,check_paths --strict259/259, ruff clean on CI's ruleset,opcountre-confirming all six README figures as written.