3 /* Subroutine */ int dsytrs_(char *uplo, integer *n, integer *nrhs,
4 doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
7 /* -- LAPACK routine (version 3.0) --
8 Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
9 Courant Institute, Argonne National Lab, and Rice University
16 DSYTRS solves a system of linear equations A*X = B with a real
17 symmetric matrix A using the factorization A = U*D*U**T or
18 A = L*D*L**T computed by DSYTRF.
23 UPLO (input) CHARACTER*1
24 Specifies whether the details of the factorization are stored
25 as an upper or lower triangular matrix.
26 = 'U': Upper triangular, form is A = U*D*U**T;
27 = 'L': Lower triangular, form is A = L*D*L**T.
30 The order of the matrix A. N >= 0.
33 The number of right hand sides, i.e., the number of columns
34 of the matrix B. NRHS >= 0.
36 A (input) DOUBLE PRECISION array, dimension (LDA,N)
37 The block diagonal matrix D and the multipliers used to
38 obtain the factor U or L as computed by DSYTRF.
41 The leading dimension of the array A. LDA >= max(1,N).
43 IPIV (input) INTEGER array, dimension (N)
44 Details of the interchanges and the block structure of D
45 as determined by DSYTRF.
47 B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
48 On entry, the right hand side matrix B.
49 On exit, the solution matrix X.
52 The leading dimension of the array B. LDB >= max(1,N).
56 < 0: if INFO = -i, the i-th argument had an illegal value
58 =====================================================================
61 Parameter adjustments */
62 /* Table of constant values */
63 static doublereal c_b7 = -1.;
64 static integer c__1 = 1;
65 static doublereal c_b19 = 1.;
67 /* System generated locals */
68 integer a_dim1, a_offset, b_dim1, b_offset, i__1;
71 extern /* Subroutine */ int dger_(integer *, integer *, doublereal *,
72 doublereal *, integer *, doublereal *, integer *, doublereal *,
74 static doublereal akm1k;
76 extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *,
78 extern logical lsame_(char *, char *);
79 static doublereal denom;
80 extern /* Subroutine */ int dgemv_(char *, integer *, integer *,
81 doublereal *, doublereal *, integer *, doublereal *, integer *,
82 doublereal *, doublereal *, integer *), dswap_(integer *,
83 doublereal *, integer *, doublereal *, integer *);
85 static doublereal ak, bk;
87 extern /* Subroutine */ int xerbla_(char *, integer *);
88 static doublereal akm1, bkm1;
89 #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
90 #define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1]
94 a_offset = 1 + a_dim1 * 1;
98 b_offset = 1 + b_dim1 * 1;
103 upper = lsame_(uplo, "U");
104 if (! upper && ! lsame_(uplo, "L")) {
108 } else if (*nrhs < 0) {
110 } else if (*lda < max(1,*n)) {
112 } else if (*ldb < max(1,*n)) {
117 xerbla_("DSYTRS", &i__1);
121 /* Quick return if possible */
123 if (*n == 0 || *nrhs == 0) {
129 /* Solve A*X = B, where A = U*D*U'.
131 First solve U*D*X = B, overwriting B with X.
133 K is the main loop index, decreasing from N to 1 in steps of
134 1 or 2, depending on the size of the diagonal blocks. */
139 /* If K < 1, exit from loop. */
147 /* 1 x 1 diagonal block
149 Interchange rows K and IPIV(K). */
153 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);
156 /* Multiply by inv(U(K)), where U(K) is the transformation
157 stored in column K of A. */
160 dger_(&i__1, nrhs, &c_b7, &a_ref(1, k), &c__1, &b_ref(k, 1), ldb,
163 /* Multiply by the inverse of the diagonal block. */
165 d__1 = 1. / a_ref(k, k);
166 dscal_(nrhs, &d__1, &b_ref(k, 1), ldb);
170 /* 2 x 2 diagonal block
172 Interchange rows K-1 and -IPIV(K). */
176 dswap_(nrhs, &b_ref(k - 1, 1), ldb, &b_ref(kp, 1), ldb);
179 /* Multiply by inv(U(K)), where U(K) is the transformation
180 stored in columns K-1 and K of A. */
183 dger_(&i__1, nrhs, &c_b7, &a_ref(1, k), &c__1, &b_ref(k, 1), ldb,
186 dger_(&i__1, nrhs, &c_b7, &a_ref(1, k - 1), &c__1, &b_ref(k - 1,
187 1), ldb, &b_ref(1, 1), ldb);
189 /* Multiply by the inverse of the diagonal block. */
191 akm1k = a_ref(k - 1, k);
192 akm1 = a_ref(k - 1, k - 1) / akm1k;
193 ak = a_ref(k, k) / akm1k;
194 denom = akm1 * ak - 1.;
196 for (j = 1; j <= i__1; ++j) {
197 bkm1 = b_ref(k - 1, j) / akm1k;
198 bk = b_ref(k, j) / akm1k;
199 b_ref(k - 1, j) = (ak * bkm1 - bk) / denom;
200 b_ref(k, j) = (akm1 * bk - bkm1) / denom;
209 /* Next solve U'*X = B, overwriting B with X.
211 K is the main loop index, increasing from 1 to N in steps of
212 1 or 2, depending on the size of the diagonal blocks. */
217 /* If K > N, exit from loop. */
225 /* 1 x 1 diagonal block
227 Multiply by inv(U'(K)), where U(K) is the transformation
228 stored in column K of A. */
231 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b[b_offset], ldb, &a_ref(
232 1, k), &c__1, &c_b19, &b_ref(k, 1), ldb);
234 /* Interchange rows K and IPIV(K). */
238 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);
243 /* 2 x 2 diagonal block
245 Multiply by inv(U'(K+1)), where U(K+1) is the transformation
246 stored in columns K and K+1 of A. */
249 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b[b_offset], ldb, &a_ref(
250 1, k), &c__1, &c_b19, &b_ref(k, 1), ldb);
252 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b[b_offset], ldb, &a_ref(
253 1, k + 1), &c__1, &c_b19, &b_ref(k + 1, 1), ldb);
255 /* Interchange rows K and -IPIV(K). */
259 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);
270 /* Solve A*X = B, where A = L*D*L'.
272 First solve L*D*X = B, overwriting B with X.
274 K is the main loop index, increasing from 1 to N in steps of
275 1 or 2, depending on the size of the diagonal blocks. */
280 /* If K > N, exit from loop. */
288 /* 1 x 1 diagonal block
290 Interchange rows K and IPIV(K). */
294 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);
297 /* Multiply by inv(L(K)), where L(K) is the transformation
298 stored in column K of A. */
302 dger_(&i__1, nrhs, &c_b7, &a_ref(k + 1, k), &c__1, &b_ref(k,
303 1), ldb, &b_ref(k + 1, 1), ldb);
306 /* Multiply by the inverse of the diagonal block. */
308 d__1 = 1. / a_ref(k, k);
309 dscal_(nrhs, &d__1, &b_ref(k, 1), ldb);
313 /* 2 x 2 diagonal block
315 Interchange rows K+1 and -IPIV(K). */
319 dswap_(nrhs, &b_ref(k + 1, 1), ldb, &b_ref(kp, 1), ldb);
322 /* Multiply by inv(L(K)), where L(K) is the transformation
323 stored in columns K and K+1 of A. */
327 dger_(&i__1, nrhs, &c_b7, &a_ref(k + 2, k), &c__1, &b_ref(k,
328 1), ldb, &b_ref(k + 2, 1), ldb);
330 dger_(&i__1, nrhs, &c_b7, &a_ref(k + 2, k + 1), &c__1, &b_ref(
331 k + 1, 1), ldb, &b_ref(k + 2, 1), ldb);
334 /* Multiply by the inverse of the diagonal block. */
336 akm1k = a_ref(k + 1, k);
337 akm1 = a_ref(k, k) / akm1k;
338 ak = a_ref(k + 1, k + 1) / akm1k;
339 denom = akm1 * ak - 1.;
341 for (j = 1; j <= i__1; ++j) {
342 bkm1 = b_ref(k, j) / akm1k;
343 bk = b_ref(k + 1, j) / akm1k;
344 b_ref(k, j) = (ak * bkm1 - bk) / denom;
345 b_ref(k + 1, j) = (akm1 * bk - bkm1) / denom;
354 /* Next solve L'*X = B, overwriting B with X.
356 K is the main loop index, decreasing from N to 1 in steps of
357 1 or 2, depending on the size of the diagonal blocks. */
362 /* If K < 1, exit from loop. */
370 /* 1 x 1 diagonal block
372 Multiply by inv(L'(K)), where L(K) is the transformation
373 stored in column K of A. */
377 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b_ref(k + 1, 1), ldb,
378 &a_ref(k + 1, k), &c__1, &c_b19, &b_ref(k, 1), ldb);
381 /* Interchange rows K and IPIV(K). */
385 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);
390 /* 2 x 2 diagonal block
392 Multiply by inv(L'(K-1)), where L(K-1) is the transformation
393 stored in columns K-1 and K of A. */
397 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b_ref(k + 1, 1), ldb,
398 &a_ref(k + 1, k), &c__1, &c_b19, &b_ref(k, 1), ldb);
400 dgemv_("Transpose", &i__1, nrhs, &c_b7, &b_ref(k + 1, 1), ldb,
401 &a_ref(k + 1, k - 1), &c__1, &c_b19, &b_ref(k - 1, 1)
405 /* Interchange rows K and -IPIV(K). */
409 dswap_(nrhs, &b_ref(k, 1), ldb, &b_ref(kp, 1), ldb);