3
4
5
6
7
8
9
10 CHARACTER UPLO
11 INTEGER IA, INFO, JA, LRWORK, LWORK, N
12 DOUBLE PRECISION ANORM, RCOND
13
14
15 INTEGER DESCA( * )
16 DOUBLE PRECISION RWORK( * )
17 COMPLEX*16 A( * ), WORK( * )
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
171 $ LLD_, MB_, M_, NB_, N_, RSRC_
172 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
173 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
174 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
175 DOUBLE PRECISION ONE, ZERO
176 parameter( one = 1.0d+0, zero = 0.0d+0 )
177
178
179 LOGICAL LQUERY, UPPER
180 CHARACTER CBTOP, COLCTOP, NORMIN, ROWCTOP
181 INTEGER IACOL, IAROW, ICOFF, ICTXT, IIA, IPNL, IPNU,
182 $ IPV, IPW, IPX, IROFF, IV, IX, IXX, JJA, JV,
183 $ JX, KASE, LRWMIN, LWMIN, MYCOL, MYROW, NP,
184 $ NPCOL, NPROW, NPMOD, NQ, NQMOD
185 DOUBLE PRECISION AINVNM, SCALE, SL, SU, SMLNUM
186 COMPLEX*16 WMAX, ZDUM
187
188
189 INTEGER DESCV( DLEN_ ), DESCX( DLEN_ ), IDUM1( 3 ),
190 $ IDUM2( 3 )
191
192
196 $ zgebr2d, zgebs2d
197
198
199 LOGICAL LSAME
200 INTEGER ICEIL, INDXG2P, NUMROC
201 DOUBLE PRECISION PDLAMCH
203
204
205 INTRINSIC abs, dble, dimag, ichar,
max, mod
206
207
208 DOUBLE PRECISION CABS1
209
210
211 cabs1( zdum ) = abs( dble( zdum ) ) + abs( dimag( zdum ) )
212
213
214
215
216
217 ictxt = desca( ctxt_ )
218 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
219
220
221
222 info = 0
223 IF( nprow.EQ.-1 ) THEN
224 info = -(600+ctxt_)
225 ELSE
226 CALL chk1mat( n, 2, n, 2, ia, ja, desca, 6, info )
227 IF( info.EQ.0 ) THEN
228 upper =
lsame( uplo,
'U' )
229 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
230 $ nprow )
231 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
232 $ npcol )
233 npmod =
numroc( n + mod( ia-1, desca( mb_ ) ), desca( mb_ ),
234 $ myrow, iarow, nprow )
235 nqmod =
numroc( n + mod( ja-1, desca( nb_ ) ), desca( nb_ ),
236 $ mycol, iacol, npcol )
237 lwmin = 2*npmod +
238 $
max( 2,
max( desca( nb_ )*
239 $
max( 1,
iceil( nprow-1, npcol ) ), nqmod +
240 $ desca( nb_ )*
241 $
max( 1,
iceil( npcol-1, nprow ) ) ) )
242 work( 1 ) = dble( lwmin )
243 lrwmin = 2*nqmod
244 rwork( 1 ) = dble( lrwmin )
245 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
246
247 IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
248 info = -1
249 ELSE IF( anorm.LT.zero ) THEN
250 info = -7
251 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
252 info = -10
253 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
254 info = -12
255 END IF
256 END IF
257
258 IF( upper ) THEN
259 idum1( 1 ) = ichar( 'U' )
260 ELSE
261 idum1( 1 ) = ichar( 'L' )
262 END IF
263 idum2( 1 ) = 1
264 IF( lwork.EQ.-1 ) THEN
265 idum1( 2 ) = -1
266 ELSE
267 idum1( 2 ) = 1
268 END IF
269 idum2( 2 ) = 10
270 IF( lrwork.EQ.-1 ) THEN
271 idum1( 3 ) = -1
272 ELSE
273 idum1( 3 ) = 1
274 END IF
275 idum2( 3 ) = 12
276 CALL pchk1mat( n, 2, n, 2, ia, ja, desca, 6, 3, idum1, idum2,
277 $ info )
278 END IF
279
280 IF( info.NE.0 ) THEN
281 CALL pxerbla( ictxt,
'PZPOCON', -info )
282 RETURN
283 ELSE IF( lquery ) THEN
284 RETURN
285 END IF
286
287
288
289 rcond = zero
290 IF( n.EQ.0 ) THEN
291 rcond = one
292 RETURN
293 ELSE IF( anorm.EQ.zero ) THEN
294 RETURN
295 ELSE IF( n.EQ.1 ) THEN
296 rcond = one
297 RETURN
298 END IF
299
300 CALL pb_topget( ictxt, 'Combine', 'Columnwise', colctop )
301 CALL pb_topget( ictxt, 'Combine', 'Rowwise', rowctop )
302 CALL pb_topset( ictxt, 'Combine', 'Columnwise', '1-tree' )
303 CALL pb_topset( ictxt, 'Combine', 'Rowwise', '1-tree' )
304
305 smlnum =
pdlamch( ictxt,
'Safe minimum' )
306 iroff = mod( ia-1, desca( mb_ ) )
307 icoff = mod( ja-1, desca( nb_ ) )
308 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
309 $ iarow, iacol )
310 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
311 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
312 iv = iroff + 1
313 ix = iv
314 jv = icoff + 1
315 jx = jv
316
317 ipx = 1
318 ipv = ipx + np
319 ipw = ipv + np
320 ipnl = 1
321 ipnu = ipnl + nq
322
323 CALL descset( descv, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
324 $ ictxt,
max( 1, np ) )
325 CALL descset( descx, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
326 $ ictxt,
max( 1, np ) )
327
328
329
330 ainvnm = zero
331 kase = 0
332 normin = 'N'
333
334 10 CONTINUE
335 CALL pzlacon( n, work( ipv ), iv, jv, descv, work( ipx ), ix, jx,
336 $ descx, ainvnm, kase )
337 IF( kase.NE.0 ) THEN
338 IF( upper ) THEN
339
340
341
342 descx( csrc_ ) = iacol
343 CALL pzlatrs(
'Upper',
'Conjugate transpose',
'Non-unit',
344 $ normin, n, a, ia, ja, desca, work( ipx ),
345 $ ix, jx, descx, sl, rwork( ipnl ),
346 $ work( ipw ) )
347 descx( csrc_ ) = mycol
348 normin = 'Y'
349
350
351
352 descx( csrc_ ) = iacol
353 CALL pzlatrs(
'Upper',
'No transpose',
'Non-unit', normin,
354 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
355 $ descx, su, rwork( ipnu ), work( ipw ) )
356 descx( csrc_ ) = mycol
357 ELSE
358
359
360
361 descx( csrc_ ) = iacol
362 CALL pzlatrs(
'Lower',
'No transpose',
'Non-unit', normin,
363 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
364 $ descx, sl, rwork( ipnl ), work( ipw ) )
365 descx( csrc_ ) = mycol
366 normin = 'Y'
367
368
369
370 descx( csrc_ ) = iacol
371 CALL pzlatrs(
'Lower',
'Conjugate transpose',
'Non-unit',
372 $ normin, n, a, ia, ja, desca, work( ipx ),
373 $ ix, jx, descx, su, rwork( ipnu ),
374 $ work( ipw ) )
375 descx( csrc_ ) = mycol
376 END IF
377
378
379
380 scale = sl*su
381 IF( scale.NE.one ) THEN
382 CALL pzamax( n, wmax, ixx, work( ipx ), ix, jx, descx, 1 )
383 IF( descx( m_ ).EQ.1 .AND. n.EQ.1 ) THEN
384 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', cbtop )
385 IF( myrow.EQ.iarow ) THEN
386 CALL zgebs2d( ictxt, 'Column', cbtop, 1, 1, wmax, 1 )
387 ELSE
388 CALL zgebr2d( ictxt, 'Column', cbtop, 1, 1, wmax, 1,
389 $ iarow, mycol )
390 END IF
391 END IF
392 IF( scale.LT.cabs1( wmax )*smlnum .OR. scale.EQ.zero )
393 $ GO TO 20
394 CALL pzdrscl( n, scale, work( ipx ), ix, jx, descx, 1 )
395 END IF
396 GO TO 10
397 END IF
398
399
400
401 IF( ainvnm.NE.zero )
402 $ rcond = ( one / ainvnm ) / anorm
403
404 20 CONTINUE
405
406 CALL pb_topset( ictxt, 'Combine', 'Columnwise', colctop )
407 CALL pb_topset( ictxt, 'Combine', 'Rowwise', rowctop )
408
409 RETURN
410
411
412
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
subroutine descset(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld)
integer function iceil(inum, idenom)
integer function indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
subroutine infog2l(grindx, gcindx, desc, nprow, npcol, myrow, mycol, lrindx, lcindx, rsrc, csrc)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
double precision function pdlamch(ictxt, cmach)
subroutine pxerbla(ictxt, srname, info)
subroutine pzdrscl(n, sa, sx, ix, jx, descx, incx)
subroutine pzlacon(n, v, iv, jv, descv, x, ix, jx, descx, est, kase)
subroutine pzlatrs(uplo, trans, diag, normin, n, a, ia, ja, desca, x, ix, jx, descx, scale, cnorm, work)