7
8
9
10
11
12
13
14 LOGICAL WKNOWN
15 CHARACTER JOBZ, UPLO
16 INTEGER IA, IPOSTPAD, IPREPAD, JA, LWORK, LWORK1, N,
17 $ NOUT, RESULT
18 DOUBLE PRECISION ABSTOL, QTQNRM, THRESH, TSTNRM
19
20
21 INTEGER DESCA( * )
22 DOUBLE PRECISION A( * ), COPYA( * ), WIN( * ), WNEW( * ),
23 $ WORK( * ), Z( * )
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, EIGS, 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 DOUBLE PRECISION EPS, EPSNORMA, ERROR, MAXERROR, MINERROR,
163 $ NORMWIN, SAFMIN
164
165
166 INTEGER DESCZ( DLEN_ ), ITMP( 2 ),
167 $ IWORK( 2 )
168
169
170
171 LOGICAL LSAME
172 INTEGER NUMROC
173 DOUBLE PRECISION PDLAMCH, PDLANSY
175
176
177 EXTERNAL blacs_gridinfo,
descinit, dgamn2d, dgamx2d,
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 DO 40 i = 1, 2
216 iwork( i ) = 0
217 40 CONTINUE
218
219 IF(
lsame( jobz,
'N' ) )
THEN
220 eigs = 0
221 ELSE
222 eigs = n
223 END IF
224
225
226 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
227 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
228 $ desca( ctxt_ ), desca( lld_ ), info )
229
230 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
231
232 iam = 1
233 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
234 $ iam = 0
235
236
237
238 result = -3
239 IF( myrow.GE.nprow .OR. myrow.LT.0 )
240 $ GO TO 150
241 result = 0
242
243 np =
numroc( n, desca( mb_ ), myrow, 0, nprow )
244 nq =
numroc( n, desca( nb_ ), mycol, 0, npcol )
245 mq =
numroc( eigs, desca( nb_ ), mycol, 0, npcol )
246
247
248
250
251 CALL dlacpy( 'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
252 $ desca( lld_ ) )
253
254 CALL pdfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
255 $ ipostpad, padval )
256
257 CALL pdfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
258 $ ipostpad, padval+1.0d+0 )
259
260 CALL pdfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
261 $ padval+2.0d+0 )
262
263 CALL pdfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
264 $ ipostpad, padval+4.0d+0 )
265
266
267
268
269 DO 60 i = 1, n, 1
270 DO 50 j = 1, eigs, 1
271 CALL pdelset( z( 1+iprepad ), i, j, desca, 13.0d+0 )
272 50 CONTINUE
273 60 CONTINUE
274
278 CALL pdsyev( jobz, uplo, n, a( 1+iprepad ), ia, ja, desca,
279 $ wnew( 1+iprepad ), z( 1+iprepad ), ia, ja, desca,
280 $ work( 1+iprepad ), lwork1, info )
283
284 IF( thresh.LE.0 ) THEN
285 result = 0
286 ELSE
287 CALL pdchekpad( desca( ctxt_ ),
'PDSYEV-A', np, nq, a,
288 $ desca( lld_ ), iprepad, ipostpad, padval )
289
290 CALL pdchekpad( descz( ctxt_ ),
'PDSYEV-Z', np, mq, z,
291 $ descz( lld_ ), iprepad, ipostpad,
292 $ padval+1.0d+0 )
293
294 CALL pdchekpad( desca( ctxt_ ),
'PDSYEV-WNEW', n, 1, wnew, n,
295 $ iprepad, ipostpad, padval+2.0d+0 )
296
297 CALL pdchekpad( desca( ctxt_ ),
'PDSYEV-WORK', lwork1, 1,
298 $ work, lwork1, iprepad, ipostpad,
299 $ padval+4.0d+0 )
300
301
302
303
304
305
306 itmp( 1 ) = info
307 itmp( 2 ) = info
308
309 CALL igamn2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp, 1, 1, 1,
310 $ -1, -1, 0 )
311 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp( 2 ), 1, 1,
312 $ 1, -1, -1, 0 )
313
314
315 IF( itmp( 1 ).NE.itmp( 2 ) ) THEN
316 IF( iam.EQ.0 )
317 $ WRITE( nout, fmt = * )
318 $ 'Different processes return different INFO'
319 result = 1
320 ELSE IF( info.NE.0 ) THEN
321 IF( iam.EQ.0 ) THEN
322 WRITE( nout, fmt = 9999 )info
323 IF( info.EQ.(n+1) )
324 $ WRITE( nout, fmt = 9994 )
325 result = 1
326 END IF
327 ELSE IF( info.EQ.14 .AND. lwork1.GE.minsize ) THEN
328 IF( iam.EQ.0 )
329 $ WRITE( nout, fmt = 9996 )info
330 result = 1
331 END IF
332
333 IF( result.EQ.0 .OR. info.GT.n ) THEN
334
335
336
337
338 DO 70 i = 1, n
339 work( i ) = wnew( i+iprepad )
340 work( i+n ) = wnew( i+iprepad )
341 70 CONTINUE
342
343 CALL dgamn2d( desca( ctxt_ ), 'a', ' ', n, 1, work, n, 1,
344 $ 1, -1, -1, 0 )
345 CALL dgamx2d( desca( ctxt_ ), 'a', ' ', n, 1,
346 $ work( 1+n ), n, 1, 1, -1, -1, 0 )
347
348 DO 80 i = 1, n
349
350 IF( abs( work( i )-work( n+i ) ).GT.zero ) THEN
351 IF( iam.EQ.0 )
352 $ WRITE( nout, fmt = 9995 )
353 result = 1
354 GO TO 90
355 END IF
356 80 CONTINUE
357 90 CONTINUE
358 END IF
359
360 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, result, 1, 1, 1,
361 $ -1, -1, 0 )
362
363
364
365 IF( n.EQ.0 ) THEN
366 epsnorma = eps
367 ELSE
368 epsnorma =
pdlansy(
'I', uplo, n, copya, ia, ja, desca,
369 $ work )*eps
370 END IF
371
372
373
374
375
376
377
378
379
380
381
382 IF(
lsame( jobz,
'V' ) )
THEN
383
384
385
386 CALL pdfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
387 $ iprepad, ipostpad, 4.3d+0 )
388
389 resaq = 0
390
391 CALL pdsepchk( n, n, copya, ia, ja, desca,
392 $
max( abstol+epsnorma, safmin ), thresh,
393 $ z( 1+iprepad ), ia, ja, descz,
394 $ a( 1+iprepad ), ia, ja, desca,
395 $ wnew( 1+iprepad ), work( 1+iprepad ),
396 $ sizechk, tstnrm, resaq )
397
398 CALL pdchekpad( desca( ctxt_ ),
'PDSEPCHK-WORK', sizechk, 1,
399 $ work, sizechk, iprepad, ipostpad, 4.3d+0 )
400
401 IF( resaq.NE.0 ) THEN
402 result = 1
403 WRITE( nout, fmt = 9993 )
404 END IF
405
406
407
408 CALL pdfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
409 $ iprepad, ipostpad, 4.3d+0 )
410
411 resqtq = 0
412
413 CALL pdsepqtq( n, n, thresh, z( 1+iprepad ), ia, ja, descz,
414 $ a( 1+iprepad ), ia, ja, desca,
415 $ iwork( 1 ), iwork( 1 ), work( 1 ),
416 $ work( iprepad+1 ), sizeqtq, qtqnrm, info,
417 $ resqtq )
418
419 CALL pdchekpad( desca( ctxt_ ),
'PDSEPQTQ-WORK', sizeqtq, 1,
420 $ work, sizeqtq, iprepad, ipostpad, 4.3d+0 )
421
422 IF( resqtq.NE.0 ) THEN
423 result = 1
424 WRITE( nout, fmt = 9992 )
425 END IF
426
427 IF( info.NE.0 ) THEN
428 IF( iam.EQ.0 )
429 $ WRITE( nout, fmt = 9998 )info
430 result = 1
431 END IF
432 END IF
433
434
435
436 IF( wknown .AND. n.GT.0 ) THEN
437
438
439
440
441 minerror = normwin
442 maxerror = 0
443
444 DO 140 i = 1, n
445 error = abs( win( i+iprepad )-wnew( i+iprepad ) )
446 maxerror =
max( maxerror, error )
447 140 CONTINUE
448 minerror =
min( maxerror, minerror )
449
450 IF( minerror.GT.normwin*five*thresh*eps ) THEN
451 IF( iam.EQ.0 )
452 $ WRITE( nout, fmt = 9997 )minerror, normwin
453 result = 1
454 END IF
455 END IF
456 END IF
457
458
459
460 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, result, 1, 1, 1, -1,
461 $ -1, 0 )
462
463 150 CONTINUE
464
465
466 RETURN
467
468 9999 FORMAT( 'PDSYEV returned INFO=', i7 )
469 9998 FORMAT( 'PDSEPQTQ in PDSQPSUBTST returned INFO=', i7 )
470 9997 FORMAT( 'PDSQPSUBTST minerror =', d11.2, ' normwin=', d11.2 )
471 9996 FORMAT( 'PDSYEV returned INFO=', i7,
472 $ ' despite adequate workspace' )
473 9995 FORMAT( 'Different processes return different eigenvalues' )
474 9994 FORMAT( 'Heterogeneity detected by PDSYEV' )
475 9993 FORMAT( 'PDSYEV failed the |AQ -QE| test' )
476 9992 FORMAT( 'PDSYEV failed the |QTQ -I| test' )
477
478
479
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 pdlasizesyev(jobz, n, desca, minsize)
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 pdsyev(jobz, uplo, n, a, ia, ja, desca, w, z, iz, jz, descz, work, lwork, info)