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

📄 qmath.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 2 页
字号:
 */NUMBER *qnum(NUMBER *q){	register NUMBER *r;	if (qisint(q))		return qlink(q);	if (zisunit(q->num)) {		r = (qisneg(q) ? &_qnegone_ : &_qone_);		return qlink(r);	}	r = qalloc();	zcopy(q->num, &r->num);	return r;}/* * Return just the denominator of a number. *	q2 = qden(q1); */NUMBER *qden(NUMBER *q){	register NUMBER *r;	if (qisint(q))		return qlink(&_qone_);	r = qalloc();	zcopy(q->den, &r->num);	return r;}/* * Return the fractional part of a number. *	q2 = qfrac(q1); */NUMBER *qfrac(NUMBER *q){	register NUMBER *r;	if (qisint(q))		return qlink(&_qzero_);	if ((q->num.len < q->den.len) || ((q->num.len == q->den.len) &&		(q->num.v[q->num.len - 1] < q->den.v[q->num.len - 1])))			return qlink(q);	r = qalloc();	zmod(q->num, q->den, &r->num, 2);	zcopy(q->den, &r->den);	return r;}/* * Return the integral part of a number. *	q2 = qint(q1); */NUMBER *qint(NUMBER *q){	register NUMBER *r;	if (qisint(q))		return qlink(q);	if ((q->num.len < q->den.len) || ((q->num.len == q->den.len) &&		(q->num.v[q->num.len - 1] < q->den.v[q->num.len - 1])))			return qlink(&_qzero_);	r = qalloc();	zquo(q->num, q->den, &r->num, 2);	return r;}/* * Compute the square of a number. */NUMBER *qsquare(NUMBER *q){	ZVALUE num, zden;	if (qiszero(q))		return qlink(&_qzero_);	if (qisunit(q))		return qlink(&_qone_);	num = q->num;	zden = q->den;	q = qalloc();	if (!zisunit(num))		zsquare(num, &q->num);	if (!zisunit(zden))		zsquare(zden, &q->den);	return q;}/* * Shift an integer by a given number of bits. This multiplies the number * by the appropriate power of two.  Positive numbers shift left, negative * ones shift right.  Low bits are truncated when shifting right. */NUMBER *qshift(NUMBER *q, long n){	register NUMBER *r;	if (qisfrac(q)) {		math_error("Shift of non-integer");		/*NOTREACHED*/	}	if (qiszero(q) || (n == 0))		return qlink(q);	if (n <= -(q->num.len * BASEB))		return qlink(&_qzero_);	r = qalloc();	zshift(q->num, n, &r->num);	return r;}/* * Scale a number by a power of two, as in: *	ans = q * 2^n. * This is similar to shifting, except that fractions work. */NUMBER *qscale(NUMBER *q, long pow){	long numshift, denshift, tmp;	NUMBER *r;	if (qiszero(q) || (pow == 0))		return qlink(q);	numshift = zisodd(q->num) ? 0 : zlowbit(q->num);	denshift = zisodd(q->den) ? 0 : zlowbit(q->den);	if (pow > 0) {		tmp = pow;		if (tmp > denshift)		tmp = denshift;		denshift = -tmp;		numshift = (pow - tmp);	} else {		pow = -pow;		tmp = pow;		if (tmp > numshift)			tmp = numshift;		numshift = -tmp;		denshift = (pow - tmp);	}	r = qalloc();	if (numshift)		zshift(q->num, numshift, &r->num);	else		zcopy(q->num, &r->num);	if (denshift)		zshift(q->den, denshift, &r->den);	else		zcopy(q->den, &r->den);	return r;}/* * Return the minimum of two numbers. */NUMBER *qmin(NUMBER *q1, NUMBER *q2){	if (q1 == q2)		return qlink(q1);	if (qrel(q1, q2) > 0)		q1 = q2;	return qlink(q1);}/* * Return the maximum of two numbers. */NUMBER *qmax(NUMBER *q1, NUMBER *q2){	if (q1 == q2)		return qlink(q1);	if (qrel(q1, q2) < 0)		q1 = q2;	return qlink(q1);}/* * Perform the bitwise OR of two integers. */NUMBER *qor(NUMBER *q1, NUMBER *q2){	register NUMBER *r;	NUMBER *q1tmp, *q2tmp, *q;	if (qisfrac(q1) || qisfrac(q2)) {		math_error("Non-integers for bitwise or");		/*NOTREACHED*/	}	if (qcmp(q1,q2) == 0 || qiszero(q2))		return qlink(q1);	if (qiszero(q1))		return qlink(q2);	if (qisneg(q1)) {		q1tmp = qcomp(q1);		if (qisneg(q2)) {			q2tmp = qcomp(q2);			q = qand(q1tmp,q2tmp);			r = qcomp(q);			qfree(q1tmp);			qfree(q2tmp);			qfree(q);			return r;		}		q = qandnot(q1tmp, q2);		qfree(q1tmp);		r = qcomp(q);		qfree(q);		return r;	}	if (qisneg(q2)) {		q2tmp = qcomp(q2);		q = qandnot(q2tmp, q1);		qfree(q2tmp);		r = qcomp(q);		qfree(q);		return r;	}	r = qalloc();	zor(q1->num, q2->num, &r->num);	return r;}/* * Perform the bitwise AND of two integers. */NUMBER *qand(NUMBER *q1, NUMBER *q2){	register NUMBER *r;	NUMBER *q1tmp, *q2tmp, *q;	ZVALUE res;	if (qisfrac(q1) || qisfrac(q2)) {		math_error("Non-integers for bitwise and");		/*NOTREACHED*/	}	if (qcmp(q1, q2) == 0)		return qlink(q1);	if (qiszero(q1) || qiszero(q2))		return qlink(&_qzero_);	if (qisneg(q1)) {		q1tmp = qcomp(q1);		if (qisneg(q2)) {			q2tmp = qcomp(q2);			q = qor(q1tmp, q2tmp);			qfree(q1tmp);			qfree(q2tmp);			r = qcomp(q);			qfree(q);			return r;		}		r = qandnot(q2, q1tmp);		qfree(q1tmp);		return r;	}	if (qisneg(q2)) {		q2tmp = qcomp(q2);		r = qandnot(q1, q2tmp);		qfree(q2tmp);		return r;	}	zand(q1->num, q2->num, &res);	if (ziszero(res)) {		zfree(res);		return qlink(&_qzero_);	}	r = qalloc();	r->num = res;	return r;}/* * Perform the bitwise XOR of two integers. */NUMBER *qxor(NUMBER *q1, NUMBER *q2){	register NUMBER *r;	NUMBER *q1tmp, *q2tmp, *q;	ZVALUE res;	if (qisfrac(q1) || qisfrac(q2)) {		math_error("Non-integers for bitwise xor");		/*NOTREACHED*/	}	if (qcmp(q1,q2) == 0)		return qlink(&_qzero_);	if (qiszero(q1))		return qlink(q2);	if (qiszero(q2))		return qlink(q1);	if (qisneg(q1)) {		q1tmp = qcomp(q1);		if (qisneg(q2)) {			q2tmp = qcomp(q2);			r = qxor(q1tmp, q2tmp);			qfree(q1tmp);			qfree(q2tmp);			return r;		}		q = qxor(q1tmp, q2);		qfree(q1tmp);		r = qcomp(q);		qfree(q);		return r;	}	if (qisneg(q2)) {		q2tmp = qcomp(q2);		q = qxor(q1, q2tmp);		qfree(q2tmp);		r = qcomp(q);		qfree(q);		return r;	}	zxor(q1->num, q2->num, &res);	if (ziszero(res)) {		zfree(res);		return qlink(&_qzero_);	}	r = qalloc();	r->num = res;	return r;}/* * Perform the bitwise ANDNOT of two integers. */NUMBER *qandnot(NUMBER *q1, NUMBER *q2){	register NUMBER *r;	NUMBER *q1tmp, *q2tmp, *q;	if (qisfrac(q1) || qisfrac(q2)) {		math_error("Non-integers for bitwise xor");		/*NOTREACHED*/	}	if (qcmp(q1,q2) == 0 || qiszero(q1))		return qlink(&_qzero_);	if (qiszero(q2))		return qlink(q1);	if (qisneg(q1)) {		q1tmp = qcomp(q1);		if (qisneg(q2)) {			q2tmp = qcomp(q2);			r = qandnot(q2tmp, q1tmp);			qfree(q1tmp);			qfree(q2tmp);			return r;		}		q = qor(q1tmp, q2);		qfree(q1tmp);		r = qcomp(q);		qfree(q);		return r;	}	if (qisneg(q2)) {		q2tmp = qcomp(q2);		r = qand(q1, q2tmp);		qfree(q2tmp);		return r;	}	r = qalloc();	zandnot(q1->num, q2->num, &r->num);	return r;}/* * Return the bitwise "complement" of a number.	 This is - q -1 if q is an * integer, - q otherwise. */NUMBER *qcomp(NUMBER *q){	NUMBER *qtmp;	NUMBER *res;	if (qiszero(q))		return qlink(&_qnegone_);	if (qisnegone(q))		return qlink(&_qzero_);	qtmp = qneg(q);	if (qisfrac(q))		return qtmp;	res = qdec(qtmp);	qfree(qtmp);	return res;}/* * Return the number whose binary representation only has the specified * bit set (counting from zero).  This thus produces a given power of two. */NUMBER *qbitvalue(long n){	register NUMBER *r;	if (n == 0)		return qlink(&_qone_);	r = qalloc();	if (n > 0)		zbitvalue(n, &r->num);	else		zbitvalue(-n, &r->den);	return r;}/* * Return 10^n */NUMBER *qtenpow(long n){	register NUMBER *r;	if (n == 0)		return qlink(&_qone_);	r = qalloc();	if (n > 0)		ztenpow(n, &r->num);	else		ztenpow(-n, &r->den);	return r;}/* * Return the precision of a number (usually for examining an epsilon value). * The precision of a number e less than 1 is the positive * integer p for which e = 2^-p * f, where 1 <= f < 2. * Numbers greater than or equal to one have a precision of zero. * For example, the precision of e is 6 if 1/64 <= e < 1/32. */longqprecision(NUMBER *q){	long r;	if (qiszero(q) || qisneg(q)) {		math_error("Non-positive number for precision");		/*NOTREACHED*/	}	r = - qilog2(q);	return (r < 0 ? 0 : r);}/* * Determine whether or not one number exactly divides another one. * Returns TRUE if the first number is an integer multiple of the second one. */BOOLqdivides(NUMBER *q1, NUMBER *q2){	if (qiszero(q1))		return TRUE;	if (qisint(q1) && qisint(q2)) {		if (qisunit(q2))			return TRUE;		return zdivides(q1->num, q2->num);	}	return zdivides(q1->num, q2->num) && zdivides(q2->den, q1->den);}/* * Compare two numbers and return an integer indicating their relative size. *	i = qrel(q1, q2); */FLAGqrel(NUMBER *q1, NUMBER *q2){	ZVALUE z1, z2;	long wc1, wc2;	int sign;	int z1f = 0, z2f = 0;	if (q1 == q2)		return 0;	sign = q2->num.sign - q1->num.sign;	if (sign)		return sign;	if (qiszero(q2))		return !qiszero(q1);	if (qiszero(q1))		return -1;	/*	 * Make a quick comparison by calculating the number of words resulting as	 * if we multiplied through by the denominators, and then comparing the	 * word counts.	 */	sign = 1;	if (qisneg(q1))		sign = -1;	wc1 = q1->num.len + q2->den.len;	wc2 = q2->num.len + q1->den.len;	if (wc1 < wc2 - 1)		return -sign;	if (wc2 < wc1 - 1)		return sign;	/*	 * Quick check failed, must actually do the full comparison.	 */	if (zisunit(q2->den)) {		z1 = q1->num;	} else if (zisone(q1->num)) {		z1 = q2->den;	} else {		z1f = 1;		zmul(q1->num, q2->den, &z1);	}	if (zisunit(q1->den)) {		z2 = q2->num;	} else if (zisone(q2->num)) {		z2 = q1->den;	} else {		z2f = 1;		zmul(q2->num, q1->den, &z2);	}	sign = zrel(z1, z2);	if (z1f)		zfree(z1);	if (z2f)		zfree(z2);	return sign;}/* * Compare two numbers to see if they are equal. * This differs from qrel in that the numbers are not ordered. * Returns TRUE if they differ. */BOOLqcmp(NUMBER *q1, NUMBER *q2){	if (q1 == q2)		return FALSE;	if ((q1->num.sign != q2->num.sign) || (q1->num.len != q2->num.len) ||		(q2->den.len != q2->den.len) || (*q1->num.v != *q2->num.v) ||		(*q1->den.v != *q2->den.v))			return TRUE;	if (zcmp(q1->num, q2->num))		return TRUE;	if (qisint(q1))		return FALSE;	return zcmp(q1->den, q2->den);}/* * Compare a number against a normal small integer. * Returns 1, 0, or -1, according to whether the first number is greater, * equal, or less than the second number. *	res = qreli(q, n); */FLAGqreli(NUMBER *q, long n){	ZVALUE z1, z2;	FLAG res;	if (qiszero(q))		return ((n > 0) ? -1 : (n < 0));	if (n == 0)		return (q->num.sign ? -1 : 0);	if (q->num.sign != (n < 0))		return ((n < 0) ? 1 : -1);	itoz(n, &z1);	if (qisfrac(q)) {		zmul(q->den, z1, &z2);		zfree(z1);		z1 = z2;	}	res = zrel(q->num, z1);	zfree(z1);	return res;}/* * Compare a number against a small integer to see if they are equal. * Returns TRUE if they differ. */BOOLqcmpi(NUMBER *q, long n){	long len;#if LONG_BITS > BASEB	FULL nf;#endif	len = q->num.len;	if (qisfrac(q) || (q->num.sign != (n < 0)))		return TRUE;	if (n < 0)		n = -n;	if (((HALF)(n)) != q->num.v[0])		return TRUE;#if LONG_BITS > BASEB	nf = ((FULL) n) >> BASEB;	return ((nf != 0 || len > 1) && (len != 2 || nf != q->num.v[1]));#else	return (len > 1);#endif}/* * Number node allocation routines */#define NNALLOC 1000static NUMBER	*freeNum = NULL;static NUMBER	**firstNums = NULL;static long	blockcount = 0;NUMBER *qalloc(void){	NUMBER *temp;	NUMBER ** newfn;	if (freeNum == NULL) {		freeNum = (NUMBER *) malloc(sizeof (NUMBER) * NNALLOC);		if (freeNum == NULL) {			math_error("Not enough memory");			/*NOTREACHED*/		}		freeNum[NNALLOC - 1].next = NULL;		freeNum[NNALLOC - 1].links = 0;		/*		 * We prevent the temp pointer from walking behind freeNum		 * by stopping one short of the end and running the loop one		 * more time.		 *		 * We would stop the loop with just temp >= freeNum, but		 * doing this helps make code checkers such as insure happy.		 */		for (temp = freeNum + NNALLOC - 2; temp > freeNum; --temp) {			temp->next = temp + 1;			temp->links = 0;		}		/* run the loop manually one last time */		temp->next = temp + 1;		temp->links = 0;		blockcount++;		if (firstNums == NULL) {		    newfn = (NUMBER **) malloc(blockcount * sizeof(NUMBER *));		} else {		    newfn = (NUMBER **)			    realloc(firstNums, blockcount * sizeof(NUMBER *));		}		if (newfn == NULL) {			math_error("Cannot allocate new number block");			/*NOTREACHED*/		}		firstNums = newfn;		firstNums[blockcount - 1] = freeNum;	}	temp = freeNum;	freeNum = temp->next;	temp->links = 1;	temp->num = _one_;	temp->den = _one_;	return temp;}voidqfreenum(NUMBER *q){	if (q == NULL) {		math_error("Calling qfreenum with null argument!!!");		/*NOTREACHED*/	}	if (q->links != 0) {		math_error("Calling qfreenum with nozero links!!!");		/*NOTREACHED*/	}	zfree(q->num);	zfree(q->den);	q->next = freeNum;	freeNum = q;}voidshownumbers(void){	NUMBER *vp;	long i, j, k;	long count = 0;	printf("Index  Links  Digits	       Value\n");	printf("-----  -----  ------	       -----\n");	for (i = 0, k = 0; i < INITCONSTCOUNT; i++) {		count++;		vp = initnumbs[i];		printf("%6ld  %4ld  ", k++, vp->links);		fitprint(vp, 40);		printf("\n");	}	for (i = 0; i < blockcount; i++) {		vp = firstNums[i];		for (j = 0; j < NNALLOC; j++, k++, vp++) {			if (vp->links > 0) {				count++;				printf("%6ld  %4ld  ", k, vp->links);				fitprint(vp, 40);				printf("\n");			}		}	}	printf("\nNumber: %ld\n", count);}

⌨️ 快捷键说明

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