In his "Notes on Structured Programming" essay, E. W. Dijkstra gives an example of a program that computes the first 1000 primes (Section 9. "A First Example of Step-Wise Program Composition").
The idea is to iterate all the numbers from 1 to 1000 in increasing order, to test each one and if found to be prime save it into an array p. The test consists of giving an answer to the question of whether the number j is divided by one of the primes found earlier: if it is divided - the number is not prime; otherwise - it is prime.
- j is the number under test and here it is assumed to be incremented by 1 at each iteration (in the original paper an optimization has been introduced where j is odd and incremented by 2).
- The smallest array index is 1.
Next is an excerpt from the paper followed by the question proper:
We use the facts that
(1) [...] the smallest potential factor to be tried is p[1]
(2) the largest prime number to be tried is p[ord - 1] where p[ord] is the smallest prime number whose square exceeds j.(Here I have also used the fact that the smallest prime number whose square exceeds j can already be found in the table p. In all humility I quote Don Knuth's comment on an earlier version of this program, where I took this fact for granted:
"Here you are guilty of a serious omission! Your program makes use of a deep result of number theory, namely that if $p_n$ denotes the $n$-th prime number, we always have $$ p_{n+1} < (p_{n})^2 $$ " Peccavi.)
In my analysis I have arrived at the conclusion that the program does not depend on this result; that is - the program will work correctly even if the inequality above were not true.
Help is needed in finding the error in my line of reasoning, or to identify the misunderstanding of the source material, if that were the case.
The program makes use of a lemma
If a natural number $n > 1$ is composite, then $n$ is divisible by some prime number $p \leq \sqrt{n}$.
(A proof can be found in "Discrete Mathematics" 2nd ed., by Edgar G. Goodaire, page 116)
Thus when we test number j for primality we only need to consider those primes whose squares are less than or equal to j.
Suppose that we have computed the first $n > 1$ primes and all of them are in the array p. We next initiate the process of computing the next prime $p_{n+1}$ by incrementing j and testing it for primality.
In the case where $p_{n} < j < (p_{n})^2$, there exists a prime $p_{k}$ such that $$(p_{k-1})^2 \leq j < (p_{k})^2$$
The potential factors of j are $p_{1},p_{2},..,p_{k-1}$ and all of them are in the array p, thus if the next prime lies in the interval $p_{n} < j < (p_{n})^2$ we are guaranteed to find it.
This is the case which corresponds to the theorem pointed by Don Knuth, and since we know it to be true, we could stop here as far as program correctness is concerned.
But for the sake of argument, let's continue and consider the case $j > (p_{n})^2$. All of the numbers $p_{n} < i < j$ are composite, so the largest prime less than j is $p_{n}$ and, by our assumption $(p_{n})^2 < j$. Thus the potential factors of j are $p_{1},p_{2},..,p_{n}$ and all of them are in the array p.
Given that in both cases the entire list of primes whose square is less than or equal to j is in the table p, and that's the necessary and sufficient condition for the primality test, we conclude that the relation $p_{n+1} < (p_{n})^2$ plays no role in the operation of the program.