'=========================================================================== ' Subject: PRIME NUMBER GENERATOR Date: 03-19-00 (16:37) ' Author: Don Schullian Code: PB ' Origin: d83@DASoftVSS.com Packet: PB.ABC '=========================================================================== $if 0 Prime Number Generator Algorithm from Knuths "Sorting and Searching" Page 617 Programmed by Rich Geldreich Coded for PowerBASIC by Don Schullian on 2000-03-19 Notes: This prime number generator uses a disk file "PRIMEPB.BIN" to hold the prime numbers, so little RAM memory is needed. Each prime number is represented as the difference between the last prime number by a single byte. In other words, the gap between each prime number is stored instead of each prime number itself. All gaps are even numbers, because all primes must be odd numbers. Therefore, each byte can represent a gap of up to 510, because the least significant bit of each gap length is always unused. (Except for the special cases of 1-2, and 2-3. These primes arent stored in the disk file; theyre assumed to be present.) Since the maximum gap between all consecutive primes up to 436,273,009 is only 286, a single byte is good enough for this program!) The program stops when escape is pressed or when the priority queue is full. $endif '----------------------------------------------------------------- $DIM ALL $STRING 4 OPTION BINARY BASE 1 '----------------------------------------------------------------- %HeapSize = 4096 'Maximum prime candidate = HeapSize*HeapSize %IOSize = 2048 '----------------------------------------------------------------- DECLARE SUB ClearKeyboard () DECLARE SUB PutPrime (SEG NewLast AS LONG) DECLARE FUNCTION fGetPrime () AS LONG '----------------------------------------------------------------- DIM PrimeBuf1 AS SHARED STRING * %IOSize DIM Buf1Loc AS SHARED INTEGER DIM Buf1FLoc AS SHARED LONG DIM PrimeBuf2 AS SHARED STRING * %IOSize DIM Buf2Loc AS SHARED INTEGER DIM Buf2FLoc AS SHARED LONG DIM LastPrime1 AS SHARED LONG DIM LastPrime2 AS SHARED LONG DIM SlideFlag AS SHARED INTEGER '----------------------------------------------------------------- DIM HeapQ (%HeapSize) AS LONG ' priority queue DIM HeapQ1(%HeapSize) AS LONG DIM HeapQ2(%HeapSize) AS LONG DIM t AS LONG DIM Q AS LONG DIM Q1 AS LONG DIM Q2 AS LONG DIM TQ AS LONG DIM TQ1 AS LONG DIM u AS LONG DIM n AS LONG DIM FileSpec AS STRING DIM i AS INTEGER DIM j AS INTEGER DIM d AS INTEGER DIM r AS INTEGER DIM Mask AS STRING '--------------------------------------------------------------------------- '-------------------- start of code -------------------------------------- '--------------------------------------------------------------------------- FileSpec = "PrimePB.bin" Buf1Loc = 1 : Buf1FLoc = 1 Buf2Loc = 2 : Buf2FLoc = 1 LastPrime1 = 3 : LastPrime2 = 5 n = 5 d = 2 r = 1 t = 25 HeapQ (1) = 25 HeapQ1(1) = 10 HeapQ2(1) = 30 IF LEN(DIR$(FileSpec)) THEN KILL FileSpec OPEN FileSpec FOR BINARY AS #1 CLS ClearKeyboard DO DO Q = HeapQ (1) Q1 = HeapQ1(1) Q2 = HeapQ2(1) TQ = Q + Q1 TQ1 = Q2 - Q1 i = 1 DO j = i * 2 IF j > r THEN EXIT DO IF ( j < r ) AND _ ( HeapQ(j) > HeapQ(j + 1) ) THEN INCR j END IF IF TQ =< HeapQ(j) THEN EXIT DO HeapQ(i) = HeapQ(j) HeapQ1(i) = HeapQ1(j) HeapQ2(i) = HeapQ2(j) i = j LOOP HeapQ(i) = TQ HeapQ1(i) = TQ1 HeapQ2(i) = Q2 LOOP UNTIL n <= Q WHILE n < Q PutPrime n n = n + d d = 6 - d WEND IF n = t THEN u = fGetPrime t = u * u j = r + 1 DO i = j \ 2 IF i = 0 THEN EXIT DO IF HeapQ(i) <= t THEN EXIT DO HeapQ(j) = HeapQ(i) HeapQ1(j) = HeapQ1(i) HeapQ2(j) = HeapQ2(i) j = i LOOP HeapQ(j) = t IF (u MOD 3) = 2 THEN HeapQ1(j) = 2 * u ELSE HeapQ1(j) = 4 * u END IF HeapQ2(j) = 6 * u INCR r IF r = %HeapSize THEN EXIT DO END IF n = n + d d = 6 - d LOOP UNTIL INSTAT IF Buf1Loc > 1 THEN DECR Buf1Loc Mask = LEFT$(PrimeBuf1,Buf1Loc) PUT #1, Buf1FLoc, Mask END IF CLS SEEK #1, 1 LastPrime1 = 3 Mask = "#,###,###,### " PRINT " 1 2 3 "; FOR i = 1 TO LOF(1) \ %IOSize GET #1, , PrimeBuf1 FOR j = 1 TO %IOSize INCR LastPrime1, ASC(PrimeBuf1, j) * 2 PRINT USING Mask; LastPrime1; IF CSRLIN = 25 THEN PRINT "Press to end"; ClearKeyboard WHILE NOT INSTAT : WEND IF INKEY$ = CHR$(27) THEN GOTO ByeBye CLS END IF NEXT IF INSTAT THEN EXIT FOR NEXT ByeBye: ClearKeyboard LOCATE 25, 1 : PRINT "THE END "; CLOSE #1 END '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- FUNCTION fGetPrime () AS LONG DIM V AS LOCAL INTEGER IF SlideFlag = 0 THEN V = ASC(PrimeBuf1, Buf2Loc) ELSE V = ASC(PrimeBuf2, Buf2Loc) END IF SHIFT LEFT V, 1 INCR LastPrime2, V INCR Buf2Loc IF Buf2Loc > %IOSize THEN INCR Buf2FLoc, %IOSize GET #1, Buf2FLoc, PrimeBuf2 Buf2Loc = 1 END IF FUNCTION = LastPrime2 END FUNCTION '--------------------------------------------------------------------------- '---------- '--------------------------------------------------------------------------- SUB PutPrime (SEG NewLast AS LONG) DIM TotalPrimes AS STATIC LONG ASC(PrimeBuf1,Buf1Loc) = (NewLast - LastPrime1) \ 2 INCR Buf1Loc LastPrime1 = NewLast IF Buf1Loc <= %IOSize THEN EXIT SUB INCR TotalPrimes, %IOSize LOCATE , 1 PRINT "Primes found:"; TotalPrimes; _ "Maximum candidate:"; NewLast; PUT #1, Buf1FLoc, PrimeBuf1 Buf1Loc = 1 INCR Buf1FLoc, %IOSize IF SlideFlag = 0 THEN SlideFlag = -1 PrimeBuf2 = PrimeBuf1 END IF END SUB '--------------------------------------------------------------------------- '---------- '--------------------------------------------------------------------------- SUB ClearKeyboard () DIM D AS LOCAL STRING WHILE INSTAT : D$ = INKEY$ : WEND END SUB