找回密码
 欢迎注册
查看: 2782|回复: 34

[原创] BPSW和QFT素性检验算法执行时间比较

[复制链接]
发表于 2023-4-28 21:55:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
数据用2^64以内强伪素数,除去 1093^2 和 3511^2 组成

先二次域测试 QFT

测试数据在百度网盘共享
链接:https://pan.baidu.com/s/1H7j_QZDvykp1XyuTMgbb7A?pwd=o1sw
提取码:o1sw
算法原理见: https://bbs.emath.ac.cn/thread-16936-1-1.html 6层

  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <flint/ulong_extras.h>

  6. typedef struct
  7. {
  8.   uint64_t r;
  9.   uint64_t i;
  10. } QF;

  11. QF qfmul(QF l, QF r, int64_t c, uint64_t p, uint64_t pinv)
  12. {
  13.   QF dst;
  14.   uint64_t t1 = n_mulmod2_preinv(l.r, r.r, p, pinv);
  15.   uint64_t t2 = n_mulmod2_preinv(l.i, r.i, p, pinv);
  16.   switch (c)
  17.   {
  18.     case -1:
  19.       dst.r = n_submod(t1, t2, p);
  20.       break;
  21.     case 2:
  22.       t2 = n_addmod(t2, t2, p);
  23.       dst.r = n_addmod(t1, t2, p);
  24.       break;
  25.     default:
  26.       t2 = n_mulmod2_preinv(t2, c, p, pinv);
  27.       dst.r = n_addmod(t1, t2, p);
  28.   }
  29.   t1 = n_mulmod2_preinv(l.i, r.r, p, pinv);
  30.   t2 = n_mulmod2_preinv(l.r, r.i, p, pinv);
  31.   dst.i = n_addmod(t1, t2, p);
  32.   return dst;
  33. }

  34. #define spCount 32
  35. uint64_t sPrime[spCount] =
  36. {
  37.    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
  38.   59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131
  39. };

  40. int64_t selectParam(uint64_t p)
  41. {
  42.   if (p % 4 == 3)
  43.     return -1;
  44.   if (p % 8 == 5)
  45.     return 2;
  46.   for (int i = 1; i < spCount; i ++)
  47.     if (n_jacobi(sPrime[i], p) == -1)
  48.       return sPrime[i];
  49.   uint64_t t = sPrime[spCount-1];
  50.   do
  51.   {
  52.     t ++;
  53.     t = n_nextprime(t, 1);
  54.   } while (n_jacobi(t, p) != -1);
  55.   return t;
  56. }

  57. bool isprime(uint64_t p)
  58. {
  59.   //printf("test %lu", p);
  60.   if (p == 1093 * 1093 || p == 3511 * 3511)
  61.     return false;
  62.   int64_t c = selectParam(p);
  63.   //printf(" c=%ld\n", c);
  64.   QF a, b;
  65.   a.r = 1; a.i = 0;
  66.   uint64_t r = (c == -1 || c == 2) ? 2 : 1;
  67.   b.r = r;
  68.   b.i = 1;
  69.   uint64_t t = p;
  70.   uint64_t pinv = n_preinvert_limb(p);
  71.   while (t > 0)
  72.   {
  73.     if (t & 1 == 1)
  74.       a = qfmul(a, b, c, p, pinv);
  75.     b = qfmul(b, b, c, p, pinv);
  76.     t >>= 1;
  77.   }
  78.   return (a.r == r && a.i == p - 1) ? true : false;
  79. }

  80. void test()
  81. {
  82.   printf("自检...\n");
  83.   for (int i = 1; i < spCount; i ++)
  84.     if (!isprime(sPrime[i]))
  85.       printf("检测错误: %lu\n", sPrime[i]);
  86.   printf("自检结束\n");
  87. }

  88. int main()
  89. {
  90.   uint64_t p, cnt = 0, tst = 0;
  91.   //test();
  92.   FILE* sprp2File = fopen("2-SPRP-2-to-64.txt", "r");
  93.   if (!sprp2File)
  94.   {
  95.     perror("文件2-SPRP-2-to-64.txt不存在");
  96.     return EXIT_FAILURE;
  97.   }
  98.   char line[32];
  99.   while (fgets(line, 32, sprp2File) != NULL)
  100.   {
  101.     char* end;
  102.     p = strtoull(line, &end, 10);
  103.     if (isprime(p))
  104.       cnt ++;
  105.     //tst ++; if (tst >= 10) break;
  106.   }

  107.   fclose(sprp2File);
  108.   printf("测试失败次数: %lu\n", cnt);
  109.   return 0;
  110. }
