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

📄 i9.c

📁 calc大数库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* i9.c */
#include <stdio.h>
#include <stdlib.h>
#include "integer.h"
#include "fun.h"

extern long int nettbytes;
/*
MPI *MAXI, *PMAXI, *QMAXI;
*/
extern int answer;

MPI **SMITHI(MPMATI *Mptr, MPMATI **Pptr, MPMATI **Qptr, USI *ptr, MPI *Eptr, USI m1, USI n1)
/*
 * returns the invariant factors of *Mptr.
 * **Pptr and **Qptr are invertible matrices such that
 * **Pptr x *Mptr x **Qptr is the Smith canonical form *Nptr below.
 * *ptr is the number of invariant factors.
 * See Rings, Modules and Linear Algebra by B. Hartley and T. O. Hawkes,
 * Chapman and Hall, 1970.
 * *Eptr is the cutoff above which we bring in MLLL. In any case MLLL is
 * done before each block is processed, as a chance of getting small entries.
 * This modification of the LLL algorithm was outlined by M. Pohst in J. 
 * Symbolic Computation (1987) 4, 123-127. m1/n1 is the LLL parameter alpha, 
 * 1/4 < alpha |= 1.
 * I initially coded this I think in 1992, along the lines of suggestions by
 * George Havas.
 */
{
	unsigned int i, k, l, m, n, p, q, j, t, z, size, r, s;
	unsigned int flag = 1, FLAG = 1;
	MPI *Q, **N, *Tmp;
	MPMATI *Nptr, *Temp;
	int isok;
	
	m = Mptr->R;
	n = Mptr->C;
	Nptr = COPYMATI(Mptr);
	*Pptr = IDENTITYI(m);
	*Qptr = IDENTITYI(n);
/*
	MAXI = MAXELTI(Mptr);
	PMAXI = MAXELTI(*Pptr);
	QMAXI = MAXELTI(*Qptr);
*/
	z = MIN((int) m - 1, (int) n - 1);
	N = (MPI **)mmalloc((z + 1) * sizeof(MPI *));
	for (i = 0; i <= z; i++)
	{
		ZEROTESTI(0, Nptr, &r, &s);
		if (r == Nptr->R && s == Nptr->C)
			break;
		flag = HAVAS_PIVOTI(Nptr, &p, &q, r, s);
		if (p > 0)/* must have a non-zero row 1 for MLLL */
		{
			Nptr = SWAP_ROWSI1(0, p, Nptr);
			*Pptr = SWAP_ROWSI1(i, p + i, *Pptr);
		}
		if (q > 0)
		{
			Nptr = SWAP_COLSI1(0, q, Nptr);
			*Qptr = SWAP_COLSI1(i, q + i, *Qptr);
		}
		if (flag)
			FLAG = 1;
		if (!flag && FLAG)
		{
			size = Nptr->R;
			Temp = Nptr;
			Nptr = BASIS_REDUCTION(Nptr, Pptr, i, m1, n1);
			/*Nptr = BASIS_REDUCTION0(Nptr, 3, 4);*/
			FREEMATI(Temp);
			ZEROTESTI(0, Nptr, &r, &s);
			if (r == Nptr->R && s == Nptr->C)
				break;
			flag = HAVAS_PIVOTI(Nptr, &p, &q, r, s);
			if (p > 0)
			{
				Nptr = SWAP_ROWSI1(0, p, Nptr);
				*Pptr = SWAP_ROWSI1(i, p + i, *Pptr);
			}
			if (q > 0)
			{
				Nptr = SWAP_COLSI1(0, q, Nptr);
				*Qptr = SWAP_COLSI1(i, q + i, *Qptr);
			}
			FLAG = 0;
			size = size - Nptr->R;
			m = m - size;
			z = MIN((int) m - 1, (int) n - 1);
		}
		/* Now elt(Nptr, 0, 0) != 0. */
		while (1)
		{
 		    while(1)
		    { /* PA bit */
			isok = 1;
			for(j = 0; j < Nptr->C; j++)
			{
				if ((Nptr->V[0][j])->S == -1)
				{
					for(t = 0; t < Nptr->R; t++)
						(Nptr->V[t][j])->S = - (Nptr->V[t][j])->S;
					for(t = 0; t < n; t++)
						((*Qptr)->V[t][j + i])->S = - ((*Qptr)->V[t][j + i])->S;
				}
			}
			/* Now all non-zero elements in row 0 are positive. */
			while (1)
			{
				l = ROWSEEKI(0, Nptr);
				if (l == Nptr->C)
					 break;
				else
				{
					/* Case 1, p. 112. */
					Q = INT(Nptr->V[0][l], Nptr->V[0][0]);
					Nptr = COLSUBI(0, l, Q, Nptr); 
/*
					MAXI = UPDATEMAXI(MAXI, Nptr);
*/
					*Qptr = COLSUBI(i, l + i, Q, *Qptr); 
/*
					QMAXI = UPDATEMAXI(QMAXI, *Qptr);
*/
					FREEMPI(Q);
					Nptr = SWAP_COLSI1(0, l, Nptr); 
					*Qptr = SWAP_COLSI1(i, l + i, *Qptr); 
					/* This reduces the size of elt(Nptr, 0, 0). */
				}
			}
			for(j = 1; j < Nptr->R; j++)
			{
				if ((Nptr->V[j][0])->S == -1)
				{
					for(t = 0; t < Nptr->C; t++)
						(Nptr->V[j][t])->S = - (Nptr->V[j][t])->S;
					for(t = 0; t < (*Pptr)->R; t++)
						((*Pptr)->V[j + i][t])->S = - ((*Pptr)->V[j + i][t])->S;
				}
			}
/*
Now all non-zero elements in column 0 are positive.
*/
			while (1)
			{
				k = COLSEEKI(0, Nptr);
				if (k == Nptr->R)
					break;
				else
				{
					isok = 0;
					/* Case 2, p. 112. */
					Q = INT0(Nptr->V[k][0], Nptr->V[0][0]);
					Nptr = ROWSUBI(0, k, Q, Nptr); 
/*
					MAXI = UPDATEMAXI(MAXI, Nptr);
*/
					*Pptr = ROWSUBI(i, k + i, Q, *Pptr);
/*
					PMAXI = UPDATEMAXI(PMAXI, *Pptr);
*/
					FREEMPI(Q);
					Nptr = SWAP_ROWSI1(0, k, Nptr); 
					*Pptr = SWAP_ROWSI1(i, k + i, *Pptr);
					/* This reduces the size of elt(Nptr, 0, 0). */
				}
			}
			/* now l = Nptr->C and k = Nptr->R */
			if (isok)
				break;
		   } /*PA bit*/
/*
Now (Case 3, p.112) elt(Nptr, 0, 0) divides each element to its right as well as below it.
*/
		for (l = 1; l < Nptr->C; l++)
		{
			if ((Nptr->V[0][l])->S != 0)
			{
	/* NOTE: Swapping above may have made elt(Nptr, 0, l) <0 */
				Q = INT(Nptr->V[0][l], Nptr->V[0][0]);
				Nptr = COLSUBI(0, l, Q, Nptr); 
/*
				MAXI = UPDATEMAXI(MAXI, Nptr);
*/
				*Qptr = COLSUBI(i, l + i, Q, *Qptr); 
/*
				QMAXI = UPDATEMAXI(QMAXI, *Qptr);
*/
				FREEMPI(Q);
			}
		}
		for (k = 1; k < Nptr->R; k++)
		{
			if ((Nptr->V[k][0])->S != 0)
			{
				Q = INT0(Nptr->V[k][0], Nptr->V[0][0]);
				FREEMPI(Nptr->V[k][0]);
				Nptr->V[k][0] = ZEROI();
				*Pptr = ROWSUBI(i, k + i, Q, *Pptr);
/*
				PMAXI = UPDATEMAXI(PMAXI, *Pptr);
*/
				FREEMPI(Q);
			}
		}
/*
Now each element to the right of and below elt(Nptr, 0, 0) is zero.
*/
		k = MATSEEKI(0, Nptr);
		if (k != Nptr->R)
		{
			for (t = 0; t < Nptr->C; t++)
			{
				if ((Nptr->V[k][t])->S != 0)
				{
					Tmp = Nptr->V[0][t];
					Nptr->V[0][t] = ADDI(Nptr->V[0][t], Nptr->V[k][t]);
/*
					MAXI = UPDATEMAXI(MAXI, Nptr);
*/
					FREEMPI(Tmp);
				}
			}
			for (t = 0; t < Mptr->R; t++)
			{
				if (((*Pptr)->V[k + i][t])->S != 0)
				{
					Tmp = (*Pptr)->V[i][t];
					(*Pptr)->V[i][t] = ADDI((*Pptr)->V[i][t], (*Pptr)->V[k + i][t]);
/*
					PMAXI = UPDATEMAXI(PMAXI, *Pptr);
*/
					FREEMPI(Tmp);
				}
			}
		}
		else
			break;
	}
/*
Now elt(Nptr, 0, 0) divides all elements elt(Nptr, k, l), k,l > 0.
*/
		N[i] = COPYI(Nptr->V[0][0]);

		if (i < z)
		{
			Temp = Nptr;
			Nptr = DELETE_ROW1I(Nptr);	
			FREEMATI(Temp);
			Temp = Nptr;
			Nptr = DELETE_COL1I(Nptr);	
			FREEMATI(Temp);
		}
		size = Nptr->R;
		Tmp = MAXELTI(Nptr);
		printf("found invariant factor d[%u] = ", i + 1); PRINTI(N[i]); printf("\n");
/*
		printf("MAXI = "); PRINTI(MAXI); printf("\n");
		printf("PMAXI = "); PRINTI(PMAXI); printf("\n");
		printf("QMAXI = "); PRINTI(QMAXI); printf("\n");
*/
		printf("MAX_ENTRY(Nptr) = "); PRINTI(Tmp); printf("\n");
		l = RSV(Tmp, Eptr);
		FREEMPI(Tmp);
		if (l == 1 && !flag)/* we don't want to use MLLL if there are
1's or -1's still present */
		{
			ZEROTESTI(0, Nptr, &r, &s);
			if (r > 0)/* must have a non-zero row 1 for MLLL */
			{
				printf("r = %u > 0\n", r);
				Nptr = SWAP_ROWSI1(0, r, Nptr);
				*Pptr = SWAP_ROWSI1(i + 1, r + i + 1, *Pptr);
			}
			Temp = Nptr;
			Nptr = BASIS_REDUCTION(Nptr, Pptr, i+1, m1, n1);
			/*Nptr = BASIS_REDUCTION0(Nptr, 3, 4);*/
			FREEMATI(Temp);
		}
		size = size - Nptr->R;
		m = m - size;
		z = MIN((int) m - 1, (int) n - 1);
	}
	FREEMATI(Nptr);
	*ptr = i++;
/*
	printf("MAXI = "); PRINTI(MAXI); printf("\n");
	printf("PMAXI = "); PRINTI(PMAXI); printf("\n");
	printf("QMAXI = "); PRINTI(QMAXI); printf("\n");
	FREEMPI(MAXI);
	FREEMPI(PMAXI);
	FREEMPI(QMAXI);
*/
	return (N);
}

