4
5
6
7
8
9
10
11 CHARACTER JOBZ, UPLO
12 INTEGER IA, INFO, IZ, JA, JZ, LIWORK, LRWORK, LWORK, N
13
14
15 INTEGER DESCA( * ), DESCZ( * ), IWORK( * )
16 DOUBLE PRECISION RWORK( * ), W( * )
17 COMPLEX*16 A( * ), WORK( * ), Z( * )
18
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 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
164 $ MB_, NB_, RSRC_, CSRC_, LLD_
165 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
166 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
167 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
168 DOUBLE PRECISION ZERO, ONE
169 parameter( zero = 0.0d+0, one = 1.0d+0 )
170 COMPLEX*16 CZERO, CONE
171 parameter( czero = ( 0.0d+0, 0.0d+0 ),
172 $ cone = ( 1.0d+0, 0.0d+0 ) )
173
174
175 LOGICAL LOWER, LQUERY
176 INTEGER CSRC_A, I, IACOL, IAROW, ICOFFA, IINFO, IIZ,
177 $ INDD, INDE, INDE2, INDRWORK, INDTAU, INDWORK,
178 $ INDZ, IPR, IPZ, IROFFA, IROFFZ, ISCALE, IZCOL,
179 $ IZROW, J, JJZ, LDR, LDZ, LIWMIN, LLRWORK,
180 $ LLWORK, LRWMIN, LWMIN, MB_A, MYCOL, MYROW, NB,
181 $ NB_A, NN, NP0, NPCOL, NPROW, NQ, NQ0, OFFSET,
182 $ RSRC_A
183 DOUBLE PRECISION ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN, SIGMA,
184 $ SMLNUM
185
186
187 INTEGER DESCRZ( 9 ), IDUM1( 2 ), IDUM2( 2 )
188
189
190 LOGICAL LSAME
191 INTEGER INDXG2L, INDXG2P, NUMROC
192 DOUBLE PRECISION PZLANHE, PDLAMCH
195
196
200 $ dscal
201
202
203 INTRINSIC dcmplx, ichar,
max,
min, mod, dble, sqrt
204
205
206
207 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
208 $ rsrc_.LT.0 )RETURN
209
210 info = 0
211
212
213
214 IF( n.EQ.0 )
215 $ RETURN
216
217
218
219 ictxt = desca( ctxt_ )
220 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
221
222 IF( nprow.EQ.-1 ) THEN
223 info = -( 700+ctxt_ )
224 ELSE
225 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 7, info )
226 CALL chk1mat( n, 3, n, 3, iz, jz, descz, 12, info )
227 IF( info.EQ.0 ) THEN
228 lower =
lsame( uplo,
'L' )
229 nb_a = desca( nb_ )
230 mb_a = desca( mb_ )
231 nb = nb_a
232 rsrc_a = desca( rsrc_ )
233 csrc_a = desca( csrc_ )
234 iroffa = mod( ia-1, mb_a )
235 icoffa = mod( ja-1, nb_a )
236 iarow =
indxg2p( ia, nb_a, myrow, rsrc_a, nprow )
237 iacol =
indxg2p( ja, mb_a, mycol, csrc_a, npcol )
238 np0 =
numroc( n, nb, myrow, iarow, nprow )
239 nq0 =
numroc( n, nb, mycol, iacol, npcol )
240 iroffz = mod( iz-1, mb_a )
241 CALL infog2l( iz, jz, descz, nprow, npcol, myrow, mycol,
242 $ iiz, jjz, izrow, izcol )
243 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 .OR. lrwork.EQ.-1 )
244
245
246
248 nq =
numroc( nn, nb, 0, 0, npcol )
249 lwmin = n + ( np0+nq+nb )*nb
250 lrwmin = 1 + 9*n + 3*np0*nq0
251 liwmin = 7*n + 8*npcol + 2
252 work( 1 ) = dcmplx( lwmin )
253 rwork( 1 ) = dble( lrwmin )
254 iwork( 1 ) = liwmin
255 IF( .NOT.
lsame( jobz,
'V' ) )
THEN
256 info = -1
257 ELSE IF( .NOT.( lower .OR.
lsame( uplo,
'U' ) ) )
THEN
258 info = -2
259 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 ) THEN
260 info = -14
261 ELSE IF( lrwork.LT.lrwmin .AND. lrwork.NE.-1 ) THEN
262 info = -16
263 ELSE IF( iroffa.NE.0 ) THEN
264 info = -4
265 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
266 info = -( 700+nb_ )
267 ELSE IF( iroffa.NE.iroffz ) THEN
268 info = -10
269 ELSE IF( iarow.NE.izrow ) THEN
270 info = -10
271 ELSE IF( desca( m_ ).NE.descz( m_ ) ) THEN
272 info = -( 1200+m_ )
273 ELSE IF( desca( n_ ).NE.descz( n_ ) ) THEN
274 info = -( 1200+n_ )
275 ELSE IF( desca( mb_ ).NE.descz( mb_ ) ) THEN
276 info = -( 1200+mb_ )
277 ELSE IF( desca( nb_ ).NE.descz( nb_ ) ) THEN
278 info = -( 1200+nb_ )
279 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) ) THEN
280 info = -( 1200+rsrc_ )
281 ELSE IF( desca( ctxt_ ).NE.descz( ctxt_ ) ) THEN
282 info = -( 1200+ctxt_ )
283 END IF
284 END IF
285 IF( lower ) THEN
286 idum1( 1 ) = ichar( 'L' )
287 ELSE
288 idum1( 1 ) = ichar( 'U' )
289 END IF
290 idum2( 1 ) = 2
291 IF( lwork.EQ.-1 ) THEN
292 idum1( 2 ) = -1
293 ELSE
294 idum1( 2 ) = 1
295 END IF
296 idum2( 2 ) = 14
297 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 7, n, 3, n, 3, iz,
298 $ jz, descz, 11, 2, idum1, idum2, info )
299 END IF
300
301 IF( info.NE.0 ) THEN
302 CALL pxerbla( desca( ctxt_ ),
'PZHEEVD', -info )
303 RETURN
304 ELSE IF( lquery ) THEN
305 RETURN
306 END IF
307
308
309
310 safmin =
pdlamch( desca( ctxt_ ),
'Safe minimum' )
311 eps =
pdlamch( desca( ctxt_ ),
'Precision' )
312 smlnum = safmin / eps
313 bignum = one / smlnum
314 rmin = sqrt( smlnum )
315 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
316
317
318
319 indtau = 1
320 indwork = indtau + n
321 llwork = lwork - indwork + 1
322
323
324
325 inde = 1
326 indd = inde + n
327 inde2 = indd + n
328 indrwork = inde2 + n
329 llrwork = lrwork - indrwork + 1
330
331
332
333 iscale = 0
334
335 anrm =
pzlanhe(
'M', uplo, n, a, ia, ja, desca,
336 $ rwork( indrwork ) )
337
338
339 IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
340 iscale = 1
341 sigma = rmin / anrm
342 ELSE IF( anrm.GT.rmax ) THEN
343 iscale = 1
344 sigma = rmax / anrm
345 END IF
346
347 IF( iscale.EQ.1 ) THEN
348 CALL pzlascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
349 END IF
350
351
352
353 CALL pzhetrd( uplo, n, a, ia, ja, desca, rwork( indd ),
354 $ rwork( inde2 ), work( indtau ), work( indwork ),
355 $ llwork, iinfo )
356
357
358
359
360
361
362
363 offset = 0
364 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.0 )
365 $ THEN
366 CALL pdlared1d( n, ia, ja, desca, rwork( indd ), w,
367 $ rwork( indrwork ), llrwork )
368
369 CALL pdlared1d( n, ia, ja, desca, rwork( inde2 ),
370 $ rwork( inde ), rwork( indrwork ), llrwork )
371 IF( .NOT.lower )
372 $ offset = 1
373 ELSE
374 DO 10 i = 1, n
375 CALL pzelget(
'A',
' ', work( indwork ), a, i+ia-1, i+ja-1,
376 $ desca )
377 w( i ) = dble( work( indwork ) )
378 10 CONTINUE
379 IF(
lsame( uplo,
'U' ) )
THEN
380 DO 20 i = 1, n - 1
381 CALL pzelget(
'A',
' ', work( indwork ), a, i+ia-1, i+ja,
382 $ desca )
383 rwork( inde+i-1 ) = dble( work( indwork ) )
384 20 CONTINUE
385 ELSE
386 DO 30 i = 1, n - 1
387 CALL pzelget(
'A',
' ', work( indwork ), a, i+ia, i+ja-1,
388 $ desca )
389 rwork( inde+i-1 ) = dble( work( indwork ) )
390 30 CONTINUE
391 END IF
392 END IF
393
394
395
396 indz = inde + n
397 indrwork = indz + np0*nq0
398 llrwork = lrwork - indrwork + 1
400 CALL descinit( descrz, descz( m_ ), descz( n_ ), descz( mb_ ),
401 $ descz( nb_ ), descz( rsrc_ ), descz( csrc_ ),
402 $ descz( ctxt_ ), ldr, info )
403 CALL pzlaset(
'Full', n, n, czero, cone, z, iz, jz, descz )
404 CALL pdlaset(
'Full', n, n, zero, one, rwork( indz ), 1, 1,
405 $ descrz )
406 CALL pdstedc(
'I', n, w, rwork( inde+offset ), rwork( indz ), iz,
407 $ jz, descrz, rwork( indrwork ), llrwork, iwork,
408 $ liwork, iinfo )
409
410 ldz = descz( lld_ )
411 ldr = descrz( lld_ )
412 iiz =
indxg2l( iz, nb, myrow, myrow, nprow )
413 jjz =
indxg2l( jz, nb, mycol, mycol, npcol )
414 ipz = iiz + ( jjz-1 )*ldz
415 ipr = indz - 1 + iiz + ( jjz-1 )*ldr
416 DO 50 j = 0, nq0 - 1
417 DO 40 i = 0, np0 - 1
418 z( ipz+i+j*ldz ) = rwork( ipr+i+j*ldr )
419 40 CONTINUE
420 50 CONTINUE
421
422
423
424 CALL pzunmtr(
'L', uplo,
'N', n, n, a, ia, ja, desca,
425 $ work( indtau ), z, iz, jz, descz, work( indwork ),
426 $ llwork, iinfo )
427
428
429
430 IF( iscale.EQ.1 ) THEN
431 CALL dscal( n, one / sigma, w, 1 )
432 END IF
433
434 work( 1 ) = dcmplx( lwmin )
435 rwork( 1 ) = dble( lrwmin )
436 iwork( 1 ) = liwmin
437
438 RETURN
439
440
441
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
integer function indxg2l(indxglob, nb, iproc, isrcproc, nprocs)
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)
subroutine pdlaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
double precision function pdlamch(ictxt, cmach)
subroutine pdlared1d(n, ia, ja, desc, bycol, byall, work, lwork)
subroutine pdstedc(compz, n, d, e, q, iq, jq, descq, work, lwork, iwork, liwork, info)
subroutine pxerbla(ictxt, srname, info)
subroutine pzlaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
subroutine pzelget(scope, top, alpha, a, ia, ja, desca)
subroutine pzhetrd(uplo, n, a, ia, ja, desca, d, e, tau, work, lwork, info)
double precision function pzlanhe(norm, uplo, n, a, ia, ja, desca, work)
subroutine pzlascl(type, cfrom, cto, m, n, a, ia, ja, desca, info)
subroutine pzunmtr(side, uplo, trans, m, n, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)