The fundamental predicate: given three points, do they turn left, right, or go straight?

int orient(P a, P b, P c) {
    long long v = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    return (v > 0) - (v < 0);           // +1 CCW, 0 collinear, -1 CW
}

This is the sign of the cross product , and equivalently the sign of the determinant

Why it is the predicate

Nearly every 2D algorithm is built from it:

AlgorithmUse of orient
Convex hullpop while the turn is not left
Segment intersectionfour orientation tests
Point in convex polygonsame sign for every edge
Polygon orientationsign of the signed area
Half-plane intersectionwhich side of each line
Sweep linesegment ordering
Is a polygon convex?all turns the same direction
Triangulationear-clipping validity

Getting it exact is therefore worth more than optimising anything else.

Exactness

With integer coordinates up to , differences reach and the products reach — the subtraction fits in long long (limit ). Beyond that, use __int128.

With floating point input, the naive formula can return the wrong sign when the points are nearly collinear — catastrophic cancellation. Three responses:

  1. Scale to integers if the input has bounded precision (multiply by and round).
  2. Use long double and an tuned to the coordinate magnitude.
  3. Adaptive exact predicates (Shewchuk) — compute a fast estimate with an error bound, and fall back to exact arithmetic only when the estimate is inconclusive. This is what production geometry libraries do.

A wrong orientation is not a small error

An incorrect sign does not perturb the answer slightly — it makes a convex hull non-convex, a sweep-line status inconsistent, or a triangulation self-intersecting, and the algorithm then fails in ways that look nothing like a precision problem. This is the single biggest source of hard-to-debug geometry failures.

Derived predicates

// is p on segment ab?  (requires collinearity)
bool onSegment(P p, P a, P b) {
    return orient(a, b, p) == 0 && dot(p - a, p - b) <= 0;
}
 
// do segments ab and cd properly intersect?
bool properIntersect(P a, P b, P c, P d) {
    int o1 = orient(a, b, c), o2 = orient(a, b, d);
    int o3 = orient(c, d, a), o4 = orient(c, d, b);
    return o1 * o2 < 0 && o3 * o4 < 0;
}

dot(p-a, p-b) <= 0 is the elegant way to say ” lies between and ” — the vectors point in opposite directions.

The in-circle predicate

The other classical predicate, needed for Delaunay triangulation: is inside the circle through (taken CCW)?

Degree 4 in the coordinates, so with inputs the determinant reaches far beyond both long long and double. This is why Delaunay implementations need exact predicates or heavily restricted coordinate ranges.

Convexity check

bool isConvex(const vector<P>& poly) {
    int n = poly.size(), sign = 0;
    for (int i = 0; i < n; i++) {
        int o = orient(poly[i], poly[(i+1)%n], poly[(i+2)%n]);
        if (o == 0) continue;                    // allow collinear points
        if (sign == 0) sign = o;
        else if (sign != o) return false;
    }
    return true;
}

Note this accepts polygons with collinear vertices; whether that counts as convex depends on the problem.

See also: Cross Product · Geometry Basics · Segment Intersection