无心人 发表于 2016-1-11 15:14:14

基于2^64以下的以2为底的伪素数的数据分析

在下面网站找到了所有的低于2^64的以2为底伪素数PSP(2)的表
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html

下载后进行了一些分析,详细结果,后面列出来

无心人 发表于 2016-1-11 15:27:02

下载的是第3项,包含Carmichael数跟强伪素数分类,和因子分解的部分
首先是统计信息,共118968379个, 其中强伪素数31894015个; Carmichael数4279356个, 既是Carmichael数又是强伪素数的32596个

mathematica 发表于 2016-1-12 15:34:27

可以给gxqcn用

无心人 发表于 2016-1-12 16:53:35

对这些数据进行了强伪素数检测,首先过滤出31894016组base 2的强伪素数,
再进行base 3, 5, 7的单独或者组合测试,结果如下,数字代表通过测试的强伪素数数量
Total: 31894016
   base 2, 3 -- 1501720
       base 2, 3, 5 -- 131157
         base 2, 3, 5, 7 -- 16826
       base 2, 3, 7 -- 171359
   base 2, 5 -- 1330740
       base 2, 5, 7 -- 126999
   base 2, 7 -- 1363175

无心人 发表于 2016-1-12 16:55:27

过滤出强伪素数的代码
#include <stdio.h>
#include <stdlib.h>


int main( void )
{
FILE * psp2, *S64;
char buf;
int i=0;
if ((psp2=fopen("psp2.txt", "rt"))!=NULL)
    if ((S64 = fopen("S64.txt", "wt"))!=NULL)
    {
      while (!feof(psp2))
      {
      fgets(buf, 256, psp2);
      if (buf == 'S')
      {
          fputs(buf, S64);
          i ++;
          if (i >= 1000)
          {
            i=0;
            fflush(S64);
          }
      }
      }
    }
fclose(psp2);
fclose(S64);
}

无心人 发表于 2016-1-12 16:59:48

基于linux 64位汇编的测试代码
m64.s
.data
.text
.global powMod, oddDivisorOf, strongPseudoPrimeTest

powMod:
#return rax = rdi ^ rsi mod rdx
#unsigned long long powMod(unsigned long long n, unsigned long long p, unsigned long long m)
        movq %rdi, %rax
        movq %rdx, %rcx
        movq $1, %r8
        movq $1, %r9
powModStart:
        cmpq %r9, %rsi
        jbepowModExit
        testq %r9, %rsi
        je powModSquare
        movq %rax, %rdi
        mulq %r8
        divq %rcx
        movq %rdi, %rax
        movq %rdx, %r8
powModSquare:
        mulq %rax
        divq %rcx
        movq %rdx, %rax
        shrq $1, %rsi
        jmp powModStart
powModExit:
        mulq %r8
        divq %rcx
        movq %rdx, %rax
        ret

oddDivisorOf:
#rdi = 2^n * rax, rax is odd number
        bsf %rdi, %rcx
        movq %rdi, %rax
        shrq %cl, %rax
        testq $1, %rdi
        cmovne %rdi, %rax
        ret

strongPseudoPrimeTest:
#retrun rdi base rsi Strong PseudoPrime Test
        movl $0, %eax
        testq $1, %rdi
        je strongPseudoPrimeTestExit
        movq %rdi, %xmm0
        subq $1, %rdi
        bsf %rdi, %rcx
        movd %ecx, %xmm1
        shrq %cl, %rdi
      xchg %rsi, %rdi
        movq %xmm0, %rdx
        call powMod
        cmpq $1, %rax
        je strongPseudoPrimeTestExit
        movd %xmm1, %ecx
        movq %xmm0, %r8
        movq %xmm0, %r9
        subq $1, %r8
        cmpq %r8, %rax
        je strongPseudoPrimeTestCheck
        subl $1, %ecx
        cmpl $0, %ecx
        je strongPseudoPrimeTestCheck
strongPseudoPrimeTestLoop:
        mulq %rax
        divq %r9
        movq %rdx, %rax
        cmpq %r8, %rax
        je strongPseudoPrimeTestCheck
        subl $1, %ecx
        jne strongPseudoPrimeTestLoop
strongPseudoPrimeTestCheck:
        movq $1, %rcx
        movq $0, %rdx
        cmpq %r8, %rax
        cmove %rcx, %rax
        cmovne %rdx, %rax
strongPseudoPrimeTestExit:
        ret

S2.c
#include <stdio.h>
#include <stdlib.h>

extern int strongPseudoPrimeTest(unsigned long long n, unsigned long long base);

int main( void )
{
FILE *S64, *S23, *S25, *S27, *S235, *S237, *S257, *S2357;
char buf, C;
int C64=0, C23=0, C25=0, C27=0, C235=0, C237=0, C257=0, C2357=0;
int P3, P5, P7;
unsigned long long p;
if ((S64=fopen("S64.txt", "rt"))!=NULL)
{
    if ((S23 = fopen("S23.txt", "wt"))!=NULL)
    if ((S25 = fopen("S25.txt", "wt"))!=NULL)
    if ((S27 = fopen("S27.txt", "wt"))!=NULL)
    if ((S235 = fopen("S235.txt", "wt"))!=NULL)
    if ((S237 = fopen("S237.txt", "wt"))!=NULL)
    if ((S257 = fopen("S257.txt", "wt"))!=NULL)
    if ((S2357 = fopen("S2357.txt", "wt"))!=NULL)
    {
      while (!feof(S64))
      {
      fgets(buf, 256, S64);
        C64++;
        buf=' ';
        sscanf(buf+2, "%llu", &p);
        P3=strongPseudoPrimeTest(p, 3);
        P5=strongPseudoPrimeTest(p, 5);
        P7=strongPseudoPrimeTest(p, 7);
        if (P3)
        {
                C23++;
                fputs(buf, S23);

                if (P5)
                {
                        C235++;
                        fputs(buf, S235);

                        if (P7)
                        {
                                C2357++;
                                fputs(buf, S2357);
                        }
                }

                if (P7)
                {
                        C237++;
                        fputs(buf, S237);
                }
        }

        if (P5)
        {
                C25++;
                fputs(buf, S25);

                if (P7)
                {
                        C257++;
                        fputs(buf, S257);
                }
        }

        if (P7)
        {
                C27++;
                fputs(buf, S27);
        }

      }
    }
}
fclose(S64);
fclose(S23);
fclose(S25);
fclose(S27);
fclose(S235);
fclose(S237);
fclose(S257);
fclose(S2357);
printf("Total: %llu\n", C64);
printf("   base 2, 3 -- %llu\n", C23);
printf("       base 2, 3, 5 -- %llu\n", C235);
printf("         base 2, 3, 5, 7 -- %llu\n", C2357);
printf("       base 2, 3, 7 -- %llu\n", C237);
printf("   base 2, 5 -- %llu\n", C25);
printf("       base 2, 5, 7 -- %llu\n", C257);
printf("   base 2, 7 -- %llu\n", C27);
return 0;
}


linux下编译命令
gcc -O3 -o S2 S2.c m64.s

粗略的算了下,每次测试大概7100时钟左右,不知道是否存在优化的可能

mathematica 发表于 2019-2-25 08:34:21

无心人 发表于 2016-1-12 16:53
对这些数据进行了强伪素数检测,首先过滤出31894016组base 2的强伪素数,
再进行base 3, 5, 7的单独或者组 ...

你真棒,那么大的数据都能搞得动!
页: [1]
查看完整版本: 基于2^64以下的以2为底的伪素数的数据分析