/*****************************************************************************/ /* */ /* COUNT PAIRS OF CONSECUTIVE ROOTS OF X**(P-1)=Y(MOD P*P), Y**P=1(MOD P*P) */ /* 02/14/07 (dkc) */ /* */ /*****************************************************************************/ #include <stdio.h> #include <math.h> #include "input.h" void div64_32(unsigned int *dividend, unsigned int *quotient, unsigned int divisor); void mul32_32(unsigned int a0, unsigned int m0, unsigned int *product); void sub64(unsigned int *a, unsigned int *b); int main () { unsigned int g,j,k,j1,h,jh,i,nq,kk,sum,S[2],T[2]; unsigned int js,jsh,jj,m[5000],p[5000]; int q,f,ilb[5001],irb[5001]; unsigned int s[101],t[101]; unsigned int l[5000]; FILE *Outfp; Outfp = fopen("out1.dat","w"); /***********************/ /* clear histograms */ /***********************/ for (i=0; i<101; i++) { s[i]=0; t[i]=0; } /*************************************/ /* load primes and primitive roots */ /*************************************/ for (g=0; g<insize; g++) { j=input[2*g]; // p (prime) if (j>10000) break; k=input[2*g+1]; // primitive root j1=j-1; // p-1 js=j*j; // p*p jsh=(js-1)/2; // (p*p-1)/2 jh=j1/2; // (p-1)/2 /**********************************/ /* compute least residue of k**p */ /**********************************/ jj=k; for (i=1; i<j; i++) { mul32_32(jj, k, S); div64_32(S, T, js); mul32_32(T[1], js, T); sub64(S, T); jj=T[1]; } if (jj>jsh) jj=js-jj; l[0]=jj; /*****************************************/ /* compute roots of x**(p-1)=1(mod p*p) */ /*****************************************/ for (i=1; i<jh; i++) { mul32_32(l[i-1], jj, S); div64_32(S, T, js); mul32_32(T[1], js, T); sub64(S, T); l[i]=T[1]; if (l[i]>jsh) l[i]=js-l[i]; } sum=0; for (i=0; i<j; i++) { /****************************************/ /* compute roots of x**(p-1)=y(mod p*p) */ /****************************************/ kk=i*j+1; // y if (kk>jsh) kk=js-kk; for (h=0; h<jh; h++) { mul32_32(l[h], kk, S); div64_32(S, T, js); mul32_32(T[1], js, T); sub64(S, T); m[h]=T[1]; if (m[h]>jsh) m[h]=js-m[h]; } if ((i==0)&&(m[jh-1]!=1)) { printf("error p=%d r=%d %d \n",j,k,m[jh-1]); goto zskip; } /*****************************************/ /* sort roots using monkey-puzzle sort */ /*****************************************/ ilb[1]=0; irb[1]=0; for (h=2; h<=jh; h++) { ilb[h]=0; irb[h]=0; q=1; lb: if (m[h-1]>m[q-1]) goto le; if(ilb[q]==0) goto ld; q=ilb[q]; goto lb; ld: irb[h]=-q; ilb[q]=(int)h; continue; le: if (irb[q]<0) goto lf; if (irb[q]==0) goto lf; q=irb[q]; goto lb; lf: irb[h]=irb[q]; irb[q]=(int)h; } f=-1; q=1; goto li; lh: q=ilb[q]; li: if (ilb[q]>0) goto lh; lj: f=f+1; p[f]=m[q-1]; if (irb[q]<0) goto lk; if (irb[q]==0) goto ll; q=irb[q]; goto li; lk: q=-irb[q]; goto lj; /*************************************/ /* count pairs of consecutive roots */ /*************************************/ ll: nq=0; for (h=1; h<jh; h++) { if ((p[h]-p[h-1])==1) nq=nq+1; } if (i!=0) s[nq]=s[nq]+1; else t[nq]=t[nq]+1; sum=sum+nq; } sum=sum*2+1; if (sum!=j-2) { printf("error: sum=%d p-2=%d \n",sum,j-2); goto zskip; } printf("p=%d \n",j); } for (i=0; i<101; i++) { fprintf(Outfp," i=%d, %d %d \n",i,s[i],t[i]); printf(" i=%d, %d %d \n",i,s[i],t[i]); } zskip: fclose(Outfp); return(0); }