Remove the corner helpers akgl_collide_rectangles no longer uses
Some checks failed
libakgl CI Build / cmake_build (push) Failing after 21s
libakgl CI Build / performance (push) Failing after 21s
libakgl CI Build / memory_check (push) Failing after 17s
libakgl CI Build / mutation_test (push) Failing after 19s

akgl_rectangle_points, akgl_collide_point_rectangle, akgl_Point and
akgl_RectanglePoints go. They were the intermediate form of an implementation
that changed: akgl_collide_rectangles was eight corner-containment tests built on
them, and it has been four span comparisons since the cross-case fix. Nothing
outside tests/ called either function, and a point-in-rectangle test is four
comparisons a caller can write without a struct conversion in front of them.

akgl_collide_rectangles stays. It has two correct callers in the sidescroller
asking a game-level overlap question -- a coin, a hazard, from an updatefunc --
where a bool is the whole answer and a proxy plus a narrowphase call would be
computing a normal nothing reads. TODO.md records the split rather than leaving
it to be rediscovered.

Public API removal, so 194 exported akgl_ symbols against 196, and the manual's
counts move with them. The perf suite loses its rectangle_points row; the
all-pairs sweep stays as the control it is now labelled, and PERFORMANCE.md says
what 0.8.0 measured against it -- 188.5 us for 32,640 pairs at 256 actors, where
a whole step with collision attached is 54.1 us doing strictly more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
This commit is contained in:
2026-08-02 08:09:42 -04:00
parent 3a6569e384
commit 4e32328681
11 changed files with 134 additions and 395 deletions

View File

@@ -125,7 +125,6 @@ reciprocal.
| `akgl_physics_simulate`, 64 live actors | frame | 1,216.8 | 821,841 |
| `akgl_physics_simulate`, empty pool | frame | 63.9 | 15,650,101 |
| logic frame: 64 updates + simulate | frame | 5,763.1 | 173,517 |
| `akgl_rectangle_points` | call | 4.0 | 248,412,026 |
| `akgl_collide_rectangles`, overlapping | call | 6.1 | 164,345,776 |
| `akgl_collide_rectangles`, disjoint | call | 6.1 | 164,423,708 |
| control: all-pairs collision sweep, 64 actors (2016 pairs) | sweep | 11,769.1 | 84,968 |
@@ -381,27 +380,29 @@ neither is the feature doing its job:
What is left is the struct, and it is paid whether or not a game uses collision.
That is worth knowing rather than smoothing over.
### The collision helpers are fine; the missing broad phase is the problem
### The overlap test is fine; the all-pairs loop around it was the problem
`akgl_collide_rectangles` is 6.1 ns whether the rectangles overlap or not. It
was 24.9 ns overlapping and 57.9 ns disjoint until 0.8.0, when it stopped being
eight `akgl_collide_point_rectangle` calls and became four comparisons -- a
change made to fix the cross case it could not see, with the speed as a side
effect rather than the goal. The disjoint case improved most because it was the
one that ran all eight tests before answering.
`akgl_collide_rectangles` is 6.1 ns whether the rectangles overlap or not. It was
24.9 ns overlapping and 57.9 ns disjoint until 0.8.0, when it stopped being eight
corner-containment tests and became four span comparisons -- a change made to fix
the cross case it could not see, with the speed as a side effect rather than the
goal. The disjoint case improved most because it was the one that ran all eight
tests before answering.
**Read that 6.1 as a floor, not a measurement.** `akgl_rectangle_points` is
untouched by that change and reads 6.1 in the same run against the 4.0 recorded
above, so this run's resolution is around 6 ns and the collision test is now too
cheap to distinguish from a function that does almost nothing. The rows above are
not re-baselined for it; only the three rows the change actually moved are.
**Read that 6.1 as a floor, not a measurement.** It is within this run's
resolution of a function that does almost nothing, and the rows above are not
re-baselined for it; only the rows the change actually moved are.
What the library does not provide is a broad phase, so a caller that wants
collision writes the all-pairs loop: 2016 pairs for 64 actors, **12 µs** a frame,
0.07% of a 60 fps budget. That is affordable. It is still O(n²): raise
`AKGL_MAX_HEAP_ACTOR` to 256 and the same loop is 32,640 pairs, which at this
per-pair cost is around 200 µs — 1.2% of the frame, for a game that has done
nothing yet.
The cost was never the test. It was the loop a caller had to write around it,
because there was no broad phase: 2016 pairs for 64 actors, **12 µs** a frame,
0.07% of a 60 fps budget. Affordable, and still O(n²) -- at
`AKGL_MAX_HEAP_ACTOR=256` the same loop is 32,640 pairs and **188.5 µs measured**,
1.1% of the frame for a game that has done nothing yet.
**That loop is what 0.8.0 removed the need for.** A whole physics step with a
collision world attached is 54.1 µs at 256 actors, doing strictly more -- see
"Collision, measured" below. The all-pairs row stays as the `control:` it is
labelled, which is what it is measuring now.
### Spawning is cheap, and a third of it is a log line