Read the trigonometric table around the whole circle (#743) - #747
Merged
Conversation
Every angle in the table of exact values is written `2pi/n`, so it names only
the angles that divide the turn evenly -- and nothing at all between `2pi/5`
and `2pi/3`, which is most of the second quadrant and the whole lower half.
Each lookup then tried a couple of identities to reach the rest, and they reach
some of it and not the neighbouring rest:
sin(2pi/3) -> sqrt(3)/2 the table has the entry
sin(4pi/3) -> -sqrt(3)/2 reached by the doubled-angle identity
sin(5pi/3) -> sin(5/3 * pi) the same value again, and not reached
What was missing is the half turn: `sin(x) = -sin(x - pi)`, and the same for
the cosine, while the tangent's period *is* half a circle so it takes no sign
back. Applied once around the lookups rather than inside them, so it cannot
turn back on itself and loop.
The table entries are also read before a value is built out of the doubled
angle, which was not the previous order and is what makes the output
consistent. Both routes are exact; the doubled-angle one builds a nested
radical where the table has a flat one, so `cos(6pi/5)` came back as
`-sqrt((1 + (sqrt(5) - 1)/4) / 2)` for a number the table names as
`-(sqrt(5) + 1)/4`, and the roots of `x^5 = 1` were written both ways at once.
This is how #743 was reported: the roots of unity are handed back in a + bi
form, and one of six came back carrying a sine.
x^6 - 1 = 0
was { 1, 1/2 + i*sqrt(3)/2, ..., 1/2 + i * sin(5/3 * pi) }
now { 1, 1/2 + i*sqrt(3)/2, ..., 1/2 + i * -1/2*sqrt(3) }
x^5 - 1 = 0 had cos(4/5*pi) and sin(8/5*pi) in it; both are now exact,
and each root is now written the way its conjugate is.
Measured by sweeping every `k/n * pi` of the first turn for eighteen
denominators -- 1158 calls -- and checking each resolved value against the
numeric value of the call it replaced. 581 resolved before and 690 after, with
no disagreement in either run: what was missing was missing rather than wrong,
and the 109 newly exact values are right.
Suite 4979 -> 4991 passed / 0 failed, F# 130/130, corpus 112/117 with 0 wrong
and every verdict and answer byte-identical. rootcheck is 595/596 on this
branch, its one incomplete case being #744, which is a separate defect in the
solver and is fixed in PR #745 rather than here.
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 #743.
What was wrong
Every angle in the table of exact trigonometric values is written
2pi/n, so the table names only the angles that divide the turn evenly — and nothing at all between2pi/5and2pi/3, which is most of the second quadrant and the whole lower half of the circle. Each lookup then tried a couple of identities to reach the rest, and they reach some of it and not the neighbouring rest:This is how #743 was reported: the roots of unity are handed back in
a + biform, so one of the six roots ofx^6 = 1came back carrying an unevaluated sine — its own conjugate, spelled differently, two lines above it.What the fix does
1. The half turn.
sin(x) = -sin(x - pi), and the same for the cosine; the tangent's period is half a circle, so it takes no sign back. Applied once around the lookups rather than inside them, so it cannot turn back on itself and loop.2. Table entries are read before a value is built out of the doubled angle. Both routes are exact, but the doubled-angle one builds a nested radical where the table has a flat one —
cos(6pi/5)came back as-sqrt((1 + (sqrt(5) - 1)/4) / 2)for a number the table names as-(sqrt(5) + 1)/4— so the roots ofx^5 = 1were written both ways at once. Reading the table first makes each root come out the way its conjugate does.sin(5/3 * pi)sin(5/3 * pi)-sqrt(3)/2cos(4/5 * pi)cos(4/5 * pi)-(1 + sqrt(5))/4sin(8/5 * pi)sin(8/5 * pi)-sqrt(10 + 2*sqrt(5))/4tan(5/3 * pi)tan(5/3 * pi)-sqrt(3)x^6 - 1 = 0{ …, 1/2 + i * sin(5/3 * pi) }x^5 - 1 = 0cos(4/5*pi)andsin(8/5*pi)Measured
The risk in widening a lookup table is that it starts answering angles it does not know, so the check is a sweep rather than the reported cases: every
k/n * piof the first turn for eighteen denominators, 1158 calls in all, each resolved value checked against the numeric value of the call it replaced.work/rootcheckis 595/596 on this branch; its one incomplete case is A power of a polynomial is solved by inverting into itself, so the roots come back containing x #744, a separate solver defect fixed in Only invert an equation whose variable occurs once (#744) #745, not this one.That sweep is the regression test, along with the reported angles, the roots of unity, and the angles the table always answered.
🤖 Generated with Claude Code