170
171
172
173
174
175
176 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
177 REAL RCOND
178
179
180 REAL A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
181
182
183
184
185
186 REAL ZERO, ONE
187 parameter( zero = 0.0e+0, one = 1.0e+0 )
188
189
190 LOGICAL LQUERY
191 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
192 $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
193 $ MAXWRK, MINMN, MINWRK, MM, MNTHR
194 INTEGER LWORK_SGEQRF, LWORK_SORMQR, LWORK_SGEBRD,
195 $ LWORK_SORMBR, LWORK_SORGBR, LWORK_SORMLQ
196 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
197
198
199 REAL DUM( 1 )
200
201
206
207
208 INTEGER ILAENV
209 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
212
213
214 INTRINSIC max, min
215
216
217
218
219
220 info = 0
221 minmn = min( m, n )
222 maxmn = max( m, n )
223 lquery = ( lwork.EQ.-1 )
224 IF( m.LT.0 ) THEN
225 info = -1
226 ELSE IF( n.LT.0 ) THEN
227 info = -2
228 ELSE IF( nrhs.LT.0 ) THEN
229 info = -3
230 ELSE IF( lda.LT.max( 1, m ) ) THEN
231 info = -5
232 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
233 info = -7
234 END IF
235
236
237
238
239
240
241
242
243 IF( info.EQ.0 ) THEN
244 minwrk = 1
245 maxwrk = 1
246 IF( minmn.GT.0 ) THEN
247 mm = m
248 mnthr =
ilaenv( 6,
'SGELSS',
' ', m, n, nrhs, -1 )
249 IF( m.GE.n .AND. m.GE.mnthr ) THEN
250
251
252
253
254
255 CALL sgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
256 lwork_sgeqrf = int( dum(1) )
257
258 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
260 lwork_sormqr = int( dum(1) )
261 mm = n
262 maxwrk = max( maxwrk, n + lwork_sgeqrf )
263 maxwrk = max( maxwrk, n + lwork_sormqr )
264 END IF
265 IF( m.GE.n ) THEN
266
267
268
269
270
271 bdspac = max( 1, 5*n )
272
273 CALL sgebrd( mm, n, a, lda, s, dum(1), dum(1),
274 $ dum(1), dum(1), -1, info )
275 lwork_sgebrd = int( dum(1) )
276
277 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
278 $ dum(1),
279 $ b, ldb, dum(1), -1, info )
280 lwork_sormbr = int( dum(1) )
281
282 CALL sorgbr(
'P', n, n, n, a, lda, dum(1),
283 $ dum(1), -1, info )
284 lwork_sorgbr = int( dum(1) )
285
286 maxwrk = max( maxwrk, 3*n + lwork_sgebrd )
287 maxwrk = max( maxwrk, 3*n + lwork_sormbr )
288 maxwrk = max( maxwrk, 3*n + lwork_sorgbr )
289 maxwrk = max( maxwrk, bdspac )
290 maxwrk = max( maxwrk, n*nrhs )
291 minwrk = max( 3*n + mm, 3*n + nrhs, bdspac )
292 maxwrk = max( minwrk, maxwrk )
293 END IF
294 IF( n.GT.m ) THEN
295
296
297
298 bdspac = max( 1, 5*m )
299 minwrk = max( 3*m+nrhs, 3*m+n, bdspac )
300 IF( n.GE.mnthr ) THEN
301
302
303
304
305
306 CALL sgebrd( m, m, a, lda, s, dum(1), dum(1),
307 $ dum(1), dum(1), -1, info )
308 lwork_sgebrd = int( dum(1) )
309
310 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
311 $ dum(1), b, ldb, dum(1), -1, info )
312 lwork_sormbr = int( dum(1) )
313
314 CALL sorgbr(
'P', m, m, m, a, lda, dum(1),
315 $ dum(1), -1, info )
316 lwork_sorgbr = int( dum(1) )
317
318 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
319 $ b, ldb, dum(1), -1, info )
320 lwork_sormlq = int( dum(1) )
321
322 maxwrk = m + m*
ilaenv( 1,
'SGELQF',
' ', m, n, -1,
323 $ -1 )
324 maxwrk = max( maxwrk, m*m + 4*m + lwork_sgebrd )
325 maxwrk = max( maxwrk, m*m + 4*m + lwork_sormbr )
326 maxwrk = max( maxwrk, m*m + 4*m + lwork_sorgbr )
327 maxwrk = max( maxwrk, m*m + m + bdspac )
328 IF( nrhs.GT.1 ) THEN
329 maxwrk = max( maxwrk, m*m + m + m*nrhs )
330 ELSE
331 maxwrk = max( maxwrk, m*m + 2*m )
332 END IF
333 maxwrk = max( maxwrk, m + lwork_sormlq )
334 ELSE
335
336
337
338
339 CALL sgebrd( m, n, a, lda, s, dum(1), dum(1),
340 $ dum(1), dum(1), -1, info )
341 lwork_sgebrd = int( dum(1) )
342
343 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
344 $ dum(1), b, ldb, dum(1), -1, info )
345 lwork_sormbr = int( dum(1) )
346
347 CALL sorgbr(
'P', m, n, m, a, lda, dum(1),
348 $ dum(1), -1, info )
349 lwork_sorgbr = int( dum(1) )
350 maxwrk = 3*m + lwork_sgebrd
351 maxwrk = max( maxwrk, 3*m + lwork_sormbr )
352 maxwrk = max( maxwrk, 3*m + lwork_sorgbr )
353 maxwrk = max( maxwrk, bdspac )
354 maxwrk = max( maxwrk, n*nrhs )
355 END IF
356 END IF
357 maxwrk = max( minwrk, maxwrk )
358 END IF
360
361 IF( lwork.LT.minwrk .AND. .NOT.lquery )
362 $ info = -12
363 END IF
364
365 IF( info.NE.0 ) THEN
366 CALL xerbla(
'SGELSS', -info )
367 RETURN
368 ELSE IF( lquery ) THEN
369 RETURN
370 END IF
371
372
373
374 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
375 rank = 0
376 RETURN
377 END IF
378
379
380
383 smlnum = sfmin / eps
384 bignum = one / smlnum
385
386
387
388 anrm =
slange(
'M', m, n, a, lda, work )
389 iascl = 0
390 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
391
392
393
394 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
395 iascl = 1
396 ELSE IF( anrm.GT.bignum ) THEN
397
398
399
400 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
401 iascl = 2
402 ELSE IF( anrm.EQ.zero ) THEN
403
404
405
406 CALL slaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
407 CALL slaset(
'F', minmn, 1, zero, zero, s, minmn )
408 rank = 0
409 GO TO 70
410 END IF
411
412
413
414 bnrm =
slange(
'M', m, nrhs, b, ldb, work )
415 ibscl = 0
416 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
417
418
419
420 CALL slascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
421 $ info )
422 ibscl = 1
423 ELSE IF( bnrm.GT.bignum ) THEN
424
425
426
427 CALL slascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
428 $ info )
429 ibscl = 2
430 END IF
431
432
433
434 IF( m.GE.n ) THEN
435
436
437
438 mm = m
439 IF( m.GE.mnthr ) THEN
440
441
442
443 mm = n
444 itau = 1
445 iwork = itau + n
446
447
448
449
450 CALL sgeqrf( m, n, a, lda, work( itau ), work( iwork ),
451 $ lwork-iwork+1, info )
452
453
454
455
456 CALL sormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ),
457 $ b,
458 $ ldb, work( iwork ), lwork-iwork+1, info )
459
460
461
462 IF( n.GT.1 )
463 $
CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ),
464 $ lda )
465 END IF
466
467 ie = 1
468 itauq = ie + n
469 itaup = itauq + n
470 iwork = itaup + n
471
472
473
474
475 CALL sgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
476 $ work( itaup ), work( iwork ), lwork-iwork+1,
477 $ info )
478
479
480
481
482 CALL sormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
483 $ work( itauq ),
484 $ b, ldb, work( iwork ), lwork-iwork+1, info )
485
486
487
488
489 CALL sorgbr(
'P', n, n, n, a, lda, work( itaup ),
490 $ work( iwork ), lwork-iwork+1, info )
491 iwork = ie + n
492
493
494
495
496
497
498 CALL sbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
499 $ 1, b, ldb, work( iwork ), info )
500 IF( info.NE.0 )
501 $ GO TO 70
502
503
504
505 thr = max( rcond*s( 1 ), sfmin )
506 IF( rcond.LT.zero )
507 $ thr = max( eps*s( 1 ), sfmin )
508 rank = 0
509 DO 10 i = 1, n
510 IF( s( i ).GT.thr ) THEN
511 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
512 rank = rank + 1
513 ELSE
514 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
515 $ ldb )
516 END IF
517 10 CONTINUE
518
519
520
521
522 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
523 CALL sgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb,
524 $ zero,
525 $ work, ldb )
526 CALL slacpy(
'G', n, nrhs, work, ldb, b, ldb )
527 ELSE IF( nrhs.GT.1 ) THEN
528 chunk = lwork / n
529 DO 20 i = 1, nrhs, chunk
530 bl = min( nrhs-i+1, chunk )
531 CALL sgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1,
532 $ i ),
533 $ ldb, zero, work, n )
534 CALL slacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
535 20 CONTINUE
536 ELSE IF( nrhs.EQ.1 ) THEN
537 CALL sgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
538 CALL scopy( n, work, 1, b, 1 )
539 END IF
540
541 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
542 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
543
544
545
546
547 ldwork = m
548 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
549 $ m*lda+m+m*nrhs ) )ldwork = lda
550 itau = 1
551 iwork = m + 1
552
553
554
555
556 CALL sgelqf( m, n, a, lda, work( itau ), work( iwork ),
557 $ lwork-iwork+1, info )
558 il = iwork
559
560
561
562 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwork )
563 CALL slaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
564 $ ldwork )
565 ie = il + ldwork*m
566 itauq = ie + m
567 itaup = itauq + m
568 iwork = itaup + m
569
570
571
572
573 CALL sgebrd( m, m, work( il ), ldwork, s, work( ie ),
574 $ work( itauq ), work( itaup ), work( iwork ),
575 $ lwork-iwork+1, info )
576
577
578
579
580 CALL sormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
581 $ work( itauq ), b, ldb, work( iwork ),
582 $ lwork-iwork+1, info )
583
584
585
586
587 CALL sorgbr(
'P', m, m, m, work( il ), ldwork,
588 $ work( itaup ),
589 $ work( iwork ), lwork-iwork+1, info )
590 iwork = ie + m
591
592
593
594
595
596
597 CALL sbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
598 $ ldwork, a, lda, b, ldb, work( iwork ), info )
599 IF( info.NE.0 )
600 $ GO TO 70
601
602
603
604 thr = max( rcond*s( 1 ), sfmin )
605 IF( rcond.LT.zero )
606 $ thr = max( eps*s( 1 ), sfmin )
607 rank = 0
608 DO 30 i = 1, m
609 IF( s( i ).GT.thr ) THEN
610 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
611 rank = rank + 1
612 ELSE
613 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
614 $ ldb )
615 END IF
616 30 CONTINUE
617 iwork = ie
618
619
620
621
622 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
623 CALL sgemm(
'T',
'N', m, nrhs, m, one, work( il ),
624 $ ldwork,
625 $ b, ldb, zero, work( iwork ), ldb )
626 CALL slacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
627 ELSE IF( nrhs.GT.1 ) THEN
628 chunk = ( lwork-iwork+1 ) / m
629 DO 40 i = 1, nrhs, chunk
630 bl = min( nrhs-i+1, chunk )
631 CALL sgemm(
'T',
'N', m, bl, m, one, work( il ),
632 $ ldwork,
633 $ b( 1, i ), ldb, zero, work( iwork ), m )
634 CALL slacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
635 $ ldb )
636 40 CONTINUE
637 ELSE IF( nrhs.EQ.1 ) THEN
638 CALL sgemv(
'T', m, m, one, work( il ), ldwork, b( 1,
639 $ 1 ), 1, zero, work( iwork ), 1 )
640 CALL scopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
641 END IF
642
643
644
645 CALL slaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
646 iwork = itau + m
647
648
649
650
651 CALL sormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
652 $ ldb, work( iwork ), lwork-iwork+1, info )
653
654 ELSE
655
656
657
658 ie = 1
659 itauq = ie + m
660 itaup = itauq + m
661 iwork = itaup + m
662
663
664
665
666 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
667 $ work( itaup ), work( iwork ), lwork-iwork+1,
668 $ info )
669
670
671
672
673 CALL sormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
674 $ work( itauq ),
675 $ b, ldb, work( iwork ), lwork-iwork+1, info )
676
677
678
679
680 CALL sorgbr(
'P', m, n, m, a, lda, work( itaup ),
681 $ work( iwork ), lwork-iwork+1, info )
682 iwork = ie + m
683
684
685
686
687
688
689 CALL sbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
690 $ 1, b, ldb, work( iwork ), info )
691 IF( info.NE.0 )
692 $ GO TO 70
693
694
695
696 thr = max( rcond*s( 1 ), sfmin )
697 IF( rcond.LT.zero )
698 $ thr = max( eps*s( 1 ), sfmin )
699 rank = 0
700 DO 50 i = 1, m
701 IF( s( i ).GT.thr ) THEN
702 CALL srscl( nrhs, s( i ), b( i, 1 ), ldb )
703 rank = rank + 1
704 ELSE
705 CALL slaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
706 $ ldb )
707 END IF
708 50 CONTINUE
709
710
711
712
713 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
714 CALL sgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb,
715 $ zero,
716 $ work, ldb )
717 CALL slacpy(
'F', n, nrhs, work, ldb, b, ldb )
718 ELSE IF( nrhs.GT.1 ) THEN
719 chunk = lwork / n
720 DO 60 i = 1, nrhs, chunk
721 bl = min( nrhs-i+1, chunk )
722 CALL sgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1,
723 $ i ),
724 $ ldb, zero, work, n )
725 CALL slacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
726 60 CONTINUE
727 ELSE IF( nrhs.EQ.1 ) THEN
728 CALL sgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
729 CALL scopy( n, work, 1, b, 1 )
730 END IF
731 END IF
732
733
734
735 IF( iascl.EQ.1 ) THEN
736 CALL slascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
737 $ info )
738 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
739 $ info )
740 ELSE IF( iascl.EQ.2 ) THEN
741 CALL slascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
742 $ info )
743 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
744 $ info )
745 END IF
746 IF( ibscl.EQ.1 ) THEN
747 CALL slascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
748 $ info )
749 ELSE IF( ibscl.EQ.2 ) THEN
750 CALL slascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
751 $ info )
752 END IF
753
754 70 CONTINUE
756 RETURN
757
758
759
subroutine xerbla(srname, info)
subroutine sbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
SBDSQR
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
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 sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine sgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
SGEMV
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.
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 srscl(n, sa, sx, incx)
SRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine sorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
SORGBR
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