5
6
7
8
9
10
11
12 CHARACTER EQUED, FACT, TRANS
13 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX, LIWORK,
14 $ LWORK, N, NRHS
15 DOUBLE PRECISION RCOND
16
17
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
19 $ DESCX( * ), IPIV( * ), IWORK( * )
20 DOUBLE PRECISION A( * ), AF( * ), B( * ), BERR( * ), C( * ),
21 $ FERR( * ), R( * ), WORK( * ), X( * )
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
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
408 $ LLD_, MB_, M_, NB_, N_, RSRC_
409 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
410 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
411 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
412 DOUBLE PRECISION ONE, ZERO
413 parameter( one = 1.0d+0, zero = 0.0d+0 )
414
415
416 LOGICAL COLEQU, EQUIL, LQUERY, NOFACT, NOTRAN, ROWEQU
417 CHARACTER NORM
418 INTEGER CONWRK, I, IACOL, IAROW, IAFROW, IBROW, IBCOL,
419 $ ICOFFA, ICOFFB, ICOFFX, ICTXT, IDUMM,
420 $ IIA, IIB, IIX,
421 $ INFEQU, IROFFA, IROFFAF, IROFFB,
422 $ IROFFX, IXCOL, IXROW, J, JJA, JJB, JJX,
423 $ LCM, LCMQ,
424 $ LIWMIN, LWMIN, MYCOL, MYROW, NP, NPCOL, NPROW,
425 $ NQ, NQB, NRHSQ, RFSWRK
426 DOUBLE PRECISION AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,
427 $ ROWCND, SMLNUM
428
429
430 INTEGER CDESC( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
431
432
434 $ dgebr2d, dgebs2d, dgamn2d,
438
439
440 LOGICAL LSAME
441 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
442 DOUBLE PRECISION PDLAMCH, PDLANGE
445
446
447 INTRINSIC dble, ichar,
max,
min, mod
448
449
450
451
452
453 ictxt = desca( ctxt_ )
454 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
455
456
457
458 info = 0
459 IF( nprow.EQ.-1 ) THEN
460 info = -(800+ctxt_)
461 ELSE
462 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
463 IF(
lsame( fact,
'F' ) )
464 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
465 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
466 CALL chk1mat( n, 3, nrhs, 4, ix, jx, descx, 24, info )
467 nofact =
lsame( fact,
'N' )
468 equil =
lsame( fact,
'E' )
469 notran =
lsame( trans,
'N' )
470 IF( nofact .OR. equil ) THEN
471 equed = 'N'
472 rowequ = .false.
473 colequ = .false.
474 ELSE
475 rowequ =
lsame( equed,
'R' ) .OR.
lsame( equed,
'B' )
476 colequ =
lsame( equed,
'C' ) .OR.
lsame( equed,
'B' )
477 smlnum =
pdlamch( ictxt,
'Safe minimum' )
478 bignum = one / smlnum
479 END IF
480 IF( info.EQ.0 ) THEN
481 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
482 $ nprow )
483 iafrow =
indxg2p( iaf, descaf( mb_ ), myrow,
484 $ descaf( rsrc_ ), nprow )
485 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
486 $ nprow )
487 ixrow =
indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
488 $ nprow )
489 iroffa = mod( ia-1, desca( mb_ ) )
490 iroffaf = mod( iaf-1, descaf( mb_ ) )
491 icoffa = mod( ja-1, desca( nb_ ) )
492 iroffb = mod( ib-1, descb( mb_ ) )
493 icoffb = mod( jb-1, descb( nb_ ) )
494 iroffx = mod( ix-1, descx( mb_ ) )
495 icoffx = mod( jx-1, descx( nb_ ) )
496 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
497 $ mycol, iia, jja, iarow, iacol )
498 np =
numroc( n+iroffa, desca( mb_ ), myrow, iarow,
499 $ nprow )
500 IF( myrow.EQ.iarow )
501 $ np = np-iroffa
502 nq =
numroc( n+icoffa, desca( nb_ ), mycol, iacol,
503 $ npcol )
504 IF( mycol.EQ.iacol )
505 $ nq = nq-icoffa
506 nqb =
iceil( n+iroffa, desca( nb_ )*npcol )
507 lcm =
ilcm( nprow, npcol )
508 lcmq = lcm / npcol
509 conwrk = 2*np + 2*nq +
max( 2,
max( desca( nb_ )*
510 $
max( 1,
iceil( nprow-1, npcol ) ), nq +
511 $ desca( nb_ )*
512 $
max( 1,
iceil( npcol-1, nprow ) ) ) )
513 rfswrk = 3*np
514 IF(
lsame( trans,
'N' ) )
THEN
515 rfswrk = rfswrk + np + nq +
516 $
iceil( nqb, lcmq )*desca( nb_ )
517 ELSE IF(
lsame( trans,
'T' ).OR.
lsame( trans,
'C' ) )
THEN
518 rfswrk = rfswrk + np + nq
519 END IF
520 lwmin =
max( conwrk, rfswrk )
521 work( 1 ) = dble( lwmin )
522 liwmin = np
523 iwork( 1 ) = liwmin
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 dgamn2d( ictxt, 'Columnwise', ' ', 1, 1, rcmin,
554 $ 1, idumm, idumm, -1, -1, mycol )
555 CALL dgamx2d( 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 dgamn2d( ictxt, 'Rowwise', ' ', 1, 1, rcmin,
574 $ 1, idumm, idumm, -1, -1, mycol )
575 CALL dgamx2d( 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 ) = dble( lwmin )
590 iwork( 1 ) = liwmin
591 lquery = ( lwork.EQ.-1 .OR. liwork.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( liwork.LT.liwmin .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( liwork.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( liwork.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,
'PDGESVX', -info )
654 RETURN
655 ELSE IF( lquery ) THEN
656 RETURN
657 END IF
658
659 IF( equil ) THEN
660
661
662
663 CALL pdgeequ( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
664 $ amax, infequ )
665 IF( infequ.EQ.0 ) THEN
666
667
668
669 CALL pdlaqge( 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 pdcopy( n, c, 1, ja, cdesc, cdesc( lld_ ), work, ib, jb,
703 $ descb, 1 )
704 IF( mycol.EQ.ibcol ) THEN
705 CALL dgebs2d( ictxt, 'Rowwise', ' ', np, 1, work( iib ),
706 $ descb( lld_ ) )
707 ELSE
708 CALL dgebr2d( ictxt, 'Rowwise', ' ', np, 1, work( 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_ ) ) = work( 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 pdlacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
724 $ descaf )
725 CALL pdgetrf( 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 =
pdlange( norm, n, n, a, ia, ja, desca, work )
744
745
746
747 CALL pdgecon( norm, n, af, iaf, jaf, descaf, anorm, rcond, work,
748 $ lwork, iwork, liwork, info )
749
750
751
752 IF( rcond.LT.
pdlamch( ictxt,
'Epsilon' ) )
THEN
753 info = ia + n
754 RETURN
755 END IF
756
757
758
759 CALL pdlacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
760 $ descx )
761 CALL pdgetrs( trans, n, nrhs, af, iaf, jaf, descaf, ipiv, x, ix,
762 $ jx, descx, info )
763
764
765
766
767 CALL pdgerfs( 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, iwork, liwork, 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 pdcopy( n, c, 1, ja, cdesc, cdesc( lld_ ), work, ix,
791 $ jx, descx, 1 )
792 IF( mycol.EQ.ibcol ) THEN
793 CALL dgebs2d( ictxt, 'Rowwise', ' ', np, 1,
794 $ work( iix ), descx( lld_ ) )
795 ELSE
796 CALL dgebr2d( ictxt, 'Rowwise', ' ', np, 1,
797 $ work( iix ), descx( lld_ ), myrow, ibcol )
798 END IF
799
800 DO 80 j = jjx, jjx+nrhsq-1
801 DO 70 i = iix, iix+np-1
802 x( i+( j-1 )*descx( lld_ ) ) = work( i )*
803 $ x( i+( j-1 )*descx( lld_ ) )
804 70 CONTINUE
805 80 CONTINUE
806 DO 90 j = jjx, jjx+nrhsq-1
807 ferr( j ) = ferr( j ) / colcnd
808 90 CONTINUE
809 END IF
810 ELSE IF( rowequ ) THEN
811 DO 110 j = jjx, jjx+nrhsq-1
812 DO 100 i = iix, iix+np-1
813 x( i+( j-1 )*descx( lld_ ) ) = r( i )*
814 $ x( i+( j-1 )*descx( lld_ ) )
815 100 CONTINUE
816 110 CONTINUE
817 DO 120 j = jjx, jjx+nrhsq-1
818 ferr( j ) = ferr( j ) / rowcnd
819 120 CONTINUE
820 END IF
821
822 work( 1 ) = dble( lwmin )
823 iwork( 1 ) = liwmin
824
825 RETURN
826
827
828
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)
subroutine pchk2mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, mb, mbpos0, nb, nbpos0, ib, jb, descb, descbpos0, nextra, ex, expos, info)
double precision function pdlamch(ictxt, cmach)
subroutine pdgecon(norm, n, a, ia, ja, desca, anorm, rcond, work, lwork, iwork, liwork, info)
subroutine pdgeequ(m, n, a, ia, ja, desca, r, c, rowcnd, colcnd, amax, info)
subroutine pdgerfs(trans, n, nrhs, a, ia, ja, desca, af, iaf, jaf, descaf, ipiv, b, ib, jb, descb, x, ix, jx, descx, ferr, berr, work, lwork, iwork, liwork, info)
subroutine pdgetrf(m, n, a, ia, ja, desca, ipiv, info)
subroutine pdgetrs(trans, n, nrhs, a, ia, ja, desca, ipiv, b, ib, jb, descb, info)
subroutine pdlacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
double precision function pdlange(norm, m, n, a, ia, ja, desca, work)
subroutine pdlaqge(m, n, a, ia, ja, desca, r, c, rowcnd, colcnd, amax, equed)
subroutine pxerbla(ictxt, srname, info)