PrimeInt.Pas Program Listing




{ Start of file PrimeInt.Pas ***********************************************}

{$A+,B-,D+,E+,F-,I+,L+,N+,O-,R-,S+,V+}
{$M 16384,0,655360}

unit PrimeInt; { Converted from Apple II+ Pascal to Turbo Pascal 5.0 }
               { and changed from SextPrime to PrimeInt }
               { 90/07/08 by Harry Smith, Saratoga CA }

{ Algorithm 357 - Collected Algorithms from ACM }
{ An Efficient Prime Number Generator using the sieve of Eratosthenes }

{ Driver can generates all the primes <= 2147107031 = 2^31 - 376617 }
{
  Name    = 'PrimeInt - Generates Primes';
  Version = 'Version 1.00, last revised: 90/09/15 0600 hours';
  Author  = 'Copyright (c) 1981-1990 by author: Harry J. Smith,';
  Address = '19628 Via Monte Dr., Saratoga CA 95070.  All rights reserved.';
}
{***************************************************************************}

{ Developed in TURBO Pascal 5.0 }

interface

const
  JLim = 6500;       { Size of working array }
  MaxT = 2147107031; { Approximately the max prime that can be generated }

type
  PrimeType  = LongInt;
  PrimeStore = array[1..JLim] of PrimeType; { Working storage for primes }

var
  IP : PrimeStore; { Working storage for primes }

{ The following PROCEDURE(s) can be called externally: }

  function NPrime(M : Integer) : Integer;
  { M = Number of new primes desired this call, must be >= 2 on 1st call }
  {     keep M <= JLim / 2 for speed, must be < JLim. }
  { The current length of the tables in array IQ and JQ is returned }
  {   This is approx. the number of primes < Sqrt(current prime) }
  {   It must not reach QS = 4793 because the 4793rd prime = 46349 and }
  {   this squared is greater than 2^32 - 1, the max LongInt. }
  {   If no more primes can be generated, -4793 is returned. }

{************************************************************}

implementation

const
  QS = 4793; { Size of IQ and JQ arrays, must be large enough to hold }
             {   all primes <= Sqrt(MaxT) }

type
  WordStore  = array[1..QS] of Word;      { Secondary table of primes }
  LongStore  = array[1..QS] of PrimeType; { Secondary table of primes squared
                                           etc. = next composite to cross off }
var
  IQ : LongStore; { Secondary table of primes squared etc. }
  JQ : WordStore; { Secondary table of primes < Sqrt(current prime) }
                  {   2, 3, 5, 7, ... 46349 (the 4793rd prime) }

{--------------------------------------}
function NPrime(M : Integer) : Integer;
label 10, 20, 30, 40, 50, 60;
const                  { Typed constants are Static variables }
  IJ  : Word      = 0; { Number of Primes in secondary prime table }
  IK  : Word      = 0; { Number of Primes for testing secondary primes }
  INC : Word      = 0; { = 2, 4, 2, 4, ... }
  J   : Word      = 0; { Array index, sieve index on exit }
  NJ  : Word      = 0; { Test number for secondary table of primes }
  NI  : PrimeType = 0; { Test number - 2 * J for primes }

{ note:  IQ[1] is used as a Static variable to save highest number in sieve }

var
  I   : Word; { Array index }
  JQI : Word; { JQ[I] to store in IP[J] }
  K   : Word; { Number of Primes in primary prime table }

begin
  K:= 0;  if (IP[1] >= 0) and (IJ < QS) then  GoTo 60;
  if IP[1] < 0 then begin
    { Set initial conditions }
    IP[1]:=  2;  JQ[1]:= 2;  IK:=    2;  INC:= 2;
    IQ[2]:=  9;  JQ[2]:= 3;  IQ[1]:= 3;  IJ:=  3;
    IQ[3]:= 25;  JQ[3]:= 5;  NJ:=    5;  K:=   1;
  end;
  if IJ >= QS then begin
    for I:= 1 to M do  IP[I]:= 0; { Clear primes that cannot be generated }
    NPrime:= -QS;  Exit;          { Indicate no more primes can be generated }
  end;
  { Prepare to delete a sequence of composite numbers }
10:
  J:= K + 1;  NI:= IQ[1] - J - J;
  IQ[1]:= NI + JLim + JLim;
  for I:= J to JLim do  IP[I]:= 0;
20:
  I:= IJ;  if IQ[IJ] >= IQ[1] then  GoTo 50;
  { Extend the list of primes in array JQ counting so as to omit
    multiples of 2 and 3 }
30:
  NJ:= NJ + INC;  INC:= 6 - INC;
  if Sqr( JQ[IK+1]) <= NJ then  IK:= IK + 1;
  for J:= 3 to IK do
    if (NJ DIV JQ[J]) * JQ[J] = NJ then  GoTo 30;
  IJ:= IJ + 1;  JQ[IJ]:= NJ;  IQ[IJ]:= PrimeType(NJ) * NJ;
  if IJ >= QS then begin
    { Clear primes that cannot be generated }
    for I:= (K + 1) to M do  IP[I]:= 0;
    NPrime:= -QS;  Exit;     { Indicate no more primes can be generated }
  end;
  GoTo 20;
  { If J+J+NI is composite, enter its smallest prime factor in IP[J].
    If J+J+NI is prime, then set IP[J] to 0 }
40:
  IP[J]:= JQI;  J:= J + JQI;
  if J < JLim then  GoTo 40;
  IQ[I]:= NI + J + J;
50:
  I:= I - 1;  JQI:= JQ[I];  J:= (IQ[I] - NI) DIV 2;
  if J < JLim then  GoTo 40;
  if I <> 1 then  GoTo 50;  J:= K;
  { Pack the next M primes in IP[1], ..., IP[M] }
60:
  J:= J + 1;  if IP[J] <> 0 then  GoTo 60; { IP[JLim] is always 0 }
  if J = JLim then  GoTo 10;  
  K:= K + 1;  IP[K]:= NI + J + J;
  if K <> M then  GoTo 60;
  NPrime:= IJ
end; { NPrime }

{ PrimeInt Unit initialization }
begin
  IP[1]:= -1;
end.

{ End of file PrimeInt.Pas *************************************************}

Return to Golygons
Return to Harry's Home Page


This page accessed times since October 20, 2004.
Page created by: hjsmithh@sbcglobal.net
Changes last made on Saturday, 14-May-05 12:47:34 PDT