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