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

📄 matfunc.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 3 页
字号:
	long index;	MATRIX *res;	if ((vp->v_type == V_NUM) && qiszero(vp->v_num)) {		math_error("Division by zero");		/*NOTREACHED*/	}	res = matalloc(m->m_size);	*res = *m;	val = m->m_table;	vres = res->m_table;	for (index = m->m_size; index > 0; index--)		quovalue(val++, vp, v3, vres++);	return res;}/* * Divide the elements of a matrix by a specified value, keeping * only the remainder of the division. * * given: *	m		matrix to be divided *	vp		value to divide by *	v3		rounding type parameter */MATRIX *matmodval(MATRIX *m, VALUE *vp, VALUE *v3){	register VALUE *val, *vres;	long index;	MATRIX *res;	if ((vp->v_type == V_NUM) && qiszero(vp->v_num)) {		math_error("Division by zero");		/*NOTREACHED*/	}	res = matalloc(m->m_size);	*res = *m;	val = m->m_table;	vres = res->m_table;	for (index = m->m_size; index > 0; index--)		modvalue(val++, vp, v3, vres++);	return res;}VALUEmattrace(MATRIX *m){	VALUE *vp;	VALUE sum;	VALUE tmp;	long i, j;	if (m->m_dim < 2) {		matsum(m, &sum);		return sum;	}	if (m->m_dim != 2)		return error_value(E_MATTRACE2);	i = (m->m_max[0] - m->m_min[0] + 1);	j = (m->m_max[1] - m->m_min[1] + 1);	if (i != j)		return error_value(E_MATTRACE3);	vp = m->m_table;	copyvalue(vp, &sum);	j++;	while (--i > 0) {		vp += j;		addvalue(&sum, vp, &tmp);		freevalue(&sum);		sum = tmp;	}	return sum;}/* * Transpose a 2-dimensional matrix */MATRIX *mattrans(MATRIX *m){	register VALUE *v1, *v2;	/* current values */	long rows, cols;		/* rows and columns in new matrix */	long row, col;			/* current row and column */	MATRIX *res;	if (m->m_dim < 2)		return matcopy(m);	res = matalloc(m->m_size);	res->m_dim = 2;	res->m_min[0] = m->m_min[1];	res->m_max[0] = m->m_max[1];	res->m_min[1] = m->m_min[0];	res->m_max[1] = m->m_max[0];	rows = (m->m_max[1] - m->m_min[1] + 1);	cols = (m->m_max[0] - m->m_min[0] + 1);	v1 = res->m_table;	for (row = 0; row < rows; row++) {		v2 = &m->m_table[row];		for (col = 0; col < cols; col++) {			copyvalue(v2, v1);			v1++;			v2 += rows;		}	}	return res;}/* * Produce a matrix with values all of which are conjugated. */MATRIX *matconj(MATRIX *m){	register VALUE *val, *vres;	long index;	MATRIX *res;	res = matalloc(m->m_size);	*res = *m;	val = m->m_table;	vres = res->m_table;	for (index = m->m_size; index > 0; index--)		conjvalue(val++, vres++);	return res;}/* * Round elements of a matrix to specified number of decimal digits */MATRIX *matround(MATRIX *m, VALUE *v2, VALUE *v3){	VALUE *p, *q;	long s;	MATRIX *res;	s = m->m_size;	res = matalloc(s);	*res = *m;	p = m->m_table;	q = res->m_table;	while (s-- > 0)		roundvalue(p++, v2, v3, q++);	return res;}/* * Round elements of a matrix to specified number of binary digits */MATRIX *matbround(MATRIX *m, VALUE *v2, VALUE *v3){	VALUE *p, *q;	long s;	MATRIX *res;	s = m->m_size;	res = matalloc(s);	*res = *m;	p = m->m_table;	q = res->m_table;	while (s-- > 0)		broundvalue(p++, v2, v3, q++);	return res;}/* * Approximate a matrix by approximating elemenbs to be multiples of * v2, rounding type determined by v3. */MATRIX *matappr(MATRIX *m, VALUE *v2, VALUE *v3){	VALUE *p, *q;	long s;	MATRIX *res;	s = m->m_size;	res = matalloc(s);	*res = *m;	p = m->m_table;	q = res->m_table;	while (s-- > 0)		apprvalue(p++, v2, v3, q++);	return res;}/* * Produce a matrix with values all of which have been truncated to integers. */MATRIX *matint(MATRIX *m){	register VALUE *val, *vres;	long index;	MATRIX *res;	res = matalloc(m->m_size);	*res = *m;	val = m->m_table;	vres = res->m_table;	for (index = m->m_size; index > 0; index--)		intvalue(val++, vres++);	return res;}/* * Produce a matrix with values all of which have only the fraction part left. */MATRIX *matfrac(MATRIX *m){	register VALUE *val, *vres;	long index;	MATRIX *res;	res = matalloc(m->m_size);	*res = *m;	val = m->m_table;	vres = res->m_table;	for (index = m->m_size; index > 0; index--)		fracvalue(val++, vres++);	return res;}/* * Index a matrix normally by the specified set of index values. * Returns the address of the matrix element if it is valid, or generates * an error if the index values are out of range.  The create flag is TRUE * if the element is to be written, but this is ignored here. * * given: *	mp		matrix to operate on *	create		TRUE => create if element does not exist *	dim		dimension of the indexing *	indices		table of values being indexed by *//*ARGSUSED*/VALUE *matindex(MATRIX *mp, BOOL UNUSED create, long dim, VALUE *indices){	NUMBER *q;		/* index value */	VALUE *vp;	long index;		/* index value as an integer */	long offset;		/* current offset into array */	int i;			/* loop counter */	if (dim < 0) {		math_error("Negative dimension %ld for matrix", dim);		/*NOTREACHED*/	}	for (;;) {		if (dim <  mp->m_dim) {			math_error(			    "Indexing a %ldd matrix as a %ldd matrix",			    mp->m_dim, dim);			/*NOTREACHED*/		}		offset = 0;		for (i = 0; i < mp->m_dim; i++) {			if (indices->v_type != V_NUM) {				math_error("Non-numeric index for matrix");				/*NOTREACHED*/			}			q = indices->v_num;			if (qisfrac(q)) {				math_error("Non-integral index for matrix");				/*NOTREACHED*/			}			index = qtoi(q);			if (zge31b(q->num) || (index < mp->m_min[i]) ||			    (index > mp->m_max[i])) {				math_error("Index out of bounds for matrix");				/*NOTREACHED*/			}			offset *= (mp->m_max[i] - mp->m_min[i] + 1);			offset += (index - mp->m_min[i]);			indices++;		}		vp = mp->m_table + offset;		dim -= mp->m_dim;		if (dim == 0)			break;		if (vp->v_type != V_MAT) {			math_error("Non-matrix argument for matindex");			/*NOTREACHED*/		}		mp = vp->v_mat;	}	return vp;}/* * Returns the list of indices for a matrix element with specified * double-bracket index. */LIST *matindices(MATRIX *mp, long index){	LIST *lp;	int j;	long d;	VALUE val;	if (index < 0 || index >= mp->m_size)		return NULL;	lp = listalloc();	val.v_type = V_NUM;	j = mp->m_dim;	while (--j >= 0) {		d = mp->m_max[j] - mp->m_min[j] + 1;		val.v_num = itoq(index % d + mp->m_min[j]);		insertlistfirst(lp, &val);		qfree(val.v_num);		index /= d;	}	return lp;}/* * Search a matrix for the specified value, starting with the specified index. * Returns 0 and stores index if value found; otherwise returns 1. */intmatsearch(MATRIX *m, VALUE *vp, long i, long j, ZVALUE *index){	register VALUE *val;	val = &m->m_table[i];	if (i < 0 || j > m->m_size) {		math_error("This should not happen in call to matsearch");		/*NOTREACHED*/	}	while (i < j) {		if (acceptvalue(val++, vp)) {			utoz(i, index);			return 0;		}		i++;	}	return 1;}/* * Search a matrix backwards for the specified value, starting with the * specified index.  Returns 0 and stores index if value found; otherwise * returns 1. */intmatrsearch(MATRIX *m, VALUE *vp, long i, long j, ZVALUE *index){	register VALUE *val;	if (i < 0 || j > m->m_size) {		math_error("This should not happen in call to matrsearch");		/*NOTREACHED*/	}	val = &m->m_table[--j];	while (j >= i) {		if (acceptvalue(val--, vp)) {			utoz(j, index);			return 0;		}		j--;	}	return 1;}/* * Fill all of the elements of a matrix with one of two specified values. * All entries are filled with the first specified value, except that if * the matrix is w-dimensional and the second value pointer is non-NULL, then * all diagonal entries are filled with the second value.  This routine * affects the supplied matrix directly, and doesn't return a copy. * * given: *	m		matrix to be filled *	v1		value to fill most of matrix with *	v2		value for diagonal entries or null */voidmatfill(MATRIX *m, VALUE *v1, VALUE *v2){	register VALUE *val;	VALUE temp1, temp2;	long rows, cols;	long i, j;	copyvalue(v1, &temp1);	val = m->m_table;	if (m->m_dim != 2 || v2 == NULL) {		for (i = m->m_size; i > 0; i--) {			freevalue(val);			copyvalue(&temp1, val++);		}		freevalue(&temp1);		return;	}	copyvalue(v2, &temp2);	rows = m->m_max[0] - m->m_min[0] + 1;	cols = m->m_max[1] - m->m_min[1] + 1;	for (i = 0; i < rows; i++) {		for (j = 0; j < cols; j++) {			freevalue(val);			if (i == j)				copyvalue(&temp2, val++);			else				copyvalue(&temp1, val++);		}	}	freevalue(&temp1);	freevalue(&temp2);}/* * Set a copy of a square matrix to the identity matrix. */static MATRIX *matident(MATRIX *m){	register VALUE *val;	/* current value */	long row, col;		/* current row and column */	long rows;		/* number of rows */	MATRIX *res;		/* resulting matrix */	if (m->m_dim != 2) {		math_error(		    "Matrix dimension must be two for setting to identity");		/*NOTREACHED*/	}	if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1])) {		math_error("Matrix must be square for setting to identity");		/*NOTREACHED*/	}	res = matalloc(m->m_size);	*res = *m;	val = res->m_table;	rows = (res->m_max[0] - res->m_min[0] + 1);	for (row = 0; row < rows; row++) {		for (col = 0; col < rows; col++) {			val->v_type = V_NUM;			val->v_num = ((row == col) ? qlink(&_qone_) :						     qlink(&_qzero_));			val++;		}	}	return res;}/* * Calculate the inverse of a matrix if it exists. * This is done by using transformations on the supplied matrix to convert * it to the identity matrix, and simultaneously applying the same set of * transformations to the identity matrix. */MATRIX *matinv(MATRIX *m){	MATRIX *res;		/* matrix to become the inverse */	long rows;		/* number of rows */	long cur;		/* current row being worked on */	long row, col;		/* temp row and column values */	VALUE *val;		/* current value in matrix*/	VALUE *vres;		/* current value in result for dim < 2 */	VALUE mulval;		/* value to multiply rows by */	VALUE tmpval;		/* temporary value */	if (m->m_dim < 2) {		res = matalloc(m->m_size);		*res = *m;		val = m->m_table;		vres = res->m_table;		for (cur = m->m_size; cur > 0; cur--)			invertvalue(val++, vres++);		return res;	}	if (m->m_dim != 2) {		math_error("Matrix dimension exceeds two for inverse");		/*NOTREACHED*/	}	if ((m->m_max[0] - m->m_min[0]) != (m->m_max[1] - m->m_min[1])) {		math_error("Inverting non-square matrix");		/*NOTREACHED*/	}	/*	 * Begin by creating the identity matrix with the same attributes.	 */	res = matalloc(m->m_size);	*res = *m;	rows = (m->m_max[0] - m->m_min[0] + 1);	val = res->m_table;	for (row = 0; row < rows; row++) {		for (col = 0; col < rows; col++) {			if (row == col)				val->v_num = qlink(&_qone_);			else				val->v_num = qlink(&_qzero_);			val->v_type = V_NUM;			val++;		}	}	/*	 * Now loop over each row, and eliminate all entries in the	 * corresponding column by using row operations.  Do the same	 * operations on the resulting matrix.	Copy the original matrix	 * so that we don't destroy it.	 */	m = matcopy(m);	for (cur = 0; cur < rows; cur++) {		/*		 * Find the first nonzero value in the rest of the column		 * downwards from [cur,cur].  If there is no such value, then		 * the matrix is not invertible.  If the first nonzero entry		 * is not the current row, then swap the two rows to make the		 * current one nonzero.		 */		row = cur;		val = &m->m_table[(row * rows) + row];		while (testvalue(val) == 0) {			if (++row >= rows) {				matfree(m);				matfree(res);				math_error("Matrix is not invertible");				/*NOTREACHED*/			}			val += rows;		}		invertvalue(val, &mulval);		if (row != cur) {			matswaprow(m, row, cur);			matswaprow(res, row, cur);		}		/*		 * Now for every other nonzero entry in the current column,		 * subtract the appropriate multiple of the current row to		 * force that entry to become zero.		 */		val = &m->m_table[cur];		for (row = 0; row < rows; row++) {			if ((row == cur) || (testvalue(val) == 0)) {				if (row+1 < rows)					val += rows;				continue;			}			mulvalue(val, &mulval, &tmpval);			matsubrow(m, row, cur, &tmpval);			matsubrow(res, row, cur, &tmpval);			freevalue(&tmpval);			if (row+1 < rows)				val += rows;		}		freevalue(&mulval);	}	/*	 * Now the original matrix has nonzero entries only on its main	 * diagonal.  Scale the rows of the result matrix by the inverse	 * of those entries.	 */	val = m->m_table;	for (row = 0; row < rows; row++) {		if ((val->v_type != V_NUM) || !qisone(val->v_num)) {			invertvalue(val, &mulval);			matmulrow(res, row, &mulval);			freevalue(&mulval);		}		if (row+1 < rows)			val += (rows + 1);	}	matfree(m);	return res;}/* * Calculate the determinant of a square matrix. * This uses the fraction-free Gauss-Bareiss algorithm. */VALUEmatdet(MATRIX *m){	long n;			/* original matrix is n x n */	long k;			/* working submatrix is k x k */	long i, j;

⌨️ 快捷键说明

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