- 注册时间
- 2008-2-6
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 51573
- 在线时间
- 小时
|
楼主 |
发表于 2020-12-10 09:08:47
|
显示全部楼层
时间降不下来,发现筛出后,标记合数的只做fermat也不行,降不下来时间,不过候选素数从1000+万降低到600+万
Start Time: 09:11:55
init Time: 09:11:55
start number: 10000000000000000000000000000
sieve Time: 09:11:56
test Time: 09:12:36
to test PSP: 4375043, to test primility 6087984
primes: 1552676
4375043里,我怀疑3的倍数占很大比例
- #include<gmp.h>
- #include<stdbool.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<time.h>
- #define NULL_TERMINATED 0
- bool fermatTest( const mpz_t n, unsigned long b)
- {
- mpz_t r, b1, ns1;
-
- mpz_inits(r, ns1, NULL_TERMINATED);
- mpz_init_set_ui(b1, b);
-
- mpz_sub_ui(ns1, n, 1);
- mpz_powm(r, b1, ns1, n);
-
- bool result = mpz_cmp_ui(r, 1) == 0;
- mpz_clears(r, b1, ns1, NULL_TERMINATED);
- return result;
- }
- bool millerrabinTest( const mpz_t n, unsigned long b )
- {
- mpz_t ns1, t, b1, r;
- unsigned long s;
- bool result;
- mpz_inits(ns1, t, r, NULL_TERMINATED);
- mpz_init_set_ui(b1, b);// b1=b
- mpz_sub_ui(ns1, n, 1);// ns1=n-1
- s = mpz_scan1(ns1, 0);
- mpz_tdiv_q_2exp(t, ns1, s);// ns1=2^s*t, t%2=1
- mpz_powm(r, b1, t, n);
- if (mpz_cmp_ui(r, 1) == 0 || mpz_cmp(r, ns1) == 0)
- result = true;
- else
- {
- result = false;
- for (unsigned long i = 1; i < s; i ++)
- {
- mpz_powm_ui(r, r, 2, n);
- if (mpz_cmp(r, ns1) == 0)
- {
- result = true;
- break;
- }
- }
- }
- mpz_clears(ns1, t, b1, r, NULL_TERMINATED);
- return result;
- }
- const unsigned long step = 100000000;
- char *buff;
- unsigned long cnt = 0, pcnt = 0, pscnt = 0;
- unsigned long small[1227][2];
- unsigned long p100[] = { 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};
- //p < 10000
- unsigned long ord(unsigned long p)
- {
- unsigned long factor[16];
- unsigned long s = 0;
- unsigned long n = p - 1;
- mpz_t b, tmp, mp;
- mpz_init_set_ui(b, 2);
- mpz_init_set_ui(mp, p);
- mpz_init(tmp);
- for (int i = 0; i < 25; i ++)
- {
- if (n%p100[i] == 0)
- do
- {
- factor[s++] = p100[i];
- n /= p100[i];
- } while (n%p100[i] == 0);
- }
- n = p - 1;
- for (int i = 0; i < s; i++)
- {
- mpz_powm_ui(tmp, b, n / factor[i], mp);
- if (mpz_cmp_ui(tmp, 1) == 0)
- n /= factor[i];
- }
- if (n%2==1)
- n*=2;
- mpz_clears(b, tmp, mp, NULL_TERMINATED);
- return n;
- }
- // 实际测试值=base + index*step + [1..step]
- void init( mpz_t base, unsigned long index )
- {
- mpz_t tmp, tmp1;
- mpz_set_ui(base, 10);
- mpz_pow_ui(base, base, 28);
- mpz_init_set_ui(tmp, step);
- mpz_mul_ui(tmp, tmp, index);
- mpz_add(base, base, tmp);
- buff = (char *)malloc(step);
- for (long i = 0; i < step; i += 2)
- buff[i] = 0;
- for (long i = 1; i < step; i += 2)
- buff[i] = 3; //3 = 位组合0:素数 1:PSP(2)
-
- unsigned long i = 0;
- mpz_init_set_ui(tmp1, 3);
- while (i < 1227)
- {
- mpz_nextprime(tmp, tmp1);
- mpz_set(tmp1, tmp);
- small[i][0] = mpz_get_ui(tmp);
- small[i][1] = ord(small[i][0]);
- i++;
- }
- mpz_clears(tmp, tmp1, NULL_TERMINATED);
- }
- bool quickTest( mpz_t n )
- {
- unsigned long b[] = {3, 5, 7, 11, 13};
- for (int i = 0; i < sizeof(b)/sizeof(unsigned long); i++)
- if (!millerrabinTest(n, b[i]))
- return false;
- return true;
- }
- void sieve( mpz_t base, long idx )
- {
- mpz_t q, r, q1;
- unsigned long r1, q2;
- mpz_inits(q, r, q1, NULL_TERMINATED);
- //置位奇数中3的倍数为非素数
- mpz_mod_ui(q1, base, 3);
- q2 = mpz_get_ui(q1);
- q2 = 3 - q2;
- if (q2%2==0)
- q2 += 3;
- while (q2 < step)
- {
- buff[q2] &= 2;
- q2 += 6;
- }
- for (long i = 0; i < 1227; i ++)
- {
- //合数形如pm, 素数p对2的次数是k, 筛掉不满足m=nk+1的,因为只需要考虑m是奇数,所以,对k不是偶数的,已经乘以2了
- mpz_fdiv_qr_ui(q, r, base, small[i][0]);
- mpz_mod_ui(q1, q, small[i][1]);
- q2 = mpz_get_ui(q1);
- r1 = mpz_get_ui(r);
- r1 = small[i][0] - r1;
- q2 = (q2+1)%small[i][1];
- if (r1%2==0)
- {
- r1 += small[i][0];
- q2 = (q2+1)%small[i][1];
- }
- while (r1 < step)
- {
- buff[r1] &= 2; //非素数
- if (q2 != 1)
- {
- buff[r1] = 0; //非PSP(2)
- }
- r1 += 2*small[i][0];
- q2 = (q2+2)%small[i][1];
- }
-
- //筛掉满足p^2的倍数,其中p是素数且不等于1093,3511
- unsigned long sq = small[i][0];
- if (sq != 1093 && sq != 3511 && sq <= 7071)
- {
- sq *= sq;
- mpz_mod_ui(q1, base, sq);
- q2 = mpz_get_ui(q1);//取模
- q2 = sq - q2;//加sq,得到第一个奇数倍数,如果q2=0,结果也是对的
- if (q2%2==0)
- q2 += sq;
- while (q2 < step)
- {
- buff[q2] = 0; //非PSP(2)
- q2 += 2*sq;
- }
- }
- }
- //筛掉奇数中9的倍数
- mpz_mod_ui(q1, base, 9);
- q2 = mpz_get_ui(q1);
- q2 = 9 - q2;
- if (q2%2==0)
- q2 += 9;
- while (q2 < step)
- {
- buff[q2] = 0;
- q2 += 18;
- }
- mpz_clears(q, r, q1, NULL_TERMINATED);
- }
- //位标0:素数 1:PSP(2)
- int check(mpz_t base, long i)
- {
- mpz_t n;
- int result;
- mpz_init(n);
- mpz_add_ui(n, base, i);
- if (fermatTest(n, 2))
- {
- if (millerrabinTest(n, 2))
- {
- if (quickTest(n))
- {
- result = 3;
- cnt ++;
- }
- else
- result = 2;
- }
- else
- result = 1;
- }
- else
- result = 0;
- if (result > 0 && result < 3)
- {
- gmp_printf("%Zd type: %d\n", n, result);
- }
-
- mpz_clear(n);
- return result;
- }
- void test( mpz_t base, long idx )
- {
- for (long i = 1; i < step; i += 2)
- if (buff[i] == 3) //未筛的数字
- {
- pcnt ++;
- buff[i] = check(base, i);
- }
- else
- if (buff[i] == 2) //判定非素数,且可能PSP(2)的数字
- {
- mpz_t n;
- pscnt++;
- mpz_init_set_ui(n, i);
- mpz_add(n, n, base);
- if (fermatTest( n, 2))
- gmp_printf("%Zd: PSP(2)\n", n);
- mpz_clear(n);
- }
- }
- void clear( void )
- {
- free(buff);
- }
- void showTime(char * pref)
- {
- time_t rawtime;
- struct tm * timeinfo;
- char buffer [16];
- time (&rawtime);
- timeinfo = localtime (&rawtime);
- strftime (buffer, 16 ,"%X", timeinfo);
- printf("%s: %s\n", pref, buffer);
- }
- int main( int argc, char * argv[] )
- {
- mpz_t base;
- mpz_init(base);
- long idx = 0;
- char * ptr;
- if (argc > 1)
- idx = strtol(argv[1], &ptr, 10);
- showTime("Start Time");
-
- init( base, idx );
- showTime(" init Time");
- gmp_printf("start number: %Zd\n", base);
- sieve( base, idx );
- showTime("sieve Time");
-
- test( base, idx );
- showTime(" test Time");
-
- printf("to test PSP: %d, to test primility %d\n", pscnt, pcnt);
- printf("primes: %d\n", cnt);
- mpz_clear(base);
- clear();
- return 0;
- }
复制代码 |
|