LAPACK 3.12.0
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zlavsp.f
Go to the documentation of this file.
1*> \brief \b ZLAVSP
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8* Definition:
9* ===========
10*
11* SUBROUTINE ZLAVSP( UPLO, TRANS, DIAG, N, NRHS, A, IPIV, B, LDB,
12* INFO )
13*
14* .. Scalar Arguments ..
15* CHARACTER DIAG, TRANS, UPLO
16* INTEGER INFO, LDB, N, NRHS
17* ..
18* .. Array Arguments ..
19* INTEGER IPIV( * )
20* COMPLEX*16 A( * ), B( LDB, * )
21* ..
22*
23*
24*> \par Purpose:
25* =============
26*>
27*> \verbatim
28*>
29*> ZLAVSP performs one of the matrix-vector operations
30*> x := A*x or x := A^T*x,
31*> where x is an N element vector and A is one of the factors
32*> from the symmetric factorization computed by ZSPTRF.
33*> ZSPTRF produces a factorization of the form
34*> U * D * U^T or L * D * L^T,
35*> where U (or L) is a product of permutation and unit upper (lower)
36*> triangular matrices, U^T (or L^T) is the transpose of
37*> U (or L), and D is symmetric and block diagonal with 1 x 1 and
38*> 2 x 2 diagonal blocks. The multipliers for the transformations
39*> and the upper or lower triangular parts of the diagonal blocks
40*> are stored columnwise in packed format in the linear array A.
41*>
42*> If TRANS = 'N' or 'n', ZLAVSP multiplies either by U or U * D
43*> (or L or L * D).
44*> If TRANS = 'C' or 'c', ZLAVSP multiplies either by U^T or D * U^T
45*> (or L^T or D * L^T ).
46*> \endverbatim
47*
48* Arguments:
49* ==========
50*
51*> \verbatim
52*> UPLO - CHARACTER*1
53*> On entry, UPLO specifies whether the triangular matrix
54*> stored in A is upper or lower triangular.
55*> UPLO = 'U' or 'u' The matrix is upper triangular.
56*> UPLO = 'L' or 'l' The matrix is lower triangular.
57*> Unchanged on exit.
58*>
59*> TRANS - CHARACTER*1
60*> On entry, TRANS specifies the operation to be performed as
61*> follows:
62*> TRANS = 'N' or 'n' x := A*x.
63*> TRANS = 'T' or 't' x := A^T*x.
64*> Unchanged on exit.
65*>
66*> DIAG - CHARACTER*1
67*> On entry, DIAG specifies whether the diagonal blocks are
68*> assumed to be unit matrices, as follows:
69*> DIAG = 'U' or 'u' Diagonal blocks are unit matrices.
70*> DIAG = 'N' or 'n' Diagonal blocks are non-unit.
71*> Unchanged on exit.
72*>
73*> N - INTEGER
74*> On entry, N specifies the order of the matrix A.
75*> N must be at least zero.
76*> Unchanged on exit.
77*>
78*> NRHS - INTEGER
79*> On entry, NRHS specifies the number of right hand sides,
80*> i.e., the number of vectors x to be multiplied by A.
81*> NRHS must be at least zero.
82*> Unchanged on exit.
83*>
84*> A - COMPLEX*16 array, dimension( N*(N+1)/2 )
85*> On entry, A contains a block diagonal matrix and the
86*> multipliers of the transformations used to obtain it,
87*> stored as a packed triangular matrix.
88*> Unchanged on exit.
89*>
90*> IPIV - INTEGER array, dimension( N )
91*> On entry, IPIV contains the vector of pivot indices as
92*> determined by ZSPTRF.
93*> If IPIV( K ) = K, no interchange was done.
94*> If IPIV( K ) <> K but IPIV( K ) > 0, then row K was inter-
95*> changed with row IPIV( K ) and a 1 x 1 pivot block was used.
96*> If IPIV( K ) < 0 and UPLO = 'U', then row K-1 was exchanged
97*> with row | IPIV( K ) | and a 2 x 2 pivot block was used.
98*> If IPIV( K ) < 0 and UPLO = 'L', then row K+1 was exchanged
99*> with row | IPIV( K ) | and a 2 x 2 pivot block was used.
100*>
101*> B - COMPLEX*16 array, dimension( LDB, NRHS )
102*> On entry, B contains NRHS vectors of length N.
103*> On exit, B is overwritten with the product A * B.
104*>
105*> LDB - INTEGER
106*> On entry, LDB contains the leading dimension of B as
107*> declared in the calling program. LDB must be at least
108*> max( 1, N ).
109*> Unchanged on exit.
110*>
111*> INFO - INTEGER
112*> INFO is the error flag.
113*> On exit, a value of 0 indicates a successful exit.
114*> A negative value, say -K, indicates that the K-th argument
115*> has an illegal value.
116*> \endverbatim
117*
118* Authors:
119* ========
120*
121*> \author Univ. of Tennessee
122*> \author Univ. of California Berkeley
123*> \author Univ. of Colorado Denver
124*> \author NAG Ltd.
125*
126*> \ingroup complex16_lin
127*
128* =====================================================================
129 SUBROUTINE zlavsp( UPLO, TRANS, DIAG, N, NRHS, A, IPIV, B, LDB,
130 $ INFO )
131*
132* -- LAPACK test routine --
133* -- LAPACK is a software package provided by Univ. of Tennessee, --
134* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
135*
136* .. Scalar Arguments ..
137 CHARACTER DIAG, TRANS, UPLO
138 INTEGER INFO, LDB, N, NRHS
139* ..
140* .. Array Arguments ..
141 INTEGER IPIV( * )
142 COMPLEX*16 A( * ), B( LDB, * )
143* ..
144*
145* =====================================================================
146*
147* .. Parameters ..
148 COMPLEX*16 ONE
149 parameter( one = ( 1.0d+0, 0.0d+0 ) )
150* ..
151* .. Local Scalars ..
152 LOGICAL NOUNIT
153 INTEGER J, K, KC, KCNEXT, KP
154 COMPLEX*16 D11, D12, D21, D22, T1, T2
155* ..
156* .. External Functions ..
157 LOGICAL LSAME
158 EXTERNAL lsame
159* ..
160* .. External Subroutines ..
161 EXTERNAL xerbla, zgemv, zgeru, zscal, zswap
162* ..
163* .. Intrinsic Functions ..
164 INTRINSIC abs, max
165* ..
166* .. Executable Statements ..
167*
168* Test the input parameters.
169*
170 info = 0
171 IF( .NOT.lsame( uplo, 'U' ) .AND. .NOT.lsame( uplo, 'L' ) ) THEN
172 info = -1
173 ELSE IF( .NOT.lsame( trans, 'N' ) .AND. .NOT.lsame( trans, 'T' ) )
174 $ THEN
175 info = -2
176 ELSE IF( .NOT.lsame( diag, 'U' ) .AND. .NOT.lsame( diag, 'N' ) )
177 $ THEN
178 info = -3
179 ELSE IF( n.LT.0 ) THEN
180 info = -4
181 ELSE IF( ldb.LT.max( 1, n ) ) THEN
182 info = -8
183 END IF
184 IF( info.NE.0 ) THEN
185 CALL xerbla( 'ZLAVSP ', -info )
186 RETURN
187 END IF
188*
189* Quick return if possible.
190*
191 IF( n.EQ.0 )
192 $ RETURN
193*
194 nounit = lsame( diag, 'N' )
195*------------------------------------------
196*
197* Compute B := A * B (No transpose)
198*
199*------------------------------------------
200 IF( lsame( trans, 'N' ) ) THEN
201*
202* Compute B := U*B
203* where U = P(m)*inv(U(m))* ... *P(1)*inv(U(1))
204*
205 IF( lsame( uplo, 'U' ) ) THEN
206*
207* Loop forward applying the transformations.
208*
209 k = 1
210 kc = 1
211 10 CONTINUE
212 IF( k.GT.n )
213 $ GO TO 30
214*
215* 1 x 1 pivot block
216*
217 IF( ipiv( k ).GT.0 ) THEN
218*
219* Multiply by the diagonal element if forming U * D.
220*
221 IF( nounit )
222 $ CALL zscal( nrhs, a( kc+k-1 ), b( k, 1 ), ldb )
223*
224* Multiply by P(K) * inv(U(K)) if K > 1.
225*
226 IF( k.GT.1 ) THEN
227*
228* Apply the transformation.
229*
230 CALL zgeru( k-1, nrhs, one, a( kc ), 1, b( k, 1 ),
231 $ ldb, b( 1, 1 ), ldb )
232*
233* Interchange if P(K) != I.
234*
235 kp = ipiv( k )
236 IF( kp.NE.k )
237 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
238 END IF
239 kc = kc + k
240 k = k + 1
241 ELSE
242*
243* 2 x 2 pivot block
244*
245 kcnext = kc + k
246*
247* Multiply by the diagonal block if forming U * D.
248*
249 IF( nounit ) THEN
250 d11 = a( kcnext-1 )
251 d22 = a( kcnext+k )
252 d12 = a( kcnext+k-1 )
253 d21 = d12
254 DO 20 j = 1, nrhs
255 t1 = b( k, j )
256 t2 = b( k+1, j )
257 b( k, j ) = d11*t1 + d12*t2
258 b( k+1, j ) = d21*t1 + d22*t2
259 20 CONTINUE
260 END IF
261*
262* Multiply by P(K) * inv(U(K)) if K > 1.
263*
264 IF( k.GT.1 ) THEN
265*
266* Apply the transformations.
267*
268 CALL zgeru( k-1, nrhs, one, a( kc ), 1, b( k, 1 ),
269 $ ldb, b( 1, 1 ), ldb )
270 CALL zgeru( k-1, nrhs, one, a( kcnext ), 1,
271 $ b( k+1, 1 ), ldb, b( 1, 1 ), ldb )
272*
273* Interchange if P(K) != I.
274*
275 kp = abs( ipiv( k ) )
276 IF( kp.NE.k )
277 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
278 END IF
279 kc = kcnext + k + 1
280 k = k + 2
281 END IF
282 GO TO 10
283 30 CONTINUE
284*
285* Compute B := L*B
286* where L = P(1)*inv(L(1))* ... *P(m)*inv(L(m)) .
287*
288 ELSE
289*
290* Loop backward applying the transformations to B.
291*
292 k = n
293 kc = n*( n+1 ) / 2 + 1
294 40 CONTINUE
295 IF( k.LT.1 )
296 $ GO TO 60
297 kc = kc - ( n-k+1 )
298*
299* Test the pivot index. If greater than zero, a 1 x 1
300* pivot was used, otherwise a 2 x 2 pivot was used.
301*
302 IF( ipiv( k ).GT.0 ) THEN
303*
304* 1 x 1 pivot block:
305*
306* Multiply by the diagonal element if forming L * D.
307*
308 IF( nounit )
309 $ CALL zscal( nrhs, a( kc ), b( k, 1 ), ldb )
310*
311* Multiply by P(K) * inv(L(K)) if K < N.
312*
313 IF( k.NE.n ) THEN
314 kp = ipiv( k )
315*
316* Apply the transformation.
317*
318 CALL zgeru( n-k, nrhs, one, a( kc+1 ), 1, b( k, 1 ),
319 $ ldb, b( k+1, 1 ), ldb )
320*
321* Interchange if a permutation was applied at the
322* K-th step of the factorization.
323*
324 IF( kp.NE.k )
325 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
326 END IF
327 k = k - 1
328*
329 ELSE
330*
331* 2 x 2 pivot block:
332*
333 kcnext = kc - ( n-k+2 )
334*
335* Multiply by the diagonal block if forming L * D.
336*
337 IF( nounit ) THEN
338 d11 = a( kcnext )
339 d22 = a( kc )
340 d21 = a( kcnext+1 )
341 d12 = d21
342 DO 50 j = 1, nrhs
343 t1 = b( k-1, j )
344 t2 = b( k, j )
345 b( k-1, j ) = d11*t1 + d12*t2
346 b( k, j ) = d21*t1 + d22*t2
347 50 CONTINUE
348 END IF
349*
350* Multiply by P(K) * inv(L(K)) if K < N.
351*
352 IF( k.NE.n ) THEN
353*
354* Apply the transformation.
355*
356 CALL zgeru( n-k, nrhs, one, a( kc+1 ), 1, b( k, 1 ),
357 $ ldb, b( k+1, 1 ), ldb )
358 CALL zgeru( n-k, nrhs, one, a( kcnext+2 ), 1,
359 $ b( k-1, 1 ), ldb, b( k+1, 1 ), ldb )
360*
361* Interchange if a permutation was applied at the
362* K-th step of the factorization.
363*
364 kp = abs( ipiv( k ) )
365 IF( kp.NE.k )
366 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
367 END IF
368 kc = kcnext
369 k = k - 2
370 END IF
371 GO TO 40
372 60 CONTINUE
373 END IF
374*-------------------------------------------------
375*
376* Compute B := A^T * B (transpose)
377*
378*-------------------------------------------------
379 ELSE
380*
381* Form B := U^T*B
382* where U = P(m)*inv(U(m))* ... *P(1)*inv(U(1))
383* and U^T = inv(U^T(1))*P(1)* ... *inv(U^T(m))*P(m)
384*
385 IF( lsame( uplo, 'U' ) ) THEN
386*
387* Loop backward applying the transformations.
388*
389 k = n
390 kc = n*( n+1 ) / 2 + 1
391 70 CONTINUE
392 IF( k.LT.1 )
393 $ GO TO 90
394 kc = kc - k
395*
396* 1 x 1 pivot block.
397*
398 IF( ipiv( k ).GT.0 ) THEN
399 IF( k.GT.1 ) THEN
400*
401* Interchange if P(K) != I.
402*
403 kp = ipiv( k )
404 IF( kp.NE.k )
405 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
406*
407* Apply the transformation:
408* y := y - B' * conjg(x)
409* where x is a column of A and y is a row of B.
410*
411 CALL zgemv( 'Transpose', k-1, nrhs, one, b, ldb,
412 $ a( kc ), 1, one, b( k, 1 ), ldb )
413 END IF
414 IF( nounit )
415 $ CALL zscal( nrhs, a( kc+k-1 ), b( k, 1 ), ldb )
416 k = k - 1
417*
418* 2 x 2 pivot block.
419*
420 ELSE
421 kcnext = kc - ( k-1 )
422 IF( k.GT.2 ) THEN
423*
424* Interchange if P(K) != I.
425*
426 kp = abs( ipiv( k ) )
427 IF( kp.NE.k-1 )
428 $ CALL zswap( nrhs, b( k-1, 1 ), ldb, b( kp, 1 ),
429 $ ldb )
430*
431* Apply the transformations.
432*
433 CALL zgemv( 'Transpose', k-2, nrhs, one, b, ldb,
434 $ a( kc ), 1, one, b( k, 1 ), ldb )
435*
436 CALL zgemv( 'Transpose', k-2, nrhs, one, b, ldb,
437 $ a( kcnext ), 1, one, b( k-1, 1 ), ldb )
438 END IF
439*
440* Multiply by the diagonal block if non-unit.
441*
442 IF( nounit ) THEN
443 d11 = a( kc-1 )
444 d22 = a( kc+k-1 )
445 d12 = a( kc+k-2 )
446 d21 = d12
447 DO 80 j = 1, nrhs
448 t1 = b( k-1, j )
449 t2 = b( k, j )
450 b( k-1, j ) = d11*t1 + d12*t2
451 b( k, j ) = d21*t1 + d22*t2
452 80 CONTINUE
453 END IF
454 kc = kcnext
455 k = k - 2
456 END IF
457 GO TO 70
458 90 CONTINUE
459*
460* Form B := L^T*B
461* where L = P(1)*inv(L(1))* ... *P(m)*inv(L(m))
462* and L^T = inv(L(m))*P(m)* ... *inv(L(1))*P(1)
463*
464 ELSE
465*
466* Loop forward applying the L-transformations.
467*
468 k = 1
469 kc = 1
470 100 CONTINUE
471 IF( k.GT.n )
472 $ GO TO 120
473*
474* 1 x 1 pivot block
475*
476 IF( ipiv( k ).GT.0 ) THEN
477 IF( k.LT.n ) THEN
478*
479* Interchange if P(K) != I.
480*
481 kp = ipiv( k )
482 IF( kp.NE.k )
483 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
484*
485* Apply the transformation
486*
487 CALL zgemv( 'Transpose', n-k, nrhs, one, b( k+1, 1 ),
488 $ ldb, a( kc+1 ), 1, one, b( k, 1 ), ldb )
489 END IF
490 IF( nounit )
491 $ CALL zscal( nrhs, a( kc ), b( k, 1 ), ldb )
492 kc = kc + n - k + 1
493 k = k + 1
494*
495* 2 x 2 pivot block.
496*
497 ELSE
498 kcnext = kc + n - k + 1
499 IF( k.LT.n-1 ) THEN
500*
501* Interchange if P(K) != I.
502*
503 kp = abs( ipiv( k ) )
504 IF( kp.NE.k+1 )
505 $ CALL zswap( nrhs, b( k+1, 1 ), ldb, b( kp, 1 ),
506 $ ldb )
507*
508* Apply the transformation
509*
510 CALL zgemv( 'Transpose', n-k-1, nrhs, one,
511 $ b( k+2, 1 ), ldb, a( kcnext+1 ), 1, one,
512 $ b( k+1, 1 ), ldb )
513*
514 CALL zgemv( 'Transpose', n-k-1, nrhs, one,
515 $ b( k+2, 1 ), ldb, a( kc+2 ), 1, one,
516 $ b( k, 1 ), ldb )
517 END IF
518*
519* Multiply by the diagonal block if non-unit.
520*
521 IF( nounit ) THEN
522 d11 = a( kc )
523 d22 = a( kcnext )
524 d21 = a( kc+1 )
525 d12 = d21
526 DO 110 j = 1, nrhs
527 t1 = b( k, j )
528 t2 = b( k+1, j )
529 b( k, j ) = d11*t1 + d12*t2
530 b( k+1, j ) = d21*t1 + d22*t2
531 110 CONTINUE
532 END IF
533 kc = kcnext + ( n-k )
534 k = k + 2
535 END IF
536 GO TO 100
537 120 CONTINUE
538 END IF
539*
540 END IF
541 RETURN
542*
543* End of ZLAVSP
544*
545 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
Definition zgemv.f:160
subroutine zgeru(m, n, alpha, x, incx, y, incy, a, lda)
ZGERU
Definition zgeru.f:130
subroutine zscal(n, za, zx, incx)
ZSCAL
Definition zscal.f:78
subroutine zswap(n, zx, incx, zy, incy)
ZSWAP
Definition zswap.f:81
subroutine zlavsp(uplo, trans, diag, n, nrhs, a, ipiv, b, ldb, info)
ZLAVSP
Definition zlavsp.f:131