Repository navigation
h3go: check the projection against an exact evaluation - #155
Merged
Merged
Conversation
Every float test so far compares pure Go with the C library, which shows agreement but cannot tell accuracy from shared error. This test evaluates the same chain from a cell's integer face coordinates to a unit vector in 256-bit arithmetic and measures how far the float64 result lands from it. The chain is rational arithmetic plus square roots since toVec3 stopped calling atan2, atan, sin and cos: the hex2d map uses sqrt(3), the per-resolution scale is 1/sqrt(7), the Class III rotation's sine and cosine are sqrt(3/28) and sqrt(25/28), the inverse gnomonic uses 1/sqrt(1+r^2), and the tangent basis is a normalization and a cross product. The only transcendentals are the sine and cosine of the twenty face-axis azimuths, which the test computes once by series. The face center vectors, the azimuths and the gnomonic scale are taken as the package's literals, which are the definition. Centers are checked through faceIJK.toVec3. Boundaries are checked by a walk that mirrors toCellBoundary and pentToCellBoundary, so the inserted face-crossing vertices and the 2D line intersection that places them are covered along with the topological vertices; the walk is checked against Boundary() by vertex count. Comparison is by chord length between the two unit vectors, which equals the angular separation at these magnitudes and avoids the asin and atan2 of the final conversion to degrees. Every cell at res 0 to 2 is enumerated by default, about one second, and one descendant per base cell at every finer resolution. The variable H3GO_EXACT_PROJECTION_MAXRES raises the enumerated resolution; res 4 takes fifteen seconds. The largest separation observed is 3.9e-14 degrees of arc, about three ulps of a unit-vector component; the bound is 1e-13. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Coverage Report for CI Build 37064629401Coverage remained the same at 100.0%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
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.
Summary
Adds a test that checks the pure-Go projection from a cell's face coordinates to a point on the unit sphere against the same formula evaluated in 256-bit arithmetic.
Every float test so far, including the conformance suite, compares pure Go with the C library. That shows agreement but cannot tell accuracy from shared error. This test can, because since
toVec3stopped callingatan2,atan,sinandcosthe whole chain from integer IJK coordinates to a unit vector is rational arithmetic plus square roots, whichmath/bigevaluates to any precision. The only transcendentals left are the sine and cosine of the twenty fixed face-axis azimuths, computed once by Taylor series.What is checked
faceIJK.toVec3for every cell at res 0 to 2 (full enumeration) and one descendant per base cell at every resolution to 15.toCellBoundaryandpentToCellBoundarystep for step, so the inserted face-crossing vertices and the 2D line intersection that places them are covered along with the topological vertices. The walk is checked againstBoundary()by vertex count on every cell.Both compare the float64 unit vector with the exact one by chord length, which equals the angular separation at these magnitudes and avoids the
asinandatan2of the final conversion to degrees.The oracle's constants are the definitions the float64 code approximates: the face center vectors, axis azimuths and gnomonic scale are the package's literals;
sqrt(3)/2,1/sqrt(7),1/3and the Class III rotation's sine and cosine (sqrt(3/28)andsqrt(25/28)) are computed exactly rather than taken from the rounded float64 constants.Results
H3GO_EXACT_PROJECTION_MAXRES=4)One ulp of a unit-vector component is about 1.3e-14 degrees, so the worst case is about three ulps. The bound is 1e-13 degrees, roughly eight ulps and a hundred times tighter than the conformance suite's coordinate tolerance.
Combined with the conformance suite this gives the first bound on the reference itself: pure Go is within 1e-13 degrees of the exact formula, and C is within 1e-11 degrees of pure Go, so C is within about 1e-11 degrees of the exact formula.
Not covered
latLngToCellneeds sine and cosine of arbitrary inputs andcellAreaneedsatan, so both stay under the agreement tests.Test plan
go test -count=2 -race ./x/h3go/passesH3GO_EXACT_PROJECTION_MAXRES=4passesgolangci-lint run ./x/h3go/clean🤖 Generated with Claude Code