Skip to content

GPU coverage fold: compute the bearing without the driver's trig - #779

Merged
A13xB0 merged 2 commits into
mainfrom
fix-530-fold-bearing
Oct 24, 2026
Merged

A13xB0 merged 2 commits into
mainfrom
fix-530-fold-bearing

Conversation

@A13xB0

@A13xB0 A13xB0 commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Refs #530. It needs confirming on the Intel UHD 620 before #530 closes.

Cause. The fold kernel computed the bearing in the textbook form. Its x term, cos(lat1)·sin(lat2) − sin(lat1)·cos(lat2)·cos(dlon), is two numbers near 0.46 that differ by about 0.001 for a cell a few km away. Vulkan only requires a driver's sin/cos to be within 2⁻¹¹ (≈0.0005) absolute, so a driver at that limit leaves x tens of percent wrong. That fits the issue's diagnosis exactly: 0.9 dB on the beam, about 8.7° of bearing, station 1 only, flat patterns unaffected, no rank swaps. Metal and RADV compute trig accurately enough to hide it, which is why it passed everywhere else.

Fix. The same quantity, rearranged so nothing cancels: x = sin(dlat) + 2·sin(lat1)·cos(lat2)·sin²(dlon/2), y = sin(dlon)·cos(lat2). Every sine is a degree-11 series (half-angle identities for latitudes), and atan2 is a polynomial good to about 1e-5 rad. The bearing no longer uses any driver trig. The elevation's atan2 uses the same polynomial.

Evidence without the hardware. A new CPU test runs the kernel's arithmetic in float32 with sin and cos pushed to ±2⁻¹¹ over the fold test's raster:

worst bearing error with trig out by 2^-11: textbook form 177.271 deg, kernel's form 0.0281 deg

The remaining 0.03° is float32 coordinates for cells within a few hundred metres of the mast. It's under 0.01° beyond 2 km, and about 0.003 dB on the test beam.

On a real GPU here (RX 5700 XT, RADV) the fold comparison is unchanged at 0.0327 dB, and it now logs its worst disagreement on a pass, so a device close to the 0.05 dB limit is visible.

Distance too. haversine_km takes sin of half a cell's latitude difference, a few ten-thousandths of a radian, which is the size of the error Vulkan allows. The same float32 mirror with trig at ±2⁻¹¹ puts a cell 50 km away 7.1 km out in the old form, and 0.32 m out with psin/pcos. It now uses them as well.

To close #530: run go test ./internal/rf/gpu/ -run 'TestKernelTwins|TestSelfCheck' -v on the Intel machine.

@A13xB0
A13xB0 force-pushed the fix-530-fold-bearing branch from de3c081 to fcd57bf Compare October 24, 2026 19:37
The textbook bearing's x term cancels two numbers near 0.46 down to about
a thousandth for a nearby cell, so a driver whose sin and cos sit at
Vulkan's permitted 2^-11 absolute error puts the bearing degrees out. On
an Intel UHD 620 that mispriced a beam by 0.9 dB and failed the device's
self-check. The kernel now uses the cancellation-free form
sin(dlat) + 2 sin(lat1) cos(lat2) sin^2(dlon/2), with series sines and a
polynomial atan2, so no driver trig is involved.

A CPU test runs the kernel's arithmetic in float32 with trig out by
2^-11: the old form is up to 177 degrees out, the new one 0.03 (float32
coordinates next to the mast). The fold comparison now logs its worst
disagreement on a pass.

Refs #530
haversine_km took sin of half a cell's latitude difference, a few
ten-thousandths of a radian, which is the error Vulkan lets a driver's
sin have. With trig only that good it put a cell 50 km away 7 km out.
It now uses psin and pcos, and a float32 mirror checks it.
@A13xB0
A13xB0 force-pushed the fix-530-fold-bearing branch from fcd57bf to 14e47c5 Compare October 24, 2026 19:52
@A13xB0
A13xB0 merged commit 5cdf9d7 into main Oct 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The coverage fold's gain is out by up to 0.9 dB on a directional antenna, against its CPU twin

1 participant