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

📄 zprime.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 3 页
字号:
 * * NOTE: This routine will not return a factor == the test value *	 except when the test value is 1 or -1. */FLAGzfactor(ZVALUE n, ZVALUE zlimit, ZVALUE *res){	FULL f;			/* factor found, or 0 */	/*	 * determine the limit	 */	if (zge32b(zlimit)) {		/* limit is too large to be reasonable */		return -1;	}	n.sign = 0;		/* ignore sign of n */	/*	 * find the smallest factor <= limit, if possible	 */	f = small_factor(n, ztofull(zlimit));	/*	 * report the results	 */	if (f > 0) {		/* return factor if requested */		if (res) {			utoz(f, res);		}		/* report a factor was found */		return 1;	}	/* no factor was found */	return 0;}/* * Find a smallest prime factor <= some small (32 bit) limit of a value * * given: *	z		number to factor *	limit		largest factor we will test * * Returns: *	0	no prime <= the limit was found *	!= 0	the smallest prime factor */static FULLsmall_factor(ZVALUE z, FULL limit){	FULL top;			/* current max factor level */	CONST unsigned short *tp;	/* pointer to a tiny prime */	FULL factlim;			/* highest factor to test */	CONST unsigned short *p;	/* test factor */	FULL factor;			/* test factor */	HALF tlim;			/* limit on prime table use */	HALF divval[2];			/* divisor value */	ZVALUE div;			/* test factor/divisor */	ZVALUE tmp;	CONST unsigned char *j;	/*	 * catch impossible ranges	 */	if (limit < 2) {		/* range is too small */		return 0;	}	/*	 * perform the even test	 */	if (ziseven(z)) {		if (zistwo(z)) {			/* z is 2, so don't return 2 as a factor */			return 0;		}		return 2;	/*	 * value is odd	 */	} else if (limit == 2) {		/* limit is 2, value is odd, no factors will ever be found */		return 0;	}	/*	 * force the factor limit to be odd	 */	if ((limit & 0x1) == 0) {		--limit;	}	/*	 * case: number to factor fits into a FULL	 */	if (!zgtmaxufull(z)) {		FULL val = ztofull(z);	/* find the smallest factor of val */		FULL isqr;		/* sqrt of val */		/*		 * special case: val is a prime <= MAX_MAP_PRIME		 */		if (val <= MAX_MAP_PRIME && pr_map_bit(val)) {			/* z is prime, so no factors will be found */			return 0;		}		/*		 * we need not search above the sqrt of val		 */		isqr = fsqrt(val);		if (limit > isqr) {			/* limit is largest odd value <= sqrt of val */			limit = ((isqr & 0x1) ? isqr : isqr-1);		}		/*		 * search for a small prime factor		 */		top = ((limit < MAX_MAP_VAL) ? limit : MAX_MAP_VAL);		for (tp = prime; *tp <= top && *tp != 1; ++tp) {			if (val%(*tp) == 0) {				return ((FULL)*tp);			}		}#if FULL_BITS == 64		/*		 * Our search will carry us beyond the prime table.  We will		 * continue to values until we reach our limit or until a		 * factor is found.		 *		 * It is faster to simply test odd values and ignore non-prime		 * factors because the work needed to find the next prime is		 * more than the work one saves in not factor with non-prime		 * values.		 *		 * We can improve on this method by skipping odd values that		 * are a multiple of 3, 5, 7 and 11.  We use a table of		 * bytes that indicate the offsets between odd values that		 * are not a multiple of 3,4,5,7 & 11.		 */		/* XXX - speed up test for large z by using gcds */		j = jmp + jmpptr(NXT_MAP_PRIME);		for (top=NXT_MAP_PRIME; top <= limit; top += nxtjmp(j)) {			if ((val % top) == 0) {				return top;			}		}#endif /* FULL_BITS == 64 */		/* no prime factors found */		return 0;	}	/*	 * Find a factor of a value that is too large to fit into a FULL.	 *	 * determine if/what our sqrt factor limit will be	 */	if (zge64b(z)) {		/* we have no factor limit, avoid highest factor */		factlim = MAX_SM_PRIME-1;	} else if (zge32b(z)) {		/* determine if limit is too small to matter */		if (limit < BASE) {			factlim = limit;		} else {			/* find the isqrt(z) */			if (!zsqrt(z, &tmp, 0)) {				/* sqrt is exact */				factlim = ztofull(tmp);			} else {				/* sqrt is inexact */				factlim = ztofull(tmp)+1;			}			zfree(tmp);			/* avoid highest factor */			if (factlim >= MAX_SM_PRIME) {				factlim = MAX_SM_PRIME-1;			}		}	} else {		/* determine our factor limit */		factlim = fsqrt(ztofull(z));		if (factlim >= MAX_SM_PRIME) {			factlim = MAX_SM_PRIME-1;		}	}	if (factlim > limit) {		factlim = limit;	}	/*	 * walk the prime table looking for factors	 *	 * XXX - consider using gcd of products of primes to speed this	 *	 section up	 */	tlim = (HALF)((factlim >= MAX_MAP_PRIME) ? MAX_MAP_PRIME-1 : factlim);	div.sign = 0;	div.v = divval;	div.len = 1;	for (p=prime; (HALF)*p <= tlim; ++p) {		/* setup factor */		div.v[0] = (HALF)(*p);		if (zdivides(z, div))			return (FULL)(*p);	}	if ((FULL)*p > factlim) {		/* no factor found */		return (FULL)0;	}	/*	 * test the highest factor possible	 */	div.v[0] = MAX_MAP_PRIME;	if (zdivides(z, div))		return (FULL)MAX_MAP_PRIME;	/*	 * generate higher test factors as needed	 *	 * XXX - consider using gcd of products of primes to speed this	 *	 section up	 */#if BASEB == 16	div.len = 2;#endif	factor = NXT_MAP_PRIME;	j = jmp + jmpptr(factor);	for(; factor <= factlim; factor += nxtjmp(j)) {		/* setup factor */#if BASEB == 32		div.v[0] = (HALF)factor;#else		div.v[0] = (HALF)(factor & BASE1);		div.v[1] = (HALF)(factor >> BASEB);#endif		if (zdivides(z, div))			return (FULL)(factor);	}	if (factor >= factlim) {		/* no factor found */		return (FULL)0;	}	/*	 * test the highest factor possible	 */#if BASEB == 32	div.v[0] = MAX_SM_PRIME;#else	div.v[0] = (MAX_SM_PRIME & BASE1);	div.v[1] = (MAX_SM_PRIME >> BASEB);#endif	if (zdivides(z, div))		return (FULL)MAX_SM_PRIME;	/*	 * no factor found	 */	return (FULL)0;}/* * Compute the product of the primes up to the specified number. */voidzpfact(ZVALUE z, ZVALUE *dest){	long n;				/* limiting number to multiply by */	long p;				/* current prime */	CONST unsigned short *tp;	/* pointer to a tiny prime */	CONST unsigned char *j;		/* current jump increment */	ZVALUE res, temp;	/* firewall */	if (zisneg(z)) {		math_error("Negative argument for factorial");		/*NOTREACHED*/	}	if (zge24b(z)) {		math_error("Very large factorial");		/*NOTREACHED*/	}	n = ztolong(z);	/*	 * Deal with table lookup pfact values	 */	if (n <= MAX_PFACT_VAL) {		utoz(pfact_tbl[n], dest);		return;	}	/*	 * Multiply by the primes in the static table	 */	utoz(pfact_tbl[MAX_PFACT_VAL], &res);	for (tp=(&prime[NXT_PFACT_VAL]); *tp != 1 && (long)(*tp) <= n; ++tp) {		zmuli(res, *tp, &temp);		zfree(res);		res = temp;	}	/*	 * if needed, multiply by primes beyond the static table	 */	j = jmp + jmpptr(NXT_MAP_PRIME);	for (p = NXT_MAP_PRIME; p <= n; p += nxtjmp(j)) {		FULL isqr;	/* isqrt(p) */		/* our factor limit - see next_prime for why this works */		isqr = fsqrt(p)+1;		if ((isqr & 0x1) == 0) {			--isqr;		}		/* ignore Saber-C warning #530 about empty for statement */		/*	  ok to ignore in proc zpfact */		/* find the next prime */		for (tp=prime; (*tp <= isqr) && (p % (long)(*tp)); ++tp) {		}		if (*tp <= isqr && *tp != 1) {			continue;		}		/* multiply by the next prime */		zmuli(res, p, &temp);		zfree(res);		res = temp;	}	*dest = res;}/* * Perform a probabilistic primality test (algorithm P in Knuth vol2, 4.5.4). * Returns FALSE if definitely not prime, or TRUE if probably prime. * Count determines how many times to check for primality. * The chance of a non-prime passing this test is less than (1/4)^count. * For example, a count of 100 fails for only 1 in 10^60 numbers. * * It is interesting to note that ptest(a,1,x) (for any x >= 0) of this * test will always return TRUE for a prime, and rarely return TRUE for * a non-prime.	 The 1/4 is appears in practice to be a poor upper * bound.  Even so the only result that is EXACT and TRUE is when * this test returns FALSE for a non-prime.  When ptest returns TRUE, * one cannot determine if the value in question is prime, or the value * is one of those rare non-primes that produces a false positive. * * The absolute value of count determines how many times to check * for primality.  If count < 0, then the trivial factor check is * omitted. * skip = 0 uses random bases * skip = 1 uses prime bases 2, 3, 5, ... * skip > 1 or < 0 uses bases skip, skip + 1, ... */BOOLzprimetest(ZVALUE z, long count, ZVALUE skip){	long limit = 0;		/* test odd values from skip up to limit */	ZVALUE zbase;		/* base as a ZVALUE */	long i, ij, ik;	ZVALUE zm1, z1, z2, z3;	int type;		/* random, prime or consecutive integers */	CONST unsigned short *pr;	/* pointer to small prime */	/*	 * firewall - ignore sign of z, values 0 and 1 are not prime	 */	z.sign = 0;	if (zisleone(z)) {		return 0;	}	/*	 * firewall - All even values, except 2, are not prime	 */	if (ziseven(z))		return zistwo(z);	if (z.len == 1 && *z.v == 3)		return 1;		/* 3 is prime */	/*	 * we know that z is an odd value > 1	 */	/*	 * Perform trivial checks if count is not negative	 */	if (count >= 0) {		/*		 * If the number is a small (32 bit) value, do a direct test		 */		if (!zge32b(z)) {			return zisprime(z);		}		/*		 * See if the number has a tiny factor.		 */		if (small_factor(z, PTEST_PRECHECK) != 0) {			/* a tiny factor was found */			return FALSE;		}		/*		 * If our count is zero, do nothing more		 */		if (count == 0) {			/* no test was done, so no test failed! */			return TRUE;		}	} else {		/* use the absolute value of count */		count = -count;	}	if (z.len < conf->redc2) {		return zredcprimetest(z, count, skip);	}	if (ziszero(skip)) {		type = 0;		zbase = _zero_;	} else if (zisone(skip)) {		type = 1;		itoz(2, &zbase);		limit = 1 << 16;		if (!zge16b(z))			limit = ztolong(z);	} else {		type = 2;		if (zrel(skip, z) >= 0 || zisneg(skip))			zmod(skip, z, &zbase, 0);		else			zcopy(skip, &zbase);	}	/*	 * Loop over various bases, testing each one.	 */	zsub(z, _one_, &zm1);	ik = zlowbit(zm1);	zshift(zm1, -ik, &z1);	pr = prime;	for (i = 0; i < count; i++) {		switch (type) {		case 0:			zfree(zbase);			zrandrange(_two_, zm1, &zbase);			break;		case 1:			if (i == 0)				break;			zfree(zbase);			if (*pr == 1 || (long)*pr >= limit) {				zfree(z1);				zfree(zm1);				return TRUE;			}			itoz((long) *pr++, &zbase);			break;		default:			if (i == 0)				break;			zadd(zbase, _one_, &z3);			zfree(zbase);			zbase = z3;		}		ij = 0;		zpowermod(zbase, z1, z, &z3);		for (;;) {			if (zisone(z3)) {				if (ij) {				/* number is definitely not prime */					zfree(z3);					zfree(zm1);					zfree(z1);					zfree(zbase);					return FALSE;				}				break;			}			if (!zcmp(z3, zm1))				break;			if (++ij >= ik) {				/* number is definitely not prime */				zfree(z3);				zfree(zm1);				zfree(z1);				zfree(zbase);				return FALSE;			}			zsquare(z3, &z2);			zfree(z3);			zmod(z2, z, &z3, 0);			zfree(z2);		}		zfree(z3);	}	zfree(zm1);	zfree(z1);	zfree(zbase);	/* number might be prime */	return TRUE;}/* * Called by zprimetest when simple cases have been eliminated * and z.len < conf->redc2.  Here count > 0, z is odd and > 3. */BOOLzredcprimetest(ZVALUE z, long count, ZVALUE skip){	long limit = 0;		/* test odd values from skip up to limit */	ZVALUE zbase;		/* base as a ZVALUE */	REDC *rp;	long i, ij, ik;	ZVALUE zm1, z1, z2, z3;	ZVALUE zredcm1;

⌨️ 快捷键说明

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