1: *> \brief \b DPSTRF computes the Cholesky factorization with complete pivoting of a real symmetric positive semidefinite matrix.
2: *
3: *
4: * =========== DOCUMENTATION ===========
5: *
6: * Online html documentation available at
7: * http://www.netlib.org/lapack/explore-html/
8: *
9: *> \htmlonly
10: *> Download DPSTRF + dependencies
11: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dpstrf.f">
12: *> [TGZ]</a>
13: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dpstrf.f">
14: *> [ZIP]</a>
15: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dpstrf.f">
16: *> [TXT]</a>
17: *> \endhtmlonly
18: *
19: * Definition:
20: * ===========
21: *
22: * SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO )
23: *
24: * .. Scalar Arguments ..
25: * DOUBLE PRECISION TOL
26: * INTEGER INFO, LDA, N, RANK
27: * CHARACTER UPLO
28: * ..
29: * .. Array Arguments ..
30: * DOUBLE PRECISION A( LDA, * ), WORK( 2*N )
31: * INTEGER PIV( N )
32: * ..
33: *
34: *
35: *> \par Purpose:
36: * =============
37: *>
38: *> \verbatim
39: *>
40: *> DPSTRF computes the Cholesky factorization with complete
41: *> pivoting of a real symmetric positive semidefinite matrix A.
42: *>
43: *> The factorization has the form
44: *> P**T * A * P = U**T * U , if UPLO = 'U',
45: *> P**T * A * P = L * L**T, if UPLO = 'L',
46: *> where U is an upper triangular matrix and L is lower triangular, and
47: *> P is stored as vector PIV.
48: *>
49: *> This algorithm does not attempt to check that A is positive
50: *> semidefinite. This version of the algorithm calls level 3 BLAS.
51: *> \endverbatim
52: *
53: * Arguments:
54: * ==========
55: *
56: *> \param[in] UPLO
57: *> \verbatim
58: *> UPLO is CHARACTER*1
59: *> Specifies whether the upper or lower triangular part of the
60: *> symmetric matrix A is stored.
61: *> = 'U': Upper triangular
62: *> = 'L': Lower triangular
63: *> \endverbatim
64: *>
65: *> \param[in] N
66: *> \verbatim
67: *> N is INTEGER
68: *> The order of the matrix A. N >= 0.
69: *> \endverbatim
70: *>
71: *> \param[in,out] A
72: *> \verbatim
73: *> A is DOUBLE PRECISION array, dimension (LDA,N)
74: *> On entry, the symmetric matrix A. If UPLO = 'U', the leading
75: *> n by n upper triangular part of A contains the upper
76: *> triangular part of the matrix A, and the strictly lower
77: *> triangular part of A is not referenced. If UPLO = 'L', the
78: *> leading n by n lower triangular part of A contains the lower
79: *> triangular part of the matrix A, and the strictly upper
80: *> triangular part of A is not referenced.
81: *>
82: *> On exit, if INFO = 0, the factor U or L from the Cholesky
83: *> factorization as above.
84: *> \endverbatim
85: *>
86: *> \param[in] LDA
87: *> \verbatim
88: *> LDA is INTEGER
89: *> The leading dimension of the array A. LDA >= max(1,N).
90: *> \endverbatim
91: *>
92: *> \param[out] PIV
93: *> \verbatim
94: *> PIV is INTEGER array, dimension (N)
95: *> PIV is such that the nonzero entries are P( PIV(K), K ) = 1.
96: *> \endverbatim
97: *>
98: *> \param[out] RANK
99: *> \verbatim
100: *> RANK is INTEGER
101: *> The rank of A given by the number of steps the algorithm
102: *> completed.
103: *> \endverbatim
104: *>
105: *> \param[in] TOL
106: *> \verbatim
107: *> TOL is DOUBLE PRECISION
108: *> User defined tolerance. If TOL < 0, then N*U*MAX( A(K,K) )
109: *> will be used. The algorithm terminates at the (K-1)st step
110: *> if the pivot <= TOL.
111: *> \endverbatim
112: *>
113: *> \param[out] WORK
114: *> \verbatim
115: *> WORK is DOUBLE PRECISION array, dimension (2*N)
116: *> Work space.
117: *> \endverbatim
118: *>
119: *> \param[out] INFO
120: *> \verbatim
121: *> INFO is INTEGER
122: *> < 0: If INFO = -K, the K-th argument had an illegal value,
123: *> = 0: algorithm completed successfully, and
124: *> > 0: the matrix A is either rank deficient with computed rank
125: *> as returned in RANK, or is not positive semidefinite. See
126: *> Section 7 of LAPACK Working Note #161 for further
127: *> information.
128: *> \endverbatim
129: *
130: * Authors:
131: * ========
132: *
133: *> \author Univ. of Tennessee
134: *> \author Univ. of California Berkeley
135: *> \author Univ. of Colorado Denver
136: *> \author NAG Ltd.
137: *
138: *> \ingroup doubleOTHERcomputational
139: *
140: * =====================================================================
141: SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO )
142: *
143: * -- LAPACK computational routine --
144: * -- LAPACK is a software package provided by Univ. of Tennessee, --
145: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
146: *
147: * .. Scalar Arguments ..
148: DOUBLE PRECISION TOL
149: INTEGER INFO, LDA, N, RANK
150: CHARACTER UPLO
151: * ..
152: * .. Array Arguments ..
153: DOUBLE PRECISION A( LDA, * ), WORK( 2*N )
154: INTEGER PIV( N )
155: * ..
156: *
157: * =====================================================================
158: *
159: * .. Parameters ..
160: DOUBLE PRECISION ONE, ZERO
161: PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
162: * ..
163: * .. Local Scalars ..
164: DOUBLE PRECISION AJJ, DSTOP, DTEMP
165: INTEGER I, ITEMP, J, JB, K, NB, PVT
166: LOGICAL UPPER
167: * ..
168: * .. External Functions ..
169: DOUBLE PRECISION DLAMCH
170: INTEGER ILAENV
171: LOGICAL LSAME, DISNAN
172: EXTERNAL DLAMCH, ILAENV, LSAME, DISNAN
173: * ..
174: * .. External Subroutines ..
175: EXTERNAL DGEMV, DPSTF2, DSCAL, DSWAP, DSYRK, XERBLA
176: * ..
177: * .. Intrinsic Functions ..
178: INTRINSIC MAX, MIN, SQRT, MAXLOC
179: * ..
180: * .. Executable Statements ..
181: *
182: * Test the input parameters.
183: *
184: INFO = 0
185: UPPER = LSAME( UPLO, 'U' )
186: IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
187: INFO = -1
188: ELSE IF( N.LT.0 ) THEN
189: INFO = -2
190: ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
191: INFO = -4
192: END IF
193: IF( INFO.NE.0 ) THEN
194: CALL XERBLA( 'DPSTRF', -INFO )
195: RETURN
196: END IF
197: *
198: * Quick return if possible
199: *
200: IF( N.EQ.0 )
201: $ RETURN
202: *
203: * Get block size
204: *
205: NB = ILAENV( 1, 'DPOTRF', UPLO, N, -1, -1, -1 )
206: IF( NB.LE.1 .OR. NB.GE.N ) THEN
207: *
208: * Use unblocked code
209: *
210: CALL DPSTF2( UPLO, N, A( 1, 1 ), LDA, PIV, RANK, TOL, WORK,
211: $ INFO )
212: GO TO 200
213: *
214: ELSE
215: *
216: * Initialize PIV
217: *
218: DO 100 I = 1, N
219: PIV( I ) = I
220: 100 CONTINUE
221: *
222: * Compute stopping value
223: *
224: PVT = 1
225: AJJ = A( PVT, PVT )
226: DO I = 2, N
227: IF( A( I, I ).GT.AJJ ) THEN
228: PVT = I
229: AJJ = A( PVT, PVT )
230: END IF
231: END DO
232: IF( AJJ.LE.ZERO.OR.DISNAN( AJJ ) ) THEN
233: RANK = 0
234: INFO = 1
235: GO TO 200
236: END IF
237: *
238: * Compute stopping value if not supplied
239: *
240: IF( TOL.LT.ZERO ) THEN
241: DSTOP = N * DLAMCH( 'Epsilon' ) * AJJ
242: ELSE
243: DSTOP = TOL
244: END IF
245: *
246: *
247: IF( UPPER ) THEN
248: *
249: * Compute the Cholesky factorization P**T * A * P = U**T * U
250: *
251: DO 140 K = 1, N, NB
252: *
253: * Account for last block not being NB wide
254: *
255: JB = MIN( NB, N-K+1 )
256: *
257: * Set relevant part of first half of WORK to zero,
258: * holds dot products
259: *
260: DO 110 I = K, N
261: WORK( I ) = 0
262: 110 CONTINUE
263: *
264: DO 130 J = K, K + JB - 1
265: *
266: * Find pivot, test for exit, else swap rows and columns
267: * Update dot products, compute possible pivots which are
268: * stored in the second half of WORK
269: *
270: DO 120 I = J, N
271: *
272: IF( J.GT.K ) THEN
273: WORK( I ) = WORK( I ) + A( J-1, I )**2
274: END IF
275: WORK( N+I ) = A( I, I ) - WORK( I )
276: *
277: 120 CONTINUE
278: *
279: IF( J.GT.1 ) THEN
280: ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
281: PVT = ITEMP + J - 1
282: AJJ = WORK( N+PVT )
283: IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
284: A( J, J ) = AJJ
285: GO TO 190
286: END IF
287: END IF
288: *
289: IF( J.NE.PVT ) THEN
290: *
291: * Pivot OK, so can now swap pivot rows and columns
292: *
293: A( PVT, PVT ) = A( J, J )
294: CALL DSWAP( J-1, A( 1, J ), 1, A( 1, PVT ), 1 )
295: IF( PVT.LT.N )
296: $ CALL DSWAP( N-PVT, A( J, PVT+1 ), LDA,
297: $ A( PVT, PVT+1 ), LDA )
298: CALL DSWAP( PVT-J-1, A( J, J+1 ), LDA,
299: $ A( J+1, PVT ), 1 )
300: *
301: * Swap dot products and PIV
302: *
303: DTEMP = WORK( J )
304: WORK( J ) = WORK( PVT )
305: WORK( PVT ) = DTEMP
306: ITEMP = PIV( PVT )
307: PIV( PVT ) = PIV( J )
308: PIV( J ) = ITEMP
309: END IF
310: *
311: AJJ = SQRT( AJJ )
312: A( J, J ) = AJJ
313: *
314: * Compute elements J+1:N of row J.
315: *
316: IF( J.LT.N ) THEN
317: CALL DGEMV( 'Trans', J-K, N-J, -ONE, A( K, J+1 ),
318: $ LDA, A( K, J ), 1, ONE, A( J, J+1 ),
319: $ LDA )
320: CALL DSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA )
321: END IF
322: *
323: 130 CONTINUE
324: *
325: * Update trailing matrix, J already incremented
326: *
327: IF( K+JB.LE.N ) THEN
328: CALL DSYRK( 'Upper', 'Trans', N-J+1, JB, -ONE,
329: $ A( K, J ), LDA, ONE, A( J, J ), LDA )
330: END IF
331: *
332: 140 CONTINUE
333: *
334: ELSE
335: *
336: * Compute the Cholesky factorization P**T * A * P = L * L**T
337: *
338: DO 180 K = 1, N, NB
339: *
340: * Account for last block not being NB wide
341: *
342: JB = MIN( NB, N-K+1 )
343: *
344: * Set relevant part of first half of WORK to zero,
345: * holds dot products
346: *
347: DO 150 I = K, N
348: WORK( I ) = 0
349: 150 CONTINUE
350: *
351: DO 170 J = K, K + JB - 1
352: *
353: * Find pivot, test for exit, else swap rows and columns
354: * Update dot products, compute possible pivots which are
355: * stored in the second half of WORK
356: *
357: DO 160 I = J, N
358: *
359: IF( J.GT.K ) THEN
360: WORK( I ) = WORK( I ) + A( I, J-1 )**2
361: END IF
362: WORK( N+I ) = A( I, I ) - WORK( I )
363: *
364: 160 CONTINUE
365: *
366: IF( J.GT.1 ) THEN
367: ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
368: PVT = ITEMP + J - 1
369: AJJ = WORK( N+PVT )
370: IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
371: A( J, J ) = AJJ
372: GO TO 190
373: END IF
374: END IF
375: *
376: IF( J.NE.PVT ) THEN
377: *
378: * Pivot OK, so can now swap pivot rows and columns
379: *
380: A( PVT, PVT ) = A( J, J )
381: CALL DSWAP( J-1, A( J, 1 ), LDA, A( PVT, 1 ), LDA )
382: IF( PVT.LT.N )
383: $ CALL DSWAP( N-PVT, A( PVT+1, J ), 1,
384: $ A( PVT+1, PVT ), 1 )
385: CALL DSWAP( PVT-J-1, A( J+1, J ), 1, A( PVT, J+1 ),
386: $ LDA )
387: *
388: * Swap dot products and PIV
389: *
390: DTEMP = WORK( J )
391: WORK( J ) = WORK( PVT )
392: WORK( PVT ) = DTEMP
393: ITEMP = PIV( PVT )
394: PIV( PVT ) = PIV( J )
395: PIV( J ) = ITEMP
396: END IF
397: *
398: AJJ = SQRT( AJJ )
399: A( J, J ) = AJJ
400: *
401: * Compute elements J+1:N of column J.
402: *
403: IF( J.LT.N ) THEN
404: CALL DGEMV( 'No Trans', N-J, J-K, -ONE,
405: $ A( J+1, K ), LDA, A( J, K ), LDA, ONE,
406: $ A( J+1, J ), 1 )
407: CALL DSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 )
408: END IF
409: *
410: 170 CONTINUE
411: *
412: * Update trailing matrix, J already incremented
413: *
414: IF( K+JB.LE.N ) THEN
415: CALL DSYRK( 'Lower', 'No Trans', N-J+1, JB, -ONE,
416: $ A( J, K ), LDA, ONE, A( J, J ), LDA )
417: END IF
418: *
419: 180 CONTINUE
420: *
421: END IF
422: END IF
423: *
424: * Ran to completion, A has full rank
425: *
426: RANK = N
427: *
428: GO TO 200
429: 190 CONTINUE
430: *
431: * Rank is the number of steps completed. Set INFO = 1 to signal
432: * that the factorization cannot be used to solve a system.
433: *
434: RANK = J - 1
435: INFO = 1
436: *
437: 200 CONTINUE
438: RETURN
439: *
440: * End of DPSTRF
441: *
442: END
CVSweb interface <joel.bertrand@systella.fr>