mersenneforum.org  

Go Back   mersenneforum.org > Math Stuff > Computer Science & Computational Number Theory > PARI/GP

Reply
 
Thread Tools
Old 2014-10-04, 11:34   #2487
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26·131 Posts
Default

Quote:
Originally Posted by CRGreathouse View Post
Does (4^4655 - 1)/3 fail also?
no. edit: but for me it fails at a(4651)

Last fiddled with by science_man_88 on 2014-10-04 at 11:58
science_man_88 is offline   Reply With Quote
Old 2014-10-05, 01:09   #2488
CRGreathouse
 
CRGreathouse's Avatar
 
Aug 2006

3·1,993 Posts
Default

Quote:
Originally Posted by science_man_88 View Post
no. edit: but for me it fails at a(4651)
So the problem is with your function a(). You'll need to rewrite it to not fill the stack.
CRGreathouse is offline   Reply With Quote
Old 2014-10-18, 17:33   #2489
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26·131 Posts
Default try at mersenne semiprimes

Code:
 = ()->for(k=0,2^199,if((isprime(floor(log(6*k+2)/log(2)))||(issquare(floor(log(6*k+2)/log(2)))&&isprimepower(floor(log(6*k+2)/log(2)))==2
&&isprime(2^floor(sqrt(log(6*k+2)/log(2)))-1)))&&#factor(6*k+1)[,1]==2&&sum(x=1,#factor(6*k+1)[,2],factor(6*k+1)[x,2])==2,print1(floor(log(6*k+2)/log(2))","));k=4*k)
I tried different versions like this before just going back through my pari history but I can't get much improvement if at all in fact some things I thought could be improvements don't appear to be like pre-calculating
Code:
floor(log(6*k+2)/log(2))
seems to not really help much and I have been debating if I should use issquarefree(x) or core(x)==x because one seems faster above a certain number once I take the limit away, I even tried k as the exponent and a forstep and nothing seems to improve it even though I know there are checks I could do to improve it more like the squarefree scenario ( of course I can limit mod 120 etc first to lower the amount of squarefree checks when checking the prime part of the OR) any other ideas that might speed it up

Last fiddled with by science_man_88 on 2014-10-18 at 17:58
science_man_88 is offline   Reply With Quote
Old 2014-10-19, 15:53   #2490
CRGreathouse
 
CRGreathouse's Avatar
 
Aug 2006

3×1,993 Posts
Default

Since your function is an unreadable single line I won't dissect it, but I notice that you're using floor(log(6*k+2)/log(2)) a lot. Let's define t = floor(log(6*k+2)/log(2)), which you'll notice stays the same for long streches of k and then goes up by 1. Why don't you loop over values of t directly, and then re-create the associated values of k if t passes your tests?
CRGreathouse is offline   Reply With Quote
Old 2014-10-19, 16:17   #2491
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26×131 Posts
Default

Quote:
Originally Posted by CRGreathouse View Post
Since your function is an unreadable single line I won't dissect it, but I notice that you're using floor(log(6*k+2)/log(2)) a lot. Let's define t = floor(log(6*k+2)/log(2)), which you'll notice stays the same for long streches of k and then goes up by 1. Why don't you loop over values of t directly, and then re-create the associated values of k if t passes your tests?
each loop through the for loop k is multiplied by 4 and then adds one more. I'm looping through k values that produce odd exponent mersenne numbers I took care of it in my newest version it still doesn't trim a lot of time like i thought. I replaced it with p=logint(6*k+2,2) for each k used and more but I realize I used %39 to call it so in my new session I can't call it back to the quickest form I got to:

Code:
try() ={
n=0;
m=vector(120,n,gcd(n-1,120)==1);
for(k=0,2^199,
     p=logint(6*k+2,2);
     if(
        (
        (
        m[(p%120)+1] && core(p)==p && isprime(p)
        )
        ||
        (
        issquare(p) && isprimepower(p,&n)==2 && isprime(2^n-1)
        )
        )
        && #factor(6*k+1)[,1]==2 && sum(x=1,2,factor(6*k+1)[x,2])==2,
        print1(p",")
        )
;        k=4*k
    )}
is the best I could do at rewriting my best implementation.

Last fiddled with by science_man_88 on 2014-10-19 at 17:01
science_man_88 is offline   Reply With Quote
Old 2014-10-19, 18:02   #2492
CRGreathouse
 
CRGreathouse's Avatar
 
Aug 2006

3×1,993 Posts
Default

OK, that gives me a lot more to go on.

First, you should always declare scope for your variables. In about 100% of cases this should be done with my(), with some residual cases using local() instead. Otherwise you overwrite global variables which is BAD and will cause unintended side-effects down the road.
Code:
try()={
	my(m=vector(120,n,gcd(n-1,120)==1), q);
	for(k=0,2^199,
		my(p=logint(6*k+2,2));
		if(
		(
			(m[(p%120)+1] && core(p)==p && isprime(p))
		||
			(issquare(p) && isprimepower(p,&q)==2 && isprime(2^q-1))
		) && #factor(6*k+1)[,1]==2 && sum(x=1,2,factor(6*k+1)[x,2])==2,
			print1(p",")
		);
		k=4*k
	)
};
Second you should split out your handling of the test of p from the rest of the program. This is just good general form. A first attempt would be a straight split:
Code:
m=vector(120,n,gcd(n-1,120)==1); \\ global

is(p,k)={
	my(q);
	(
		(m[(p%120)+1] && core(p)==p && isprime(p))
	||
		(issquare(p) && isprimepower(p,&q)==2 && isprime(2^q-1))
	) && #factor(6*k+1)[,1]==2 && sum(x=1,2,factor(6*k+1)[x,2])==2
};

try()={
	for(k=0,2^199,
		my(p=logint(6*k+2,2));
		if(is(p, k),
			print1(p",")
		);
		k=4*k
	)
};
Let's work on is() first. There's no need for m, it would be better to do the gcd each time. Much faster than core(n)==n is the function issquarefree(n), but you don't even need this at all because primes are always squarefree. That gives:
Code:
is(p,k)={
	my(q);
	(
		(gcd(p,120)==1 && isprime(p))
	||
		(issquare(p, &q) && isprime(q) && isprime(2^q-1))
	) && #factor(6*k+1)[,1]==2 && sum(x=1,2,factor(6*k+1)[x,2])==2
};

try()={
	for(k=0,2^199,
		my(p=logint(6*k+2,2));
		if(is(p, k),
			print1(p",")
		);
		k=4*k
	)
};
Next I notice that you're factoring 6k+1 three times, which seems extreme. One way to handle this would be to store the results of factoring, but in this case there's an easier solution: just look at the exponent vector. Numbers relatively prime to 120 are just those relatively prime to 30, but we can simplify further since that path is just looking for primes so we can just test that p > 5. In fact that test can be pulled outside (since the only prime square <= 5 is 4 which doesn't pass). Oh, and we need a definition of logint, so here we go:
Code:
logint(N,b)=my(k);while(N>=b,N\=b;k++);k;

is(p,k)={
	my(q);
	p>5 && 
	(isprime(p) || (issquare(p, &q) && isprime(q) && isprime(2^q-1)))
	&& factor(6*k+1)[,2]==[1,1]~
};

try()={
	for(k=0,2^199,
		my(p=logint(6*k+2,2));
		if(is(p, k),
			print1(p",")
		);
		k=4*k
	)
};
Now let's look at try(). I don't like abusing for() loops like this, a while() loop would make the transformation k -> 4k+1 clearer. But I think that it would be even clearer if you just wrote (4^n - 1)/3, and since the calculations inside is() take far longer than this calculation I'd just do that directly. (k <= 2^199 corresponds to n <= 100 here.) That also makes it clear that p = 2n+1 which was not at all clear before! Also we can remove our new function logint() since it isn't used.
Code:
is(p,k)={
	my(n);
	p>5 && 
	(isprime(p) || (issquare(p, &n) && isprime(n) && isprime(2^n-1)))
	&& factor(6*k+1)[,2]==[1,1]~
};

try()={
	for(n=0,100,
		my(k=(4^n-1)/3, p=2*n+1);
		if(is(p, k),
			print1(p",")
		)
	)
};
Now the code is much clearer, and you can see that you're just looking for semiprimes of the form 2^m - 1 subject to some conditions on m -- probably necessary conditions for semiprimality. But we can go further! You're ultimately testing 2^p - 1 for primality, and if p is the square of a prime q then the factorization of 2^p - 1 must be 2^q-1 times another prime, so we don't need to factor 2^p-1 in generality in that case. This also lets us clean up the code to remove k, which is no longer needed.
Code:
is(p)={
	my(q);
	if(p < 7, return(0));
	if(issquare(p, &q) && isprime(q) && isprime(2^q-1)),
		return(isprime((2^p-1)/(2^q-1)))
	);
	isprime(p) && factor(2^p-1)[,2]==[1,1]~
};

try()={
	for(n=0,100,
		my(p=2*n+1);
		if(is(p),
			print1(p",")
		)
	)
};
Evidently we can clean up the loop in try() to go directly over the odd numbers, no need for n. Also, since we're requiring it to be at least 7, let's just start the loop there and remove that condition from is().
Code:
is(p)={
	my(q);
	if(issquare(p, &q) && isprime(q) && isprime(2^q-1),
		return(isprime((2^p-1)/(2^q-1)))
	);
	isprime(p) && factor(2^p-1)[,2]==[1,1]~
};

try()={
	forstep(p=7,201,2,
		if(is(p), print1(p","))
	)
};
At this point I'm done simplifying, but you could improve this further. For example, you could replace the test isprime(2^q-1) with a function LL(q) which uses the Lucas-Lehmer test to see if 2^q-1 is prime, and you could write trial division code that checks for small prime factors of 2^p-1 (using only the ones which could be factors, of course) -- if you find one you don't have to complete the factorization, you can just test the cofactor for primality.

Edit: Another good step would be to replace try() with try(lim=201) and using forstep(p=7,lim,2 so you can test different regions without editing the function.

Last fiddled with by CRGreathouse on 2014-10-19 at 20:51
CRGreathouse is offline   Reply With Quote
Old 2014-10-19, 19:12   #2493
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26×131 Posts
Default

sometimes I think you know too much about PARI in the sense that my all inbuilt function using codes are half as fast as the ones you make. I was doing the other testing to decrease the number of checks but I guess my checks took so much time that the decrease didn't matter. I thought about using k as the exponent but could never get it to work. my code caught 9 but not 4 and yours appears to forget about 9. I'll see what I can implement of your further suggestions.

Last fiddled with by CRGreathouse on 2014-10-19 at 20:51 Reason: snip long quote
science_man_88 is offline   Reply With Quote
Old 2014-10-19, 20:50   #2494
CRGreathouse
 
CRGreathouse's Avatar
 
Aug 2006

135338 Posts
Default

I get
Code:
9,11,23,37,41,49,59,67,83,97,101,103,109,131,137,139,149,167,197,199,
in 7 seconds. This could be improved, no doubt.

Edit: I did have to remove a superfluous paren from my code, try it now to see if it works.

Last fiddled with by CRGreathouse on 2014-10-19 at 20:56
CRGreathouse is offline   Reply With Quote
Old 2014-10-19, 21:05   #2495
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26×131 Posts
Default

Quote:
Originally Posted by CRGreathouse View Post
I get
Code:
9,11,23,37,41,49,59,67,83,97,101,103,109,131,137,139,149,167,197,199,
in 7 seconds. This could be improved, no doubt.

Edit: I did have to remove a superfluous paren from my code, try it now to see if it works.
Code:
(16:51) gp > is(p)=my(q);if(issquare(p,&q)&&isprime(q)&&isprime(2^q-1),(isprime((2^p-1)/(2^q-1))));isprime(p)&&factor(2^p-1)[,2]==[1,1]~;
(17:57) gp > try(lim=201)={forstep(p=7,lim,2,if(is(p), print1(p",")))};
(17:57) gp > try()
11,23,37,41,59,67,83,97,101,103,109,131,137,139,149,167,197,199,
(17:58) gp > ##
  ***   last result computed in 3,970 ms.
oh and I tried to make the LL check but it made it take longer probably because I suck I was thinking of just using your M code ( if I can find it) or a vector of known to be mersenne prime exponents because even with a complete list I could use the code in theory to check up to 924309391636849 or a little higher.
science_man_88 is offline   Reply With Quote
Old 2014-10-19, 21:21   #2496
CRGreathouse
 
CRGreathouse's Avatar
 
Aug 2006

3×1,993 Posts
Default

The ultimate optimization would be something like
2^p-1
2^(p^2)-1
CRGreathouse is offline   Reply With Quote
Old 2014-10-20, 14:07   #2497
science_man_88
 
science_man_88's Avatar
 
"Forget I exist"
Jul 2009
Dumbassville

26×131 Posts
Default

Quote:
Originally Posted by CRGreathouse View Post
The ultimate optimization would be something like
2^p-1
2^(p^2)-1
I'm trying now to optimize to check if the division is prime from the formula I got for when the exponent's a certain multiple plus something and the reduced binomial theorem on wikipedia for when you have a variable plus 1 to a power I get that the result of division is:
Code:
my(n=q);sum(k=0,n-1,binomial(n,k+1)*y^k)
but I'm trying to think the best way to use this to test primality.

Last fiddled with by science_man_88 on 2014-10-20 at 14:17
science_man_88 is offline   Reply With Quote
Reply

Thread Tools


Similar Threads
Thread Thread Starter Forum Replies Last Post
Why do I sometimes see all the <> formatting commands when I quote or edit? cheesehead Forum Feedback 3 2013-05-25 12:56
Passing commands to PARI on Windows James Heinrich Software 2 2012-05-13 19:19
Ubiquity commands Mini-Geek Aliquot Sequences 1 2009-09-22 19:33
64-bit Pari? CRGreathouse Software 2 2009-03-13 04:22
Are these commands correct? jasong Linux 2 2007-10-18 23:40

All times are UTC. The time now is 06:55.


Fri Aug 6 06:55:27 UTC 2021 up 14 days, 1:24, 1 user, load averages: 2.49, 2.64, 2.71

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.

This forum has received and complied with 0 (zero) government requests for information.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation.
A copy of the license is included in the FAQ.