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


/* func.c */ 
#include  
#include "integer.h" 
#include "fun.h" 
 
unsigned int VERBOSE; 
unsigned int FREE_PRIMES; 
extern unsigned long PRIME[]; 
unsigned int ECMAX; 
 
MPI *FACTORX(MPI *N) 
{ 
	unsigned int z; 
 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
	  printf("N <= 1\n"); 
	  return NULL; 
	} 
	printf("enter the number of elliptic curves to be used:"); 
	scanf("%u", &ECMAX); 
	getchar(); 
	VERBOSE = 1; 
	FREE_PRIMES = 1; 
	z = FACTOR(N); 
	VERBOSE = 0; 
	FREE_PRIMES = 0; 
	if (z == 0) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (CHANGE(z)); 
} 
 
/* Returns NULL on failure.  Wrapper handles this. */ 
MPI *Nextprime(MPI *N) 
{ 
	MPI *tmp; 
	if (N->S < 0 ) 
	{ 
	  printf("N <= 0\n"); 
	  return NULL; 
	} 
	tmp = NEXT_PRIMEX(N); 
	return(tmp); 
} 
 
MPI *JACOB(MPI *M, MPI *N) 
/* 
 * Evaluates the Jacobi symbol (M/N); N odd, N > 0. 
 */ 
{ 
	int t; 
	MPI *MM; 
 
	if (MOD0_(N, (USL)2) == 0) 
	{ 
	  printf("N is even\n"); 
	  return NULL; 
	} 
	if (N->S < 0) 
	{ 
	  printf("N is negative\n"); 
	  return NULL; 
	} 
	MM = MOD(M, N); 
	if (N->D == 0) 
		t = JACOBI(CONVERTI(MM), CONVERTI(N)); 
	else	 
		t = JACOBIB(MM, N); 
	FREEMPI(MM); 
	if (t == 0) 
		return(ZEROI()); 
	else if (t == 1) 
		return( ONEI()); 
	else 
		return( MINUS_ONEI()); 
} 
 
 
MPI *GCD_ARRAYVX(MPIA M, MPIA *Y) 
/* 
 * Returns d=gcd(M[0],...,M[N-1]) and an array Y[] of MPI's such that 
 * d = M[0]*Y[0]+...+M[N-1]*Y[N-1]. Here N > 1. 
 */ 
{ 
	MPI *Z; 
	MPIA V; 
 
	Z = GCD_ARRAYV(M, &V); 
	*Y = V;	 
	return (Z); 
} 
MPI *SQRTMX(MPI *x, MPI *p) 
/* 
 * Calculates sqrt(x) (mod p) using "A simple and fast probabilistic algorithm 
 * for computing square roots modulo a prime number", I.E.E.E. Trans. Inform. 
 * Theory, IT-32, 1986, 846-847, R. Peralta. 
 * Here x is a quadratic residue mod p. x can be negative. 
 * Returns NULL on failure.  This is taken care of by wrapper.  
 */ 
{ 
	unsigned long X, P, Z; 
	MPI *M, *N=NULL, *T; 
	int t; 
 
	if (p->S <= 0 || (p->D == 0 && p->V[0] <= 2)) 
	{ 
	  printf("p <= 2\n"); 
	} 
	T = LUCAS(p); 
	t = T->S; 
	FREEMPI(T); 
	if (!t) 
	{ 
	  printf("2nd argument is not a prime\n"); 
	  return N; 
	} 
	if (JACOBIB(x, p) != 1) 
	{ 
	  printf("x is not a quadratic residue mod p\n"); 
	  return N; 
	} 
	if (p->D == 0) 
	{ 
		M = MOD(x, p); 
		X = CONVERTI(M); 
		P = CONVERTI(p); 
		Z = SQRTm(X, P); 
		FREEMPI(M); 
		return(CHANGE(Z)); 
	} 
	else 
	{ 
		N = SQRTM(x, p); 
		return (N); 
	} 
} 
 
