আরপিথন (পাইপাই 4.0.1), 4032
আরপিথন পাইথনের একটি সীমাবদ্ধ উপসেট, যা সিতে অনুবাদ করা যায় এবং তারপরে আরপিথন টুলচেন ব্যবহার করে সংকলিত হতে পারে। এর প্রকাশিত উদ্দেশ্য ভাষা দোভাষী তৈরিতে সহায়তা করা, তবে এটি সাধারণ প্রোগ্রামগুলি সংকলন করতেও ব্যবহার করা যেতে পারে।
সংকলন করতে, বর্তমান পাইপাই উত্সটি ডাউনলোড করুন (পাইপাই ৪.০.১) এবং নিম্নলিখিতগুলি চালান:
$ pypy /pypy-4.0.1-src/rpython/bin/rpython --opt=3 good-primes.py
ফলস্বরূপ এক্সিকিউটেবলের নাম good-primes-c
বা বর্তমান চলমান ডিরেক্টরিতে অনুরূপ।
বাস্তবায়ন নোট
প্রাইম নম্বর জেনারেটরটি primes
ইরোটোথিনিসের সীমাহীন চালনী যা 2 , 3 , 5 বা 7 এর কোনও গুণকে এড়াতে চাকা ব্যবহার করে । এটি চিহ্নিতকরণের জন্য ব্যবহারের জন্য পরবর্তী মান উত্পন্ন করতে পুনরাবৃত্তভাবে নিজেকে কল করে। আমি এই জেনারেটরের সাথে যথেষ্ট সন্তুষ্ট। লাইন প্রোফাইলিংটি প্রকাশ করে যে ধীরতম দুটি লাইন হ'ল:
37> n += o
38> if n not in sieve:
সুতরাং আমি সম্ভবত বৃহত্তর চাকা ব্যবহার ব্যতীত উন্নতির বেশি জায়গা নেই বলে মনে করি না।
"ধার্মিকতা" পরীক্ষার জন্য প্রথমে দুটি -এর সমস্ত কারণকে এন -1 থেকে সরানো হয়েছে , বিট-টুইডলিং হ্যাক ব্যবহার করে দু'জনের বৃহত্তম পাওয়ার খুঁজে পেতে যা একটি বিভাজক (n-1 & 1-n)
। যেহেতু পি -1 প্রয়োজনীয় কোনও প্রাইম পি> 2 এর জন্যও , এটি অনুসরণ করে যে 2 অবশ্যই পৃথক প্রধান উপাদানগুলির মধ্যে একটি হতে হবে। যা অবশিষ্ট রয়েছে তা is_prime_power
ফাংশনে প্রেরণ করা হয় , যা এর নামটি বোঝায় does পরীক্ষা করা হচ্ছে মানটি যদি প্রধানমন্ত্রীদের ক্ষমতার যেহেতু এটি সর্বাধিক primality চেক দিয়ে একযোগে সম্পন্ন করা হয়, সঙ্গে হল "প্রায় মুক্ত" হয়, হে (লগ পি ঢ) অপারেশন, যেখানে পি ক্ষুদ্রতম মৌলিক ফ্যাক্টর এন। ট্রায়াল বিভাগটি কিছুটা নির্বোধ মনে হতে পারে তবে আমার পরীক্ষার দ্বারা এটি 2 32 এর চেয়ে কম মানের জন্য দ্রুততম পদ্ধতি । চালুনি থেকে চাকাটি পুনরায় ব্যবহার করে আমি কিছুটা সাশ্রয় করি। নির্দিষ্টভাবে:
59> while p*p < n:
60> for o in offsets:
48 টি দৈর্ঘ্যের চাকা ধরে পুনরাবৃত্তি করার মাধ্যমে, 48 p*p < n
বারের বেশি মডুলো ক্রিয়াকলাপের কম, কম দামে, চেকটি কয়েক হাজার বার এড়িয়ে যাবে। এটি কেবল প্রতিকূলতার কারণে 50% পরিবর্তে সমস্ত প্রার্থীর 77% ছাড়িয়ে যায়।
শেষ কয়েকটি ফলাফল:
3588 (987417437 - 987413849) 60.469000s
3900 (1123404923 - 1123401023) 70.828000s
3942 (1196634239 - 1196630297) 76.594000s
4032 (1247118179 - 1247114147) 80.625000s
4176 (1964330609 - 1964326433) 143.047000s
4224 (2055062753 - 2055058529) 151.562000s
কোডটি বৈধ পাইথনও, এবং সাম্প্রতিক পাইপাই ইন্টারপ্রেটার দিয়ে চালাকালে 3588 ~ 3900 এ পৌঁছানো উচিত।
# primes less than 212
small_primes = [
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
97,101,103,107,109,113,127,131,137,139,149,151,
157,163,167,173,179,181,191,193,197,199,211]
# pre-calced sieve of eratosthenes for n = 2, 3, 5, 7
# distances between sieve values, starting from 211
offsets = [
10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4,
2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6,
4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2]
# tabulated, mod 105
dindices =[
0,10, 2, 0, 4, 0, 0, 0, 8, 0, 0, 2, 0, 4, 0,
0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 6, 0, 0, 2,
0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 4, 2,
0, 6, 6, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 4, 2,
0, 6, 2, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 6, 2,
0, 6, 0, 0, 4, 0, 0, 4, 6, 0, 0, 2, 0, 4, 8,
0, 0, 2, 0,10, 0, 0, 4, 0, 0, 0, 2, 0, 4, 2]
def primes(start = 0):
for n in small_primes[start:]: yield n
pg = primes(6)
p = pg.next()
q = p*p
sieve = {221: 13, 253: 11}
n = 211
while True:
for o in offsets:
n += o
stp = sieve.pop(n, 0)
if stp:
nxt = n/stp
nxt += dindices[nxt%105]
while nxt*stp in sieve: nxt += dindices[nxt%105]
sieve[nxt*stp] = stp
else:
if n < q:
yield n
else:
sieve[q + dindices[p%105]*p] = p
p = pg.next()
q = p*p
def is_prime_power(n):
for p in small_primes:
if n%p == 0:
n /= p
while n%p == 0: n /= p
return n == 1
p = 211
while p*p < n:
for o in offsets:
p += o
if n%p == 0:
n /= p
while n%p == 0: n /= p
return n == 1
return n > 1
def main(argv):
from time import time
t0 = time()
m = 0
p = q = 7
pgen = primes(3)
for n in pgen:
d = (n-1 & 1-n)
if is_prime_power(n/d):
p, q = q, n
if q-p > m:
m = q-p
print m, "(%d - %d) %fs"%(q, p, time()-t0)
return 0
def target(*args):
return main, None
if __name__ == '__main__':
from sys import argv
main(argv)
আরপিথন (পাইপাই 4.0.1), 22596
এই জমাটি এখনও অবধি পোস্ট করা অন্যদের তুলনায় কিছুটা আলাদা, কারণ এটি সমস্ত ভাল প্রাইমগুলি পরীক্ষা করে না, পরিবর্তে তুলনামূলকভাবে বড় লাফ দেয়। এটি করার একটি অসুবিধা হ'ল চালুনি ব্যবহার করা যায় না [আমি সংশোধন করে দাঁড়িয়েছি?] , সুতরাং একজনকে পুরোপুরি আদিমতার পরীক্ষার উপর নির্ভর করতে হবে যা অনুশীলনে বেশ খানিকটা ধীর গতির হয়। বৃদ্ধির হার এবং প্রতিবার পরীক্ষিত মানগুলির সংখ্যার মধ্যেও খুঁজে পাওয়ার জন্য একটি সুখী মাধ্যম রয়েছে। ছোট মানগুলি চেক করতে খুব দ্রুত, তবে বৃহত্তর মানগুলির বৃহত্তর ফাঁক হওয়ার সম্ভাবনা বেশি।
গণিত দেবতাদের সন্তুষ্ট করার জন্য, আমি সিদ্ধান্ত নিয়েছি একটি ফিবোনাকির মতো ক্রম অনুসরণ করব, যার পরের সূচনা পয়েন্টটি পূর্বের দু'জনের যোগফল হিসাবে হবে। যদি 10 টি জোড়া পরীক্ষা করে কোনও নতুন রেকর্ড না পাওয়া যায় তবে স্ক্রিপ্টটি পরের দিকে চলে যায়।
শেষ কয়েকটি ফলাফল:
6420 (12519586667324027 - 12519586667317607) 0.364000s
6720 (707871808582625903 - 707871808582619183) 0.721000s
8880 (626872872579606869 - 626872872579597989) 0.995000s
10146 (1206929709956703809 - 1206929709956693663) 4.858000s
22596 (918415168400717543 - 918415168400694947) 8.797000s
সংকলিত হয়ে গেলে, -৪-বিট পূর্ণসংখ্যা ব্যবহৃত হয়, যদিও এটি কয়েকটি জায়গায় অনুমান করা হয় যে দুটি সংখ্যার অতিরিক্ত প্রবাহ ছাড়াই যুক্ত করা যেতে পারে, সুতরাং অনুশীলনে কেবল 63৩ টি ব্যবহারযোগ্য। 62 টি উল্লেখযোগ্য বিট পৌঁছানোর পরে, গণনার মধ্যে অতিরিক্ত প্রবাহ এড়াতে বর্তমান মানটি দু'বার অর্ধেক হয়ে যায়। ফলাফলটি হ'ল স্ক্রিপ্টটি 2 60 - 2 62 রেঞ্জের মানগুলিতে পরিবর্তিত হয় । দেশীয় পূর্ণসংখ্যার নির্ভুলতা ছাড়িয়ে না যাওয়া যখন ব্যাখ্যা করা হয় তখন স্ক্রিপ্টটি আরও দ্রুত করে তোলে।
নিম্নলিখিত PARI / GP স্ক্রিপ্টটি এই ফলাফলটি নিশ্চিত করতে ব্যবহার করা যেতে পারে:
isgoodprime(n) = isprime(n) && omega(n-1)==2
for(n = 918415168400694947, 918415168400717543, {
if(isgoodprime(n), print(n" is a good prime"))
})
try:
from rpython.rlib.rarithmetic import r_int64
from rpython.rtyper.lltypesystem.lltype import SignedLongLongLong
from rpython.translator.c.primitive import PrimitiveType
# check if the compiler supports long long longs
if SignedLongLongLong in PrimitiveType:
from rpython.rlib.rarithmetic import r_longlonglong
def mul_mod(a, b, m):
return r_int64(r_longlonglong(a)*b%m)
else:
from rpython.rlib.rbigint import rbigint
def mul_mod(a, b, m):
biga = rbigint.fromrarith_int(a)
bigb = rbigint.fromrarith_int(b)
bigm = rbigint.fromrarith_int(m)
return biga.mul(bigb).mod(bigm).tolonglong()
# modular exponentiation b**e (mod m)
def pow_mod(b, e, m):
r = 1
while e:
if e&1: r = mul_mod(b, r, m)
e >>= 1
b = mul_mod(b, b, m)
return r
except:
import sys
r_int64 = int
if sys.maxint == 2147483647:
mul_mod = lambda a, b, m: a*b%m
else:
mul_mod = lambda a, b, m: int(a*b%m)
pow_mod = pow
# legendre symbol (a|m)
# note: returns m-1 if a is a non-residue, instead of -1
def legendre(a, m):
return pow_mod(a, (m-1) >> 1, m)
# strong probable prime
def is_sprp(n, b=2):
if n < 2: return False
d = n-1
s = 0
while d&1 == 0:
s += 1
d >>= 1
x = pow_mod(b, d, n)
if x == 1 or x == n-1:
return True
for r in xrange(1, s):
x = mul_mod(x, x, n)
if x == 1:
return False
elif x == n-1:
return True
return False
# lucas probable prime
# assumes D = 1 (mod 4), (D|n) = -1
def is_lucas_prp(n, D):
Q = (1-D) >> 2
# n+1 = 2**r*s where s is odd
s = n+1
r = 0
while s&1 == 0:
r += 1
s >>= 1
# calculate the bit reversal of (odd) s
# e.g. 19 (10011) <=> 25 (11001)
t = r_int64(0)
while s:
if s&1:
t += 1
s -= 1
else:
t <<= 1
s >>= 1
# use the same bit reversal process to calculate the sth Lucas number
# keep track of q = Q**n as we go
U = 0
V = 2
q = 1
# mod_inv(2, n)
inv_2 = (n+1) >> 1
while t:
if t&1:
# U, V of n+1
U, V = mul_mod(inv_2, U + V, n), mul_mod(inv_2, V + mul_mod(D, U, n), n)
q = mul_mod(q, Q, n)
t -= 1
else:
# U, V of n*2
U, V = mul_mod(U, V, n), (mul_mod(V, V, n) - 2 * q) % n
q = mul_mod(q, q, n)
t >>= 1
# double s until we have the 2**r*sth Lucas number
while r:
U, V = mul_mod(U, V, n), (mul_mod(V, V, n) - 2 * q) % n
q = mul_mod(q, q, n)
r -= 1
# primality check
# if n is prime, n divides the n+1st Lucas number, given the assumptions
return U == 0
# primes less than 212
small_primes = [
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
97,101,103,107,109,113,127,131,137,139,149,151,
157,163,167,173,179,181,191,193,197,199,211]
# pre-calced sieve of eratosthenes for n = 2, 3, 5, 7
indices = [
1, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,
107,109,113,121,127,131,137,139,143,149,151,157,
163,167,169,173,179,181,187,191,193,197,199,209]
# distances between sieve values
offsets = [
10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4,
2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6,
4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2]
bit_lengths = [
0x00000000, 0x00000001, 0x00000003, 0x00000007,
0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF]
max_int = 2147483647
# returns the index of x in a sorted list a
# or the index of the next larger item if x is not present
# i.e. the proper insertion point for x in a
def binary_search(a, x):
s = 0
e = len(a)
m = e >> 1
while m != e:
if a[m] < x:
s = m
m = (s + e + 1) >> 1
else:
e = m
m = (s + e) >> 1
return m
def log2(n):
hi = n >> 32
if hi:
return binary_search(bit_lengths, hi) + 32
return binary_search(bit_lengths, n)
# integer sqrt of n
def isqrt(n):
c = n*4/3
d = log2(c)
a = d>>1
if d&1:
x = r_int64(1) << a
y = (x + (n >> a)) >> 1
else:
x = (r_int64(3) << a) >> 2
y = (x + (c >> a)) >> 1
if x != y:
x = y
y = (x + n/x) >> 1
while y < x:
x = y
y = (x + n/x) >> 1
return x
# integer cbrt of n
def icbrt(n):
d = log2(n)
if d%3 == 2:
x = r_int64(3) << d/3-1
else:
x = r_int64(1) << d/3
y = (2*x + n/(x*x))/3
if x != y:
x = y
y = (2*x + n/(x*x))/3
while y < x:
x = y
y = (2*x + n/(x*x))/3
return x
## Baillie-PSW ##
# this is technically a probabalistic test, but there are no known pseudoprimes
def is_bpsw(n):
if not is_sprp(n, 2): return False
# idea shamelessly stolen from Mathmatica's PrimeQ
# if n is a 2-sprp and a 3-sprp, n is necessarily square-free
if not is_sprp(n, 3): return False
a = 5
s = 2
# if n is a perfect square, this will never terminate
while legendre(a, n) != n-1:
s = -s
a = s-a
return is_lucas_prp(n, a)
# an 'almost certain' primality check
def is_prime(n):
if n < 212:
m = binary_search(small_primes, n)
return n == small_primes[m]
for p in small_primes:
if n%p == 0:
return False
# if n is a 32-bit integer, perform full trial division
if n <= max_int:
p = 211
while p*p < n:
for o in offsets:
p += o
if n%p == 0:
return False
return True
return is_bpsw(n)
# next prime strictly larger than n
def next_prime(n):
if n < 2:
return 2
# first odd larger than n
n = (n + 1) | 1
if n < 212:
m = binary_search(small_primes, n)
return small_primes[m]
# find our position in the sieve rotation via binary search
x = int(n%210)
m = binary_search(indices, x)
i = r_int64(n + (indices[m] - x))
# adjust offsets
offs = offsets[m:] + offsets[:m]
while True:
for o in offs:
if is_prime(i):
return i
i += o
# true if n is a prime power > 0
def is_prime_power(n):
if n > 1:
for p in small_primes:
if n%p == 0:
n /= p
while n%p == 0: n /= p
return n == 1
r = isqrt(n)
if r*r == n:
return is_prime_power(r)
s = icbrt(n)
if s*s*s == n:
return is_prime_power(s)
p = r_int64(211)
while p*p < r:
for o in offsets:
p += o
if n%p == 0:
n /= p
while n%p == 0: n /= p
return n == 1
if n <= max_int:
while p*p < n:
for o in offsets:
p += o
if n%p == 0:
return False
return True
return is_bpsw(n)
return False
def next_good_prime(n):
n = next_prime(n)
d = (n-1 & 1-n)
while not is_prime_power(n/d):
n = next_prime(n)
d = (n-1 & 1-n)
return n
def main(argv):
from time import time
t0 = time()
if len(argv) > 1:
n = r_int64(int(argv[1]))
else:
n = r_int64(7)
if len(argv) > 2:
limit = int(argv[2])
else:
limit = 10
m = 0
e = 1
q = n
try:
while True:
e += 1
p, q = q, next_good_prime(q)
if q-p > m:
m = q-p
print m, "(%d - %d) %fs"%(q, p, time()-t0)
n, q = p, n+p
if log2(q) > 61:
q >>= 2
e = 1
q = next_good_prime(q)
elif e > limit:
n, q = p, n+p
if log2(q) > 61:
q >>= 2
e = 1
q = next_good_prime(q)
except KeyboardInterrupt:
pass
return 0
def target(*args):
return main, None
if __name__ == '__main__':
from sys import argv
main(argv)