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

📄 qres.c

📁 calc大数库
💻 C
字号:
/* qres.c */
#include <stdio.h>
#include <stdlib.h>
#include "integer.h"
#include "fun.h"

int JACOBIB(MPI *N, MPI *M)
/*
 * Evaluates the Jacobi symbol (N/M); M odd, M > 0.
 */
{
	int sign = 1;
	unsigned long parity, t;
	MPI *Tmp, *NN, *MM;

	NN = MOD(N, M);
	if (NN->S == 0)
	{
		FREEMPI(NN);
		return (0);
	}
	MM = COPYI(M); 
	while (1)
	{
		parity = 0;
		while ((NN->V[0] & 1) == 0)
		{
			Tmp = NN;
			NN = INT0_(NN, (USL)2);
			FREEMPI(Tmp);
			parity = 1 - parity;
		}
		if (parity)
		{
			t = MM->V[0] & 7;
			if (t == 3 || t == 5)
				sign = -sign;
		}
		if (EQONEI(NN))
			break;
		if ((MM->V[0] & 3) == 3 && (NN->V[0] & 3) == 3)
			sign = -sign;
		Tmp = NN;
		NN = MOD0(MM, NN);
		FREEMPI(MM);
		if (NN->S == 0)
		{
			FREEMPI(Tmp);
			FREEMPI(NN);
			return (0);
		}
		MM = Tmp;
	}
	FREEMPI(NN);
	FREEMPI(MM);
	return (sign);
}

int JACOBI(USL n, USL m)
/*
 * Evaluates the Jacobi symbol (n/m); m odd, 0 < n < m.
 */
{
	int sign = 1;
	unsigned int parity, temp;
	unsigned long t;
	
	while (1)
	{
		parity = 0;
		while (n % 2 == 0)
		{
			n = n / 2;
			parity = 1 - parity;
		}
		if (parity)
		{
			t = m % 8;
			if (t == 3 || t == 5)
				sign = -sign;
		}
		if (n == 1)
			break;
		if (m % 4 == 3 && n % 4 == 3)
			sign = -sign;
		temp = n;
		n = m %	n;
		if (n == 0)
			return (0);
		m = temp;
	}
	return (sign);
}

void MULTXm(USL a, USL b, USL c, USL d, USL *eptr, USL *fptr, USL x, USL p)
/*
 * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))(c+dsqrt(x)) (mod p). Used in R.C. Peralta's 
 * probabilistic method of finding sqrt(x) (mod p).
 */
{
	unsigned long u, v;

	u = (b * d) % p;
	v = (a * c) % p;
	u = (u * x) % p;
	*eptr = ADDm(v, u, p);
	u = (b * c) % p;
	v = (a * d) % p;
	*fptr = ADDm(v, u, p);
	return;
}

void POWERXm(USL a, USL b, USL n, USL *eptr, USL *fptr, USL x, USL p)
/*
 * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))^n (mod p). Used in R.C. Peralta's 
 * probabilistic method of finding sqrt(x) (mod p).
 */
{
	unsigned long x1, x2, z1, z2;

	x1 = a;
	x2 = b;
	z1 = 1;
	z2 = 0;
	while (n)
	{
		while (n % 2 == 0)
		{
			n = n / 2;
			MULTXm(x1, x2, x1, x2, &x1, &x2, x, p);
		}
		n = n - 1;
		MULTXm(z1, z2, x1, x2, &z1, &z2, x, p);
	}
	*eptr = z1;
	*fptr = z2;
	return;
}