MPI *CONGRX(MPI *A, MPI *B, MPI *M, MPI **N) 
/* 
 * Returns the least solution (mod N) of the congruence AX=B(mod M), where 
 * N = M / gcd(A, M). 
 * returns NULL if function fails. Handled by wrapper CONGRX_W. 
 */ 
{ 
	MPI *Z=NULL; 
 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
	  printf("M <= 1\n"); 
	  *N = ZEROI(); 
	  return Z; 
	} 
	Z = CONGR(A, B, M, N); 
	if (Z == NULL) 
	{ 
	  printf("the congruence has no solution\n"); 
	  *N = ZEROI(); 
	} 
	return (Z); 
} 
 
MPI *CHINESEX(MPI *A, MPI *B, MPI *M, MPI *N, MPI **Mptr) 
/* 
 * Returns the solution mod *Mptr=lcm[M,N] of the congruences X = A (mod M) 
 * and X = B (mod N), if soluble. 
 * Returns NULL if it failed.  This case is handled by wrapper CHINESEX_W. 
 */ 
{ 
	MPI *Z=NULL; 
		 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
	  printf("M <= 1\n"); 
	  *Mptr = ZEROI(); 
	  return(Z); 
	} 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
	  printf("N <= 1\n"); 
	  *Mptr = ZEROI(); 
	  return(Z); 
	} 
	Z = CHINESE(A, B, M, N, Mptr); 
	if (Z == NULL) 
	{ 
	  printf("the system has no solution\n"); 
	  *Mptr = ZEROI(); 
	} 
	  return (Z); 
} 
 
MPI *CHINESE_ARRAYX(MPIA A, MPIA M, MPI **Mptr) 
/* 
 * Returns the solution mod *Mptr=lcm[M[0],...,M[n-1] of the congruences 
 * X = A[i] (mod M[i]),0 <= i < N, if soluble; otherwise returns NULL. 
 */ 
{ 
	unsigned int i, n; 
	MPI *Z; 
 
	n = ((A->size >= M->size) ? M->size: A->size); 
	for (i = 0; i < n; i++) 
	{ 
		if (M->A[i]->S <= 0 || (M->A[i]->D == 0 && M->A[i]->V[0] == 1)) 
		{ 
		  *Mptr = ZEROI(); 
		  printf("M[i] <= 1\n"); 
		  return NULL; 
		} 
	} 
	Z = CHINESE_ARRAY(A->A, M->A, Mptr, n); 
	if (Z == NULL) 
	{ 
	  *Mptr = ZEROI(); 
	  printf("the system has no solution\n"); 
	  return NULL; 
 
	} 
	return (Z); 
} 
 
void MTHROOTX(MPI *Aptr, MPI *Bptr, MPI *M, MPI *R) 
/* 
 * *Aptr and *Bptr are positive MPI'S. 
 * The mthroot of *Aptr/(*Bptr) is computed to R decimal places, R >= 0 ; 
 * M, R are integers, 0 < M * R < R0 * R0. 
 */ 
{ 
	unsigned int m, r; 
 
	if (Aptr->S < 0 || Bptr->S <= 0 ) 
	{ 
	  printf("Numerator or denominator <= 0\n"); 
	  return; 
	} 
	if (M->S <= 0 || M->D >= 1 || M->V[0] == 1) 
	{ 
	  printf("m <= 1 or m >= R0\n"); 
	  return; 
	} 
	if (R->S < 0 || R->D >= 1) 
	{ 
	  printf("r < 0 or r >= R0\n"); 
	  return; 
	} 
	m = CONVERTI(M); 
	r = CONVERTI(R); 
	MTHROOT(Aptr, Bptr, m, r); 
	return ; 
} 
 
MPI *BIG_MTHROOTX(MPI *Aptr, MPI *M) 
/* 
 * *Eptr, the integer part of the Mth root of the positive MPI *Aptr, 
 * 1 < M < R0, is obtained by Newton's method, using the integer part function. 
 * Returns NULL on failure.  Handled by wrapper function.  
 */ 
{ 
	unsigned int m; 
	if (Aptr->S <= 0) 
	{ 
	  printf("argument <= 0\n"); 
	  return NULL; 
	} 
	if (M->S <= 0 || M->D >= 1 || M->V[0] == 1) 
	{ 
	  printf("m <= 1 or m >= R\n"); 
	  return NULL; 
	} 
	m = CONVERTI(M); 
	return (BIG_MTHROOT(Aptr, m)); 
} 
 