MPI *ROWSUMI(MPMATI *Mptr, USI i)
{
	unsigned int j;
	MPI *S, *Temp1I, *Temp2I;

	S = ZEROI();
	for (j = 0; j < Mptr->C; j++)
	{
		Temp1I = ABSI(Mptr->V[i][j]);
		Temp2I = S;
		S = ADD0I(Temp1I, S);
		FREEMPI(Temp1I);
		FREEMPI(Temp2I);
	}
	return (S);
}

MPI *COLSUMI(MPMATI *Mptr, USI j)
{
	unsigned int i;
	MPI *S, *Temp1I, *Temp2I;

	S = ZEROI();
	for (i = 0; i < Mptr->R; i++)
	{
		Temp1I = ABSI(Mptr->V[i][j]);
		Temp2I = S;
		S = ADD0I(Temp1I, S);
		FREEMPI(Temp1I);
		FREEMPI(Temp2I);
	}
	return (S);
}

MPI *MINELTI(MPMATI *Mptr)
/* returns the minimum element of *Mptr */
{
	unsigned int i, j, I, J, flag = 0;

	I = J = 0;
	for (i = 0; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if ((Mptr->V[i][j])->S)
			{
				I = i;
				J = j;
				flag = 1;
				break;
			}
		}
		if (flag)
			break;
	}
	for (i = I; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if (RSV(Mptr->V[I][J], Mptr->V[i][j]) == 1 && (Mptr->V[i][j])->S)
			{
				I = i;
				J = j;
			}
		}
	}
	return (ABSI(Mptr->V[I][J]));
}

