204
205
206
207
208
209
210 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
211 REAL RCOND
212
213
214 INTEGER IWORK( * )
215 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
216
217
218
219
220
221 REAL ZERO, ONE, TWO
222 parameter( zero = 0.0e0, one = 1.0e0, two = 2.0e0 )
223
224
225 LOGICAL LQUERY
226 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
227 $ LDWORK, LIWORK, MAXMN, MAXWRK, MINMN, MINWRK,
228 $ MM, MNTHR, NLVL, NWORK, SMLSIZ, WLALSD
229 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
230
231
234
235
236 INTEGER ILAENV
237 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
239
240
241 INTRINSIC int, log, max, min, real
242
243
244
245
246
247 info = 0
248 minmn = min( m, n )
249 maxmn = max( m, n )
250 lquery = ( lwork.EQ.-1 )
251 IF( m.LT.0 ) THEN
252 info = -1
253 ELSE IF( n.LT.0 ) THEN
254 info = -2
255 ELSE IF( nrhs.LT.0 ) THEN
256 info = -3
257 ELSE IF( lda.LT.max( 1, m ) ) THEN
258 info = -5
259 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
260 info = -7
261 END IF
262
263
264
265
266
267
268
269
270 IF( info.EQ.0 ) THEN
271 minwrk = 1
272 maxwrk = 1
273 liwork = 1
274 IF( minmn.GT.0 ) THEN
275 smlsiz =
ilaenv( 9,
'SGELSD',
' ', 0, 0, 0, 0 )
276 mnthr =
ilaenv( 6,
'SGELSD',
' ', m, n, nrhs, -1 )
277 nlvl = max( int( log( real( minmn ) / real( smlsiz + 1 ) ) /
278 $ log( two ) ) + 1, 0 )
279 liwork = 3*minmn*nlvl + 11*minmn
280 mm = m
281 IF( m.GE.n .AND. m.GE.mnthr ) THEN
282
283
284
285
286 mm = n
287 maxwrk = max( maxwrk, n + n*
ilaenv( 1,
'SGEQRF',
' ', m,
288 $ n, -1, -1 ) )
289 maxwrk = max( maxwrk, n + nrhs*
ilaenv( 1,
'SORMQR',
'LT',
290 $ m, nrhs, n, -1 ) )
291 END IF
292 IF( m.GE.n ) THEN
293
294
295
296 maxwrk = max( maxwrk, 3*n + ( mm + n )*
ilaenv( 1,
297 $ 'SGEBRD', ' ', mm, n, -1, -1 ) )
298 maxwrk = max( maxwrk, 3*n + nrhs*
ilaenv( 1,
'SORMBR',
299 $ 'QLT', mm, nrhs, n, -1 ) )
300 maxwrk = max( maxwrk, 3*n + ( n - 1 )*
ilaenv( 1,
301 $ 'SORMBR', 'PLN', n, nrhs, n, -1 ) )
302 wlalsd = 9*n + 2*n*smlsiz + 8*n*nlvl + n*nrhs +
303 $ ( smlsiz + 1 )**2
304 maxwrk = max( maxwrk, 3*n + wlalsd )
305 minwrk = max( 3*n + mm, 3*n + nrhs, 3*n + wlalsd )
306 END IF
307 IF( n.GT.m ) THEN
308 wlalsd = 9*m + 2*m*smlsiz + 8*m*nlvl + m*nrhs +
309 $ ( smlsiz + 1 )**2
310 IF( n.GE.mnthr ) THEN
311
312
313
314
315 maxwrk = m + m*
ilaenv( 1,
'SGELQF',
' ', m, n, -1,
316 $ -1 )
317 maxwrk = max( maxwrk, m*m + 4*m + 2*m*
ilaenv( 1,
318 $ 'SGEBRD', ' ', m, m, -1, -1 ) )
319 maxwrk = max( maxwrk, m*m + 4*m + nrhs*
ilaenv( 1,
320 $ 'SORMBR', 'QLT', m, nrhs, m, -1 ) )
321 maxwrk = max( maxwrk, m*m + 4*m + ( m - 1 )*
ilaenv( 1,
322 $ 'SORMBR', 'PLN', m, nrhs, m, -1 ) )
323 IF( nrhs.GT.1 ) THEN
324 maxwrk = max( maxwrk, m*m + m + m*nrhs )
325 ELSE
326 maxwrk = max( maxwrk, m*m + 2*m )
327 END IF
328 maxwrk = max( maxwrk, m + nrhs*
ilaenv( 1,
'SORMLQ',
329 $ 'LT', n, nrhs, m, -1 ) )
330 maxwrk = max( maxwrk, m*m + 4*m + wlalsd )
331
332
333 maxwrk = max( maxwrk,
334 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
335 ELSE
336
337
338
339 maxwrk = 3*m + ( n + m )*
ilaenv( 1,
'SGEBRD',
' ', m,
340 $ n, -1, -1 )
341 maxwrk = max( maxwrk, 3*m + nrhs*
ilaenv( 1,
'SORMBR',
342 $ 'QLT', m, nrhs, n, -1 ) )
343 maxwrk = max( maxwrk, 3*m + m*
ilaenv( 1,
'SORMBR',
344 $ 'PLN', n, nrhs, m, -1 ) )
345 maxwrk = max( maxwrk, 3*m + wlalsd )
346 END IF
347 minwrk = max( 3*m + nrhs, 3*m + m, 3*m + wlalsd )
348 END IF
349 END IF
350 minwrk = min( minwrk, maxwrk )
352 iwork( 1 ) = liwork
353
354 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
355 info = -12
356 END IF
357 END IF
358
359 IF( info.NE.0 ) THEN
360 CALL xerbla(
'SGELSD', -info )
361 RETURN
362 ELSE IF( lquery ) THEN
363 RETURN
364 END IF
365
366
367
368 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
369 rank = 0
370 RETURN
371 END IF
372
373
374
377 smlnum = sfmin / eps
378 bignum = one / smlnum
379
380
381
382 anrm =
slange(
'M', m, n, a, lda, work )
383 iascl = 0
384 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
385
386
387
388 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
389 iascl = 1
390 ELSE IF( anrm.GT.bignum ) THEN
391
392
393
394 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
395 iascl = 2
396 ELSE IF( anrm.EQ.zero ) THEN
397
398
399
400 CALL slaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
401 CALL slaset(
'F', minmn, 1, zero, zero, s, 1 )
402 rank = 0
403 GO TO 10
404 END IF
405
406
407
408 bnrm =
slange(
'M', m, nrhs, b, ldb, work )
409 ibscl = 0
410 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
411
412
413
414 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, info )
415 ibscl = 1
416 ELSE IF( bnrm.GT.bignum ) THEN
417
418
419
420 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb, info )
421 ibscl = 2
422 END IF
423
424
425
426 IF( m.LT.n )
427 $
CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
428
429
430
431 IF( m.GE.n ) THEN
432
433
434
435 mm = m
436 IF( m.GE.mnthr ) THEN
437
438
439
440 mm = n
441 itau = 1
442 nwork = itau + n
443
444
445
446
447 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
448 $ lwork-nwork+1, info )
449
450
451
452
453 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
454 $ ldb, work( nwork ), lwork-nwork+1, info )
455
456
457
458 IF( n.GT.1 ) THEN
459 CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
460 END IF
461 END IF
462
463 ie = 1
464 itauq = ie + n
465 itaup = itauq + n
466 nwork = itaup + n
467
468
469
470
471 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
472 $ work( itaup ), work( nwork ), lwork-nwork+1,
473 $ info )
474
475
476
477
478 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
479 $ b, ldb, work( nwork ), lwork-nwork+1, info )
480
481
482
483 CALL slalsd(
'U', smlsiz, n, nrhs, s, work( ie ), b, ldb,
484 $ rcond, rank, work( nwork ), iwork, info )
485 IF( info.NE.0 ) THEN
486 GO TO 10
487 END IF
488
489
490
491 CALL sormbr(
'P',
'L',
'N', n, nrhs, n, a, lda, work( itaup ),
492 $ b, ldb, work( nwork ), lwork-nwork+1, info )
493
494 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
495 $ max( m, 2*m-4, nrhs, n-3*m, wlalsd ) ) THEN
496
497
498
499
500 ldwork = m
501 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
502 $ m*lda+m+m*nrhs, 4*m+m*lda+wlalsd ) )ldwork = lda
503 itau = 1
504 nwork = m + 1
505
506
507
508
509 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
510 $ lwork-nwork+1, info )
511 il = nwork
512
513
514
515 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
516 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
517 $ ldwork )
518 ie = il + ldwork*m
519 itauq = ie + m
520 itaup = itauq + m
521 nwork = itaup + m
522
523
524
525
526 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
527 $ work( itauq ), work( itaup ), work( nwork ),
528 $ lwork-nwork+1, info )
529
530
531
532
533 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
534 $ work( itauq ), b, ldb, work( nwork ),
535 $ lwork-nwork+1, info )
536
537
538
539 CALL slalsd(
'U', smlsiz, m, nrhs, s, work( ie ), b, ldb,
540 $ rcond, rank, work( nwork ), iwork, info )
541 IF( info.NE.0 ) THEN
542 GO TO 10
543 END IF
544
545
546
547 CALL sormbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
548 $ work( itaup ), b, ldb, work( nwork ),
549 $ lwork-nwork+1, info )
550
551
552
553 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
554 nwork = itau + m
555
556
557
558
559 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
560 $ ldb, work( nwork ), lwork-nwork+1, info )
561
562 ELSE
563
564
565
566 ie = 1
567 itauq = ie + m
568 itaup = itauq + m
569 nwork = itaup + m
570
571
572
573
574 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
575 $ work( itaup ), work( nwork ), lwork-nwork+1,
576 $ info )
577
578
579
580
581 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
582 $ b, ldb, work( nwork ), lwork-nwork+1, info )
583
584
585
586 CALL slalsd(
'L', smlsiz, m, nrhs, s, work( ie ), b, ldb,
587 $ rcond, rank, work( nwork ), iwork, info )
588 IF( info.NE.0 ) THEN
589 GO TO 10
590 END IF
591
592
593
594 CALL sormbr(
'P',
'L',
'N', n, nrhs, m, a, lda, work( itaup ),
595 $ b, ldb, work( nwork ), lwork-nwork+1, info )
596
597 END IF
598
599
600
601 IF( iascl.EQ.1 ) THEN
602 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
603 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
604 $ info )
605 ELSE IF( iascl.EQ.2 ) THEN
606 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
607 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
608 $ info )
609 END IF
610 IF( ibscl.EQ.1 ) THEN
611 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
612 ELSE IF( ibscl.EQ.2 ) THEN
613 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
614 END IF
615
616 10 CONTINUE
618 iwork( 1 ) = liwork
619 RETURN
620
621
622
subroutine xerbla(srname, info)
subroutine sgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
SGEBRD
subroutine sgelqf(m, n, a, lda, tau, work, lwork, info)
SGELQF
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
subroutine slalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, iwork, info)
SLALSD uses the singular value decomposition of A to solve the least squares problem.
real function slamch(cmach)
SLAMCH
real function slange(norm, m, n, a, lda, work)
SLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
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 slaset(uplo, m, n, alpha, beta, a, lda)
SLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR