How to resolve the algorithm Sieve of Pritchard step by step in the Pascal programming language
How to resolve the algorithm Sieve of Pritchard step by step in the Pascal programming language
Table of Contents
Problem Statement
The Sieve of Pritchard is an algorithm for finding the prime numbers up to a given limit N, published in 1981. It considers many fewer composite numbers than the Sieve of Eratosthenes (and has a better asymptotic time complexity). However, unlike the latter, it cannot be modified to greatly reduce its space requirement, making it unsuitable for very large limits. Conceptually, it works by building a wheel representing the repeating pattern of numbers not divisible by one of the first k primes, increasing k until the square of the k'th prime is at least N. Since wheels grow very quickly, the algorithm restricts attention to the initial portions of wheels up to N. (Small examples of the wheels constructed by the Sieve of Pritchard are used in the "wheel-based optimizations" mentioned in the Eratosthenes task.) For example, the second-order wheel has circumference 6 (the product of the first two primes, 2 and 3) and is marked only at the numbers between 1 and 6 that are not multiples of 2 or 3, namely 1 and 5. As this wheel is rolled along the number line, it will pick up only numbers of the form 6k+1 or 6k+5 (that is, n where n mod 6 is in {1,5}). By the time it stops at 30 (2x3x5) it has added only 8 of the numbers between 6 and 30 as candidates for primality. Those that are multiples of 5 (only 2: 15 and 55) are obtained by multiplying the members of the second-order wheel. Removing them gives the next wheel, and so on. This YouTube video presents the execution of the algorithm for N=150 in a format that permits single-stepping forward and backward through the run. In that implementation, the wheel is represented by a sparse global array s such that for each member w of the wheel, s[w] contains the next member of the wheel; along with a similar "previous member" value, this allows numbers to be removed in a constant number of operations. But the simple abstract algorithm is based on an ordered set, and there is plenty of scope for different implementations. Write a program/subprogram that uses the Sieve of Pritchard algorithm to find all primes up to a specified limit. Show the result of running it with a limit of 150.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Sieve of Pritchard step by step in the Pascal programming language
Source code in the pascal programming language
program Pritchard_console;
{$APPTYPE CONSOLE}
uses
Math, SysUtils, Types;
// Function to return an array of all primes <= N
function PritchardSieve( const N : integer) : Types.TIntegerDynArray;
var
j, j_max, k, len, nrPrimes, p : integer;
marked : Types.TBooleanDynArray;
smallPrimes : Types.TIntegerDynArray; // i.e. primes <= sqrt( N)
spi : integer; // index into array smallPrimes
const
SP_STEP = 16; // step when extending dynamic array smallPrimes
begin
// Deal with trivial input
result := nil;
if (N <= 1) then exit;
// Initialize
SetLength( marked, N + 1); // 0..N for convenience; marked[0] is not used
marked[1] := true; // no other initialization of "marked" is needed
len := 1;
p := 2;
SetLength( smallPrimes, SP_STEP);
spi := 0;
while p*p <= N do begin
// Roll the wheel
if len < N then begin
j_max := Math.Min( p*len, N);
for j := len + 1 to j_max do marked[j] := marked[j - len];
len := j_max;
end;
// Unmark multiples of p
for k := len div p downto 1 do
if marked[k] then marked[p*k] := false;
// Store the prime p, extending the array if necessary
if spi = Length( smallPrimes) then
SetLength( smallPrimes, spi + SP_STEP);
smallPrimes[spi] := p;
inc(spi);
// Find the next prime p
if p = 2 then p := 3
else repeat inc(p) until (p > N) or marked[p];
// Condition p > N is a safety net; should always hit a marked value
Assert(p <= N);
end; // while
// Final roll, if needed. It is not needed if N >= 49. This is because
// 2 < 3^2, 2*3 < 5^2, 2*3*5 < 7^2, but thereafter 2*3*5*7 > 11^2, etc.
if len < N then
for j := len + 1 to N do marked[j] := marked[j - len];
// Remove 1 and put the small primes back
marked[1] := false;
for k := 0 to spi - 1 do marked[smallPrimes[k]] := true;
// Use the boolean array to return an array of prime integers
nrPrimes := 0;
for j := 2 to N do
if marked[j] then inc( nrPrimes);
SetLength( result, nrPrimes);
k := 0;
for j := 2 to N do
if marked[j] then begin result[k] := j; inc(k); end;
end;
// Main routine. User types the program name,
// optionally followed by the limit N (defaults to 150)
var
N, j : integer;
primes : Types.TIntegerDynArray;
begin
if ParamCount = 0 then N := 150
else N := SysUtils.StrToInt( ParamStr(1));
primes := PritchardSieve(N);
WriteLn( 'Number of primes = ', Length(primes));
for j := 0 to Length(primes) - 1 do begin
Write( ' ', primes[j]:4);
if j mod 10 = 9 then WriteLn;
end;
end.
You may also check:How to resolve the algorithm Morse code step by step in the AutoHotkey programming language
You may also check:How to resolve the algorithm Check output device is a terminal step by step in the Raku programming language
You may also check:How to resolve the algorithm Erdős-Nicolas numbers step by step in the ALGOL 68 programming language
You may also check:How to resolve the algorithm Law of cosines - triples step by step in the Go programming language
You may also check:How to resolve the algorithm Ackermann function step by step in the OCaml programming language