├── .gitignore ├── LICENSE ├── README.md ├── count.go ├── fill.go ├── go.mod ├── primegen.go ├── primegen_test.go ├── primes └── primes.go ├── primespeed └── primespeed.go └── sieve.go /.gitignore: -------------------------------------------------------------------------------- 1 | _* 2 | 6.out 3 | *.6 4 | primes 5 | primespeed 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 John Barham 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # primegen 2 | 3 | *primegen* is a Go package that generates prime numbers in order using the Sieve 4 | of Atkin instead of the traditional Sieve of Eratosthenes. 5 | 6 | It is a relatively straightforward port of D. J. Bernstein's 7 | [original C implementation](http://cr.yp.to/primegen.html) but makes use of 8 | Go's concurrency features which should make it faster on multi-core CPUs. 9 | 10 | Do `go get github.com/jbarham/primegen` to install the package. 11 | 12 | View the package documentation online at 13 | https://pkg.go.dev/github.com/jbarham/primegen 14 | or on the command line by running `go doc github.com/jbarham/primegen`. 15 | 16 | The repository includes two additional programs that illustrate usage of the 17 | primegen package: 18 | 19 | 1. primes, which writes prime numbers to standard out 20 | 2. primespeed, which prints the time taken to generate the first 50,847,534 21 | prime numbers 22 | 23 | John Barham, [Wombat Software](https://www.wombatsoftware.com/) 24 | -------------------------------------------------------------------------------- /count.go: -------------------------------------------------------------------------------- 1 | package primegen 2 | 3 | var pop = []uint32{ 4 | 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 5 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 6 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 7 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 8 | 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 9 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 10 | 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 11 | 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8} 12 | 13 | // Count returns the number of prime numbers from the generator's current 14 | // position up to x. 15 | func (pg *Primegen) Count(x uint64) uint64 { 16 | var count uint64 = 0 17 | var smallcount, bits uint32 18 | 19 | for { 20 | for pg.num != 0 { 21 | if pg.p[pg.num-1] >= x { 22 | return count 23 | } 24 | count++ 25 | pg.num-- 26 | } 27 | 28 | smallcount = 0 29 | pos := pg.pos 30 | for (pos < _B32) && (pg.base+1920 < x) { 31 | for j := 0; j < 16; j++ { 32 | bits = ^pg.buf[j][pos] 33 | smallcount += pop[bits&255] 34 | bits >>= 8 35 | smallcount += pop[bits&255] 36 | bits >>= 8 37 | smallcount += pop[bits&255] 38 | bits >>= 8 39 | smallcount += pop[bits&255] 40 | } 41 | pg.base += 1920 42 | pos++ 43 | } 44 | pg.pos = pos 45 | count += uint64(smallcount) 46 | 47 | if pos == _B32 { 48 | for pg.base+_B*60 < x { 49 | pg.sieve() 50 | pg._L += _B 51 | 52 | smallcount = 0 53 | for j := 0; j < 16; j++ { 54 | for pos = 0; pos < _B32; pos++ { 55 | bits = ^pg.buf[j][pos] 56 | smallcount += pop[bits&255] 57 | bits >>= 8 58 | smallcount += pop[bits&255] 59 | bits >>= 8 60 | smallcount += pop[bits&255] 61 | bits >>= 8 62 | smallcount += pop[bits&255] 63 | } 64 | } 65 | count += uint64(smallcount) 66 | pg.base += _B * 60 67 | } 68 | } 69 | 70 | pg.fill() 71 | } 72 | return count // Shouldn't get here. 73 | } 74 | -------------------------------------------------------------------------------- /fill.go: -------------------------------------------------------------------------------- 1 | package primegen 2 | 3 | func (pg *Primegen) fill() { 4 | var bits0, bits1, bits2, bits3, bits4, bits5, bits6, bits7 uint32 5 | var bits8, bits9, bits10, bits11, bits12, bits13, bits14, bits15 uint32 6 | 7 | i := pg.pos 8 | if i == _B32 { 9 | pg.sieve() 10 | pg._L += _B 11 | i = 0 12 | } 13 | pg.pos = i + 1 14 | 15 | bits0 = ^pg.buf[0][i] 16 | bits1 = ^pg.buf[1][i] 17 | bits2 = ^pg.buf[2][i] 18 | bits3 = ^pg.buf[3][i] 19 | bits4 = ^pg.buf[4][i] 20 | bits5 = ^pg.buf[5][i] 21 | bits6 = ^pg.buf[6][i] 22 | bits7 = ^pg.buf[7][i] 23 | bits8 = ^pg.buf[8][i] 24 | bits9 = ^pg.buf[9][i] 25 | bits10 = ^pg.buf[10][i] 26 | bits11 = ^pg.buf[11][i] 27 | bits12 = ^pg.buf[12][i] 28 | bits13 = ^pg.buf[13][i] 29 | bits14 = ^pg.buf[14][i] 30 | bits15 = ^pg.buf[15][i] 31 | 32 | base := pg.base + 1920 33 | pg.base = base 34 | 35 | pg.num = 0 36 | 37 | for mask := uint32(0x80000000); mask != 0; mask >>= 1 { 38 | base -= 60 39 | if bits15&mask != 0 { 40 | pg.p[pg.num] = base + 59 41 | pg.num++ 42 | } 43 | if bits14&mask != 0 { 44 | pg.p[pg.num] = base + 53 45 | pg.num++ 46 | } 47 | if bits13&mask != 0 { 48 | pg.p[pg.num] = base + 49 49 | pg.num++ 50 | } 51 | if bits12&mask != 0 { 52 | pg.p[pg.num] = base + 47 53 | pg.num++ 54 | } 55 | if bits11&mask != 0 { 56 | pg.p[pg.num] = base + 43 57 | pg.num++ 58 | } 59 | if bits10&mask != 0 { 60 | pg.p[pg.num] = base + 41 61 | pg.num++ 62 | } 63 | if bits9&mask != 0 { 64 | pg.p[pg.num] = base + 37 65 | pg.num++ 66 | } 67 | if bits8&mask != 0 { 68 | pg.p[pg.num] = base + 31 69 | pg.num++ 70 | } 71 | if bits7&mask != 0 { 72 | pg.p[pg.num] = base + 29 73 | pg.num++ 74 | } 75 | if bits6&mask != 0 { 76 | pg.p[pg.num] = base + 23 77 | pg.num++ 78 | } 79 | if bits5&mask != 0 { 80 | pg.p[pg.num] = base + 19 81 | pg.num++ 82 | } 83 | if bits4&mask != 0 { 84 | pg.p[pg.num] = base + 17 85 | pg.num++ 86 | } 87 | if bits3&mask != 0 { 88 | pg.p[pg.num] = base + 13 89 | pg.num++ 90 | } 91 | if bits2&mask != 0 { 92 | pg.p[pg.num] = base + 11 93 | pg.num++ 94 | } 95 | if bits1&mask != 0 { 96 | pg.p[pg.num] = base + 7 97 | pg.num++ 98 | } 99 | if bits0&mask != 0 { 100 | pg.p[pg.num] = base + 1 101 | pg.num++ 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jbarham/primegen 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /primegen.go: -------------------------------------------------------------------------------- 1 | // The primegen package generates prime numbers in order. It uses the Sieve of 2 | // Atkin instead of the traditional Sieve of Eratosthenes. 3 | // 4 | // The primegen Go package is a port of D. J. Bernstein's original implementation 5 | // in C (http://cr.yp.to/primegen.html). 6 | package primegen 7 | 8 | import ( 9 | "bufio" 10 | "io" 11 | ) 12 | 13 | const ( 14 | _PRIMEGEN_WORDS = 8192 // Assumes 32K L1 data cache 15 | _B32 = _PRIMEGEN_WORDS 16 | _B = _PRIMEGEN_WORDS * 32 17 | ) 18 | 19 | type Primegen struct { 20 | buf [16][]uint32 21 | p [512]uint64 /* p[num-1] ... p[0], in that order */ 22 | num int 23 | pos int /* next entry to use in buf; _PRIMEGEN_WORDS to restart */ 24 | base uint64 25 | _L uint64 26 | } 27 | 28 | // New returns a new primegen.Primegen prime number generator. 29 | func New() *Primegen { 30 | pg := new(Primegen) 31 | for i := 0; i < len(pg.buf); i++ { 32 | pg.buf[i] = make([]uint32, _PRIMEGEN_WORDS) 33 | } 34 | pg.Reset() 35 | return pg 36 | } 37 | 38 | // Reset resets the generator at the first prime number. 39 | func (pg *Primegen) Reset() { 40 | pg._L = 1 41 | pg.base = 60 42 | 43 | pg.pos = _PRIMEGEN_WORDS 44 | 45 | pg.p[0] = 59 46 | pg.p[1] = 53 47 | pg.p[2] = 47 48 | pg.p[3] = 43 49 | pg.p[4] = 41 50 | pg.p[5] = 37 51 | pg.p[6] = 31 52 | pg.p[7] = 29 53 | pg.p[8] = 23 54 | pg.p[9] = 19 55 | pg.p[10] = 17 56 | pg.p[11] = 13 57 | pg.p[12] = 11 58 | pg.p[13] = 7 59 | pg.p[14] = 5 60 | pg.p[15] = 3 61 | pg.p[16] = 2 62 | 63 | pg.num = 17 64 | } 65 | 66 | // Peek returns the next prime number, without advancing the generator. 67 | func (pg *Primegen) Peek() uint64 { 68 | for pg.num == 0 { 69 | pg.fill() 70 | } 71 | 72 | return pg.p[pg.num-1] 73 | } 74 | 75 | // Next returns the next prime number and advances the generator. 76 | func (pg *Primegen) Next() uint64 { 77 | p := pg.Peek() 78 | pg.num-- 79 | return p 80 | } 81 | 82 | // SkipTo advances the generator to generate prime numbers >= x. 83 | func (pg *Primegen) SkipTo(x uint64) { 84 | for { 85 | for pg.num != 0 { 86 | if pg.p[pg.num-1] >= x { 87 | return 88 | } 89 | pg.num-- 90 | } 91 | 92 | pos := pg.pos 93 | for (pos < _B32) && (pg.base+1920 < x) { 94 | pg.base += 1920 95 | pos++ 96 | } 97 | pg.pos = pos 98 | if pos == _B32 { 99 | for pg.base+_B*60 < x { 100 | pg._L += _B 101 | pg.base += _B * 60 102 | } 103 | } 104 | 105 | pg.fill() 106 | } 107 | } 108 | 109 | const ndigits = 32 110 | 111 | // Write efficiently writes the list of prime numbers between low and high, 112 | // separated by newline, to w. 113 | func Write(w io.Writer, low, high uint64) (err error) { 114 | var i int 115 | digits := make([]byte, 32) 116 | digits[ndigits-1] = '\n' 117 | 118 | sieve := New() 119 | sieve.SkipTo(low) 120 | x := sieve.Next() 121 | b := bufio.NewWriter(w) 122 | for x < high { 123 | xx := x 124 | for i = ndigits - 2; i > 0; i-- { 125 | digits[i] = '0' + byte(xx%10) 126 | if xx < 10 { 127 | break 128 | } 129 | xx /= 10 130 | } 131 | if _, err = b.Write(digits[i:]); err != nil { 132 | return err 133 | } 134 | x = sieve.Next() 135 | } 136 | return b.Flush() 137 | } 138 | -------------------------------------------------------------------------------- /primegen_test.go: -------------------------------------------------------------------------------- 1 | package primegen 2 | 3 | import ( 4 | "crypto/md5" 5 | "encoding/hex" 6 | "testing" 7 | ) 8 | 9 | type primegenTest struct { 10 | high uint64 11 | checksum string 12 | } 13 | 14 | // Test checksums are listed at http://cr.yp.to/primegen.html 15 | var golden = []primegenTest{ 16 | {1000000, "c13929ee9d2aea8f83aa076236079e94"}, 17 | {10000000, "60e34d268bad671a5f299e1ecc988ff6"}, 18 | {100000000, "4e2b0027288a27e9c99699364877c9db"}, 19 | } 20 | 21 | func TestSieve(t *testing.T) { 22 | h := md5.New() 23 | for _, test := range golden { 24 | h.Reset() 25 | Write(h, 1, test.high) 26 | sum := hex.EncodeToString(h.Sum(nil)) 27 | if sum != test.checksum { 28 | t.Errorf("Invalid checksum for high value %d: Expected %s, got %s\n", test.high, test.checksum, sum) 29 | } 30 | } 31 | } 32 | 33 | func TestCount(t *testing.T) { 34 | sieve := New() 35 | count := sieve.Count(1000000000) 36 | if count != 50847534 { 37 | t.Errorf("Incorrect count %d of primes up to 1000000000, expected 50847534\n", count) 38 | } 39 | } 40 | 41 | func BenchmarkSieve(b *testing.B) { 42 | b.StopTimer() 43 | sieve := New() 44 | b.StartTimer() 45 | for i := 0; i < b.N; i++ { 46 | sieve.Reset() 47 | for j := 0; j < 1000000; j++ { 48 | sieve.Next() 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /primes/primes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strconv" 9 | 10 | "github.com/jbarham/primegen" 11 | ) 12 | 13 | var low, high uint64 = 2, 1000000000 14 | 15 | func usage() { 16 | fmt.Fprintf(os.Stderr, "usage: primes [[low=%d] high=%d]\n", low, high) 17 | os.Exit(2) 18 | } 19 | 20 | func main() { 21 | flag.Usage = usage 22 | flag.Parse() 23 | 24 | args := flag.Args() 25 | var err error 26 | if len(args) == 1 { 27 | high, err = strconv.ParseUint(args[0], 10, 64) 28 | if err != nil { 29 | usage() 30 | } 31 | } else if len(args) == 2 { 32 | low, err = strconv.ParseUint(args[0], 10, 64) 33 | if err != nil { 34 | usage() 35 | } 36 | high, err = strconv.ParseUint(args[1], 10, 64) 37 | if err != nil { 38 | usage() 39 | } 40 | } else if len(args) > 2 { 41 | usage() 42 | } 43 | 44 | err = primegen.Write(os.Stdout, low, high) 45 | if err != nil { 46 | log.Fatalf("Error writing primes: %s\n", err) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /primespeed/primespeed.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/jbarham/primegen" 8 | ) 9 | 10 | func main() { 11 | high := uint64(1000000000) 12 | sieve := primegen.New() 13 | start := time.Now() 14 | count := sieve.Count(high) 15 | end := time.Now() 16 | fmt.Printf("%d primes up to %d\n", count, high) 17 | fmt.Printf("Overall seconds: approximately %.5f\n", float64(end.Sub(start))/1e9) 18 | } 19 | -------------------------------------------------------------------------------- /sieve.go: -------------------------------------------------------------------------------- 1 | package primegen 2 | 3 | import ( 4 | "runtime" 5 | "sync" 6 | ) 7 | 8 | var two = [32]uint32{ 9 | 0x00000001, 0x00000002, 0x00000004, 0x00000008, 10 | 0x00000010, 0x00000020, 0x00000040, 0x00000080, 11 | 0x00000100, 0x00000200, 0x00000400, 0x00000800, 12 | 0x00001000, 0x00002000, 0x00004000, 0x00008000, 13 | 0x00010000, 0x00020000, 0x00040000, 0x00080000, 14 | 0x00100000, 0x00200000, 0x00400000, 0x00800000, 15 | 0x01000000, 0x02000000, 0x04000000, 0x08000000, 16 | 0x10000000, 0x20000000, 0x40000000, 0x80000000, 17 | } 18 | 19 | func doit4(a []uint32, x, y int, start int64) { 20 | var i, i0, y0 int 21 | 22 | x += x 23 | x += 15 24 | y += 15 25 | 26 | start += 1000000000 27 | for start < 0 { 28 | start += int64(x) 29 | x += 30 30 | } 31 | start -= 1000000000 32 | i = int(start) 33 | 34 | for i < _B { 35 | i += x 36 | x += 30 37 | } 38 | 39 | for { 40 | x -= 30 41 | if x <= 15 { 42 | return 43 | } 44 | i -= x 45 | 46 | for i < 0 { 47 | i += y 48 | y += 30 49 | } 50 | 51 | i0 = i 52 | y0 = y 53 | for i < _B { 54 | pos := uint32(i) >> 5 55 | data := uint32(i) & 31 56 | i += y 57 | y += 30 58 | bits := a[pos] 59 | data = two[data] 60 | bits ^= data 61 | a[pos] = bits 62 | } 63 | i = i0 64 | y = y0 65 | } 66 | } 67 | 68 | func doit6(a []uint32, x, y int, start int64) { 69 | var i, i0, y0 int 70 | 71 | x += 5 72 | y += 15 73 | 74 | start += 1000000000 75 | for start < 0 { 76 | start += int64(x) 77 | x += 10 78 | } 79 | start -= 1000000000 80 | i = int(start) 81 | for i < _B { 82 | i += x 83 | x += 10 84 | } 85 | 86 | for { 87 | x -= 10 88 | if x <= 5 { 89 | return 90 | } 91 | i -= x 92 | 93 | for i < 0 { 94 | i += y 95 | y += 30 96 | } 97 | 98 | i0 = i 99 | y0 = y 100 | for i < _B { 101 | pos := uint32(i) >> 5 102 | data := uint32(i) & 31 103 | i += y 104 | y += 30 105 | bits := a[pos] 106 | data = two[data] 107 | bits ^= data 108 | a[pos] = bits 109 | } 110 | i = i0 111 | y = y0 112 | } 113 | } 114 | 115 | func doit12(a []uint32, x, y int, start int64) { 116 | var i, i0, y0 int 117 | 118 | x += 5 119 | 120 | start += 1000000000 121 | for start < 0 { 122 | start += int64(x) 123 | x += 10 124 | } 125 | start -= 1000000000 126 | i = int(start) 127 | for i < 0 { 128 | i += x 129 | x += 10 130 | } 131 | 132 | y += 15 133 | x += 10 134 | 135 | for { 136 | for i >= _B { 137 | if x <= y { 138 | return 139 | } 140 | i -= y 141 | y += 30 142 | } 143 | i0 = i 144 | y0 = y 145 | for (i >= 0) && (y < x) { 146 | pos := uint32(i) >> 5 147 | data := uint32(i) & 31 148 | i -= y 149 | y += 30 150 | bits := a[pos] 151 | data = two[data] 152 | bits ^= data 153 | a[pos] = bits 154 | } 155 | i = i0 156 | y = y0 157 | i += x - 10 158 | x += 10 159 | } 160 | } 161 | 162 | var deltainverse = [60]int{ 163 | -1, _B32 * 0, -1, -1, -1, -1, -1, _B32 * 1, -1, -1, -1, _B32 * 2, -1, _B32 * 3, -1, 164 | -1, -1, _B32 * 4, -1, _B32 * 5, -1, -1, -1, _B32 * 6, -1, -1, -1, -1, -1, _B32 * 7, 165 | -1, _B32 * 8, -1, -1, -1, -1, -1, _B32 * 9, -1, -1, -1, _B32 * 10, -1, _B32 * 11, -1, 166 | -1, -1, _B32 * 12, -1, _B32 * 13, -1, -1, -1, _B32 * 14, -1, -1, -1, -1, -1, _B32 * 15, 167 | } 168 | 169 | func squarefree1big(buf [16][]uint32, base uint64, q uint32, qq uint64) { 170 | var i uint64 171 | bound := base + 60*_B 172 | 173 | for qq < bound { 174 | if bound < 2000000000 { 175 | i = qq - uint64(uint32(base)%uint32(qq)) 176 | } else { 177 | i = qq - (base % qq) 178 | } 179 | if (i & 1) == 0 { 180 | i += qq 181 | } 182 | 183 | if i < _B*60 { 184 | pos := uint32(i) 185 | n := deltainverse[pos%60] 186 | if n >= 0 { 187 | pos /= 60 188 | idx := n + int(pos>>5) 189 | buf[idx/_B32][idx%_B32] |= two[pos&31] 190 | } 191 | } 192 | 193 | qq += uint64(q) 194 | q += 1800 195 | } 196 | } 197 | 198 | func squarefree1(buf [16][]uint32, L uint64, q uint32) { 199 | var i uint32 200 | 201 | base := 60 * L 202 | qq := q * q 203 | q = 60*q + 900 204 | 205 | for qq < _B*60 { 206 | if base < 2000000000 { 207 | i = qq - (uint32(base) % qq) 208 | } else { 209 | i = qq - uint32(base%uint64(qq)) 210 | } 211 | if (i & 1) == 0 { 212 | i += qq 213 | } 214 | 215 | if i < _B*60 { 216 | qqhigh := qq / 60 217 | ilow := i % 60 218 | ihigh := i / 60 219 | 220 | qqhigh += qqhigh 221 | for ihigh < _B { 222 | n := deltainverse[ilow] 223 | if n >= 0 { 224 | idx := n + int(ihigh>>5) 225 | buf[idx/_B32][idx%_B32] |= two[ihigh&31] 226 | } 227 | 228 | ilow += 2 229 | ihigh += qqhigh 230 | if ilow >= 60 { 231 | ilow -= 60 232 | ihigh += 1 233 | } 234 | } 235 | } 236 | 237 | qq += q 238 | q += 1800 239 | } 240 | 241 | squarefree1big(buf, base, q, uint64(qq)) 242 | } 243 | 244 | func squarefree49big(buf [16][]uint32, base uint64, q uint32, qq uint64) { 245 | var i uint64 246 | bound := base + 60*_B 247 | 248 | for qq < bound { 249 | if bound < 2000000000 { 250 | i = qq - uint64(uint32(base)%uint32(qq)) 251 | } else { 252 | i = qq - (base % qq) 253 | } 254 | if (i & 1) == 0 { 255 | i += qq 256 | } 257 | 258 | if i < _B*60 { 259 | pos := uint32(i) 260 | n := deltainverse[pos%60] 261 | if n >= 0 { 262 | pos /= 60 263 | idx := n + int(pos>>5) 264 | buf[idx/_B32][idx%_B32] |= two[pos&31] 265 | } 266 | } 267 | 268 | qq += uint64(q) 269 | q += 1800 270 | } 271 | } 272 | 273 | func squarefree49(buf [16][]uint32, L uint64, q uint32) { 274 | var i uint32 275 | 276 | base := 60 * L 277 | qq := q * q 278 | q = 60*q + 900 279 | 280 | for qq < _B*60 { 281 | if base < 2000000000 { 282 | i = qq - (uint32(base) % qq) 283 | } else { 284 | i = qq - uint32(base%uint64(qq)) 285 | } 286 | if (i & 1) == 0 { 287 | i += qq 288 | } 289 | 290 | if i < _B*60 { 291 | qqhigh := qq / 60 292 | ilow := i % 60 293 | ihigh := i / 60 294 | 295 | qqhigh += qqhigh 296 | qqhigh += 1 297 | for ihigh < _B { 298 | n := deltainverse[ilow] 299 | if n >= 0 { 300 | idx := n + int(ihigh>>5) 301 | buf[idx/_B32][idx%_B32] |= two[ihigh&31] 302 | } 303 | 304 | ilow += 38 305 | ihigh += qqhigh 306 | if ilow >= 60 { 307 | ilow -= 60 308 | ihigh += 1 309 | } 310 | } 311 | } 312 | 313 | qq += q 314 | q += 1800 315 | } 316 | 317 | squarefree49big(buf, base, q, uint64(qq)) 318 | } 319 | 320 | /* squares of primes >= 7, < 240 */ 321 | var qqtab = [49]uint32{ 322 | 49, 121, 169, 289, 361, 529, 841, 961, 1369, 1681, 323 | 1849, 2209, 2809, 3481, 3721, 4489, 5041, 5329, 6241, 6889, 324 | 7921, 9409, 10201, 10609, 11449, 11881, 12769, 16129, 17161, 18769, 325 | 19321, 22201, 22801, 24649, 26569, 27889, 29929, 32041, 32761, 36481, 326 | 37249, 38809, 39601, 44521, 49729, 51529, 52441, 54289, 57121, 327 | } 328 | 329 | /* (qq * 11 + 1) / 60 or (qq * 59 + 1) / 60 */ 330 | var qq60tab = [49]uint32{ 331 | 9, 119, 31, 53, 355, 97, 827, 945, 251, 1653, 332 | 339, 405, 515, 3423, 3659, 823, 4957, 977, 6137, 333 | 1263, 7789, 1725, 10031, 1945, 2099, 11683, 2341, 2957, 334 | 16875, 3441, 18999, 21831, 22421, 4519, 4871, 5113, 5487, 335 | 31507, 32215, 35873, 6829, 7115, 38941, 43779, 9117, 9447, 51567, 9953, 56169, 336 | } 337 | 338 | func squarefreetiny(a []uint32, Lmodqq []uint32, d uint32) { 339 | for j := 0; j < 49; j++ { 340 | qq := qqtab[j] 341 | k := qq - 1 - ((Lmodqq[j] + qq60tab[j]*d - 1) % qq) 342 | for k < _B { 343 | pos := k >> 5 344 | data := k & 31 345 | k += qq 346 | bits := a[pos] 347 | data = two[data] 348 | bits |= data 349 | a[pos] = bits 350 | } 351 | } 352 | } 353 | 354 | type todo struct { 355 | index, f, g, k int 356 | } 357 | 358 | var for4 = []todo{ 359 | {0, 2, 15, 4}, {0, 3, 5, 1}, {0, 3, 25, 11}, {0, 5, 9, 3}, 360 | {0, 5, 21, 9}, {0, 7, 15, 7}, {0, 8, 15, 8}, {0, 10, 9, 8}, 361 | {0, 10, 21, 14}, {0, 12, 5, 10}, {0, 12, 25, 20}, {0, 13, 15, 15}, 362 | {0, 15, 1, 15}, {0, 15, 11, 17}, {0, 15, 19, 21}, {0, 15, 29, 29}, 363 | {3, 1, 3, 0}, {3, 1, 27, 12}, {3, 4, 3, 1}, {3, 4, 27, 13}, 364 | {3, 6, 7, 3}, {3, 6, 13, 5}, {3, 6, 17, 7}, {3, 6, 23, 11}, 365 | {3, 9, 7, 6}, {3, 9, 13, 8}, {3, 9, 17, 10}, {3, 9, 23, 14}, 366 | {3, 11, 3, 8}, {3, 11, 27, 20}, {3, 14, 3, 13}, {3, 14, 27, 25}, 367 | {4, 2, 1, 0}, {4, 2, 11, 2}, {4, 2, 19, 6}, {4, 2, 29, 14}, 368 | {4, 7, 1, 3}, {4, 7, 11, 5}, {4, 7, 19, 9}, {4, 7, 29, 17}, 369 | {4, 8, 1, 4}, {4, 8, 11, 6}, {4, 8, 19, 10}, {4, 8, 29, 18}, 370 | {4, 13, 1, 11}, {4, 13, 11, 13}, {4, 13, 19, 17}, {4, 13, 29, 25}, 371 | {7, 1, 5, 0}, {7, 1, 25, 10}, {7, 4, 5, 1}, {7, 4, 25, 11}, 372 | {7, 5, 7, 2}, {7, 5, 13, 4}, {7, 5, 17, 6}, {7, 5, 23, 10}, 373 | {7, 10, 7, 7}, {7, 10, 13, 9}, {7, 10, 17, 11}, {7, 10, 23, 15}, 374 | {7, 11, 5, 8}, {7, 11, 25, 18}, {7, 14, 5, 13}, {7, 14, 25, 23}, 375 | {9, 2, 9, 1}, {9, 2, 21, 7}, {9, 3, 1, 0}, {9, 3, 11, 2}, 376 | {9, 3, 19, 6}, {9, 3, 29, 14}, {9, 7, 9, 4}, {9, 7, 21, 10}, 377 | {9, 8, 9, 5}, {9, 8, 21, 11}, {9, 12, 1, 9}, {9, 12, 11, 11}, 378 | {9, 12, 19, 15}, {9, 12, 29, 23}, {9, 13, 9, 12}, {9, 13, 21, 18}, 379 | {10, 2, 5, 0}, {10, 2, 25, 10}, {10, 5, 1, 1}, {10, 5, 11, 3}, 380 | {10, 5, 19, 7}, {10, 5, 29, 15}, {10, 7, 5, 3}, {10, 7, 25, 13}, 381 | {10, 8, 5, 4}, {10, 8, 25, 14}, {10, 10, 1, 6}, {10, 10, 11, 8}, 382 | {10, 10, 19, 12}, {10, 10, 29, 20}, {10, 13, 5, 11}, {10, 13, 25, 21}, 383 | {13, 1, 15, 3}, {13, 4, 15, 4}, {13, 5, 3, 1}, {13, 5, 27, 13}, 384 | {13, 6, 5, 2}, {13, 6, 25, 12}, {13, 9, 5, 5}, {13, 9, 25, 15}, 385 | {13, 10, 3, 6}, {13, 10, 27, 18}, {13, 11, 15, 11}, {13, 14, 15, 16}, 386 | {13, 15, 7, 15}, {13, 15, 13, 17}, {13, 15, 17, 19}, {13, 15, 23, 23}, 387 | {14, 1, 7, 0}, {14, 1, 13, 2}, {14, 1, 17, 4}, {14, 1, 23, 8}, 388 | {14, 4, 7, 1}, {14, 4, 13, 3}, {14, 4, 17, 5}, {14, 4, 23, 9}, 389 | {14, 11, 7, 8}, {14, 11, 13, 10}, {14, 11, 17, 12}, {14, 11, 23, 16}, 390 | {14, 14, 7, 13}, {14, 14, 13, 15}, {14, 14, 17, 17}, {14, 14, 23, 21}, 391 | } 392 | 393 | var for6 = []todo{ 394 | {1, 1, 2, 0}, {1, 1, 8, 1}, {1, 1, 22, 8}, {1, 1, 28, 13}, 395 | {1, 3, 10, 2}, {1, 3, 20, 7}, {1, 7, 10, 4}, {1, 7, 20, 9}, 396 | {1, 9, 2, 4}, {1, 9, 8, 5}, {1, 9, 22, 12}, {1, 9, 28, 17}, 397 | {5, 1, 4, 0}, {5, 1, 14, 3}, {5, 1, 16, 4}, {5, 1, 26, 11}, 398 | {5, 5, 2, 1}, {5, 5, 8, 2}, {5, 5, 22, 9}, {5, 5, 28, 14}, 399 | {5, 9, 4, 4}, {5, 9, 14, 7}, {5, 9, 16, 8}, {5, 9, 26, 15}, 400 | {8, 3, 2, 0}, {8, 3, 8, 1}, {8, 3, 22, 8}, {8, 3, 28, 13}, 401 | {8, 5, 4, 1}, {8, 5, 14, 4}, {8, 5, 16, 5}, {8, 5, 26, 12}, 402 | {8, 7, 2, 2}, {8, 7, 8, 3}, {8, 7, 22, 10}, {8, 7, 28, 15}, 403 | {11, 1, 10, 1}, {11, 1, 20, 6}, {11, 3, 4, 0}, {11, 3, 14, 3}, 404 | {11, 3, 16, 4}, {11, 3, 26, 11}, {11, 7, 4, 2}, {11, 7, 14, 5}, 405 | {11, 7, 16, 6}, {11, 7, 26, 13}, {11, 9, 10, 5}, {11, 9, 20, 10}, 406 | } 407 | 408 | var for12 = []todo{ 409 | {2, 2, 1, 0}, {2, 2, 11, -2}, {2, 2, 19, -6}, {2, 2, 29, -14}, 410 | {2, 3, 4, 0}, {2, 3, 14, -3}, {2, 3, 16, -4}, {2, 3, 26, -11}, 411 | {2, 5, 2, 1}, {2, 5, 8, 0}, {2, 5, 22, -7}, {2, 5, 28, -12}, 412 | {2, 7, 4, 2}, {2, 7, 14, -1}, {2, 7, 16, -2}, {2, 7, 26, -9}, 413 | {2, 8, 1, 3}, {2, 8, 11, 1}, {2, 8, 19, -3}, {2, 8, 29, -11}, 414 | {2, 10, 7, 4}, {2, 10, 13, 2}, {2, 10, 17, 0}, {2, 10, 23, -4}, 415 | {6, 1, 10, -2}, {6, 1, 20, -7}, {6, 2, 7, -1}, {6, 2, 13, -3}, 416 | {6, 2, 17, -5}, {6, 2, 23, -9}, {6, 3, 2, 0}, {6, 3, 8, -1}, 417 | {6, 3, 22, -8}, {6, 3, 28, -13}, {6, 4, 5, 0}, {6, 4, 25, -10}, 418 | {6, 6, 5, 1}, {6, 6, 25, -9}, {6, 7, 2, 2}, {6, 7, 8, 1}, 419 | {6, 7, 22, -6}, {6, 7, 28, -11}, {6, 8, 7, 2}, {6, 8, 13, 0}, 420 | {6, 8, 17, -2}, {6, 8, 23, -6}, {6, 9, 10, 2}, {6, 9, 20, -3}, 421 | {12, 1, 4, -1}, {12, 1, 14, -4}, {12, 1, 16, -5}, {12, 1, 26, -12}, 422 | {12, 2, 5, -1}, {12, 2, 25, -11}, {12, 3, 10, -2}, {12, 3, 20, -7}, 423 | {12, 4, 1, 0}, {12, 4, 11, -2}, {12, 4, 19, -6}, {12, 4, 29, -14}, 424 | {12, 6, 1, 1}, {12, 6, 11, -1}, {12, 6, 19, -5}, {12, 6, 29, -13}, 425 | {12, 7, 10, 0}, {12, 7, 20, -5}, {12, 8, 5, 2}, {12, 8, 25, -8}, 426 | {12, 9, 4, 3}, {12, 9, 14, 0}, {12, 9, 16, -1}, {12, 9, 26, -8}, 427 | {15, 1, 2, -1}, {15, 1, 8, -2}, {15, 1, 22, -9}, {15, 1, 28, -14}, 428 | {15, 4, 7, -1}, {15, 4, 13, -3}, {15, 4, 17, -5}, {15, 4, 23, -9}, 429 | {15, 5, 4, 0}, {15, 5, 14, -3}, {15, 5, 16, -4}, {15, 5, 26, -11}, 430 | {15, 6, 7, 0}, {15, 6, 13, -2}, {15, 6, 17, -4}, {15, 6, 23, -8}, 431 | {15, 9, 2, 3}, {15, 9, 8, 2}, {15, 9, 22, -5}, {15, 9, 28, -10}, 432 | {15, 10, 1, 4}, {15, 10, 11, 2}, {15, 10, 19, -2}, {15, 10, 29, -10}, 433 | } 434 | 435 | type doitParams struct { 436 | bufIdx int 437 | f func([]uint32, int, int, int64) 438 | start, end int 439 | ffor []todo 440 | q uint32 441 | } 442 | 443 | var sieveParams = []doitParams{ 444 | {0, doit4, 0, 16, for4, 1}, 445 | {3, doit4, 16, 32, for4, 13}, 446 | {4, doit4, 32, 48, for4, 17}, 447 | {7, doit4, 48, 64, for4, 29}, 448 | {9, doit4, 64, 80, for4, 37}, 449 | {10, doit4, 80, 96, for4, 41}, 450 | {13, doit4, 96, 112, for4, 49}, 451 | {14, doit4, 112, 128, for4, 53}, 452 | 453 | {1, doit6, 0, 12, for6, 7}, 454 | {5, doit6, 12, 24, for6, 19}, 455 | {8, doit6, 24, 36, for6, 31}, 456 | {11, doit6, 36, 48, for6, 43}, 457 | 458 | {2, doit12, 0, 24, for12, 11}, 459 | {6, doit12, 24, 48, for12, 23}, 460 | {12, doit12, 48, 72, for12, 47}, 461 | {15, doit12, 72, 96, for12, 59}, 462 | } 463 | 464 | func doit(pg *Primegen, Lmodqq []uint32, paramsIdx chan int, wg *sync.WaitGroup) { 465 | for idx := range paramsIdx { 466 | if idx == -1 { 467 | break 468 | } 469 | p := sieveParams[idx] 470 | buf := pg.buf[p.bufIdx] 471 | for i := p.start; i < p.end; i++ { 472 | p.f(buf, p.ffor[i].f, p.ffor[i].g, int64(uint64(p.ffor[i].k)-pg._L)) 473 | } 474 | squarefreetiny(buf, Lmodqq, p.q) 475 | } 476 | wg.Done() 477 | } 478 | 479 | func (pg *Primegen) sieve() { 480 | var i, j int 481 | Lmodqq := make([]uint32, 49) 482 | 483 | buf := pg.buf 484 | L := pg._L 485 | 486 | if L > 2000000000 { 487 | for i = 0; i < 49; i++ { 488 | Lmodqq[i] = uint32(L % uint64(qqtab[i])) 489 | } 490 | 491 | } else { 492 | for i = 0; i < 49; i++ { 493 | Lmodqq[i] = uint32(L % uint64(qqtab[i])) 494 | } 495 | } 496 | 497 | for j = 0; j < 16; j++ { 498 | for i = 0; i < _B32; i++ { 499 | buf[j][i] = uint32(0xffffffff) 500 | } 501 | } 502 | 503 | // Create GOMAXPROCS doit threads. 504 | maxprocs := runtime.GOMAXPROCS(-1) 505 | cp := make(chan int) 506 | var wg sync.WaitGroup 507 | wg.Add(maxprocs) 508 | for i = 0; i < maxprocs; i++ { 509 | go doit(pg, Lmodqq, cp, &wg) 510 | } 511 | 512 | // Send params index to threads. 513 | for i := 0; i < len(sieveParams); i++ { 514 | cp <- i 515 | } 516 | // Notify threads that there's no more work. 517 | for i = 0; i < maxprocs; i++ { 518 | cp <- -1 519 | } 520 | wg.Wait() 521 | 522 | squarefree49(buf, L, 247) 523 | squarefree49(buf, L, 253) 524 | squarefree49(buf, L, 257) 525 | squarefree49(buf, L, 263) 526 | squarefree1(buf, L, 241) 527 | squarefree1(buf, L, 251) 528 | squarefree1(buf, L, 259) 529 | squarefree1(buf, L, 269) 530 | } 531 | --------------------------------------------------------------------------------