170
171
172
173
174
175
176 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
177 DOUBLE PRECISION RCOND
178
179
180 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
181
182
183
184
185
186 DOUBLE PRECISION ZERO, ONE
187 parameter( zero = 0.0d+0, one = 1.0d+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_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
195 $ LWORK_DORMBR, LWORK_DORGBR, LWORK_DORMLQ,
196 $ LWORK_DGELQF
197 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
198
199
200 DOUBLE PRECISION DUM( 1 )
201
202
207
208
209 INTEGER ILAENV
210 DOUBLE PRECISION DLAMCH, DLANGE
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,
'DGELSS',
' ', m, n, nrhs, -1 )
249 IF( m.GE.n .AND. m.GE.mnthr ) THEN
250
251
252
253
254
255 CALL dgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
256 lwork_dgeqrf = int( dum(1) )
257
258 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
259 $ ldb, dum(1), -1, info )
260 lwork_dormqr = int( dum(1) )
261 mm = n
262 maxwrk = max( maxwrk, n + lwork_dgeqrf )
263 maxwrk = max( maxwrk, n + lwork_dormqr )
264 END IF
265 IF( m.GE.n ) THEN
266
267
268
269
270
271 bdspac = max( 1, 5*n )
272
273 CALL dgebrd( mm, n, a, lda, s, dum(1), dum(1),
274 $ dum(1), dum(1), -1, info )
275 lwork_dgebrd = int( dum(1) )
276
277 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
278 $ dum(1),
279 $ b, ldb, dum(1), -1, info )
280 lwork_dormbr = int( dum(1) )
281
282 CALL dorgbr(
'P', n, n, n, a, lda, dum(1),
283 $ dum(1), -1, info )
284 lwork_dorgbr = int( dum(1) )
285
286 maxwrk = max( maxwrk, 3*n + lwork_dgebrd )
287 maxwrk = max( maxwrk, 3*n + lwork_dormbr )
288 maxwrk = max( maxwrk, 3*n + lwork_dorgbr )
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 dgelqf( m, n, a, lda, dum(1), dum(1),
307 $ -1, info )
308 lwork_dgelqf = int( dum(1) )
309
310 CALL dgebrd( m, m, a, lda, s, dum(1), dum(1),
311 $ dum(1), dum(1), -1, info )
312 lwork_dgebrd = int( dum(1) )
313
314 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
315 $ dum(1), b, ldb, dum(1), -1, info )
316 lwork_dormbr = int( dum(1) )
317
318 CALL dorgbr(
'P', m, m, m, a, lda, dum(1),
319 $ dum(1), -1, info )
320 lwork_dorgbr = int( dum(1) )
321
322 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, dum(1),
323 $ b, ldb, dum(1), -1, info )
324 lwork_dormlq = int( dum(1) )
325
326 maxwrk = m + lwork_dgelqf
327 maxwrk = max( maxwrk, m*m + 4*m + lwork_dgebrd )
328 maxwrk = max( maxwrk, m*m + 4*m + lwork_dormbr )
329 maxwrk = max( maxwrk, m*m + 4*m + lwork_dorgbr )
330 maxwrk = max( maxwrk, m*m + m + bdspac )
331 IF( nrhs.GT.1 ) THEN
332 maxwrk = max( maxwrk, m*m + m + m*nrhs )
333 ELSE
334 maxwrk = max( maxwrk, m*m + 2*m )
335 END IF
336 maxwrk = max( maxwrk, m + lwork_dormlq )
337 ELSE
338
339
340
341
342 CALL dgebrd( m, n, a, lda, s, dum(1), dum(1),
343 $ dum(1), dum(1), -1, info )
344 lwork_dgebrd = int( dum(1) )
345
346 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, a, lda,
347 $ dum(1), b, ldb, dum(1), -1, info )
348 lwork_dormbr = int( dum(1) )
349
350 CALL dorgbr(
'P', m, n, m, a, lda, dum(1),
351 $ dum(1), -1, info )
352 lwork_dorgbr = int( dum(1) )
353 maxwrk = 3*m + lwork_dgebrd
354 maxwrk = max( maxwrk, 3*m + lwork_dormbr )
355 maxwrk = max( maxwrk, 3*m + lwork_dorgbr )
356 maxwrk = max( maxwrk, bdspac )
357 maxwrk = max( maxwrk, n*nrhs )
358 END IF
359 END IF
360 maxwrk = max( minwrk, maxwrk )
361 END IF
362 work( 1 ) = maxwrk
363
364 IF( lwork.LT.minwrk .AND. .NOT.lquery )
365 $ info = -12
366 END IF
367
368 IF( info.NE.0 ) THEN
369 CALL xerbla(
'DGELSS', -info )
370 RETURN
371 ELSE IF( lquery ) THEN
372 RETURN
373 END IF
374
375
376
377 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
378 rank = 0
379 RETURN
380 END IF
381
382
383
386 smlnum = sfmin / eps
387 bignum = one / smlnum
388
389
390
391 anrm =
dlange(
'M', m, n, a, lda, work )
392 iascl = 0
393 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
394
395
396
397 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
398 iascl = 1
399 ELSE IF( anrm.GT.bignum ) THEN
400
401
402
403 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
404 iascl = 2
405 ELSE IF( anrm.EQ.zero ) THEN
406
407
408
409 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
410 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
411 rank = 0
412 GO TO 70
413 END IF
414
415
416
417 bnrm =
dlange(
'M', m, nrhs, b, ldb, work )
418 ibscl = 0
419 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
420
421
422
423 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
424 $ info )
425 ibscl = 1
426 ELSE IF( bnrm.GT.bignum ) THEN
427
428
429
430 CALL dlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
431 $ info )
432 ibscl = 2
433 END IF
434
435
436
437 IF( m.GE.n ) THEN
438
439
440
441 mm = m
442 IF( m.GE.mnthr ) THEN
443
444
445
446 mm = n
447 itau = 1
448 iwork = itau + n
449
450
451
452
453 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
454 $ lwork-iwork+1, info )
455
456
457
458
459 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ),
460 $ b,
461 $ ldb, work( iwork ), lwork-iwork+1, info )
462
463
464
465 IF( n.GT.1 )
466 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ),
467 $ lda )
468 END IF
469
470 ie = 1
471 itauq = ie + n
472 itaup = itauq + n
473 iwork = itaup + n
474
475
476
477
478 CALL dgebrd( mm, n, a, lda, s, work( ie ), work( itauq ),
479 $ work( itaup ), work( iwork ), lwork-iwork+1,
480 $ info )
481
482
483
484
485 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda,
486 $ work( itauq ),
487 $ b, ldb, work( iwork ), lwork-iwork+1, info )
488
489
490
491
492 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
493 $ work( iwork ), lwork-iwork+1, info )
494 iwork = ie + n
495
496
497
498
499
500
501 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
502 $ 1, b, ldb, work( iwork ), info )
503 IF( info.NE.0 )
504 $ GO TO 70
505
506
507
508 thr = max( rcond*s( 1 ), sfmin )
509 IF( rcond.LT.zero )
510 $ thr = max( eps*s( 1 ), sfmin )
511 rank = 0
512 DO 10 i = 1, n
513 IF( s( i ).GT.thr ) THEN
514 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
515 rank = rank + 1
516 ELSE
517 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
518 $ ldb )
519 END IF
520 10 CONTINUE
521
522
523
524
525 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
526 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb,
527 $ zero,
528 $ work, ldb )
529 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
530 ELSE IF( nrhs.GT.1 ) THEN
531 chunk = lwork / n
532 DO 20 i = 1, nrhs, chunk
533 bl = min( nrhs-i+1, chunk )
534 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1,
535 $ i ),
536 $ ldb, zero, work, n )
537 CALL dlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
538 20 CONTINUE
539 ELSE IF( nrhs.EQ.1 ) THEN
540 CALL dgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
541 CALL dcopy( n, work, 1, b, 1 )
542 END IF
543
544 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
545 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
546
547
548
549
550 ldwork = m
551 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
552 $ m*lda+m+m*nrhs ) )ldwork = lda
553 itau = 1
554 iwork = m + 1
555
556
557
558
559 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
560 $ lwork-iwork+1, info )
561 il = iwork
562
563
564
565 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
566 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
567 $ ldwork )
568 ie = il + ldwork*m
569 itauq = ie + m
570 itaup = itauq + m
571 iwork = itaup + m
572
573
574
575
576 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
577 $ work( itauq ), work( itaup ), work( iwork ),
578 $ lwork-iwork+1, info )
579
580
581
582
583 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
584 $ work( itauq ), b, ldb, work( iwork ),
585 $ lwork-iwork+1, info )
586
587
588
589
590 CALL dorgbr(
'P', m, m, m, work( il ), ldwork,
591 $ work( itaup ),
592 $ work( iwork ), lwork-iwork+1, info )
593 iwork = ie + m
594
595
596
597
598
599
600 CALL dbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
601 $ ldwork, a, lda, b, ldb, work( iwork ), info )
602 IF( info.NE.0 )
603 $ GO TO 70
604
605
606
607 thr = max( rcond*s( 1 ), sfmin )
608 IF( rcond.LT.zero )
609 $ thr = max( eps*s( 1 ), sfmin )
610 rank = 0
611 DO 30 i = 1, m
612 IF( s( i ).GT.thr ) THEN
613 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
614 rank = rank + 1
615 ELSE
616 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
617 $ ldb )
618 END IF
619 30 CONTINUE
620 iwork = ie
621
622
623
624
625 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
626 CALL dgemm(
'T',
'N', m, nrhs, m, one, work( il ),
627 $ ldwork,
628 $ b, ldb, zero, work( iwork ), ldb )
629 CALL dlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
630 ELSE IF( nrhs.GT.1 ) THEN
631 chunk = ( lwork-iwork+1 ) / m
632 DO 40 i = 1, nrhs, chunk
633 bl = min( nrhs-i+1, chunk )
634 CALL dgemm(
'T',
'N', m, bl, m, one, work( il ),
635 $ ldwork,
636 $ b( 1, i ), ldb, zero, work( iwork ), m )
637 CALL dlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
638 $ ldb )
639 40 CONTINUE
640 ELSE IF( nrhs.EQ.1 ) THEN
641 CALL dgemv(
'T', m, m, one, work( il ), ldwork, b( 1,
642 $ 1 ),1, zero, work( iwork ), 1 )
643 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
644 END IF
645
646
647
648 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
649 iwork = itau + m
650
651
652
653
654 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
655 $ ldb, work( iwork ), lwork-iwork+1, info )
656
657 ELSE
658
659
660
661 ie = 1
662 itauq = ie + m
663 itaup = itauq + m
664 iwork = itaup + m
665
666
667
668
669 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
670 $ work( itaup ), work( iwork ), lwork-iwork+1,
671 $ info )
672
673
674
675
676 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda,
677 $ work( itauq ),
678 $ b, ldb, work( iwork ), lwork-iwork+1, info )
679
680
681
682
683 CALL dorgbr(
'P', m, n, m, a, lda, work( itaup ),
684 $ work( iwork ), lwork-iwork+1, info )
685 iwork = ie + m
686
687
688
689
690
691
692 CALL dbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
693 $ 1, b, ldb, work( iwork ), info )
694 IF( info.NE.0 )
695 $ GO TO 70
696
697
698
699 thr = max( rcond*s( 1 ), sfmin )
700 IF( rcond.LT.zero )
701 $ thr = max( eps*s( 1 ), sfmin )
702 rank = 0
703 DO 50 i = 1, m
704 IF( s( i ).GT.thr ) THEN
705 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
706 rank = rank + 1
707 ELSE
708 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ),
709 $ ldb )
710 END IF
711 50 CONTINUE
712
713
714
715
716 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
717 CALL dgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb,
718 $ zero,
719 $ work, ldb )
720 CALL dlacpy(
'F', n, nrhs, work, ldb, b, ldb )
721 ELSE IF( nrhs.GT.1 ) THEN
722 chunk = lwork / n
723 DO 60 i = 1, nrhs, chunk
724 bl = min( nrhs-i+1, chunk )
725 CALL dgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1,
726 $ i ),
727 $ ldb, zero, work, n )
728 CALL dlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
729 60 CONTINUE
730 ELSE IF( nrhs.EQ.1 ) THEN
731 CALL dgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
732 CALL dcopy( n, work, 1, b, 1 )
733 END IF
734 END IF
735
736
737
738 IF( iascl.EQ.1 ) THEN
739 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
740 $ info )
741 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
742 $ info )
743 ELSE IF( iascl.EQ.2 ) THEN
744 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
745 $ info )
746 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
747 $ info )
748 END IF
749 IF( ibscl.EQ.1 ) THEN
750 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
751 $ info )
752 ELSE IF( ibscl.EQ.2 ) THEN
753 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
754 $ info )
755 END IF
756
757 70 CONTINUE
758 work( 1 ) = maxwrk
759 RETURN
760
761
762
subroutine xerbla(srname, info)
subroutine dbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, work, info)
DBDSQR
subroutine dcopy(n, dx, incx, dy, incy)
DCOPY
subroutine dgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
DGEBRD
subroutine dgelqf(m, n, a, lda, tau, work, lwork, info)
DGELQF
subroutine dgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
DGEMM
subroutine dgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
DGEMV
subroutine dgeqrf(m, n, a, lda, tau, work, lwork, info)
DGEQRF
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine dlacpy(uplo, m, n, a, lda, b, ldb)
DLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function dlange(norm, m, n, a, lda, work)
DLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
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 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 drscl(n, sa, sx, incx)
DRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine dorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
DORGBR
subroutine dormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMBR
subroutine dormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMLQ
subroutine dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
DORMQR