5
6
7
8
9
10
11
12 CHARACTER EQUED, FACT, TRANS
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( * ),
19 $ DESCX( * ), IPIV( * )
20 REAL BERR( * ), C( * ), FERR( * ), R( * ),
21 $ RWORK( * )
22 COMPLEX A( * ), AF( * ), 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
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
409 $ LLD_, MB_, M_, NB_, N_, RSRC_
410 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
411 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
412 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
413 REAL ONE, ZERO
414 parameter( one = 1.0e+0, zero = 0.0e+0 )
415
416
417 LOGICAL COLEQU, EQUIL, LQUERY, NOFACT, NOTRAN, ROWEQU
418 CHARACTER NORM
419 INTEGER CONWRK, I, IACOL, IAROW, IAFROW, IBROW, IBCOL,
420 $ ICOFFA, ICOFFB, ICOFFX, ICTXT, IDUMM,
421 $ IIA, IIB, IIX,
422 $ INFEQU, IROFFA, IROFFAF, IROFFB,
423 $ IROFFX, IXCOL, IXROW, J, JJA, JJB, JJX,
424 $ LCM, LCMQ,
425 $ LRWMIN, LWMIN, MYCOL, MYROW, NP, NPCOL, NPROW,
426 $ NQ, NQB, NRHSQ, RFSWRK
427 REAL AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,
428 $ ROWCND, SMLNUM
429
430
431 INTEGER CDESC( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
432
433
438 $ sgebs2d, sgamn2d, sgamx2d
439
440
441 LOGICAL LSAME
442 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
443 REAL PSLAMCH, PCLANGE
446
447
448 INTRINSIC ichar,
max,
min, mod, real
449
450
451
452
453
454 ictxt = desca( ctxt_ )
455 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
456
457
458
459 info = 0
460 IF( nprow.EQ.-1 ) THEN
461 info = -(800+ctxt_)
462 ELSE
463 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
464 IF(
lsame( fact,
'F' ) )
465 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
466 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
467 CALL chk1mat( n, 3, nrhs, 4, ix, jx, descx, 24, info )
468 nofact =
lsame( fact,
'N' )
469 equil =
lsame( fact,
'E' )
470 notran =
lsame( trans,
'N' )
471 IF( nofact .OR. equil ) THEN
472 equed = 'N'
473 rowequ = .false.
474 colequ = .false.
475 ELSE
476 rowequ =
lsame( equed,
'R' ) .OR.
lsame( equed,
'B' )
477 colequ =
lsame( equed,
'C' ) .OR.
lsame( equed,
'B' )
478 smlnum =
pslamch( ictxt,
'Safe minimum' )
479 bignum = one / smlnum
480 END IF
481 IF( info.EQ.0 ) THEN
482 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
483 $ nprow )
484 iafrow =
indxg2p( iaf, descaf( mb_ ), myrow,
485 $ descaf( rsrc_ ), nprow )
486 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
487 $ nprow )
488 ixrow =
indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
489 $ nprow )
490 iroffa = mod( ia-1, desca( mb_ ) )
491 iroffaf = mod( iaf-1, descaf( mb_ ) )
492 icoffa = mod( ja-1, desca( nb_ ) )
493 iroffb = mod( ib-1, descb( mb_ ) )
494 icoffb = mod( jb-1, descb( nb_ ) )
495 iroffx = mod( ix-1, descx( mb_ ) )
496 icoffx = mod( jx-1, descx( nb_ ) )
497 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
498 $ mycol, iia, jja, iarow, iacol )
499 np =
numroc( n+iroffa, desca( mb_ ), myrow, iarow,
500 $ nprow )
501 IF( myrow.EQ.iarow )
502 $ np = np-iroffa
503 nq =
numroc( n+icoffa, desca( nb_ ), mycol, iacol,
504 $ npcol )
505 IF( mycol.EQ.iacol )
506 $ nq = nq-icoffa
507 nqb =
iceil( n+iroffa, desca( nb_ )*npcol )
508 lcm =
ilcm( nprow, npcol )
509 lcmq = lcm / npcol
510 conwrk = 2*np + 2*nq +
max( 2,
max( desca( nb_ )*
511 $
max( 1,
iceil( nprow-1, npcol ) ), nq +
512 $ desca( nb_ )*
513 $
max( 1,
iceil( npcol-1, nprow ) ) ) )
514 rfswrk = 3*np
515 IF(
lsame( trans,
'N' ) )
THEN
516 rfswrk = rfswrk + np + nq +
517 $
iceil( nqb, lcmq )*desca( nb_ )
518 ELSE IF(
lsame( trans,
'T' ).OR.
lsame( trans,
'C' ) )
THEN
519 rfswrk = rfswrk + np + nq
520 END IF
521 lwmin =
max( conwrk, rfswrk )
522 lrwmin =
max( 2*nq, np )
523 rwork( 1 ) = real( lrwmin )
524 IF( .NOT.nofact .AND. .NOT.equil .AND.
525 $ .NOT.
lsame( fact,
'F' ) )
THEN
526 info = -1
527 ELSE IF( .NOT.notran .AND. .NOT.
lsame( trans,
'T' ) .AND.
528 $ .NOT.
lsame( trans,
'C' ) )
THEN
529 info = -2
530 ELSE IF( iroffa.NE.0 ) THEN
531 info = -6
532 ELSE IF( icoffa.NE.0 .OR. iroffa.NE.icoffa ) THEN
533 info = -7
534 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
535 info = -(800+nb_)
536 ELSE IF( iafrow.NE.iarow ) THEN
537 info = -10
538 ELSE IF( iroffaf.NE.0 ) THEN
539 info = -10
540 ELSE IF( ictxt.NE.descaf( ctxt_ ) ) THEN
541 info = -(1200+ctxt_)
542 ELSE IF(
lsame( fact,
'F' ) .AND. .NOT.
543 $ ( rowequ .OR. colequ .OR.
lsame( equed,
'N' ) ) )
THEN
544 info = -13
545 ELSE
546 IF( rowequ ) THEN
547 rcmin = bignum
548 rcmax = zero
549 DO 10 j = iia, iia + np - 1
550 rcmin =
min( rcmin, r( j ) )
551 rcmax =
max( rcmax, r( j ) )
552 10 CONTINUE
553 CALL sgamn2d( ictxt, 'Columnwise', ' ', 1, 1, rcmin,
554 $ 1, idumm, idumm, -1, -1, mycol )
555 CALL sgamx2d( ictxt, 'Columnwise', ' ', 1, 1, rcmax,
556 $ 1, idumm, idumm, -1, -1, mycol )
557 IF( rcmin.LE.zero ) THEN
558 info = -14
559 ELSE IF( n.GT.0 ) THEN
560 rowcnd =
max( rcmin, smlnum ) /
561 $
min( rcmax, bignum )
562 ELSE
563 rowcnd = one
564 END IF
565 END IF
566 IF( colequ .AND. info.EQ.0 ) THEN
567 rcmin = bignum
568 rcmax = zero
569 DO 20 j = jja, jja+nq-1
570 rcmin =
min( rcmin, c( j ) )
571 rcmax =
max( rcmax, c( j ) )
572 20 CONTINUE
573 CALL sgamn2d( ictxt, 'Rowwise', ' ', 1, 1, rcmin,
574 $ 1, idumm, idumm, -1, -1, mycol )
575 CALL sgamx2d( ictxt, 'Rowwise', ' ', 1, 1, rcmax,
576 $ 1, idumm, idumm, -1, -1, mycol )
577 IF( rcmin.LE.zero ) THEN
578 info = -15
579 ELSE IF( n.GT.0 ) THEN
580 colcnd =
max( rcmin, smlnum ) /
581 $
min( rcmax, bignum )
582 ELSE
583 colcnd = one
584 END IF
585 END IF
586 END IF
587 END IF
588
589 work( 1 ) = real( lwmin )
590 rwork( 1 ) = real( lrwmin )
591 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
592 IF( info.EQ.0 ) THEN
593 IF( ibrow.NE.iarow ) THEN
594 info = -18
595 ELSE IF( ixrow.NE.ibrow ) THEN
596 info = -22
597 ELSE IF( descb( mb_ ).NE.desca( nb_ ) ) THEN
598 info = -(2000+nb_)
599 ELSE IF( ictxt.NE.descb( ctxt_ ) ) THEN
600 info = -(2000+ctxt_)
601 ELSE IF( descx( mb_ ).NE.desca( nb_ ) ) THEN
602 info = -(2400+nb_)
603 ELSE IF( ictxt.NE.descx( ctxt_ ) ) THEN
604 info = -(2400+ctxt_)
605 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
606 info = -29
607 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
608 info = -31
609 END IF
610 idum1( 1 ) = ichar( fact )
611 idum2( 1 ) = 1
612 idum1( 2 ) = ichar( trans )
613 idum2( 2 ) = 2
614 IF(
lsame( fact,
'F' ) )
THEN
615 idum1( 3 ) = ichar( equed )
616 idum2( 3 ) = 14
617 IF( lwork.EQ.-1 ) THEN
618 idum1( 4 ) = -1
619 ELSE
620 idum1( 4 ) = 1
621 END IF
622 idum2( 4 ) = 29
623 IF( lrwork.EQ.-1 ) THEN
624 idum1( 5 ) = -1
625 ELSE
626 idum1( 5 ) = 1
627 END IF
628 idum2( 5 ) = 31
629 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3,
630 $ nrhs, 4, ib, jb, descb, 20, 5, idum1,
631 $ idum2, info )
632 ELSE
633 IF( lwork.EQ.-1 ) THEN
634 idum1( 3 ) = -1
635 ELSE
636 idum1( 3 ) = 1
637 END IF
638 idum2( 3 ) = 29
639 IF( lrwork.EQ.-1 ) THEN
640 idum1( 4 ) = -1
641 ELSE
642 idum1( 4 ) = 1
643 END IF
644 idum2( 4 ) = 31
645 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3,
646 $ nrhs, 4, ib, jb, descb, 20, 4, idum1,
647 $ idum2, info )
648 END IF
649 END IF
650 END IF
651
652 IF( info.NE.0 ) THEN
653 CALL pxerbla( ictxt,
'PCGESVX', -info )
654 RETURN
655 ELSE IF( lquery ) THEN
656 RETURN
657 END IF
658
659 IF( equil ) THEN
660
661
662
663 CALL pcgeequ( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
664 $ amax, infequ )
665 IF( infequ.EQ.0 ) THEN
666
667
668
669 CALL pclaqge( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
670 $ amax, equed )
671 rowequ =
lsame( equed,
'R' ) .OR.
lsame( equed,
'B' )
672 colequ =
lsame( equed,
'C' ) .OR.
lsame( equed,
'B' )
673 END IF
674 END IF
675
676
677
678 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol, iib,
679 $ jjb, ibrow, ibcol )
680 np =
numroc( n+iroffb, descb( mb_ ), myrow, ibrow, nprow )
681 nrhsq =
numroc( nrhs+icoffb, descb( nb_ ), mycol, ibcol, npcol )
682 IF( myrow.EQ.ibrow )
683 $ np = np-iroffb
684 IF( mycol.EQ.ibcol )
685 $ nrhsq = nrhsq-icoffb
686
687 IF( notran ) THEN
688 IF( rowequ ) THEN
689 DO 40 j = jjb, jjb+nrhsq-1
690 DO 30 i = iib, iib+np-1
691 b( i+( j-1 )*descb( lld_ ) ) = r( i )*
692 $ b( i+( j-1 )*descb( lld_ ) )
693 30 CONTINUE
694 40 CONTINUE
695 END IF
696 ELSE IF( colequ ) THEN
697
698
699
700 CALL descset( cdesc, 1, n+icoffa, 1, desca( nb_ ), myrow,
701 $ iacol, ictxt, 1 )
702 CALL pscopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ib, jb,
703 $ descb, 1 )
704 IF( mycol.EQ.ibcol ) THEN
705 CALL sgebs2d( ictxt, 'Rowwise', ' ', np, 1, rwork( iib ),
706 $ descb( lld_ ) )
707 ELSE
708 CALL sgebr2d( ictxt, 'Rowwise', ' ', np, 1, rwork( iib ),
709 $ descb( lld_ ), myrow, ibcol )
710 END IF
711 DO 60 j = jjb, jjb+nrhsq-1
712 DO 50 i = iib, iib+np-1
713 b( i+( j-1 )*descb( lld_ ) ) = rwork( i )*
714 $ b( i+( j-1 )*descb( lld_ ) )
715 50 CONTINUE
716 60 CONTINUE
717 END IF
718
719 IF( nofact.OR.equil ) THEN
720
721
722
723 CALL pclacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
724 $ descaf )
725 CALL pcgetrf( n, n, af, iaf, jaf, descaf, ipiv, info )
726
727
728
729 IF( info.NE.0 ) THEN
730 IF( info.GT.0 )
731 $ rcond = zero
732 RETURN
733 END IF
734 END IF
735
736
737
738 IF( notran ) THEN
739 norm = '1'
740 ELSE
741 norm = 'I'
742 END IF
743 anorm =
pclange( norm, n, n, a, ia, ja, desca, rwork )
744
745
746
747 CALL pcgecon( norm, n, af, iaf, jaf, descaf, anorm, rcond, work,
748 $ lwork, rwork, lrwork, info )
749
750
751
752 IF( rcond.LT.
pslamch( ictxt,
'Epsilon' ) )
THEN
753 info = ia + n
754 RETURN
755 END IF
756
757
758
759 CALL pclacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
760 $ descx )
761 CALL pcgetrs( trans, n, nrhs, af, iaf, jaf, descaf, ipiv, x, ix,
762 $ jx, descx, info )
763
764
765
766
767 CALL pcgerfs( trans, n, nrhs, a, ia, ja, desca, af, iaf, jaf,
768 $ descaf, ipiv, b, ib, jb, descb, x, ix, jx, descx,
769 $ ferr, berr, work, lwork, rwork, lrwork, info )
770
771
772
773
774 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix,
775 $ jjx, ixrow, ixcol )
776 np =
numroc( n+iroffx, descx( mb_ ), myrow, ixrow, nprow )
777 nrhsq =
numroc( nrhs+icoffx, descx( nb_ ), mycol, ixcol, npcol )
778 IF( myrow.EQ.ibrow )
779 $ np = np-iroffx
780 IF( mycol.EQ.ibcol )
781 $ nrhsq = nrhsq-icoffx
782
783 IF( notran ) THEN
784 IF( colequ ) THEN
785
786
787
788 CALL descset( cdesc, 1, n+icoffa, 1, desca( nb_ ), myrow,
789 $ iacol, ictxt, 1 )
790 CALL pscopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ix,
791 $ jx, descx, 1 )
792 IF( mycol.EQ.ibcol ) THEN
793 CALL sgebs2d( ictxt, 'Rowwise', ' ', np, 1,
794 $ rwork( iix ), descx( lld_ ) )
795 ELSE
796 CALL sgebr2d( ictxt, 'Rowwise', ' ', np, 1,
797 $ rwork( iix ), descx( lld_ ), myrow,
798 $ ibcol )
799 END IF
800
801 DO 80 j = jjx, jjx+nrhsq-1
802 DO 70 i = iix, iix+np-1
803 x( i+( j-1 )*descx( lld_ ) ) = rwork( i )*
804 $ x( i+( j-1 )*descx( lld_ ) )
805 70 CONTINUE
806 80 CONTINUE
807 DO 90 j = jjx, jjx+nrhsq-1
808 ferr( j ) = ferr( j ) / colcnd
809 90 CONTINUE
810 END IF
811 ELSE IF( rowequ ) THEN
812 DO 110 j = jjx, jjx+nrhsq-1
813 DO 100 i = iix, iix+np-1
814 x( i+( j-1 )*descx( lld_ ) ) = r( i )*
815 $ x( i+( j-1 )*descx( lld_ ) )
816 100 CONTINUE
817 110 CONTINUE
818 DO 120 j = jjx, jjx+nrhsq-1
819 ferr( j ) = ferr( j ) / rowcnd
820 120 CONTINUE
821 END IF
822
823 work( 1 ) = real( lwmin )
824 rwork( 1 ) = real( lrwmin )
825
826 RETURN
827
828
829
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 ilcm(m, n)
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 pcgecon(norm, n, a, ia, ja, desca, anorm, rcond, work, lwork, rwork, lrwork, info)
subroutine pcgeequ(m, n, a, ia, ja, desca, r, c, rowcnd, colcnd, amax, info)
subroutine pcgerfs(trans, n, nrhs, a, ia, ja, desca, af, iaf, jaf, descaf, ipiv, b, ib, jb, descb, x, ix, jx, descx, ferr, berr, work, lwork, rwork, lrwork, info)
subroutine pcgetrf(m, n, a, ia, ja, desca, ipiv, info)
subroutine pcgetrs(trans, n, nrhs, a, ia, ja, desca, ipiv, b, ib, jb, descb, info)
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 pclange(norm, m, n, a, ia, ja, desca, work)
subroutine pclaqge(m, n, a, ia, ja, desca, r, c, rowcnd, colcnd, amax, equed)
subroutine pxerbla(ictxt, srname, info)