/* * $Id: dgtsv.c,v 1.1.1.1 2005/09/18 22:04:48 dhmunro Exp $ * LAPACK routine to solve a tridiagonal matrix. */ /* Copyright (c) 2005, The Regents of the University of California. * All rights reserved. * This file is part of yorick (http://yorick.sourceforge.net). * Read the accompanying LICENSE file for details. */ #include "dg.h" /*-----Fortran intrinsics converted-----*/ #define abs(x) ((x)>=0?(x):-(x)) #define max(x,y) ((x)>(y)?(x):(y)) /*-----end of Fortran intrinsics-----*/ void dgtsv( long n, long nrhs, double dl[], double d[], double du[], double b[], long ldb, long *info ) { /** * -- LAPACK routine (version 1.1) -- * Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., * Courant Institute, Argonne National Lab, and Rice University * March 31, 1993 * * .. Scalar Arguments ..*/ /** .. * .. Array Arguments ..*/ #undef du_1 #define du_1(a1) du[a1-1] #undef dl_1 #define dl_1(a1) dl[a1-1] #undef d_1 #define d_1(a1) d[a1-1] #undef b_2 #define b_2(a1,a2) b[a1-1+ldb*(a2-1)] /** .. * * Purpose * ======= * * DGTSV solves the equation * * A*X = B, * * where A is an N-by-N tridiagonal matrix, by Gaussian elimination with * partial pivoting. * * Note that the equation A'*X = B may be solved by interchanging the * order of the arguments DU and DL. * * Arguments * ========= * * N (input) INTEGER * The order of the matrix A. N >= 0. * * NRHS (input) INTEGER * The number of right hand sides, i.e., the number of columns * of the matrix B. NRHS >= 0. * * DL_1 (input/output) DOUBLE PRECISION array, dimension (N-1) * On entry, DL must contain the (n-1) subdiagonal elements of * A. * On exit, DL is overwritten by the (n-2) elements of the * second superdiagonal of the upper triangular matrix U from * the LU factorization of A, in DL_1(1), ..., DL_1(n-2). * * D_1 (input/output) DOUBLE PRECISION array, dimension (N) * On entry, D must contain the diagonal elements of A. * On exit, D is overwritten by the n diagonal elements of U. * * DU_1 (input/output) DOUBLE PRECISION array, dimension (N-1) * On entry, DU must contain the (n-1) superdiagonal elements * of A. * On exit, DU is overwritten by the (n-1) elements of the first * superdiagonal of U. * * B_2 (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS) * On entry, the N-by-NRHS right hand side matrix B. * On exit, if INFO = 0, the N-by-NRHS solution matrix X. * * LDB (input) INTEGER * The leading dimension of the array B. LDB >= max(1,N). * * INFO (output) * = 0: successful exit * < 0: if INFO = -i, the i-th argument had an illegal value * > 0: if INFO = i, U(i,i) is exactly zero, and the solution * has not been computed. The factorization has not been * completed unless i = N. * * ===================================================================== * * .. Parameters ..*/ #undef zero #define zero 0.0e+0 /** .. * .. Local Scalars ..*/ long j, k; double mult, temp; /** .. * .. Intrinsic Functions ..*/ /* intrinsic abs, max;*/ /** .. * .. Executable Statements .. **/ /*-----implicit-declarations-----*/ /*-----end-of-declarations-----*/ *info = 0; if( n<0 ) { *info = -1; } else if( nrhs<0 ) { *info = -2; } else if( ldb=abs( dl_1( k ) ) ) { /** * No row interchange required **/ mult = dl_1( k ) / d_1( k ); d_1( k+1 ) = d_1( k+1 ) - mult*du_1( k ); for (j=1 ; j<=nrhs ; j+=1) { b_2( k+1, j ) = b_2( k+1, j ) - mult*b_2( k, j ); } if( k<( n-1 ) ) dl_1( k ) = zero; } else { /** * Interchange rows K and K+1 **/ mult = d_1( k ) / dl_1( k ); d_1( k ) = dl_1( k ); temp = d_1( k+1 ); d_1( k+1 ) = du_1( k ) - mult*temp; if( k<( n-1 ) ) { dl_1( k ) = du_1( k+1 ); du_1( k+1 ) = -mult*dl_1( k ); } du_1( k ) = temp; for (j=1 ; j<=nrhs ; j+=1) { temp = b_2( k, j ); b_2( k, j ) = b_2( k+1, j ); b_2( k+1, j ) = temp - mult*b_2( k+1, j ); } } } if( d_1( n )==zero ) { *info = n; return; } /** * Back solve with the matrix U from the factorization. **/ for (j=1 ; j<=nrhs ; j+=1) { b_2( n, j ) = b_2( n, j ) / d_1( n ); if( n>1 ) b_2( n-1, j ) = ( b_2( n-1, j )-du_1( n-1 )*b_2( n, j ) ) / d_1( n-1 ); for (k=n - 2 ; k>=1 ; k+=-1) { b_2( k, j ) = ( b_2( k, j )-du_1( k )*b_2( k+1, j )-dl_1( k )* b_2( k+2, j ) ) / d_1( k ); } } return; /** * End of DGTSV **/ }