www.pudn.com > calc.rar > lllhermi.c


/* lllhermi.c */ 
#include  
#include  
#include "integer.h" 
#include "fun.h" 
extern MPI *MAXI, *PMAXI; 
 
extern unsigned int MLLLVERBOSE; 
extern unsigned int HERMITE1VERBOSE; 
unsigned int keith97; 
 
USI FLAGCOLI(MPMATI *Aptr); 
 
 
MPMATI *LLLHERMITE1(MPMATI *DD, MPMATI **Aptr, USI *rank, USI m1, USI n1) 
/*  
 * Input: an m x n matrix DD of MPI's. 
 * Output: *Aptr = HNF(DD). Also we return a small transformation matrix B 
 * if nullity > 0. 
 * The limiting form of  LLL applied to [I_m|N^mD_1|N^{m-1}D_2|...] is used. 
 * Normally m1/n1 = 3/4. 
 * 23/2/97. 
 */ 
{ 
	unsigned int *COL; 
	unsigned int i, j, k, l, m, n, col1, col2, r; 
	int t; 
	MPI **D, *X, *Y, *Z, *Tmp, *R, ***temp1, ***temp2; 
	MPI *M1, *N1; 
	MPMATI *L, *B; 
 
	keith97 = FLAGCOLI(DD); 
	m = DD->R; 
	n = DD->C; 
	B = IDENTITYI(m); 
	*Aptr = COPYMATI(DD); 
	if (!keith97){ 
		(B->V[m - 1][m - 1])->S = -1; 
		for (j = 0; j < n; j++) 
			((*Aptr)->V[m - 1][j])->S = - (((*Aptr)->V[m - 1][j])->S); 
	} 
	D = (MPI **)mmalloc((1 + m) * sizeof(MPI *)); 
	for (i = 0; i <= m; i++) 
		D[i] = ONEI(); 
 
	L = ZEROMNI(m, m); 
 
	k = 2; 
	M1 = CHANGE(m1); 
	N1 = CHANGE(n1); 
	while (k <= m) 
	{ 
		REDUCE1(k, k - 1, &L, &B, D, Aptr, &col1, &col2); 
		X = MULTI(D[k - 2], D[k]); 
		Y = MULTI(D[k - 1], D[k - 1]); 
		Tmp = Y; 
		Y = MULTI(Y, M1); 
		FREEMPI(Tmp); 
		R = MULTI(L->V[k - 1][k - 2], L->V[k - 1][k - 2]); 
		Z = ADD0I(X, R); 
		FREEMPI(R); 
		Tmp = Z; 
		Z = MULTI(Z, N1); 
		FREEMPI(Tmp); 
		if ((RSV(Y, Z) == 1 && col1 == n && col2 == n ) || (col1 <= col2 && col1 < n )) 
		{ 
			for (i = k + 1; i <= m; i++) 
				SWAP1(i, k, &L, D); 
			SWAP21(k, &B, &L, Aptr); 
			FREEMPI(Y); 
			Y = MULTI(L->V[k - 1][k - 2], L->V[k - 1][k - 2]); 
			Tmp = Y; 
			Y = ADD0I(Y, X); 
			FREEMPI(X); 
			FREEMPI(Tmp); 
			Tmp = D[k - 1]; 
			D[k - 1] = INT0(Y, D[k - 1]); 
			FREEMPI(Tmp); 
			FREEMPI(Y); 
			if (k > 2) 
				k--; 
		} 
		else 
		{  
			FREEMPI(X); 
			FREEMPI(Y); 
			for (l = k - 2; l >= 1; l--) 
				REDUCE1(k, l, &L, &B, D, Aptr, &col1, &col2); 
			k++; 
		} 
		FREEMPI(Z);		 
	} 
	FREEMPI(M1); 
	FREEMPI(N1); 
	FREEMATI(L); 
	for (i = 0; i <= m; i++) 
		FREEMPI(D[i]); 
 
	COL = (USI *)mmalloc((1 + m) * sizeof(USI)); 
	COL[0] = 0; 
	for (t = m - 1; t >= 0; t--) 
	{ 
		r = COLSEEKI0((*Aptr), t, COL[m-1-t]); 
		if (r == n)  
			break; 
		else 
			COL[m-t] = r; 
	} 
	if (t == -1)  
		*rank = m; 
	else 
		*rank = m - t - 1; 
 
	temp1 = (MPI ***)mmalloc((*rank) * sizeof(MPI **)); 
	temp2 = (MPI ***)mmalloc((*rank) * sizeof(MPI **)); 
	for (i = 0; i < *rank; i++) 
	{ 
		temp1[i] = (*Aptr)->V[m - 1 - i]; 
		temp2[i] = B->V[m - 1 - i]; 
	} 
	for (i = m - 1; i >= *rank; i--) 
	{ 
		(*Aptr)->V[i] = (*Aptr)->V[i - *rank]; 
		B->V[i] = B->V[i - *rank]; 
	} 
	for (i = 0; i < *rank; i++) 
	{ 
		(*Aptr)->V[i] = temp1[i]; 
		B->V[i] = temp2[i]; 
	} 
 
	ffree((char *)COL, (1 + m) * sizeof(USI *)); 
	ffree((char *)temp1, (*rank) * sizeof(MPI **)); 
	ffree((char *)temp2, (*rank) * sizeof(MPI **)); 
	ffree((char *)D, (1 + m) * sizeof(MPI *)); 
	return (B); 
} 
 
 
void REDUCE1(USI k, USI l, MPMATI **Lptr, MPMATI **Bptr, MPI *D[], MPMATI **Aptr, USI *col1, USI *col2) 
/* 
 * updates *Lptr, *Bptr, *Aptr. 
 */ 
{ 
	unsigned int j, n, t; 
	MPI *X, *Y, *Q, *Tmp; 
	MPMATI *TempMATI; 
 
	n = (*Aptr)->C; 
	*col1 =  n; 
	for (j = 0; j < n; j++) 
	{ 
		t = ((*Aptr)->V[l - 1][j])->S; 
		if (t) 
		{ 
			*col1 = j; 
			if (t == -1) 
				LLLMINUS(Aptr, Bptr, Lptr, l - 1); 
			break; 
		} 
	} 
	*col2 =  n; 
	for (j = 0; j < n; j++) 
	{ 
		t = ((*Aptr)->V[k - 1][j])->S; 
		if (t) 
		{ 
			*col2 = j; 
/* 
			if ((k == (*Aptr)->R) && !keith97) 
			{ 
				if (t == -1) 
					LLLMINUS(Aptr, Bptr, Lptr, k - 1); 
			} 
*/ 
			break; 
		} 
	} 
 
	if (*col1 < n) 
/*		Q = NEAREST_INTI((*Aptr)->V[k - 1][*col1], (*Aptr)->V[l - 1][*col1]);*/ 
		Q = INTI((*Aptr)->V[k - 1][*col1], (*Aptr)->V[l - 1][*col1]); 
	else 
	{ 
		Y = MULT_I((*Lptr)->V[k - 1][l - 1], 2); 
		if (RSV(Y, D[l]) == 1) 
			Q = NEAREST_INTI((*Lptr)->V[k - 1][l - 1], D[l]); 
		else 
			Q = ZEROI(); 
		FREEMPI(Y); 
	} 
	if (Q->S == 0) 
	{ 
		FREEMPI(Q); 
		return; 
	} 
	X = MINUSI(Q); 
	TempMATI = *Bptr; 
	*Bptr = ADD_MULT_ROWI(l - 1, k - 1, X, *Bptr); 
	FREEMATI(TempMATI); 
	TempMATI = *Aptr; 
	*Aptr = ADD_MULT_ROWI(l - 1, k - 1, X, *Aptr); 
	FREEMATI(TempMATI); 
	if (HERMITE1VERBOSE) 
	{ 
		printf("Row %u -> Row %u + ", k,k);PRINTI(X);printf(" x Row %u\n", l); 
		printf("P = \n"); 
		PRINTMATI(0,(*Bptr)->R-1,0,(*Bptr)->C-1,*Bptr); 
		printf("A = \n"); 
		PRINTMATI(0,(*Aptr)->R-1,0,(*Aptr)->C-1,*Aptr); 
		GetReturn(); 
	} 
	FREEMPI(X); 
	for (j = 1; j < l; j++) 
	{ 
		X = MULTI((*Lptr)->V[l - 1][j - 1], Q); 
		Tmp = (*Lptr)->V[k - 1][j - 1]; 
		(*Lptr)->V[k - 1][j - 1] = SUBI((*Lptr)->V[k - 1][j - 1], X); 
		FREEMPI(Tmp); 
		FREEMPI(X); 
	} 
	X = MULTI(D[l], Q); 
	Tmp = (*Lptr)->V[k - 1][l - 1]; 
	(*Lptr)->V[k - 1][l - 1] = SUBI((*Lptr)->V[k - 1][l - 1], X); 
	FREEMPI(Tmp); 
	FREEMPI(X); 
	FREEMPI(Q); 
	return; 
} 
 
 
void SWAP21(USI k, MPMATI **Bptr, MPMATI **Lptr, MPMATI **Aptr) 
{ 
	MPI *T; 
 
	*Aptr = SWAP_ROWSI1(k - 2, k - 1, *Aptr); 
	*Bptr = SWAP_ROWSI1(k - 2, k - 1, *Bptr); 
	T = COPYI((*Lptr)->V[k - 1][k - 2]); 
	*Lptr = SWAP_ROWSI1(k - 2, k - 1, *Lptr); 
	FREEMPI((*Lptr)->V[k - 1][k - 2]); 
	(*Lptr)->V[k - 1][k - 2] = T; 
	FREEMPI((*Lptr)->V[k - 2][k - 2]); 
	(*Lptr)->V[k - 2][k - 2] = ZEROI(); 
	if (HERMITE1VERBOSE) 
	{ 
		printf("Swapping Rows %u and %u\n", k-1,k); 
		printf("P = \n"); 
		PRINTMATI(0,(*Bptr)->R-1,0,(*Bptr)->C-1,*Bptr); 
		printf("A = \n"); 
		PRINTMATI(0,(*Aptr)->R-1,0,(*Aptr)->C-1,*Aptr); 
		GetReturn(); 
		return; 
	} 
} 
 