unsigned long SQRTm(USL x, USL 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, 0 < x < p. 
 */
{
	unsigned long r, z, u, v;

	z = (p - 1) / 2;
	if (p % 4 == 3)
		return (POWER_m(x, (z + 1) / 2, p));
	for ( r = 1; r <= z; r++)
	{
		if ( x == (r * r) % p)
			return (r);
		POWERXm(r, (USL)1, z, &u, &v, x, p);
		if (u == 0)
			break;
	}
	return (INVERSEm(v, p));
}

void MULTXM(MPI *a, MPI *b, MPI *c, MPI *d, MPI **eptr, MPI **fptr, MPI *x, MPI *p)
/*
 * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))(c+dsqrt(x)) (mod p). Used in R.C. Peralta's 
 * probabilistic method of finding sqrt(x) (mod p).
 */
{
	MPI *u, *v, *tmp1, *tmp2, *tmp3;

	tmp1 =	MULTI(b, d);
	tmp2 = MOD(tmp1, p);
	FREEMPI(tmp1);
	tmp3 = MULTI(tmp2, x);
	FREEMPI(tmp2);
	u = MOD(tmp3, p);
	FREEMPI(tmp3);
	tmp1 =	MULTI(a, c);
	v = MOD(tmp1, p);
	FREEMPI(tmp1);
	*eptr = ADDM(v, u, p);
	tmp2 = u;
	tmp1 =	MULTI(b, c);
	u = MOD(tmp1, p);
	FREEMPI(tmp1);
	FREEMPI(tmp2);
	tmp2 = v;
	tmp1 =	MULTI(a, d);
	v = MOD(tmp1, p);
	FREEMPI(tmp1);
	FREEMPI(tmp2);
	*fptr = ADDM(v, u, p);
	FREEMPI(u);
	FREEMPI(v);
	return;
}

void POWERXM(MPI *a, MPI *b, MPI *n, MPI **eptr, MPI **fptr, MPI *x, MPI *p)
/*
 * *eptr+(*fptr)*sqrt(x)=(a+b*sqrt(x))^n (mod p). Used in R.C. Peralta's 
 * probabilistic method of finding sqrt(x) (mod p).
 */
{
	MPI *x1, *x2, *x3, *x4, *x5, *x6, *z1, *z2, *tmp, *tmp1, *tmp2, *N;

	x1 = COPYI(a);
	x2 = COPYI(b);
	z1 = ONEI();
	z2 = ZEROI();
	N = COPYI(n);
	while (N->S)
	{
		while ((N->V[0]) % 2 == 0)
		{
			tmp = N;
			N = INT0_(N, (USL)2);
			FREEMPI(tmp);
			tmp1 = x1;
			tmp2 = x2;
			MULTXM(x1, x2, x1, x2, &x3, &x4, x, p);
			x1 = x3;
			x2 = x4;
			FREEMPI(tmp1);
			FREEMPI(tmp2);
		}
		tmp = N;
		N = SUB0_I(N, (USL)1);
		FREEMPI(tmp);
		tmp1 = z1;
		tmp2 = z2;
		MULTXM(z1, z2, x1, x2, &x5, &x6, x, p);
		z1 = x5;
		z2 = x6;
		FREEMPI(tmp1);
		FREEMPI(tmp2);
	}
	*eptr = z1;
	*fptr = z2;
	FREEMPI(x1);
	FREEMPI(x2);
	FREEMPI(N);
	return;
}

MPI *SQRTM(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.
 */
{
	MPI *z, *u, *v, *tmp, *tmp1, *tmp2, *tmp3;
	unsigned int t;
	unsigned long r;

	z = INT0_(p, (USL)2);
	if ((p->V[0]) % 4 == 3)
	{
		tmp = ADD0_I(z, (USL)1);
		FREEMPI(z);
		tmp1 = INT0_(tmp, (USL)2);
		FREEMPI(tmp);
		tmp2 = MPOWER(x, tmp1, p);
		FREEMPI(tmp1);
		return (tmp2);
	}
	tmp = ONEI();
	for ( r = 1; r < R0; r++)
	{
		tmp1 = CHANGE(r);
		tmp2 = MULTI(tmp1, tmp1);
		tmp3 = MOD0(tmp2, p);
		FREEMPI(tmp2);
		t = EQUALI(x, tmp3);
		FREEMPI(tmp3);
		if (t)
		{
			FREEMPI(tmp);
			FREEMPI(z);
	/*		FREEMPI(x); deleted on 10th Dec 2000 */ 
			return (tmp1);
		}
		POWERXM(tmp1, tmp, z, &u, &v, x, p);
		FREEMPI(tmp1);
		if (u->S == 0)
		{
			tmp2 = INVERSEM(v, p);
			FREEMPI(u);
			FREEMPI(v);
			FREEMPI(tmp);
			FREEMPI(z);
			break;
		}
		FREEMPI(u);
		FREEMPI(v);
	}
	return (tmp2);
}

MPI *LUCASU(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.
 */
{
	unsigned int *b, h;
	int i;
	MPI *Y, *R, *S, *T, *U, *V, *Temp0, *Temp, *Temp1, *Temp2;
	
	if (N->S == 0)
		return (ZEROI());
	if (EQONEI(N))
		return(ONEI());
	h = 0;
	b = (USI *)mmalloc(10000 * sizeof(USI));
	Y = COPYI(N);
	while (Y->S)
	{
		b[h] = (Y->V[0]) % 2;
		Temp = Y;
		Y = INT0_(Y, 2);
		FREEMPI(Temp);
		h++;
	}
	R = ZEROI();
	S = ONEI();
	FREEMPI(Y);
	Temp = MINUSI(Q);
	T = MOD(Temp, M);
	FREEMPI(Temp);
	V = ADDM(T, T, M);
	i = h - 1;
	while (1)
	{
		U = S;
		Temp1 = MULTM(V, R, M);
		Temp2 = ADDM(Temp1, S, M);
		S = MULTM(Temp2, S, M);
		FREEMPI(Temp1);
		FREEMPI(Temp2);
		Temp0 = MULTM(R, R, M);
		Temp1 = MULTM(Temp0, T, M);
		FREEMPI(Temp0);
		Temp2 = MULTM(U, U, M);
		FREEMPI(U);
		Temp = R;
		R = ADDM(Temp2, Temp1, M);
		FREEMPI(Temp);
		FREEMPI(Temp1);
		FREEMPI(Temp2);
		i--;
		if (i == -1)
			break;
		if (b[i])
		{
			Temp1 = MULTM(T, R, M);
			FREEMPI(R);
			R = S;
			S = ADDM(S, Temp1, M);
			FREEMPI(Temp1);
		}
	}
	FREEMPI(R);
	FREEMPI(T);
	FREEMPI(V);
	ffree(b, 10000 * sizeof(USI));
	return (S);
}

MPI *LUCASB(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.
 */
{
	unsigned int h;
	MPI *S, *T, *X, *Q, *L, *Temp, *Temp1;
	int d, t, s;

	X = BIG_MTHROOT(N, 2);
	Temp = MULTI(X, X);
	FREEMPI(X);
	if (EQUALI(Temp, N))
	{
		/* N is a perfect square */;
		FREEMPI(Temp);
		return (ZEROI());
	}
	FREEMPI(Temp);
	s = 5;
	t = -7;
	for (h = 0; 1; h++)
	{
		S = CHANGEI(s);
		if (JACOBIB(S, N) == -1)
		{
			FREEMPI(S);
			d = s;
			break;
		}
		FREEMPI(S);
		s = s + 4;
		T = CHANGEI(t);
		if (JACOBIB(T, N) == -1)
		{
			FREEMPI(T);
			d = t;
			break;
		}
		FREEMPI(T);
		t = t -4;
	}
	Q = CHANGEI((1-d)/4);
	Temp = ADD0_I(N, 1);
	Temp1 = INT0_(Temp, 2);
	FREEMPI(Temp);
	L = LUCASU(Temp1, Q, N);
	FREEMPI(Q);
	FREEMPI(Temp1);
	t = L->S;
	FREEMPI(L);
	if (t == 0)/* N is a Lucas probable prime */
		return (ONEI());
	else /* N is composite */
		return (ZEROI());
}

MPI *LUCAS(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.
 */
{
	unsigned int l;
	int t;
	MPI *L;

	l = MILLER(N, 2);
	if (l == 0)
		return (ZEROI());	
	L = LUCASB(N);
	t = L->S;
	FREEMPI(L);
	if (t)
		return (ONEI());	
	else
		return (ZEROI());	
}

MPI *LEASTQNR(MPI *P)
/*
 * Returns NP, the least quadratic non-residue (mod P) if NP < R0.
 * Else returns 0.
 */
{
	MPI *Q, *S, *T;
	unsigned int flag = 0;
	unsigned long i;

	Q = INT0_(P, (USL)2);
	T = MPOWER_((long)2, Q, P);	
	S = SUBI(T, P);
	if (EQMINUSONEI(S))
	{
		FREEMPI(Q);
		FREEMPI(S);
		FREEMPI(T);
		return (CHANGE((USL)2));
	}
	FREEMPI(S);
	FREEMPI(T);
	for (i = 3; i < R0; i = i + 2)
	{
		T = MPOWER_((long)i, Q, P);	
		S = SUBI(T, P);
		if (EQMINUSONEI(S))
		{
			FREEMPI(S);
			FREEMPI(T);
			flag = 1;
			break;
		}
		FREEMPI(S);
		FREEMPI(T);
	}
	FREEMPI(Q);
	if (flag)
		return (CHANGE(i));
	else
		return(ZEROI());
}

⌨️ 快捷键说明

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