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