diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f844ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +primes +primes.txt +*.tar.gz \ No newline at end of file diff --git a/primes.go b/primes.go new file mode 100644 index 0000000..53e0d6e --- /dev/null +++ b/primes.go @@ -0,0 +1,68 @@ +package main + +import ( + "fmt" + "os" + "bufio" + "strconv" + "runtime" +) + +var ch chan uint64 + +func check(e error) { + if e != nil { + panic(e) + } +} + +func main() { + ch = make(chan uint64) + numThreads := runtime.NumCPU() + fmt.Printf("Starting to calculate primes\n") + f, err := os.OpenFile("primes.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + check(err) + defer f.Close() + w := bufio.NewWriter(f) + defer w.Flush() + start := uint64(1) + if len(os.Args) >= 2 { + start, err = strconv.ParseUint(os.Args[1], 10, 64) + check(err) + } + if start % 2 == 0 { + start += 1 + } + for i := 0; i < numThreads; i++ { + go getPrimes(start + uint64(i * 2), uint64(numThreads * 2)) + } + for { + prime := <- ch + fmt.Printf("%d\n", prime) + w.WriteString(strconv.FormatUint(prime, 10) + "\n") + } +} + +// coroutine that calculates primes and adds it to the channel +func getPrimes(start, incr uint64) { + num := uint64(start) + for { + isPrime := true + if (num < 3 || num % 2 == 0) { + isPrime = false + num += incr + continue + } + var i uint64 + for i = 3; i < num/2; i+=2 { + if num % i == 0 { + isPrime = false + break + } + } + if isPrime { + ch <- num + } + num += incr + } +} \ No newline at end of file