173
174
175
176
177
178
179 CHARACTER UPLO
180 INTEGER INFO, LDB, N, NRHS, RANK, SMLSIZ
181 REAL RCOND
182
183
184 INTEGER IWORK( * )
185 REAL B( LDB, * ), D( * ), E( * ), WORK( * )
186
187
188
189
190
191 REAL ZERO, ONE, TWO
192 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
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 REAL CS, EPS, ORGNRM, R, RCND, SN, TOL
200
201
202 INTEGER ISAMAX
203 REAL SLAMCH, SLANST
205
206
209
210
211 INTRINSIC abs, int, log, real, 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(
'SLALSD', -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 slaset(
'A', 1, nrhs, zero, zero, b, ldb )
250 ELSE
251 rank = 1
252 CALL slascl(
'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 slartg( 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 srot( 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 srot( 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 =
slanst(
'M', n, d, e )
288 IF( orgnrm.EQ.zero ) THEN
289 CALL slaset(
'A', n, nrhs, zero, zero, b, ldb )
290 RETURN
291 END IF
292
293 CALL slascl(
'G', 0, 0, orgnrm, one, n, 1, d, n, info )
294 CALL slascl(
'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 slaset(
'A', n, n, zero, one, work, n )
302 CALL slasdq(
'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(
isamax( n, d, 1 ) ) )
308 DO 40 i = 1, n
309 IF( d( i ).LE.tol ) THEN
310 CALL slaset(
'A', 1, nrhs, zero, zero, b( i, 1 ), ldb )
311 ELSE
312 CALL slascl(
'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 sgemm(
'T',
'N', n, nrhs, n, one, work, n, b, ldb, zero,
318 $ work( nwork ), n )
319 CALL slacpy(
'A', n, nrhs, work( nwork ), n, b, ldb )
320
321
322
323 CALL slascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
324 CALL slasrt(
'D', n, d, info )
325 CALL slascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
326
327 RETURN
328 END IF
329
330
331
332 nlvl = int( log( real( n ) / real( 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 scopy( 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 scopy( nrhs, b( st, 1 ), ldb, work( bx+st1 ), n )
407 ELSE IF( nsize.LE.smlsiz ) THEN
408
409
410
411 CALL slaset(
'A', nsize, nsize, zero, one,
412 $ work( vt+st1 ), n )
413 CALL slasdq(
'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 slacpy(
'A', nsize, nrhs, b( st, 1 ), ldb,
420 $ work( bx+st1 ), n )
421 ELSE
422
423
424
425 CALL slasda( 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 slalsa( 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(
isamax( n, d, 1 ) ) )
458
459 DO 70 i = 1, n
460
461
462
463
464 IF( abs( d( i ) ).LE.tol ) THEN
465 CALL slaset(
'A', 1, nrhs, zero, zero, work( bx+i-1 ), n )
466 ELSE
467 rank = rank + 1
468 CALL slascl(
'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 scopy( nrhs, work( bxst ), n, b( st, 1 ), ldb )
484 ELSE IF( nsize.LE.smlsiz ) THEN
485 CALL sgemm(
'T',
'N', nsize, nrhs, nsize, one,
486 $ work( vt+st1 ), n, work( bxst ), n, zero,
487 $ b( st, 1 ), ldb )
488 ELSE
489 CALL slalsa( 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 slascl(
'G', 0, 0, one, orgnrm, n, 1, d, n, info )
507 CALL slasrt(
'D', n, d, info )
508 CALL slascl(
'G', 0, 0, orgnrm, one, n, nrhs, b, ldb, info )
509
510 RETURN
511
512
513
subroutine xerbla(srname, info)
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
integer function isamax(n, sx, incx)
ISAMAX
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
subroutine slalsa(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)
SLALSA computes the SVD of the coefficient matrix in compact form. Used by sgelsd.
real function slamch(cmach)
SLAMCH
real function slanst(norm, n, d, e)
SLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
subroutine slartg(f, g, c, s, r)
SLARTG generates a plane rotation with real cosine and real sine.
subroutine slascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
SLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
subroutine slasda(icompq, smlsiz, n, sqre, d, e, u, ldu, vt, k, difl, difr, z, poles, givptr, givcol, ldgcol, perm, givnum, c, s, work, iwork, info)
SLASDA computes the singular value decomposition (SVD) of a real upper bidiagonal matrix with diagona...
subroutine slasdq(uplo, sqre, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SLASDQ computes the SVD of a real bidiagonal matrix with diagonal d and off-diagonal e....
subroutine slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine slasrt(id, n, d, info)
SLASRT sorts numbers in increasing or decreasing order.
subroutine srot(n, sx, incx, sy, incy, c, s)
SROT