5
6
7
8
9
10
11
12 CHARACTER TRANS
13 INTEGER IA, IAF, IB, IX, INFO, JA, JAF, JB, JX,
14 $ LIWORK, LWORK, N, NRHS
15
16
17 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
18 $ DESCX( * ),IPIV( * ), IWORK( * )
19 DOUBLE PRECISION A( * ), AF( * ), B( * ), BERR( * ), FERR( * ),
20 $ WORK( * ), X( * )
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
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
262 $ LLD_, MB_, M_, NB_, N_, RSRC_
263 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
264 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
265 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
266 INTEGER ITMAX
267 parameter( itmax = 5 )
268 DOUBLE PRECISION ZERO, ONE
269 parameter( zero = 0.0d+0, one = 1.0d+0 )
270 DOUBLE PRECISION TWO, THREE
271 parameter( two = 2.0d+0, three = 3.0d+0 )
272
273
274 LOGICAL LQUERY, NOTRAN
275 CHARACTER TRANST
276 INTEGER COUNT, IACOL, IAFCOL, IAFROW, IAROW, IXBCOL,
277 $ IXBROW, IXCOL, IXROW, ICOFFA, ICOFFAF, ICOFFB,
278 $ ICOFFX, ICTXT, ICURCOL, IDUM, II, IIXB, IIW,
279 $ IOFFXB, IPB, IPR, IPV, IROFFA, IROFFAF, IROFFB,
280 $ IROFFX, IW, J, JBRHS, JJ, JJFBE, JJXB, JN, JW,
281 $ K, KASE, LDXB, LIWMIN, LWMIN, MYCOL, MYRHS,
282 $ MYROW, NP, NP0, NPCOL, NPMOD, NPROW, NZ
283 DOUBLE PRECISION EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
284
285
286 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
287
288
289 LOGICAL LSAME
290 INTEGER ICEIL, INDXG2P, NUMROC
291 DOUBLE PRECISION PDLAMCH
293
294
297 $ pdagemv, pdaxpy, pdcopy, pdgemv,
299
300
301 INTRINSIC abs, dble, ichar,
max,
min, mod
302
303
304
305
306
307 ictxt = desca( ctxt_ )
308 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
309
310
311
312 notran =
lsame( trans,
'N' )
313
314 info = 0
315 IF( nprow.EQ.-1 ) THEN
316 info = -(700+ctxt_)
317 ELSE
318 CALL chk1mat( n, 2, n, 2, ia, ja, desca, 7, info )
319 CALL chk1mat( n, 2, n, 2, iaf, jaf, descaf, 11, info )
320 CALL chk1mat( n, 2, nrhs, 3, ib, jb, descb, 16, info )
321 CALL chk1mat( n, 2, nrhs, 3, ix, jx, descx, 20, info )
322 IF( info.EQ.0 ) THEN
323 iroffa = mod( ia-1, desca( mb_ ) )
324 icoffa = mod( ja-1, desca( nb_ ) )
325 iroffaf = mod( iaf-1, descaf( mb_ ) )
326 icoffaf = mod( jaf-1, descaf( nb_ ) )
327 iroffb = mod( ib-1, descb( mb_ ) )
328 icoffb = mod( jb-1, descb( nb_ ) )
329 iroffx = mod( ix-1, descx( mb_ ) )
330 icoffx = mod( jx-1, descx( nb_ ) )
331 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
332 $ nprow )
333 iafcol =
indxg2p( jaf, descaf( nb_ ), mycol,
334 $ descaf( csrc_ ), npcol )
335 iafrow =
indxg2p( iaf, descaf( mb_ ), myrow,
336 $ descaf( rsrc_ ), nprow )
337 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
338 $ npcol )
339 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol,
340 $ iixb, jjxb, ixbrow, ixbcol )
341 ixrow =
indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
342 $ nprow )
343 ixcol =
indxg2p( jx, descx( nb_ ), mycol, descx( csrc_ ),
344 $ npcol )
345 npmod =
numroc( n+iroffa, desca( mb_ ), myrow, iarow,
346 $ nprow )
347 lwmin = 3 * npmod
348 liwmin = npmod
349 work( 1 ) = dble( lwmin )
350 iwork( 1 ) = liwmin
351 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
352
353 IF( ( .NOT.notran ) .AND. ( .NOT.
lsame( trans,
'T' ) ) .AND.
354 $ ( .NOT.
lsame( trans,
'C' ) ) )
THEN
355 info = -1
356 ELSE IF( n.LT.0 ) THEN
357 info = -2
358 ELSE IF( nrhs.LT.0 ) THEN
359 info = -3
360 ELSE IF( iroffa.NE.0 ) THEN
361 info = -5
362 ELSE IF( icoffa.NE.0 ) THEN
363 info = -6
364 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
365 info = -( 700 + nb_ )
366 ELSE IF( desca( mb_ ).NE.descaf( mb_ ) ) THEN
367 info = -( 1100 + mb_ )
368 ELSE IF( iroffaf.NE.0 .OR. iarow.NE.iafrow ) THEN
369 info = -9
370 ELSE IF( desca( nb_ ).NE.descaf( nb_ ) ) THEN
371 info = -( 1100 + nb_ )
372 ELSE IF( icoffaf.NE.0 .OR. iacol.NE.iafcol ) THEN
373 info = -10
374 ELSE IF( ictxt.NE.descaf( ctxt_ ) ) THEN
375 info = -( 1100 + ctxt_ )
376 ELSE IF( iroffa.NE.iroffb .OR. iarow.NE.ixbrow ) THEN
377 info = -14
378 ELSE IF( desca( mb_ ).NE.descb( mb_ ) ) THEN
379 info = -( 1600 + mb_ )
380 ELSE IF( ictxt.NE.descb( ctxt_ ) ) THEN
381 info = -( 1600 + ctxt_ )
382 ELSE IF( descb( mb_ ).NE.descx( mb_ ) ) THEN
383 info = -( 2000 + mb_ )
384 ELSE IF( iroffx.NE.0 .OR. ixbrow.NE.ixrow ) THEN
385 info = -18
386 ELSE IF( descb( nb_ ).NE.descx( nb_ ) ) THEN
387 info = -( 2000 + nb_ )
388 ELSE IF( icoffb.NE.icoffx .OR. ixbcol.NE.ixcol ) THEN
389 info = -19
390 ELSE IF( ictxt.NE.descx( ctxt_ ) ) THEN
391 info = -( 2000 + ctxt_ )
392 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
393 info = -24
394 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
395 info = -26
396 END IF
397 END IF
398
399 IF( notran ) THEN
400 idum1( 1 ) = ichar( 'N' )
401 ELSE IF(
lsame( trans,
'T' ) )
THEN
402 idum1( 1 ) = ichar( 'T' )
403 ELSE
404 idum1( 1 ) = ichar( 'C' )
405 END IF
406 idum2( 1 ) = 1
407 idum1( 2 ) = n
408 idum2( 2 ) = 2
409 idum1( 3 ) = nrhs
410 idum2( 3 ) = 3
411 IF( lwork.EQ.-1 ) THEN
412 idum1( 4 ) = -1
413 ELSE
414 idum1( 4 ) = 1
415 END IF
416 idum2( 4 ) = 24
417 IF( liwork.EQ.-1 ) THEN
418 idum1( 5 ) = -1
419 ELSE
420 idum1( 5 ) = 1
421 END IF
422 idum2( 5 ) = 26
423 CALL pchk2mat( n, 2, n, 2, ia, ja, desca, 7, n, 2, n, 2, iaf,
424 $ jaf, descaf, 11, 5, idum1, idum2, info )
425 CALL pchk2mat( n, 2, nrhs, 3, ib, jb, descb, 16, n, 2, nrhs, 3,
426 $ ix, jx, descx, 20, 5, idum1, idum2, info )
427 END IF
428 IF( info.NE.0 ) THEN
429 CALL pxerbla( ictxt,
'PDGERFS', -info )
430 RETURN
431 ELSE IF( lquery ) THEN
432 RETURN
433 END IF
434
435 jjfbe = jjxb
436 myrhs =
numroc( jb+nrhs-1, descb( nb_ ), mycol, descb( csrc_ ),
437 $ npcol )
438
439
440
441 IF( n.LE.1 .OR. nrhs.EQ.0 ) THEN
442 DO 10 jj = jjfbe, myrhs
443 ferr( jj ) = zero
444 berr( jj ) = zero
445 10 CONTINUE
446 RETURN
447 END IF
448
449 IF( notran ) THEN
450 transt = 'T'
451 ELSE
452 transt = 'N'
453 END IF
454
455 np0 =
numroc( n+iroffb, descb( mb_ ), myrow, ixbrow, nprow )
456 CALL descset( descw, n+iroffb, 1, desca( mb_ ), 1, ixbrow, ixbcol,
457 $ ictxt,
max( 1, np0 ) )
458 ipb = 1
459 ipr = ipb + np0
460 ipv = ipr + np0
461 IF( myrow.EQ.ixbrow ) THEN
462 iiw = 1 + iroffb
463 np = np0 - iroffb
464 ELSE
465 iiw = 1
466 np = np0
467 END IF
468 iw = 1 + iroffb
469 jw = 1
470 ldxb = descb( lld_ )
471 ioffxb = ( jjxb-1 )*ldxb
472
473
474
475 nz = n + 1
476 eps =
pdlamch( ictxt,
'Epsilon' )
477 safmin =
pdlamch( ictxt,
'Safe minimum' )
478 safe1 = nz*safmin
479 safe2 = safe1 / eps
480 jn =
min(
iceil( jb, descb( nb_ ) ) * descb( nb_ ), jb+nrhs-1 )
481
482
483
484 jbrhs = jn - jb + 1
485 DO 100 k = 0, jbrhs-1
486
487 count = 1
488 lstres = three
489 20 CONTINUE
490
491
492
493
494
495
496
497 CALL pdcopy( n, b, ib, jb+k, descb, 1, work( ipr ), iw, jw,
498 $ descw, 1 )
499 CALL pdgemv( trans, n, n, -one, a, ia, ja, desca, x, ix,
500 $ jx+k, descx, 1, one, work( ipr ), iw, jw,
501 $ descw, 1 )
502
503
504
505
506
507
508
509
510
511
512
513 IF( mycol.EQ.ixbcol ) THEN
514 IF( np.GT.0 ) THEN
515 DO 30 ii = iixb, iixb + np - 1
516 work( iiw+ii-iixb ) = abs( b( ii+ioffxb ) )
517 30 CONTINUE
518 END IF
519 END IF
520
521 CALL pdagemv( trans, n, n, one, a, ia, ja, desca, x, ix, jx+k,
522 $ descx, 1, one, work( ipb ), iw, jw, descw, 1 )
523
524 s = zero
525 IF( mycol.EQ.ixbcol ) THEN
526 IF( np.GT.0 ) THEN
527 DO 40 ii = iiw-1, iiw+np-2
528 IF( work( ipb+ii ).GT.safe2 ) THEN
529 s =
max( s, abs( work( ipr+ii ) ) /
530 $ work( ipb+ii ) )
531 ELSE
532 s =
max( s, ( abs( work( ipr+ii ) )+safe1 ) /
533 $ ( work( ipb+ii )+safe1 ) )
534 END IF
535 40 CONTINUE
536 END IF
537 END IF
538
539 CALL dgamx2d( ictxt, 'All', ' ', 1, 1, s, 1, idum, idum, 1,
540 $ -1, mycol )
541 IF( mycol.EQ.ixbcol )
542 $ berr( jjfbe ) = s
543
544
545
546
547
548
549
550
551 IF( s.GT.eps .AND. two*s.LE.lstres .AND. count.LE.itmax ) THEN
552
553
554
555 CALL pdgetrs( trans, n, 1, af, iaf, jaf, descaf, ipiv,
556 $ work( ipr ), iw, jw, descw, info )
557 CALL pdaxpy( n, one, work( ipr ), iw, jw, descw, 1, x, ix,
558 $ jx+k, descx, 1 )
559 lstres = s
560 count = count + 1
561 GO TO 20
562 END IF
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590 IF( mycol.EQ.ixbcol ) THEN
591 IF( np.GT.0 ) THEN
592 DO 50 ii = iiw-1, iiw+np-2
593 IF( work( ipb+ii ).GT.safe2 ) THEN
594 work( ipb+ii ) = abs( work( ipr+ii ) ) +
595 $ nz*eps*work( ipb+ii )
596 ELSE
597 work( ipb+ii ) = abs( work( ipr+ii ) ) +
598 $ nz*eps*work( ipb+ii ) + safe1
599 END IF
600 50 CONTINUE
601 END IF
602 END IF
603
604 kase = 0
605 60 CONTINUE
606 IF( mycol.EQ.ixbcol ) THEN
607 CALL dgebs2d( ictxt, 'Rowwise', ' ', np, 1, work( ipr ),
608 $ descw( lld_ ) )
609 ELSE
610 CALL dgebr2d( ictxt, 'Rowwise', ' ', np, 1, work( ipr ),
611 $ descw( lld_ ), myrow, ixbcol )
612 END IF
613 descw( csrc_ ) = mycol
614 CALL pdlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
615 $ iw, jw, descw, iwork, est, kase )
616 descw( csrc_ ) = ixbcol
617
618 IF( kase.NE.0 ) THEN
619 IF( kase.EQ.1 ) THEN
620
621
622
623 CALL pdgetrs( transt, n, 1, af, iaf, jaf, descaf,
624 $ ipiv, work( ipr ), iw, jw, descw, info )
625
626 IF( mycol.EQ.ixbcol ) THEN
627 IF( np.GT.0 ) THEN
628 DO 70 ii = iiw-1, iiw+np-2
629 work( ipr+ii ) = work( ipb+ii )*work( ipr+ii )
630 70 CONTINUE
631 END IF
632 END IF
633 ELSE
634
635
636
637 IF( mycol.EQ.ixbcol ) THEN
638 IF( np.GT.0 ) THEN
639 DO 80 ii = iiw-1, iiw+np-2
640 work( ipr+ii ) = work( ipb+ii )*work( ipr+ii )
641 80 CONTINUE
642 END IF
643 END IF
644
645 CALL pdgetrs( trans, n, 1, af, iaf, jaf, descaf, ipiv,
646 $ work( ipr ), iw, jw, descw, info )
647 END IF
648 GO TO 60
649 END IF
650
651
652
653 lstres = zero
654 IF( mycol.EQ.ixbcol ) THEN
655 IF( np.GT.0 ) THEN
656 DO 90 ii = iixb, iixb+np-1
657 lstres =
max( lstres, abs( x( ioffxb+ii ) ) )
658 90 CONTINUE
659 END IF
660 CALL dgamx2d( ictxt, 'Column', ' ', 1, 1, lstres, 1, idum,
661 $ idum, 1, -1, mycol )
662 IF( lstres.NE.zero )
663 $ ferr( jjfbe ) = est / lstres
664
665 jjxb = jjxb + 1
666 jjfbe = jjfbe + 1
667 ioffxb = ioffxb + ldxb
668
669 END IF
670
671 100 CONTINUE
672
673 icurcol = mod( ixbcol+1, npcol )
674
675
676
677 DO 200 j = jn+1, jb+nrhs-1, descb( nb_ )
678 jbrhs =
min( jb+nrhs-j, descb( nb_ ) )
679 descw( csrc_ ) = icurcol
680
681 DO 190 k = 0, jbrhs-1
682
683 count = 1
684 lstres = three
685 110 CONTINUE
686
687
688
689
690
691
692
693 CALL pdcopy( n, b, ib, j+k, descb, 1, work( ipr ), iw, jw,
694 $ descw, 1 )
695 CALL pdgemv( trans, n, n, -one, a, ia, ja, desca, x,
696 $ ix, j+k, descx, 1, one, work( ipr ), iw, jw,
697 $ descw, 1 )
698
699
700
701
702
703
704
705
706
707
708
709
710 IF( mycol.EQ.icurcol ) THEN
711 IF( np.GT.0 ) THEN
712 DO 120 ii = iixb, iixb+np-1
713 work( iiw+ii-iixb ) = abs( b( ii+ioffxb ) )
714 120 CONTINUE
715 END IF
716 END IF
717
718 CALL pdagemv( trans, n, n, one, a, ia, ja, desca, x, ix,
719 $ j+k, descx, 1, one, work( ipb ), iw, jw,
720 $ descw, 1 )
721
722 s = zero
723 IF( mycol.EQ.icurcol ) THEN
724 IF( np.GT.0 )THEN
725 DO 130 ii = iiw-1, iiw+np-2
726 IF( work( ipb+ii ).GT.safe2 ) THEN
727 s =
max( s, abs( work( ipr+ii ) ) /
728 $ work( ipb+ii ) )
729 ELSE
730 s =
max( s, ( abs( work( ipr+ii ) )+safe1 ) /
731 $ ( work( ipb+ii )+safe1 ) )
732 END IF
733 130 CONTINUE
734 END IF
735 END IF
736
737 CALL dgamx2d( ictxt, 'All', ' ', 1, 1, s, 1, idum, idum, 1,
738 $ -1, mycol )
739 IF( mycol.EQ.icurcol )
740 $ berr( jjfbe ) = s
741
742
743
744
745
746
747
748
749 IF( s.GT.eps .AND. two*s.LE.lstres .AND.
750 $ count.LE.itmax ) THEN
751
752
753
754 CALL pdgetrs( trans, n, 1, af, iaf, jaf, descaf, ipiv,
755 $ work( ipr ), iw, jw, descw, info )
756 CALL pdaxpy( n, one, work( ipr ), iw, jw, descw, 1, x,
757 $ ix, j+k, descx, 1 )
758 lstres = s
759 count = count + 1
760 GO TO 110
761 END IF
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789 IF( mycol.EQ.icurcol ) THEN
790 IF( np.GT.0 ) THEN
791 DO 140 ii = iiw-1, iiw+np-2
792 IF( work( ipb+ii ).GT.safe2 ) THEN
793 work( ipb+ii ) = abs( work( ipr+ii ) ) +
794 $ nz*eps*work( ipb+ii )
795 ELSE
796 work( ipb+ii ) = abs( work( ipr+ii ) ) +
797 $ nz*eps*work( ipb+ii ) + safe1
798 END IF
799 140 CONTINUE
800 END IF
801 END IF
802
803 kase = 0
804 150 CONTINUE
805 IF( mycol.EQ.icurcol ) THEN
806 CALL dgebs2d( ictxt, 'Rowwise', ' ', np, 1, work( ipr ),
807 $ descw( lld_ ) )
808 ELSE
809 CALL dgebr2d( ictxt, 'Rowwise', ' ', np, 1, work( ipr ),
810 $ descw( lld_ ), myrow, icurcol )
811 END IF
812 descw( csrc_ ) = mycol
813 CALL pdlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
814 $ iw, jw, descw, iwork, est, kase )
815 descw( csrc_ ) = icurcol
816
817 IF( kase.NE.0 ) THEN
818 IF( kase.EQ.1 ) THEN
819
820
821
822 CALL pdgetrs( transt, n, 1, af, iaf, jaf, descaf,
823 $ ipiv, work( ipr ), iw, jw, descw, info )
824
825 IF( mycol.EQ.icurcol ) THEN
826 IF( np.GT.0 ) THEN
827 DO 160 ii = iiw-1, iiw+np-2
828 work( ipr+ii ) = work( ipb+ii )*
829 $ work( ipr+ii )
830 160 CONTINUE
831 END IF
832 END IF
833 ELSE
834
835
836
837 IF( mycol.EQ.icurcol ) THEN
838 IF( np.GT.0 ) THEN
839 DO 170 ii = iiw-1, iiw+np-2
840 work( ipr+ii ) = work( ipb+ii )*
841 $ work( ipr+ii )
842 170 CONTINUE
843 END IF
844 END IF
845
846 CALL pdgetrs( trans, n, 1, af, iaf, jaf, descaf,
847 $ ipiv, work( ipr ), iw, jw, descw,
848 $ info )
849 END IF
850 GO TO 150
851 END IF
852
853
854
855 lstres = zero
856 IF( mycol.EQ.icurcol ) THEN
857 IF( np.GT.0 ) THEN
858 DO 180 ii = iixb, iixb+np-1
859 lstres =
max( lstres, abs( x( ioffxb+ii ) ) )
860 180 CONTINUE
861 END IF
862 CALL dgamx2d( ictxt, 'Column', ' ', 1, 1, lstres,
863 $ 1, idum, idum, 1, -1, mycol )
864 IF( lstres.NE.zero )
865 $ ferr( jjfbe ) = est / lstres
866
867 jjxb = jjxb + 1
868 jjfbe = jjfbe + 1
869 ioffxb = ioffxb + ldxb
870
871 END IF
872
873 190 CONTINUE
874
875 icurcol = mod( icurcol+1, npcol )
876
877 200 CONTINUE
878
879 work( 1 ) = dble( lwmin )
880 iwork( 1 ) = liwmin
881
882 RETURN
883
884
885
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 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 pdgetrs(trans, n, nrhs, a, ia, ja, desca, ipiv, b, ib, jb, descb, info)
subroutine pdlacon(n, v, iv, jv, descv, x, ix, jx, descx, isgn, est, kase)
subroutine pxerbla(ictxt, srname, info)