-
Notifications
You must be signed in to change notification settings - Fork 3
/
generator_probablyprime.go
63 lines (55 loc) · 1.33 KB
/
generator_probablyprime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package primebot
import (
"context"
"math/big"
"sync"
)
// NewProbablyPrimeGenerator creates a new ProbablyPrimeGenerator, starting at
// the given number
func NewProbablyPrimeGenerator(start *big.Int) *ProbablyPrimeGenerator {
cur := &big.Int{}
cur.Set(start)
one := big.NewInt(1)
return &ProbablyPrimeGenerator{
cur: cur,
one: one,
mutex: &sync.Mutex{},
}
}
// ProbablyPrimeGenerator is a prime number generator that uses the math/big
// package's ProbablyPrime; it is 100% accurate up to the max value of a uint,
// at which point it overflows; this cannot be used to generate any prime number
// larger than 2**64
type ProbablyPrimeGenerator struct {
cur *big.Int
one *big.Int
mutex *sync.Mutex
}
func (p *ProbablyPrimeGenerator) SetStart(start *big.Int) {
p.mutex.Lock()
defer p.mutex.Unlock()
cur := &big.Int{}
cur.Set(start)
p.cur = cur
}
// Generate generates the next prime number from the ProbablyPrime generator
func (p *ProbablyPrimeGenerator) Generate(ctx context.Context) (*big.Int, error) {
p.mutex.Lock()
defer p.mutex.Unlock()
p.cur.Add(p.cur, p.one)
ret := &big.Int{}
for {
select {
case <-ctx.Done():
return ret, ErrCanceled
default:
if !p.cur.IsUint64() {
return ret, ErrOverflow
}
if p.cur.ProbablyPrime(1) {
return ret.Set(p.cur), nil
}
p.cur.Add(p.cur, p.one)
}
}
}