MPI  *FUND_UNITX(MPI *D, MPI **Xptr, MPI **Yptr) 
/* 
 * This is a program for finding the fundamental unit of Q(sqrt(D)). 
 * The algorithm is based on K. Rosen, Elementary number theory 
 * and its applications, p382, B.A. Venkov, Elementary Number theory, p.62  
 * and D. Knuth, Art of computer programming, Vol.2, p359, with Pohst's trick  
 * of using half the period. 
 * w=(1+sqrt(D))/2 if D=1 (mod 4), w=sqrt(D) otherwise. 
 * The norm of the fundamental unit is returned. 
 * 
 * Returns NULL on failure.  Wrapper function handles this. 
 */ 
{ 
	MPI *G, *X, *tmp; 
	unsigned int t; 
 
	if (D->S <= 0) 
	{ 
	  printf("D <= 0\n"); 
	  *Xptr = ZEROI(); 
	  *Yptr = ZEROI(); 
	  return NULL; 
	} 
	X = BIG_MTHROOT(D, 2); 
	G = MULTI(X, X); 
	t = EQUALI(D, G); 
	FREEMPI(G); 
	FREEMPI(X); 
	if (t) 
	{ 
		printf("D is a perfect square\n"); 
		*Xptr = ZEROI(); 
		*Yptr = ZEROI(); 
		return NULL; 
	} 
	tmp = FUND_UNIT(D, Xptr, Yptr); 
	return (tmp); 
} 
 
MPI  *PELX(MPI *D, MPI *E, MPI **Xptr, MPI **Yptr) 
/* 
 * This is a program for finding the least solution of Pell's equation 
 * x*x - D*y*y = +-1. 
 * The algorithm is based on K. Rosen, Elementary number theory 
 * and its applications, p382, B.A. Venkov, Elementary Number theory, p.62  
 * and D. Knuth, Art of computer programming, Vol.2, p359, with Pohst's trick  
 * of using half the period. 
 * The norm of the least solution is returned. 
 * The partial quotients are printed iff E->S != 0. 
 * 
 * Returns NULL on failure.  Wrapper handles this. 
 */ 
{ 
	MPI *G, *X, *tmp; 
	unsigned int t; 
 
	if (D->S <= 0) 
	{ 
	  printf("D <= 0\n"); 
	  *Xptr = ZEROI(); 
	  *Yptr = ZEROI(); 
	  return NULL; 
	} 
	X = BIG_MTHROOT(D, 2); 
	G = MULTI(X, X); 
	t = EQUALI(D, G); 
	FREEMPI(G); 
	FREEMPI(X); 
	if (t) 
	{ 
	  printf("D is a perfect square\n"); 
	  *Xptr = ZEROI(); 
	  *Yptr = ZEROI(); 
	  return NULL; 
	} 
	tmp = PEL(D, E, Xptr, Yptr); 
	return (tmp); 
} 
 
MPI *SURDX(MPI *D, MPI *T, MPI *U, MPI *V, MPIA *A_ARRAY, MPIA *U_ARRAY, MPIA *V_ARRAY, MPIA *P_ARRAY, MPIA *Q_ARRAY) 
/* 
 * This function uses the continued fraction algorithm expansion in K. Rosen, 
 * Elementary Number theory and its applications,p.379-381 and Knuth's 
 * The art of computer programming, Vol.2, p. 359. It locates the first complete 
 * quotient that is reduced and then uses the function REDUCED(D,U,V,i) above 
 * to locate and return the period of the continued fraction expansion. 
 * 
 * Returns NULL on failure.  Wrapper handles this.  
 */ 
{ 
	MPI *G, *X; 
	unsigned int t; 
	unsigned long f; 
 
	if (D->S <= 0) 
	{ 
	  printf("D <= 0\n"); 
	  return NULL; 
	} 
	X = BIG_MTHROOT(D, 2); 
	G = MULTI(X, X); 
	f = EQUALI(D, G); 
	FREEMPI(G); 
	FREEMPI(X); 
	if (f) 
	{ 
	  printf("D is a perfect square\n"); 
	  return NULL; 
	} 
	if (V->S == 0) 
	{ 
	  printf("V = 0\n"); 
	  return NULL; 
	} 
	t = SURD(D, T, U, V, A_ARRAY, U_ARRAY, V_ARRAY, P_ARRAY, Q_ARRAY, 0); 
	return (CHANGE((USL)t)); 
} 
 