复制代码


BPSW版本
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <flint/ulong_extras.h>

  6. typedef struct
  7. {
  8.   int64_t D, P, Q;
  9. } BPSWParam;

  10. typedef struct
  11. {
  12.   uint64_t U, V, Q;
  13. } lucasItem;

  14. void showParam(BPSWParam param, uint64_t n)
  15. {
  16.   printf("%lu的lucas测试参数: D=%ld, P=%ld, Q=%ld\n", n, param.D, param.P, param.Q);
  17. }

  18. void showItem(char* pos, char * s, lucasItem item, uint64_t n)
  19. {
  20.   printf("当前循环%s-%s: %lu的lucas测试当前值: U=%lu, V=%lu, Q=%lu\n", pos, s, n, item.U, item.V, item.Q);
  21. }

  22. //U(2k)=U(k)*V(k), V(2k)=V(k)^2-2Q(k), Q(2k)=Q(k)^2
  23. void lucasDouble(char* pos, lucasItem* I, uint64_t n, uint64_t ninv)
  24. {
  25.   I->U = n_mulmod2_preinv(I->U, I->V, n, ninv);
  26.   I->V = n_mulmod2_preinv(I->V, I->V, n, ninv);
  27.   uint64_t t = n_addmod(I->Q, I->Q, n);
  28.   I->V = n_submod(I->V, t, n);
  29.   I->Q = n_mulmod2_preinv(I->Q, I->Q, n, ninv);
  30.   //showItem(pos, "x2", *I, n);
  31. }

  32. //U(k+1)=(PU(k)+V(K))/2, V(K+1)=(DU(K)+PV(K))/2, Q(K+1)=Q(K)Q
  33. void lucasNext(char* pos, lucasItem* I, BPSWParam param, uint64_t n, uint64_t half_n, uint64_t ninv)
  34. {
  35.   uint64_t t = I->U;
  36.   I->U = n_mulmod2_preinv(param.P, I->U, n, ninv);
  37.   I->U = n_addmod(I->U, I->V, n);
  38.   I->U = (I->U&1==1)? (n - (n - I->U) >> 1) : (I->U >> 1);
  39.   uint64_t t1 = n_mulmod2_preinv(param.P, I->V, n, ninv);
  40.   uint64_t t2 = n_mulmod2_preinv(param.D, t, n, ninv);
  41.   I->V = n_addmod(t1, t2, n);
  42.   I->V = (I->V&1==1)? (n - (n - I->V) >> 1) : (I->V >> 1);
  43.   I->Q = n_mulmod2_preinv(I->Q, param.Q, n, ninv);  
  44.   //showItem(pos, "+1", *I, n);
  45. }

  46. BPSWParam selectParam(uint64_t n)
  47. {
  48.   int64_t d = 5, p, q, delta = 2;
  49.   while (n_jacobi(d, n) != -1)
  50.   {
  51.     delta = - delta;
  52.     d = delta - d;
  53.   }
  54.   p = 1;
  55.   q = (1 - d) >> 2;
  56.   if (q == - 1)
  57.     d = p = q = 5;
  58.   //printf("%lu的lucas测试参数: D=%ld, P=%ld, Q=%ld\n", n, d, p, q);
  59.   if (d < 0)
  60.     d = n - (-d) % n;
  61.   if (q < 0)
  62.     q = n - (-q) % n;   
  63.   BPSWParam param = {d%n, p, q%n};
  64.   //showParam(param, n);
  65.   return param;
  66. }

  67. bool strongLucasTest(uint64_t n)
  68. {
  69.   if (n == 1093 * 1093 || n == 3511 * 3511)
  70.     return false;
  71.   BPSWParam param = selectParam( n );
  72.   uint64_t ninv =  n_preinvert_limb( n );
  73.   uint64_t m = n + 1;
  74.   uint64_t half_n = m >> 1;
  75.   int64_t k = __builtin_ctzll( m );
  76.   m >>= k;
  77.   lucasItem item = {0, 2, 1};
  78.   int64_t tm = __builtin_clzll(m);
  79.   tm = sizeof(m)*8 - tm - 1;
  80.   uint64_t t = 1 << tm;
  81.   //printf("%lu=%lu*2^%lu, tm=%ld, t=%lu, half_n=%lu\n", n+1, m, k, tm, t, half_n);
  82.   for (int64_t i = tm; i >= 0; i --)
  83.   {
  84.     lucasDouble("1", &item, n, ninv);  
  85.     if (m&t == t)
  86.       lucasNext("1", &item, param, n, half_n, ninv);
  87.     m >>= 1;
  88.     t >>= 1;
  89.   }
  90.   if (item.U == 0)
  91.     return true;
  92.   for (int64_t i = 0; i < k; i ++)
  93.     if (item.V != 0)
  94.     {
  95.       item.V = n_mulmod2_preinv(item.V, item.V, n, ninv);
  96.       uint64_t t = n_addmod(item.Q, item.Q, n);
  97.       item.V = n_submod(item.V, t, n);
  98.       item.Q = n_mulmod2_preinv(item.Q, item.Q, n, ninv);
  99.       //showItem("2", "x2", item, n);
  100.     }
  101.     else
  102.       return true;
  103.   return false;
  104. }

  105. #define testCount 16

  106. uint64_t testSet[testCount] = { 3, 5, 7, 17,
  107.                                 33, 79, 101, 111,
  108.                                 127, 2047, 5459, 5777,
  109.                                 10877, 58519, 65535, 65537};

  110. void test()
  111. {
  112.   printf("自检...\n");
  113.   printf("U(2k)=U(k)*V(k), V(2k)=V(k)^2-2Q(k), Q(2k)=Q(k)^2\n");
  114.   printf("U(k+1)=(PU(k)+V(K))/2, V(K+1)=(DU(K)+PV(K))/2, Q(K+1)=Q(K)Q\n");
  115.   for (int i = 0; i < testCount; i ++)
  116.     if (strongLucasTest(testSet[i]))
  117.       printf("素数: %lu\n", testSet[i]);
  118.     else
  119.       printf("合数: %lu\n", testSet[i]);
  120.   printf("自检结束\n");
  121. }

  122. int main( void )
  123. {
  124.   uint64_t n, cnt = 0, tst = 0;
  125.   //test(); return 1;
  126.   FILE* sprp2File = fopen("2-SPRP-2-to-64.txt", "r");
  127.   if (!sprp2File)
  128.   {
  129.     perror("文件2-SPRP-2-to-64.txt不存在");
  130.     return EXIT_FAILURE;
  131.   }
  132.   char line[32];
  133.   while (fgets(line, 32, sprp2File) != NULL)
  134.   {
  135.     char* end;
  136.     n = strtoull(line, &end, 10);
  137.     if (strongLucasTest(n))
  138.       cnt ++;
  139.     //tst ++; if (tst >= 1000000) break;
  140.   }

  141.   fclose(sprp2File);
  142.   printf("测试失败次数: %lu\n", cnt);

  143.   return 0;
  144. }

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2023-5-3 20:00:11 | 显示全部楼层
先在WSL2中测试的,两个程序都在7m左右
后来用msys2测试,发现执行时间大大降低
QFT:    1m21s
BPSW: 1m11s
放到实际linux执行发现,msys2的执行时间是正确的

