172
173
174
175
176
177
178 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
179 DOUBLE PRECISION RCOND
180
181
182 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
183
184
185
186
187
188 DOUBLE PRECISION ZERO, ONE
189 parameter( zero = 0.0d+0, one = 1.0d+0 )
190
191
192 LOGICAL LQUERY
193 INTEGER BDSPAC, BL, CHUNK, I, IASCL, IBSCL, IE, IL,
194 $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
195 $ MAXWRK, MINMN, MINWRK, MM, MNTHR
196 INTEGER LWORK_DGEQRF, LWORK_DORMQR, LWORK_DGEBRD,
197 $ LWORK_DORMBR, LWORK_DORGBR, LWORK_DORMLQ,
198 $ LWORK_DGELQF
199 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
200
201
202 DOUBLE PRECISION DUM( 1 )
203
204
208
209
210 INTEGER ILAENV
211 DOUBLE PRECISION DLAMCH, DLANGE
213
214
215 INTRINSIC max, min
216
217
218
219
220
221 info = 0
222 minmn = min( m, n )
223 maxmn = max( m, n )
224 lquery = ( lwork.EQ.-1 )
225 IF( m.LT.0 ) THEN
226 info = -1
227 ELSE IF( n.LT.0 ) THEN
228 info = -2
229 ELSE IF( nrhs.LT.0 ) THEN
230 info = -3
231 ELSE IF( lda.LT.max( 1, m ) ) THEN
232 info = -5
233 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
234 info = -7
235 END IF
236
237
238
239
240
241
242
243
244 IF( info.EQ.0 ) THEN
245 minwrk = 1
246 maxwrk = 1
247 IF( minmn.GT.0 ) THEN
248 mm = m
249 mnthr =
ilaenv( 6,
'DGELSS',
' ', m, n, nrhs, -1 )
250 IF( m.GE.n .AND. m.GE.mnthr ) THEN
251
252
253
254
255
256 CALL dgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
257 lwork_dgeqrf = int( dum(1) )
258
259 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, dum(1), b,
260 $ ldb, dum(1), -1, info )
261 lwork_dormqr = int( dum(1) )
262 mm = n
263 maxwrk = max( maxwrk, n + lwork_dgeqrf )
264 maxwrk = max( maxwrk, n + lwork_dormqr )
265 END IF
266 IF( m.GE.n ) THEN
267
268
269
270
271
272 bdspac = max( 1, 5*n )
273
274 CALL dgebrd( mm, n, a, lda, s, dum(1), dum(1),
275 $ dum(1), dum(1), -1, info )
276 lwork_dgebrd = int( dum(1) )
277
278 CALL dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, 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 CALL dlabad( smlnum, bignum )
389
390
391
392 anrm =
dlange(
'M', m, n, a, lda, work )
393 iascl = 0
394 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
395
396
397
398 CALL dlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
399 iascl = 1
400 ELSE IF( anrm.GT.bignum ) THEN
401
402
403
404 CALL dlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
405 iascl = 2
406 ELSE IF( anrm.EQ.zero ) THEN
407
408
409
410 CALL dlaset(
'F', max( m, n ), nrhs, zero, zero, b, ldb )
411 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
412 rank = 0
413 GO TO 70
414 END IF
415
416
417
418 bnrm =
dlange(
'M', m, nrhs, b, ldb, work )
419 ibscl = 0
420 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
421
422
423
424 CALL dlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb, 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, info )
431 ibscl = 2
432 END IF
433
434
435
436 IF( m.GE.n ) THEN
437
438
439
440 mm = m
441 IF( m.GE.mnthr ) THEN
442
443
444
445 mm = n
446 itau = 1
447 iwork = itau + n
448
449
450
451
452 CALL dgeqrf( m, n, a, lda, work( itau ), work( iwork ),
453 $ lwork-iwork+1, info )
454
455
456
457
458 CALL dormqr(
'L',
'T', m, nrhs, n, a, lda, work( itau ), b,
459 $ ldb, work( iwork ), lwork-iwork+1, info )
460
461
462
463 IF( n.GT.1 )
464 $
CALL dlaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), 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 dgebrd( 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 dormbr(
'Q',
'L',
'T', mm, nrhs, n, a, lda, work( itauq ),
483 $ b, ldb, work( iwork ), lwork-iwork+1, info )
484
485
486
487
488 CALL dorgbr(
'P', n, n, n, a, lda, work( itaup ),
489 $ work( iwork ), lwork-iwork+1, info )
490 iwork = ie + n
491
492
493
494
495
496
497 CALL dbdsqr(
'U', n, n, 0, nrhs, s, work( ie ), a, lda, dum,
498 $ 1, b, ldb, work( iwork ), info )
499 IF( info.NE.0 )
500 $ GO TO 70
501
502
503
504 thr = max( rcond*s( 1 ), sfmin )
505 IF( rcond.LT.zero )
506 $ thr = max( eps*s( 1 ), sfmin )
507 rank = 0
508 DO 10 i = 1, n
509 IF( s( i ).GT.thr ) THEN
510 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
511 rank = rank + 1
512 ELSE
513 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
514 END IF
515 10 CONTINUE
516
517
518
519
520 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
521 CALL dgemm(
'T',
'N', n, nrhs, n, one, a, lda, b, ldb, zero,
522 $ work, ldb )
523 CALL dlacpy(
'G', n, nrhs, work, ldb, b, ldb )
524 ELSE IF( nrhs.GT.1 ) THEN
525 chunk = lwork / n
526 DO 20 i = 1, nrhs, chunk
527 bl = min( nrhs-i+1, chunk )
528 CALL dgemm(
'T',
'N', n, bl, n, one, a, lda, b( 1, i ),
529 $ ldb, zero, work, n )
530 CALL dlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
531 20 CONTINUE
532 ELSE
533 CALL dgemv(
'T', n, n, one, a, lda, b, 1, zero, work, 1 )
534 CALL dcopy( n, work, 1, b, 1 )
535 END IF
536
537 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
538 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
539
540
541
542
543 ldwork = m
544 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
545 $ m*lda+m+m*nrhs ) )ldwork = lda
546 itau = 1
547 iwork = m + 1
548
549
550
551
552 CALL dgelqf( m, n, a, lda, work( itau ), work( iwork ),
553 $ lwork-iwork+1, info )
554 il = iwork
555
556
557
558 CALL dlacpy(
'L', m, m, a, lda, work( il ), ldwork )
559 CALL dlaset(
'U', m-1, m-1, zero, zero, work( il+ldwork ),
560 $ ldwork )
561 ie = il + ldwork*m
562 itauq = ie + m
563 itaup = itauq + m
564 iwork = itaup + m
565
566
567
568
569 CALL dgebrd( m, m, work( il ), ldwork, s, work( ie ),
570 $ work( itauq ), work( itaup ), work( iwork ),
571 $ lwork-iwork+1, info )
572
573
574
575
576 CALL dormbr(
'Q',
'L',
'T', m, nrhs, m, work( il ), ldwork,
577 $ work( itauq ), b, ldb, work( iwork ),
578 $ lwork-iwork+1, info )
579
580
581
582
583 CALL dorgbr(
'P', m, m, m, work( il ), ldwork, work( itaup ),
584 $ work( iwork ), lwork-iwork+1, info )
585 iwork = ie + m
586
587
588
589
590
591
592 CALL dbdsqr(
'U', m, m, 0, nrhs, s, work( ie ), work( il ),
593 $ ldwork, a, lda, b, ldb, work( iwork ), info )
594 IF( info.NE.0 )
595 $ GO TO 70
596
597
598
599 thr = max( rcond*s( 1 ), sfmin )
600 IF( rcond.LT.zero )
601 $ thr = max( eps*s( 1 ), sfmin )
602 rank = 0
603 DO 30 i = 1, m
604 IF( s( i ).GT.thr ) THEN
605 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
606 rank = rank + 1
607 ELSE
608 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
609 END IF
610 30 CONTINUE
611 iwork = ie
612
613
614
615
616 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
617 CALL dgemm(
'T',
'N', m, nrhs, m, one, work( il ), ldwork,
618 $ b, ldb, zero, work( iwork ), ldb )
619 CALL dlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
620 ELSE IF( nrhs.GT.1 ) THEN
621 chunk = ( lwork-iwork+1 ) / m
622 DO 40 i = 1, nrhs, chunk
623 bl = min( nrhs-i+1, chunk )
624 CALL dgemm(
'T',
'N', m, bl, m, one, work( il ), ldwork,
625 $ b( 1, i ), ldb, zero, work( iwork ), m )
626 CALL dlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
627 $ ldb )
628 40 CONTINUE
629 ELSE
630 CALL dgemv(
'T', m, m, one, work( il ), ldwork, b( 1, 1 ),
631 $ 1, zero, work( iwork ), 1 )
632 CALL dcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
633 END IF
634
635
636
637 CALL dlaset(
'F', n-m, nrhs, zero, zero, b( m+1, 1 ), ldb )
638 iwork = itau + m
639
640
641
642
643 CALL dormlq(
'L',
'T', n, nrhs, m, a, lda, work( itau ), b,
644 $ ldb, work( iwork ), lwork-iwork+1, info )
645
646 ELSE
647
648
649
650 ie = 1
651 itauq = ie + m
652 itaup = itauq + m
653 iwork = itaup + m
654
655
656
657
658 CALL dgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
659 $ work( itaup ), work( iwork ), lwork-iwork+1,
660 $ info )
661
662
663
664
665 CALL dormbr(
'Q',
'L',
'T', m, nrhs, n, a, lda, work( itauq ),
666 $ b, ldb, work( iwork ), lwork-iwork+1, info )
667
668
669
670
671 CALL dorgbr(
'P', m, n, m, a, lda, work( itaup ),
672 $ work( iwork ), lwork-iwork+1, info )
673 iwork = ie + m
674
675
676
677
678
679
680 CALL dbdsqr(
'L', m, n, 0, nrhs, s, work( ie ), a, lda, dum,
681 $ 1, b, ldb, work( iwork ), info )
682 IF( info.NE.0 )
683 $ GO TO 70
684
685
686
687 thr = max( rcond*s( 1 ), sfmin )
688 IF( rcond.LT.zero )
689 $ thr = max( eps*s( 1 ), sfmin )
690 rank = 0
691 DO 50 i = 1, m
692 IF( s( i ).GT.thr ) THEN
693 CALL drscl( nrhs, s( i ), b( i, 1 ), ldb )
694 rank = rank + 1
695 ELSE
696 CALL dlaset(
'F', 1, nrhs, zero, zero, b( i, 1 ), ldb )
697 END IF
698 50 CONTINUE
699
700
701
702
703 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
704 CALL dgemm(
'T',
'N', n, nrhs, m, one, a, lda, b, ldb, zero,
705 $ work, ldb )
706 CALL dlacpy(
'F', n, nrhs, work, ldb, b, ldb )
707 ELSE IF( nrhs.GT.1 ) THEN
708 chunk = lwork / n
709 DO 60 i = 1, nrhs, chunk
710 bl = min( nrhs-i+1, chunk )
711 CALL dgemm(
'T',
'N', n, bl, m, one, a, lda, b( 1, i ),
712 $ ldb, zero, work, n )
713 CALL dlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
714 60 CONTINUE
715 ELSE
716 CALL dgemv(
'T', m, n, one, a, lda, b, 1, zero, work, 1 )
717 CALL dcopy( n, work, 1, b, 1 )
718 END IF
719 END IF
720
721
722
723 IF( iascl.EQ.1 ) THEN
724 CALL dlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb, info )
725 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
726 $ info )
727 ELSE IF( iascl.EQ.2 ) THEN
728 CALL dlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb, info )
729 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
730 $ info )
731 END IF
732 IF( ibscl.EQ.1 ) THEN
733 CALL dlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb, info )
734 ELSE IF( ibscl.EQ.2 ) THEN
735 CALL dlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb, info )
736 END IF
737
738 70 CONTINUE
739 work( 1 ) = maxwrk
740 RETURN
741
742
743
double precision function dlamch(CMACH)
DLAMCH
subroutine dlabad(SMALL, LARGE)
DLABAD
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 dlacpy(UPLO, M, N, A, LDA, B, LDB)
DLACPY copies all or part of one two-dimensional array to another.
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.
integer function ilaenv(ISPEC, NAME, OPTS, N1, N2, N3, N4)
ILAENV
subroutine xerbla(SRNAME, INFO)
XERBLA
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 dgemv(TRANS, M, N, ALPHA, A, LDA, X, INCX, BETA, Y, INCY)
DGEMV
subroutine dgemm(TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
DGEMM
subroutine dorgbr(VECT, M, N, K, A, LDA, TAU, WORK, LWORK, INFO)
DORGBR
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 dgeqrf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGEQRF
subroutine dgelqf(M, N, A, LDA, TAU, WORK, LWORK, INFO)
DGELQF
subroutine dgebrd(M, N, A, LDA, D, E, TAUQ, TAUP, WORK, LWORK, INFO)
DGEBRD
subroutine drscl(N, SA, SX, INCX)
DRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine dormqr(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMQR
subroutine dormlq(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMLQ
subroutine dormbr(VECT, SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
DORMBR