Compare CELT rotation paths within a tolerance - #254
Closed
hashirmuzaffar wants to merge 1 commit into
Closed
hashirmuzaffar wants to merge 1 commit into
hashirmuzaffar wants to merge 1 commit into
Conversation
TestExpRotation1BlockOfFour asserted that the block-of-four rotation and the scalar reference produce identical float32 results. The language permits a multiplication followed by an addition to be fused into one operation that rounds once rather than twice, and the two loop bodies are written differently enough that a compiler may fuse one and not the other. arm64 does, so the test fails there on every Go version from 1.24 to 1.27 while passing on amd64. Neither result is wrong. Measured against the same rotation carried out in float64, both stay within a few units in the last place, and across these lengths and a range of rotation angles the largest disagreement between them is 2e-06 on values of magnitude ten. The tolerance is set well above that and far below a real defect: introducing a 0.01 percent error in one coefficient of the unrolled path still fails the test. Fixes pion#241
Author
|
Superseded by #252, which landed the same fix. I missed that it was already open when I started — my fault for checking the issue but not the open pull requests. Leaving one measurement here in case it is ever useful. Across the four shapes in the test and rotation angles of (0.9, 0.4), (0.6, 0.8), (0.99, 0.14) and (0.1, 0.99), the largest disagreement between the two paths is 1.91e-06 on values of magnitude ten, so the 1e-5 tolerance in #252 has roughly five times headroom. A pure ulp bound would have needed to be around 64, because one output cancels to 0.088 where a 4e-07 absolute difference is 52 ulp. |
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.
Fixes #241.
TestExpRotation1BlockOfFourcompares the block-of-four rotation against the scalar reference withassert.Equal. Both are Go, both compiled for the host, so the comparison looked safe — but the spec lets an implementation fuse a multiply and a following add into one operation that rounds once instead of twice, and the two loop bodies are written differently enough that a compiler may fuse one and not the other. arm64 does. It reproduces on Go 1.24 through 1.27, on Linux and macOS, and passes on amd64.One note on the issue text: the expected values aren't stored vectors generated on amd64.
wantis produced at runtime byexpRotation1Scalarin the same file, so this is two Go functions disagreeing on the same machine rather than a recorded-vector mismatch.Neither result is wrong. Running the same rotation in float64 and measuring both against it:
Neither is consistently closer; they are both a few ulp from exact and differ in where the rounding lands.
The tolerance is chosen from measurement rather than picked. Across these four shapes and rotation angles of (0.9, 0.4), (0.6, 0.8), (0.99, 0.14) and (0.1, 0.99), the largest disagreement between the two paths is 1.91e-06 on values of magnitude ten, so the bound is 1e-5. A pure ulp bound would have needed to be around 64, because one output cancels down to 0.088 where a 4e-07 absolute difference is 52 ulp — relative error is not meaningful for a value that has cancelled.
It still catches real defects: introducing a 0.01 percent error into one coefficient of the unrolled forward path fails the test.
go test ./...passes on arm64 with this change; it fails onmainwithout it.