void LLLMINUS(MPMATI **Aptr, MPMATI **Pptr, MPMATI **Lptr, USI j) 
{ 
	USI r, s, m; 
	MPI *Temp; 
	MPMATI *TempMATI; 
 
	m = (*Aptr)->R; 
	for (r = 0; r < m; r++) 
		for (s = 0; s < r; s++) 
		{ 
			if (r == j || s == j) 
			{ 
				Temp = (*Lptr)->V[r][s]; 
				(*Lptr)->V[r][s] = MINUSI(Temp); 
				FREEMPI(Temp); 
			} 
		} 
	 
	TempMATI = *Aptr; 
	Temp = MINUS_ONEI(); 
	*Aptr = SCALAR_ROWI(j, Temp, *Aptr); 
	FREEMPI(Temp); 
	FREEMATI(TempMATI); 
	TempMATI = *Pptr; 
	Temp = MINUS_ONEI(); 
	*Pptr = SCALAR_ROWI(j, Temp, *Pptr); 
	FREEMPI(Temp); 
	FREEMATI(TempMATI); 
	if (HERMITE1VERBOSE) 
	{ 
		printf("Row %u -> - Row %u\n", j + 1,j + 1); 
		printf("P = \n"); 
		PRINTMATI(0,(*Pptr)->R-1,0,(*Pptr)->C-1,*Pptr); 
		printf("A = \n"); 
		PRINTMATI(0,(*Aptr)->R-1,0,(*Aptr)->C-1,*Aptr); 
		GetReturn(); 
	} 
	return; 
} 
 