实际代码,BPSW比QFT复杂很多
但是QFT要测试整个的log(n)次
BPSW类似米勒罗宾测试,测试次数小于log(n)
BPSW较少的测试次数和较复杂的测试函数,
综合起来,执行时间略少于QFT

但是,QFT有个优势就是,单独执行,
对非平方数 n ,2^64内,只要通过测试,
必然是素数,不存在伪素数,
BPSW对应的强 lucas 测试,存在伪素数

点评

nyy
独创独创独创!郭先强独创!  发表于 2023-6-5 16:26
nyy
https://bbs.emath.ac.cn/forum.php?mod=redirect&goto=findpost&ptid=16936&pid=81205&fromuid=14149 这个测试算法第六楼的链接,比你那个链接要好一点点!  发表于 2023-5-5 09:20
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-5-4 09:40:10 | 显示全部楼层
代码没语法高亮,好不爽呀!

点评

复制到VS Code里看  发表于 2023-5-4 09:56
nyy
论坛不能显示代码的语法高亮,真不爽!  发表于 2023-5-4 09:40
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2023-5-4 10:22:15 | 显示全部楼层
QFT增加一次基3强伪素数测试后

  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <flint/ulong_extras.h>

  6. typedef struct
  7. {
  8.   uint64_t r;
  9.   uint64_t i;
  10. } QF;

  11. QF qfmul(QF l, QF r, int64_t c, uint64_t p, uint64_t pinv)
  12. {
  13.   QF dst;
  14.   uint64_t t1 = n_mulmod2_preinv(l.r, r.r, p, pinv);
  15.   uint64_t t2 = n_mulmod2_preinv(l.i, r.i, p, pinv);
  16.   switch (c)
  17.   {
  18.     case -1:
  19.       dst.r = n_submod(t1, t2, p);
  20.       break;
  21.     case 2:
  22.       t2 = n_addmod(t2, t2, p);
  23.       dst.r = n_addmod(t1, t2, p);
  24.       break;
  25.     default:
  26.       t2 = n_mulmod2_preinv(t2, c, p, pinv);
  27.       dst.r = n_addmod(t1, t2, p);
  28.   }
  29.   t1 = n_mulmod2_preinv(l.i, r.r, p, pinv);
  30.   t2 = n_mulmod2_preinv(l.r, r.i, p, pinv);
  31.   dst.i = n_addmod(t1, t2, p);
  32.   return dst;
  33. }

  34. #define spCount 32
  35. uint64_t sPrime[spCount] =
  36. {
  37.    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
  38.   59, 61, 67, 71, 73, 79, 83, 89, 97,101,103,107,109,113,127,131
  39. };

  40. int64_t selectParam(uint64_t p)
  41. {
  42.   if (p % 4 == 3)
  43.     return -1;
  44.   if (p % 8 == 5)
  45.     return 2;
  46.   for (int i = 1; i < spCount; i ++)
  47.     if (n_jacobi(sPrime[i], p) == -1)
  48.       return sPrime[i];
  49.   uint64_t t = sPrime[spCount-1];
  50.   do
  51.   {
  52.     t ++;
  53.     t = n_nextprime(t, 1);
  54.   } while (n_jacobi(t, p) != -1);
  55.   return t;
  56. }

  57. bool quadraticFrobeniusTest(uint64_t p)
  58. {
  59.   uint64_t pinv = n_preinvert_limb(p);
  60.   int64_t k = __builtin_ctzll(p-1);
  61.   uint64_t d = (p-1) >> k;
  62.   if (!n_is_strong_probabprime2_preinv(p, pinv, 3, d))
  63.     return false;
  64.   int64_t c = selectParam(p);
  65.   uint64_t r = (c == -1 || c == 2) ? 2 : 1;
  66.   QF a = {1, 0}, b = {r, 1};
  67.   uint64_t t = p;
  68.   while (t > 0)
  69.   {
  70.     if (t&1==1)
  71.       a = qfmul(a, b, c, p, pinv);
  72.     b = qfmul(b, b, c, p, pinv);
  73.     t>>=1;
  74.   }
  75.   return (a.r == r && a.i == p - 1) ? true : false;
  76. }

  77. void test()
  78. {
  79.   printf("自检...\n");
  80.   for (int i = 1; i < spCount; i ++)
  81.     if (!quadraticFrobeniusTest(sPrime[i]))
  82.       printf("检测错误: %lu\n", sPrime[i]);
  83.   printf("自检结束\n");
  84. }

  85. int main()
  86. {
  87.   uint64_t p, cnt = 0, tst = 0;
  88.   //test();
  89.   FILE* sprp2File = fopen("2-SPRP-2-to-64.txt", "r");
  90.   if (!sprp2File)
  91.   {
  92.     perror("文件2-SPRP-2-to-64.txt不存在");
  93.     return EXIT_FAILURE;
  94.   }
  95.   char line[32];
  96.   while (fgets(line, 32, sprp2File) != NULL)
  97.   {
  98.     char* end;
  99.     p = strtoull(line, &end, 10);
  100.     if (quadraticFrobeniusTest(p))
  101.       cnt ++;
  102.     tst ++;
  103.   }

  104.   fclose(sprp2File);
  105.   printf("test: %lu, failed: %lu\n", tst, cnt);
  106.   return 0;
  107. }

