diff options
Diffstat (limited to 'libm/double/simq.c')
| -rw-r--r-- | libm/double/simq.c | 180 | 
1 files changed, 180 insertions, 0 deletions
| diff --git a/libm/double/simq.c b/libm/double/simq.c new file mode 100644 index 000000000..96d63e521 --- /dev/null +++ b/libm/double/simq.c @@ -0,0 +1,180 @@ +/*							simq.c + * + *	Solution of simultaneous linear equations AX = B + *	by Gaussian elimination with partial pivoting + * + * + * + * SYNOPSIS: + * + * double A[n*n], B[n], X[n]; + * int n, flag; + * int IPS[]; + * int simq(); + * + * ercode = simq( A, B, X, n, flag, IPS ); + * + * + * + * DESCRIPTION: + * + * B, X, IPS are vectors of length n. + * A is an n x n matrix (i.e., a vector of length n*n), + * stored row-wise: that is, A(i,j) = A[ij], + * where ij = i*n + j, which is the transpose of the normal + * column-wise storage. + * + * The contents of matrix A are destroyed. + * + * Set flag=0 to solve. + * Set flag=-1 to do a new back substitution for different B vector + * using the same A matrix previously reduced when flag=0. + * + * The routine returns nonzero on error; messages are printed. + * + * + * ACCURACY: + * + * Depends on the conditioning (range of eigenvalues) of matrix A. + * + * + * REFERENCE: + * + * Computer Solution of Linear Algebraic Systems, + * by George E. Forsythe and Cleve B. Moler; Prentice-Hall, 1967. + * + */ + +/*							simq	2 */ + +#include <stdio.h> +#define fabs(x) ((x) < 0 ? -(x) : (x)) + +int simq( A, B, X, n, flag, IPS ) +double A[], B[], X[]; +int n, flag; +int IPS[]; +{ +int i, j, ij, ip, ipj, ipk, ipn; +int idxpiv, iback; +int k, kp, kp1, kpk, kpn; +int nip, nkp, nm1; +double em, q, rownrm, big, size, pivot, sum; + +nm1 = n-1; +if( flag < 0 ) +	goto solve; + +/*	Initialize IPS and X	*/ + +ij=0; +for( i=0; i<n; i++ ) +	{ +	IPS[i] = i; +	rownrm = 0.0; +	for( j=0; j<n; j++ ) +		{ +		q = fabs( A[ij] ); +		if( rownrm < q ) +			rownrm = q; +		++ij; +		} +	if( rownrm == 0.0 ) +		{ +		printf("SIMQ ROWNRM=0"); +		return(1); +		} +	X[i] = 1.0/rownrm; +	} + +/*							simq	3 */ +/*	Gaussian elimination with partial pivoting 	*/ + +for( k=0; k<nm1; k++ ) +	{ +	big= 0.0; +	idxpiv = 0; +	for( i=k; i<n; i++ ) +		{ +		ip = IPS[i]; +		ipk = n*ip + k; +		size = fabs( A[ipk] ) * X[ip]; +		if( size > big ) +			{ +			big = size; +			idxpiv = i; +			} +		} + +	if( big == 0.0 ) +		{ +		printf( "SIMQ BIG=0" ); +		return(2); +		} +	if( idxpiv != k ) +		{ +		j = IPS[k]; +		IPS[k] = IPS[idxpiv]; +		IPS[idxpiv] = j; +		} +	kp = IPS[k]; +	kpk = n*kp + k; +	pivot = A[kpk]; +	kp1 = k+1; +	for( i=kp1; i<n; i++ ) +		{ +		ip = IPS[i]; +		ipk = n*ip + k; +		em = -A[ipk]/pivot; +		A[ipk] = -em; +		nip = n*ip; +		nkp = n*kp; +		for( j=kp1; j<n; j++ ) +			{ +			ipj = nip + j; +			A[ipj] = A[ipj] + em * A[nkp + j]; +			} +		} +	} +kpn = n * IPS[n-1] + n - 1;	/* last element of IPS[n] th row */ +if( A[kpn] == 0.0 ) +	{ +	printf( "SIMQ A[kpn]=0"); +	return(3); +	} + +/*							simq 4 */ +/*	back substitution	*/ + +solve: +ip = IPS[0]; +X[0] = B[ip]; +for( i=1; i<n; i++ ) +	{ +	ip = IPS[i]; +	ipj = n * ip; +	sum = 0.0; +	for( j=0; j<i; j++ ) +		{ +		sum += A[ipj] * X[j]; +		++ipj; +		} +	X[i] = B[ip] - sum; +	} + +ipn = n * IPS[n-1] + n - 1; +X[n-1] = X[n-1]/A[ipn]; + +for( iback=1; iback<n; iback++ ) +	{ +/* i goes (n-1),...,1	*/ +	i = nm1 - iback; +	ip = IPS[i]; +	nip = n*ip; +	sum = 0.0; +	for( j=i+1; j<n; j++ ) +		sum += A[nip+j] * X[j]; +	X[i] = (X[i] - sum)/A[nip+i]; +	} +return(0); +} | 
