LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
ssptrs.f
Go to the documentation of this file.
1*> \brief \b SSPTRS
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SSPTRS + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ssptrs.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ssptrs.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssptrs.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SSPTRS( UPLO, N, NRHS, AP, IPIV, B, LDB, INFO )
20*
21* .. Scalar Arguments ..
22* CHARACTER UPLO
23* INTEGER INFO, LDB, N, NRHS
24* ..
25* .. Array Arguments ..
26* INTEGER IPIV( * )
27* REAL AP( * ), B( LDB, * )
28* ..
29*
30*
31*> \par Purpose:
32* =============
33*>
34*> \verbatim
35*>
36*> SSPTRS solves a system of linear equations A*X = B with a real
37*> symmetric matrix A stored in packed format using the factorization
38*> A = U*D*U**T or A = L*D*L**T computed by SSPTRF.
39*> \endverbatim
40*
41* Arguments:
42* ==========
43*
44*> \param[in] UPLO
45*> \verbatim
46*> UPLO is CHARACTER*1
47*> Specifies whether the details of the factorization are stored
48*> as an upper or lower triangular matrix.
49*> = 'U': Upper triangular, form is A = U*D*U**T;
50*> = 'L': Lower triangular, form is A = L*D*L**T.
51*> \endverbatim
52*>
53*> \param[in] N
54*> \verbatim
55*> N is INTEGER
56*> The order of the matrix A. N >= 0.
57*> \endverbatim
58*>
59*> \param[in] NRHS
60*> \verbatim
61*> NRHS is INTEGER
62*> The number of right hand sides, i.e., the number of columns
63*> of the matrix B. NRHS >= 0.
64*> \endverbatim
65*>
66*> \param[in] AP
67*> \verbatim
68*> AP is REAL array, dimension (N*(N+1)/2)
69*> The block diagonal matrix D and the multipliers used to
70*> obtain the factor U or L as computed by SSPTRF, stored as a
71*> packed triangular matrix.
72*> \endverbatim
73*>
74*> \param[in] IPIV
75*> \verbatim
76*> IPIV is INTEGER array, dimension (N)
77*> Details of the interchanges and the block structure of D
78*> as determined by SSPTRF.
79*> \endverbatim
80*>
81*> \param[in,out] B
82*> \verbatim
83*> B is REAL array, dimension (LDB,NRHS)
84*> On entry, the right hand side matrix B.
85*> On exit, the solution matrix X.
86*> \endverbatim
87*>
88*> \param[in] LDB
89*> \verbatim
90*> LDB is INTEGER
91*> The leading dimension of the array B. LDB >= max(1,N).
92*> \endverbatim
93*>
94*> \param[out] INFO
95*> \verbatim
96*> INFO is INTEGER
97*> = 0: successful exit
98*> < 0: if INFO = -i, the i-th argument had an illegal value
99*> \endverbatim
100*
101* Authors:
102* ========
103*
104*> \author Univ. of Tennessee
105*> \author Univ. of California Berkeley
106*> \author Univ. of Colorado Denver
107*> \author NAG Ltd.
108*
109*> \ingroup hptrs
110*
111* =====================================================================
112 SUBROUTINE ssptrs( UPLO, N, NRHS, AP, IPIV, B, LDB, INFO )
113*
114* -- LAPACK computational routine --
115* -- LAPACK is a software package provided by Univ. of Tennessee, --
116* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
117*
118* .. Scalar Arguments ..
119 CHARACTER UPLO
120 INTEGER INFO, LDB, N, NRHS
121* ..
122* .. Array Arguments ..
123 INTEGER IPIV( * )
124 REAL AP( * ), B( LDB, * )
125* ..
126*
127* =====================================================================
128*
129* .. Parameters ..
130 REAL ONE
131 parameter( one = 1.0e+0 )
132* ..
133* .. Local Scalars ..
134 LOGICAL UPPER
135 INTEGER J, K, KC, KP
136 REAL AK, AKM1, AKM1K, BK, BKM1, DENOM
137* ..
138* .. External Functions ..
139 LOGICAL LSAME
140 EXTERNAL lsame
141* ..
142* .. External Subroutines ..
143 EXTERNAL sgemv, sger, sscal, sswap, xerbla
144* ..
145* .. Intrinsic Functions ..
146 INTRINSIC max
147* ..
148* .. Executable Statements ..
149*
150 info = 0
151 upper = lsame( uplo, 'U' )
152 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
153 info = -1
154 ELSE IF( n.LT.0 ) THEN
155 info = -2
156 ELSE IF( nrhs.LT.0 ) THEN
157 info = -3
158 ELSE IF( ldb.LT.max( 1, n ) ) THEN
159 info = -7
160 END IF
161 IF( info.NE.0 ) THEN
162 CALL xerbla( 'SSPTRS', -info )
163 RETURN
164 END IF
165*
166* Quick return if possible
167*
168 IF( n.EQ.0 .OR. nrhs.EQ.0 )
169 $ RETURN
170*
171 IF( upper ) THEN
172*
173* Solve A*X = B, where A = U*D*U**T.
174*
175* First solve U*D*X = B, overwriting B with X.
176*
177* K is the main loop index, decreasing from N to 1 in steps of
178* 1 or 2, depending on the size of the diagonal blocks.
179*
180 k = n
181 kc = n*( n+1 ) / 2 + 1
182 10 CONTINUE
183*
184* If K < 1, exit from loop.
185*
186 IF( k.LT.1 )
187 $ GO TO 30
188*
189 kc = kc - k
190 IF( ipiv( k ).GT.0 ) THEN
191*
192* 1 x 1 diagonal block
193*
194* Interchange rows K and IPIV(K).
195*
196 kp = ipiv( k )
197 IF( kp.NE.k )
198 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
199*
200* Multiply by inv(U(K)), where U(K) is the transformation
201* stored in column K of A.
202*
203 CALL sger( k-1, nrhs, -one, ap( kc ), 1, b( k, 1 ), ldb,
204 $ b( 1, 1 ), ldb )
205*
206* Multiply by the inverse of the diagonal block.
207*
208 CALL sscal( nrhs, one / ap( kc+k-1 ), b( k, 1 ), ldb )
209 k = k - 1
210 ELSE
211*
212* 2 x 2 diagonal block
213*
214* Interchange rows K-1 and -IPIV(K).
215*
216 kp = -ipiv( k )
217 IF( kp.NE.k-1 )
218 $ CALL sswap( nrhs, b( k-1, 1 ), ldb, b( kp, 1 ), ldb )
219*
220* Multiply by inv(U(K)), where U(K) is the transformation
221* stored in columns K-1 and K of A.
222*
223 CALL sger( k-2, nrhs, -one, ap( kc ), 1, b( k, 1 ), ldb,
224 $ b( 1, 1 ), ldb )
225 CALL sger( k-2, nrhs, -one, ap( kc-( k-1 ) ), 1,
226 $ b( k-1, 1 ), ldb, b( 1, 1 ), ldb )
227*
228* Multiply by the inverse of the diagonal block.
229*
230 akm1k = ap( kc+k-2 )
231 akm1 = ap( kc-1 ) / akm1k
232 ak = ap( kc+k-1 ) / akm1k
233 denom = akm1*ak - one
234 DO 20 j = 1, nrhs
235 bkm1 = b( k-1, j ) / akm1k
236 bk = b( k, j ) / akm1k
237 b( k-1, j ) = ( ak*bkm1-bk ) / denom
238 b( k, j ) = ( akm1*bk-bkm1 ) / denom
239 20 CONTINUE
240 kc = kc - k + 1
241 k = k - 2
242 END IF
243*
244 GO TO 10
245 30 CONTINUE
246*
247* Next solve U**T*X = B, overwriting B with X.
248*
249* K is the main loop index, increasing from 1 to N in steps of
250* 1 or 2, depending on the size of the diagonal blocks.
251*
252 k = 1
253 kc = 1
254 40 CONTINUE
255*
256* If K > N, exit from loop.
257*
258 IF( k.GT.n )
259 $ GO TO 50
260*
261 IF( ipiv( k ).GT.0 ) THEN
262*
263* 1 x 1 diagonal block
264*
265* Multiply by inv(U**T(K)), where U(K) is the transformation
266* stored in column K of A.
267*
268 CALL sgemv( 'Transpose', k-1, nrhs, -one, b, ldb,
269 $ ap( kc ),
270 $ 1, one, b( k, 1 ), ldb )
271*
272* Interchange rows K and IPIV(K).
273*
274 kp = ipiv( k )
275 IF( kp.NE.k )
276 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
277 kc = kc + k
278 k = k + 1
279 ELSE
280*
281* 2 x 2 diagonal block
282*
283* Multiply by inv(U**T(K+1)), where U(K+1) is the transformation
284* stored in columns K and K+1 of A.
285*
286 CALL sgemv( 'Transpose', k-1, nrhs, -one, b, ldb,
287 $ ap( kc ),
288 $ 1, one, b( k, 1 ), ldb )
289 CALL sgemv( 'Transpose', k-1, nrhs, -one, b, ldb,
290 $ ap( kc+k ), 1, one, b( k+1, 1 ), ldb )
291*
292* Interchange rows K and -IPIV(K).
293*
294 kp = -ipiv( k )
295 IF( kp.NE.k )
296 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
297 kc = kc + 2*k + 1
298 k = k + 2
299 END IF
300*
301 GO TO 40
302 50 CONTINUE
303*
304 ELSE
305*
306* Solve A*X = B, where A = L*D*L**T.
307*
308* First solve L*D*X = B, overwriting B with X.
309*
310* K is the main loop index, increasing from 1 to N in steps of
311* 1 or 2, depending on the size of the diagonal blocks.
312*
313 k = 1
314 kc = 1
315 60 CONTINUE
316*
317* If K > N, exit from loop.
318*
319 IF( k.GT.n )
320 $ GO TO 80
321*
322 IF( ipiv( k ).GT.0 ) THEN
323*
324* 1 x 1 diagonal block
325*
326* Interchange rows K and IPIV(K).
327*
328 kp = ipiv( k )
329 IF( kp.NE.k )
330 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
331*
332* Multiply by inv(L(K)), where L(K) is the transformation
333* stored in column K of A.
334*
335 IF( k.LT.n )
336 $ CALL sger( n-k, nrhs, -one, ap( kc+1 ), 1, b( k, 1 ),
337 $ ldb, b( k+1, 1 ), ldb )
338*
339* Multiply by the inverse of the diagonal block.
340*
341 CALL sscal( nrhs, one / ap( kc ), b( k, 1 ), ldb )
342 kc = kc + n - k + 1
343 k = k + 1
344 ELSE
345*
346* 2 x 2 diagonal block
347*
348* Interchange rows K+1 and -IPIV(K).
349*
350 kp = -ipiv( k )
351 IF( kp.NE.k+1 )
352 $ CALL sswap( nrhs, b( k+1, 1 ), ldb, b( kp, 1 ), ldb )
353*
354* Multiply by inv(L(K)), where L(K) is the transformation
355* stored in columns K and K+1 of A.
356*
357 IF( k.LT.n-1 ) THEN
358 CALL sger( n-k-1, nrhs, -one, ap( kc+2 ), 1, b( k,
359 $ 1 ),
360 $ ldb, b( k+2, 1 ), ldb )
361 CALL sger( n-k-1, nrhs, -one, ap( kc+n-k+2 ), 1,
362 $ b( k+1, 1 ), ldb, b( k+2, 1 ), ldb )
363 END IF
364*
365* Multiply by the inverse of the diagonal block.
366*
367 akm1k = ap( kc+1 )
368 akm1 = ap( kc ) / akm1k
369 ak = ap( kc+n-k+1 ) / akm1k
370 denom = akm1*ak - one
371 DO 70 j = 1, nrhs
372 bkm1 = b( k, j ) / akm1k
373 bk = b( k+1, j ) / akm1k
374 b( k, j ) = ( ak*bkm1-bk ) / denom
375 b( k+1, j ) = ( akm1*bk-bkm1 ) / denom
376 70 CONTINUE
377 kc = kc + 2*( n-k ) + 1
378 k = k + 2
379 END IF
380*
381 GO TO 60
382 80 CONTINUE
383*
384* Next solve L**T*X = B, overwriting B with X.
385*
386* K is the main loop index, decreasing from N to 1 in steps of
387* 1 or 2, depending on the size of the diagonal blocks.
388*
389 k = n
390 kc = n*( n+1 ) / 2 + 1
391 90 CONTINUE
392*
393* If K < 1, exit from loop.
394*
395 IF( k.LT.1 )
396 $ GO TO 100
397*
398 kc = kc - ( n-k+1 )
399 IF( ipiv( k ).GT.0 ) THEN
400*
401* 1 x 1 diagonal block
402*
403* Multiply by inv(L**T(K)), where L(K) is the transformation
404* stored in column K of A.
405*
406 IF( k.LT.n )
407 $ CALL sgemv( 'Transpose', n-k, nrhs, -one, b( k+1, 1 ),
408 $ ldb, ap( kc+1 ), 1, one, b( k, 1 ), ldb )
409*
410* Interchange rows K and IPIV(K).
411*
412 kp = ipiv( k )
413 IF( kp.NE.k )
414 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
415 k = k - 1
416 ELSE
417*
418* 2 x 2 diagonal block
419*
420* Multiply by inv(L**T(K-1)), where L(K-1) is the transformation
421* stored in columns K-1 and K of A.
422*
423 IF( k.LT.n ) THEN
424 CALL sgemv( 'Transpose', n-k, nrhs, -one, b( k+1, 1 ),
425 $ ldb, ap( kc+1 ), 1, one, b( k, 1 ), ldb )
426 CALL sgemv( 'Transpose', n-k, nrhs, -one, b( k+1, 1 ),
427 $ ldb, ap( kc-( n-k ) ), 1, one, b( k-1, 1 ),
428 $ ldb )
429 END IF
430*
431* Interchange rows K and -IPIV(K).
432*
433 kp = -ipiv( k )
434 IF( kp.NE.k )
435 $ CALL sswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
436 kc = kc - ( n-k+2 )
437 k = k - 2
438 END IF
439*
440 GO TO 90
441 100 CONTINUE
442 END IF
443*
444 RETURN
445*
446* End of SSPTRS
447*
448 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
Definition sgemv.f:158
subroutine sger(m, n, alpha, x, incx, y, incy, a, lda)
SGER
Definition sger.f:130
subroutine ssptrs(uplo, n, nrhs, ap, ipiv, b, ldb, info)
SSPTRS
Definition ssptrs.f:113
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
subroutine sswap(n, sx, incx, sy, incy)
SSWAP
Definition sswap.f:82