3
4
5
6
7
8
9
10
11 CHARACTER DIAG, NORM, UPLO
12 INTEGER IA, JA, INFO, LRWORK, LWORK, N
13 REAL RCOND
14
15
16 INTEGER DESCA( * )
17 REAL RWORK( * )
18 COMPLEX A( * ), WORK( * )
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 REAL ONE, ZERO
188 parameter( one = 1.0e+0, zero = 0.0e+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, LRWMIN, LWMIN, MYCOL, MYROW, NP, NPCOL,
196 $ NPMOD, NPROW, NQMOD
197 REAL AINVNM, ANORM, SCALE, SMLNUM
198 COMPLEX WMAX, ZDUM
199
200
201 INTEGER DESCV( DLEN_ ), DESCX( DLEN_ ), IDUM1( 5 ),
202 $ IDUM2( 5 )
203
204
205 EXTERNAL blacs_gridinfo, cgebr2d, cgebs2d,
chk1mat,
209
210
211 LOGICAL LSAME
212 INTEGER ICEIL, INDXG2P, NUMROC
213 REAL PCLANTR, PSLAMCH
216
217
218 INTRINSIC abs, aimag, ichar,
max, mod, real
219
220
221 REAL CABS1
222
223
224 cabs1( zdum ) = abs( real( zdum ) ) + abs( aimag( zdum ) )
225
226
227
228
229
230 ictxt = desca( ctxt_ )
231 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
232
233
234
235 info = 0
236 IF( nprow.EQ.-1 ) THEN
237 info = -( 800 + ctxt_ )
238 ELSE
239 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
240 IF( info.EQ.0 ) THEN
241 upper =
lsame( uplo,
'U' )
242 onenrm = norm.EQ.
'1' .OR.
lsame( norm,
'O' )
243 nounit =
lsame( diag,
'N' )
244 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
245 $ nprow )
246 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
247 $ npcol )
248 npmod =
numroc( n + mod( ia-1, desca( mb_ ) ), desca( mb_ ),
249 $ myrow, iarow, nprow )
250 nqmod =
numroc( n + mod( ja-1, desca( nb_ ) ), desca( nb_ ),
251 $ mycol, iacol, npcol )
252 lwmin = 2*npmod +
253 $
max( 2,
max( desca( nb_ )*
254 $
max( 1,
iceil( nprow-1, npcol ) ), nqmod +
255 $ desca( nb_ )*
256 $
max( 1,
iceil( npcol-1, nprow ) ) ) )
257 work( 1 ) = real( lwmin )
258 lrwmin = nqmod
259 rwork( 1 ) = real( lrwmin )
260 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
261
262 IF( .NOT.onenrm .AND. .NOT.
lsame( norm,
'I' ) )
THEN
263 info = -1
264 ELSE IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
265 info = -2
266 ELSE IF( .NOT.nounit .AND. .NOT.
lsame( diag,
'U' ) )
THEN
267 info = -3
268 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
269 info = -11
270 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
271 info = -13
272 END IF
273 END IF
274
275 IF( onenrm ) THEN
276 idum1( 1 ) = ichar( '1' )
277 ELSE
278 idum1( 1 ) = ichar( 'I' )
279 END IF
280 idum2( 1 ) = 1
281 IF( upper ) THEN
282 idum1( 2 ) = ichar( 'U' )
283 ELSE
284 idum1( 2 ) = ichar( 'L' )
285 END IF
286 idum2( 2 ) = 2
287 IF( nounit ) THEN
288 idum1( 3 ) = ichar( 'N' )
289 ELSE
290 idum1( 3 ) = ichar( 'U' )
291 END IF
292 idum2( 3 ) = 3
293 IF( lwork.EQ.-1 ) THEN
294 idum1( 4 ) = -1
295 ELSE
296 idum1( 4 ) = 1
297 END IF
298 idum2( 4 ) = 11
299 IF( lrwork.EQ.-1 ) THEN
300 idum1( 5 ) = -1
301 ELSE
302 idum1( 5 ) = 1
303 END IF
304 idum2( 5 ) = 13
305 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 5, idum1, idum2,
306 $ info )
307 END IF
308
309 IF( info.NE.0 ) THEN
310 CALL pxerbla( ictxt,
'PCTRCON', -info )
311 RETURN
312 ELSE IF( lquery ) THEN
313 RETURN
314 END IF
315
316
317
318 IF( n.EQ.0 ) THEN
319 rcond = one
320 RETURN
321 END IF
322
323 CALL pb_topget( ictxt, 'Combine', 'Columnwise', colctop )
324 CALL pb_topget( ictxt, 'Combine', 'Rowwise', rowctop )
325 CALL pb_topset( ictxt, 'Combine', 'Columnwise', '1-tree' )
326 CALL pb_topset( ictxt, 'Combine', 'Rowwise', '1-tree' )
327
328 rcond = zero
329 smlnum =
pslamch( ictxt,
'Safe minimum' )*real(
max( 1, n ) )
330 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
331 $ iarow, iacol )
332 iroff = mod( ia-1, desca( mb_ ) )
333 icoff = mod( ja-1, desca( nb_ ) )
334 np =
numroc( n+iroff, desca( mb_ ), myrow, iarow, nprow )
335 iv = iroff + 1
336 ix = iv
337 jv = icoff + 1
338 jx = jv
339
340 ipx = 1
341 ipv = ipx + np
342 ipw = ipv + np
343 ipn = 1
344
345 CALL descset( descv, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
346 $ ictxt,
max( 1, np ) )
347 CALL descset( descx, n+iroff, 1, desca( mb_ ), 1, iarow, mycol,
348 $ ictxt,
max( 1, np ) )
349
350
351
352 anorm =
pclantr( norm, uplo, diag, n, n, a, ia, ja, desca, rwork )
353
354
355
356 IF( anorm.GT.zero ) THEN
357
358
359
360 ainvnm = zero
361 normin = 'N'
362 IF( onenrm ) THEN
363 kase1 = 1
364 ELSE
365 kase1 = 2
366 END IF
367 kase = 0
368 10 CONTINUE
369 CALL pclacon( n, work( ipv ), iv, jv, descv, work( ipx ),
370 $ ix, jx, descx, ainvnm, kase )
371 IF( kase.NE.0 ) THEN
372 IF( kase.EQ.kase1 ) THEN
373
374
375
376 descx( csrc_ ) = iacol
377 CALL pclatrs( uplo,
'No transpose', diag, normin,
378 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
379 $ descx, scale, rwork( ipn ), work( ipw ) )
380 descx( csrc_ ) = mycol
381 ELSE
382
383
384
385 descx( csrc_ ) = iacol
386 CALL pclatrs( uplo,
'Conjugate transpose', diag, normin,
387 $ n, a, ia, ja, desca, work( ipx ), ix, jx,
388 $ descx, scale, rwork( ipn ), work( ipw ) )
389 descx( csrc_ ) = mycol
390 END IF
391 normin = 'Y'
392
393
394
395 IF( scale.NE.one ) THEN
396 CALL pcamax( n, wmax, ixx, work( ipx ), ix, jx,
397 $ descx, 1 )
398 IF( descx( m_ ).EQ.1 .AND. n.EQ.1 ) THEN
399 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise',
400 $ cbtop )
401 IF( myrow.EQ.iarow ) THEN
402 CALL cgebs2d( ictxt, 'Column', cbtop, 1, 1, wmax,
403 $ 1 )
404 ELSE
405 CALL cgebr2d( ictxt, 'Column', cbtop, 1, 1, wmax,
406 $ 1, iarow, mycol )
407 END IF
408 END IF
409 IF( scale.LT.cabs1( wmax )*smlnum .OR. scale.EQ.zero )
410 $ GO TO 20
411 CALL pcsrscl( n, scale, work( ipx ), ix, jx, descx, 1 )
412 END IF
413 GO TO 10
414 END IF
415
416
417
418 IF( ainvnm.NE.zero )
419 $ rcond = ( one / anorm ) / ainvnm
420 END IF
421
422 20 CONTINUE
423
424 CALL pb_topset( ictxt, 'Combine', 'Columnwise', colctop )
425 CALL pb_topset( ictxt, 'Combine', 'Rowwise', rowctop )
426
427 RETURN
428
429
430
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)
real function pslamch(ictxt, cmach)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
subroutine pclacon(n, v, iv, jv, descv, x, ix, jx, descx, est, kase)
real function pclantr(norm, uplo, diag, m, n, a, ia, ja, desca, work)
subroutine pclatrs(uplo, trans, diag, normin, n, a, ia, ja, desca, x, ix, jx, descx, scale, cnorm, work)
subroutine pcsrscl(n, sa, sx, ix, jx, descx, incx)
subroutine pxerbla(ictxt, srname, info)