void MINELTI1(MPMATI *Mptr, USI *iptr, USI *jptr)
/* returns the position of the minimum element of *Mptr */
{
	unsigned int i, j, I, J, flag = 0;

	I = J = 0;
	for (i = 0; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if ((Mptr->V[i][j])->S)
			{
				I = i;
				J = j;
				flag = 1;
				break;
			}
		}
		if (flag)
			break;
	}
	for (i = 0; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if (RSV(Mptr->V[I][J], Mptr->V[i][j]) == 1 && (Mptr->V[i][j])->S)
			{
				I = i;
				J = j;
			}
		}
	}
	*iptr = I;
	*jptr = J;
	return;
}

MPI *MAXELTI(MPMATI *Mptr)
/* returns the maximum element of *Mptr */
{
	unsigned int i, j, I = 0, J = 0;

	for (i = 0; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if (RSV(Mptr->V[i][j], Mptr->V[I][J]) == 1)
			{
				I = i;
				J = j;
			}
		}
	}
	return (ABSI(Mptr->V[I][J]));
}

void MAXELTI1(MPMATI *Mptr, USI *iptr, USI *jptr)
/* returns the position of the maximum element of *Mptr */
{
	unsigned int i, j, I = 0, J = 0;

	for (i = 0; i < Mptr->R; i++)
	{
		for (j = 0; j < Mptr->C; j++)
		{
			if (RSV(Mptr->V[i][j], Mptr->V[I][J]) == 1)
			{
				I = i;
				J = j;
			}
		}
	}
	*iptr = I;
	*jptr = J;
	return;
}

