{ 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 *************************************************}