I've been playing with Nim for about 4 weeks now. I've copied/run some small
programs (Rosetta Stone), and translated some small Ruby snippets that
compiled. Now I'm trying to do a direct translation of a bigger C++ program of
about 200 loc with about 5 separate functions.
Here's an example of a snippet of code that won't compile.
When I write this routine with the following indention (starting from first
column)
proc segsieve(Kn: uint):
# for Kn resgroups in segment
for b in 0 .. <Kn: # for every byte in the segment
seg[b] = 0 # set every byte bit to prime (0)
for r in 0 .. <rescnt: # for each ith (of 8) residues for P5
let biti = uint8(1 shl r) # set the ith residue track bit mask
let row = r*pcnt # set address to ith row in next[]
for j in 0 .. <pcnt: # for each prime <= sqrt(N) for
restrack
if next[row+j] < uint(Kn): # if 1st mult resgroup index <= seg
size
var k: int = int(next[row+j]) # get its resgroup value
let prime = primes[j] # get the prime
while k < Kn: # for each primenth byte < segment
size
seg[k] = seg[k] or biti # set ith residue in byte as nonprime
next[row+j] = uint(k - Kn) # 1st resgroup in next eligible
segment
k += prime
else: next[row+j] -= uint(Kn) # if 1st mult resgroup index > seg
size
# count the primes in the segment
for byt in seg: # for the Kn resgroup bytes
primecnt += uint(pbits[int(byt)]) # count the '0' bits as primes
I get the following compiler message, which points to the start of the first
**for** statement:
ssozp5segsieve.nim(56, 3) Error: expression expected, but found 'keyword
for'
But when I get rid of the **proc** statement, and write it like below, starting
from first column, it compiles and run.
#proc segsieve(Kn: uint):
# for Kn resgroups in segment
for b in 0 .. <Kn: # for every byte in the segment
seg[b] = 0 # set every byte bit to prime (0)
for r in 0 .. <rescnt: # for each ith (of 8) residues for P5
let biti = uint8(1 shl r) # set the ith residue track bit mask
let row = r*pcnt # set address to ith row in next[]
for j in 0 .. <pcnt: # for each prime <= sqrt(N) for restrack
if next[row+j] < uint(Kn): # if 1st mult resgroup index <= seg size
var k: int = int(next[row+j]) # get its resgroup value
let prime = primes[j] # get the prime
while k < Kn: # for each primenth byte < segment size
seg[k] = seg[k] or biti # set ith residue in byte as nonprime
next[row+j] = uint(k - Kn) # 1st resgroup in next eligible segment
k += prime
else: next[row+j] -= uint(Kn) # if 1st mult resgroup index > seg size
# count the primes in the segment
for byt in seg: # for the Kn resgroup bytes
primecnt += uint(pbits[int(byt)]) # count the '0' bits as primes
This happens with alll the **procs** in the code. What am I doing wrong? Here's
the whole code (88 tloc) that runs when no indentation is used.
let pbits = [
8,7,7,6,7,6,6,5,7,6,6,5,6,5,5,4,7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3
,7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2
,7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2
,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1
,7,6,6,5,6,5,5,4,6,5,5,4,5,4,4,3,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2
,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1
,6,5,5,4,5,4,4,3,5,4,4,3,4,3,3,2,5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1
,5,4,4,3,4,3,3,2,4,3,3,2,3,2,2,1,4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0
]
let residues = [1, 7, 11, 13, 17, 19, 23, 29, 31]
# Global parameters
const
modp5 = 30 # prime generator mod value
rescnt = 8 # number of residues for prime generator
let
#B = 262144
B = 354
Kn = B
Ki = 0
pcnt = 24 # number of primes from r1..sqrt(N)
var
primecnt = 3'u64 # number of primes <= N
#next: seq[uint64 | uint] # array of primes first multiples
#primes: seq[uint] # array of primes <= sqrt(N)
#seg: seq[uint8] # seg[B] segment byte array
seg = newSeq[uint8](B)
var next = newSeq[uint](rescnt*pcnt)
let primes = [7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
67, 71, 73, 79, 83, 89, 97, 101, 103]
#proc next_init():
var pos = newSeq[int](modp5)
for i in 0 .. <rescnt: pos[residues[i]] = i-1
pos[1] = rescnt-1
# for each prime store resgroup on each restrack for prime*(modk+ri)
for j in 0 .. <pcnt: # for the pcnt primes r1..sqrt(N)
let prime: uint = uint(primes[j]) # for each prime
let k: uint = (prime-2) div uint(modp5) # find the resgroup it's in
let r: uint = (prime-2) mod uint(modp5) + 2 # its base residue value
for ri in residues[1 .. rescnt]: # for each residue value
let prod: int = int(r) * ri # create residues
cross-product r*ri
let row: int = pos[prod mod modp5] * pcnt # create residue track
address
next[row + j] = k*(prime + uint(ri)) + uint(prod-2) div uint(modp5) #
resgroup for prime*(modk+ri))
#proc segsieve(Kn: uint):
# for Kn resgroups in segment
for b in 0 .. <Kn: # for every byte in the segment
seg[b] = 0 # set every byte bit to prime (0)
for r in 0 .. <rescnt: # for each ith (of 8) residues for P5
let biti = uint8(1 shl r) # set the ith residue track bit mask
let row = r*pcnt # set address to ith row in next[]
for j in 0 .. <pcnt: # for each prime <= sqrt(N) for restrack
if next[row+j] < uint(Kn): # if 1st mult resgroup index <= seg size
var k: int = int(next[row+j]) # get its resgroup value
let prime = primes[j] # get the prime
while k < Kn: # for each primenth byte < segment size
seg[k] = seg[k] or biti # set ith residue in byte as nonprime
next[row+j] = uint(k - Kn) # 1st resgroup in next eligible segment
k += prime
else: next[row+j] -= uint(Kn) # if 1st mult resgroup index > seg size
# count the primes in the segment
for byt in seg: # for the Kn resgroup bytes
primecnt += uint(pbits[int(byt)]) # count the '0' bits as primes
#proc printprms(Kn: unit, Ki: uint64):
# Extract and print the primes in each segment:
# recommend piping output to less: ./ssozpxxx | less
# can then use Home, End, Pgup, Pgdn keys to see primes
for k in 0 .. <Kn: # for Kn residues groups|bytes
for r in 0 .. <8: # for each residue|bit in a byte
if (int(seg[k]) and (1 shl r)) == 0: # if it's '0' it's a prime
write(stdout, " ", modp5*(Ki+k) + residues[r+1])
echo "\n"
#segsieve(Kn)
echo(primecnt)
echo(seg[0..353])
I'm using Nim 0.17 with Manjaro (KDE5) in VirtualBox with gcc 7.1.1 and clang
4.0.1 (same results using gcc or clang) with the following compiler directive.
[jzakiya@jabari-pc nim]$ nim c --cc:clang --d:release ssozp5segsieve.nim
Hint: used config file '/etc/nim.cfg' [Conf]
Hint: system [Processing]
Hint: ssozp5segsieve [Processing]
ssozp5segsieve.nim(56, 3) Error: expression expected, but found 'keyword
for'