Skip to content

Commit a7a5a88

Browse files
authored
Merge pull request #203 from corywalker/corywalker
Implement the Prime[] function.
2 parents 190864c + 1224895 commit a7a5a88

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

expreduce/builtin_numbertheory.go

+31-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package expreduce
22

33
import (
4+
"math"
45
"math/big"
56

67
"github.com/corywalker/expreduce/expreduce/atoms"
@@ -164,30 +165,43 @@ func getNumberTheoryDefinitions() (defs []Definition) {
164165
&SameTest{"3", "PrimePi[6.9]"},
165166
},
166167
})
167-
/*defs = append(defs, Definition{
168-
Name: "Prime",
169-
Usage: "`Prime[n]` returns the `n`th prime number.",
168+
defs = append(defs, Definition{
169+
Name: "Prime",
170+
Usage: "`Prime[n]` returns the `n`th prime number.",
170171
Attributes: []string{"Listable"},
171-
legacyEvalFn: func(this *Expression, es *EvalState) Ex {
172-
if len(this.Parts) != 2 {
172+
legacyEvalFn: func(this expreduceapi.ExpressionInterface, es expreduceapi.EvalStateInterface) expreduceapi.Ex {
173+
if len(this.GetParts()) != 2 {
173174
return this
174175
}
175-
asInt, isInt := this.Parts[1].(*Integer)
176+
asInt, isInt := this.GetParts()[1].(*atoms.Integer)
176177
if !isInt {
177178
return this
178179
}
179180
n := asInt.Val.Int64()
180181
if n <= 0 {
181182
return this
182183
}
183-
p := prime.Primes(uint64(n))
184-
//return &Integer{big.NewInt(0)}
185-
// A hack to get this working would be to find an upper bound on
186-
// the PrimePi funciton given an n value, and use that as the input
187-
// to the Primes() function. Then I can directly select the nth
188-
// value from the slice. See:
189-
// https://math.stackexchange.com/questions/479798/estimating-the-upper-bound-of-prime-count-in-the-given-range
190-
return &Integer{big.NewInt(int64(p[len(p)-1]))}
184+
// (Solve[n*(Log[n]+Log[Log[n]])==2^63,n, Reals][[1,1,2]]//N//Floor)-1000
185+
if n > 211642827166041848 {
186+
// Large numbers are not supported yet due to lack of big integer support.
187+
return this
188+
}
189+
floatN := float64(n)
190+
// https://math.stackexchange.com/questions/1270814/bounds-for-n-th-prime
191+
upperBound := floatN * (math.Log(floatN) + math.Log(math.Log(floatN)))
192+
if n < 6 {
193+
upperBound = 11
194+
}
195+
// There is a bug in prime.Primes where the csegPool uses a stale segSize when
196+
// we call the function for increasing values. For example, prime.Primes(15)
197+
// and prime.Primes(19) will trigger the issue. To bypass this issue, use the
198+
// slower function that doesn't have the problem, in the future, we could
199+
// consider fixing this.
200+
// Lines with the bug:
201+
// https://github.com/kavehmz/prime/blob/a94ad56341db886ae3346de1e6b341387c3c01d3/prime.go#L110-L112
202+
// Reproduced the issue at: https://github.com/corywalker/prime/commit/efd80a4fe9efd7263b329006629855d6f73c1c2e
203+
p := prime.SieveOfEratosthenes(uint64(upperBound) + 1)
204+
return atoms.NewInteger(big.NewInt(int64(p[n-1])))
191205
},
192206
SimpleExamples: []TestInstruction{
193207
&SameTest{"5", "Prime[3]"},
@@ -197,8 +211,10 @@ func getNumberTheoryDefinitions() (defs []Definition) {
197211
&SameTest{"Prime[0]", "Prime[0]"},
198212
&SameTest{"Prime[1.]", "Prime[1.]"},
199213
&SameTest{"2", "Prime[1]"},
214+
// Large numbers should remain unevaluated due to overflow risk.
215+
&SameTest{"Prime", "Prime[2^64]//Head"},
200216
},
201-
})*/
217+
})
202218
defs = append(defs, Definition{Name: "EvenQ"})
203219
defs = append(defs, Definition{Name: "OddQ"})
204220
defs = append(defs, Definition{Name: "FactorInteger"})

0 commit comments

Comments
 (0)