MPI *UPDATEMAXI(MPI *S, MPMATI *Mptr)
{
	MPI *TempI;

	TempI = MAXELTI(Mptr);
	if (RSV(TempI, S) == 1)
	{
		FREEMPI(S);
		return(TempI);
	}	
	else
	{
		FREEMPI(TempI);
		return (S);
	}
}

unsigned int HAVAS_PIVOTI(MPMATI *Mptr, USI *rptr, USI *cptr, USI r, USI s)
{
	MPI **RS, **CS, *S, *Temp1I, *Temp2I, *TempI;
	unsigned int i, j, I, J, m, n, flag;

	m = Mptr->R;
	n = Mptr->C;
	RS = (MPI **)mmalloc(m * sizeof(MPI *));
	CS = (MPI **)mmalloc(n * sizeof(MPI *));
	for (i = 0; i < m; i++)
	{
		TempI = ROWSUMI(Mptr, i);
		if (TempI->S == 0)
		{
			FREEMPI(TempI);
			RS[i] = MINUS_ONEI();
		}
		else
		{
			Temp1I = ONEI();
			RS[i] = SUB0I(TempI, Temp1I);
			FREEMPI(TempI);
			FREEMPI(Temp1I);
		}
	}
	for (j = 0; j < Mptr->C; j++)
	{
		TempI = COLSUMI(Mptr, j);
		if (TempI->S == 0)
		{
			FREEMPI(TempI);
			CS[j] = MINUS_ONEI();
		}
		else
		{
			Temp1I = ONEI();
			CS[j] = SUB0I(TempI, Temp1I);
			FREEMPI(TempI);

⌨️ 快捷键说明

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