MPMATI *SCALAR_ROWI(USI p, MPI *Aptr, MPMATI *Mptr) 
/* 
 * multiplying the pth row of *Mptr by *Aptr. 
 */ 
{ 
	unsigned int j; 
	MPI *Temp; 
	MPMATI *Nptr; 
 
	Nptr = COPYMATI(Mptr); 
	for (j = 0; j <= Nptr->C - 1; j++) 
	{ 
		Temp = Nptr->V[p][j]; 
		Nptr->V[p][j] = MULTI(Temp, Aptr); 
		FREEMPI(Temp); 
	} 
	return (Nptr); 
} 
 
USI COLSEEKI0(MPMATI *A, USI i, USI j) 
/* Scans cols >= i, rows >= j for first nonzero column if any. Returns  
 * this column number if ther is one, else returns A->C; 
 */ 
{ 
	USI k, l, n; 
 
	n = A->C; 
	for (k = j; k < n; k++) 
	{ 
		for (l = 0; l <= i; l++) 
		{ 
			if (A->V[l][k]->S) 
				return k; 
		} 
	} 
	return k; 
} 
 
USI FLAGCOLI(MPMATI *Aptr) 
/* 
 * Returns 1 if the first nonzero column of Aptr contains more than one 
 * entry, 0 otherwise.  Only applied to a nonzero matrix with at least  
 * two rows. 
 */ 
{ 
	USI i, j, k, flag = 0, m, n; 
 
	m = Aptr->R; 
	n = Aptr->C; 
	for (j = 0; j < n; j++) 
	{ 
		for (i = 0; i < m; i++) 
		{ 
			if ((Aptr->V[i][j])->S) 
			{ 
				flag = 1; 
				break; 
			} 
		} 
		if (flag) 
		{ 
			for (k = i + 1; k < m; k++) 
			{ 
				if ((Aptr->V[k][j])->S) 
					return (1); 
			} 
			return (0); 
		} 
	} 
	return (0); 
}