Definition · Andrew's monotone chainSort the distinct points lexicographically by x then y. Build the lower chain by scanning left to right: maintain a stack, and before pushing p, repeatedly pop the top while the stack has at least two points and orient(s₂, s₁, p) ≤ 0, where s₁ is the top and s₂ the one below it. Build the upper chain the same way over the reversed order. The hull is the two chains concatenated with each one's last point dropped, since it is the other's first.
The sort costs n log n and dominates; the scan is linear, because each point is pushed once per chain and popped at most once per chain. The two chains between them push exactly 2n times and pop no more than they pushed, so the stack work is at most 4n operations. On the square-with-midpoints example further down this course the lab measures 18 pushes and 12 pops, and 30 operations is inside the 36 that argument allows.
Theorem · What the chain computesWith an exact orientation predicate, the monotone chain returns exactly the vertices of the convex hull of the input, in counter-clockwise order, each once. Points strictly inside the hull and points lying in the interior of a hull edge are both excluded.
Take the lower chain. Its invariant is that the stack is a sequence of points increasing in x that turns strictly left at every interior point of the sequence. The pop loop restores that invariant before each push, and a push of a point with larger x cannot violate the part of the sequence below it.
At the end, every point of the input lies on or above the lower chain: if some point were below it, it would have been scanned at its own turn and would have popped whatever lay above it. So the lower chain is the lower boundary of the hull, and its interior points are exactly the hull vertices whose neighbours lie to either side in x.
The upper chain is the mirror image and gives the upper boundary. Their concatenation is the boundary of a convex polygon whose vertices are the points at which it genuinely turns, because the pop condition was ≤ 0 and so removed every point at which it does not.
□
Example · Three points, two predicates, and one missing cornerTake the needle triple (0, 0), (134217729, 134217728), (134217728, 134217727). Sorted, it is (0, 0), then (134217728, 134217727), then (134217729, 134217728). The exact determinant of those three in that order is +1, a left turn, so the lower chain pushes all three and the hull has 3 vertices. The double determinant of the same three is 0, which satisfies ≤ 0, so the middle point is popped at step 3 and the hull comes back with 2. The lab prints both counts side by side and labels the shortfall.
Read the two traces beside each other in the lab's lower table. The exact run is push (0, 0), push (134217728, 134217727), push (134217729, 134217728) on the lower chain: six pushes and one pop across both chains. The double run is push (0, 0), push (134217728, 134217727), then POP (134217728, 134217727), then push (134217729, 134217728). One extra pop, one fewer vertex, and the pop is at the step where the rounded determinant was consulted.
Nothing downstream can put the corner back
Suppose the hull is fed to the rotating-calipers diameter computation, or to a point-in-polygon test, or to anything else that consumes a hull. It receives a convex polygon on two of the three points. Every invariant it would check holds: the points are input points, the polygon is convex, the winding is consistent. The consumer has no evidence that anything is missing, and the diameter it computes will be a real distance between two real points — just not the right one when the missing corner was an endpoint.
This is the argument for exact predicates stated as a number rather than as a principle. It is not that floating point is imprecise; it is that a predicate returning a discrete answer either returns the right discrete answer or corrupts the data structure built on it, and there is no third option and no amount of downstream care that recovers it.
What the lab checks the algorithms against
The page does not decide which hull is right by trusting either chain. Before either algorithm runs, every point is classified from the definition: p is a hull VERTEX when some line through p has every other point weakly on one side and every point lying ON that line strictly beyond p along it. That is a cubic-time test with no sort, no stack and no incremental step in it, and the colours in the drawing come from it rather than from either algorithm.
So the table in the middle of the lab is a comparison and not a restatement. On the needle triple the definition says all three points are vertices, the exact chain agrees, and the double chain is one short — and the row for the missing point is marked. If the chain and the definition ever disagreed, the status line would say so in red and decline to pick a winner, because a page that reports two exact routes disagreeing is not entitled to guess which one is broken.