OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
pssvdtst.f
Go to the documentation of this file.
1 SUBROUTINE pssvdtst( M, N, NPROW, NPCOL, NB, ISEED, THRESH, WORK,
2 $ RESULT, LWORK, NOUT )
3*
4* -- ScaLAPACK routine (version 1.7) --
5* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
6* and University of California, Berkeley.
7* May 1, 1997
8*
9* .. Scalar Arguments ..
10 INTEGER LWORK, M, N, NB, NOUT, NPCOL, NPROW
11 REAL THRESH
12* ..
13* .. Array Arguments ..
14 INTEGER ISEED( 4 ), RESULT( 9 )
15 REAL WORK( * )
16* ..
17*
18* Purpose
19* =======
20*
21* PSSVDTST checks the singular value decomposition (SVD) routine
22* PSGESVD. PSGESVD factors A = U diag(S) VT, where U and VT are
23* orthogonal and diag(S) is diagonal with the entries of the array
24* S on its diagonal. The entries of S are the singular values, stored
25* in decreasing order. U and VT can be optionally not computed,
26* computed and overwritten on A, or computed partially.
27*
28* A is M by N. Let SIZE = min( M, N ). S has dimension SIZE by SIZE.
29* U is M by SIZE and VT is SIZE by N. PDGESVD optionally calculates
30* U and VT, depending on the values of its parameters JOBU and JOBVT.
31* There are four possible combinations of "job" parameters for a call
32* to PDGESVD, that correspond to four values of internal index JOBTYPE.
33* The table below shows the mapping between "job" parameters of
34* PDGESVD and respective values of the index JOBTYPE together
35* with matrices computed for each type of the job.
36*
37*
38* | JOBU = 'V' | JOBU = 'N'
39* ---------- -------------------------------------------
40* JOBVT = 'V'| JOBTYPE = 1 | JOBTYPE = 3
41* | U1, S1, VT1 | S3, VT3
42* ---------- ------------------------------------------
43* JOBVT = 'N'| JOBTYPE = 2 | JOBTYPE = 4
44* | U2, S2 | S4
45*
46*
47* When PSSVDTST is called, a number of matrix "types" are specified.
48* For each type of matrix, and for the minimal workspace as well as
49* for larger than minimal workspace an M x N matrix "A" with known
50* singular values is generated and used to test the SVD routines.
51* For each matrix, A will be factored as A = U diag(S) VT and the
52* following 9 tests computed:
53*
54* (1) | A - U1 diag(S1) VT1 | / ( |A| max(M,N) ulp )
55*
56* (2) | I - U1'U1 | / ( M ulp )
57*
58* (3) | I - VT1 VT1' | / ( N ulp ),
59*
60* (4) S1 contains SIZE nonnegative values in decreasing order.
61* (Return 0 if true, 1/ULP if false.)
62*
63* (5) | S1 - S2 | / ( SIZE ulp |S| )
64*
65* (6) | U1 - U2 | / ( M ulp )
66*
67* (7) | S1 - S3 | / ( SIZE ulp |S| )
68*
69* (8) | VT1 - VT3 | / ( N ulp )
70*
71* (9) | S1 - S4 | / ( SIZE ulp |S| )
72*
73* Currently, the list of possible matrix types is:
74*
75* (1) The zero matrix.
76*
77* (2) The identity matrix.
78*
79* (3) A diagonal matrix with evenly spaced entries
80* 1, ..., ULP.
81* (ULP = (first number larger than 1) - 1 )
82*
83* (4) A matrix of the form U D VT, where U, VT are orthogonal and
84* D has evenly spaced entries 1, ..., ULP.
85*
86* (5) Same as (4), but multiplied by SQRT( overflow threshold )
87*
88* (6) Same as (4), but multiplied by SQRT( underflow threshold )
89*
90*
91* Notes
92* =====
93*
94* Each global data object is described by an associated description
95* vector. This vector stores the information required to establish
96* the mapping between an object element and its corresponding process
97* and memory location.
98*
99* Let A be a generic term for any 2D block cyclicly distributed array.
100* Such a global array has an associated description vector DESCA.
101* In the following comments, the character _ should be read as
102* "of the global array".
103*
104* NOTATION STORED IN EXPLANATION
105* --------------- -------------- --------------------------------------
106* DTYPE_A(global) DESCA( DTYPE_ )The descriptor type. In this case,
107* DTYPE_A = 1.
108* CTXT_A (global) DESCA( CTXT_ ) The BLACS context handle, indicating
109* the BLACS process grid A is distribu-
110* ted over. The context itself is glo-
111* bal, but the handle (the integer
112* value) may vary.
113* M_A (global) DESCA( M_ ) The number of rows in the global
114* array A.
115* N_A (global) DESCA( N_ ) The number of columns in the global
116* array A.
117* MB_A (global) DESCA( MB_ ) The blocking factor used to distribute
118* the rows of the array.
119* NB_A (global) DESCA( NB_ ) The blocking factor used to distribute
120* the columns of the array.
121* RSRC_A (global) DESCA( RSRC_ ) The process row over which the first
122* row of the array A is distributed.
123* CSRC_A (global) DESCA( CSRC_ ) The process column over which the
124* first column of the array A is
125* distributed.
126* LLD_A (local) DESCA( LLD_ ) The leading dimension of the local
127* array. LLD_A >= MAX(1,LOCr(M_A)).
128*
129* Let K be the number of rows or columns of a distributed matrix,
130* and assume that its process grid has dimension p x q.
131* LOCr( K ) denotes the number of elements of K that a process
132* would receive if K were distributed over the p processes of its
133* process column.
134* Similarly, LOCc( K ) denotes the number of elements of K that a
135* process would receive if K were distributed over the q processes of
136* its process row.
137* The values of LOCr() and LOCc() may be determined via a call to the
138* ScaLAPACK tool function, NUMROC:
139* LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
140* LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
141* An upper bound for these quantities may be computed by:
142* LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
143* LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
144*
145* Arguments
146* ==========
147*
148* M (global input) INTEGER dimension
149* The value of the matrix row dimension.
150*
151* N (global input) INTEGER dimension
152* The value of the matrix column dimension.
153*
154* NPROW (global input) INTEGER
155* Number of process rows
156*
157* NPCOL (global input) INTEGER
158* Number of process columns
159*
160* NB (global input) INTEGER
161* The block size of the matrix A. NB >=1.
162*
163* ISEED (global input/local output) INTEGER array, dimension (4)
164* On entry, the seed of the random number generator. The array
165* elements should be between 0 and 4095; if not they will be
166* reduced mod 4096. Also, ISEED(4) must be odd.
167* On exit, ISEED is changed and can be used in the next call to
168* SDRVBD to continue the same random number sequence.
169*
170* THRESH (global input) REAL
171* The threshold value for the test ratios. A result is
172* included in the output file if RESULT >= THRESH. The test
173* ratios are scaled to be O(1), so THRESH should be a small
174* multiple of 1, e.g., 10 or 100. To have every test ratio
175* printed, use THRESH = 0.
176*
177* RESULT (global input/output) INTEGER array of dimension 9. Initially
178* RESULT( I ) = 0. On the output, RESULT ( I ) = 1 if test I
179* ( see above ) wasn't passed.
180*
181* WORK (local workspace) REAL array, dimension (LWORK)
182*
183* LWORK (local input) INTEGER
184* Dimension of the array WORK. It is defined as follows
185* LWORK = 1 + 2*LDA*NQ + 3*SIZE +
186* MAX(WPSLAGGE, LDU*SIZEQ + LDVT*NQ + MAX(LDU*SIZEQ, LDVT*NQ)
187* + WPSGESVD + MAX( WPSSVDCHK, WPSSVDCMP)),
188* where WPSLAGGE, WPSGESVD, WPSSVDCHK, WPSSVDCMP are amounts
189* of workspace required respectively by PSLAGGE, PSGESVD,
190* PSSVDCHK, PSSVDCMP.
191* Here
192* LDA = NUMROC( M, NB, MYROW, 0, NPROW ), LDU = LDA,
193* LDVT = NUMROC( SIZE, NB, MYROW, 0, NPROW ),
194* NQ = NUMROC( N, NB, MYCOL, 0, NPCOL ),
195* SIZEQ = NUMROC( SIZE, NB, MYCOL, 0, NPCOL ).
196* Values of the variables WPSLAGGE, WPSGESVD, WPSSVDCHK,
197* WPSSVDCMP are found by "dummy" calls to
198* the respective routines. In every "dummy" call, variable
199* LWORK is set to -1, thus causing respective routine
200* immediately return required workspace in WORK(1) without
201* executing any calculations
202*
203* NOUT (local input) INTEGER
204* The unit number for output file. Only used on node 0.
205* NOUT = 6, output to screen,
206* NOUT = 0, output to stderr.
207* =====================================================================
208*
209* .. Parameters ..
210 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
211 $ mb_, nb_, rsrc_, csrc_, lld_, ntypes
212 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
213 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
214 $ rsrc_ = 7, csrc_ = 8, lld_ = 9, ntypes = 6 )
215 REAL ZERO, ONE
216 parameter( zero = 0.0e0, one = 1.0e0 )
217* ..
218* .. Local Scalars ..
219 CHARACTER HETERO, JOBU, JOBVT
220 INTEGER CONTEXT, DINFO, I, IA, IAM, INFO, ITYPE, IU,
221 $ ivt, ja, jobtype, ju, jvt, lda, ldu, ldvt,
222 $ llwork, lwmin, mycol, myrow, nnodes, nq, pass,
223 $ ptra, ptrac, ptrd, ptrs, ptrsc, ptru, ptruc,
224 $ ptrvt, ptrvtc, ptrwork, sethet, SIZE, sizeq,
225 $ wpsgesvd, wpslagge, wpssvdchk, wpssvdcmp
226 REAL CHK, DELTA, H, MTM, OVFL, RTOVFL, RTUNFL, ULP,
227 $ unfl
228* ..
229* .. External Subroutines ..
230 EXTERNAL blacs_barrier, blacs_get, blacs_gridexit,
231 $ blacs_gridinfo, blacs_gridinit, blacs_pinfo,
232 $ blacs_set,
233 $ descinit, sgamn2d, sgamx2d, slabad, sscal,
234 $ igamn2d, igamx2d, igebr2d, igebs2d, pselset,
237* ..
238* .. External Functions ..
239 INTEGER NUMROC
240 REAL PSLAMCH
241 EXTERNAL numroc, pslamch
242* ..
243* .. Local Arrays ..
244 INTEGER DESCA( DLEN_ ), DESCU( DLEN_ ),
245 $ descvt( dlen_ ), itmp( 2 )
246 DOUBLE PRECISION CTIME( 1 ), WTIME( 1 )
247* ..
248* .. Intrinsic Functions ..
249 INTRINSIC abs, int, max, min, sqrt
250* ..
251* .. Executable Statements ..
252* This is just to keep ftnchek happy
253 IF( block_cyclic_2d*csrc_*dtype_*lld_*mb_*m_*nb_*n_*rsrc_.LT.0 )
254 $ RETURN
255*
256 CALL blacs_pinfo( iam, nnodes )
257 CALL blacs_get( -1, 0, context )
258 CALL blacs_gridinit( context, 'R', nprow, npcol )
259 CALL blacs_gridinfo( context, nprow, npcol, myrow, mycol )
260*
261* If this process is not a part of the contex, bail out now.
262*
263 IF( ( myrow.GE.nprow ) .OR. ( myrow.LT.0 ) .OR.
264 $ ( mycol.GE.npcol ) .OR. ( mycol.LT.0 ) )GO TO 110
265 CALL blacs_set( context, 15, 1 )
266 info = 0
267*
268* Check input parameters.
269*
270 IF( m.LE.0 ) THEN
271 info = -1
272 ELSE IF( n.LE.0 ) THEN
273 info = -2
274 ELSE IF( nprow.LE.0 ) THEN
275 info = -3
276 ELSE IF( npcol.LE.0 ) THEN
277 info = -4
278 ELSE IF( nb.LE.0 ) THEN
279 info = -5
280 ELSE IF( thresh.LE.0 ) THEN
281 info = -7
282 END IF
283*
284 SIZE = min( m, n )
285*
286* Initialize matrix descriptors.
287*
288 ia = 1
289 ja = 1
290 iu = 1
291 ju = 1
292 ivt = 1
293 jvt = 1
294*
295 lda = numroc( m, nb, myrow, 0, nprow )
296 lda = max( 1, lda )
297 nq = numroc( n, nb, mycol, 0, npcol )
298 ldu = lda
299 sizeq = numroc( SIZE, nb, mycol, 0, npcol )
300 ldvt = numroc( SIZE, nb, myrow, 0, nprow )
301 ldvt = max( 1, ldvt )
302 CALL descinit( desca, m, n, nb, nb, 0, 0, context, lda, dinfo )
303 CALL descinit( descu, m, SIZE, nb, nb, 0, 0, context, ldu, dinfo )
304 CALL descinit( descvt, SIZE, n, nb, nb, 0, 0, context, ldvt,
305 $ dinfo )
306*
307* Set some pointers to work array in order to do "dummy" calls.
308*
309 ptra = 2
310 ptrac = ptra + lda*nq
311 ptrd = ptrac + lda*nq
312 ptrs = ptrd + SIZE
313 ptrsc = ptrs + SIZE
314 ptrwork = ptrsc + SIZE
315*
316 ptru = ptrwork
317 ptrvt = ptrwork
318 ptruc = ptrwork
319 ptrvtc = ptrwork
320*
321* "Dummy" calls -- return required workspace in work(1) without
322* any calculation.
323*
324 CALL pslagge( m, n, work( ptrd ), work( ptra ), ia, ja, desca,
325 $ iseed, SIZE, work( ptrwork ), -1, dinfo )
326 wpslagge = int( work( ptrwork ) )
327*
328 CALL psgesvd( 'v', 'v', M, N, WORK( PTRA ), IA, JA, DESCA,
329 $ WORK( PTRS ), WORK( PTRU ), IU, JU, DESCU,
330 $ WORK( PTRVT ), IVT, JVT, DESCVT,
331 $ WORK( PTRWORK ), -1, DINFO )
332 WPSGESVD = INT( WORK( PTRWORK ) )
333*
334 CALL PSSVDCHK( M, N, WORK( PTRAC ), IA, JA, DESCA, WORK( PTRUC ),
335 $ IU, JU, DESCU, WORK( PTRVT ), IVT, JVT, DESCVT,
336 $ WORK( PTRS ), THRESH, WORK( PTRWORK ), -1,
337 $ RESULT, CHK, MTM )
338 WPSSVDCHK = INT( WORK( PTRWORK ) )
339*
340 CALL PSSVDCMP( M, N, 1, WORK( PTRS ), WORK( PTRSC ), WORK( PTRU ),
341 $ WORK( PTRUC ), IU, JU, DESCU, WORK( PTRVT ),
342 $ WORK( PTRVTC ), IVT, JVT, DESCVT, THRESH,
343 $ RESULT, DELTA, WORK( PTRWORK ), -1 )
344 WPSSVDCMP = INT( WORK( PTRWORK ) )
345*
346* Calculation of workspace at last.
347*
348 LWMIN = 1 + 2*LDA*NQ + 3*SIZE +
349 $ MAX( WPSLAGGE, LDU*SIZEQ+LDVT*NQ+MAX( LDU*SIZEQ,
350 $ LDVT*NQ )+WPSGESVD+MAX( WPSSVDCHK, WPSSVDCMP ) )
351 WORK( 1 ) = LWMIN
352*
353* If this is a "dummy" call, return.
354*
355.EQ. IF( LWORK-1 )
356 $ GO TO 120
357.EQ. IF( INFO0 ) THEN
358.LT. IF( LWORKLWMIN ) THEN
359 INFO = -10
360 END IF
361 END IF
362*
363.NE. IF( INFO0 ) THEN
364 CALL PXERBLA( DESCA( CTXT_ ), 'pssvdtst', -INFO )
365 RETURN
366 END IF
367*
368 ULP = PSLAMCH( CONTEXT, 'p' )
369 UNFL = PSLAMCH( CONTEXT, 'safe min' )
370 OVFL = ONE / UNFL
371 CALL SLABAD( UNFL, OVFL )
372 RTUNFL = SQRT( UNFL )
373 RTOVFL = SQRT( OVFL )
374*
375* This ensures that everyone starts out with the same seed.
376*
377.EQ..AND..EQ. IF( MYROW0 MYCOL0 ) THEN
378 CALL IGEBS2D( CONTEXT, 'a', ' ', 4, 1, ISEED, 4 )
379 ELSE
380 CALL IGEBR2D( CONTEXT, 'a', ' ', 4, 1, ISEED, 4, 0, 0 )
381 END IF
382*
383* Loop over matrix types.
384*
385 DO 100 ITYPE = 1, NTYPES
386*
387 PASS = 0
388 SETHET = 0
389 PTRWORK = PTRSC + SIZE
390 LLWORK = LWORK - PTRWORK + 1
391*
392* Compute A.
393*
394.EQ. IF( ITYPE1 ) THEN
395*
396* Zero Matrix.
397*
398 DO 10 I = 1, SIZE
399 WORK( PTRD+I-1 ) = ZERO
400 10 CONTINUE
401*
402 CALL PSLASET( 'all', M, N, ZERO, ZERO, WORK( PTRA ),
403 $ IA, JA, DESCA )
404*
405.EQ. ELSE IF( ITYPE2 ) THEN
406*
407* Identity Matrix.
408*
409 DO 20 I = 1, SIZE
410 WORK( PTRD+I-1 ) = ONE
411 20 CONTINUE
412*
413 CALL PSLASET( 'all', M, N, ZERO, ONE, WORK( PTRA ),
414 $ IA, JA, DESCA )
415*
416.GT. ELSE IF( ITYPE2 ) THEN
417*
418* Preset Singular Values.
419*
420.NE. IF( SIZE1 ) THEN
421 H = ( ULP-1 ) / ( SIZE-1 )
422 DO 30 I = 1, SIZE
423 WORK( PTRD+I-1 ) = 1 + H*( I-1 )
424 30 CONTINUE
425 ELSE
426 WORK( PTRD ) = 1
427 END IF
428*
429.EQ. IF( ITYPE3 ) THEN
430*
431* Diagonal Matrix with specified singular values.
432*
433 CALL PSLASET( 'all', M, N, ZERO, ZERO, WORK( PTRA ),
434 $ IA, JA, DESCA )
435*
436 DO 40 I = 1, SIZE
437 CALL PSELSET( WORK( PTRA ), I, I, DESCA,
438 $ WORK( PTRD+I-1 ) )
439 40 CONTINUE
440*
441.EQ. ELSE IF( ITYPE4 ) THEN
442*
443* General matrix with specified singular values.
444*
445 CALL PSLAGGE( M, N, WORK( PTRD ), WORK( PTRA ), IA, JA,
446 $ DESCA, ISEED, SIZE, WORK( PTRWORK ),
447 $ LLWORK, INFO )
448*
449.EQ. ELSE IF( ITYPE5 ) THEN
450*
451* Singular values scaled by overflow.
452*
453 CALL SSCAL( SIZE, RTOVFL, WORK( PTRD ), 1 )
454*
455 CALL PSLAGGE( M, N, WORK( PTRD ), WORK( PTRA ), IA, JA,
456 $ DESCA, ISEED, SIZE, WORK( PTRWORK ),
457 $ LLWORK, INFO )
458*
459.EQ. ELSE IF( ITYPE6 ) THEN
460*
461* Singular values scaled by underflow.
462*
463 CALL SSCAL( SIZE, RTUNFL, WORK( PTRD ), 1 )
464 CALL PSLAGGE( M, N, WORK( PTRD ), WORK( PTRA ), IA, JA,
465 $ DESCA, ISEED, SIZE, WORK( PTRWORK ),
466 $ LLWORK, INFO )
467*
468 END IF
469*
470 END IF
471*
472* Set mapping between JOBTYPE and calling parameters of
473* PSGESVD, reset pointers to WORK array to save space.
474*
475 DO 80 JOBTYPE = 1, 4
476*
477.EQ. IF( JOBTYPE1 ) THEN
478 JOBU = 'v'
479 JOBVT = 'v'
480 PTRVT = PTRU + LDU*SIZEQ
481 PTRUC = PTRVT + LDVT*NQ
482 PTRWORK = PTRUC + LDU*SIZEQ
483 LLWORK = LWORK - PTRWORK + 1
484.EQ. ELSE IF( JOBTYPE2 ) THEN
485 JOBU = 'v'
486 JOBVT = 'n'
487.EQ. ELSE IF( JOBTYPE3 ) THEN
488 JOBU = 'n'
489 JOBVT = 'v'
490 PTRVTC = PTRUC
491 PTRWORK = PTRVTC + LDVT*NQ
492 LLWORK = LWORK - PTRWORK + 1
493.EQ. ELSE IF( JOBTYPE4 ) THEN
494 JOBU = 'n'
495 JOBVT = 'n'
496 PTRWORK = PTRUC
497 LLWORK = LWORK - PTRWORK + 1
498 END IF
499*
500* Duplicate matrix A.
501*
502 CALL PSLACPY( 'a', M, N, WORK( PTRA ), IA, JA, DESCA,
503 $ WORK( PTRAC ), IA, JA, DESCA )
504*
505* Test SVD calculation with minimum amount of workspace
506* calculated earlier.
507*
508.EQ. IF( JOBTYPE1 ) THEN
509*
510* Run SVD.
511 CALL SLBOOT
512 CALL BLACS_BARRIER( CONTEXT, 'all' )
513 CALL SLTIMER( 1 )
514*
515 CALL PSGESVD( JOBU, JOBVT, M, N, WORK( PTRAC ), IA, JA,
516 $ DESCA, WORK( PTRS ), WORK( PTRU ), IU, JU,
517 $ DESCU, WORK( PTRVT ), IVT, JVT, DESCVT,
518 $ WORK( PTRWORK ), WPSGESVD, INFO )
519*
520 CALL SLTIMER( 1 )
521 CALL SLCOMBINE( CONTEXT, 'all', '>', 'w', 1, 1, WTIME )
522 CALL SLCOMBINE( CONTEXT, 'all', '>', 'c', 1, 1, CTIME )
523*
524* Check INFO. Different INFO for different processes mean
525* something went wrong.
526*
527 ITMP( 1 ) = INFO
528 ITMP( 2 ) = INFO
529*
530 CALL IGAMN2D( DESCA( CTXT_ ), 'a', ' ', 1, 1, ITMP, 1, 1,
531 $ 1, -1, -1, 0 )
532 CALL IGAMX2D( DESCA( CTXT_ ), 'a', ' ', 1, 1, ITMP( 2 ),
533 $ 1, 1, 1, -1, -1, 0 )
534*
535.NE. IF( ITMP( 1 )ITMP( 2 ) ) THEN
536.EQ..AND..EQ. IF( MYROW0 MYCOL0 ) THEN
537 WRITE( NOUT, FMT = * )
538 $ 'different processes return different info'
539 GO TO 120
540 END IF
541 END IF
542*
543* If INFO is negative PXERBLA tells you. So the only thing
544* is to check for positive INFO -- detected heterogeneous
545* system.
546*
547.EQ. IF( INFO( SIZE+1 ) ) THEN
548 HETERO = 'p'
549 SETHET = 1
550 END IF
551*
552* If INFO was fine do more exhaustive check.
553*
554.EQ. IF( INFOZERO ) THEN
555*
556 DO 50 I = 1, SIZE
557 WORK( I+PTRWORK ) = WORK( I+PTRS-1 )
558 WORK( I+SIZE+PTRWORK ) = WORK( I+PTRS-1 )
559 50 CONTINUE
560*
561 CALL SGAMN2D( DESCA( CTXT_ ), 'a', ' ', SIZE, 1,
562 $ WORK( 1+PTRWORK ), SIZE, 1, 1, -1, -1,
563 $ 0 )
564 CALL SGAMX2D( DESCA( CTXT_ ), 'a', ' ', SIZE, 1,
565 $ WORK( 1+SIZE+PTRWORK ), SIZE, 1, 1, -1,
566 $ -1, 0 )
567*
568 DO 60 I = 1, SIZE
569 IF( ABS( WORK( I+PTRWORK )-WORK( SIZE+I+
570.GT. $ PTRWORK ) )ZERO ) THEN
571 WRITE( NOUT, FMT = * )'i= ', I, ' min=',
572 $ WORK( I+PTRWORK ), ' max=',
573 $ WORK( SIZE+I+PTRWORK )
574 HETERO = 't'
575 SETHET = 1
576 GO TO 70
577 END IF
578*
579 60 CONTINUE
580 70 CONTINUE
581*
582 END IF
583*
584.NE. IF( SETHET1 )
585 $ HETERO = 'n'
586*
587* After PSGESVD AC got screwed up -- need to copy again.
588*
589 CALL PSLACPY( 'a', M, N, WORK( PTRA ), IA, JA, DESCA,
590 $ WORK( PTRAC ), IA, JA, DESCA )
591*
592* PSSVDCHK screws up U. So before the call to PSSVDCHK
593* U is copied to UC and a pointer to UC is passed to
594* PSSVDCHK.
595*
596 CALL PSLACPY( 'a', M, SIZE, WORK( PTRU ), IU, JU, DESCU,
597 $ WORK( PTRUC ), IU, JU, DESCU )
598*
599* Run tests 1 - 4.
600*
601 CALL PSSVDCHK( M, N, WORK( PTRAC ), IA, JA, DESCA,
602 $ WORK( PTRUC ), IU, JU, DESCU,
603 $ WORK( PTRVT ), IVT, JVT, DESCVT,
604 $ WORK( PTRS ), THRESH, WORK( PTRWORK ),
605 $ LLWORK, RESULT, CHK, MTM )
606*
607 ELSE
608*
609* Once again test PSGESVD with min workspace.
610*
611 CALL PSGESVD( JOBU, JOBVT, M, N, WORK( PTRAC ), IA, JA,
612 $ DESCA, WORK( PTRSC ), WORK( PTRUC ), IU,
613 $ JU, DESCU, WORK( PTRVTC ), IVT, JVT,
614 $ DESCVT, WORK( PTRWORK ), WPSGESVD, INFO )
615*
616 CALL PSSVDCMP( M, N, JOBTYPE, WORK( PTRS ),
617 $ WORK( PTRSC ), WORK( PTRU ),
618 $ WORK( PTRUC ), IU, JU, DESCU,
619 $ WORK( PTRVT ), WORK( PTRVTC ), IVT, JVT,
620 $ DESCVT, THRESH, RESULT, DELTA,
621 $ WORK( PTRWORK ), LLWORK )
622*
623 END IF
624*
625 80 CONTINUE
626*
627.EQ..AND..EQ. IF( MYROW0 MYCOL0 ) THEN
628 DO 90 I = 1, 9
629.EQ. IF( RESULT( I )1 ) THEN
630 PASS = 1
631 WRITE( NOUT, FMT = * )'test i = ', I, 'has failed'
632 WRITE( NOUT, FMT = * )' '
633 END IF
634 90 CONTINUE
635.EQ. IF( PASS0 ) THEN
636 WRITE( NOUT, FMT = 9999 )'passed', WTIME( 1 ),
637 $ CTIME( 1 ), M, N, NPROW, NPCOL, NB, ITYPE, CHK, MTM,
638 $ DELTA, HETERO
639 END IF
640 END IF
641 100 CONTINUE
642 CALL BLACS_GRIDEXIT( CONTEXT )
643 110 CONTINUE
644*
645 9999 FORMAT( A6, 2E10.3, 2I6, 2I4, I5, I6, 3F6.2, 4X, A1 )
646 120 CONTINUE
647*
648* End of PSSVDTST
649*
650 RETURN
651 END
subroutine slabad(small, large)
SLABAD
Definition slabad.f:74
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
#define min(a, b)
Definition macros.h:20
#define max(a, b)
Definition macros.h:21
subroutine blacs_gridinit(cntxt, c, nprow, npcol)
Definition mpi.f:745
subroutine pxerbla(contxt, srname, info)
Definition mpi.f:1600
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
Definition mpi.f:777
subroutine blacs_gridexit(cntxt)
Definition mpi.f:762
subroutine blacs_gridinfo(cntxt, nprow, npcol, myrow, mycol)
Definition mpi.f:754
subroutine pslaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
Definition psblastst.f:6863
subroutine pselset(a, ia, ja, desca, alpha)
Definition pselset.f:2
subroutine psgesvd(jobu, jobvt, m, n, a, ia, ja, desca, s, u, iu, ju, descu, vt, ivt, jvt, descvt, work, lwork, info)
Definition psgesvd.f:4
subroutine pslacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
Definition pslacpy.f:3
subroutine pslagge(m, n, d, a, ia, ja, desca, iseed, order, work, lwork, info)
Definition pslagge.f:3
subroutine pssvdchk(m, n, a, ia, ja, desca, u, iu, ju, descu, vt, ivt, jvt, descvt, s, thresh, work, lwork, result, chk, mtm)
Definition pssvdchk.f:4
subroutine pssvdcmp(m, n, jobtype, s, sc, u, uc, iu, ju, descu, vt, vtc, ivt, jvt, descvt, thresh, result, delta, work, lwork)
Definition pssvdcmp.f:4
subroutine pssvdtst(m, n, nprow, npcol, nb, iseed, thresh, work, result, lwork, nout)
Definition pssvdtst.f:3
subroutine slboot()
Definition sltimer.f:2
subroutine sltimer(i)
Definition sltimer.f:47
subroutine slcombine(ictxt, scope, op, timetype, n, ibeg, times)
Definition sltimer.f:267