6
7
8
9
10
11
12
13 LOGICAL WKNOWN
14 CHARACTER UPLO
15 INTEGER IA, IPOSTPAD, IPREPAD, JA, LWORK, LWORK1, N,
16 $ NOUT, RESULT, LIWORK
17 DOUBLE PRECISION ABSTOL, QTQNRM, THRESH, TSTNRM
18
19
20 INTEGER DESCA( * ), IWORK( * )
21 DOUBLE PRECISION A( * ), COPYA( * ), WIN( * ), WNEW( * ),
22 $ WORK( * ), Z( * )
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 INTEGER BLOCK_CYCLIC_2D, DLEN_, DT_, CTXT_, M_, N_,
147 $ MB_, NB_, RSRC_, CSRC_, LLD_
148 parameter( block_cyclic_2d = 1, dlen_ = 9, dt_ = 1,
149 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
150 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
151 DOUBLE PRECISION FIVE, NEGONE, PADVAL, ZERO
152 parameter( padval = 13.5285d+0, five = 5.0d+0,
153 $ negone = -1.0d+0, zero = 0.0d+0 )
154
155
156 INTEGER I, IAM, INFO, ISIZESUBTST, ISIZESYEVX,
157 $ ISIZETST, J, MINSIZE, MQ, MYCOL, MYROW,
158 $ NP, NPCOL, NPROW, NQ, RESAQ, RESQTQ,
159 $ SIZECHK, SIZEMQRLEFT, SIZEMQRRIGHT, SIZEQRF,
160 $ SIZEQTQ, SIZESUBTST, SIZESYEV, SIZESYEVX,
161 $ SIZETMS, SIZETST, SIZESYEVD, ISIZESYEVD,
162 $ TRILWMIN
163 DOUBLE PRECISION EPS, EPSNORMA, ERROR, MAXERROR, MINERROR,
164 $ NORMWIN, SAFMIN
165
166
167 INTEGER DESCZ( DLEN_ ), ITMP( 2 )
168
169
170
171 LOGICAL LSAME
172 INTEGER NUMROC
173 DOUBLE PRECISION PDLAMCH, PDLANSY
175
176
177 EXTERNAL blacs_gridinfo,
descinit, igamn2d, igamx2d,
181
182
183 INTRINSIC abs,
max,
min, mod
184
185
186
187 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dt_*lld_*mb_*m_*nb_*n_*
188 $ rsrc_.LT.0 )RETURN
189 CALL pdlasizesqp( desca, iprepad, ipostpad, sizemqrleft,
190 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
191 $ sizechk, sizesyevx, isizesyevx, sizesyev,
192 $ sizesyevd, isizesyevd, sizesubtst, isizesubtst,
193 $ sizetst, isizetst )
194
195 tstnrm = negone
196 qtqnrm = negone
197 eps =
pdlamch( desca( ctxt_ ),
'Eps' )
198 safmin =
pdlamch( desca( ctxt_ ),
'Safe min' )
199
200 normwin = safmin / eps
201 IF( n.GE.1 )
202 $ normwin =
max( abs( win( 1+iprepad ) ),
203 $ abs( win( n+iprepad ) ), normwin )
204
205
206
207 DO 10 i = 1, lwork1, 1
208 work( i+iprepad ) = 14.3d+0
209 10 CONTINUE
210
211 DO 30 i = 1, n
212 wnew( i+iprepad ) = 3.14159d+0
213 30 CONTINUE
214
215 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
216 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
217 $ desca( ctxt_ ), desca( lld_ ), info )
218
219 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
220
221 iam = 1
222 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
223 $ iam = 0
224
225
226
227 IF( myrow.GE.nprow .OR. myrow.LT.0 )
228 $ GO TO 150
229 result = 0
230
231 np =
numroc( n, desca( mb_ ), myrow, 0, nprow )
232 nq =
numroc( n, desca( nb_ ), mycol, 0, npcol )
233 mq =
numroc( n, desca( nb_ ), mycol, 0, npcol )
234
235
236
237 trilwmin = 3*n +
max( desca( nb_ )*( np+1 ), 3*desca( nb_ ) )
238 minsize =
max( 1 + 6*n + 2*np*nq, trilwmin ) + 2*n
239
240 CALL dlacpy( 'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
241 $ desca( lld_ ) )
242
243 CALL pdfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
244 $ ipostpad, padval )
245
246 CALL pdfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
247 $ ipostpad, padval+1.0d+0 )
248
249 CALL pdfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
250 $ padval+2.0d+0 )
251
252 CALL pdfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
253 $ ipostpad, padval+4.0d+0 )
254
255
256
257
258 DO 60 i = 1, n, 1
259 DO 50 j = 1, n, 1
260 CALL pdelset( z( 1+iprepad ), i, j, desca, 13.0d+0 )
261 50 CONTINUE
262 60 CONTINUE
263
267 CALL pdsyevd(
'V', uplo, n, a( 1+iprepad ), ia, ja, desca,
268 $ wnew( 1+iprepad ), z( 1+iprepad ), ia, ja, desca,
269 $ work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
270 $ liwork, info )
273
274 IF( thresh.LE.0 ) THEN
275 result = 0
276 ELSE
277 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVD-A', np, nq, a,
278 $ desca( lld_ ), iprepad, ipostpad, padval )
279
280 CALL pdchekpad( descz( ctxt_ ),
'PDSYEVD-Z', np, mq, z,
281 $ descz( lld_ ), iprepad, ipostpad,
282 $ padval+1.0d+0 )
283
284 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVD-WNEW', n, 1, wnew, n,
285 $ iprepad, ipostpad, padval+2.0d+0 )
286
287 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVD-WORK', lwork1, 1,
288 $ work, lwork1, iprepad, ipostpad,
289 $ padval+4.0d+0 )
290
291
292
293
294
295
296 itmp( 1 ) = info
297 itmp( 2 ) = info
298
299 CALL igamn2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp, 1, 1, 1,
300 $ -1, -1, 0 )
301 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp( 2 ), 1, 1,
302 $ 1, -1, -1, 0 )
303
304
305 IF( itmp( 1 ).NE.itmp( 2 ) ) THEN
306 IF( iam.EQ.0 )
307 $ WRITE( nout, fmt = * )
308 $ 'Different processes return different INFO'
309 result = 1
310 ELSE IF( info.NE.0 ) THEN
311 IF( iam.EQ.0 ) THEN
312 WRITE( nout, fmt = 9999 )info
313 IF( info.EQ.(n+1) )
314 $ WRITE( nout, fmt = 9994 )
315 result = 1
316 END IF
317 ELSE IF( info.EQ.14 .AND. lwork1.GE.minsize ) THEN
318 IF( iam.EQ.0 )
319 $ WRITE( nout, fmt = 9996 )info
320 result = 1
321 END IF
322
323 IF( result.EQ.0 .OR. info.GT.n ) THEN
324
325
326
327
328 DO 70 i = 1, n
329 work( i ) = wnew( i+iprepad )
330 work( i+n ) = wnew( i+iprepad )
331 70 CONTINUE
332
333 CALL dgamn2d( desca( ctxt_ ), 'a', ' ', n, 1, work, n, 1,
334 $ 1, -1, -1, 0 )
335 CALL dgamx2d( desca( ctxt_ ), 'a', ' ', n, 1,
336 $ work( 1+n ), n, 1, 1, -1, -1, 0 )
337
338 DO 80 i = 1, n
339
340 IF( abs( work( i )-work( n+i ) ).GT.zero ) THEN
341 IF( iam.EQ.0 )
342 $ WRITE( nout, fmt = 9995 )
343 result = 1
344 GO TO 90
345 END IF
346 80 CONTINUE
347 90 CONTINUE
348 END IF
349
350 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, result, 1, 1, 1,
351 $ -1, -1, 0 )
352
353
354
355 IF( n.EQ.0 ) THEN
356 epsnorma = eps
357 ELSE
358 epsnorma =
pdlansy(
'I', uplo, n, copya, ia, ja, desca,
359 $ work )*eps
360 END IF
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375 CALL pdfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
376 $ iprepad, ipostpad, 4.3d+0 )
377
378 resaq = 0
379
380 CALL pdsepchk( n, n, copya, ia, ja, desca,
381 $
max( abstol+epsnorma, safmin ), thresh,
382 $ z( 1+iprepad ), ia, ja, descz,
383 $ a( 1+iprepad ), ia, ja, desca,
384 $ wnew( 1+iprepad ), work( 1+iprepad ),
385 $ sizechk, tstnrm, resaq )
386
387 CALL pdchekpad( desca( ctxt_ ),
'PDSEPCHK-WORK', sizechk, 1,
388 $ work, sizechk, iprepad, ipostpad, 4.3d+0 )
389
390 IF( resaq.NE.0 ) THEN
391 result = 1
392 WRITE( nout, fmt = 9993 )
393 END IF
394
395
396
397 CALL pdfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
398 $ iprepad, ipostpad, 4.3d+0 )
399
400 resqtq = 0
401
402
403 DO 40 i = 1, 2
404 iwork( iprepad + i ) = 0
405 40 CONTINUE
406 CALL pdsepqtq( n, n, thresh, z( 1+iprepad ), ia, ja, descz,
407 $ a( 1+iprepad ), ia, ja, desca,
408 $ iwork( 1 ), iwork( 1 ), work( 1 ),
409 $ work( iprepad+1 ), sizeqtq, qtqnrm, info,
410 $ resqtq )
411
412 CALL pdchekpad( desca( ctxt_ ),
'PDSEPQTQ-WORK', sizeqtq, 1,
413 $ work, sizeqtq, iprepad, ipostpad, 4.3d+0 )
414
415 IF( resqtq.NE.0 ) THEN
416 result = 1
417 WRITE( nout, fmt = 9992 )
418 END IF
419
420 IF( info.NE.0 ) THEN
421 IF( iam.EQ.0 )
422 $ WRITE( nout, fmt = 9998 )info
423 result = 1
424 END IF
425 ENDIF
426
427
428
429 IF( wknown .AND. n.GT.0 ) THEN
430
431
432
433
434 minerror = normwin
435 maxerror = 0
436
437 DO 140 i = 1, n
438 error = abs( win( i+iprepad )-wnew( i+iprepad ) )
439 maxerror =
max( maxerror, error )
440 140 CONTINUE
441 minerror =
min( maxerror, minerror )
442
443 IF( minerror.GT.normwin*five*thresh*eps ) THEN
444 IF( iam.EQ.0 )
445 $ WRITE( nout, fmt = 9997 )minerror, normwin
446 result = 1
447 END IF
448 END IF
449
450
451
452 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, result, 1, 1, 1, -1,
453 $ -1, 0 )
454
455 150 CONTINUE
456
457
458 RETURN
459
460 9999 FORMAT( 'PDSYEVD returned INFO=', i7 )
461 9998 FORMAT( 'PDSEPQTQ in PDSDPSUBTST returned INFO=', i7 )
462 9997 FORMAT( 'PDSDPSUBTST minerror =', d11.2, ' normwin=', d11.2 )
463 9996 FORMAT( 'PDSYEVD returned INFO=', i7,
464 $ ' despite adequate workspace' )
465 9995 FORMAT( 'Different processes return different eigenvalues' )
466 9994 FORMAT( 'Heterogeneity detected by PDSYEVD' )
467 9993 FORMAT( 'PDSYEVD failed the |AQ -QE| test' )
468 9992 FORMAT( 'PDSYEVD failed the |QTQ -I| test' )
469
470
471
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
double precision function pdlamch(ictxt, cmach)
subroutine pdchekpad(ictxt, mess, m, n, a, lda, ipre, ipost, chkval)
subroutine pdelset(a, ia, ja, desca, alpha)
subroutine pdfillpad(ictxt, m, n, a, lda, ipre, ipost, chkval)
double precision function pdlansy(norm, uplo, n, a, ia, ja, desca, work)
subroutine pdlasizesqp(desca, iprepad, ipostpad, sizemqrleft, sizemqrright, sizeqrf, sizetms, sizeqtq, sizechk, sizesyevx, isizesyevx, sizesyev, sizesyevd, isizesyevd, sizesubtst, isizesubtst, sizetst, isizetst)
subroutine pdsepchk(ms, nv, a, ia, ja, desca, epsnorma, thresh, q, iq, jq, descq, c, ic, jc, descc, w, work, lwork, tstnrm, result)
subroutine pdsepqtq(ms, nv, thresh, q, iq, jq, descq, c, ic, jc, descc, procdist, iclustr, gap, work, lwork, qtqnrm, info, res)
subroutine pdsyevd(jobz, uplo, n, a, ia, ja, desca, w, z, iz, jz, descz, work, lwork, iwork, liwork, info)