173
174
175
176
177
178
179 CHARACTER UPLO
180 INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
181 DOUBLE PRECISION RCOND
182
183
184 INTEGER IWORK( * )
185 DOUBLE PRECISION B( LDB, * ), D( * ), E( * ), WORK( * )
186
187
188
189
190
191 DOUBLE PRECISION ZERO, ONE, TWO
192 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0 )
193
194
195 INTEGER BX, BXST, C, DIFL, DIFR, GIVCOL, GIVNUM,
196 $ GIVPTR, I, ICMPQ1, ICMPQ2, IWK, J, K, NLVL,
197 $ NM1, NSIZE, NSUB, NWORK, PERM, POLES, S, SIZEI,
198 $ SMLSZP, SQRE, ST, ST1, U, VT, Z
199 DOUBLE PRECISION CS, EPS, ORGNRM, R, RCND, SN, TOL
200
201
202 INTEGER IDAMAX
203 DOUBLE PRECISION DLAMCH, DLANST
205
206
209
210
211 INTRINSIC abs, dble, int, log, sign
212
213
214
215
216
217 info = 0
218
219 IF( n.LT.0 ) THEN
220 info = -3
221 ELSE IF( nrhs.LT.1 ) THEN
222 info = -4
223 ELSE IF( ( ldb.LT.1 ) .OR. ( ldb.LT.n ) ) THEN
224 info = -8
225 END IF
226 IF( info.NE.0 ) THEN
227 CALL xerbla(
'DLALSD', -info )
228 RETURN
229 END IF
230
232
233
234
235 IF( ( rcond.LE.zero ) .OR. ( rcond.GE.one ) ) THEN
236 rcnd = eps
237 ELSE
238 rcnd = rcond
239 END IF
240
241 rank = 0
242
243
244
245 IF( n.EQ.0 ) THEN
246 RETURN
247 ELSE IF( n.EQ.1 ) THEN
248 IF( d( 1 ).EQ.zero ) THEN
249 CALL dlaset(
'A', 1, nrhs, zero, zero, b, ldb )
250 ELSE
251 rank = 1
252 CALL dlascl(
'G', 0, 0, d( 1 ), one, 1, nrhs, b, ldb, 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, sn )
279 20 CONTINUE
280 30 CONTINUE
281 END IF
282 END IF
283
284
285
286 nm1 = n - 1
287 orgnrm =
dlanst(
'M', n, d, e )
288 IF( orgnrm.EQ.zero ) THEN
289 CALL dlaset(
'A', n, nrhs, zero, zero, b, ldb )
290 RETURN
291 END IF
292
293 CALL dlascl(
'G', 0, 0, orgnrm, one, n, 1, d, n, info )
294 CALL dlascl(
'G', 0, 0, orgnrm, one, nm1, 1, e, nm1, info )
295
296
297
298
299 IF( n.LE.smlsiz ) THEN
300 nwork = 1 + n*n
301 CALL dlaset(
'A', n, n, zero, one, work, n )
302 CALL dlasdq(
'U', 0, n, n, 0, nrhs, d, e, work, n, work, n, b,
303 $ ldb, work( nwork ), info )
304 IF( info.NE.0 ) THEN
305 RETURN
306 END IF
307 tol = rcnd*abs( d(
idamax( n, d, 1 ) ) )
308 DO 40 i = 1, n
309 IF( d( i ).LE.tol ) THEN
310 CALL dlaset(
'A', 1, nrhs, zero, zero, b( i, 1 ), ldb )
311 ELSE
312 CALL dlascl(
'G', 0, 0, d( i ), one, 1, nrhs, b( i, 1 ),
313 $ ldb, info )
314 rank = rank + 1
315 END IF
316 40 CONTINUE
317 CALL dgemm(
'T',
'N', n, nrhs, n, one, work, n, b, ldb, zero,
318 $ work( nwork ), n )
319 CALL dlacpy(
'A', n, nrhs, work( nwork ), n, b, ldb )
320
321
322
323 CALL dlascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
324 CALL dlasrt(
'D', n, d, info )
325 CALL dlascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
326
327 RETURN
328 END IF
329
330
331
332 nlvl = int( log( dble( n ) / dble( smlsiz+1 ) ) / log( two ) ) + 1
333
334 smlszp = smlsiz + 1
335
336 u = 1
337 vt = 1 + smlsiz*n
338 difl = vt + smlszp*n
339 difr = difl + nlvl*n
340 z = difr + nlvl*n*2
341 c = z + nlvl*n
342 s = c + n
343 poles = s + n
344 givnum = poles + 2*nlvl*n
345 bx = givnum + 2*nlvl*n
346 nwork = bx + n*nrhs
347
348 sizei = 1 + n
349 k = sizei + n
350 givptr = k + n
351 perm = givptr + n
352 givcol = perm + nlvl*n
353 iwk = givcol + nlvl*n*2
354
355 st = 1
356 sqre = 0
357 icmpq1 = 1
358 icmpq2 = 0
359 nsub = 0
360
361 DO 50 i = 1, n
362 IF( abs( d( i ) ).LT.eps ) THEN
363 d( i ) = sign( eps, d( i ) )
364 END IF
365 50 CONTINUE
366
367 DO 60 i = 1, nm1
368 IF( ( abs( e( i ) ).LT.eps ) .OR. ( i.EQ.nm1 ) ) THEN
369 nsub = nsub + 1
370 iwork( nsub ) = st
371
372
373
374
375 IF( i.LT.nm1 ) THEN
376
377
378
379 nsize = i - st + 1
380 iwork( sizei+nsub-1 ) = nsize
381 ELSE IF( abs( e( i ) ).GE.eps ) THEN
382
383
384
385 nsize = n - st + 1
386 iwork( sizei+nsub-1 ) = nsize
387 ELSE
388
389
390
391
392
393 nsize = i - st + 1
394 iwork( sizei+nsub-1 ) = nsize
395 nsub = nsub + 1
396 iwork( nsub ) = n
397 iwork( sizei+nsub-1 ) = 1
398 CALL dcopy( nrhs, b( n, 1 ), ldb, work( bx+nm1 ), n )
399 END IF
400 st1 = st - 1
401 IF( nsize.EQ.1 ) THEN
402
403
404
405
406 CALL dcopy( nrhs, b( st, 1 ), ldb, work( bx+st1 ), n )
407 ELSE IF( nsize.LE.smlsiz ) THEN
408
409
410
411 CALL dlaset(
'A', nsize, nsize, zero, one,
412 $ work( vt+st1 ), n )
413 CALL dlasdq(
'U', 0, nsize, nsize, 0, nrhs, d( st ),
414 $ e( st ), work( vt+st1 ), n, work( nwork ),
415 $ n, b( st, 1 ), ldb, work( nwork ), info )
416 IF( info.NE.0 ) THEN
417 RETURN
418 END IF
419 CALL dlacpy(
'A', nsize, nrhs, b( st, 1 ), ldb,
420 $ work( bx+st1 ), n )
421 ELSE
422
423
424
425 CALL dlasda( icmpq1, smlsiz, nsize, sqre, d( st ),
426 $ e( st ), work( u+st1 ), n, work( vt+st1 ),
427 $ iwork( k+st1 ), work( difl+st1 ),
428 $ work( difr+st1 ), work( z+st1 ),
429 $ work( poles+st1 ), iwork( givptr+st1 ),
430 $ iwork( givcol+st1 ), n, iwork( perm+st1 ),
431 $ work( givnum+st1 ), work( c+st1 ),
432 $ work( s+st1 ), work( nwork ), iwork( iwk ),
433 $ info )
434 IF( info.NE.0 ) THEN
435 RETURN
436 END IF
437 bxst = bx + st1
438 CALL dlalsa( icmpq2, smlsiz, nsize, nrhs, b( st, 1 ),
439 $ ldb, work( bxst ), n, work( u+st1 ), n,
440 $ work( vt+st1 ), iwork( k+st1 ),
441 $ work( difl+st1 ), work( difr+st1 ),
442 $ work( z+st1 ), work( poles+st1 ),
443 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
444 $ iwork( perm+st1 ), work( givnum+st1 ),
445 $ work( c+st1 ), work( s+st1 ), work( nwork ),
446 $ iwork( iwk ), info )
447 IF( info.NE.0 ) THEN
448 RETURN
449 END IF
450 END IF
451 st = i + 1
452 END IF
453 60 CONTINUE
454
455
456
457 tol = rcnd*abs( d(
idamax( n, d, 1 ) ) )
458
459 DO 70 i = 1, n
460
461
462
463
464 IF( abs( d( i ) ).LE.tol ) THEN
465 CALL dlaset(
'A', 1, nrhs, zero, zero, work( bx+i-1 ), n )
466 ELSE
467 rank = rank + 1
468 CALL dlascl(
'G', 0, 0, d( i ), one, 1, nrhs,
469 $ work( bx+i-1 ), n, info )
470 END IF
471 d( i ) = abs( d( i ) )
472 70 CONTINUE
473
474
475
476 icmpq2 = 1
477 DO 80 i = 1, nsub
478 st = iwork( i )
479 st1 = st - 1
480 nsize = iwork( sizei+i-1 )
481 bxst = bx + st1
482 IF( nsize.EQ.1 ) THEN
483 CALL dcopy( nrhs, work( bxst ), n, b( st, 1 ), ldb )
484 ELSE IF( nsize.LE.smlsiz ) THEN
485 CALL dgemm(
'T',
'N', nsize, nrhs, nsize, one,
486 $ work( vt+st1 ), n, work( bxst ), n, zero,
487 $ b( st, 1 ), ldb )
488 ELSE
489 CALL dlalsa( icmpq2, smlsiz, nsize, nrhs, work( bxst ), n,
490 $ b( st, 1 ), ldb, work( u+st1 ), n,
491 $ work( vt+st1 ), iwork( k+st1 ),
492 $ work( difl+st1 ), work( difr+st1 ),
493 $ work( z+st1 ), work( poles+st1 ),
494 $ iwork( givptr+st1 ), iwork( givcol+st1 ), n,
495 $ iwork( perm+st1 ), work( givnum+st1 ),
496 $ work( c+st1 ), work( s+st1 ), work( nwork ),
497 $ iwork( iwk ), info )
498 IF( info.NE.0 ) THEN
499 RETURN
500 END IF
501 END IF
502 80 CONTINUE
503
504
505
506 CALL dlascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
507 CALL dlasrt(
'D', n, d, info )
508 CALL dlascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
509
510 RETURN
511
512
513
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