4
5
6
7
8
9
10
11
12 CHARACTER JOBU,JOBVT
13 INTEGER IA,INFO,IU,IVT,JA,JU,JVT,LWORK,M,N
14
15
16 INTEGER DESCA(*),DESCU(*),DESCVT(*)
17 COMPLEX*16 A(*),U(*),VT(*),WORK(*)
18 DOUBLE PRECISION S(*)
19 DOUBLE PRECISION RWORK(*)
20
21
22
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290 INTEGER BLOCK_CYCLIC_2D,DLEN_,DTYPE_,CTXT_,M_,N_,MB_,NB_,RSRC_,
291 + CSRC_,LLD_,ITHVAL
292 parameter(block_cyclic_2d=1,dlen_=9,dtype_=1,ctxt_=2,m_=3,n_=4,
293 + mb_=5,nb_=6,rsrc_=7,csrc_=8,lld_=9,ithval=10)
294 COMPLEX*16 ZERO,ONE
295 parameter(zero= ((0.0d+0,0.0d+0)),one= ((1.0d+0,0.0d+0)))
296 DOUBLE PRECISION DZERO,DONE
297 parameter(dzero=0.0d+0,done=1.0d+0)
298
299
300 CHARACTER UPLO
301 INTEGER CONTEXTC,CONTEXTR,I,INDD,INDD2,INDE,INDE2,INDTAUP,INDTAUQ,
302 + INDU,INDV,INDWORK,IOFFD,IOFFE,ISCALE,J,K,LDU,LDVT,LLWORK,
303 + LWMIN,MAXIM,MB,MP,MYPCOL,MYPCOLC,MYPCOLR,MYPROW,MYPROWC,
304 + MYPROWR,NB,NCVT,NPCOL,NPCOLC,NPCOLR,NPROCS,NPROW,NPROWC,
305 + NPROWR,NQ,NRU,SIZE,SIZEB,SIZEP,SIZEPOS,SIZEQ,WANTU,WANTVT,
306 + WATOBD,WBDTOSVD,WZBDSQR,WPZGEBRD,WPZLANGE,WPZORMBRPRT,
307 + WPZORMBRQLN
308 DOUBLE PRECISION ANRM,BIGNUM,EPS,RMAX,RMIN,SAFMIN,SIGMA,SMLNUM
309
310
311 INTEGER DESCTU(DLEN_),DESCTVT(DLEN_),IDUM1(3),IDUM2(3)
312 DOUBLE PRECISION C(1,1)
313
314
315 LOGICAL LSAME
316 INTEGER NUMROC
317 DOUBLE PRECISION PDLAMCH,PZLANGE
319
320
321 EXTERNAL blacs_get,blacs_gridexit,blacs_gridinfo,blacs_gridinit,
325
326
327 INTRINSIC max,
min,sqrt,dble
328 INTRINSIC dcmplx
329
330
331
332 IF (block_cyclic_2d*dtype_*lld_*mb_*m_*nb_*n_.LT.0) RETURN
333
334 CALL blacs_gridinfo(desca(ctxt_),nprow,npcol,myprow,mypcol)
335 iscale = 0
336 info = 0
337
338 IF (nprow.EQ.-1) THEN
339 info = - (800+ctxt_)
340 ELSE
341
344 nprocs = nprow*npcol
345 IF (m.GE.n) THEN
346 ioffd = ja - 1
347 ioffe = ia - 1
348 sizepos = 1
349 ELSE
350 ioffd = ia - 1
351 ioffe = ja - 1
352 sizepos = 3
353 END IF
354
355 IF (
lsame(jobu,
'V'))
THEN
356 wantu = 1
357 ELSE
358 wantu = 0
359 END IF
360 IF (
lsame(jobvt,
'V'))
THEN
361 wantvt = 1
362 ELSE
363 wantvt = 0
364 END IF
365
366 CALL chk1mat(m,3,n,4,ia,ja,desca,8,info)
367 IF (wantu.EQ.1) THEN
368 CALL chk1mat(m,3,
SIZE,sizepos,iu,ju,descu,13,info)
369 END IF
370 IF (wantvt.EQ.1) THEN
371 CALL chk1mat(
SIZE,sizepos,n,4,ivt,jvt,descvt,17,info)
372 END IF
373 CALL igamx2d(desca(ctxt_),'A',' ',1,1,info,1,1,1,-1,-1,0)
374
375 IF (info.EQ.0) THEN
376
377
378
379 indd = 2
380 inde = indd + sizeb + ioffd
381 indd2 = inde + sizeb + ioffe
382 inde2 = indd2 + sizeb + ioffd
383
384 indtauq = 2
385 indtaup = indtauq + sizeb + ja - 1
386 indwork = indtaup + sizeb + ia - 1
387 llwork = lwork - indwork + 1
388
389
390
391 CALL blacs_get(desca(ctxt_),10,contextc)
392 CALL blacs_gridinit(contextc,'R',nprocs,1)
393 CALL blacs_gridinfo(contextc,nprowc,npcolc,myprowc,
394 + mypcolc)
395 CALL blacs_get(desca(ctxt_),10,contextr)
396 CALL blacs_gridinit(contextr,'R',1,nprocs)
397 CALL blacs_gridinfo(contextr,nprowr,npcolr,myprowr,
398 + mypcolr)
399
400
401
402 nru =
numroc(m,1,myprowc,0,nprocs)
403 ncvt =
numroc(n,1,mypcolr,0,nprocs)
404 nb = desca(nb_)
405 mb = desca(mb_)
406 mp =
numroc(m,mb,myprow,desca(rsrc_),nprow)
407 nq =
numroc(n,nb,mypcol,desca(csrc_),npcol)
408 IF (wantvt.EQ.1) THEN
409 sizep =
numroc(
SIZE,descvt(mb_),myprow,descvt(rsrc_),
410 + nprow)
411 ELSE
412 sizep = 0
413 END IF
414 IF (wantu.EQ.1) THEN
415 sizeq =
numroc(
SIZE,descu(nb_),mypcol,descu(csrc_),
416 + npcol)
417 ELSE
418 sizeq = 0
419 END IF
420
421
422
423 IF (myprow.EQ.0 .AND. mypcol.EQ.0) THEN
425 CALL igebs2d(desca(ctxt_),'All',' ',1,1,maxim,1)
426 ELSE
427 CALL igebr2d(desca(ctxt_),'All',' ',1,1,maxim,1,0,0)
428 END IF
429
430 wpzlange = mp
431 wpzgebrd = nb* (mp+nq+1) + nq
432 watobd =
max(
max(wpzlange,wpzgebrd),maxim)
433
434 wzbdsqr =
max(1,4*size)
435 wpzormbrqln =
max((nb* (nb-1))/2, (sizeq+mp)*nb) + nb*nb
436 wpzormbrprt =
max((mb* (mb-1))/2, (sizep+nq)*mb) + mb*mb
437 wbdtosvd = size* (wantu*nru+wantvt*ncvt) +
438 +
max(wzbdsqr,
max(wantu*wpzormbrqln,
439 + wantvt*wpzormbrprt))
440
441
442
443 lwmin = 1 + 2*sizeb +
max(watobd,wbdtosvd)
444 work(1) = dcmplx(lwmin,0d+00)
445 rwork(1) = dble(1+4*sizeb)
446
447 IF (wantu.NE.1 .AND. .NOT. (
lsame(jobu,
'N')))
THEN
448 info = -1
449 ELSE IF (wantvt.NE.1 .AND. .NOT. (
lsame(jobvt,
'N')))
THEN
450 info = -2
451 ELSE IF (lwork.LT.lwmin .AND. lwork.NE.-1) THEN
452 info = -19
453 END IF
454
455 END IF
456
457 idum1(1) = wantu
458 idum1(2) = wantvt
459 IF (lwork.EQ.-1) THEN
460 idum1(3) = -1
461 ELSE
462 idum1(3) = 1
463 END IF
464 idum2(1) = 1
465 idum2(2) = 2
466 idum2(3) = 19
467 CALL pchk1mat(m,3,n,4,ia,ja,desca,8,3,idum1,idum2,info)
468 IF (info.EQ.0) THEN
469 IF (wantu.EQ.1) THEN
470 CALL pchk1mat(m,3,
SIZE,4,iu,ju,descu,13,0,idum1,idum2,
471 + info)
472 END IF
473 IF (wantvt.EQ.1) THEN
474 CALL pchk1mat(
SIZE,3,n,4,ivt,jvt,descvt,17,0,idum1,
475 + idum2,info)
476 END IF
477 END IF
478
479 END IF
480
481 IF (info.NE.0) THEN
482 CALL pxerbla(desca(ctxt_),
'PZGESVD',-info)
483 RETURN
484 ELSE IF (lwork.EQ.-1) THEN
485 GO TO 40
486 END IF
487
488
489
490 IF (m.LE.0 .OR. n.LE.0) GO TO 40
491
492
493
494 safmin =
pdlamch(desca(ctxt_),
'Safe minimum')
495 eps =
pdlamch(desca(ctxt_),
'Precision')
496 smlnum = safmin/eps
497 bignum = done/smlnum
498 rmin = sqrt(smlnum)
499 rmax =
min(sqrt(bignum),done/sqrt(sqrt(safmin)))
500
501
502
503 anrm =
pzlange(
'1',m,n,a,ia,ja,desca,work(indwork))
504 IF (anrm.GT.dzero .AND. anrm.LT.rmin) THEN
505 iscale = 1
506 sigma = rmin/anrm
507 ELSE IF (anrm.GT.rmax) THEN
508 iscale = 1
509 sigma = rmax/anrm
510 END IF
511
512 IF (iscale.EQ.1) THEN
513 CALL pzlascl(
'G',done,sigma,m,n,a,ia,ja,desca,info)
514 END IF
515
516 CALL pzgebrd(m,n,a,ia,ja,desca,rwork(indd),rwork(inde),
517 + work(indtauq),work(indtaup),work(indwork),llwork,
518 + info)
519
520
521
522
523
524
525
526 IF (m.GE.n) THEN
527
528 CALL pdlared1d(n+ioffd,ia,ja,desca,rwork(indd),rwork(indd2),
529 + work(indwork),llwork)
530
531 CALL pdlared2d(m+ioffe,ia,ja,desca,rwork(inde),rwork(inde2),
532 + work(indwork),llwork)
533 ELSE
534
535 CALL pdlared2d(m+ioffd,ia,ja,desca,rwork(indd),rwork(indd2),
536 + work(indwork),llwork)
537
538 CALL pdlared1d(n+ioffe,ia,ja,desca,rwork(inde),rwork(inde2),
539 + work(indwork),llwork)
540 END IF
541
542
543
544 IF (m.GE.n) THEN
545 uplo = 'U'
546 ELSE
547 uplo = 'L'
548 END IF
549
550 indu = indwork
551 indv = indu + size*nru*wantu
552 indwork = indv + size*ncvt*wantvt
553
556
557 CALL descinit(desctu,m,
SIZE,1,1,0,0,contextc,ldu,info)
558 CALL descinit(desctvt,
SIZE,n,1,1,0,0,contextr,ldvt,info)
559
560 IF (wantu.EQ.1) THEN
561 CALL pzlaset(
'Full',m,
SIZE,zero,one,work(indu),1,1,desctu)
562 ELSE
563 nru = 0
564 END IF
565
566 IF (wantvt.EQ.1) THEN
567 CALL pzlaset(
'Full',
SIZE,n,zero,one,work(indv),1,1,desctvt)
568 ELSE
569 ncvt = 0
570 END IF
571
572 CALL zbdsqr(uplo,SIZE,ncvt,nru,0,rwork(indd2+ioffd),
573 + rwork(inde2+ioffe),work(indv),SIZE,work(indu),ldu,c,1,
574 + work(indwork),info)
575
576
577
578 IF (wantu.EQ.1) CALL pzgemr2d(m,SIZE,work(indu),1,1,desctu,u,iu,
579 + ju,descu,descu(ctxt_))
580
581 IF (wantvt.EQ.1) CALL pzgemr2d(SIZE,n,work(indv),1,1,desctvt,vt,
582 + ivt,jvt,descvt,descvt(ctxt_))
583
584
585
586 IF (m.GT.n .AND. wantu.EQ.1) THEN
587 CALL pzlaset(
'Full',m-
SIZE,
SIZE,zero,zero,u,ia+
SIZE,ju,descu)
588 ELSE IF (n.GT.m .AND. wantvt.EQ.1) THEN
589 CALL pzlaset(
'Full',
SIZE,n-
SIZE,zero,zero,vt,ivt,jvt+
SIZE,
590 + descvt)
591 END IF
592
593
594
595 IF (wantu.EQ.1)
CALL pzunmbr(
'Q',
'L',
'N',m,
SIZE,n,a,ia,ja,desca,
596 + work(indtauq),u,iu,ju,descu,
597 + work(indwork),llwork,info)
598
599 IF (wantvt.EQ.1)
CALL pzunmbr(
'P',
'R',
'C',
SIZE,n,m,a,ia,ja,desca,
600 + work(indtaup),vt,ivt,jvt,descvt,
601 + work(indwork),llwork,info)
602
603
604
605 DO 10 i = 1,SIZE
606 s(i) = rwork(indd2+ioffd+i-1)
607 10 CONTINUE
608
609
610
611 IF (iscale.EQ.1) THEN
612 CALL dscal(SIZE,one/sigma,s,1)
613 END IF
614
615
616
617
618 IF (size.LE.ithval) THEN
619 j = SIZE
620 k = 1
621 ELSE
622 j = size/ithval
623 k = ithval
624 END IF
625
626 DO 20 i = 1,j
627 rwork(i+inde) = s((i-1)*k+1)
628 rwork(i+indd2) = s((i-1)*k+1)
629 20 CONTINUE
630
631 CALL dgamn2d(desca(ctxt_),'a',' ',j,1,rwork(1+inde),j,1,1,-1,-1,0)
632 CALL dgamx2d(desca(ctxt_),'a',' ',j,1,rwork(1+indd2),j,1,1,-1,-1,
633 + 0)
634
635 DO 30 i = 1,j
636 IF ((rwork(i+inde)-rwork(i+indd2)).NE.dzero) THEN
637 info = SIZE + 1
638 END IF
639 30 CONTINUE
640
641 40 CONTINUE
642
643 CALL blacs_gridexit(contextc)
644 CALL blacs_gridexit(contextr)
645
646
647
648 RETURN
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
double precision function pdlamch(ictxt, cmach)
subroutine pdlared1d(n, ia, ja, desc, bycol, byall, work, lwork)
subroutine pdlared2d(n, ia, ja, desc, byrow, byall, work, lwork)
subroutine pxerbla(ictxt, srname, info)
subroutine pzlaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
subroutine pzgebrd(m, n, a, ia, ja, desca, d, e, tauq, taup, work, lwork, info)
double precision function pzlange(norm, m, n, a, ia, ja, desca, work)
subroutine pzlascl(type, cfrom, cto, m, n, a, ia, ja, desca, info)
subroutine pzunmbr(vect, side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)