5
6
7
8
9
10
11
12 CHARACTER EQUED, FACT, UPLO
13 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX, LIWORK,
14 $ LWORK, N, NRHS
15 REAL RCOND
16
17
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
19 $ DESCX( * ), IWORK( * )
20 REAL A( * ), AF( * ),
21 $ B( * ), BERR( * ), FERR( * ),
22 $ SC( * ), SR( * ), WORK( * ), X( * )
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
354 $ LLD_, MB_, M_, NB_, N_, RSRC_
355 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
356 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
357 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
358 REAL ONE, ZERO
359 parameter( one = 1.0e+0, zero = 0.0e+0 )
360
361
362 LOGICAL EQUIL, LQUERY, NOFACT, RCEQU
363 INTEGER I, IACOL, IAROW, IAFROW, IBROW, IBCOL, ICOFF,
364 $ ICOFFA, ICTXT, IDUMM, IIA, IIB, IIX, INFEQU,
365 $ IROFF, IROFFA, IROFFAF, IROFFB, IROFFX, IXCOL,
366 $ IXROW, J, JJA, JJB, JJX, LDB, LDX, LIWMIN,
367 $ LWMIN, MYCOL, MYROW, NP, NPCOL, NPROW, NRHSQ,
368 $ NQ
369 REAL AMAX, ANORM, BIGNUM, SCOND, SMAX, SMIN, SMLNUM
370
371
372 INTEGER IDUM1( 5 ), IDUM2( 5 )
373
374
379 $ sgamn2d, sgamx2d
380
381
382 LOGICAL LSAME
383 INTEGER INDXG2P, NUMROC
384 REAL PSLANSY, PSLAMCH
386
387
388 INTRINSIC ichar,
max,
min, mod
389
390
391
392
393
394 ictxt = desca( ctxt_ )
395 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
396
397
398
399 info = 0
400 IF( nprow.EQ.-1 ) THEN
401 info = -(800+ctxt_)
402 ELSE
403 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
404 IF(
lsame( fact,
'F' ) )
405 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
406 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
407 IF( info.EQ.0 ) THEN
408 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
409 $ nprow )
410 iafrow =
indxg2p( iaf, descaf( mb_ ), myrow,
411 $ descaf( rsrc_ ), nprow )
412 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
413 $ nprow )
414 ixrow =
indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
415 $ nprow )
416 iroffa = mod( ia-1, desca( mb_ ) )
417 iroffaf = mod( iaf-1, descaf( mb_ ) )
418 icoffa = mod( ja-1, desca( nb_ ) )
419 iroffb = mod( ib-1, descb( mb_ ) )
420 iroffx = mod( ix-1, descx( mb_ ) )
421 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
422 $ mycol, iia, jja, iarow, iacol )
423 np =
numroc( n+iroffa, desca( mb_ ), myrow, iarow, nprow )
424 IF( myrow.EQ.iarow )
425 $ np = np-iroffa
426 nq =
numroc( n+icoffa, desca( nb_ ), mycol, iacol, npcol )
427 IF( mycol.EQ.iacol )
428 $ nq = nq-icoffa
429 lwmin = 3*desca( lld_ )
430 liwmin = np
431 nofact =
lsame( fact,
'N' )
432 equil =
lsame( fact,
'E' )
433 IF( nofact .OR. equil ) THEN
434 equed = 'N'
435 rcequ = .false.
436 ELSE
437 rcequ =
lsame( equed,
'Y' )
438 smlnum =
pslamch( ictxt,
'Safe minimum' )
439 bignum = one / smlnum
440 END IF
441 IF( .NOT.nofact .AND. .NOT.equil .AND.
442 $ .NOT.
lsame( fact,
'F' ) )
THEN
443 info = -1
444 ELSE IF( .NOT.
lsame( uplo,
'U' ) .AND.
445 $ .NOT.
lsame( uplo,
'L' ) )
THEN
446 info = -2
447 ELSE IF( iroffa.NE.0 ) THEN
448 info = -6
449 ELSE IF( icoffa.NE.0 .OR. iroffa.NE.icoffa ) THEN
450 info = -7
451 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
452 info = -(800+nb_)
453 ELSE IF( iafrow.NE.iarow ) THEN
454 info = -10
455 ELSE IF( iroffaf.NE.0 ) THEN
456 info = -10
457 ELSE IF( ictxt.NE.descaf( ctxt_ ) ) THEN
458 info = -(1200+ctxt_)
459 ELSE IF(
lsame( fact,
'F' ) .AND. .NOT.
460 $ ( rcequ .OR.
lsame( equed,
'N' ) ) )
THEN
461 info = -13
462 ELSE
463 IF( rcequ ) THEN
464
465 smin = bignum
466 smax = zero
467 DO 10 j = iia, iia + np - 1
468 smin =
min( smin, sr( j ) )
469 smax =
max( smax, sr( j ) )
470 10 CONTINUE
471 CALL sgamn2d( ictxt, 'Columnwise', ' ', 1, 1, smin,
472 $ 1, idumm, idumm, -1, -1, mycol )
473 CALL sgamx2d( ictxt, 'Columnwise', ' ', 1, 1, smax,
474 $ 1, idumm, idumm, -1, -1, mycol )
475 IF( smin.LE.zero ) THEN
476 info = -14
477 ELSE IF( n.GT.0 ) THEN
478 scond =
max( smin, smlnum ) /
min( smax, bignum )
479 ELSE
480 scond = one
481 END IF
482 END IF
483 END IF
484 END IF
485
486 work( 1 ) = real( lwmin )
487 iwork( 1 ) = liwmin
488 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
489 IF( info.EQ.0 ) THEN
490 IF( ibrow.NE.iarow ) THEN
491 info = -18
492 ELSE IF( ixrow.NE.ibrow ) THEN
493 info = -22
494 ELSE IF( descb( mb_ ).NE.desca( nb_ ) ) THEN
495 info = -(2000+nb_)
496 ELSE IF( ictxt.NE.descb( ctxt_ ) ) THEN
497 info = -(2000+ctxt_)
498 ELSE IF( ictxt.NE.descx( ctxt_ ) ) THEN
499 info = -(2400+ctxt_)
500 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
501 info = -28
502 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
503 info = -30
504 END IF
505 idum1( 1 ) = ichar( fact )
506 idum2( 1 ) = 1
507 idum1( 2 ) = ichar( uplo )
508 idum2( 2 ) = 2
509 IF(
lsame( fact,
'F' ) )
THEN
510 idum1( 3 ) = ichar( equed )
511 idum2( 3 ) = 13
512 IF( lwork.EQ.-1 ) THEN
513 idum1( 4 ) = -1
514 ELSE
515 idum1( 4 ) = 1
516 END IF
517 idum2( 4 ) = 28
518 IF( liwork.EQ.-1 ) THEN
519 idum1( 5 ) = -1
520 ELSE
521 idum1( 5 ) = 1
522 END IF
523 idum2( 5 ) = 30
524 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3, nrhs,
525 $ 4, ib, jb, descb, 19, 5, idum1, idum2,
526 $ info )
527 ELSE
528 IF( lwork.EQ.-1 ) THEN
529 idum1( 3 ) = -1
530 ELSE
531 idum1( 3 ) = 1
532 END IF
533 idum2( 3 ) = 28
534 IF( liwork.EQ.-1 ) THEN
535 idum1( 4 ) = -1
536 ELSE
537 idum1( 4 ) = 1
538 END IF
539 idum2( 4 ) = 30
540 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3, nrhs,
541 $ 4, ib, jb, descb, 19, 4, idum1, idum2,
542 $ info )
543 END IF
544 END IF
545 END IF
546
547 IF( info.NE.0 ) THEN
548 CALL pxerbla( ictxt,
'PSPOSVX', -info )
549 RETURN
550 ELSE IF( lquery ) THEN
551 RETURN
552 END IF
553
554 IF( equil ) THEN
555
556
557
558 CALL pspoequ( n, a, ia, ja, desca, sr, sc, scond, amax,
559 $ infequ )
560
561 IF( infequ.EQ.0 ) THEN
562
563
564
565 CALL pslaqsy( uplo, n, a, ia, ja, desca, sr, sc, scond,
566 $ amax, equed )
567 rcequ =
lsame( equed,
'Y' )
568 END IF
569 END IF
570
571
572
573 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol, iib,
574 $ jjb, ibrow, ibcol )
575 ldb = descb( lld_ )
576 iroff = mod( ib-1, descb( mb_ ) )
577 icoff = mod( jb-1, descb( nb_ ) )
578 np =
numroc( n+iroff, descb( mb_ ), myrow, ibrow, nprow )
579 nrhsq =
numroc( nrhs+icoff, descb( nb_ ), mycol, ibcol, npcol )
580 IF( myrow.EQ.ibrow ) np = np-iroff
581 IF( mycol.EQ.ibcol ) nrhsq = nrhsq-icoff
582
583 IF( rcequ ) THEN
584 DO 30 j = jjb, jjb+nrhsq-1
585 DO 20 i = iib, iib+np-1
586 b( i + ( j-1 )*ldb ) = sr( i )*b( i + ( j-1 )*ldb )
587 20 CONTINUE
588 30 CONTINUE
589 END IF
590
591 IF( nofact .OR. equil ) THEN
592
593
594
595 CALL pslacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
596 $ descaf )
597 CALL pspotrf( uplo, n, af, iaf, jaf, descaf, info )
598
599
600
601 IF( info.NE.0 ) THEN
602 IF( info.GT.0 )
603 $ rcond = zero
604 RETURN
605 END IF
606 END IF
607
608
609
610 anorm =
pslansy(
'1', uplo, n, a, ia, ja, desca, work )
611
612
613
614 CALL pspocon( uplo, n, af, iaf, jaf, descaf, anorm, rcond, work,
615 $ lwork, iwork, liwork, info )
616
617
618
619 IF( rcond.LT.
pslamch( ictxt,
'Epsilon' ) )
THEN
620 info = ia + n
621 RETURN
622 END IF
623
624
625
626 CALL pslacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
627 $ descx )
628 CALL pspotrs( uplo, n, nrhs, af, iaf, jaf, descaf, x, ix, jx,
629 $ descx, info )
630
631
632
633
634 CALL psporfs( uplo, n, nrhs, a, ia, ja, desca, af, iaf, jaf,
635 $ descaf, b, ib, jb, descb, x, ix, jx, descx, ferr,
636 $ berr, work, lwork, iwork, liwork, info )
637
638
639
640
641 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix,
642 $ jjx, ixrow, ixcol )
643 ldx = descx( lld_ )
644 iroff = mod( ix-1, descx( mb_ ) )
645 icoff = mod( jx-1, descx( nb_ ) )
646 np =
numroc( n+iroff, descx( mb_ ), myrow, ixrow, nprow )
647 nrhsq =
numroc( nrhs+icoff, descx( nb_ ), mycol, ixcol, npcol )
648 IF( myrow.EQ.ibrow ) np = np-iroff
649 IF( mycol.EQ.ibcol ) nrhsq = nrhsq-icoff
650
651 IF( rcequ ) THEN
652 DO 50 j = jjx, jjx+nrhsq-1
653 DO 40 i = iix, iix+np-1
654 x( i + ( j-1 )*ldx ) = sr( i )*x( i + ( j-1 )*ldx )
655 40 CONTINUE
656 50 CONTINUE
657 DO 60 j = jjx, jjx+nrhsq-1
658 ferr( j ) = ferr( j ) / scond
659 60 CONTINUE
660 END IF
661
662 work( 1 ) = real( lwmin )
663 iwork( 1 ) = liwmin
664 RETURN
665
666
667
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
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 pslacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
real function pslansy(norm, uplo, n, a, ia, ja, desca, work)
subroutine pslaqsy(uplo, n, a, ia, ja, desca, sr, sc, scond, amax, equed)
subroutine pspocon(uplo, n, a, ia, ja, desca, anorm, rcond, work, lwork, iwork, liwork, info)
subroutine pspoequ(n, a, ia, ja, desca, sr, sc, scond, amax, info)
subroutine psporfs(uplo, n, nrhs, a, ia, ja, desca, af, iaf, jaf, descaf, b, ib, jb, descb, x, ix, jx, descx, ferr, berr, work, lwork, iwork, liwork, info)
subroutine pspotrf(uplo, n, a, ia, ja, desca, info)
subroutine pspotrs(uplo, n, nrhs, a, ia, ja, desca, b, ib, jb, descb, info)
subroutine pxerbla(ictxt, srname, info)