MPI *MPOWERX(MPI *Aptr, MPI *Bptr, MPI *Cptr) 
/* 
 * *Aptr, *Bptr, *Cptr, *Eptr  are MPI'S, *Cptr > 0, *Bptr >= 0, 
 * (*Aptr)^ *Bptr (mod *Cptr) is returned. 
 *  
 * Returns NULL on failure.  Handled by wrapper. 
 */  
{ 
	if (Cptr->S <= 0) 
	{ 
	  printf("Modulus <= 0\n"); 
	  return NULL; 
	} 
	if (Cptr->D == 0 && Cptr->V[0] == 1) 
	{ 
	  printf("Modulus = 1\n"); 
	  return NULL; 
	} 
	return (MPOWER(Aptr, Bptr, Cptr)); 
} 
 
MPI *INVERSEMX(MPI *A, MPI *M) 
/* 
 * Returns the inverse of A mod M. 
 */ 
{ 
	MPI *temp, *Z; 
	unsigned int t; 
 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
	  printf("M <= 1\n"); 
	  return NULL; 
	} 
	temp = GCD(A, M); 
	t = EQONEI(temp); 
	FREEMPI(temp); 
	if (!t) 
	{ 
	  printf("A is not relatively prime to M\n"); 
	  return NULL; 
	} 
	temp = MOD(A, M); 
	Z = INVERSEM(temp, M); 
	FREEMPI(temp); 
	return (Z); 
} 
 
void MILLERX(MPI *N, MPI *B) 
/* 
 * *N is odd, > 1, and does not divide b, 0 < b < R0. 
 *  If *N passes Miller's test for base *B, *N is likely to be prime. 
 * If *N fails Miller's test for base *B, then *N is composite. 
 */ 
{ 
	unsigned long b, r; 
	int t; 
	MPI *M; 
 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
	  printf("N <= 1\n"); 
	  return; 
	} 
	if (B->S <= 0 || B->D >= 1 || B->V[0] == 1) 
	{ 
	  printf("BASE <= 1 or BASE >= R0\n"); 
	  return; 
	} 
	if (N->V[0] %2 == 0) 
	{ 
	  printf("N is even\n"); 
	  return; 
	} 
	M = MOD0(B, N); 
	t = M->S; 
	FREEMPI(M); 
	if (t == 0) 
	{ 
	  printf("N divides base\n"); 
	  return; 
	} 
	b = CONVERTI(B);	 
	r = MILLER(N, b);	 
	PRINTI(N); 
	if (r) 
		printf(" passes Miller's test to base %lu\n", b); 
	else 
		printf(" fails Miller's test to base %lu\n", b); 
	return; 
} 
 
MPI *DIVISORX(MPI *N) 
/* Returns the number of divisors of N.  
 * Returns NULL on failure.  Handled by wrapper */ 
{ 
	MPI *M; 
 
	if (N->S <= 0) 
	{ 
	  printf("N <= 0\n"); 
	  return NULL; 
	} 
	M = DIVISOR(N); 
	if (M == NULL) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (M); 
} 
 
MPI *MOBIUSX(MPI *N) 
/* Returns  Mu(N). */ 
{ 
	MPI *M; 
 
	if (N->S <= 0) 
	{ 
	  printf("N <= 0\n"); 
	  return NULL; 
	} 
	M = MOBIUS(N); 
	if (M == NULL) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (M); 
} 
 
