3
4
5
6
7
8
9
10
11 CHARACTER DIAG, NORM, UPLO
12 INTEGER IA, JA, INFO, LIWORK, LWORK, N
13 DOUBLE PRECISION RCOND
14
15
16 INTEGER DESCA( * ), IWORK( * )
17 DOUBLE PRECISION 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
171
172
173
174
175
176
177
178
179
180
181
182 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
183 $ LLD_, MB_, M_, NB_, N_, RSRC_
184 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
185 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
186 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
187 DOUBLE PRECISION ONE, ZERO
188 parameter( one = 1.0d+0, zero = 0.0d+0 )
189
190
191 LOGICAL LQUERY, NOUNIT, ONENRM, UPPER
192 CHARACTER CBTOP, COLCTOP, NORMIN, ROWCTOP
193 INTEGER IACOL, IAROW, ICOFF, ICTXT, IIA, IPN, IPV, IPW,
194 $ IPX, IROFF, IV, IX, IXX, JJA, JV, JX, KASE,
195 $ KASE1, LIWMIN, LWMIN, MYCOL, MYROW, NP, NPCOL,
196 $ NPMOD, NPROW, NQ, NQMOD
197 DOUBLE PRECISION AINVNM, ANORM, SCALE, SMLNUM
198 DOUBLE PRECISION WMAX
199
200
201 INTEGER DESCV( DLEN_ ), DESCX( DLEN_ ), IDUM1( 5 ),
202 $ IDUM2( 5 )
203
204
209
210
211 LOGICAL LSAME
212 INTEGER ICEIL, INDXG2P, NUMROC
213 DOUBLE PRECISION PDLAMCH, PDLANTR
216
217
218 INTRINSIC abs, dble, ichar,
max, mod
219
220
221
222
223
224 ictxt = desca( ctxt_ )
225 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
226
227
228
229 info = 0
230 IF( nprow.EQ.-1 ) THEN
231 info = -( 800 + ctxt_ )
232 ELSE
233 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
234 IF( info.EQ.0 ) THEN
235 upper =
lsame( uplo,
'U' )
236 onenrm = norm.EQ.
'1' .OR.
lsame( norm,
'O' )
237 nounit =
lsame( diag,
'N' )
238 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
239 $ nprow )
240 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
241 $ npcol )
242 npmod =
numroc( n + mod( ia-1, desca( mb_ ) ), desca( mb_ ),
243 $ myrow, iarow, nprow )
244 nqmod =
numroc( n + mod( ja-1, desca( nb_ ) ), desca( nb_ ),
245 $ mycol, iacol, npcol )
246 lwmin = 2*npmod + nqmod +
247 $
max( 2,
max( desca( nb_ )*
248 $
max( 1,
iceil( nprow-1, npcol ) ), nqmod +
249 $ desca( nb_ )*
250 $
max( 1,
iceil( npcol-1, nprow ) ) ) )
251 work( 1 ) = dble( lwmin )
252 liwmin = npmod
253 iwork( 1 ) = liwmin
254 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
255
256 IF( .NOT.onenrm .AND. .NOT.
lsame( norm,
'I' ) )
THEN
257 info = -1
258 ELSE IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
259 info = -2
260 ELSE IF( .NOT.nounit .AND. .NOT.
lsame( diag,
'U' ) )
THEN
261 info = -3
262 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
263 info = -11
264 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
265 info = -13
266 END IF
267 END IF
268
269 IF( onenrm ) THEN
270 idum1( 1 ) = ichar( '1' )
271 ELSE
272 idum1( 1 ) = ichar( 'I' )
273 END IF
274 idum2( 1 ) = 1
275 IF( upper ) THEN
276 idum1( 2 ) = ichar( 'U' )
277 ELSE
278 idum1( 2 ) = ichar( 'L' )
279 END IF
280 idum2( 2 ) = 2
281 IF( nounit ) THEN
282 idum1( 3 ) = ichar( 'N' )
283 ELSE
284 idum1( 3 ) = ichar( 'U' )
285 END IF
286 idum2( 3 ) = 3
287 IF( lwork.EQ.-1 ) THEN
288 idum1( 4 ) = -1
289 ELSE
290 idum1( 4 ) = 1
291 END IF
292 idum2( 4 ) = 11
293 IF( liwork.EQ.-1 ) THEN
294 idum1( 5 ) = -1
295 ELSE
296 idum1( 5 ) = 1
297 END IF
298 idum2( 5 ) = 13
299 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 5, idum1, idum2,
300 $ info )
301 END IF
302
303 IF( info.NE.0 ) THEN
304 CALL pxerbla( ictxt,
'PDTRCON', -info )
305 RETURN
306 ELSE IF( lquery ) THEN
307 RETURN
308 END IF
309
310
311
312 IF( n.EQ.0 ) THEN
313 rcond = one
314 RETURN
315 END IF
316
317 CALL pb_topget( ictxt, 'Combine', 'Columnwise', colctop )
318 CALL pb_topget( ictxt, 'Combine', 'Rowwise', rowctop )
319 CALL pb_topset( ictxt, 'Combine', 'Columnwise', '1-tree' )
320 CALL pb_topset( ictxt, 'Combine', 'Rowwise', '1-tree' )
321
322 rcond = zero
323 smlnum =
pdlamch( ictxt,
'Safe minimum' )*dble(
max( 1, n ) )
324 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
325 $ iarow, iacol )
326 iroff = mod( ia-1, desca( mb_ ) )
327 icoff = mod( ja-1, desca( nb_ ) )
328 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
329 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
330 iv = iroff + 1
331 ix = iv
332 jv = icoff + 1
333 jx = jv
334
335 ipx = 1
336 ipv = ipx + np
337 ipn = ipv + np
338 ipw = ipn + nq
339
340 CALL descset( descv, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
341 $ ictxt,
max( 1, np ) )
342 CALL descset( descx, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
343 $ ictxt,
max( 1, np ) )
344
345
346
347 anorm =
pdlantr( norm, uplo, diag, n, n, a, ia, ja, desca, work )
348
349
350
351 IF( anorm.GT.zero ) THEN
352
353
354
355 ainvnm = zero
356 normin = 'N'
357 IF( onenrm ) THEN
358 kase1 = 1
359 ELSE
360 kase1 = 2
361 END IF
362 kase = 0
363 10 CONTINUE
364 CALL pdlacon( n, work( ipv ), iv, jv, descv, work( ipx ),
365 $ ix, jx, descx, iwork, ainvnm, kase )
366 IF( kase.NE.0 ) THEN
367 IF( kase.EQ.kase1 ) THEN
368
369
370
371 descx( csrc_ ) = iacol
372 CALL pdlatrs( uplo,
'No transpose', diag, normin,
373 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
374 $ descx, scale, work( ipn ), work( ipw ) )
375 descx( csrc_ ) = mycol
376 ELSE
377
378
379
380 descx( csrc_ ) = iacol
381 CALL pdlatrs( uplo,
'Transpose', diag, normin,
382 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
383 $ descx, scale, work( ipn ), work( ipw ) )
384 descx( csrc_ ) = mycol
385 END IF
386 normin = 'Y'
387
388
389
390 IF( scale.NE.one ) THEN
391 CALL pdamax( n, wmax, ixx, work( ipx ), ix, jx,
392 $ descx, 1 )
393 IF( descx( m_ ).EQ.1 .AND. n.EQ.1 ) THEN
394 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise',
395 $ cbtop )
396 IF( myrow.EQ.iarow ) THEN
397 CALL dgebs2d( ictxt, 'Column', cbtop, 1, 1, wmax,
398 $ 1 )
399 ELSE
400 CALL dgebr2d( ictxt, 'Column', cbtop, 1, 1, wmax,
401 $ 1, iarow, mycol )
402 END IF
403 END IF
404 IF( scale.LT.abs( wmax )*smlnum .OR. scale.EQ.zero )
405 $ GO TO 20
406 CALL pdrscl( n, scale, work( ipx ), ix, jx, descx, 1 )
407 END IF
408 GO TO 10
409 END IF
410
411
412
413 IF( ainvnm.NE.zero )
414 $ rcond = ( one / anorm ) / ainvnm
415 END IF
416
417 20 CONTINUE
418
419 CALL pb_topset( ictxt, 'Combine', 'Columnwise', colctop )
420 CALL pb_topset( ictxt, 'Combine', 'Rowwise', rowctop )
421
422 RETURN
423
424
425
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 pdlacon(n, v, iv, jv, descv, x, ix, jx, descx, isgn, est, kase)
double precision function pdlantr(norm, uplo, diag, m, n, a, ia, ja, desca, work)
subroutine pdlatrs(uplo, trans, diag, normin, n, a, ia, ja, desca, x, ix, jx, descx, scale, cnorm, work)
subroutine pdrscl(n, sa, sx, ix, jx, descx, incx)
subroutine pxerbla(ictxt, srname, info)