/*****************************************************************************/ /* */ /* FIND CYCLES IN THE 3N+C SEQUENCE (cycles with attachment points only) */ /* 02/19/13 (dkc) */ /* */ /* This C program finds cycles in the 3n+c sequence. Attachment points are */ /* output. Double-precision (64-bit) words are used. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <math.h> #include "table.h" unsigned int carry(unsigned int a, unsigned int b, unsigned int sum); unsigned int lmbd(unsigned int mode, unsigned int a); void add64(unsigned int *a, unsigned int *b); void sub64(unsigned int *a, unsigned int *b); void div64_32(unsigned int *dividend, unsigned int *quotient, unsigned int divisor); void mul64_32(unsigned int a0, unsigned int a2, unsigned int m0, unsigned int *product); int main () { // unsigned int cstart=48001; // beginning c value unsigned int cend=48097; // ending c value unsigned int mode=0; // double-word flag unsigned int iters=1; // number of "jumps" from the initial odd integer // divisible by 3, usually set to 1 (every cycle having // an attachment point has at least one one-jump or // no-jump attachment point). A jump usually results // in gain of the initial value. Cycles with large // elements can then be found starting with relatively // small initial values. unsigned int limit=1500000; // must be a multiple of 6, should be about half // of "max" to allow for cycles having a constrained // dynamic range (a preferable value is 3000000, but // execution time is too long [cycles with (K+L,K) // values equal to generalized continued-fraction // convergents of log(3)/log(2) are most likely to // be missed]) unsigned int max=0x80000000; // maximum allowable value of second word of double- // word (when "bigmax" is set to 0), apparently adequate // for c values of up to about 20000. For larger c // values, both words are required for some cycles. // When the mode is set to 0, only the second word // of attachment points is output. (When "iters" is // greater than 1, "max" usually must be increased to // accommodate the gain.) unsigned int bigmax=0; // if set, "max" is the upper bound of the first word of // the double word (a typical value of "max" would be 1) int i; unsigned int first,acount; unsigned int c,t,e,f,g,h,j,m,n,count,total,flag,wrap,oldlop,lodds,bigind; unsigned int save[32*2],v[32768*2]; unsigned char cyc[60000]; unsigned int lopcnt[500]; unsigned int out[15000*2]; unsigned int outn[15000]; unsigned int factor[400]; unsigned int bigcyc[100*5]; unsigned int index,z,lopind,lop,K[2],T[2],U[2],L[2],C[2],V[2],Y[2],Z[2],P[3]; FILE *Outfp; Outfp = fopen("out0a.dat","w"); if (cstart==(cstart/3)*3) { printf("c divisible by 3 \n"); goto zskip; } if (cstart==(cstart/2)*2) { printf("c divisible by 2 \n"); goto zskip; } if (cend==(cend/3)*3) { printf("c divisible by 3 \n"); goto zskip; } if (cend==(cend/2)*2) { printf("c divisible by 2 \n"); goto zskip; } if (cend>49865) printf("warning: cycle may not be primitive \n"); for (h=0; h<100*5; h++) bigcyc[h]=0; bigind=0; Z[0]=0; Z[1]=0; fprintf(Outfp,"// c=%d \n",cstart); fprintf(Outfp,"int sinp[ ]={ \n"); if (mode==0) wrap=15; else wrap=3; index=0; lopind=0; total=0; for (c=cstart; c<=cend; c+=2) { if (c==(c/3)*3) continue; printf("c=%d \n",c); C[0]=0; C[1]=c; count=0; z=0; if (c!=1) { factor[0]=c; count=1; } for (i=0; i<1228; i++) { t=(unsigned int)table[i]; if (c==(c/t)*t) { factor[count]=t; count=count+1; } } m=0; lop=0; for (i=3-(int)limit; i<(int)limit; i+=6) { K[0]=0; if (i<0) { // initial sequence value K[1]=-i; sub64(Z, K); } else K[1]=i; for (e=0; e<iters; e++) { add64(C, K); n=0; // clear count while ((K[1]&1)==0) { K[1]=(K[1]>>1)|(K[0]<<31); K[0]=(int)K[0]>>1; n=n+1; } T[0]=K[0]; T[1]=K[1]; if ((T[0]&0x80000000)!=0) sub64(Z, T); for (j=0; j<n; j++) { if (bigmax==0) { if ((T[0]!=0)||(T[1]>max)) goto askip; } else { if (T[0]>max) goto askip; } L[0]=T[0]; L[1]=T[1]; add64(T, T); add64(L, T); L[0]=K[0]; L[1]=K[1]; add64(K, K); add64(L, K); } L[0]=C[0]; L[1]=C[1]; sub64(K, L); K[1]=(L[1]>>1)|(L[0]<<31); K[0]=(int)L[0]>>1; if ((K[1]&1)==0) goto bskip; } T[0]=K[0]; T[1]=K[1]; if ((T[0]&0x80000000)!=0) sub64(Z, T); if (bigmax==0) { if ((T[0]!=0)||(T[1]>max)) goto askip; } else { if (T[0]>max) goto askip; } L[0]=K[0]; L[1]=K[1]; add64(K, K); add64(L, K); add64(C, K); bskip: h=0; // clear index n=0; // clear index while ((K[1]&1)==0) { v[2*n]=K[0]; v[2*n+1]=K[1]; n=n+1; // increment index if (h<32) { // check index save[2*h]=K[0]; save[2*h+1]=K[1]; h=h+1; // increment index } else { // array too small printf("error: array too small \n"); goto zskip; } K[1]=(K[1]>>1)|(K[0]<<31); K[0]=(int)K[0]>>1; } for (j=1; j<1000000; j++) { v[n*2]=K[0]; v[n*2+1]=K[1]; n=n+1; // increment index if (n>32767) // array full goto askip; T[0]=K[0]; T[1]=K[1]; if ((T[0]&0x80000000)!=0) sub64(Z, T); if (bigmax==0) { if ((T[0]!=0)||(T[1]>max)) goto askip; } else { if (T[0]>max) goto askip; } L[0]=K[0]; L[1]=K[1]; add64(K, K); add64(L, K); add64(C, K); while ((K[1]&1)==0) { for (g=0; g<h; g++) { if ((K[0]==save[g*2])&&(K[1]==save[g*2+1])) { for (f=g; f<n; f++) { if ((v[f*2+1]&7)==0) { Y[1]=(v[f*2+1]>>2)|(v[f*2]<<30); Y[0]=(int)v[f*2]>>2; for (e=0; e<m; e++) { if (((n-g)==outn[e])&&(Y[0]==out[2*e])&&(Y[1]==out[2*e+1])) { goto askip; } } // check if primitive T[0]=Y[0]; T[1]=Y[1]; if ((T[0]&0x80000000)!=0) sub64(Z, T); for (e=0; e<count; e++) { t=factor[e]; div64_32(T, U, t); mul64_32(U[0], U[1], t, P); if ((T[0]==P[1])&&(T[1]==P[2])) goto askip; } // attachment point oldlop=lop; lodds=0; acount=0; flag=0; T[0]=v[f*2]; T[1]=v[f*2+1]; V[0]=T[0]; V[1]=T[1]; aloop: first=0; while ((T[1]&3)==0) { T[1]=(T[1]>>2)|(T[0]<<30); T[0]=(int)T[0]>>2; if ((T[1]&1)==1) goto qskip; if (first==0) { acount=acount+1; first=1; } U[0]=T[0]; U[1]=T[1]; if ((U[0]&0x80000000)!=0) sub64(Z, U); if ((U[0]!=0)||((U[1]&0xe0000000)!=0)) flag=1; printf("n=%d, k=%d \n",n-g,T[1]); if (mode==0) fprintf(Outfp,"%d,",T[1]); else fprintf(Outfp,"%#010x,%#010x,",T[0],T[1]); total=total+1; if (total>wrap) { fprintf(Outfp,"\n"); total=0; } cyc[index]=z; index=index+1; if (index>59999) { printf("error: array not big enough \n"); goto zskip; } lop=lop+1; outn[m]=(n-g); out[2*m]=T[0]; out[2*m+1]=T[1]; m=m+1; if (m>=15000) { printf("output array full \n"); goto zskip; } if ((T[0]==V[0])&&(T[1]==V[1])) { acount=acount-1; goto rskip; } } if ((T[1]&1)==0) { T[1]=(T[1]>>1)|(T[0]<<31); T[0]=(int)T[0]>>1; } qskip: lodds=lodds+1; L[0]=T[0]; L[1]=T[1]; add64(T, T); add64(L, T); add64(C, T); if ((T[0]!=V[0])||(T[1]!=V[1])) goto aloop; // new cycle rskip: if (flag!=0) { printf("big attachment point: c=%d, count=%d \n",c,lop-oldlop); bigcyc[bigind*5]=c; bigcyc[bigind*5+1]=lop-oldlop; bigcyc[bigind*5+2]=n-g-2*lodds; bigcyc[bigind*5+3]=lodds; bigcyc[bigind*5+4]=acount; bigind=bigind+1; if (bigind>99) { printf("array not big enough \n"); goto zskip; } } printf("L=%d, K=%d, a=%d, big=%d \n",n-g-2*lodds,lodds,acount,bigind); z=z+1; goto askip; } } } } v[n*2]=K[0]; v[n*2+1]=K[1]; n=n+1; if (n>32767) goto askip; K[1]=(K[1]>>1)|(K[0]<<31); K[0]=(int)K[0]>>1; } } askip:n=0; } lopcnt[lopind]=lop; lopind=lopind+1; printf("\n"); } printf("\n"); fprintf(Outfp,"\n"); fprintf(Outfp,"unsigned char cflag[ +1]={ \n"); total=0; for (h=0; h<index; h++) { fprintf(Outfp,"%d,",cyc[h]); total=total+1; if (total>20) { fprintf(Outfp,"\n"); total=0; } } fprintf(Outfp,"255};"); fprintf(Outfp," // index=%d \n",index); fprintf(Outfp,"unsigned int size[ ]={ \n"); for (h=0; h<lopind; h++) fprintf(Outfp," %d,\n",lopcnt[h]); fprintf(Outfp,"int cval[ ]={ \n"); index=0; total=0; for (h=(unsigned int)cstart; h<=(unsigned int)cend; h+=2) { if (h==(h/3)*3) continue; index=index+1; fprintf(Outfp,"%d,",h); total=total+1; if (total>10) { fprintf(Outfp,"\n"); total=0; } } fprintf(Outfp,"\n"); fprintf(Outfp,"unsigned int numbc=%d; \n",index); printf("\n"); fprintf(Outfp,"\n"); for (h=0; h<bigind; h++) { printf("c=%d, count=%d, L=%d, K=%d, a=%d \n",bigcyc[h*5],bigcyc[h*5+1],bigcyc[h*5+2],bigcyc[h*5+3],bigcyc[h*5+4]); fprintf(Outfp,"c=%d, count=%d, L=%d, K=%d, a=%d \n",bigcyc[h*5],bigcyc[h*5+1],bigcyc[h*5+2],bigcyc[h*5+3],bigcyc[h*5+4]); } zskip: fclose(Outfp); return(0); }