MPI *EULERX(MPI *N) 
/* Returns Euler's function phi(N). */ 
{ 
	MPI *M; 
 
	if (N->S <= 0) 
	{ 
	  printf("N <= 0\n"); 
	  return NULL; 
	} 
	M = EULER(N); 
	if (M == NULL) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (M); 
} 
 
MPI *SIGMAX(MPI *N) 
/* Returns sigma(N), the sum of the divisors of N. */ 
{ 
	MPI *M; 
 
	if (N->S <= 0) 
	{ 
	  printf("N <= 0\n"); 
	  return NULL; 
	} 
	M = SIGMA(N); 
	if (M == NULL) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (M); 
} 
 
MPI *LPRIMROOTX(MPI *P) 
/* Returns the least primitive root mod P. */ 
{ 
	MPI *M; 
 
	if (P->S <= 0 || (P->D == 0 && P->V[0] == 1)) 
	{ 
	  printf("P <= 1\n"); 
	  return NULL; 
	} 
	M = LPRIMROOT(P); 
	if (M->S  == 0) 
	{ 
	  printf("factorization of P-1 unsuccessful\n"); 
	  return NULL; 
	} 
	return (M); 
} 
 
MPI *ORDERPX(MPI *A, MPI *P) 
/* 
 * Returns the order of A mod P, a prime. 
 */ 
{ 
	if (P->S <= 0 || (P->D == 0 && P->V[0] == 1)) 
	{ 
	  printf("P <= 1\n"); 
	  return NULL; 
	} 
	return (ORDERP(A, P)); 
} 
 
MPI *ORDERQX(MPI *A, MPI *P, MPI *N) 
/* 
 * Returns the order of A mod P^N, P a prime. 
 */ 
{ 
	unsigned int n; 
 
	if (N->S <= 0 || N->D || (N->D == 0 && (N->V[0] > 1000))) 
	{ 
	  printf("N <= 0 or N > 1000\n"); 
	  return NULL; 
	} 
	if (P->S <= 0 || (P->D == 0 && P->V[0] == 1)) 
	{ 
	  printf("P <= 1\n"); 
	  return NULL; 
	} 
	n = (USI)(CONVERTI(N)); 
	return (ORDERQ(A, P, n)); 
} 
 
MPI *ORDERMX(MPI *A, MPI *M) 
/* 
 * Returns the order of A mod M. 
 */ 
{ 
	MPI *G; 
	unsigned int t; 
 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
	  printf("M <= 1\n"); 
	  return NULL; 
	} 
	G = GCD(A, M); 
	t = EQONEI(G); 
	FREEMPI(G); 
	if (!t) 
	{ 
	  printf("GCD(A, M) > 1\n"); 
	  return NULL; 
	} 
	return (ORDERM(A, M)); 
} 
 
MPI *LUCASUX(MPI *N, MPI *Q, MPI *M) 
/* 
 * returns U_n (mod m), where U_{k+1}=U_k-qU_{k-1}, U_0=0,U_1=1. 
 * D=1-4q != 0. 
 * We use the recurrence relations: 
 * U_{k+1}=U_k-qU_{k-1}, 
 * U_{2k}=-2qU_{k-1}U_k+U_kU_k, 
 * U_{2k-1}=U_kU_k-qU_{k-1}U_{k-1} 
 * See Niven, Zuckermann and Montgomery, p.202. 
 * Also D. Bressoud, Factorization and Primality Testing, p.179-191 and  
 * C. Pomerance, Kent State Lecture Notes, 19-22. 
 */ 
{ 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
		FREEMPI(N); FREEMPI(Q); FREEMPI(M); 
		execerror("M <= 1", ""); 
	} 
	return (LUCASU(N, Q, M)); 
} 
 