复制代码


总测试数字31894014,执行时间23.027s
去掉QFT部分,只测试基3强伪素数,执行时间18.996s,
有1501720个合数通过测试
SPSPTime=18996ms/3189.4014万=5.956ms/万
QFTTime=(23027-18996)ms/150.1720万=26.843ms/万
1次QFT约等于4.5次SPSP

当增加1次SPSP测试后,剩余未通过的合数比例低于1/5时,用QFT测试是合算的
实测再增加一次基5强伪素数测试,执行时间降低到19.768s
再增加基7强伪素数测试,降低的时间有限了
因此理想的基于QFT的测试,先测试基2,3,5的强伪素数测试,再做QFT测试,是最优化的选择
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2023-5-4 10:47:21 | 显示全部楼层
同样增加一次基3强伪素数测试的BPSW

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <stdbool.h>
  5. #include <flint/ulong_extras.h>

  6. typedef struct
  7. {
  8.   int64_t D, P, Q;
  9. } BPSWParam;

  10. typedef struct
  11. {
  12.   uint64_t U, V, Q;
  13. } lucasItem;

  14. void showParam(BPSWParam param, uint64_t n)
  15. {
  16.   printf("%lu的lucas测试参数: D=%ld, P=%ld, Q=%ld\n", n, param.D, param.P, param.Q);
  17. }

  18. void showItem(char* pos, char * s, lucasItem item, uint64_t n)
  19. {
  20.   printf("当前循环%s-%s: %lu的lucas测试当前值: U=%lu, V=%lu, Q=%lu\n", pos, s, n, item.U, item.V, item.Q);
  21. }

  22. //U(2k)=U(k)*V(k), V(2k)=V(k)^2-2Q(k), Q(2k)=Q(k)^2
  23. void lucasDouble(lucasItem* I, uint64_t n, uint64_t ninv)
  24. {
  25.   I->U = n_mulmod2_preinv(I->U, I->V, n, ninv);
  26.   I->V = n_mulmod2_preinv(I->V, I->V, n, ninv);
  27.   uint64_t t = n_addmod(I->Q, I->Q, n);
  28.   I->V = n_submod(I->V, t, n);
  29.   I->Q = n_mulmod2_preinv(I->Q, I->Q, n, ninv);
  30. }

  31. //U(k+1)=(PU(k)+V(K))/2, V(K+1)=(DU(K)+PV(K))/2, Q(K+1)=Q(K)Q
  32. void lucasNext(lucasItem* I, BPSWParam param, uint64_t n, uint64_t ninv)
  33. {
  34.   uint64_t t = I->U;
  35.   I->U = n_mulmod2_preinv(param.P, I->U, n, ninv);
  36.   I->U = n_addmod(I->U, I->V, n);
  37.   I->U = (I->U&1==1)? (n - (n - I->U) >> 1) : (I->U >> 1);
  38.   uint64_t t1 = n_mulmod2_preinv(param.P, I->V, n, ninv);
  39.   uint64_t t2 = n_mulmod2_preinv(param.D, t, n, ninv);
  40.   I->V = n_addmod(t1, t2, n);
  41.   I->V = (I->V&1==1)? (n - (n - I->V) >> 1) : (I->V >> 1);
  42.   I->Q = n_mulmod2_preinv(I->Q, param.Q, n, ninv);  
  43. }

  44. BPSWParam selectParam(uint64_t n)
  45. {
  46.   int64_t d = 5, p, q, delta = 2;
  47.   while (n_jacobi(d, n) != -1)
  48.   {
  49.     delta = - delta;
  50.     d = delta - d;
  51.   }
  52.   p = 1;
  53.   q = (1 - d) >> 2;
  54.   if (q == - 1)
  55.     d = p = q = 5;
  56.   //printf("%lu的lucas测试参数: D=%ld, P=%ld, Q=%ld\n", n, d, p, q);
  57.   if (d < 0)
  58.     d = n - (-d) % n;
  59.   if (q < 0)
  60.     q = n - (-q) % n;   
  61.   BPSWParam param = {d%n, p, q%n};
  62.   //showParam(param, n);
  63.   return param;
  64. }

  65. bool strongLucasTest(uint64_t n)
  66. {
  67.   uint64_t ninv = n_preinvert_limb(n);
  68.   int64_t k = __builtin_ctzll(n-1);
  69.   uint64_t d = (n-1) >> k;
  70.   if (!n_is_strong_probabprime2_preinv(n, ninv, 3, d))
  71.     return false;
  72.   BPSWParam param = selectParam( n );
  73.   uint64_t m = n + 1;
  74.   k = __builtin_ctzll(m);
  75.   m >>= k;
  76.   lucasItem item = {0, 2, 1};
  77.   int64_t tm = __builtin_clzll(m);
  78.   tm = sizeof(m)*8 - tm - 1;
  79.   uint64_t t = 1 << tm;
  80.   //printf("%lu=%lu*2^%lu, tm=%ld, t=%lu, half_n=%lu\n", n+1, m, k, tm, t, half_n);
  81.   for (int64_t i = tm; i >= 0; i --)
  82.   {
  83.     lucasDouble(&item, n, ninv);  
  84.     if (m&t == t)
  85.       lucasNext(&item, param, n, ninv);
  86.     m >>= 1;
  87.     t >>= 1;
  88.   }
  89.   if (item.U == 0)
  90.     return true;
  91.   for (int64_t i = 0; i < k; i ++)
  92.     if (item.V != 0)
  93.     {
  94.       item.V = n_mulmod2_preinv(item.V, item.V, n, ninv);
  95.       uint64_t t = n_addmod(item.Q, item.Q, n);
  96.       item.V = n_submod(item.V, t, n);
  97.       item.Q = n_mulmod2_preinv(item.Q, item.Q, n, ninv);
  98.     }
  99.     else
  100.       return true;
  101.   return false;
  102. }

  103. #define testCount 16

  104. uint64_t testSet[testCount] = { 3, 5, 7, 17,
  105.                                 33, 79, 101, 111,
  106.                                 127, 2047, 5459, 5777,
  107.                                 10877, 58519, 65535, 65537};

  108. void test()
  109. {
  110.   printf("自检...\n");
  111.   printf("U(2k)=U(k)*V(k), V(2k)=V(k)^2-2Q(k), Q(2k)=Q(k)^2\n");
  112.   printf("U(k+1)=(PU(k)+V(K))/2, V(K+1)=(DU(K)+PV(K))/2, Q(K+1)=Q(K)Q\n");
  113.   for (int i = 0; i < testCount; i ++)
  114.     if (strongLucasTest(testSet[i]))
  115.       printf("素数: %lu\n", testSet[i]);
  116.     else
  117.       printf("合数: %lu\n", testSet[i]);
  118.   printf("自检结束\n");
  119. }

  120. int main( void )
  121. {
  122.   uint64_t n, cnt = 0, tst = 0;
  123.   //test(); return 1;
  124.   FILE* sprp2File = fopen("2-SPRP-2-to-64.txt", "r");
  125.   if (!sprp2File)
  126.   {
  127.     perror("文件2-SPRP-2-to-64.txt不存在");
  128.     return EXIT_FAILURE;
  129.   }
  130.   char line[32];
  131.   while (fgets(line, 32, sprp2File) != NULL)
  132.   {
  133.     char* end;
  134.     n = strtoull(line, &end, 10);
  135.     if (strongLucasTest(n))
  136.       cnt ++;
  137.     //tst ++; if (tst >= 1000000) break;
  138.   }

  139.   fclose(sprp2File);
  140.   printf("测试失败次数: %lu\n", cnt);

  141.   return 0;
  142. }
