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 REAL ABSTOL, QTQNRM, THRESH, TSTNRM
18
19
20 INTEGER DESCA( * ), IWORK( * )
21 REAL 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 REAL FIVE, NEGONE, PADVAL, ZERO
152 parameter( padval = 13.5285e+0, five = 5.0e+0,
153 $ negone = -1.0e+0, zero = 0.0e+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 REAL 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 REAL PSLAMCH, PSLANSY
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 pslasizesqp( desca, iprepad, ipostpad, sizemqrleft,
190 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
191 $ sizechk, sizesyevx, isizesyevx, sizesyev,
192 $ sizesyevd, isizesyevd, sizesubtst,
193 $ isizesubtst, sizetst, isizetst )
194
195 tstnrm = negone
196 qtqnrm = negone
197 eps =
pslamch( desca( ctxt_ ),
'Eps' )
198 safmin =
pslamch( 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.3e+0
209 10 CONTINUE
210
211 DO 30 i = 1, n
212 wnew( i+iprepad ) = 3.14159e+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 slacpy( 'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
241 $ desca( lld_ ) )
242
243 CALL psfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
244 $ ipostpad, padval )
245
246 CALL psfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
247 $ ipostpad, padval+1.0e+0 )
248
249 CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
250 $ padval+2.0e+0 )
251
252 CALL psfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
253 $ ipostpad, padval+4.0e+0 )
254
255
256
257
258 DO 60 i = 1, n, 1
259 DO 50 j = 1, n, 1
260 CALL pselset( z( 1+iprepad ), i, j, desca, 13.0e+0 )
261 50 CONTINUE
262 60 CONTINUE
263
267 CALL pssyevd(
'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 pschekpad( desca( ctxt_ ),
'PSSYEVD-A', np, nq, a,
278 $ desca( lld_ ), iprepad, ipostpad, padval )
279
280 CALL pschekpad( descz( ctxt_ ),
'PSSYEVD-Z', np, mq, z,
281 $ descz( lld_ ), iprepad, ipostpad,
282 $ padval+1.0e+0 )
283
284 CALL pschekpad( desca( ctxt_ ),
'PSSYEVD-WNEW', n, 1, wnew, n,
285 $ iprepad, ipostpad, padval+2.0e+0 )
286
287 CALL pschekpad( desca( ctxt_ ),
'PSSYEVD-WORK', lwork1, 1,
288 $ work, lwork1, iprepad, ipostpad,
289 $ padval+4.0e+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 sgamn2d( desca( ctxt_ ), 'a', ' ', n, 1, work, n, 1,
334 $ 1, -1, -1, 0 )
335 CALL sgamx2d( 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 =
pslansy(
'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 psfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
376 $ iprepad, ipostpad, 4.3e+0 )
377
378 resaq = 0
379
380 CALL pssepchk( 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 pschekpad( desca( ctxt_ ),
'PSSEPCHK-WORK', sizechk, 1,
388 $ work, sizechk, iprepad, ipostpad, 4.3e+0 )
389
390 IF( resaq.NE.0 ) THEN
391 result = 1
392 WRITE( nout, fmt = 9993 )
393 END IF
394
395
396
397 CALL psfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
398 $ iprepad, ipostpad, 4.3e+0 )
399
400 resqtq = 0
401
402
403 DO 40 i = 1, 2
404 iwork( iprepad + i ) = 0
405 40 CONTINUE
406 CALL pssepqtq( 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 pschekpad( desca( ctxt_ ),
'PSSEPQTQ-WORK', sizeqtq, 1,
413 $ work, sizeqtq, iprepad, ipostpad, 4.3e+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
438
439 DO 140 i = 1, n
440 error = abs( win( i+iprepad )-wnew( i+iprepad ) )
441 maxerror =
max( maxerror, error )
442 140 CONTINUE
443 minerror =
min( maxerror, minerror )
444
445 IF( minerror.GT.normwin*five*thresh*eps ) THEN
446 IF( iam.EQ.0 )
447 $ WRITE( nout, fmt = 9997 )minerror, normwin
448 result = 1
449 END IF
450 END IF
451
452
453
454 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, result, 1, 1, 1, -1,
455 $ -1, 0 )
456
457 150 CONTINUE
458
459
460 RETURN
461
462 9999 FORMAT( 'PSSYEVD returned INFO=', i7 )
463 9998 FORMAT( 'PSSEPQTQ in PSSDPSUBTST returned INFO=', i7 )
464 9997 FORMAT( 'PSSDPSUBTST minerror =', d11.2, ' normwin=', d11.2 )
465 9996 FORMAT( 'PSSYEVD returned INFO=', i7,
466 $ ' despite adequate workspace' )
467 9995 FORMAT( 'Different processes return different eigenvalues' )
468 9994 FORMAT( 'Heterogeneity detected by PSSYEVD' )
469 9993 FORMAT( 'PSSYEVD failed the |AQ -QE| test' )
470 9992 FORMAT( 'PSSYEVD failed the |QTQ -I| test' )
471
472
473
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
real function pslamch(ictxt, cmach)
subroutine pschekpad(ictxt, mess, m, n, a, lda, ipre, ipost, chkval)
subroutine pselset(a, ia, ja, desca, alpha)
subroutine psfillpad(ictxt, m, n, a, lda, ipre, ipost, chkval)
real function pslansy(norm, uplo, n, a, ia, ja, desca, work)
subroutine pslasizesqp(desca, iprepad, ipostpad, sizemqrleft, sizemqrright, sizeqrf, sizetms, sizeqtq, sizechk, sizesyevx, isizesyevx, sizesyev, sizesyevd, isizesyevd, sizesubtst, isizesubtst, sizetst, isizetst)
subroutine pssepchk(ms, nv, a, ia, ja, desca, epsnorma, thresh, q, iq, jq, descq, c, ic, jc, descc, w, work, lwork, tstnrm, result)
subroutine pssepqtq(ms, nv, thresh, q, iq, jq, descq, c, ic, jc, descc, procdist, iclustr, gap, work, lwork, qtqnrm, info, res)
subroutine pssyevd(jobz, uplo, n, a, ia, ja, desca, w, z, iz, jz, descz, work, lwork, iwork, liwork, info)