Skip to content

Commit f491b86

Browse files
authored
COMAL solution that runs within Docker (PlummersSoftwareLLC#719)
1 parent 2b23ac1 commit f491b86

File tree

5 files changed

+134
-0
lines changed

5 files changed

+134
-0
lines changed

PrimeCOMAL/solution_2/Dockerfile

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM primeimages/opencomal:0.3.0
2+
3+
RUN apt-get update && apt-get install -y socat && apt-get clean && rm -rf /var/lib/apt/lists/*
4+
5+
WORKDIR /opt/app/
6+
7+
COPY opencomal.txt run.sh build.sh ./
8+
9+
RUN sh build.sh
10+
11+
ENTRYPOINT [ "sh", "run.sh" ]
12+

PrimeCOMAL/solution_2/README.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# COMAL solution by kottm, adapted for OpenCOMAL by rbergen
2+
3+
![Algorithm](https://img.shields.io/badge/Algorithm-base-green)
4+
![Faithfulness](https://img.shields.io/badge/Faithful-no-yellowgreen)
5+
![Parallelism](https://img.shields.io/badge/Parallel-no-green)
6+
![Bit count](https://img.shields.io/badge/Bits-1-green)
7+
8+
This is an adaption of kottm's COMAL solution that targets UniComal. This version has been changed to allow it to be run under [OpenCOMAL](https://github.com/poldy/OpenCOMAL), specifically [version 0.3.0](https://github.com/poldy/OpenCOMAL/releases/tag/v0.3.0). Amongst others, this allows the solution to be run within Docker.
9+
Changes made to the original solution are the following:
10+
- The sieve size is set to the "standard" 1,000,000.
11+
- The calculation of `checkindex#` is done using `LOG10()` instead of `LOG()`. The division involved in the latter triggered an integer rounding error that yielded the wrong index.
12+
- Instead of `TIMER`, the solution uses `SYS(now)` for timekeeping, at the cost of losing timing precision (i.e., duration is now counted in whole seconds). The reason is that OpenCOMAL doesn't include support for `TIMER`.
13+
- Output is being redirected to a file, so it is accessible outside of the OpenCOMAL runtime environment.
14+
- All output (`PRINT` commands) have been removed, except for the final output lines.
15+
16+
While putting the Dockerfile and support scripts together, I found that OpenCOMAL doesn't respond well to the absence of a TTY. The `build.sh` and `run.sh` scripts include some `socat` trickery and input/output redirection to work around this.
17+
18+
## Run instructions
19+
20+
### Docker
21+
A Dockerfile has been provided. It can be used to build and run the solution using the following commands:
22+
```
23+
docker build -t comal-2 .
24+
docker run -ti --rm comal-2
25+
```
26+
27+
## Output
28+
```
29+
Passes: 1, Time: 13, Avg: 13, Count1: 78498, Count2: 78498, Valid: 1
30+
31+
kottm;1;13;1;algorithm=base,faithful=no,bits=1
32+
```

PrimeCOMAL/solution_2/build.sh

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export TERM=xterm
2+
3+
socat - EXEC:'opencomal',pty,setsid,ctty > /dev/null << EOF
4+
ENTER "opencomal.txt"
5+
SAVE "opencomal.cml"
6+
BYE
7+
EOF

PrimeCOMAL/solution_2/opencomal.txt

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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

PrimeCOMAL/solution_2/run.sh

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export TERM=xterm
2+
3+
socat - EXEC:'opencomalrun opencomal.cml',pty,setsid,ctty < /dev/zero > /dev/null
4+
5+
cat output.txt
6+
rm output.txt

0 commit comments

Comments
 (0)