复制代码


总测试数字31894014,执行时间22.397s
去掉SLPSP测试部分,只测试基3 SPSP,执行时间18.973s,
有1501720个合数通过测试
SPSPTime=18973ms/3189.4014万=5.949ms/万
SLPSPTime=(22397-18973)ms/150.1720万=22.801ms/万
1次SLPSP测试约等于3.8次SPSP测试

当增加1次SPSP测试后,剩余未通过的合数比例低于1/4时,用BPSW的SLPSP测试是合算的
按照上面的思路,再增加一次基5的强伪素数测试,共19.807s, 时间也降低明显,
即BPSW,先执行基2,3,5的强伪素数测试,再做强lucas测试,是最优化的选择


毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-5-4 11:00:44 | 显示全部楼层
无心人 发表于 2023-5-4 10:47
同样增加一次基3强伪素数测试的BPSW

lucas U  lucas V都测试了吗?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-5-4 11:06:49 | 显示全部楼层
无心人 发表于 2023-5-4 10:47
同样增加一次基3强伪素数测试的BPSW

我当初问***他素数判定的实现算法,***把他的算法当成宝贝,还舍不得告诉我。
没想到你也能实现这个算法,要是早知道,我就问你了。
只可惜你在论坛上发出来之前,我已经学会了BPSW的实现算法,
我从GitHub上搜索到相关的代码,然后研究透的!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2023-5-4 11:44:50 | 显示全部楼层
作为比较,贴上flint自带素性测试的代码,执行时间60.261s
考虑我代码少做一次基2测试,加上基2测试,以QFT为例,是30.948秒,

  1. #include <stdbool.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <flint/ulong_extras.h>

  6. int main()
  7. {
  8.   uint64_t p, cnt = 0, tst = 0;
  9.   //test();
  10.   FILE* sprp2File = fopen("2-SPRP-2-to-64.txt", "r");
  11.   if (!sprp2File)
  12.   {
  13.     perror("文件2-SPRP-2-to-64.txt不存在");
  14.     return EXIT_FAILURE;
  15.   }
  16.   char line[32];
  17.   while (fgets(line, 32, sprp2File) != NULL)
  18.   {
  19.     char* end;
  20.     p = strtoull(line, &end, 10);
  21.     if (n_is_prime(p))
  22.       cnt ++;
  23.     tst ++;
  24.   }

  25.   fclose(sprp2File);
  26.   printf("test: %lu, failed: %lu\n", tst, cnt);
  27.   return 0;
  28. }

复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-5-4 13:30:53 | 显示全部楼层
无心人 发表于 2023-5-4 11:44
作为比较,贴上flint自带素性测试的代码,执行时间60.261s
考虑我代码少做一次基2测试,加上基2测试,以QF ...

你的伪素数文件,能上传共享一下不?
要那种以2为底的强伪素数!

点评

已经贴出来了  发表于 2023-5-4 18:02
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2023-5-4 18:53:02 | 显示全部楼层
无心人 发表于 2023-5-4 11:44
作为比较,贴上flint自带素性测试的代码,执行时间60.261s
考虑我代码少做一次基2测试,加上基2测试,以QF ...

只要以2为底的强伪素数!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-19 16:48 , Processed in 0.048889 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表