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


/* cyclo.c */ 
 
#include  
#include  
#include "integer.h" 
#include "fun.h" 
#define S0 65536 
 
void NEXTPHI(USL p, USL *gptr, MPIA *b, MPIA *coef) 
{ 
	USL cycle, grad, t, lastgrad; 
        int i, j, next; 
	MPI *l, *ZERO, *TEMP, *w; 
 
	ZERO = ZEROI(); 
	cycle=p; 
	grad = *gptr; 
	next=grad; 
	 
	for(i=grad; i>=0; i--){ 
		  if(cycle==p) 
		  { 
		    cycle=1; 
		    TEMP = COPYI(((*coef)->A)[next]); 
		    ADD_TO_MPIA(*b, TEMP, i); 
		    FREEMPI(TEMP); 
		    next=next-1; 
		  }else{ 
		    cycle++; 
		    ADD_TO_MPIA(*b, ZERO, i); 
		  } 
	} 
	lastgrad=grad; 
	grad=grad*(p-1); 
 
	t=grad/2; 
	for(i=grad; i>=t; i--){ 
		  /* PHI = PHI(x^p)/PHI.  First half of the coefficients. */ 
		  l = COPYI(((*b)->A)[lastgrad]); 
		  ADD_TO_MPIA(*coef, l, i); 
		  for(j=lastgrad-1; j>=0; j--) 
		  { 
		    w = MULTI(l, ((*coef)->A)[j]); 
		    TEMP = SUBI(((*b)->A)[j], w); 
		    FREEMPI(w); 
		    ADD_TO_MPIA(*b, TEMP, j+1); 
		    FREEMPI(TEMP); 
		  } 
		  FREEMPI(l); 
		  if(cycle==p) 
		  { 
		    cycle=1; 
		    TEMP = COPYI(((*coef)->A)[next]); 
		    ADD_TO_MPIA(*b, TEMP, 0); 
		    FREEMPI(TEMP); 
	/*	    next--;*/ /*commented out by KRM on 1h26/9/02 */ 
		  } 
		  else 
		  { 
		    cycle++; 
		    ADD_TO_MPIA(*b, ZERO, 0); 
		  } 
	} 
	FREEMPI(ZERO); 
 
	t=grad/2 - 1; 
	for(j = 0; j <= t; j++){ 
            TEMP=COPYI(((*coef)->A)[grad-j]); 
            ADD_TO_MPIA(*coef, TEMP, j); 
            FREEMPI(TEMP); 
	} 
	*gptr = grad; 
} 
 
int NOTYET(USL n, USL i, USL *qptr) 
{ 
	USL q; 
 
	q = n / i; 
	*qptr = q; 
	if ((n > q * i) && (i <= q)) 
		return 1; 
	else 
		return 0; 
} 
 
int LPF(USL n) 
{ 
	USL c, i, q; 
 
	if (n % 2 == 0) return (2); 
	if (n % 3 == 0) return (3); 
	else 
	{ 
		i = 5; 
		c = 0; 
		while (NOTYET(n, i, &q)) 
		{ 
			i = (c == 0) ? i + 2 : i + 4; 
			c = 1 - c; 
		} 
		if (q < i) 
			return (n); 
		else 
			return (i);	 
	} 
} 
 
POLYI CYCLOTOMIC(MPI *N) 
/* This algorithm is from Heinz Luneburg's book Galoisfelder, Kreisteilungs 
 * korper and Schieberegisterfolgen. It was originally coded in CMAT by perhaps Peter Adams. 
 * I imported the code to CALC on 25-26 Seotember 2002, tightening up the code. 
 */ 
 
{ 
	USL n, n1, socn, p, grad; 
	int i; 
	POLYI P; 
	MPI *H, *TEMP, *MINUSONE, *ONE, *ZERO; 
	MPIA b, coef; 
 
	if(N->D){ 
		printf("N >= 65536\n"); 
		return (POLYI)NULL; 
	} 
	MINUSONE = MINUS_ONEI(); 
	ONE = ONEI(); 
	ZERO = ZEROI(); 
 
	n = CONVERTI(N); 
	b = BUILDMPIA(); 
        coef = BUILDMPIA(); 
	n1 = n; 
	if (n1 == 1) 
	{ 
		grad = 1; 
		ADD_TO_MPIA(coef, MINUSONE, 0); 
		ADD_TO_MPIA(coef, ONE, 1); 
	} 
	else 
	{ 
		p = LPF(n1); 
		socn = p; 
		while (n1 % p == 0) 
			n1 = n1 / p; 
		grad = p - 1; 
		for (i = 0; i <= grad; i++){ 
			ADD_TO_MPIA(coef, ONE, i); 
		} 
		/* PHI is the pth cyclotomic polynomial. */ 
			 
		while (n1 > 1) 
		{ 
			p = LPF(n1); 
			socn = socn * p; 
			while (n1 % p == 0) 
				n1 = n1 / p; 
			NEXTPHI(p, &grad, &b, &coef); 
		/* PHI is the socnth cyclotomic polynomial. */		 
		} 
		n1 = n / socn; 
		if (n1 > 1) 
		{ 
		/* PHI = PHI(x^n). */ 
			grad = n1 * grad; 
			for (i = grad; i >= 0; i--) 
			{ 
				if (i % n1 == 0){ 
					TEMP = COPYI((coef->A)[i/n1]); 
					ADD_TO_MPIA(coef, TEMP, i); 
					FREEMPI(TEMP); 
				} 
				else{ 
					ADD_TO_MPIA(coef, ZERO, i); 
				} 
			} 
		}	 
	} 
	FREEMPIA(b); 
	P = NULL; 
	for (i = 0; i <= grad; i++) 
	{ 
		if (((coef->A)[i])->S) 
		{ 
			H = COPYI((coef->A)[i]); 
			PINSERTPI((int)i, H, &P, 0); 
			FREEMPI(H); 
		} 
	} 
	FREEMPIA(coef); 
	FREEMPI(MINUSONE); 
	FREEMPI(ONE); 
	FREEMPI(ZERO); 
	return (P); 
}