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

📄 matfunc.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 3 页
字号:
	VALUE *pivot, *div, *val;	VALUE *vp, *vv;	VALUE tmp1, tmp2, tmp3;	BOOL neg;		/* whether to negate determinant */	if (m->m_dim < 2) {		vp = m->m_table;		i = m->m_size;		copyvalue(vp, &tmp1);		while (--i > 0) {			mulvalue(&tmp1, ++vp, &tmp2);			freevalue(&tmp1);			tmp1 = tmp2;		}		return tmp1;	}	if (m->m_dim != 2)		return error_value(E_DET2);	if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1]))		return error_value(E_DET3);	/*	 * Loop over each row, and eliminate all lower entries in the	 * corresponding column by using row operations.  Copy the original	 * matrix so that we don't destroy it.	 */	neg = FALSE;	m = matcopy(m);	n = (m->m_max[0] - m->m_min[0] + 1);	pivot = div = m->m_table;	for (k = n; k > 0; k--) {		/*		 * Find the first nonzero value in the rest of the column		 * downwards from pivot.  If there is no such value, then		 * the determinant is zero.  If the first nonzero entry is not		 * the pivot, then swap rows in the k * k submatrix, and		 * remember that the determinant changes sign.		 */		val = pivot;		i = k;		while (!testvalue(val)) {			if (--i <= 0) {				tmp1.v_type = V_NUM;				tmp1.v_subtype = V_NOSUBTYPE;				tmp1.v_num = qlink(&_qzero_);				matfree(m);				return tmp1;			}			val += n;		}		if (i < k) {			vp = pivot;			vv = val;			j = k;			while (j-- > 0) {				tmp1 = *vp;				*vp++ = *vv;				*vv++ = tmp1;			}			neg = !neg;		}		/*		 * Now for every val below the pivot, for each entry to		 * the right of val, calculate the 2 x 2 determinant		 * with corners at the pivot and the entry.  If		 * k < n, divide by div (the previous pivot value).		 */		val = pivot;		i = k;		while (--i > 0) {			val += n;			vp = pivot;			vv = val;			j = k;			while (--j > 0) {				mulvalue(pivot, ++vv, &tmp1);				mulvalue(val, ++vp, &tmp2);				subvalue(&tmp1, &tmp2, &tmp3);				freevalue(&tmp1);				freevalue(&tmp2);				freevalue(vv);				if (k < n) {					divvalue(&tmp3, div, vv);					freevalue(&tmp3);				}				else					*vv = tmp3;			}		}		div = pivot;		if (k > 0)			pivot += n + 1;	}	if (neg)		negvalue(div, &tmp1);	else		copyvalue(div, &tmp1);	matfree(m);	return tmp1;}/* * Local utility routine to swap two rows of a square matrix. * No checks are made to verify the legality of the arguments. */static voidmatswaprow(MATRIX *m, long r1, long r2){	register VALUE *v1, *v2;	register long rows;	VALUE tmp;	if (r1 == r2)		return;	rows = (m->m_max[0] - m->m_min[0] + 1);	v1 = &m->m_table[r1 * rows];	v2 = &m->m_table[r2 * rows];	while (rows-- > 0) {		tmp = *v1;		*v1 = *v2;		*v2 = tmp;		v1++;		v2++;	}}/* * Local utility routine to subtract a multiple of one row to another one. * The row to be changed is oprow, the row to be subtracted is baserow. * No checks are made to verify the legality of the arguments. */static voidmatsubrow(MATRIX *m, long oprow, long baserow, VALUE *mulval){	register VALUE *vop, *vbase;	register long entries;	VALUE tmp1, tmp2;	entries = (m->m_max[0] - m->m_min[0] + 1);	vop = &m->m_table[oprow * entries];	vbase = &m->m_table[baserow * entries];	while (entries-- > 0) {		mulvalue(vbase, mulval, &tmp1);		subvalue(vop, &tmp1, &tmp2);		freevalue(&tmp1);		freevalue(vop);		*vop = tmp2;		vop++;		vbase++;	}}/* * Local utility routine to multiply a row by a specified number. * No checks are made to verify the legality of the arguments. */static voidmatmulrow(MATRIX *m, long row, VALUE *mulval){	register VALUE *val;	register long rows;	VALUE tmp;	rows = (m->m_max[0] - m->m_min[0] + 1);	val = &m->m_table[row * rows];	while (rows-- > 0) {		mulvalue(val, mulval, &tmp);		freevalue(val);		*val = tmp;		val++;	}}/* * Make a full copy of a matrix. */MATRIX *matcopy(MATRIX *m){	MATRIX *res;	register VALUE *v1, *v2;	register long i;	res = matalloc(m->m_size);	*res = *m;	v1 = m->m_table;	v2 = res->m_table;	i = m->m_size;	while (i-- > 0) {		copyvalue(v1, v2);		v1++;		v2++;	}	return res;}/* * Make a matrix the same size as another and filled with a fixed value. * * given: *	m		matrix to initialize *	v1		value to fill most of matrix with *	v2		value for diagonal entries (or NULL) */MATRIX *matinit(MATRIX *m, VALUE *v1, VALUE *v2){	MATRIX *res;	register VALUE *v;	register long i;	long row;	long rows;	/*	 * clone matrix size	 */	res = matalloc(m->m_size);	*res = *m;	/*	 * firewall	 */	if (v2 && ((res->m_dim != 2) ||		((res->m_max[0] - res->m_min[0]) !=		 (res->m_max[1] - res->m_min[1])))) {			math_error("Filling diagonals of non-square matrix");			/*NOTREACHED*/	}	/*	 * fill the bulk of the matrix	 */	v = res->m_table;	if (v2 == NULL) {		i = m->m_size;		while (i-- > 0) {			copyvalue(v1, v++);		}		return res;	}	/*	 * fill the diaginal of a square matrix if requested	 */	rows = res->m_max[0] - res->m_min[0] + 1;	v = res->m_table;	for (row = 0; row < rows; row++) {		copyvalue(v2, v+row);		v += rows;	}	return res;}/* * Allocate a matrix with the specified number of elements. */MATRIX *matalloc(long size){	MATRIX *m;	long i;	VALUE *vp;	m = (MATRIX *) malloc(matsize(size));	if (m == NULL) {		math_error("Cannot get memory to allocate matrix of size %d",			   size);		/*NOTREACHED*/	}	m->m_size = size;	for (i = size, vp = m->m_table; i > 0; i--, vp++)		vp->v_subtype = V_NOSUBTYPE;	return m;}/* * Free a matrix, along with all of its element values. */voidmatfree(MATRIX *m){	register VALUE *vp;	register long i;	vp = m->m_table;	i = m->m_size;	while (i-- > 0)		freevalue(vp++);	free(m);}/* * Test whether a matrix has any "nonzero" values. * Returns TRUE if so. */BOOLmattest(MATRIX *m){	register VALUE *vp;	register long i;	vp = m->m_table;	i = m->m_size;	while (i-- > 0) {		if (testvalue(vp++))			return TRUE;	}	return FALSE;}/* * Sum the elements in a matrix. */voidmatsum(MATRIX *m, VALUE *vres){	VALUE *vp;	VALUE tmp;		/* first sum value */	VALUE sum;		/* final sum value */	long i;	vp = m->m_table;	i = m->m_size;	copyvalue(vp, &sum);	while (--i > 0) {		addvalue(&sum, ++vp, &tmp);		freevalue(&sum);		sum = tmp;	}	*vres = sum;}/* * Test whether or not two matrices are equal. * Equality is determined by the shape and values of the matrices, * but not by their index bounds.  Returns TRUE if they differ. */BOOLmatcmp(MATRIX *m1, MATRIX *m2){	VALUE *v1, *v2;	long i;	if (m1 == m2)		return FALSE;	if ((m1->m_dim != m2->m_dim) || (m1->m_size != m2->m_size))		return TRUE;	for (i = 0; i < m1->m_dim; i++) {		if ((m1->m_max[i] - m1->m_min[i]) !=		    (m2->m_max[i] - m2->m_min[i]))		return TRUE;	}	v1 = m1->m_table;	v2 = m2->m_table;	i = m1->m_size;	while (i-- > 0) {		if (comparevalue(v1++, v2++))			return TRUE;	}	return FALSE;}voidmatreverse(MATRIX *m){	VALUE *p, *q;	VALUE tmp;	p = m->m_table;	q = m->m_table + m->m_size - 1;	while (q > p) {		tmp = *p;		*p++ = *q;		*q-- = tmp;	}}voidmatsort(MATRIX *m){	VALUE *a, *b, *next, *end;	VALUE *buf, *p;	VALUE *S[LONG_BITS];	long len[LONG_BITS];	long i, j, k;	buf = (VALUE *) malloc(m->m_size * sizeof(VALUE));	if (buf == NULL) {		math_error("Not enough memory for matsort");		/*NOTREACHED*/	}	next = m->m_table;	end = next + m->m_size;	for (k = 0; next && k < LONG_BITS; k++) {		S[k] = next++;			/* S[k] is start of a run */		len[k] = 1;		if (next == end)			next = NULL;		while (k > 0 && (!next || len[k] >= len[k - 1])) {/* merging */			j = len[k];			b = S[k--];			i = len[k];			a = S[k];			len[k] += j;			p = buf;			if (precvalue(b, a)) {				do {					*p++ = *b++;					j--;				} while (j > 0 && precvalue(b,a));				if (j == 0) {					memcpy(p, a, i * sizeof(VALUE));					memcpy(S[k], buf,					       len[k] * sizeof(VALUE));					continue;				}			}			do {				do {					*p++ = *a++;					i--;				} while (i > 0 && !precvalue(b,a));				if (i == 0) {					break;				}				do {					*p++ = *b++;					j--;				} while (j > 0 && precvalue(b,a));			} while (j != 0);			if (i == 0) {				memcpy(S[k], buf, (p - buf) * sizeof(VALUE));			} else if (j == 0) {				memcpy(p, a, i * sizeof(VALUE));				memcpy(S[k], buf, len[k] * sizeof(VALUE));			}		}	}	free(buf);	if (k >= LONG_BITS) {		/* this should never happen */		math_error("impossible k overflow in matsort!");		/*NOTREACHED*/	}}voidmatrandperm(MATRIX *m){	VALUE *vp;	long s, i;	VALUE val;	s = m->m_size;	for (vp = m->m_table; s > 1; vp++, s--) {		i = irand(s);		if (i > 0) {			val = *vp;			*vp = vp[i];			vp[i] = val;		}	}}/* * Test whether or not a matrix is the identity matrix. * Returns TRUE if so. */BOOLmatisident(MATRIX *m){	register VALUE *val;	/* current value */	long row, col;		/* row and column numbers */	val = m->m_table;	if (m->m_dim == 0) {		return (val->v_type == V_NUM && qisone(val->v_num));	}	if (m->m_dim == 1) {		for (row = m->m_min[0]; row <= m->m_max[0]; row++, val++) {			if (val->v_type != V_NUM || !qisone(val->v_num))				return FALSE;		}		return TRUE;	}	if ((m->m_dim != 2) ||		((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1])))			return FALSE;	for (row = m->m_min[0]; row <= m->m_max[0]; row++) {		/*		 * We could use col = m->m_min[1]; col < m->m_max[1]		 * but if m->m_min[0] != m->m_min[1] this won't work.		 * We know that we have a square 2-dimensional matrix		 * so we will pretend that m->m_min[0] == m->m_min[1].		 */		for (col = m->m_min[0]; col <= m->m_max[0]; col++) {			if (val->v_type != V_NUM)				return FALSE;			if (row == col) {				if (!qisone(val->v_num))					return FALSE;			} else {				if (!qiszero(val->v_num))					return FALSE;			}			val++;		}	}	return TRUE;}/* * Print a matrix and possibly few of its elements. * The argument supplied specifies how many elements to allow printing. * If any elements are printed, they are printed in short form. */voidmatprint(MATRIX *m, long max_print){	VALUE *vp;	long fullsize, count, index;	long dim, i, j;	char *msg;	long sizes[MAXDIM];	dim = m->m_dim;	fullsize = 1;	for (i = dim - 1; i >= 0; i--) {		sizes[i] = fullsize;		fullsize *= (m->m_max[i] - m->m_min[i] + 1);	}	msg = ((max_print > 0) ? "\nmat [" : "mat [");	if (dim) {		for (i = 0; i < dim; i++) {			if (m->m_min[i]) {				math_fmt("%s%ld:%ld", msg,					 m->m_min[i], m->m_max[i]);			} else {				math_fmt("%s%ld", msg, m->m_max[i] + 1);			}			msg = ",";		}	} else {		math_str("mat [");	}	if (max_print > fullsize) {		max_print = fullsize;	}	vp = m->m_table;	count = 0;	for (index = 0; index < fullsize; index++) {		if ((vp->v_type != V_NUM) || !qiszero(vp->v_num))			count++;		vp++;	}	math_fmt("] (%ld element%s, %ld nonzero)",		fullsize, (fullsize == 1) ? "" : "s", count);	if (max_print <= 0)		return;	/*	 * Now print the first few elements of the matrix in short	 * and unambigous format.	 */	math_str(":\n");	vp = m->m_table;	for (index = 0; index < max_print; index++) {		msg = "	 [";		j = index;		if (dim) {			for (i = 0; i < dim; i++) {				math_fmt("%s%ld", msg,					 m->m_min[i] + (j / sizes[i]));				j %= sizes[i];				msg = ",";			}		} else {			math_str(msg);		}		math_str("] = ");		printvalue(vp++, PRINT_SHORT | PRINT_UNAMBIG);		math_str("\n");	}	if (max_print < fullsize)		math_str("  ...\n");}

⌨️ 快捷键说明

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