MPI *LUCASBX(MPI *N) 
/* 
 * Let N > 1 be odd. Then LUCASB(N) determines an integer D(!=-3) of the form 
 * 4m+1,  such that the Jacobi symbol j(D,N)= -1. Then with Q=(1-d)/4, the Lucas 
 * pseudoprime test examines L=U_{(N+1)/2}mod N. If L=0, N is a Lucas probable  
 * prime, otherwise N is composite. See "The Pseudoprimes to 25.10^9",  
 * Mathematics of computation, 35 (1980) 1003-1026. At the end of this paper  
 * it is conjectured that if N is a strong base 2 pseudoprime and a Lucas  
 * probable prime, then N is in fact a prime. A $30 prize is offered for a   
 * counterexample. 
 * if LUCASB(N) = 1, then N is a Lucas probable prime, else N is composite. 
 * Returns NULL if N is a perfect square. 
 */ 
{ 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
		FREEMPI(N); 
		execerror("N <= 1", ""); 
	} 
	if ((N->V[0]) % 2 == 0) 
	{ 
		FREEMPI(N); 
		execerror("N is even", ""); 
	} 
	return (LUCASB(N)); 
} 
 
MPI *LUCASX(MPI *N) 
/* Here N is odd and > 1. 
 * If LUCAS(N) returns 1, then N is a strong base 2 pseudoprime and a Lucas 
 * probable prime; if LUCAS(N) returns 0, then N is composite. 
 * See "The Pseudoprimes to 25.10^9", Mathematics of computation, 35 (1980) 
 * 1003-1026. At the end of this paper it is conjectured that if N is a strong 
 * base 2 pseudoprime and a Lucas probable prime, then N is in fact a prime.  
 * A $30 prize is offered for a counterexample. 
 */ 
{ 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
	  printf("N <= 1\n"); 
	  return NULL; 
	} 
	if ((N->V[0]) % 2 == 0) 
	{ 
	  printf("N is even\n"); 
	  return NULL; 
	} 
	return (LUCAS(N)); 
} 
 
MPI *LENGTHX(MPI *N) 
/* Returns the number of decimal digits of N. */ 
{ 
	unsigned long z; 
 
	z = LENGTHI(N); 
	if (N->S < 0) 
		z--; 
	return (CHANGE(z)); 
} 
 
MPI *MULT32X(MPI *X, MPI *Y) 
{ 
	USL x, y, z; 
 
	x = CONVERTI(X); 
	y = CONVERTI(Y); 
	z = MULT32(x, y); 
	return (CHANGE(z)); 
} 
 
MPI *NEXTPRIMEAPX(MPI *A, MPI *B, MPI *M) 
/* 
 * Finds the first Lucas probable prime P, A | P - B, M <= P. 
 * Here A is even, B is odd, A > B >= 1, gcd(A,B) = 1, M > 1. 
 */ 
{ 
	MPI *tmp1; 
	unsigned int s; 
 
	if (A->V[0] % 2) 
	{ 
	  printf("A is odd\n"); 
	  return NULL; 
	} 
	if (B->V[0] % 2 == 0) 
	{ 
	  printf("B is even\n"); 
	  return NULL; 
	} 
	if (A->S <= 0 || (A->D == 0 && A->V[0] == 1)) 
	{ 
	  printf("A <= 1\n"); 
	  return NULL; 
	} 
	if (B->S <= 0) 
	{ 
	  printf("B <= 0\n"); 
	  return NULL; 
	} 
	if (M->S <= 0 || (M->D == 0 && M->V[0] == 1)) 
	{ 
	  printf("M <= 1\n"); 
	  return NULL; 
	} 
	if (RSV(A, B) <= 0) 
	{ 
	  printf("A <= B\n"); 
	  return NULL; 
	} 
	tmp1 = GCD(A, B); 
	s = EQONEI(tmp1); 
	FREEMPI(tmp1); 
	if (!s) 
	{ 
	  printf("GCD(A,B) > 1\n"); 
	  return NULL; 
	} 
	return (NEXTPRIMEAP(A, B, M)); 
} 
void SHALLIT() 
{ 
	MPI *K, *N, *tmp, *L, *M; 
	unsigned int i; 
 
	K = ONEI(); 
	L = ONEI(); 
	VERBOSE=1; 
	for (i = 2; i <= 20; i++) 
	{ 
		M = CHANGE(4 * i - 2); 
		tmp = MULTI(M, L); 
		FREEMPI(M); 
		N = ADD0I(tmp, K); 
		FREEMPI(tmp); 
		FACTOR(N); 
		printf("completed K[%u]\n", i); 
		printf("is the factorization of K[%u] = ", i); 
		PRINTI(N); 
		printf("\n"); 
		FREEMPI(K); 
		K = L; 
		L = N; 
	} 
	VERBOSE=0; 
	FREEMPI(K); 
	FREEMPI(L); 
} 
 
