This is blog 6 of a series of blogs about algorithmic challenges I came across when creating tgen.
In this blog we will tackle:
- Generate random distinct integer points in an box, with no three collinear, in time.
We call such set of points (all distinct, with no three collinear) to be in general position. This is useful when testing geometry problems. Our construction has no uniformity guarantee: we do not sample uniformly from all general-position point sets in the box. Our goal is only for the points to look random, in the sense that they have no obvious geometric pattern. Picking random grid points and rejecting a point whenever it forms a line with two previous points is expensive: there are already forbidden lines after choosing points. We would rather have a construction where general position is guaranteed.
The parabola almost works
Consider the construction
Lemma 1: The points are in general position.
Proof: A nonvertical line intersects the parabola where
This is a quadratic equation, so it has at most two roots. A vertical line intersects the parabola at most once. Therefore no line contains three of the points.
The problem is the coordinate range: the second coordinate grows to . We want the same quadratic-root argument while keeping both coordinates in a range of size .
A hyperbola over a finite field
Let be a prime and work in the finite field . Consider
There are points, and both coordinates are residues in . More importantly, no line contains three of them.
Lemma 2: No three points of are collinear over .
Proof: Write a line as
where are not all zero. At a point of , and . Multiplying the line equation by gives
This is a nonzero polynomial of degree at most two, so it has at most two roots in a field. Hence the line meets in at most two points.
We can now choose the first prime , shuffle the residues , keep the first values , and take . Only is required to have enough nonzero residues; starting from gives us a larger pool to sample from while keeping .
Using a prime modulus is important because is a field: every nonzero has an inverse, and a nonzero polynomial of degree two has at most two roots. Both facts are used in Lemma 2 and might not hold modulo a composite number.

The first points modulo . The construction is correct, but the points only occupy the left half of the box and the algebraic pattern is visible.
Randomizing the shape
The raw construction visibly lies on the modular hyperbola, so we can randomize its appearance with invertible linear maps over . We compose a constant number of random shears of the two forms
Each shear is reversible: its inverse is the same shear with replaced by . Shears also map lines to lines. Therefore, if three transformed points were collinear, applying the inverse shears would show that the three original points were collinear as well. By Lemma 2 this is impossible, so any composition of these shears preserves general position.
All arithmetic here is modulo ; after each shear, we represent each coordinate by an integer in .
Theorem 1: The construction returns distinct integer points in , with no three collinear.
Proof: The base points are distinct because their first coordinates are distinct. By Lemma 2, every triple has nonzero orientation determinant over . Every shear is invertible, so the determinant of every triple remains nonzero modulo ; in particular, distinct points remain distinct.
Coordinate range and complexity
By Bertrand’s postulate, the smallest prime satisfies . Therefore the required side length is .
There are candidate residues. Shuffling them, computing modular inverses, and applying a constant number of shears take time in total. The construction uses memory.
The result is not uniform among all general-position subsets of the box. The random subset and shears are there to provide varied test cases while retaining a deterministic correctness guarantee.

The same points after eight random invertible shears. They now fill the box much more evenly, while the proof that no three are collinear is unchanged.
Warning: The shears hide the visual pattern, but not the algebraic one: modulo , all output points still lie on a single conic (an affine image of ). Combine this generator with other test families if that structure could make the tested problem easier.
References
Bertrand’s postulate: https://en.wikipedia.org/wiki/Bertrand%27s_postulate