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