⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collatz.c

📁 calc大数库
💻 C
字号:
/* collatz.c */
#ifdef _WIN32
#include "unistd_DOS.h"
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -