/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC C C C COMPUTE MERTENS FUNCTION (similar to E. Kuznetsov's algorithm) C C 01/27/16 (DKC) C C C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/ #include <stdio.h> #include <math.h> #include "table2.h" // 17984 primes less than 200000 extern char *malloc(); // compute Mobius function int newmob(unsigned int a, unsigned int b, int *out, unsigned int *table, unsigned int tsize) { unsigned int i,count,p,ps,beg,rem; int t; count=b-a; for (i=0; i<count; i++) out[i]=1; for (i=0; i<tsize; i++) { p=table[i]; ps=p*p; if (ps>b) goto askip; rem=a-(a/ps)*ps; if (rem!=0) beg=ps-rem; else beg=0; while (beg<count) { out[beg]=0; beg=beg+ps; } rem=a-(a/p)*p; if (rem!=0) beg=p-rem; else beg=0; while (beg<count) { out[beg]=-out[beg]*p; beg=beg+p; } } return(-1); askip: for (i=0; i<count; i++) { if (out[i]==0) continue; t=out[i]; if (t<0) t=-t; if ((unsigned int)t<(i+a)) out[i]=-out[i]; } for (i=0; i<count; i++) { if (out[i]==0) continue; if (out[i]>0) out[i]=1; else out[i]=-1; } return(1); } // compute partial sums of Mertens function int newmert(unsigned int s, unsigned int x, int *M) { unsigned int i,t,delta; int sum; t=(unsigned int)sqrt((double)x); t=t+2; if (s>(x/t)) return(0x7fffffff); sum=0; for (i=s; i<=(x/t); i++) sum=sum+M[x/i-1]; for (i=1; i<t; i++) { // suitable for implementation on a GPU delta=x/i-x/(i+1); sum=sum+delta*M[i-1]; } return(sum); } // unsigned int maxx=100000; // size of Mertens number look-up table (multiple of 1000) unsigned int tmpmax=2000; // greater than or equal to 1000 unsigned int tsize=17984; // size of prime look-up table void main() { unsigned int i,j,k,index,ta,tb,count,x,L,start; int T[1000]; int t,sum; char *m; int *M,*temp; FILE *Outfp; Outfp = fopen("out19g.dat","w"); temp=(int*) malloc(4004); if (temp==NULL) { printf("not enough memory \n"); return; } m=(char*) malloc(maxx+1); if (m==NULL) { printf("not enough memory \n"); return; } M=(int*) malloc(4*(maxx+1)); if (M==NULL) { printf("not enough memory \n"); return; } // printf("computing Mobius function \n"); count=maxx; count=count/1000; index=0; ta=1; tb=1001; for (i=0; i<count; i++) { t=newmob(ta,tb,temp,table,tsize); if (t!=1) { printf("error \n"); goto zskip; } ta=tb; tb=tb+1000; for (j=0; j<1000; j++) M[j+index]=temp[j]; index=index+1000; } // // compute Mertens function // printf("computing Mertens function \n"); m[0]=(char)M[0]; for (i=1; i<=maxx; i++) { m[i]=(char)M[i]; M[i]=M[i-1]+M[i]; } // // compute Mertens function // printf("comparing results \n"); for (i=(tmpmax-1000); i<=maxx; i++) { x=i; if (x<=tmpmax) { t=newmert(2,x, M); if (t==0x7fffffff) { printf(" s>x/t \n"); goto zskip; } t=1-t; } else { L=x/tmpmax; if (L>1000) { printf("not enough memory: 1 \n"); goto zskip; } for (j=1; j<=L; j++) { start=(x/j)/tmpmax+1; t=newmert(start,x/j,M); if (t==0x7fffffff) { printf(" s>x/t \n"); goto zskip; } T[j-1]=1-t; } for (j=(L/2); j>=1; j--) { sum=0; for (k=1; k<=(L/j-1); k++) sum=sum+T[(k+1)*j-1]; T[j-1]=T[j-1]-sum; } t=T[0]; } if (t!=M[x-1]) { printf("error: x=%d t=%d, M[x-1]=%d \n",x,t,M[x-1]); goto zskip; } if (i==(i/10000)*10000) printf("x=%d, M(x)=%d \n",i,t); } zskip: fclose(Outfp); return; }