# append the current number to the prime list proc.append # initial state # [prime, i, n, primes..] # [prime, prime, i, n, primes..] dup # [i, prime, prime, i, n, primes..] dup.2 # [prime, i, n, primes..] mem_store # [i++, n, primes..] swap.2 swap add.1 end # push a boolean on whether or not the program should continue proc.should_continue # initial state # [i, n, primes..] # [i, n, i, n, primes..] dup.1 dup.1 # [should_continue, i, n, primes..] neq end # define if check should continue # will return two flags: one if the loop should continue, the other if candidate is prime proc.is_not_prime_should_continue # initial state # [j, candidate, i, n, primes..] # load the current prime # [prime, j, candidate, i, n, primes..] dup mem_load # push return flags # [continue loop?, is prime?, prime, j, candidate, i, n, primes..] push.0.1 # a composite number have its smallest prime squared lesser than itself. # if the squared prime is bigger than the candidate, and provided we iterate # a list of ordered primes, then the number is a prime. # # this will also protect the algorithm from overflowing the list of current list of primes # because the squared prime will always halt the iteration before the end of the list is # reached # # [squared prime, continue loop?, is prime?, prime, j, candidate, i, n, primes..] dup.2 dup mul # [candidate, squared prime, continue loop?, is prime?, prime, j, candidate, i, n, primes..] dup.5 # [continue loop?, is prime?, prime, j, candidate, i, n, primes..] gt if.true drop drop push.1.0 end # check mod only if should continue loop dup if.true # [remainder, continue loop?, is prime?, prime, j, candidate, i, n, primes..] dup.4 dup.3 u32assert2 u32mod # if remainder is zero, then the number is divisible by prime; hence isn't prime # [continue loop?, is prime?, prime, j, candidate, i, n, primes..] eq.0 if.true drop drop push.0.0 end end # [continue loop?, is prime?, j, candidate, i, n, primes..] swap.2 drop swap end # check if current candidate isn't a prime proc.is_not_prime # initial state # [candidate, i, n, primes..] # create a counter `j` to iterate over primes # [j, candidate, i, n, primes..] push.0 exec.is_not_prime_should_continue while.true # [j, candidate, i, n, primes..] drop add.1 # [is prime?, j, candidate, i, n, primes..] exec.is_not_prime_should_continue end # [is not prime?, candidate, i, n, primes..] swap drop eq.0 end # calculate and push next prime to the stack proc.next # initial state # [i, n, primes..] # create a candidate # [candidate, i, n, primes..] dup.2 add.2 exec.is_not_prime while.true # [candidate, i, n, primes..] add.2 exec.is_not_prime end # [i, n, primes..] exec.append end # the stack is expected to contain on its top the desired primes count. this can be achieved via the # *.inputs file. # # the end of the program will return a stack containing all the primes, up to the nth argument. # # example: # # input: # [50, ..] # # output: # [229, 227, 223, 211, 199, 197, 193, 191, 181, 179, 173, 167, 163, 157, 151, 149] begin # create a counter `i` push.0 # 2 and 3 are the unique sequential primes. by pushing these manually, we can iterate # the candidates in chunks of 2 # append first known prime push.2 exec.append # append second known prime push.3 exec.append # find next primes until limit is reached exec.should_continue while.true exec.next exec.should_continue end # drop the counters drop drop end