Algorithm Search⌘K

Proofs: Linear sieve

These are the human proofs of Linear sieve, at full length.

The linear sieve computes the primes and the least prime factors up to n, writing each composite once full

This proof shows: correctness.

For m≥2m \ge 2 let lp(m)\mathrm{lp}(m) be the least prime factor of mm. If n<2n < 2, the loop of line L2 does not run, and the output is the empty list with lp[m]=0\mathrm{lp}[m] = 0 for m≤nm \le n, which is correct. Let n≥2n \ge 2.

Lemma 1 (unique form). Let m≥2m \ge 2 be composite. Among all ways to write m=p⋅im = p \cdot i with pp prime and i≥2i \ge 2, exactly one has p≤lp(i)p \le \mathrm{lp}(i), namely p=lp(m)p = \mathrm{lp}(m) and i=m/lp(m)i = m / \mathrm{lp}(m). Moreover, for every prime pp and every i≥2i \ge 2 with p≤lp(i)p \le \mathrm{lp}(i), we have lp(pi)=p\mathrm{lp}(p i) = p.

Proof. Take i≥2i \ge 2 and a prime p≤lp(i)p \le \mathrm{lp}(i). Every prime factor of pip i is pp or a prime factor of ii, which is at least lp(i)≥p\mathrm{lp}(i) \ge p; so lp(pi)=p\mathrm{lp}(p i) = p. This is the second statement. For the first, if m=pim = p i with p≤lp(i)p \le \mathrm{lp}(i), then p=lp(m)p = \mathrm{lp}(m) by the second statement and i=m/pi = m/p, so there is at most one such form. And the form exists: with p=lp(m)p = \mathrm{lp}(m) and i=m/pi = m/p, we have i≥2i \ge 2 because mm is composite, and every prime factor of ii divides mm, so it is at least pp; thus p≤lp(i)p \le \mathrm{lp}(i). □\square

Invariant. When the loop of line L2 starts the round of ii (with 2≤i≤n+12 \le i \le n + 1, the value n+1n + 1 meaning the end):

(A) for 2≤j<i2 \le j < i, lp[j]=lp(j)\mathrm{lp}[j] = \mathrm{lp}(j), and the list holds exactly the primes less than ii, in increasing order;

(B) for i≤m≤ni \le m \le n, lp[m]≠0\mathrm{lp}[m] \ne 0 if and only if mm is composite and m/lp(m)<im / \mathrm{lp}(m) < i, and then lp[m]=lp(m)\mathrm{lp}[m] = \mathrm{lp}(m);

(C) every write of line L7 so far went to a different index.

Initialization. At i=2i = 2, the list is empty and every entry is 0. No composite mm has m/lp(m)<2m/\mathrm{lp}(m) < 2. No write has happened. So (A), (B) and (C) hold.

Maintenance. Assume the invariant at the start of the round of i≤ni \le n.

First, lines L3 and L4. By (B) with m=im = i: if ii is composite, then i/lp(i)<ii / \mathrm{lp}(i) < i, so lp[i]=lp(i)≠0\mathrm{lp}[i] = \mathrm{lp}(i) \ne 0 and line L3 fails. If ii is prime, then lp[i]=0\mathrm{lp}[i] = 0, and line L4 sets lp[i]=i=lp(i)\mathrm{lp}[i] = i = \mathrm{lp}(i) and appends ii, which is larger than every prime in the list. Either way, after line L4, lp[i]=lp(i)\mathrm{lp}[i] = \mathrm{lp}(i) and the list holds exactly the primes up to ii, in increasing order.

Next, the loop of lines L5 to L7. Every prime p≤lp(i)p \le \mathrm{lp}(i) satisfies p≤ip \le i, so it is in the list. The loop takes the primes of the list in increasing order and stops at the first one with p>lp(i)p > \mathrm{lp}(i) or pi>np i > n. So it runs line L7 exactly for the primes pp with p≤lp(i)p \le \mathrm{lp}(i) and pi≤np i \le n. By Lemma 1, line L7 sets lp[pi]=p=lp(pi)\mathrm{lp}[p i] = p = \mathrm{lp}(p i), and (pi)/lp(pi)=i(p i) / \mathrm{lp}(p i) = i.

Now check the invariant at i+1i + 1. (A): the entry lp[i]\mathrm{lp}[i] is correct, as shown, and entries below ii do not change, because each write goes to pi≥2i>ip i \ge 2i > i. (B): let i+1≤m≤ni + 1 \le m \le n. If mm is composite with m/lp(m)<im / \mathrm{lp}(m) < i, then lp[m]=lp(m)\mathrm{lp}[m] = \mathrm{lp}(m) already by (B), and a write in this round would go to m=pim = p i with m/lp(m)=im / \mathrm{lp}(m) = i, which is not the case, so the entry stays. If mm is composite with m/lp(m)=im / \mathrm{lp}(m) = i, then p=lp(m)≤lp(i)p = \mathrm{lp}(m) \le \mathrm{lp}(i) by Lemma 1, and pi=m≤np i = m \le n, so this round writes lp[m]=lp(m)\mathrm{lp}[m] = \mathrm{lp}(m). In every other case, mm is prime or m/lp(m)>im / \mathrm{lp}(m) > i; then lp[m]=0\mathrm{lp}[m] = 0 by (B), and this round does not write mm, since each write goes to an mm with m/lp(m)=im / \mathrm{lp}(m) = i. (C): the writes of this round go to the indices pip i for distinct pp, which are distinct, and each has m/lp(m)=im / \mathrm{lp}(m) = i. A write of an earlier round i′<ii' < i went to an index with m/lp(m)=i′≠im / \mathrm{lp}(m) = i' \ne i. So no index is written twice.

Termination. The outer loop runs n−1n - 1 times, and each inner loop runs at most π(n)+1\pi(n) + 1 times.

Conclusion. At the end, i=n+1i = n + 1, and (A) says that lp[j]=lp(j)\mathrm{lp}[j] = \mathrm{lp}(j) for all 2≤j≤n2 \le j \le n and that the list holds exactly the primes up to nn, in increasing order. Indices 0 and 1 are never written, since each write goes to pi≥4p i \ge 4 and line L4 writes i≥2i \ge 2. ■\blacksquare

The count of writes. By (C) and (B), line L7 writes each composite m≤nm \le n exactly once, in the round of i=m/lp(m)i = m / \mathrm{lp}(m), and writes nothing else. So it runs exactly n−1−π(n)n - 1 - \pi(n) times. In each round, the inner loop makes one test of line L6 per write, plus at most one test that breaks or the end of the list, so lines L5 and L6 run at most (n−1−π(n))+(n−1)(n - 1 - \pi(n)) + (n - 1) times in total. This gives the Θ(n)\Theta(n) bound.

Back to Linear sieve