5
6
7
8
9
10
11
12 CHARACTER EQUED, FACT, UPLO
13 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX, LRWORK,
14 $ LWORK, N, NRHS
15 REAL RCOND
16
17
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ), DESCX( * )
19 REAL BERR( * ), FERR( * ), SC( * ),
20 $ SR( * ), RWORK( * )
21 COMPLEX A( * ), AF( * ),
22 $ B( * ), WORK( * ), X( * )
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
353 $ LLD_, MB_, M_, NB_, N_, RSRC_
354 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
355 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
356 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
357 REAL ONE, ZERO
358 parameter( one = 1.0e+0, zero = 0.0e+0 )
359
360
361 LOGICAL EQUIL, LQUERY, NOFACT, RCEQU
362 INTEGER I, IACOL, IAROW, IAFROW, IBROW, IBCOL, ICOFF,
363 $ ICOFFA, ICTXT, IDUMM, IIA, IIB, IIX, INFEQU,
364 $ IROFF, IROFFA, IROFFAF, IROFFB, IROFFX, IXCOL,
365 $ IXROW, J, JJA, JJB, JJX, LDB, LDX, LRWMIN,
366 $ LWMIN, MYCOL, MYROW, NP, NPCOL, NPROW, NRHSQ,
367 $ NQ
368 REAL AMAX, ANORM, BIGNUM, SCOND, SMAX, SMIN, SMLNUM
369
370
371 INTEGER IDUM1( 5 ), IDUM2( 5 )
372
373
378 $ sgamn2d, sgamx2d
379
380
381 LOGICAL LSAME
382 INTEGER INDXG2P, NUMROC
383 REAL PCLANHE, PSLAMCH
385
386
387 INTRINSIC ichar,
max,
min, mod
388
389
390
391
392
393 ictxt = desca( ctxt_ )
394 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
395
396
397
398 info = 0
399 IF( nprow.EQ.-1 ) THEN
400 info = -(800+ctxt_)
401 ELSE
402 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
403 IF(
lsame( fact,
'F' ) )
404 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
405 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
406 IF( info.EQ.0 ) THEN
407 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
408 $ nprow )
409 iafrow =
indxg2p( iaf, descaf( mb_ ), myrow,
410 $ descaf( rsrc_ ), nprow )
411 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
412 $ nprow )
413 ixrow =
indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
414 $ nprow )
415 iroffa = mod( ia-1, desca( mb_ ) )
416 iroffaf = mod( iaf-1, descaf( mb_ ) )
417 icoffa = mod( ja-1, desca( nb_ ) )
418 iroffb = mod( ib-1, descb( mb_ ) )
419 iroffx = mod( ix-1, descx( mb_ ) )
420 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
421 $ mycol, iia, jja, iarow, iacol )
422 np =
numroc( n+iroffa, desca( mb_ ), myrow, iarow, nprow )
423 IF( myrow.EQ.iarow )
424 $ np = np-iroffa
425 nq =
numroc( n+icoffa, desca( nb_ ), mycol, iacol, npcol )
426 IF( mycol.EQ.iacol )
427 $ nq = nq-icoffa
428 lwmin = 3*desca( lld_ )
429 lrwmin =
max( 2*nq, np )
430 nofact =
lsame( fact,
'N' )
431 equil =
lsame( fact,
'E' )
432 IF( nofact .OR. equil ) THEN
433 equed = 'N'
434 rcequ = .false.
435 ELSE
436 rcequ =
lsame( equed,
'Y' )
437 smlnum =
pslamch( ictxt,
'Safe minimum' )
438 bignum = one / smlnum
439 END IF
440 IF( .NOT.nofact .AND. .NOT.equil .AND.
441 $ .NOT.
lsame( fact,
'F' ) )
THEN
442 info = -1
443 ELSE IF( .NOT.
lsame( uplo,
'U' ) .AND.
444 $ .NOT.
lsame( uplo,
'L' ) )
THEN
445 info = -2
446 ELSE IF( iroffa.NE.0 ) THEN
447 info = -6
448 ELSE IF( icoffa.NE.0 .OR. iroffa.NE.icoffa ) THEN
449 info = -7
450 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
451 info = -(800+nb_)
452 ELSE IF( iafrow.NE.iarow ) THEN
453 info = -10
454 ELSE IF( iroffaf.NE.0 ) THEN
455 info = -10
456 ELSE IF( ictxt.NE.descaf( ctxt_ ) ) THEN
457 info = -(1200+ctxt_)
458 ELSE IF(
lsame( fact,
'F' ) .AND. .NOT.
459 $ ( rcequ .OR.
lsame( equed,
'N' ) ) )
THEN
460 info = -13
461 ELSE
462 IF( rcequ ) THEN
463
464 smin = bignum
465 smax = zero
466 DO 10 j = iia, iia + np - 1
467 smin =
min( smin, sr( j ) )
468 smax =
max( smax, sr( j ) )
469 10 CONTINUE
470 CALL sgamn2d( ictxt, 'Columnwise', ' ', 1, 1, smin,
471 $ 1, idumm, idumm, -1, -1, mycol )
472 CALL sgamx2d( ictxt, 'Columnwise', ' ', 1, 1, smax,
473 $ 1, idumm, idumm, -1, -1, mycol )
474 IF( smin.LE.zero ) THEN
475 info = -14
476 ELSE IF( n.GT.0 ) THEN
477 scond =
max( smin, smlnum ) /
min( smax, bignum )
478 ELSE
479 scond = one
480 END IF
481 END IF
482 END IF
483 END IF
484
485 work( 1 ) = real( lwmin )
486 rwork( 1 ) = real( lrwmin )
487 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
488 IF( info.EQ.0 ) THEN
489 IF( ibrow.NE.iarow ) THEN
490 info = -18
491 ELSE IF( ixrow.NE.ibrow ) THEN
492 info = -22
493 ELSE IF( descb( mb_ ).NE.desca( nb_ ) ) THEN
494 info = -(2000+nb_)
495 ELSE IF( ictxt.NE.descb( ctxt_ ) ) THEN
496 info = -(2000+ctxt_)
497 ELSE IF( ictxt.NE.descx( ctxt_ ) ) THEN
498 info = -(2400+ctxt_)
499 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
500 info = -28
501 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
502 info = -30
503 END IF
504 idum1( 1 ) = ichar( fact )
505 idum2( 1 ) = 1
506 idum1( 2 ) = ichar( uplo )
507 idum2( 2 ) = 2
508 IF(
lsame( fact,
'F' ) )
THEN
509 idum1( 3 ) = ichar( equed )
510 idum2( 3 ) = 13
511 IF( lwork.EQ.-1 ) THEN
512 idum1( 4 ) = -1
513 ELSE
514 idum1( 4 ) = 1
515 END IF
516 idum2( 4 ) = 28
517 IF( lrwork.EQ.-1 ) THEN
518 idum1( 5 ) = -1
519 ELSE
520 idum1( 5 ) = 1
521 END IF
522 idum2( 5 ) = 30
523 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3, nrhs,
524 $ 4, ib, jb, descb, 19, 5, idum1, idum2,
525 $ info )
526 ELSE
527 IF( lwork.EQ.-1 ) THEN
528 idum1( 3 ) = -1
529 ELSE
530 idum1( 3 ) = 1
531 END IF
532 idum2( 3 ) = 28
533 IF( lrwork.EQ.-1 ) THEN
534 idum1( 4 ) = -1
535 ELSE
536 idum1( 4 ) = 1
537 END IF
538 idum2( 4 ) = 30
539 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3, nrhs,
540 $ 4, ib, jb, descb, 19, 4, idum1, idum2,
541 $ info )
542 END IF
543 END IF
544 END IF
545
546 IF( info.NE.0 ) THEN
547 CALL pxerbla( ictxt,
'PCPOSVX', -info )
548 RETURN
549 ELSE IF( lquery ) THEN
550 RETURN
551 END IF
552
553 IF( equil ) THEN
554
555
556
557 CALL pcpoequ( n, a, ia, ja, desca, sr, sc, scond, amax,
558 $ infequ )
559
560 IF( infequ.EQ.0 ) THEN
561
562
563
564 CALL pclaqsy( uplo, n, a, ia, ja, desca, sr, sc, scond,
565 $ amax, equed )
566 rcequ =
lsame( equed,
'Y' )
567 END IF
568 END IF
569
570
571
572 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol, iib,
573 $ jjb, ibrow, ibcol )
574 ldb = descb( lld_ )
575 iroff = mod( ib-1, descb( mb_ ) )
576 icoff = mod( jb-1, descb( nb_ ) )
577 np =
numroc( n+iroff, descb( mb_ ), myrow, ibrow, nprow )
578 nrhsq =
numroc( nrhs+icoff, descb( nb_ ), mycol, ibcol, npcol )
579 IF( myrow.EQ.ibrow ) np = np-iroff
580 IF( mycol.EQ.ibcol ) nrhsq = nrhsq-icoff
581
582 IF( rcequ ) THEN
583 DO 30 j = jjb, jjb+nrhsq-1
584 DO 20 i = iib, iib+np-1
585 b( i + ( j-1 )*ldb ) = sr( i )*b( i + ( j-1 )*ldb )
586 20 CONTINUE
587 30 CONTINUE
588 END IF
589
590 IF( nofact .OR. equil ) THEN
591
592
593
594 CALL pclacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
595 $ descaf )
596 CALL pcpotrf( uplo, n, af, iaf, jaf, descaf, info )
597
598
599
600 IF( info.NE.0 ) THEN
601 IF( info.GT.0 )
602 $ rcond = zero
603 RETURN
604 END IF
605 END IF
606
607
608
609 anorm =
pclanhe(
'1', uplo, n, a, ia, ja, desca, rwork )
610
611
612
613 CALL pcpocon( uplo, n, af, iaf, jaf, descaf, anorm, rcond, work,
614 $ lwork, rwork, lrwork, info )
615
616
617
618 IF( rcond.LT.
pslamch( ictxt,
'Epsilon' ) )
THEN
619 info = ia + n
620 RETURN
621 END IF
622
623
624
625 CALL pclacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
626 $ descx )
627 CALL pcpotrs( uplo, n, nrhs, af, iaf, jaf, descaf, x, ix, jx,
628 $ descx, info )
629
630
631
632
633 CALL pcporfs( uplo, n, nrhs, a, ia, ja, desca, af, iaf, jaf,
634 $ descaf, b, ib, jb, descb, x, ix, jx, descx, ferr,
635 $ berr, work, lwork, rwork, lrwork, info )
636
637
638
639
640 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix,
641 $ jjx, ixrow, ixcol )
642 ldx = descx( lld_ )
643 iroff = mod( ix-1, descx( mb_ ) )
644 icoff = mod( jx-1, descx( nb_ ) )
645 np =
numroc( n+iroff, descx( mb_ ), myrow, ixrow, nprow )
646 nrhsq =
numroc( nrhs+icoff, descx( nb_ ), mycol, ixcol, npcol )
647 IF( myrow.EQ.ibrow ) np = np-iroff
648 IF( mycol.EQ.ibcol ) nrhsq = nrhsq-icoff
649
650 IF( rcequ ) THEN
651 DO 50 j = jjx, jjx+nrhsq-1
652 DO 40 i = iix, iix+np-1
653 x( i + ( j-1 )*ldx ) = sr( i )*x( i + ( j-1 )*ldx )
654 40 CONTINUE
655 50 CONTINUE
656 DO 60 j = jjx, jjx+nrhsq-1
657 ferr( j ) = ferr( j ) / scond
658 60 CONTINUE
659 END IF
660
661 work( 1 ) = real( lwmin )
662 rwork( 1 ) = real( lrwmin )
663 RETURN
664
665
666
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
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 pchk2mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, mb, mbpos0, nb, nbpos0, ib, jb, descb, descbpos0, nextra, ex, expos, info)
subroutine pclacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
real function pclanhe(norm, uplo, n, a, ia, ja, desca, work)
subroutine pclaqsy(uplo, n, a, ia, ja, desca, sr, sc, scond, amax, equed)
subroutine pcpocon(uplo, n, a, ia, ja, desca, anorm, rcond, work, lwork, rwork, lrwork, info)
subroutine pcpoequ(n, a, ia, ja, desca, sr, sc, scond, amax, info)
subroutine pcporfs(uplo, n, nrhs, a, ia, ja, desca, af, iaf, jaf, descaf, b, ib, jb, descb, x, ix, jx, descx, ferr, berr, work, lwork, rwork, lrwork, info)
subroutine pcpotrf(uplo, n, a, ia, ja, desca, info)
subroutine pcpotrs(uplo, n, nrhs, a, ia, ja, desca, b, ib, jb, descb, info)
subroutine pxerbla(ictxt, srname, info)