Annotation of rpl/lapack/lapack/dpstrf.f, revision 1.11
1.11 ! bertrand 1: *> \brief \b DPSTRF computes the Cholesky factorization with complete pivoting of a real symmetric positive semidefinite matrix.
! 2: *
1.6 bertrand 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
1.11 ! bertrand 125: *> as returned in RANK, or is not positive semidefinite. See
! 126: *> Section 7 of LAPACK Working Note #161 for further
! 127: *> information.
1.6 bertrand 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: *
1.11 ! bertrand 138: *> \date November 2015
1.6 bertrand 139: *
140: *> \ingroup doubleOTHERcomputational
141: *
142: * =====================================================================
1.1 bertrand 143: SUBROUTINE DPSTRF( UPLO, N, A, LDA, PIV, RANK, TOL, WORK, INFO )
144: *
1.11 ! bertrand 145: * -- LAPACK computational routine (version 3.6.0) --
1.6 bertrand 146: * -- LAPACK is a software package provided by Univ. of Tennessee, --
147: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.11 ! bertrand 148: * November 2015
1.1 bertrand 149: *
150: * .. Scalar Arguments ..
151: DOUBLE PRECISION TOL
152: INTEGER INFO, LDA, N, RANK
153: CHARACTER UPLO
154: * ..
155: * .. Array Arguments ..
156: DOUBLE PRECISION A( LDA, * ), WORK( 2*N )
157: INTEGER PIV( N )
158: * ..
159: *
160: * =====================================================================
161: *
162: * .. Parameters ..
163: DOUBLE PRECISION ONE, ZERO
164: PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
165: * ..
166: * .. Local Scalars ..
167: DOUBLE PRECISION AJJ, DSTOP, DTEMP
168: INTEGER I, ITEMP, J, JB, K, NB, PVT
169: LOGICAL UPPER
170: * ..
171: * .. External Functions ..
172: DOUBLE PRECISION DLAMCH
173: INTEGER ILAENV
174: LOGICAL LSAME, DISNAN
175: EXTERNAL DLAMCH, ILAENV, LSAME, DISNAN
176: * ..
177: * .. External Subroutines ..
178: EXTERNAL DGEMV, DPSTF2, DSCAL, DSWAP, DSYRK, XERBLA
179: * ..
180: * .. Intrinsic Functions ..
181: INTRINSIC MAX, MIN, SQRT, MAXLOC
182: * ..
183: * .. Executable Statements ..
184: *
185: * Test the input parameters.
186: *
187: INFO = 0
188: UPPER = LSAME( UPLO, 'U' )
189: IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
190: INFO = -1
191: ELSE IF( N.LT.0 ) THEN
192: INFO = -2
193: ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
194: INFO = -4
195: END IF
196: IF( INFO.NE.0 ) THEN
197: CALL XERBLA( 'DPSTRF', -INFO )
198: RETURN
199: END IF
200: *
201: * Quick return if possible
202: *
203: IF( N.EQ.0 )
204: $ RETURN
205: *
206: * Get block size
207: *
208: NB = ILAENV( 1, 'DPOTRF', UPLO, N, -1, -1, -1 )
209: IF( NB.LE.1 .OR. NB.GE.N ) THEN
210: *
211: * Use unblocked code
212: *
213: CALL DPSTF2( UPLO, N, A( 1, 1 ), LDA, PIV, RANK, TOL, WORK,
214: $ INFO )
215: GO TO 200
216: *
217: ELSE
218: *
219: * Initialize PIV
220: *
221: DO 100 I = 1, N
222: PIV( I ) = I
223: 100 CONTINUE
224: *
225: * Compute stopping value
226: *
227: PVT = 1
228: AJJ = A( PVT, PVT )
229: DO I = 2, N
230: IF( A( I, I ).GT.AJJ ) THEN
231: PVT = I
232: AJJ = A( PVT, PVT )
233: END IF
234: END DO
1.11 ! bertrand 235: IF( AJJ.LE.ZERO.OR.DISNAN( AJJ ) ) THEN
1.1 bertrand 236: RANK = 0
237: INFO = 1
238: GO TO 200
239: END IF
240: *
241: * Compute stopping value if not supplied
242: *
243: IF( TOL.LT.ZERO ) THEN
244: DSTOP = N * DLAMCH( 'Epsilon' ) * AJJ
245: ELSE
246: DSTOP = TOL
247: END IF
248: *
249: *
250: IF( UPPER ) THEN
251: *
1.5 bertrand 252: * Compute the Cholesky factorization P**T * A * P = U**T * U
1.1 bertrand 253: *
254: DO 140 K = 1, N, NB
255: *
256: * Account for last block not being NB wide
257: *
258: JB = MIN( NB, N-K+1 )
259: *
260: * Set relevant part of first half of WORK to zero,
261: * holds dot products
262: *
263: DO 110 I = K, N
264: WORK( I ) = 0
265: 110 CONTINUE
266: *
267: DO 130 J = K, K + JB - 1
268: *
269: * Find pivot, test for exit, else swap rows and columns
270: * Update dot products, compute possible pivots which are
271: * stored in the second half of WORK
272: *
273: DO 120 I = J, N
274: *
275: IF( J.GT.K ) THEN
276: WORK( I ) = WORK( I ) + A( J-1, I )**2
277: END IF
278: WORK( N+I ) = A( I, I ) - WORK( I )
279: *
280: 120 CONTINUE
281: *
282: IF( J.GT.1 ) THEN
283: ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
284: PVT = ITEMP + J - 1
285: AJJ = WORK( N+PVT )
286: IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
287: A( J, J ) = AJJ
288: GO TO 190
289: END IF
290: END IF
291: *
292: IF( J.NE.PVT ) THEN
293: *
294: * Pivot OK, so can now swap pivot rows and columns
295: *
296: A( PVT, PVT ) = A( J, J )
297: CALL DSWAP( J-1, A( 1, J ), 1, A( 1, PVT ), 1 )
298: IF( PVT.LT.N )
299: $ CALL DSWAP( N-PVT, A( J, PVT+1 ), LDA,
300: $ A( PVT, PVT+1 ), LDA )
301: CALL DSWAP( PVT-J-1, A( J, J+1 ), LDA,
302: $ A( J+1, PVT ), 1 )
303: *
304: * Swap dot products and PIV
305: *
306: DTEMP = WORK( J )
307: WORK( J ) = WORK( PVT )
308: WORK( PVT ) = DTEMP
309: ITEMP = PIV( PVT )
310: PIV( PVT ) = PIV( J )
311: PIV( J ) = ITEMP
312: END IF
313: *
314: AJJ = SQRT( AJJ )
315: A( J, J ) = AJJ
316: *
317: * Compute elements J+1:N of row J.
318: *
319: IF( J.LT.N ) THEN
320: CALL DGEMV( 'Trans', J-K, N-J, -ONE, A( K, J+1 ),
321: $ LDA, A( K, J ), 1, ONE, A( J, J+1 ),
322: $ LDA )
323: CALL DSCAL( N-J, ONE / AJJ, A( J, J+1 ), LDA )
324: END IF
325: *
326: 130 CONTINUE
327: *
328: * Update trailing matrix, J already incremented
329: *
330: IF( K+JB.LE.N ) THEN
331: CALL DSYRK( 'Upper', 'Trans', N-J+1, JB, -ONE,
332: $ A( K, J ), LDA, ONE, A( J, J ), LDA )
333: END IF
334: *
335: 140 CONTINUE
336: *
337: ELSE
338: *
1.5 bertrand 339: * Compute the Cholesky factorization P**T * A * P = L * L**T
1.1 bertrand 340: *
341: DO 180 K = 1, N, NB
342: *
343: * Account for last block not being NB wide
344: *
345: JB = MIN( NB, N-K+1 )
346: *
347: * Set relevant part of first half of WORK to zero,
348: * holds dot products
349: *
350: DO 150 I = K, N
351: WORK( I ) = 0
352: 150 CONTINUE
353: *
354: DO 170 J = K, K + JB - 1
355: *
356: * Find pivot, test for exit, else swap rows and columns
357: * Update dot products, compute possible pivots which are
358: * stored in the second half of WORK
359: *
360: DO 160 I = J, N
361: *
362: IF( J.GT.K ) THEN
363: WORK( I ) = WORK( I ) + A( I, J-1 )**2
364: END IF
365: WORK( N+I ) = A( I, I ) - WORK( I )
366: *
367: 160 CONTINUE
368: *
369: IF( J.GT.1 ) THEN
370: ITEMP = MAXLOC( WORK( (N+J):(2*N) ), 1 )
371: PVT = ITEMP + J - 1
372: AJJ = WORK( N+PVT )
373: IF( AJJ.LE.DSTOP.OR.DISNAN( AJJ ) ) THEN
374: A( J, J ) = AJJ
375: GO TO 190
376: END IF
377: END IF
378: *
379: IF( J.NE.PVT ) THEN
380: *
381: * Pivot OK, so can now swap pivot rows and columns
382: *
383: A( PVT, PVT ) = A( J, J )
384: CALL DSWAP( J-1, A( J, 1 ), LDA, A( PVT, 1 ), LDA )
385: IF( PVT.LT.N )
386: $ CALL DSWAP( N-PVT, A( PVT+1, J ), 1,
387: $ A( PVT+1, PVT ), 1 )
388: CALL DSWAP( PVT-J-1, A( J+1, J ), 1, A( PVT, J+1 ),
389: $ LDA )
390: *
391: * Swap dot products and PIV
392: *
393: DTEMP = WORK( J )
394: WORK( J ) = WORK( PVT )
395: WORK( PVT ) = DTEMP
396: ITEMP = PIV( PVT )
397: PIV( PVT ) = PIV( J )
398: PIV( J ) = ITEMP
399: END IF
400: *
401: AJJ = SQRT( AJJ )
402: A( J, J ) = AJJ
403: *
404: * Compute elements J+1:N of column J.
405: *
406: IF( J.LT.N ) THEN
407: CALL DGEMV( 'No Trans', N-J, J-K, -ONE,
408: $ A( J+1, K ), LDA, A( J, K ), LDA, ONE,
409: $ A( J+1, J ), 1 )
410: CALL DSCAL( N-J, ONE / AJJ, A( J+1, J ), 1 )
411: END IF
412: *
413: 170 CONTINUE
414: *
415: * Update trailing matrix, J already incremented
416: *
417: IF( K+JB.LE.N ) THEN
418: CALL DSYRK( 'Lower', 'No Trans', N-J+1, JB, -ONE,
419: $ A( J, K ), LDA, ONE, A( J, J ), LDA )
420: END IF
421: *
422: 180 CONTINUE
423: *
424: END IF
425: END IF
426: *
427: * Ran to completion, A has full rank
428: *
429: RANK = N
430: *
431: GO TO 200
432: 190 CONTINUE
433: *
434: * Rank is the number of steps completed. Set INFO = 1 to signal
435: * that the factorization cannot be used to solve a system.
436: *
437: RANK = J - 1
438: INFO = 1
439: *
440: 200 CONTINUE
441: RETURN
442: *
443: * End of DPSTRF
444: *
445: END
CVSweb interface <joel.bertrand@systella.fr>