4
5
6
7
8
9
10
11 INTEGER INFO, IZ, JZ, LIWORK, LWORK, M, N
12 REAL ORFAC
13
14
15 INTEGER DESCZ( * ), IBLOCK( * ), ICLUSTR( * ),
16 $ IFAIL( * ), ISPLIT( * ), IWORK( * )
17 REAL D( * ), E( * ), GAP( * ), W( * ), WORK( * ),
18 $ Z( * )
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264 INTRINSIC abs,
max,
min, mod, real
265
266
267 INTEGER ICEIL, NUMROC
269
270
271 EXTERNAL blacs_gridinfo,
chk1mat, igamn2d, igebr2d,
274
275
276 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
277 $ MB_, NB_, RSRC_, CSRC_, LLD_
278 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
279 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
280 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
281 REAL ZERO, NEGONE, ODM1, FIVE, ODM3, ODM18
282 parameter( zero = 0.0e+0, negone = -1.0e+0,
283 $ odm1 = 1.0e-1, five = 5.0e+0, odm3 = 1.0e-3,
284 $ odm18 = 1.0e-18 )
285
286
287 LOGICAL LQUERY, SORTED
288 INTEGER B1, BN, BNDRY, CLSIZ, COL, I, IFIRST, IINFO,
289 $ ILAST, IM, INDRW, ITMP, J, K, LGCLSIZ, LLWORK,
290 $ LOAD, LOCINFO, MAXVEC, MQ00, MYCOL, MYROW,
291 $ NBLK, NERR, NEXT, NP00, NPCOL, NPROW, NVS,
292 $ OLNBLK, P, ROW, SELF, TILL, TOTERR
293 REAL DIFF, MINGAP, ONENRM, ORGFAC, ORTOL, TMPFAC
294
295
296 INTEGER IDUM1( 1 ), IDUM2( 1 )
297
298
299
300 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
301 $ rsrc_.LT.0 )RETURN
302
303 CALL blacs_gridinfo( descz( ctxt_ ), nprow, npcol, myrow, mycol )
304 self = myrow*npcol + mycol
305
306
307
308 info = 0
309 IF( nprow.EQ.-1 ) THEN
310 info = -( 1200+ctxt_ )
311 ELSE
312
313
314
315 CALL chk1mat( n, 1, n, 1, iz, jz, descz, 12, info )
316 IF( info.EQ.0 ) THEN
317
318
319
320
321 np00 =
numroc( n, descz( mb_ ), 0, 0, nprow )
322 mq00 =
numroc( m, descz( nb_ ), 0, 0, npcol )
323 p = nprow*npcol
324
325
326
327 llwork = lwork
328 CALL igamn2d( descz( ctxt_ ), 'A', ' ', 1, 1, llwork, 1, 1,
329 $ 1, -1, -1, -1 )
330 indrw =
max( 5*n, np00*mq00 )
331 IF( n.NE.0 )
332 $ maxvec = ( llwork-indrw ) / n
334 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
335 tmpfac = orfac
336 CALL sgebs2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, tmpfac,
337 $ 1 )
338 ELSE
339 CALL sgebr2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, tmpfac,
340 $ 1, 0, 0 )
341 END IF
342
343 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
344 IF( m.LT.0 .OR. m.GT.n ) THEN
345 info = -4
346 ELSE IF( maxvec.LT.load .AND. .NOT.lquery ) THEN
347 info = -14
348 ELSE IF( liwork.LT.3*n+p+1 .AND. .NOT.lquery ) THEN
349 info = -16
350 ELSE
351 DO 10 i = 2, m
352 IF( iblock( i ).LT.iblock( i-1 ) ) THEN
353 info = -6
354 GO TO 20
355 END IF
356 IF( iblock( i ).EQ.iblock( i-1 ) .AND. w( i ).LT.
357 $ w( i-1 ) ) THEN
358 info = -5
359 GO TO 20
360 END IF
361 10 CONTINUE
362 20 CONTINUE
363 IF( info.EQ.0 ) THEN
364 IF( abs( tmpfac-orfac ).GT.five*abs( tmpfac ) )
365 $ info = -8
366 END IF
367 END IF
368
369 END IF
370 idum1( 1 ) = m
371 idum2( 1 ) = 4
372 CALL pchk1mat( n, 1, n, 1, iz, jz, descz, 12, 1, idum1, idum2,
373 $ info )
374 work( 1 ) = real(
max( 5*n, np00*mq00 )+
iceil( m, p )*n )
375 iwork( 1 ) = 3*n + p + 1
376 END IF
377 IF( info.NE.0 ) THEN
378 CALL pxerbla( descz( ctxt_ ),
'PSSTEIN', -info )
379 RETURN
380 ELSE IF( lwork.EQ.-1 .OR. liwork.EQ.-1 ) THEN
381 RETURN
382 END IF
383
384 DO 30 i = 1, m
385 ifail( i ) = 0
386 30 CONTINUE
387 DO 40 i = 1, p + 1
388 iwork( i ) = 0
389 40 CONTINUE
390 DO 50 i = 1, p
391 gap( i ) = negone
392 iclustr( 2*i-1 ) = 0
393 iclustr( 2*i ) = 0
394 50 CONTINUE
395
396
397
398
399 IF( n.EQ.0 .OR. m.EQ.0 )
400 $ RETURN
401
402 IF( orfac.GE.zero ) THEN
403 tmpfac = orfac
404 ELSE
405 tmpfac = odm3
406 END IF
407 orgfac = tmpfac
408
409
410
411 ilast = m / load
412 IF( mod( m, load ).EQ.0 )
413 $ ilast = ilast - 1
414 olnblk = -1
415 nvs = 0
416 next = 1
417 im = 0
418 onenrm = zero
419 DO 100 i = 0, ilast - 1
420 next = next + load
421 j = next - 1
422 IF( j.GT.nvs ) THEN
423 nblk = iblock( next )
424 IF( nblk.EQ.iblock( next-1 ) .AND. nblk.NE.olnblk ) THEN
425
426
427
428 IF( nblk.EQ.1 ) THEN
429 b1 = 1
430 ELSE
431 b1 = isplit( nblk-1 ) + 1
432 END IF
433 bn = isplit( nblk )
434
435 onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
436 onenrm =
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
437 DO 60 j = b1 + 1, bn - 1
438 onenrm =
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
439 $ abs( e( j ) ) )
440 60 CONTINUE
441 olnblk = nblk
442 END IF
443 till = nvs + maxvec
444 70 CONTINUE
445 j = next - 1
446 IF( tmpfac.GT.odm18 ) THEN
447 ortol = tmpfac*onenrm
448 DO 80 j = next - 1,
min( till, m-1 )
449 IF( iblock( j+1 ).NE.iblock( j ) .OR. w( j+1 )-
450 $ w( j ).GE.ortol ) THEN
451 GO TO 90
452 END IF
453 80 CONTINUE
454 IF( j.EQ.m .AND. till.GE.m )
455 $ GO TO 90
456 tmpfac = tmpfac*odm1
457 GO TO 70
458 END IF
459 90 CONTINUE
461 END IF
462 IF( self.EQ.i )
463 $ im =
max( 0, j-nvs )
464
465 iwork( i+1 ) = nvs
467 100 CONTINUE
468 IF( self.EQ.ilast )
469 $ im = m - nvs
470 iwork( ilast+1 ) = nvs
471 DO 110 i = ilast + 2, p + 1
472 iwork( i ) = m
473 110 CONTINUE
474
475 clsiz = 1
476 lgclsiz = 1
477 ilast = 0
478 nblk = 0
479 bndry = 2
480 k = 1
481 DO 140 i = 1, m
482 IF( iblock( i ).NE.nblk ) THEN
483 nblk = iblock( i )
484 IF( nblk.EQ.1 ) THEN
485 b1 = 1
486 ELSE
487 b1 = isplit( nblk-1 ) + 1
488 END IF
489 bn = isplit( nblk )
490
491 onenrm = abs( d( b1 ) ) + abs( e( b1 ) )
492 onenrm =
max( onenrm, abs( d( bn ) )+abs( e( bn-1 ) ) )
493 DO 120 j = b1 + 1, bn - 1
494 onenrm =
max( onenrm, abs( d( j ) )+abs( e( j-1 ) )+
495 $ abs( e( j ) ) )
496 120 CONTINUE
497
498 END IF
499 IF( i.GT.1 ) THEN
500 diff = w( i ) - w( i-1 )
501 IF( iblock( i ).NE.iblock( i-1 ) .OR. i.EQ.m .OR. diff.GT.
502 $ orgfac*onenrm ) THEN
503 ifirst = ilast
504 IF( i.EQ.m ) THEN
505 IF( iblock( m ).NE.iblock( m-1 ) .OR. diff.GT.orgfac*
506 $ onenrm ) THEN
507 ilast = m - 1
508 ELSE
509 ilast = m
510 END IF
511 ELSE
512 ilast = i - 1
513 END IF
514 clsiz = ilast - ifirst
515 IF( clsiz.GT.1 ) THEN
516 IF( lgclsiz.LT.clsiz )
517 $ lgclsiz = clsiz
518 mingap = onenrm
519 130 CONTINUE
520 IF( bndry.GT.p+1 )
521 $ GO TO 150
522 IF( iwork( bndry ).GT.ifirst .AND. iwork( bndry ).LT.
523 $ ilast ) THEN
524 mingap =
min( w( iwork( bndry )+1 )-
525 $ w( iwork( bndry ) ), mingap )
526 ELSE IF( iwork( bndry ).GE.ilast ) THEN
527 IF( mingap.LT.onenrm ) THEN
528 iclustr( 2*k-1 ) = ifirst + 1
529 iclustr( 2*k ) = ilast
530 gap( k ) = mingap / onenrm
531 k = k + 1
532 END IF
533 GO TO 140
534 END IF
535 bndry = bndry + 1
536 GO TO 130
537 END IF
538 END IF
539 END IF
540 140 CONTINUE
541 150 CONTINUE
542 info = ( k-1 )*( m+1 )
543
544
545
546 CALL sstein2( n, d, e, im, w( iwork( self+1 )+1 ),
547 $ iblock( iwork( self+1 )+1 ), isplit, orgfac,
548 $ work( indrw+1 ), n, work, iwork( p+2 ),
549 $ ifail( iwork( self+1 )+1 ), locinfo )
550
551
552
553
554
555 DO 160 i = 1, m
556 iwork( p+1+i ) = i
557 160 CONTINUE
558
559 CALL slasrt2(
'I', m, w, iwork( p+2 ), iinfo )
560
561 DO 170 i = 1, m
562 iwork( m+p+1+iwork( p+1+i ) ) = i
563 170 CONTINUE
564
565
566 DO 180 i = 1, locinfo
567 itmp = iwork( self+1 ) + i
568 ifail( itmp ) = ifail( itmp ) + itmp - i
569 ifail( itmp ) = iwork( m+p+1+ifail( itmp ) )
570 180 CONTINUE
571
572 DO 190 i = 1, k - 1
573 iclustr( 2*i-1 ) = iwork( m+p+1+iclustr( 2*i-1 ) )
574 iclustr( 2*i ) = iwork( m+p+1+iclustr( 2*i ) )
575 190 CONTINUE
576
577
578
579
580
581 toterr = 0
582 DO 210 i = 1, p
583 IF( self.EQ.i-1 ) THEN
584 CALL igebs2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, locinfo, 1 )
585 IF( locinfo.NE.0 ) THEN
586 CALL igebs2d( descz( ctxt_ ), 'ALL', ' ', locinfo, 1,
587 $ ifail( iwork( i )+1 ), locinfo )
588 DO 200 j = 1, locinfo
589 ifail( toterr+j ) = ifail( iwork( i )+j )
590 200 CONTINUE
591 toterr = toterr + locinfo
592 END IF
593 ELSE
594
595 row = ( i-1 ) / npcol
596 col = mod( i-1, npcol )
597
598 CALL igebr2d( descz( ctxt_ ), 'ALL', ' ', 1, 1, nerr, 1,
599 $ row, col )
600 IF( nerr.NE.0 ) THEN
601 CALL igebr2d( descz( ctxt_ ), 'ALL', ' ', nerr, 1,
602 $ ifail( toterr+1 ), nerr, row, col )
603 toterr = toterr + nerr
604 END IF
605 END IF
606 210 CONTINUE
607 info = info + toterr
608
609
610 CALL pslaevswp( n, work( indrw+1 ), n, z, iz, jz, descz, iwork,
611 $ iwork( m+p+2 ), work, indrw )
612
613 DO 220 i = 2, p
614 iwork( i ) = iwork( m+p+1+iwork( i ) )
615 220 CONTINUE
616
617
618
619
620
621 230 CONTINUE
622 sorted = .true.
623 DO 240 i = 2, p - 1
624 IF( iwork( i ).GT.iwork( i+1 ) ) THEN
625 itmp = iwork( i+1 )
626 iwork( i+1 ) = iwork( i )
627 iwork( i ) = itmp
628 sorted = .false.
629 END IF
630 240 CONTINUE
631 IF( .NOT.sorted )
632 $ GO TO 230
633
634 DO 250 i = p + 1, 1, -1
635 iwork( i+1 ) = iwork( i )
636 250 CONTINUE
637
638 work( 1 ) = ( lgclsiz+load-1 )*n + indrw
639 iwork( 1 ) = 3*n + p + 1
640
641
642
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
integer function iceil(inum, idenom)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
subroutine pslaevswp(n, zin, ldzi, z, iz, jz, descz, nvs, key, work, lwork)
subroutine pxerbla(ictxt, srname, info)
subroutine slasrt2(id, n, d, key, info)
subroutine sstein2(n, d, e, m, w, iblock, isplit, orfac, z, ldz, work, iwork, ifail, info)