SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
pdsvdtst.f
Go to the documentation of this file.
1 SUBROUTINE pdsvdtst( 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 DOUBLE PRECISION THRESH
12* ..
13* .. Array Arguments ..
14 INTEGER ISEED( 4 ), RESULT( 9 )
15 DOUBLE PRECISION WORK( * )
16* ..
17*
18* Purpose
19* =======
20*
21* PDSVDTST checks the singular value decomposition (SVD) routine
22* PDGESVD. PDGESVD 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 PDSVDTST 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) DOUBLE PRECISION
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) DOUBLE PRECISION 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(WPDLAGGE, LDU*SIZEQ + LDVT*NQ + MAX(LDU*SIZEQ, LDVT*NQ)
187* + WPDGESVD + MAX( WPDSVDCHK, WPDSVDCMP)),
188* where WPDLAGGE, WPDGESVD, WPDSVDCHK, WPDSVDCMP are amounts
189* of workspace required respectively by PDLAGGE, PDGESVD,
190* PDSVDCHK, PDSVDCMP.
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 WPDLAGGE, WPDGESVD, WPDSVDCHK,
197* WPDSVDCMP 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 DOUBLE PRECISION ZERO, ONE
216 parameter( zero = 0.0d0, one = 1.0d0 )
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, ptrwork, ptrs, ptrsc, ptru,
224 $ ptruc, ptrvt, ptrvtc, sethet, SIZE, sizeq,
225 $ wpdgesvd, wpdlagge, wpdsvdchk, wpdsvdcmp
226 DOUBLE PRECISION 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, dgamn2d, dgamx2d, dlabad, dscal,
234 $ igamn2d, igamx2d, igebr2d, igebs2d, pdelset,
237* ..
238* .. External Functions ..
239 INTEGER NUMROC
240 DOUBLE PRECISION PDLAMCH
241 EXTERNAL numroc, pdlamch
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 pdlagge( m, n, work( ptrd ), work( ptra ), ia, ja, desca,
325 $ iseed, SIZE, work( ptrwork ), -1, dinfo )
326 wpdlagge = int( work( ptrwork ) )
327*
328 CALL pdgesvd( '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 wpdgesvd = int( work( ptrwork ) )
333*
334 CALL pdsvdchk( 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 wpdsvdchk = int( work( ptrwork ) )
339*
340 CALL pdsvdcmp( 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 wpdsvdcmp = int( work( ptrwork ) )
345*
346* Calculation of workspace at last.
347*
348 lwmin = 1 + 2*lda*nq + 3*SIZE +
349 $ max( wpdlagge, ldu*sizeq+ldvt*nq+max( ldu*sizeq,
350 $ ldvt*nq )+wpdgesvd+max( wpdsvdchk, wpdsvdcmp ) )
351 work( 1 ) = lwmin
352*
353* If this is a "dummy" call, return.
354*
355 IF( lwork.EQ.-1 )
356 $ GO TO 120
357 IF( info.EQ.0 ) THEN
358 IF( lwork.LT.lwmin ) THEN
359 info = -10
360 END IF
361 END IF
362*
363 IF( info.NE.0 ) THEN
364 CALL pxerbla( desca( ctxt_ ), 'PDSVDTST', -info )
365 RETURN
366 END IF
367*
368 ulp = pdlamch( context, 'P' )
369 unfl = pdlamch( context, 'Safe min' )
370 ovfl = one / unfl
371 CALL dlabad( unfl, ovfl )
372 rtunfl = sqrt( unfl )
373 rtovfl = sqrt( ovfl )
374*
375* This ensures that everyone starts out with the same seed.
376*
377 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) 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 IF( itype.EQ.1 ) THEN
395*
396* Zero Matrix.
397*
398 DO 10 i = 1, SIZE
399 work( ptrd+i-1 ) = zero
400 10 CONTINUE
401*
402 CALL pdlaset( 'All', m, n, zero, zero, work( ptra ),
403 $ ia, ja, desca )
404*
405 ELSE IF( itype.EQ.2 ) THEN
406*
407* Identity Matrix.
408*
409 DO 20 i = 1, SIZE
410 work( ptrd+i-1 ) = one
411 20 CONTINUE
412*
413 CALL pdlaset( 'All', m, n, zero, one, work( ptra ),
414 $ ia, ja, desca )
415*
416 ELSE IF( itype.GT.2 ) THEN
417*
418* Preset Singular Values.
419*
420 IF( size.NE.1 ) 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 IF( itype.EQ.3 ) THEN
430*
431* Diagonal Matrix with specified singular values.
432*
433 CALL pdlaset( 'All', m, n, zero, zero, work( ptra ),
434 $ ia, ja, desca )
435*
436 DO 40 i = 1, SIZE
437 CALL pdelset( work( ptra ), i, i, desca,
438 $ work( ptrd+i-1 ) )
439 40 CONTINUE
440*
441 ELSE IF( itype.EQ.4 ) THEN
442*
443* General matrix with specified singular values.
444*
445 CALL pdlagge( m, n, work( ptrd ), work( ptra ), ia, ja,
446 $ desca, iseed, SIZE, work( ptrwork ),
447 $ llwork, info )
448*
449 ELSE IF( itype.EQ.5 ) THEN
450*
451* Singular values scaled by overflow.
452*
453 CALL dscal( SIZE, rtovfl, work( ptrd ), 1 )
454*
455 CALL pdlagge( m, n, work( ptrd ), work( ptra ), ia, ja,
456 $ desca, iseed, SIZE, work( ptrwork ),
457 $ llwork, info )
458*
459 ELSE IF( itype.EQ.6 ) THEN
460*
461* Singular values scaled by underflow.
462*
463 CALL dscal( SIZE, rtunfl, work( ptrd ), 1 )
464 CALL pdlagge( 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* PDGESVD, reset pointers to WORK array to save space.
474*
475 DO 80 jobtype = 1, 4
476*
477 IF( jobtype.EQ.1 ) 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 ELSE IF( jobtype.EQ.2 ) THEN
485 jobu = 'V'
486 jobvt = 'N'
487 ELSE IF( jobtype.EQ.3 ) THEN
488 jobu = 'N'
489 jobvt = 'V'
490 ptrvtc = ptruc
491 ptrwork = ptrvtc + ldvt*nq
492 llwork = lwork - ptrwork + 1
493 ELSE IF( jobtype.EQ.4 ) 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 pdlacpy( '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 IF( jobtype.EQ.1 ) THEN
509*
510* Run SVD.
511*
512 CALL slboot
513 CALL blacs_barrier( context, 'All' )
514 CALL sltimer( 1 )
515*
516 CALL pdgesvd( jobu, jobvt, m, n, work( ptrac ), ia, ja,
517 $ desca, work( ptrs ), work( ptru ), iu, ju,
518 $ descu, work( ptrvt ), ivt, jvt, descvt,
519 $ work( ptrwork ), wpdgesvd, info )
520*
521 CALL sltimer( 1 )
522 CALL slcombine( context, 'All', '>', 'W', 1, 1, wtime )
523 CALL slcombine( context, 'All', '>', 'C', 1, 1, ctime )
524*
525* Check INFO. Different INFO for different processes mean
526* something went wrong.
527*
528 itmp( 1 ) = info
529 itmp( 2 ) = info
530*
531 CALL igamn2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp, 1, 1,
532 $ 1, -1, -1, 0 )
533 CALL igamx2d( desca( ctxt_ ), 'a', ' ', 1, 1, itmp( 2 ),
534 $ 1, 1, 1, -1, -1, 0 )
535*
536 IF( itmp( 1 ).NE.itmp( 2 ) ) THEN
537 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
538 WRITE( nout, fmt = * )
539 $ 'Different processes return different INFO'
540 GO TO 120
541 END IF
542 END IF
543*
544* If INFO is negative PXERBLA tells you. So the only thing
545* is to check for positive INFO -- detected heterogeneous
546* system.
547*
548 IF( info.EQ.( size+1 ) ) THEN
549 hetero = 'P'
550 sethet = 1
551 END IF
552*
553* If INFO was fine do more exhaustive check.
554*
555 IF( info.EQ.zero ) THEN
556*
557 DO 50 i = 1, SIZE
558 work( i+ptrwork ) = work( i+ptrs-1 )
559 work( i+size+ptrwork ) = work( i+ptrs-1 )
560 50 CONTINUE
561*
562 CALL dgamn2d( desca( ctxt_ ), 'a', ' ', SIZE, 1,
563 $ work( 1+ptrwork ), SIZE, 1, 1, -1, -1,
564 $ 0 )
565 CALL dgamx2d( desca( ctxt_ ), 'a', ' ', SIZE, 1,
566 $ work( 1+size+ptrwork ), SIZE, 1, 1, -1,
567 $ -1, 0 )
568*
569 DO 60 i = 1, SIZE
570 IF( abs( work( i+ptrwork )-work( size+i+
571 $ ptrwork ) ).GT.zero ) THEN
572 WRITE( nout, fmt = * )'I= ', i, ' MIN=',
573 $ work( i+ptrwork ), ' MAX=',
574 $ work( size+i+ptrwork )
575 hetero = 'T'
576 sethet = 1
577 GO TO 70
578 END IF
579*
580 60 CONTINUE
581 70 CONTINUE
582*
583 END IF
584*
585 IF( sethet.NE.1 )
586 $ hetero = 'N'
587*
588* Need to copy A again since AC was overwritten by PDGESVD.
589*
590 CALL pdlacpy( 'A', m, n, work( ptra ), ia, ja, desca,
591 $ work( ptrac ), ia, ja, desca )
592*
593* PDSVDCHK overwrites U. So before the call to PDSVDCHK
594* U is copied to UC and a pointer to UC is passed to
595* PDSVDCHK.
596*
597 CALL pdlacpy( 'A', m, SIZE, work( ptru ), iu, ju, descu,
598 $ work( ptruc ), iu, ju, descu )
599*
600* Run tests 1 - 4.
601*
602 CALL pdsvdchk( m, n, work( ptrac ), ia, ja, desca,
603 $ work( ptruc ), iu, ju, descu,
604 $ work( ptrvt ), ivt, jvt, descvt,
605 $ work( ptrs ), thresh, work( ptrwork ),
606 $ llwork, result, chk, mtm )
607*
608 ELSE
609*
610* Once again test PDGESVD with min workspace.
611*
612 CALL pdgesvd( jobu, jobvt, m, n, work( ptrac ), ia, ja,
613 $ desca, work( ptrsc ), work( ptruc ), iu,
614 $ ju, descu, work( ptrvtc ), ivt, jvt,
615 $ descvt, work( ptrwork ), wpdgesvd, info )
616*
617 CALL pdsvdcmp( m, n, jobtype, work( ptrs ),
618 $ work( ptrsc ), work( ptru ),
619 $ work( ptruc ), iu, ju, descu,
620 $ work( ptrvt ), work( ptrvtc ), ivt, jvt,
621 $ descvt, thresh, result, delta,
622 $ work( ptrwork ), llwork )
623*
624 END IF
625*
626 80 CONTINUE
627*
628 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
629 DO 90 i = 1, 9
630 IF( result( i ).EQ.1 ) THEN
631 pass = 1
632 WRITE( nout, fmt = * )'Test I = ', i, 'has failed'
633 WRITE( nout, fmt = * )' '
634 END IF
635 90 CONTINUE
636 IF( pass.EQ.0 ) THEN
637 WRITE( nout, fmt = 9999 )'Passed', wtime( 1 ),
638 $ ctime( 1 ), m, n, nprow, npcol, nb, itype, chk, mtm,
639 $ delta, hetero
640 END IF
641 END IF
642 100 CONTINUE
643 CALL blacs_gridexit( context )
644 110 CONTINUE
645*
646 9999 FORMAT( a6, 2e10.3, 2i6, 2i4, i5, i6, 3f6.2, 4x, a1 )
647 120 CONTINUE
648*
649* End of PDSVDTST
650*
651 RETURN
652 END
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
Definition descinit.f:3
#define max(A, B)
Definition pcgemr.c:180
#define min(A, B)
Definition pcgemr.c:181
subroutine pdlaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
Definition pdblastst.f:6862
subroutine pdelset(a, ia, ja, desca, alpha)
Definition pdelset.f:2
subroutine pdgesvd(jobu, jobvt, m, n, a, ia, ja, desca, s, u, iu, ju, descu, vt, ivt, jvt, descvt, work, lwork, info)
Definition pdgesvd.f:4
subroutine pdlacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
Definition pdlacpy.f:3
subroutine pdlagge(m, n, d, a, ia, ja, desca, iseed, order, work, lwork, info)
Definition pdlagge.f:3
subroutine pdsvdchk(m, n, a, ia, ja, desca, u, iu, ju, descu, vt, ivt, jvt, descvt, s, thresh, work, lwork, result, chk, mtm)
Definition pdsvdchk.f:4
subroutine pdsvdcmp(m, n, jobtype, s, sc, u, uc, iu, ju, descu, vt, vtc, ivt, jvt, descvt, thresh, result, delta, work, lwork)
Definition pdsvdcmp.f:4
subroutine pdsvdtst(m, n, nprow, npcol, nb, iseed, thresh, work, result, lwork, nout)
Definition pdsvdtst.f:3
subroutine pxerbla(ictxt, srname, info)
Definition pxerbla.f:2
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