www.pudn.com > calc.rar > collatz.c
/* collatz.c */ #ifdef _WIN32 #include "unistd_DOS.h" #else #include#endif #include #include #include #include "integer.h" #include "fun.h" #define UPPER_BOUND 4294967294UL /* 2^32 - 2 */ #define CYCLE_MAX 150 #define BRANCH_MAX 20 MPI *GEN_COLLATZ(MPI *Aptr, USL d, MPI *m[], MPI *X[]) /* * The generalized Collatz function. * Here d is the number of branches. * m[0],...,m[d-1] are non-zero integers (the multipliers). * X[0],...,X[d-1] are the shifts. * T(Aptr)=INT(m[r]*Aptr/d)+X[r], if Aptr(MOD(d))=r. */ { USL r; MPI *T1, *T2, *T3; r = MOD_(Aptr, d); T1 = MULTI(Aptr, m[r]); T2 = INT_(T1, d); FREEMPI(T1); T3 = ADDI(T2, X[r]); FREEMPI(T2); return (T3); } void P_CYCLE(MPI *Aptr, USL d, MPI *m[], MPI *X[], USI c) /* the cycle starting with *Aptr is printed */ { MPI *B, *Temp, *MIN_ELT, *TEMP1; unsigned int i = 0; FILE *outfile; char buff[20]; strcpy(buff, "cycle.out"); outfile = fopen(buff, "a"); B = COPYI(Aptr); MIN_ELT = COPYI(Aptr); do{ Temp = B; B = GEN_COLLATZ(B, d, m, X); FREEMPI(Temp); if(RSV(B, MIN_ELT) < 0){ TEMP1 = MIN_ELT; MIN_ELT = COPYI(B); FREEMPI(TEMP1); } }while (!EQUALI(Aptr, B)); Temp = B; B = COPYI(MIN_ELT); FREEMPI(Temp); do { PRINTI(B); FPRINTI(outfile, B); printf("\n"); fprintf(outfile, "\n"); Temp = B; B = GEN_COLLATZ(B, d, m, X); FREEMPI(Temp); i++; } while (!EQUALI(MIN_ELT, B)); printf("length of cycle %u is %u\n", c, i); fprintf(outfile, "length of cycle %u is %u\n", c, i); fclose(outfile); FREEMPI(B); FREEMPI(MIN_ELT); return; } unsigned int IS_CYCLE(MPI *Aptr, USL d, MPI *m[], MPI *X[], MPI *Z[], USI c) /* the cycle starting from Aptr is distinct from those starting from * Z[0],..., Z[c] if and only if IS_CYCLE() = 1. */ { USL k; MPI *B, *Temp; unsigned int i, t; B = COPYI(Aptr); for (k = 0; 1; k++) { for (i = 0; i < c; i++) { if (EQUALI(B, Z[i])) { FREEMPI(B); return (0); } } Temp = B; B = GEN_COLLATZ(B, d, m, X); FREEMPI(Temp); t = EQUALI(Aptr, B); if (t) /* found a new cycle */ { FREEMPI(B); break; } } return (1); } void CYCLE(USL d, MPI *m[], MPI *X[], USL INFINITY, USL RANGE) /* * This function searches all trajectories of the generalized Collatz * function which start from p, |p| <= RANGE/2 (RANGE an even integer). */ { MPI *A, *B, **Z, *Temp, *B1; unsigned int c = 0, n, r, end, *FLAG, t = 0, i, s = 0; USI diverge_flag=0; long int p, q, LIMIT, k; FILE *outfile; char buff[20]; strcpy(buff, "cycle.out"); LIMIT = CYCLE_MAX; FLAG = (unsigned int *)ccalloc(RANGE + 1, sizeof(unsigned int)); Z = (MPI **)mmalloc(LIMIT * sizeof(MPI *)); INTSETI((int *)FLAG, RANGE + 1, RANGE + 1); for (n = 0; n <= RANGE; n++) { if (FLAG[n] > n) { if ((n & 1) == 0) p = (n >> 1); else p = -((n + 1) >> 1); q = p; printf("p = %ld\n", p); A = CHANGEI(p); B = COPYI(A); end = 0; for (k = 0; k <= UPPER_BOUND; k++) { Temp = A; A = GEN_COLLATZ(A, d, m, X); FREEMPI(Temp); if (A->D >= INFINITY) { if(diverge_flag == 0){ outfile = fopen(buff, "a"); fprintf(outfile, "divergent trajectory starting from q = %ld\n", q); printf("divergent trajectory starting from q = %ld\n", q); fclose(outfile); diverge_flag = 1; } FREEMPI(A); FREEMPI(B); break; } Temp = B; B1 = GEN_COLLATZ(B, d, m, X); B = GEN_COLLATZ(B1, d, m, X); FREEMPI(B1); FREEMPI(Temp); t = EQUALI(A, B); if (t) { /* cycle detected starting at p */ FREEMPI(B); break; } if (A->D == 0 && A->V[0] <= RANGE/2) { p = A->V[0]; r = (A->S >= 0 ? 2 * p : 2 * p - 1); if (FLAG[r] < n) { end = 1; FREEMPI(A); FREEMPI(B); break; } else FLAG[r] = n; } } if (end == 1) continue; if (t) { if (c == 0) { /* store A, the start of first cycle */ Z[0] = A; printf("\ncycle %u:\n", c + 1); outfile = fopen(buff, "a"); fprintf(outfile, "\ncycle %u:\n", c + 1); fclose(outfile); P_CYCLE(A, d, m, X, c + 1); c++; } else { /* store start of subsequent cycles */ s = IS_CYCLE(A, d, m, X, Z, c); if (s == 0) FREEMPI(A); else { if (c >= LIMIT) { LIMIT++; /* ptr = Z;*/ Z = (MPI **)rrealloc((char *)Z, (c + 1) * sizeof(MPI *), sizeof(MPI *)); /*if (ptr != Z) free((char *) ptr);*/ } Z[c] = A; printf("\ncycle %u:\n", c + 1); outfile = fopen(buff, "a"); fprintf(outfile, "\ncycle %u:\n", c + 1); fclose(outfile); P_CYCLE(A, d, m, X, c + 1); c++; } } } } } for (i = 0; i < c; i++) FREEMPI(Z[i]); ffree((char *)Z, LIMIT * sizeof(MPI *)); ffree((char *)FLAG, (RANGE + 1) * sizeof(USI)); return; } void CYCLEX() { unsigned int i, RANGE, u; USL d, INFINITY; MPI **m, **X; FILE *outfile; char buff[20]; strcpy(buff, "cycle.out"); if(access(buff, R_OK) == 0) unlink(buff); outfile = fopen(buff, "w"); printf("enter 'INFINITY', (the cut-off number of allowable digits (base %u) for an iterate - say <20):", R0); scanf("%lu", &INFINITY); printf("INFINITY = %lu\n", INFINITY); fprintf(outfile, "INFINITY = %lu\n", INFINITY); printf("enter an even integer 'RANGE' (<= (say)500,000): (searches all trajectories of the generalized Collatz function which start from p, |p| <= RANGE)/2\n"); scanf("%u", &RANGE); printf("RANGE = %u\n", RANGE); fprintf(outfile, "RANGE = %u\n", RANGE); printf("enter the number d of branches (<= %u)\n", BRANCH_MAX); scanf("%lu", &d); printf("the number of branches is d = %lu\n", d); fprintf(outfile, "the number of branches is d = %lu\n", d); m = (MPI **)mmalloc(d * sizeof(MPI *)); X = (MPI **)mmalloc(d * sizeof(MPI *)); for (i = 0; i < d; i++) { printf("enter the nonzero multiplier m[%u]\n", i); m[i] = INPUTI(&u);; printf("m[%u] = ", i); fprintf(outfile, "m[%u] = ", i); PRINTI(m[i]); FPRINTI(outfile, m[i]); printf("\n"); fprintf(outfile, "\n"); } for (i = 0; i < d; i++) { printf("enter the shift X[%u]\n", i); X[i] = INPUTI(&u);; printf("X[%u] = ", i); fprintf(outfile, "X[%u] = ", i); PRINTI(X[i]); FPRINTI(outfile, X[i]); printf("\n"); fprintf(outfile, "\n"); } fclose(outfile); Flush(); printf("\n\n"); CYCLE(d, m, X, INFINITY, RANGE); for (i = 0; i < d; i++) FREEMPI(m[i]); ffree((char *)m, d * sizeof(MPI *)); for (i = 0; i < d; i++) FREEMPI(X[i]); ffree((char *)X, d * sizeof(MPI *)); return; }