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

📄 zfunc.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 4 页
字号:
longzgcdrem(ZVALUE z1, ZVALUE z2, ZVALUE *res){	ZVALUE tmp1, tmp2;	long count, onecount;	long sh;	if (ziszero(z1) || ziszero(z2)) {		math_error("Zero argument in call to zgcdrem!!!");		/*NOTREACHED*/	}	/*	 * Begin by taking the gcd for the first time.	 * If the number is already relatively prime, then we are done.	 */	z1.sign = 0;	z2.sign = 0;	if (zisone(z2))		return 0;	if (zisonebit(z2)) {		sh = zlowbit(z1);		if (sh == 0)			return 0;		zshift(z1, -sh, res);		return 1 + (sh - 1)/zlowbit(z2);	}	if (zisonebit(z1)) {		if (zisodd(z2))			return 0;		*res = _one_;		return zlowbit(z1);	}	zgcd(z1, z2, &tmp1);	if (zisunit(tmp1) || ziszero(tmp1))		return 0;	zequo(z1, tmp1, &tmp2);	count = 1;	z1 = tmp2;	z2 = tmp1;	/*	 * Now keep alternately taking the gcd and removing factors until	 * the gcd becomes one.	 */	while (!zisunit(z2)) {		onecount = zfacrem(z1, z2, &tmp1);		if (onecount) {			count += onecount;			zfree(z1);			z1 = tmp1;		}		zgcd(z1, z2, &tmp1);		zfree(z2);		z2 = tmp1;	}	*res = z1;	return count;}/* * Return the number of digits (base 10) in a number, ignoring the sign. */longzdigits(ZVALUE z1){	long count, val;	z1.sign = 0;	if (!zge16b(z1)) {	/* do small numbers ourself */		count = 1;		val = 10;		while (*z1.v >= (HALF)val) {			count++;			val *= 10;		}		return count;	}	return (zlog10(z1, NULL) + 1);}/* * Return the single digit at the specified decimal place of a number, * where 0 means the rightmost digit.  Example:	 zdigit(1234, 1) = 3. */longzdigit(ZVALUE z1, long n){	ZVALUE tmp1, tmp2;	long res;	z1.sign = 0;	if (ziszero(z1) || (n < 0) || (n / BASEDIG >= z1.len))		return 0;	if (n == 0)		return zmodi(z1, 10L);	if (n == 1)		return zmodi(z1, 100L) / 10;	if (n == 2)		return zmodi(z1, 1000L) / 100;	if (n == 3)		return zmodi(z1, 10000L) / 1000;	ztenpow(n, &tmp1);	zquo(z1, tmp1, &tmp2, 0);	res = zmodi(tmp2, 10L);	zfree(tmp1);	zfree(tmp2);	return res;}/* * z is to be a nonnegative integer * If z is the square of a integer stores at dest the square root of z; *	otherwise stores at z an integer differing from the square root *	by less than 1.	 Returns the sign of the true square root minus *	the calculated integer.	 Type of rounding is determined by *	rnd as follows: rnd = 0 gives round down, rnd = 1 *	rounds up, rnd = 8 rounds to even integer, rnd = 9 rounds to odd *	integer, rnd = 16 rounds to nearest integer. */FLAGzsqrt(ZVALUE z, ZVALUE *dest, long rnd){	HALF *a, *A, *b, *a0, u;	int i, j, j1, j2, k, k1, m, m0, m1, n, n0, o;	FULL d, e, f, g, h, s, t, x, topbit;	int remsign;	BOOL up, onebit;	ZVALUE sqrt;	if (z.sign) {		math_error("Square root of negative number");		/*NOTREACHED*/	}	if (ziszero(z)) {		*dest = _zero_;		return 0;	}	m0 = z.len;	o = m0 & 1;	m = m0 + o;		/* m is smallest even number >= z.len */	n0 = n = m / 2;	f = z.v[z.len - 1];	k = 1;	while (f >>= 2)		k++;	if (!o)		k += BASEB/2;	j = BASEB - k;	m1 = m;	if (k == BASEB) {		m1 += 2;		n0++;	}	A = alloc(m1);	A[m1] = 0;	a0 = A + n0;	memcpy(A, z.v, m0 * sizeof(HALF));	if (o)		A[m - 1] = 0;	if (n == 1) {		if (j)			f = (FULL) A[1] << j | A[0] >> k;		else			f = A[1];		g = (FULL) A[0] << (j + BASEB);		d = e = topbit = (FULL)1 << (k - 1);	} else {		if (j)			f = (FULL) A[m-1] << (j + BASEB) | (FULL) A[m-2] << j |				A[m-3] >> k;		else			f = (FULL) A[m-1] << BASEB | A[m-2];		g = (FULL) A[m-3] << (j + BASEB) | (FULL) A[m-4] << j;		d = e = topbit = (FULL)1 << (BASEB + k - 1);	}	s = (f & topbit);	f <<= 1;	if (g & TOPFULL)		f++;	g <<= 1;	if (s) {		f -= 4 * d;		e = 2 * d - 1;	}	else		f -= d;	while (d >>= 1) {		if (!(s | f | g))			break;		while (d && (f & topbit) == s) {			d >>= 1;			f <<= 1;			if (g & TOPFULL)				f++;			g <<= 1;		}		if (d == 0)			break;		if (s)			f += e + 1;		else			f -= e;		t = f & topbit;		f <<= 1;		if (g & TOPFULL)			f++;		g <<= 1;		if (t == 0 && f < d)			t = topbit;		f -= d;		if (s)			e -= d - !t;		else			e += d - (t > 0);		s = t;	}	if (n0 == 1) {		A[1] = (HALF)e;		A[0] = (HALF)f;		m = 1;		goto done;	}	if (n0 == 2) {		A[3] = (HALF)(e >> BASEB);		A[2] = (HALF)e;		A[1] = (HALF)(f >> BASEB);		A[0] = (HALF)f;		m = 2;		goto done;	}	u = (HALF)(s ? BASE1 : 0);	if (k < BASEB) {		A[m1 - 1] = (HALF)(e >> (BASEB - 1));		A[m1 - 2] = ((HALF)(e << 1) | (HALF)(s > 0));		A[m1 - 3] = (HALF)(f >> BASEB);		A[m1 - 4] = (HALF)f;		m = m1 - 2;		k1 = k + 1;	} else {		A[m1 - 1] = 1;		A[m1 - 2] = (HALF)(e >> (BASEB - 1));		A[m1 - 3] = ((HALF)(e << 1) | (HALF)(s > 0));		A[m1 - 4] = u;		A[m1 - 5] = (HALF)(f >> BASEB);		A[m1 - 6] = (HALF)f;		m = m1 - 3;		k1 = 1;	}	h = e >> k;	onebit = ((e & ((FULL)1 << (k - 1))) ? TRUE : FALSE);	j2 = BASEB - k1;	j1 = BASEB + j2;	while (m > n0) {		a = A + m - 1;		if (j2)			f = (FULL) *a << j1 | (FULL) a[-1] << j2 | a[-2] >> k1;		else			f = (FULL) *a << BASEB | a[-1];		if (u)			f = ~f;		x = f / h;		if (x) {			if (onebit && x > 2 * (f % h) + 2)				x--;			b = a + 1;			i = m1 - m;			a -= i + 1;			if (u) {				f = *a + x * (BASE - x);				*a++ = (HALF)f;				u = (HALF)(f >> BASEB);				while (i--) {					f = *a + x * *b++ + u;					*a++ = (HALF)f;					u = (HALF)(f >> BASEB);				}				u += *a;				x = ~x + !u;				if (!(x & TOPHALF))					a[1] -= 1;			} else {				f = *a - x * x;				*a++ = (HALF)f;				u = -(HALF)(f >> BASEB);				while (i--) {					f = *a - x * *b++ - u;					*a++ = (HALF)f;					u = -(HALF)(f >> BASEB);				}				u = *a - u;				x = x + u;				if (x & TOPHALF)					a[1] |= 1;			}			*a = ((HALF)(x << 1) | (HALF)(u > 0));		} else {			*a = u;		}		m--;		if (*--a == u) {			while (m > 1 && *--a == u)				m--;		}	}	i = n;	a = a0;	while (i--) {		*a >>= 1;		if (a[1] & 1) *a |= TOPHALF;		a++;	}	s = u;done:	if (s == 0) {		while (m > 0 && A[m - 1] == 0)			m--;		if (m == 0) {			remsign = 0;			sqrt.v = alloc(n);			sqrt.len = n;			sqrt.sign = 0;			memcpy(sqrt.v, a0, n * sizeof(HALF));			freeh(A);			*dest = sqrt;			return remsign;		}	}	if (rnd & 16) {		if (s == 0) {			if (m != n) {				up = (m > n);			} else {				i = n;				b = a0 + n;				a = A + n;				while (i > 0 && *--a == *--b)					i--;				up = (i > 0 && *a > *b);			}		} else {			while (m > 1 && A[m - 1] == BASE1)				m--;			if (m != n) {				up = (m < n);			} else {				i = n;				b = a0 + n;				a = A + n;				while (i > 0 && *--a + *--b == BASE1)					i--;				up = ((FULL) *a + *b >= BASE);			}		}	}	else	if (rnd & 8)		up = (((rnd ^ *a0) & 1) ? TRUE : FALSE);	else		up = ((rnd & 1) ? TRUE : FALSE);	if (up) {		remsign = -1;		i = n;		a = a0;		while (i-- && *a == BASE1)			*a++ = 0;		if (i >= 0) {			(*a)++;		} else {			n++;			*a = 1;		}	} else {		remsign = 1;	}	sqrt.v = alloc(n);	sqrt.len = n;	sqrt.sign = 0;	memcpy(sqrt.v, a0, n * sizeof(HALF));	freeh(A);	*dest = sqrt;	return remsign;}/* * Take an arbitrary root of a number (to the greatest integer). * This uses the following iteration to get the Kth root of N: *	x = ((K-1) * x + N / x^(K-1)) / K */voidzroot(ZVALUE z1, ZVALUE z2, ZVALUE *dest){	ZVALUE ztry, quo, old, temp, temp2;	ZVALUE k1;			/* holds k - 1 */	int sign;	long i;	LEN highbit, k;	SIUNION sival;	sign = z1.sign;	if (sign && ziseven(z2)) {		math_error("Even root of negative number");		/*NOTREACHED*/	}	if (ziszero(z2) || zisneg(z2)) {		math_error("Non-positive root");		/*NOTREACHED*/	}	if (ziszero(z1)) {	/* root of zero */		*dest = _zero_;		return;	}	if (zisunit(z2)) {	/* first root */		zcopy(z1, dest);		return;	}	if (zge31b(z2)) {	/* humongous root */		*dest = _one_;		dest->sign = (BOOL)((HALF)sign);		return;	}	k = (LEN)ztolong(z2);	highbit = zhighbit(z1);	if (highbit < k) {	/* too high a root */		*dest = _one_;		dest->sign = (BOOL)((HALF)sign);		return;	}	sival.ivalue = k - 1;	k1.v = &sival.silow;	/* ignore Saber-C warning #112 - get ushort from uint */	/*	  ok to ignore on name zroot`sival */	k1.len = 1 + (sival.sihigh != 0);	k1.sign = 0;	z1.sign = 0;	/*	 * Allocate the numbers to use for the main loop.	 * The size and high bits of the final result are correctly set here.	 * Notice that the remainder of the test value is rubbish, but this	 * is unimportant.	 */	highbit = (highbit + k - 1) / k;	ztry.len = (highbit / BASEB) + 1;	ztry.v = alloc(ztry.len);	zclearval(ztry);	ztry.v[ztry.len-1] = ((HALF)1 << (highbit % BASEB));	ztry.sign = 0;	old.v = alloc(ztry.len);	old.len = 1;	zclearval(old);	old.sign = 0;	/*	 * Main divide and average loop	 */	for (;;) {		zpowi(ztry, k1, &temp);		zquo(z1, temp, &quo, 0);		zfree(temp);		i = zrel(ztry, quo);		if (i <= 0) {			/*			 * Current try is less than or equal to the root since it is			 * less than the quotient. If the quotient is equal to the try,			 * we are all done.  Also, if the try is equal to the old value,			 * we are done since no improvement occurred.			 * If not, save the improved value and loop some more.			 */			if ((i == 0) || (zcmp(old, ztry) == 0)) {				zfree(quo);				zfree(old);				ztry.sign = (BOOL)((HALF)sign);				zquicktrim(ztry);				*dest = ztry;				return;			}			old.len = ztry.len;			zcopyval(ztry, old);		}		/* average current try and quotient for the new try */		zmul(ztry, k1, &temp);		zfree(ztry);		zadd(quo, temp, &temp2);		zfree(temp);		zfree(quo);		zquo(temp2, z2, &ztry, 0);		zfree(temp2);	}}/* * Test to see if a number is an exact square or not. */BOOLzissquare(ZVALUE z){	long n;	ZVALUE tmp;	/* negative values are never perfect squares */	if (zisneg(z)) {		return FALSE;	}	/* ignore trailing zero words */	while ((z.len > 1) && (*z.v == 0)) {		z.len--;		z.v++;	}	/* zero or one is a perfect square */	if (zisabsleone(z)) {		return TRUE;	}	/* check mod 4096 values */	if (issq_mod4k[(int)(*z.v & 0xfff)] == 0) {		return FALSE;	}	/* must do full square root test now */	n = !zsqrt(z, &tmp, 0);	zfree(tmp);	return (n ? TRUE : FALSE);}

⌨️ 快捷键说明

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