LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
dsptrf.f
Go to the documentation of this file.
1*> \brief \b DSPTRF
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download DSPTRF + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsptrf.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsptrf.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsptrf.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE DSPTRF( UPLO, N, AP, IPIV, INFO )
20*
21* .. Scalar Arguments ..
22* CHARACTER UPLO
23* INTEGER INFO, N
24* ..
25* .. Array Arguments ..
26* INTEGER IPIV( * )
27* DOUBLE PRECISION AP( * )
28* ..
29*
30*
31*> \par Purpose:
32* =============
33*>
34*> \verbatim
35*>
36*> DSPTRF computes the factorization of a real symmetric matrix A stored
37*> in packed format using the Bunch-Kaufman diagonal pivoting method:
38*>
39*> A = U*D*U**T or A = L*D*L**T
40*>
41*> where U (or L) is a product of permutation and unit upper (lower)
42*> triangular matrices, and D is symmetric and block diagonal with
43*> 1-by-1 and 2-by-2 diagonal blocks.
44*> \endverbatim
45*
46* Arguments:
47* ==========
48*
49*> \param[in] UPLO
50*> \verbatim
51*> UPLO is CHARACTER*1
52*> = 'U': Upper triangle of A is stored;
53*> = 'L': Lower triangle of A is stored.
54*> \endverbatim
55*>
56*> \param[in] N
57*> \verbatim
58*> N is INTEGER
59*> The order of the matrix A. N >= 0.
60*> \endverbatim
61*>
62*> \param[in,out] AP
63*> \verbatim
64*> AP is DOUBLE PRECISION array, dimension (N*(N+1)/2)
65*> On entry, the upper or lower triangle of the symmetric matrix
66*> A, packed columnwise in a linear array. The j-th column of A
67*> is stored in the array AP as follows:
68*> if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
69*> if UPLO = 'L', AP(i + (j-1)*(2n-j)/2) = A(i,j) for j<=i<=n.
70*>
71*> On exit, the block diagonal matrix D and the multipliers used
72*> to obtain the factor U or L, stored as a packed triangular
73*> matrix overwriting A (see below for further details).
74*> \endverbatim
75*>
76*> \param[out] IPIV
77*> \verbatim
78*> IPIV is INTEGER array, dimension (N)
79*> Details of the interchanges and the block structure of D.
80*> If IPIV(k) > 0, then rows and columns k and IPIV(k) were
81*> interchanged and D(k,k) is a 1-by-1 diagonal block.
82*> If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and
83*> columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k)
84*> is a 2-by-2 diagonal block. If UPLO = 'L' and IPIV(k) =
85*> IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were
86*> interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
87*> \endverbatim
88*>
89*> \param[out] INFO
90*> \verbatim
91*> INFO is INTEGER
92*> = 0: successful exit
93*> < 0: if INFO = -i, the i-th argument had an illegal value
94*> > 0: if INFO = i, D(i,i) is exactly zero. The factorization
95*> has been completed, but the block diagonal matrix D is
96*> exactly singular, and division by zero will occur if it
97*> is used to solve a system of equations.
98*> \endverbatim
99*
100* Authors:
101* ========
102*
103*> \author Univ. of Tennessee
104*> \author Univ. of California Berkeley
105*> \author Univ. of Colorado Denver
106*> \author NAG Ltd.
107*
108*> \ingroup hptrf
109*
110*> \par Further Details:
111* =====================
112*>
113*> \verbatim
114*>
115*> If UPLO = 'U', then A = U*D*U**T, where
116*> U = P(n)*U(n)* ... *P(k)U(k)* ...,
117*> i.e., U is a product of terms P(k)*U(k), where k decreases from n to
118*> 1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
119*> and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as
120*> defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
121*> that if the diagonal block D(k) is of order s (s = 1 or 2), then
122*>
123*> ( I v 0 ) k-s
124*> U(k) = ( 0 I 0 ) s
125*> ( 0 0 I ) n-k
126*> k-s s n-k
127*>
128*> If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k).
129*> If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
130*> and A(k,k), and v overwrites A(1:k-2,k-1:k).
131*>
132*> If UPLO = 'L', then A = L*D*L**T, where
133*> L = P(1)*L(1)* ... *P(k)*L(k)* ...,
134*> i.e., L is a product of terms P(k)*L(k), where k increases from 1 to
135*> n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
136*> and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as
137*> defined by IPIV(k), and L(k) is a unit lower triangular matrix, such
138*> that if the diagonal block D(k) is of order s (s = 1 or 2), then
139*>
140*> ( I 0 0 ) k-1
141*> L(k) = ( 0 I 0 ) s
142*> ( 0 v I ) n-k-s+1
143*> k-1 s n-k-s+1
144*>
145*> If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k).
146*> If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k),
147*> and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1).
148*> \endverbatim
149*
150*> \par Contributors:
151* ==================
152*>
153*> J. Lewis, Boeing Computer Services Company
154*>
155* =====================================================================
156 SUBROUTINE dsptrf( UPLO, N, AP, IPIV, INFO )
157*
158* -- LAPACK computational routine --
159* -- LAPACK is a software package provided by Univ. of Tennessee, --
160* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
161*
162* .. Scalar Arguments ..
163 CHARACTER UPLO
164 INTEGER INFO, N
165* ..
166* .. Array Arguments ..
167 INTEGER IPIV( * )
168 DOUBLE PRECISION AP( * )
169* ..
170*
171* =====================================================================
172*
173* .. Parameters ..
174 DOUBLE PRECISION ZERO, ONE
175 parameter( zero = 0.0d+0, one = 1.0d+0 )
176 DOUBLE PRECISION EIGHT, SEVTEN
177 parameter( eight = 8.0d+0, sevten = 17.0d+0 )
178* ..
179* .. Local Scalars ..
180 LOGICAL UPPER
181 INTEGER I, IMAX, J, JMAX, K, KC, KK, KNC, KP, KPC,
182 $ KSTEP, KX, NPP
183 DOUBLE PRECISION ABSAKK, ALPHA, COLMAX, D11, D12, D21, D22, R1,
184 $ ROWMAX, T, WK, WKM1, WKP1
185* ..
186* .. External Functions ..
187 LOGICAL LSAME
188 INTEGER IDAMAX
189 EXTERNAL lsame, idamax
190* ..
191* .. External Subroutines ..
192 EXTERNAL dscal, dspr, dswap, xerbla
193* ..
194* .. Intrinsic Functions ..
195 INTRINSIC abs, max, sqrt
196* ..
197* .. Executable Statements ..
198*
199* Test the input parameters.
200*
201 info = 0
202 upper = lsame( uplo, 'U' )
203 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
204 info = -1
205 ELSE IF( n.LT.0 ) THEN
206 info = -2
207 END IF
208 IF( info.NE.0 ) THEN
209 CALL xerbla( 'DSPTRF', -info )
210 RETURN
211 END IF
212*
213* Initialize ALPHA for use in choosing pivot block size.
214*
215 alpha = ( one+sqrt( sevten ) ) / eight
216*
217 IF( upper ) THEN
218*
219* Factorize A as U*D*U**T using the upper triangle of A
220*
221* K is the main loop index, decreasing from N to 1 in steps of
222* 1 or 2
223*
224 k = n
225 kc = ( n-1 )*n / 2 + 1
226 10 CONTINUE
227 knc = kc
228*
229* If K < 1, exit from loop
230*
231 IF( k.LT.1 )
232 $ GO TO 110
233 kstep = 1
234*
235* Determine rows and columns to be interchanged and whether
236* a 1-by-1 or 2-by-2 pivot block will be used
237*
238 absakk = abs( ap( kc+k-1 ) )
239*
240* IMAX is the row-index of the largest off-diagonal element in
241* column K, and COLMAX is its absolute value
242*
243 IF( k.GT.1 ) THEN
244 imax = idamax( k-1, ap( kc ), 1 )
245 colmax = abs( ap( kc+imax-1 ) )
246 ELSE
247 colmax = zero
248 END IF
249*
250 IF( max( absakk, colmax ).EQ.zero ) THEN
251*
252* Column K is zero: set INFO and continue
253*
254 IF( info.EQ.0 )
255 $ info = k
256 kp = k
257 ELSE
258 IF( absakk.GE.alpha*colmax ) THEN
259*
260* no interchange, use 1-by-1 pivot block
261*
262 kp = k
263 ELSE
264*
265 rowmax = zero
266 jmax = imax
267 kx = imax*( imax+1 ) / 2 + imax
268 DO 20 j = imax + 1, k
269 IF( abs( ap( kx ) ).GT.rowmax ) THEN
270 rowmax = abs( ap( kx ) )
271 jmax = j
272 END IF
273 kx = kx + j
274 20 CONTINUE
275 kpc = ( imax-1 )*imax / 2 + 1
276 IF( imax.GT.1 ) THEN
277 jmax = idamax( imax-1, ap( kpc ), 1 )
278 rowmax = max( rowmax, abs( ap( kpc+jmax-1 ) ) )
279 END IF
280*
281 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
282*
283* no interchange, use 1-by-1 pivot block
284*
285 kp = k
286 ELSE IF( abs( ap( kpc+imax-1 ) ).GE.alpha*rowmax ) THEN
287*
288* interchange rows and columns K and IMAX, use 1-by-1
289* pivot block
290*
291 kp = imax
292 ELSE
293*
294* interchange rows and columns K-1 and IMAX, use 2-by-2
295* pivot block
296*
297 kp = imax
298 kstep = 2
299 END IF
300 END IF
301*
302 kk = k - kstep + 1
303 IF( kstep.EQ.2 )
304 $ knc = knc - k + 1
305 IF( kp.NE.kk ) THEN
306*
307* Interchange rows and columns KK and KP in the leading
308* submatrix A(1:k,1:k)
309*
310 CALL dswap( kp-1, ap( knc ), 1, ap( kpc ), 1 )
311 kx = kpc + kp - 1
312 DO 30 j = kp + 1, kk - 1
313 kx = kx + j - 1
314 t = ap( knc+j-1 )
315 ap( knc+j-1 ) = ap( kx )
316 ap( kx ) = t
317 30 CONTINUE
318 t = ap( knc+kk-1 )
319 ap( knc+kk-1 ) = ap( kpc+kp-1 )
320 ap( kpc+kp-1 ) = t
321 IF( kstep.EQ.2 ) THEN
322 t = ap( kc+k-2 )
323 ap( kc+k-2 ) = ap( kc+kp-1 )
324 ap( kc+kp-1 ) = t
325 END IF
326 END IF
327*
328* Update the leading submatrix
329*
330 IF( kstep.EQ.1 ) THEN
331*
332* 1-by-1 pivot block D(k): column k now holds
333*
334* W(k) = U(k)*D(k)
335*
336* where U(k) is the k-th column of U
337*
338* Perform a rank-1 update of A(1:k-1,1:k-1) as
339*
340* A := A - U(k)*D(k)*U(k)**T = A - W(k)*1/D(k)*W(k)**T
341*
342 r1 = one / ap( kc+k-1 )
343 CALL dspr( uplo, k-1, -r1, ap( kc ), 1, ap )
344*
345* Store U(k) in column k
346*
347 CALL dscal( k-1, r1, ap( kc ), 1 )
348 ELSE
349*
350* 2-by-2 pivot block D(k): columns k and k-1 now hold
351*
352* ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
353*
354* where U(k) and U(k-1) are the k-th and (k-1)-th columns
355* of U
356*
357* Perform a rank-2 update of A(1:k-2,1:k-2) as
358*
359* A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**T
360* = A - ( W(k-1) W(k) )*inv(D(k))*( W(k-1) W(k) )**T
361*
362 IF( k.GT.2 ) THEN
363*
364 d12 = ap( k-1+( k-1 )*k / 2 )
365 d22 = ap( k-1+( k-2 )*( k-1 ) / 2 ) / d12
366 d11 = ap( k+( k-1 )*k / 2 ) / d12
367 t = one / ( d11*d22-one )
368 d12 = t / d12
369*
370 DO 50 j = k - 2, 1, -1
371 wkm1 = d12*( d11*ap( j+( k-2 )*( k-1 ) / 2 )-
372 $ ap( j+( k-1 )*k / 2 ) )
373 wk = d12*( d22*ap( j+( k-1 )*k / 2 )-
374 $ ap( j+( k-2 )*( k-1 ) / 2 ) )
375 DO 40 i = j, 1, -1
376 ap( i+( j-1 )*j / 2 ) = ap( i+( j-1 )*j / 2 ) -
377 $ ap( i+( k-1 )*k / 2 )*wk -
378 $ ap( i+( k-2 )*( k-1 ) / 2 )*wkm1
379 40 CONTINUE
380 ap( j+( k-1 )*k / 2 ) = wk
381 ap( j+( k-2 )*( k-1 ) / 2 ) = wkm1
382 50 CONTINUE
383*
384 END IF
385*
386 END IF
387 END IF
388*
389* Store details of the interchanges in IPIV
390*
391 IF( kstep.EQ.1 ) THEN
392 ipiv( k ) = kp
393 ELSE
394 ipiv( k ) = -kp
395 ipiv( k-1 ) = -kp
396 END IF
397*
398* Decrease K and return to the start of the main loop
399*
400 k = k - kstep
401 kc = knc - k
402 GO TO 10
403*
404 ELSE
405*
406* Factorize A as L*D*L**T using the lower triangle of A
407*
408* K is the main loop index, increasing from 1 to N in steps of
409* 1 or 2
410*
411 k = 1
412 kc = 1
413 npp = n*( n+1 ) / 2
414 60 CONTINUE
415 knc = kc
416*
417* If K > N, exit from loop
418*
419 IF( k.GT.n )
420 $ GO TO 110
421 kstep = 1
422*
423* Determine rows and columns to be interchanged and whether
424* a 1-by-1 or 2-by-2 pivot block will be used
425*
426 absakk = abs( ap( kc ) )
427*
428* IMAX is the row-index of the largest off-diagonal element in
429* column K, and COLMAX is its absolute value
430*
431 IF( k.LT.n ) THEN
432 imax = k + idamax( n-k, ap( kc+1 ), 1 )
433 colmax = abs( ap( kc+imax-k ) )
434 ELSE
435 colmax = zero
436 END IF
437*
438 IF( max( absakk, colmax ).EQ.zero ) THEN
439*
440* Column K is zero: set INFO and continue
441*
442 IF( info.EQ.0 )
443 $ info = k
444 kp = k
445 ELSE
446 IF( absakk.GE.alpha*colmax ) THEN
447*
448* no interchange, use 1-by-1 pivot block
449*
450 kp = k
451 ELSE
452*
453* JMAX is the column-index of the largest off-diagonal
454* element in row IMAX, and ROWMAX is its absolute value
455*
456 rowmax = zero
457 kx = kc + imax - k
458 DO 70 j = k, imax - 1
459 IF( abs( ap( kx ) ).GT.rowmax ) THEN
460 rowmax = abs( ap( kx ) )
461 jmax = j
462 END IF
463 kx = kx + n - j
464 70 CONTINUE
465 kpc = npp - ( n-imax+1 )*( n-imax+2 ) / 2 + 1
466 IF( imax.LT.n ) THEN
467 jmax = imax + idamax( n-imax, ap( kpc+1 ), 1 )
468 rowmax = max( rowmax, abs( ap( kpc+jmax-imax ) ) )
469 END IF
470*
471 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
472*
473* no interchange, use 1-by-1 pivot block
474*
475 kp = k
476 ELSE IF( abs( ap( kpc ) ).GE.alpha*rowmax ) THEN
477*
478* interchange rows and columns K and IMAX, use 1-by-1
479* pivot block
480*
481 kp = imax
482 ELSE
483*
484* interchange rows and columns K+1 and IMAX, use 2-by-2
485* pivot block
486*
487 kp = imax
488 kstep = 2
489 END IF
490 END IF
491*
492 kk = k + kstep - 1
493 IF( kstep.EQ.2 )
494 $ knc = knc + n - k + 1
495 IF( kp.NE.kk ) THEN
496*
497* Interchange rows and columns KK and KP in the trailing
498* submatrix A(k:n,k:n)
499*
500 IF( kp.LT.n )
501 $ CALL dswap( n-kp, ap( knc+kp-kk+1 ), 1,
502 $ ap( kpc+1 ),
503 $ 1 )
504 kx = knc + kp - kk
505 DO 80 j = kk + 1, kp - 1
506 kx = kx + n - j + 1
507 t = ap( knc+j-kk )
508 ap( knc+j-kk ) = ap( kx )
509 ap( kx ) = t
510 80 CONTINUE
511 t = ap( knc )
512 ap( knc ) = ap( kpc )
513 ap( kpc ) = t
514 IF( kstep.EQ.2 ) THEN
515 t = ap( kc+1 )
516 ap( kc+1 ) = ap( kc+kp-k )
517 ap( kc+kp-k ) = t
518 END IF
519 END IF
520*
521* Update the trailing submatrix
522*
523 IF( kstep.EQ.1 ) THEN
524*
525* 1-by-1 pivot block D(k): column k now holds
526*
527* W(k) = L(k)*D(k)
528*
529* where L(k) is the k-th column of L
530*
531 IF( k.LT.n ) THEN
532*
533* Perform a rank-1 update of A(k+1:n,k+1:n) as
534*
535* A := A - L(k)*D(k)*L(k)**T = A - W(k)*(1/D(k))*W(k)**T
536*
537 r1 = one / ap( kc )
538 CALL dspr( uplo, n-k, -r1, ap( kc+1 ), 1,
539 $ ap( kc+n-k+1 ) )
540*
541* Store L(k) in column K
542*
543 CALL dscal( n-k, r1, ap( kc+1 ), 1 )
544 END IF
545 ELSE
546*
547* 2-by-2 pivot block D(k): columns K and K+1 now hold
548*
549* ( W(k) W(k+1) ) = ( L(k) L(k+1) )*D(k)
550*
551* where L(k) and L(k+1) are the k-th and (k+1)-th columns
552* of L
553*
554 IF( k.LT.n-1 ) THEN
555*
556* Perform a rank-2 update of A(k+2:n,k+2:n) as
557*
558* A := A - ( L(k) L(k+1) )*D(k)*( L(k) L(k+1) )**T
559* = A - ( W(k) W(k+1) )*inv(D(k))*( W(k) W(k+1) )**T
560*
561* where L(k) and L(k+1) are the k-th and (k+1)-th
562* columns of L
563*
564 d21 = ap( k+1+( k-1 )*( 2*n-k ) / 2 )
565 d11 = ap( k+1+k*( 2*n-k-1 ) / 2 ) / d21
566 d22 = ap( k+( k-1 )*( 2*n-k ) / 2 ) / d21
567 t = one / ( d11*d22-one )
568 d21 = t / d21
569*
570 DO 100 j = k + 2, n
571 wk = d21*( d11*ap( j+( k-1 )*( 2*n-k ) / 2 )-
572 $ ap( j+k*( 2*n-k-1 ) / 2 ) )
573 wkp1 = d21*( d22*ap( j+k*( 2*n-k-1 ) / 2 )-
574 $ ap( j+( k-1 )*( 2*n-k ) / 2 ) )
575*
576 DO 90 i = j, n
577 ap( i+( j-1 )*( 2*n-j ) / 2 ) = ap( i+( j-1 )*
578 $ ( 2*n-j ) / 2 ) - ap( i+( k-1 )*( 2*n-k ) /
579 $ 2 )*wk - ap( i+k*( 2*n-k-1 ) / 2 )*wkp1
580 90 CONTINUE
581*
582 ap( j+( k-1 )*( 2*n-k ) / 2 ) = wk
583 ap( j+k*( 2*n-k-1 ) / 2 ) = wkp1
584*
585 100 CONTINUE
586 END IF
587 END IF
588 END IF
589*
590* Store details of the interchanges in IPIV
591*
592 IF( kstep.EQ.1 ) THEN
593 ipiv( k ) = kp
594 ELSE
595 ipiv( k ) = -kp
596 ipiv( k+1 ) = -kp
597 END IF
598*
599* Increase K and return to the start of the main loop
600*
601 k = k + kstep
602 kc = knc + n - k + 2
603 GO TO 60
604*
605 END IF
606*
607 110 CONTINUE
608 RETURN
609*
610* End of DSPTRF
611*
612 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dspr(uplo, n, alpha, x, incx, ap)
DSPR
Definition dspr.f:127
subroutine dsptrf(uplo, n, ap, ipiv, info)
DSPTRF
Definition dsptrf.f:157
subroutine dscal(n, da, dx, incx)
DSCAL
Definition dscal.f:79
subroutine dswap(n, dx, incx, dy, incy)
DSWAP
Definition dswap.f:82