MPI *EFACTORX(MPI *N, MPI *M, MPI *P) 
/* Elliptic curve factoring.  
 * Warning: 2329 is the number of array elements in PRIMEPOWERS[]  
 * in primepow.h 
 */ 
{ 
	MPI *Z; 
	unsigned long m, p; 
 
	if (N->S <= 0 || (N->D == 0 && N->V[0] == 1)) 
	{ 
	  printf("N <= 1\n"); 
	  return NULL; 
	} 
	if (M->S <= 0 || (M->D == 0 && M->V[0] <= 10)) 
	{ 
	  printf("M <= 0 or M <= 10\n"); 
	  return NULL; 
	} 
	if ((M->D == 0 && (M->V[0] > 2328)) || M->D) 
	{ 
	  printf("M > 2328\n"); 
	  return NULL; 
	} 
	if (P->S <= 0 || P->D >= 2) 
	{ 
	  printf("P <= 0 or P >= 2^32\n"); 
	  return NULL; 
	} 
	m = CONVERTI(M); 
	p = CONVERTI(P); 
	Z = EFACTOR(N, m, p); 
	if (Z == NULL) 
	{ 
	  printf("Factorization unsuccessful\n"); 
	  return NULL; 
	} 
	return (Z); 
} 
void ABS_NEAREST_INTRX() 
{ 
	unsigned int u; 
	MPI *tempI, *G, *S; 
	MPR *R; 
 
	R = BUILDMPR(); 
	printf("enter the numerator:"); 
	R->N = INPUTI(&u); 
	Flush(); 
	printf("enter the denominator (> 0):"); 
	R->D = INPUTI(&u); 
	Flush(); 
	G = GCD(R->N, R->D); 
	tempI = R->N; 
	R->N = INT(R->N, G); 
	FREEMPI(tempI); 
	tempI = R->D; 
	R->D = INT(R->D, G); 
	FREEMPI(tempI); 
	FREEMPI(G); 
	S = ABS_NEAREST_INTR(R); 
	printf("abs-nearest-int of "); PRINTR(R); printf("=");  PRINTI(S); 
        printf("\n"); 
	FREEMPI(S); 
	FREEMPR(R); 
	return; 
} 
 
 
MPI *FIBONACCI(USI n) 
/* 
 * Returns the nth Fibonacci number. 
 */ 
{ 
	MPI *A, *B, *C; 
	USI i; 
 
	C = NULL; 
	if (n == 0) 
		return(ZEROI()); 
	if (n == 1) 
		return(ONEI()); 
	A = ZEROI(); 
	B = ONEI(); 
	for (i = 2; i <= n; i++) 
	{ 
		C = ADD0I(A, B); 
		FREEMPI(A); 
		A = B; 
		B = C; 
	} 
	FREEMPI(A); 
	return(C); 
} 
MPI *LUCASS(USI n) 
/* 
 * Returns the nth Lucas number. 
 */ 
{ 
	MPI *A, *B, *C, *THREE; 
	USI i; 
 
	C = NULL; 
	THREE = BUILDMPI(1); 
	THREE->S = 1; 
	THREE->V[0] = 3; 
	if (n == 0) 
		return(ONEI()); 
	if (n == 1) 
		return(THREE); 
	A = ZEROI(); 
	B = ONEI(); 
	for (i = 2; i <= n; i++) 
	{ 
		C = ADD0I(A, B); 
		FREEMPI(A); 
		A = B; 
		B = C; 
	} 
	FREEMPI(A); 
	return(C); 
}