Skip to content

Commit

Permalink
Merge pull request #198 from beef331/drag-race
Browse files Browse the repository at this point in the history
Added Nim solution #2
  • Loading branch information
marghidanu authored May 25, 2021
2 parents 5b32725 + 9728b48 commit f40e34d
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions PrimeNim/solution_2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
primes
7 changes: 7 additions & 0 deletions PrimeNim/solution_2/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM nimlang/nim:alpine

WORKDIR /opt/app
COPY primes.nim .
RUN nim c -d:danger --passC:"-march=native" -d:lto primes.nim

ENTRYPOINT [ "/opt/app/primes" ]
31 changes: 31 additions & 0 deletions PrimeNim/solution_2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Nim implementation #2

![Category](https://img.shields.io/badge/Category-faithful-green)

## Run

### Run locally

Nim is available via package manager under the popular systems. The following command should get you started:

```
nim c -d:danger --passC:"-march=native" -d:lto -r primes.nim
```

### Docker

As per usual minimal just a minimal set of commands:

```
docker build -t primes .
docker run --rm primes
```

## Benchmarks
Gains around 10% performance from `solution_1` with just `-d:release`. With added flags around 50% faster.

## Output
```
beef331;5398;5.00043797492981;1
```

99 changes: 99 additions & 0 deletions PrimeNim/solution_2/primes.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import std/[times, math, strformat, tables, bitops]

const DICT = {
10'u64: 4,
100'u64: 25,
1000'u64: 168,
10000'u64: 1229,
100000'u64: 9592,
1000000'u64: 78498,
10000000'u64: 664579,
100000000'u64: 5761455,
1000000000'u64: 50847534,
10000000000'u64: 455052511,
}.toTable()

type
BitList = seq[uint8]
PrimeSieve = ref object of RootObj
sieveSize: uint64
bits: BitList

proc `{}`(a: BitList, i: SomeInteger): bool {.inline.} =
let
byteIndex = i div 8
bitInd = i mod 8
a[byteIndex].testBit(bitInd)

proc `{}=`(a: var BitList, i: SomeInteger, val: bool) {.inline.}=
let
byteIndex = i div 8
bitInd = i mod 8
if val:
a[byteIndex].setBit(bitInd)
else:
a[byteIndex].clearBit(bitInd)

method runSieve(this: PrimeSieve) {.base.} =
var factor = 3'u64
let q = uint64(math.sqrt(float64(this.sieveSize)))

while factor <= q:
for num in countup(factor, this.sieveSize, 2'u64):
if not this.bits{num}:
factor = num
break

var num2 = factor * factor
while num2 < this.sieveSize:
this.bits{num2} = true
num2 += (factor * 2'u64)

factor += 2'u64

method countPrimes(this: PrimeSieve): uint64 {.base.} =
var count = 1'u64

for num in countup(3'u64, this.sieveSize, 2'u64):
if not this.bits{num}:
count += 1'u64

return count

method printResults(this: PrimeSieve, showResults: bool, duration: float64, passes: int) {.base.} =
if showResults:
stdout.write("2, ")

var count = 1'u64
for num in countup(3'u64, this.sieveSize, 2'u64):
if not this.bits{num}:
if showResults:
stdout.write(&"{num}")
count += 1'u64

if showResults:
echo ""

let
countPrimes = this.countPrimes()
isValid = (countPrimes == uint64(DICT[this.sieveSize]))

stderr.writeLine(&"Passes: {passes}, Time: {duration}, Avg: {(duration / float64(passes))}, Limit: {this.sieveSize}, Count1: {count}, Count2: {countPrimes}, Valid: {isValid}")
echo &"beef331;{passes};{duration};1"

proc newPrimeSieve(sieveSize: uint64): PrimeSieve =
PrimeSieve(sieveSize: sieveSize, bits: newSeq[uint8](sieveSize div 8))

# --- Main block
var passes = 0
let startTime = times.epochTime()

while true:
var sieve = newPrimeSieve(1000000'u64)
sieve.runSieve()

passes += 1
var duration = times.epochTime() - startTime
if duration >= 5:
sieve.printResults(false, duration, passes)
break

0 comments on commit f40e34d

Please sign in to comment.