171
172
173
174
175
176
177 CHARACTER UPLO
178 INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
179 DOUBLE PRECISION RCOND
180
181
182 INTEGER IWORK( * )
183 DOUBLE PRECISION B( LDB, * ), D( * ), E( * ), WORK( * )
184
185
186
187
188
189 DOUBLE PRECISION ZERO, ONE, TWO
190 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0 )
191
192
193 INTEGER BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
194 $ GIVPTR, I, ICMPQ1, ICMPQ2, IWK, J, K, NLVL,
195 $ NM1, NSIZE, NSUB, NWORK, PERM, POLES, S, SIZEI,
196 $ SMLSZP, SQRE, ST, ST1, U, VT, Z
197 DOUBLE PRECISION CS, EPS, ORGNRM, R, RCND, SN, TOL
198
199
200 INTEGER IDAMAX
201 DOUBLE PRECISION DLAMCH, DLANST
203
204
208
209
210 INTRINSIC abs, dble, int, log, sign
211
212
213
214
215
216 info = 0
217
218 IF( n.LT.0 ) THEN
219 info = -3
220 ELSE IF( nrhs.LT.1 ) THEN
221 info = -4
222 ELSE IF( ( ldb.LT.1 ) .OR. ( ldb.LT.n ) ) THEN
223 info = -8
224 END IF
225 IF( info.NE.0 ) THEN
226 CALL xerbla(
'DLALSD', -info )
227 RETURN
228 END IF
229
231
232
233
234 IF( ( rcond.LE.zero ) .OR. ( rcond.GE.one ) ) THEN
235 rcnd = eps
236 ELSE
237 rcnd = rcond
238 END IF
239
240 rank = 0
241
242
243
244 IF( n.EQ.0 ) THEN
245 RETURN
246 ELSE IF( n.EQ.1 ) THEN
247 IF( d( 1 ).EQ.zero ) THEN
248 CALL dlaset(
'A', 1, nrhs, zero, zero, b, ldb )
249 ELSE
250 rank = 1
251 CALL dlascl(
'G', 0, 0, d( 1 ), one, 1, nrhs, b, ldb,
252 $ info )
253 d( 1 ) = abs( d( 1 ) )
254 END IF
255 RETURN
256 END IF
257
258
259
260 IF( uplo.EQ.'L' ) THEN
261 DO 10 i = 1, n - 1
262 CALL dlartg( d( i ), e( i ), cs, sn, r )
263 d( i ) = r
264 e( i ) = sn*d( i+1 )
265 d( i+1 ) = cs*d( i+1 )
266 IF( nrhs.EQ.1 ) THEN
267 CALL drot( 1, b( i, 1 ), 1, b( i+1, 1 ), 1, cs, sn )
268 ELSE
269 work( i*2-1 ) = cs
270 work( i*2 ) = sn
271 END IF
272 10 CONTINUE
273 IF( nrhs.GT.1 ) THEN
274 DO 30 i = 1, nrhs
275 DO 20 j = 1, n - 1
276 cs = work( j*2-1 )
277 sn = work( j*2 )
278 CALL drot( 1, b( j, i ), 1, b( j+1, i ), 1, cs,
279 $ sn )
280 20 CONTINUE
281 30 CONTINUE
282 END IF
283 END IF
284
285
286
287 nm1 = n - 1
288 orgnrm =
dlanst(
'M', n, d, e )
289 IF( orgnrm.EQ.zero ) THEN
290 CALL dlaset(
'A', n, nrhs, zero, zero, b, ldb )
291 RETURN
292 END IF
293
294 CALL dlascl(
'G', 0, 0, orgnrm, one, n, 1, d, n, info )
295 CALL dlascl(
'G', 0, 0, orgnrm, one, nm1, 1, e, nm1, info )
296
297
298
299
300 IF( n.LE.smlsiz ) THEN
301 nwork = 1 + n*n
302 CALL dlaset(
'A', n, n, zero, one, work, n )
303 CALL dlasdq(
'U', 0, n, n, 0, nrhs, d, e, work, n, work, n,
304 $ b,
305 $ ldb, work( nwork ), info )
306 IF( info.NE.0 ) THEN
307 RETURN
308 END IF
309 tol = rcnd*abs( d(
idamax( n, d, 1 ) ) )
310 DO 40 i = 1, n
311 IF( d( i ).LE.tol ) THEN
312 CALL dlaset(
'A', 1, nrhs, zero, zero, b( i, 1 ),
313 $ ldb )
314 ELSE
315 CALL dlascl(
'G', 0, 0, d( i ), one, 1, nrhs, b( i,
316 $ 1 ),
317 $ ldb, info )
318 rank = rank + 1
319 END IF
320 40 CONTINUE
321 CALL dgemm(
'T',
'N', n, nrhs, n, one, work, n, b, ldb,
322 $ zero,
323 $ work( nwork ), n )
324 CALL dlacpy(
'A', n, nrhs, work( nwork ), n, b, ldb )
325
326
327
328 CALL dlascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
329 CALL dlasrt(
'D', n, d, info )
330 CALL dlascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
331
332 RETURN
333 END IF
334
335
336
337 nlvl = int( log( dble( n ) / dble( smlsiz+1 ) ) / log( two ) ) + 1
338
339 smlszp = smlsiz + 1
340
341 u = 1
342 vt = 1 + smlsiz*n
343 difl = vt + smlszp*n
344 difr = difl + nlvl*n
345 z = difr + nlvl*n*2
346 c = z + nlvl*n
347 s = c + n
348 poles = s + n
349 givnum = poles + 2*nlvl*n
350 bx = givnum + 2*nlvl*n
351 nwork = bx + n*nrhs
352
353 sizei = 1 + n
354 k = sizei + n
355 givptr = k + n
356 perm = givptr + n
357 givcol = perm + nlvl*n
358 iwk = givcol + nlvl*n*2
359
360 st = 1
361 sqre = 0
362 icmpq1 = 1
363 icmpq2 = 0
364 nsub = 0
365
366 DO 50 i = 1, n
367 IF( abs( d( i ) ).LT.eps ) THEN
368 d( i ) = sign( eps, d( i ) )
369 END IF
370 50 CONTINUE
371
372 DO 60 i = 1, nm1
373 IF( ( abs( e( i ) ).LT.eps ) .OR. ( i.EQ.nm1 ) ) THEN
374 nsub = nsub + 1
375 iwork( nsub ) = st
376
377
378
379
380 IF( i.LT.nm1 ) THEN
381
382
383
384 nsize = i - st + 1
385 iwork( sizei+nsub-1 ) = nsize
386 ELSE IF( abs( e( i ) ).GE.eps ) THEN
387
388
389
390 nsize = n - st + 1
391 iwork( sizei+nsub-1 ) = nsize
392 ELSE
393
394
395
396
397
398 nsize = i - st + 1
399 iwork( sizei+nsub-1 ) = nsize
400 nsub = nsub + 1
401 iwork( nsub ) = n
402 iwork( sizei+nsub-1 ) = 1
403 CALL dcopy( nrhs, b( n, 1 ), ldb, work( bx+nm1 ), n )
404 END IF
405 st1 = st - 1
406 IF( nsize.EQ.1 ) THEN
407
408
409
410
411 CALL dcopy( nrhs, b( st, 1 ), ldb, work( bx+st1 ), n )
412 ELSE IF( nsize.LE.smlsiz ) THEN
413
414
415
416 CALL dlaset(
'A', nsize, nsize, zero, one,
417 $ work( vt+st1 ), n )
418 CALL dlasdq(
'U', 0, nsize, nsize, 0, nrhs, d( st ),
419 $ e( st ), work( vt+st1 ), n, work( nwork ),
420 $ n, b( st, 1 ), ldb, work( nwork ), info )
421 IF( info.NE.0 ) THEN
422 RETURN
423 END IF
424 CALL dlacpy(
'A', nsize, nrhs, b( st, 1 ), ldb,
425 $ work( bx+st1 ), n )
426 ELSE
427
428
429
430 CALL dlasda( icmpq1, smlsiz, nsize, sqre, d( st ),
431 $ e( st ), work( u+st1 ), n, work( vt+st1 ),
432 $ iwork( k+st1 ), work( difl+st1 ),
433 $ work( difr+st1 ), work( z+st1 ),
434 $ work( poles+st1 ), iwork( givptr+st1 ),
435 $ iwork( givcol+st1 ), n, iwork( perm+st1 ),
436 $ work( givnum+st1 ), work( c+st1 ),
437 $ work( s+st1 ), work( nwork ), iwork( iwk ),
438 $ info )
439 IF( info.NE.0 ) THEN
440 RETURN
441 END IF
442 bxst = bx + st1
443 CALL dlalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1 ),
444 $ ldb, work( bxst ), n, work( u+st1 ), n,
445 $ work( vt+st1 ), iwork( k+st1 ),
446 $ work( difl+st1 ), work( difr+st1 ),
447 $ work( z+st1 ), work( poles+st1 ),
448 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
449 $ iwork( perm+st1 ), work( givnum+st1 ),
450 $ work( c+st1 ), work( s+st1 ), work( nwork ),
451 $ iwork( iwk ), info )
452 IF( info.NE.0 ) THEN
453 RETURN
454 END IF
455 END IF
456 st = i + 1
457 END IF
458 60 CONTINUE
459
460
461
462 tol = rcnd*abs( d(
idamax( n, d, 1 ) ) )
463
464 DO 70 i = 1, n
465
466
467
468
469 IF( abs( d( i ) ).LE.tol ) THEN
470 CALL dlaset(
'A', 1, nrhs, zero, zero, work( bx+i-1 ),
471 $ n )
472 ELSE
473 rank = rank + 1
474 CALL dlascl(
'G', 0, 0, d( i ), one, 1, nrhs,
475 $ work( bx+i-1 ), n, info )
476 END IF
477 d( i ) = abs( d( i ) )
478 70 CONTINUE
479
480
481
482 icmpq2 = 1
483 DO 80 i = 1, nsub
484 st = iwork( i )
485 st1 = st - 1
486 nsize = iwork( sizei+i-1 )
487 bxst = bx + st1
488 IF( nsize.EQ.1 ) THEN
489 CALL dcopy( nrhs, work( bxst ), n, b( st, 1 ), ldb )
490 ELSE IF( nsize.LE.smlsiz ) THEN
491 CALL dgemm(
'T',
'N', nsize, nrhs, nsize, one,
492 $ work( vt+st1 ), n, work( bxst ), n, zero,
493 $ b( st, 1 ), ldb )
494 ELSE
495 CALL dlalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ),
496 $ n,
497 $ b( st, 1 ), ldb, work( u+st1 ), n,
498 $ work( vt+st1 ), iwork( k+st1 ),
499 $ work( difl+st1 ), work( difr+st1 ),
500 $ work( z+st1 ), work( poles+st1 ),
501 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
502 $ iwork( perm+st1 ), work( givnum+st1 ),
503 $ work( c+st1 ), work( s+st1 ), work( nwork ),
504 $ iwork( iwk ), info )
505 IF( info.NE.0 ) THEN
506 RETURN
507 END IF
508 END IF
509 80 CONTINUE
510
511
512
513 CALL dlascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
514 CALL dlasrt(
'D', n, d, info )
515 CALL dlascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
516
517 RETURN
518
519
520
subroutine xerbla(srname, info)
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
integer function idamax(n, dx, incx)
IDAMAX
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
subroutine dlalsa(icompq, smlsiz, n, nrhs, b, ldb, bx, ldbx, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
DLALSA computes the SVD of the coefficient matrix in compact form. Used by sgelsd.
double precision function dlamch(cmach)
DLAMCH
double precision function dlanst(norm, n, d, e)
DLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine dlasda(icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
DLASDA computes the singular value decomposition (SVD) of a real upper bidiagonal matrix with diagona...
subroutine dlasdq(uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
DLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e....
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine dlasrt(id, n, d, info)
DLASRT sorts numbers in increasing or decreasing order.
subroutine drot(n, dx, incx, dy, incy, c, s)
DROT