-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprime_cache.go
More file actions
86 lines (80 loc) · 1.74 KB
/
Copy pathprime_cache.go
File metadata and controls
86 lines (80 loc) · 1.74 KB
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package lfs
import (
"math"
"math/big"
"sync"
)
type primeCache struct {
l []int // list of prime numbers
m sync.Map // map from a prime to the product of primes up to that prime
max int // largest prime in the cache
}
// findPrimeProd returns the product of primes less than logN.
func (p *primeCache) findPrimeProd(logN int) *big.Int {
l, r := 0, len(p.l)-1
for l <= r {
mid := (l + r) / 2
current := p.l[mid]
if mid == len(p.l)-1 {
if bi, ok := p.m.Load(current); ok {
return new(big.Int).Set(bi.(*big.Int))
}
}
next := p.l[mid+1]
if current < logN && next >= logN {
if bi, ok := p.m.Load(current); ok {
return new(big.Int).Set(bi.(*big.Int))
}
}
if current >= logN {
r = mid - 1
} else {
l = mid + 1
}
}
return big.NewInt(2)
}
func newPrimeCache(limit int) *primeCache {
ps := &primeCache{
l: []int{1, 2, 3, 5, 7},
max: 7,
}
ps.m.Store(1, big.NewInt(1))
ps.m.Store(2, big.NewInt(2))
ps.m.Store(3, big.NewInt(6))
ps.m.Store(5, big.NewInt(30))
ps.m.Store(7, big.NewInt(210))
prod := iPool.Get().(*big.Int).SetInt64(210)
defer iPool.Put(prod)
opt := iPool.Get().(*big.Int)
defer iPool.Put(opt)
for idx := 9; idx <= limit; idx += 2 {
ps.checkAddPrime(idx, prod, opt)
}
return ps
}
func (p *primeCache) checkAddPrime(n int, prod, opt *big.Int) {
isPrime := true
sqrtN := int(math.Sqrt(float64(n)))
for _, prime := range p.l[1:] { // skip 1
if prime > sqrtN {
break
}
if n%prime == 0 && n != prime {
isPrime = false
break
}
}
if !isPrime {
return
}
p.l = append(p.l, n)
opt.SetInt64(int64(n))
prod.Mul(prod, opt)
p.m.Store(n, new(big.Int).Set(prod))
p.max = n
}
// ResetCachePrime resets the prime cache.
func ResetCachePrime() {
pCache = newPrimeCache(0)
}