zmath.c

来自「Calc Software Package for Number Calc」· C语言 代码 · 共 2,000 行 · 第 1/3 页

C
2,000
字号
	return ans;}/* * Compute the bitwise OR of two integers */voidzor(ZVALUE z1, ZVALUE z2, ZVALUE *res){	register HALF *sp, *dp;	long len;	ZVALUE bz, lz, dest;	if (z1.len >= z2.len) {		bz = z1;		lz = z2;	} else {		bz = z2;		lz = z1;	}	dest.len = bz.len;	dest.v = alloc(dest.len);	dest.sign = 0;	zcopyval(bz, dest);	len = lz.len;	sp = lz.v;	dp = dest.v;	while (len--)		*dp++ |= *sp++;	*res = dest;}/* * Compute the bitwise AND of two integers */voidzand(ZVALUE z1, ZVALUE z2, ZVALUE *res){	HALF *h1, *h2, *hd;	LEN len;	ZVALUE dest;	len = ((z1.len <= z2.len) ? z1.len : z2.len);	h1 = &z1.v[len-1];	h2 = &z2.v[len-1];	while ((len > 1) && ((*h1 & *h2) == 0)) {		h1--;		h2--;		len--;	}	dest.len = len;	dest.v = alloc(len);	dest.sign = 0;	h1 = z1.v;	h2 = z2.v;	hd = dest.v;	while (len--)		*hd++ = (*h1++ & *h2++);	*res = dest;}/* * Compute the bitwise XOR of two integers. */voidzxor(ZVALUE z1, ZVALUE z2, ZVALUE *res){	HALF *dp, *h1, *h2;	LEN len, j, k;	ZVALUE dest;	h1 = z1.v;	h2 = z2.v;	len = z1.len;	j = z2.len;	if (z1.len < z2.len) {		len = z2.len;		j = z1.len;		h1 = z2.v;		h2 = z1.v;	} else if (z1.len == z2.len) {		while (len > 1 && z1.v[len-1] == z2.v[len-1])			len--;		j = len;	}	k = len - j;	dest.len = len;	dest.v = alloc(len);	dest.sign = 0;	dp = dest.v;	while (j-- > 0)		*dp++ = *h1++ ^ *h2++;	while (k-- > 0)		*dp++ = *h1++;	*res = dest;}/* * Compute the bitwise ANDNOT of two integers. */voidzandnot(ZVALUE z1, ZVALUE z2, ZVALUE *res){	HALF *dp, *h1, *h2;	LEN len, j, k;	ZVALUE dest;	len = z1.len;	if (z2.len >= len) {		while (len > 1 && (z1.v[len-1] & ~z2.v[len-1]) == 0)			len--;		j = len;		k = 0;	} else {		j = z2.len;		k = len - z2.len;	}	dest.len = len;	dest.v = alloc(len);	dest.sign = 0;	dp = dest.v;	h1 = z1.v;	h2 = z2.v;	while (j-- > 0)		*dp++ = *h1++ & ~*h2++;	while (k-- > 0)		*dp++ = *h1++;	*res = dest;}/* * Shift a number left (or right) by the specified number of bits. * Positive shift means to the left.  When shifting right, rightmost * bits are lost.  The sign of the number is preserved. */voidzshift(ZVALUE z, long n, ZVALUE *res){	ZVALUE ans;	LEN hc;		/* number of halfwords shift is by */	if (ziszero(z)) {		*res = _zero_;		return;	}	if (n == 0) {		zcopy(z, res);		return;	}	/*	 * If shift value is negative, then shift right.	 * Check for large shifts, and handle word-sized shifts quickly.	 */	if (n < 0) {		n = -n;		if ((n < 0) || (n >= (z.len * BASEB))) {			*res = _zero_;			return;		}		hc = (LEN)(n / BASEB);		n %= BASEB;		z.v += hc;		z.len -= hc;		ans.len = z.len;		ans.v = alloc(ans.len);		ans.sign = z.sign;		zcopyval(z, ans);		if (n > 0) {			zshiftr(ans, n);			ztrim(&ans);		}		if (ziszero(ans)) {			zfree(ans);			ans = _zero_;		}		*res = ans;		return;	}	/*	 * Shift value is positive, so shift leftwards.	 * Check specially for a shift of the value 1, since this is common.	 * Also handle word-sized shifts quickly.	 */	if (zisunit(z)) {		zbitvalue(n, res);		res->sign = z.sign;		return;	}	hc = (LEN)(n / BASEB);	n %= BASEB;	ans.len = z.len + hc + 1;	ans.v = alloc(ans.len);	ans.sign = z.sign;	if (hc > 0)		memset((char *) ans.v, 0, hc * sizeof(HALF));	memcpy((char *) (ans.v + hc),	    (char *) z.v, z.len * sizeof(HALF));	ans.v[ans.len - 1] = 0;	if (n > 0) {		ans.v += hc;		ans.len -= hc;		zshiftl(ans, n);		ans.v -= hc;		ans.len += hc;	}	ztrim(&ans);	*res = ans;}/* * Return the position of the lowest bit which is set in the binary * representation of a number (counting from zero).  This is the highest * power of two which evenly divides the number. */longzlowbit(ZVALUE z){	register HALF *zp;	long n;	HALF dataval;	HALF *bitval;	n = 0;	for (zp = z.v; *zp == 0; zp++)		if (++n >= z.len)			return 0;	dataval = *zp;	bitval = bitmask;	/* ignore Saber-C warning #530 about empty while statement */	/*	  ok to ignore in proc zlowbit */	while ((*(bitval++) & dataval) == 0) {	}	return (n*BASEB)+(bitval-bitmask-1);}/* * Return the position of the highest bit which is set in the binary * representation of a number (counting from zero).  This is the highest power * of two which is less than or equal to the number (which is assumed nonzero). */LENzhighbit(ZVALUE z){	HALF dataval;	HALF *bitval;	dataval = z.v[z.len-1];	if (dataval == 0) {		return 0;	}	bitval = bitmask+BASEB;	if (dataval) {		/* ignore Saber-C warning #530 about empty while statement */		/*	  ok to ignore in proc zhighbit */		while ((*(--bitval) & dataval) == 0) {		}	}	return (z.len*BASEB)+(LEN)(bitval-bitmask-BASEB);}/* * Return whether or not the specifed bit number is set in a number. * Rightmost bit of a number is bit 0. */BOOLzisset(ZVALUE z, long n){	if ((n < 0) || ((n / BASEB) >= z.len))		return FALSE;	return ((z.v[n / BASEB] & (((HALF) 1) << (n % BASEB))) != 0);}/* * Check whether or not a number has exactly one bit set, and * thus is an exact power of two.  Returns TRUE if so. */BOOLzisonebit(ZVALUE z){	register HALF *hp;	register LEN len;	if (ziszero(z) || zisneg(z))		return FALSE;	hp = z.v;	len = z.len;	while (len > 4) {		len -= 4;		if (*hp++ || *hp++ || *hp++ || *hp++)			return FALSE;	}	while (--len > 0) {		if (*hp++)			return FALSE;	}	return ((*hp & -*hp) == *hp);		/* NEEDS 2'S COMPLEMENT */}/* * Check whether or not a number has all of its bits set below some * bit position, and thus is one less than an exact power of two. * Returns TRUE if so. */BOOLzisallbits(ZVALUE z){	register HALF *hp;	register LEN len;	HALF digit;	if (ziszero(z) || zisneg(z))		return FALSE;	hp = z.v;	len = z.len;	while (len > 4) {		len -= 4;		if ((*hp++ != BASE1) || (*hp++ != BASE1) ||			(*hp++ != BASE1) || (*hp++ != BASE1))				return FALSE;	}	while (--len > 0) {		if (*hp++ != BASE1)			return FALSE;	}	digit = (HALF)(*hp + 1);	return ((digit & -digit) == digit);	/* NEEDS 2'S COMPLEMENT */}/* * Return the number whose binary representation contains only one bit which * is in the specified position (counting from zero).  This is equivilant * to raising two to the given power. */voidzbitvalue(long n, ZVALUE *res){	ZVALUE z;	if (n < 0) n = 0;	z.sign = 0;	z.len = (LEN)((n / BASEB) + 1);	z.v = alloc(z.len);	zclearval(z);	z.v[z.len-1] = (((HALF) 1) << (n % BASEB));	*res = z;}/* * Compare a number against zero. * Returns the sgn function of the number (-1, 0, or 1). */FLAGztest(ZVALUE z){	register int sign;	register HALF *h;	register long len;	sign = 1;	if (z.sign)		sign = -sign;	h = z.v;	len = z.len;	while (len--)		if (*h++)			return sign;	return 0;}/* * Return the sign of z1 - z2, i.e. 1 if the first integer is greater, * 0 if they are equal, -1 otherwise. */FLAGzrel(ZVALUE z1, ZVALUE z2){	HALF *h1, *h2;	LEN len;	int sign;	sign = 1;	if (z1.sign < z2.sign)		return 1;	if (z2.sign < z1.sign)		return -1;	if (z2.sign)		sign = -1;	if (z1.len != z2.len)		return (z1.len > z2.len) ? sign : -sign;	len = z1.len;	h1 = z1.v + len;	h2 = z2.v + len;	while (len > 0) {		if (*--h1 != *--h2)			break;		len--;	}	if (len > 0)		return (*h1 > *h2) ? sign : -sign;	return 0;}/* * Return the sign of abs(z1) - abs(z2), i.e. 1 if the first integer * has greater absolute value, 0 is they have equal absolute value, * -1 otherwise. */FLAGzabsrel(ZVALUE z1, ZVALUE z2){	HALF *h1, *h2;	LEN len;	if (z1.len != z2.len)		return (z1.len > z2.len) ? 1 : -1;	len = z1.len;	h1 = z1.v + len;	h2 = z2.v + len;	while (len > 0) {		if (*--h1 != *--h2)			break;		len--;	}	if (len > 0)		return (*h1 > *h2) ? 1 : -1;	return 0;}/* * Compare two numbers to see if they are equal or not. * Returns TRUE if they differ. */BOOLzcmp(ZVALUE z1, ZVALUE z2){	register HALF *h1, *h2;	register long len;	if ((z1.sign != z2.sign) || (z1.len != z2.len) || (*z1.v != *z2.v))		return TRUE;	len = z1.len;	h1 = z1.v;	h2 = z2.v;	while (--len > 0) {		if (*++h1 != *++h2)			return TRUE;	}	return FALSE;}/* * Utility to calculate the gcd of two FULL integers. */FULLuugcd(FULL f1, FULL f2){	FULL temp;	while (f1) {		temp = f2 % f1;		f2 = f1;		f1 = temp;	}	return (FULL) f2;}/* * Utility to calculate the gcd of two small integers. */longiigcd(long i1, long i2){	FULL f1, f2, temp;	f1 = (FULL) ((i1 >= 0) ? i1 : -i1);	f2 = (FULL) ((i2 >= 0) ? i2 : -i2);	while (f1) {		temp = f2 % f1;		f2 = f1;		f1 = temp;	}	return (long) f2;}voidztrim(ZVALUE *z){	HALF *h;	LEN len;	h = z->v + z->len - 1;	len = z->len;	while (*h == 0 && len > 1) {		--h;		--len;	}	z->len = len;}/* * Utility routine to shift right. * * NOTE: The ZVALUE length is not adjusted instead, the value is *	 zero padded from the left.  One may need to call ztrim() *	 or use zshift() instead. */voidzshiftr(ZVALUE z, long n){	register HALF *h, *lim;	FULL mask, maskt;	long len;	if (n >= BASEB) {		len = n / BASEB;		h = z.v;		lim = z.v + z.len - len;		while (h < lim) {			h[0] = h[len];			++h;		}		n -= BASEB * len;		lim = z.v + z.len;		while (h < lim)			*h++ = 0;	}	if (n) {		len = z.len;		h = z.v + len;		mask = 0;		while (len--) {			maskt = (((FULL) *--h) << (BASEB - n)) & BASE1;			*h = ((*h >> n) | (HALF)mask);			mask = maskt;		}	}}/* * Utility routine to shift left. * * NOTE: The ZVALUE length is not adjusted.  The bits in the upper *	 HALF are simply tossed.  You may want to use zshift() instead. */voidzshiftl(ZVALUE z, long n){	register HALF *h;	FULL mask, i;	long len;	if (n >= BASEB) {		len = n / BASEB;		h = z.v + z.len - 1;		while (!*h)			--h;		while (h >= z.v) {			h[len] = h[0];			--h;		}		n -= BASEB * len;		while (len)			h[len--] = 0;	}	if (n > 0) {		len = z.len;		h = z.v;		mask = 0;		while (len--) {			i = (((FULL) *h) << n) | mask;			if (i > BASE1) {				mask = i >> BASEB;				i &= BASE1;			} else {				mask = 0;			}			*h = (HALF) i;			++h;		}	}}/* * popcnt - count the number of 0 or 1 bits in an integer * * We ignore all 0 bits above the highest bit. */longzpopcnt(ZVALUE z, int bitval){	long cnt = 0;	/* number of times found */	HALF h;		/* HALF to count */	int i;	/*	 * count 1's	 */	if (bitval) {		/*		 * count each HALF		 */		for (i=0; i < z.len; ++i) {			/* count each octet */			for (h = z.v[i]; h; h >>= 8) {				cnt += (long)popcnt[h & 0xff];			}		}	/*	 * count 0's	 */	} else {		/*		 * count each HALF up until the last		 */		for (i=0; i < z.len-1; ++i) {			/* count each octet */			cnt += BASEB;			for (h = z.v[i]; h; h >>= 8) {				cnt -= (long)popcnt[h & 0xff];			}		}		/*		 * count the last octet up until the highest 1 bit		 */		for (h = z.v[z.len-1]; h; h>>=1) {			/* count each 0 bit */			if ((h & 0x1) == 0) {				++cnt;			}		}	}	/*	 * return count	 */	return cnt;}

⌨️ 快捷键说明

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