LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
dsposv.f
Go to the documentation of this file.
1*> \brief <b> DSPOSV computes the solution to system of linear equations A * X = B for PO matrices</b>
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download DSPOSV + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsposv.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsposv.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsposv.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE DSPOSV( UPLO, N, NRHS, A, LDA, B, LDB, X, LDX, WORK,
20* SWORK, ITER, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER UPLO
24* INTEGER INFO, ITER, LDA, LDB, LDX, N, NRHS
25* ..
26* .. Array Arguments ..
27* REAL SWORK( * )
28* DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( N, * ),
29* $ X( LDX, * )
30* ..
31*
32*
33*> \par Purpose:
34* =============
35*>
36*> \verbatim
37*>
38*> DSPOSV computes the solution to a real system of linear equations
39*> A * X = B,
40*> where A is an N-by-N symmetric positive definite matrix and X and B
41*> are N-by-NRHS matrices.
42*>
43*> DSPOSV first attempts to factorize the matrix in SINGLE PRECISION
44*> and use this factorization within an iterative refinement procedure
45*> to produce a solution with DOUBLE PRECISION normwise backward error
46*> quality (see below). If the approach fails the method switches to a
47*> DOUBLE PRECISION factorization and solve.
48*>
49*> The iterative refinement is not going to be a winning strategy if
50*> the ratio SINGLE PRECISION performance over DOUBLE PRECISION
51*> performance is too small. A reasonable strategy should take the
52*> number of right-hand sides and the size of the matrix into account.
53*> This might be done with a call to ILAENV in the future. Up to now, we
54*> always try iterative refinement.
55*>
56*> The iterative refinement process is stopped if
57*> ITER > ITERMAX
58*> or for all the RHS we have:
59*> RNRM < SQRT(N)*XNRM*ANRM*EPS*BWDMAX
60*> where
61*> o ITER is the number of the current iteration in the iterative
62*> refinement process
63*> o RNRM is the infinity-norm of the residual
64*> o XNRM is the infinity-norm of the solution
65*> o ANRM is the infinity-operator-norm of the matrix A
66*> o EPS is the machine epsilon returned by DLAMCH('Epsilon')
67*> The value ITERMAX and BWDMAX are fixed to 30 and 1.0D+00
68*> respectively.
69*> \endverbatim
70*
71* Arguments:
72* ==========
73*
74*> \param[in] UPLO
75*> \verbatim
76*> UPLO is CHARACTER*1
77*> = 'U': Upper triangle of A is stored;
78*> = 'L': Lower triangle of A is stored.
79*> \endverbatim
80*>
81*> \param[in] N
82*> \verbatim
83*> N is INTEGER
84*> The number of linear equations, i.e., the order of the
85*> matrix A. N >= 0.
86*> \endverbatim
87*>
88*> \param[in] NRHS
89*> \verbatim
90*> NRHS is INTEGER
91*> The number of right hand sides, i.e., the number of columns
92*> of the matrix B. NRHS >= 0.
93*> \endverbatim
94*>
95*> \param[in,out] A
96*> \verbatim
97*> A is DOUBLE PRECISION array,
98*> dimension (LDA,N)
99*> On entry, the symmetric matrix A. If UPLO = 'U', the leading
100*> N-by-N upper triangular part of A contains the upper
101*> triangular part of the matrix A, and the strictly lower
102*> triangular part of A is not referenced. If UPLO = 'L', the
103*> leading N-by-N lower triangular part of A contains the lower
104*> triangular part of the matrix A, and the strictly upper
105*> triangular part of A is not referenced.
106*> On exit, if iterative refinement has been successfully used
107*> (INFO = 0 and ITER >= 0, see description below), then A is
108*> unchanged, if double precision factorization has been used
109*> (INFO = 0 and ITER < 0, see description below), then the
110*> array A contains the factor U or L from the Cholesky
111*> factorization A = U**T*U or A = L*L**T.
112*> \endverbatim
113*>
114*> \param[in] LDA
115*> \verbatim
116*> LDA is INTEGER
117*> The leading dimension of the array A. LDA >= max(1,N).
118*> \endverbatim
119*>
120*> \param[in] B
121*> \verbatim
122*> B is DOUBLE PRECISION array, dimension (LDB,NRHS)
123*> The N-by-NRHS right hand side matrix B.
124*> \endverbatim
125*>
126*> \param[in] LDB
127*> \verbatim
128*> LDB is INTEGER
129*> The leading dimension of the array B. LDB >= max(1,N).
130*> \endverbatim
131*>
132*> \param[out] X
133*> \verbatim
134*> X is DOUBLE PRECISION array, dimension (LDX,NRHS)
135*> If INFO = 0, the N-by-NRHS solution matrix X.
136*> \endverbatim
137*>
138*> \param[in] LDX
139*> \verbatim
140*> LDX is INTEGER
141*> The leading dimension of the array X. LDX >= max(1,N).
142*> \endverbatim
143*>
144*> \param[out] WORK
145*> \verbatim
146*> WORK is DOUBLE PRECISION array, dimension (N,NRHS)
147*> This array is used to hold the residual vectors.
148*> \endverbatim
149*>
150*> \param[out] SWORK
151*> \verbatim
152*> SWORK is REAL array, dimension (N*(N+NRHS))
153*> This array is used to use the single precision matrix and the
154*> right-hand sides or solutions in single precision.
155*> \endverbatim
156*>
157*> \param[out] ITER
158*> \verbatim
159*> ITER is INTEGER
160*> < 0: iterative refinement has failed, double precision
161*> factorization has been performed
162*> -1 : the routine fell back to full precision for
163*> implementation- or machine-specific reasons
164*> -2 : narrowing the precision induced an overflow,
165*> the routine fell back to full precision
166*> -3 : failure of SPOTRF
167*> -31: stop the iterative refinement after the 30th
168*> iterations
169*> > 0: iterative refinement has been successfully used.
170*> Returns the number of iterations
171*> \endverbatim
172*>
173*> \param[out] INFO
174*> \verbatim
175*> INFO is INTEGER
176*> = 0: successful exit
177*> < 0: if INFO = -i, the i-th argument had an illegal value
178*> > 0: if INFO = i, the leading principal minor of order i
179*> of (DOUBLE PRECISION) A is not positive, so the
180*> factorization could not be completed, and the solution
181*> has not been computed.
182*> \endverbatim
183*
184* Authors:
185* ========
186*
187*> \author Univ. of Tennessee
188*> \author Univ. of California Berkeley
189*> \author Univ. of Colorado Denver
190*> \author NAG Ltd.
191*
192*> \ingroup posv_mixed
193*
194* =====================================================================
195 SUBROUTINE dsposv( UPLO, N, NRHS, A, LDA, B, LDB, X, LDX, WORK,
196 $ SWORK, ITER, INFO )
197*
198* -- LAPACK driver routine --
199* -- LAPACK is a software package provided by Univ. of Tennessee, --
200* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
201*
202* .. Scalar Arguments ..
203 CHARACTER UPLO
204 INTEGER INFO, ITER, LDA, LDB, LDX, N, NRHS
205* ..
206* .. Array Arguments ..
207 REAL SWORK( * )
208 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), WORK( N, * ),
209 $ x( ldx, * )
210* ..
211*
212* =====================================================================
213*
214* .. Parameters ..
215 LOGICAL DOITREF
216 parameter( doitref = .true. )
217*
218 INTEGER ITERMAX
219 parameter( itermax = 30 )
220*
221 DOUBLE PRECISION BWDMAX
222 parameter( bwdmax = 1.0e+00 )
223*
224 DOUBLE PRECISION NEGONE, ONE
225 parameter( negone = -1.0d+0, one = 1.0d+0 )
226*
227* .. Local Scalars ..
228 INTEGER I, IITER, PTSA, PTSX
229 DOUBLE PRECISION ANRM, CTE, EPS, RNRM, XNRM
230*
231* .. External Subroutines ..
232 EXTERNAL daxpy, dsymm, dlacpy, dlat2s, dlag2s,
233 $ slag2d,
235* ..
236* .. External Functions ..
237 INTEGER IDAMAX
238 DOUBLE PRECISION DLAMCH, DLANSY
239 LOGICAL LSAME
240 EXTERNAL idamax, dlamch, dlansy, lsame
241* ..
242* .. Intrinsic Functions ..
243 INTRINSIC abs, dble, max, sqrt
244* ..
245* .. Executable Statements ..
246*
247 info = 0
248 iter = 0
249*
250* Test the input parameters.
251*
252 IF( .NOT.lsame( uplo, 'U' ) .AND.
253 $ .NOT.lsame( uplo, 'L' ) ) THEN
254 info = -1
255 ELSE IF( n.LT.0 ) THEN
256 info = -2
257 ELSE IF( nrhs.LT.0 ) THEN
258 info = -3
259 ELSE IF( lda.LT.max( 1, n ) ) THEN
260 info = -5
261 ELSE IF( ldb.LT.max( 1, n ) ) THEN
262 info = -7
263 ELSE IF( ldx.LT.max( 1, n ) ) THEN
264 info = -9
265 END IF
266 IF( info.NE.0 ) THEN
267 CALL xerbla( 'DSPOSV', -info )
268 RETURN
269 END IF
270*
271* Quick return if (N.EQ.0).
272*
273 IF( n.EQ.0 )
274 $ RETURN
275*
276* Skip single precision iterative refinement if a priori slower
277* than double precision factorization.
278*
279 IF( .NOT.doitref ) THEN
280 iter = -1
281 GO TO 40
282 END IF
283*
284* Compute some constants.
285*
286 anrm = dlansy( 'I', uplo, n, a, lda, work )
287 eps = dlamch( 'Epsilon' )
288 cte = anrm*eps*sqrt( dble( n ) )*bwdmax
289*
290* Set the indices PTSA, PTSX for referencing SA and SX in SWORK.
291*
292 ptsa = 1
293 ptsx = ptsa + n*n
294*
295* Convert B from double precision to single precision and store the
296* result in SX.
297*
298 CALL dlag2s( n, nrhs, b, ldb, swork( ptsx ), n, info )
299*
300 IF( info.NE.0 ) THEN
301 iter = -2
302 GO TO 40
303 END IF
304*
305* Convert A from double precision to single precision and store the
306* result in SA.
307*
308 CALL dlat2s( uplo, n, a, lda, swork( ptsa ), n, info )
309*
310 IF( info.NE.0 ) THEN
311 iter = -2
312 GO TO 40
313 END IF
314*
315* Compute the Cholesky factorization of SA.
316*
317 CALL spotrf( uplo, n, swork( ptsa ), n, info )
318*
319 IF( info.NE.0 ) THEN
320 iter = -3
321 GO TO 40
322 END IF
323*
324* Solve the system SA*SX = SB.
325*
326 CALL spotrs( uplo, n, nrhs, swork( ptsa ), n, swork( ptsx ), n,
327 $ info )
328*
329* Convert SX back to double precision
330*
331 CALL slag2d( n, nrhs, swork( ptsx ), n, x, ldx, info )
332*
333* Compute R = B - AX (R is WORK).
334*
335 CALL dlacpy( 'All', n, nrhs, b, ldb, work, n )
336*
337 CALL dsymm( 'Left', uplo, n, nrhs, negone, a, lda, x, ldx, one,
338 $ work, n )
339*
340* Check whether the NRHS normwise backward errors satisfy the
341* stopping criterion. If yes, set ITER=0 and return.
342*
343 DO i = 1, nrhs
344 xnrm = abs( x( idamax( n, x( 1, i ), 1 ), i ) )
345 rnrm = abs( work( idamax( n, work( 1, i ), 1 ), i ) )
346 IF( rnrm.GT.xnrm*cte )
347 $ GO TO 10
348 END DO
349*
350* If we are here, the NRHS normwise backward errors satisfy the
351* stopping criterion. We are good to exit.
352*
353 iter = 0
354 RETURN
355*
356 10 CONTINUE
357*
358 DO 30 iiter = 1, itermax
359*
360* Convert R (in WORK) from double precision to single precision
361* and store the result in SX.
362*
363 CALL dlag2s( n, nrhs, work, n, swork( ptsx ), n, info )
364*
365 IF( info.NE.0 ) THEN
366 iter = -2
367 GO TO 40
368 END IF
369*
370* Solve the system SA*SX = SR.
371*
372 CALL spotrs( uplo, n, nrhs, swork( ptsa ), n, swork( ptsx ),
373 $ n,
374 $ info )
375*
376* Convert SX back to double precision and update the current
377* iterate.
378*
379 CALL slag2d( n, nrhs, swork( ptsx ), n, work, n, info )
380*
381 DO i = 1, nrhs
382 CALL daxpy( n, one, work( 1, i ), 1, x( 1, i ), 1 )
383 END DO
384*
385* Compute R = B - AX (R is WORK).
386*
387 CALL dlacpy( 'All', n, nrhs, b, ldb, work, n )
388*
389 CALL dsymm( 'L', uplo, n, nrhs, negone, a, lda, x, ldx, one,
390 $ work, n )
391*
392* Check whether the NRHS normwise backward errors satisfy the
393* stopping criterion. If yes, set ITER=IITER>0 and return.
394*
395 DO i = 1, nrhs
396 xnrm = abs( x( idamax( n, x( 1, i ), 1 ), i ) )
397 rnrm = abs( work( idamax( n, work( 1, i ), 1 ), i ) )
398 IF( rnrm.GT.xnrm*cte )
399 $ GO TO 20
400 END DO
401*
402* If we are here, the NRHS normwise backward errors satisfy the
403* stopping criterion, we are good to exit.
404*
405 iter = iiter
406*
407 RETURN
408*
409 20 CONTINUE
410*
411 30 CONTINUE
412*
413* If we are at this place of the code, this is because we have
414* performed ITER=ITERMAX iterations and never satisfied the
415* stopping criterion, set up the ITER flag accordingly and follow
416* up on double precision routine.
417*
418 iter = -itermax - 1
419*
420 40 CONTINUE
421*
422* Single-precision iterative refinement failed to converge to a
423* satisfactory solution, so we resort to double precision.
424*
425 CALL dpotrf( uplo, n, a, lda, info )
426*
427 IF( info.NE.0 )
428 $ RETURN
429*
430 CALL dlacpy( 'All', n, nrhs, b, ldb, x, ldx )
431 CALL dpotrs( uplo, n, nrhs, a, lda, x, ldx, info )
432*
433 RETURN
434*
435* End of DSPOSV
436*
437 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dlag2s(m, n, a, lda, sa, ldsa, info)
DLAG2S converts a double precision matrix to a single precision matrix.
Definition dlag2s.f:106
subroutine slag2d(m, n, sa, ldsa, a, lda, info)
SLAG2D converts a single precision matrix to a double precision matrix.
Definition slag2d.f:102
subroutine dlat2s(uplo, n, a, lda, sa, ldsa, info)
DLAT2S converts a double-precision triangular matrix to a single-precision triangular matrix.
Definition dlat2s.f:109
subroutine daxpy(n, da, dx, incx, dy, incy)
DAXPY
Definition daxpy.f:89
subroutine dsymm(side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc)
DSYMM
Definition dsymm.f:189
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
Definition dlacpy.f:101
subroutine dsposv(uplo, n, nrhs, a, lda, b, ldb, x, ldx, work, swork, iter, info)
DSPOSV computes the solution to system of linear equations A * X = B for PO matrices
Definition dsposv.f:197
subroutine dpotrf(uplo, n, a, lda, info)
DPOTRF
Definition dpotrf.f:105
subroutine spotrf(uplo, n, a, lda, info)
SPOTRF
Definition spotrf.f:105
subroutine dpotrs(uplo, n, nrhs, a, lda, b, ldb, info)
DPOTRS
Definition dpotrs.f:108
subroutine spotrs(uplo, n, nrhs, a, lda, b, ldb, info)
SPOTRS
Definition spotrs.f:108