|
| 1 | +0010 // opencomal.txt : a prime sieve implementation in COMAL |
| 2 | +0020 // using a string as a pseudo-bit array for flags |
| 3 | +0030 // by Matthew Kott (kottm), 2021-08-12 |
| 4 | +0040 // inspired by Dave's Garage Prime Sieve |
| 5 | +0050 // modified for OpenCOMAL by Rutger van Bergen |
| 6 | +0070 |
| 7 | +0080 // Historical data for validating our results - the number of primes |
| 8 | +0090 // to be found under some limit, such as 168 primes under 1000 |
| 9 | +0100 // value is for 10^index, for example: |
| 10 | +0110 // knownprimes#(2) = 25 (number of primes under 10^2 or 100) |
| 11 | +0120 DIM knownprimes#(10) |
| 12 | +0130 FOR i:=1 TO 10 DO |
| 13 | +0140 READ knownprimes#(i) |
| 14 | +0150 ENDFOR i |
| 15 | +0160 DATA 4,25,168,1229,9592,78498,664579,5761455,50847534,455052511 |
| 16 | +0170 |
| 17 | +0180 size#:=1000000 |
| 18 | +0190 checkindex#:=LOG10(size#) // for checking aginst knownprimes# |
| 19 | +0200 bitarr_size#:=(size# DIV 8)+(size# MOD 8<>0) |
| 20 | +0210 DIM sieve$ OF bitarr_size# // create a string pseudo-bit array for flags |
| 21 | +0220 passes#:=0 |
| 22 | +0240 |
| 23 | +0250 SELECT OUTPUT "output.txt" |
| 24 | +0260 |
| 25 | +0280 start#:=SYS(now) |
| 26 | +0310 |
| 27 | +0320 WHILE (SYS(now)-start#)<5 DO // do as many iterations as possible in 5 seconds |
| 28 | +0330 sieve$:=CHR$(0)*bitarr_size# // initialze bit array each pass |
| 29 | +0340 runsieve |
| 30 | +0350 passes#:+1 |
| 31 | +0360 ENDWHILE |
| 32 | +0380 |
| 33 | +0390 elapsed#:=SYS(now)-start# |
| 34 | +0400 |
| 35 | +0410 PRINT "Passes: ",passes#,", Time: ",elapsed#,", Avg: ",elapsed#/passes#, |
| 36 | +0420 PRINT ", Count1: ",count#,", Count2: ",knownprimes#(checkindex#), |
| 37 | +0430 PRINT ", Valid: ",valid |
| 38 | +0450 PRINT |
| 39 | +0460 PRINT "kottm;",passes#,";",elapsed#,";1;algorithm=base,faithful=no,bits=1" |
| 40 | +0470 |
| 41 | +0480 END |
| 42 | +0490 |
| 43 | +0500 // end of main program; procudures and functions follow |
| 44 | +0510 |
| 45 | +0520 PROC bitcalc(pos#) // calculate which bit in the string |
| 46 | +0530 byte#:=(pos# DIV 8)+1 |
| 47 | +0540 bit#:=(pos#-1) MOD 8 |
| 48 | +0550 byte$:=sieve$(byte#:byte#) |
| 49 | +0560 ENDPROC bitcalc |
| 50 | +0570 |
| 51 | +0580 FUNC checkbit(pos#) // check the value of a specific bit |
| 52 | +0590 bitcalc(pos#) |
| 53 | +0600 RETURN (ORD(byte$) BITAND 2^bit#)/(2^bit#) |
| 54 | +0610 ENDFUNC checkbit |
| 55 | +0620 |
| 56 | +0630 PROC setbit(pos#,val#) // set a bit to a specific value |
| 57 | +0640 IF checkbit(pos#)<>val# THEN |
| 58 | +0650 sieve$(byte#:byte#):=CHR$(ORD(byte$) BITOR 2^bit#) |
| 59 | +0660 ENDIF |
| 60 | +0670 ENDPROC setbit |
| 61 | +0680 |
| 62 | +0690 PROC runsieve // main procedure for Sieve of Eratosthenes |
| 63 | +0700 count#:=0 |
| 64 | +0710 FOR i#:=2 TO size#-1 DO |
| 65 | +0720 IF checkbit(i#)=0 THEN |
| 66 | +0730 prime#:=i#+i# |
| 67 | +0740 FOR k#:=prime# TO size#-1 STEP i# DO |
| 68 | +0750 setbit(k#,1) |
| 69 | +0760 ENDFOR k# |
| 70 | +0770 count#:+1 |
| 71 | +0780 ENDIF |
| 72 | +0790 ENDFOR i# |
| 73 | +0800 ENDPROC runsieve |
| 74 | +0810 |
| 75 | +0820 FUNC valid // check sieve's output against value in knownprimes# |
| 76 | +0830 RETURN knownprimes#(checkindex#)=count# |
| 77 | +0840 ENDFUNC valid |
0 commit comments