176
177
178
179
180
181
182 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
183 DOUBLE PRECISION RCOND
184
185
186 DOUBLE PRECISION RWORK( * ), S( * )
187 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
188
189
190
191
192
193 DOUBLE PRECISION ZERO, ONE
194 parameter( zero = 0.0d+0, one = 1.0d+0 )
195 COMPLEX*16 CZERO, CONE
196 parameter( czero = ( 0.0d+0, 0.0d+0 ),
197 $ cone = ( 1.0d+0, 0.0d+0 ) )
198
199
200 LOGICAL LQUERY
201 INTEGER BL, CHUNK, I, IASCL, IBSCL, IE, IL, IRWORK,
202 $ ITAU, ITAUP, ITAUQ, IWORK, LDWORK, MAXMN,
203 $ MAXWRK, MINMN, MINWRK, MM, MNTHR
204 INTEGER LWORK_ZGEQRF, LWORK_ZUNMQR, LWORK_ZGEBRD,
205 $ LWORK_ZUNMBR, LWORK_ZUNGBR, LWORK_ZUNMLQ,
206 $ LWORK_ZGELQF
207 DOUBLE PRECISION ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM, THR
208
209
210 COMPLEX*16 DUM( 1 )
211
212
217
218
219 INTEGER ILAENV
220 DOUBLE PRECISION DLAMCH, ZLANGE
222
223
224 INTRINSIC max, min
225
226
227
228
229
230 info = 0
231 minmn = min( m, n )
232 maxmn = max( m, n )
233 lquery = ( lwork.EQ.-1 )
234 IF( m.LT.0 ) THEN
235 info = -1
236 ELSE IF( n.LT.0 ) THEN
237 info = -2
238 ELSE IF( nrhs.LT.0 ) THEN
239 info = -3
240 ELSE IF( lda.LT.max( 1, m ) ) THEN
241 info = -5
242 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
243 info = -7
244 END IF
245
246
247
248
249
250
251
252
253
254 IF( info.EQ.0 ) THEN
255 minwrk = 1
256 maxwrk = 1
257 IF( minmn.GT.0 ) THEN
258 mm = m
259 mnthr =
ilaenv( 6,
'ZGELSS',
' ', m, n, nrhs, -1 )
260 IF( m.GE.n .AND. m.GE.mnthr ) THEN
261
262
263
264
265
266 CALL zgeqrf( m, n, a, lda, dum(1), dum(1), -1, info )
267 lwork_zgeqrf = int( dum(1) )
268
269 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, dum(1), b,
270 $ ldb, dum(1), -1, info )
271 lwork_zunmqr = int( dum(1) )
272 mm = n
273 maxwrk = max( maxwrk, n + n*
ilaenv( 1,
'ZGEQRF',
' ',
274 $ m,
275 $ n, -1, -1 ) )
276 maxwrk = max( maxwrk, n + nrhs*
ilaenv( 1,
'ZUNMQR',
277 $ 'LC',
278 $ m, nrhs, n, -1 ) )
279 END IF
280 IF( m.GE.n ) THEN
281
282
283
284
285 CALL zgebrd( mm, n, a, lda, s, s, dum(1), dum(1),
286 $ dum(1),
287 $ -1, info )
288 lwork_zgebrd = int( dum(1) )
289
290 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
291 $ dum(1),
292 $ b, ldb, dum(1), -1, info )
293 lwork_zunmbr = int( dum(1) )
294
295 CALL zungbr(
'P', n, n, n, a, lda, dum(1),
296 $ dum(1), -1, info )
297 lwork_zungbr = int( dum(1) )
298
299 maxwrk = max( maxwrk, 2*n + lwork_zgebrd )
300 maxwrk = max( maxwrk, 2*n + lwork_zunmbr )
301 maxwrk = max( maxwrk, 2*n + lwork_zungbr )
302 maxwrk = max( maxwrk, n*nrhs )
303 minwrk = 2*n + max( nrhs, m )
304 END IF
305 IF( n.GT.m ) THEN
306 minwrk = 2*m + max( nrhs, n )
307 IF( n.GE.mnthr ) THEN
308
309
310
311
312
313 CALL zgelqf( m, n, a, lda, dum(1), dum(1),
314 $ -1, info )
315 lwork_zgelqf = int( dum(1) )
316
317 CALL zgebrd( m, m, a, lda, s, s, dum(1), dum(1),
318 $ dum(1), -1, info )
319 lwork_zgebrd = int( dum(1) )
320
321 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
322 $ dum(1), b, ldb, dum(1), -1, info )
323 lwork_zunmbr = int( dum(1) )
324
325 CALL zungbr(
'P', m, m, m, a, lda, dum(1),
326 $ dum(1), -1, info )
327 lwork_zungbr = int( dum(1) )
328
329 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, dum(1),
330 $ b, ldb, dum(1), -1, info )
331 lwork_zunmlq = int( dum(1) )
332
333 maxwrk = m + lwork_zgelqf
334 maxwrk = max( maxwrk, 3*m + m*m + lwork_zgebrd )
335 maxwrk = max( maxwrk, 3*m + m*m + lwork_zunmbr )
336 maxwrk = max( maxwrk, 3*m + m*m + lwork_zungbr )
337 IF( nrhs.GT.1 ) THEN
338 maxwrk = max( maxwrk, m*m + m + m*nrhs )
339 ELSE
340 maxwrk = max( maxwrk, m*m + 2*m )
341 END IF
342 maxwrk = max( maxwrk, m + lwork_zunmlq )
343 ELSE
344
345
346
347
348 CALL zgebrd( m, n, a, lda, s, s, dum(1), dum(1),
349 $ dum(1), -1, info )
350 lwork_zgebrd = int( dum(1) )
351
352 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, a, lda,
353 $ dum(1), b, ldb, dum(1), -1, info )
354 lwork_zunmbr = int( dum(1) )
355
356 CALL zungbr(
'P', m, n, m, a, lda, dum(1),
357 $ dum(1), -1, info )
358 lwork_zungbr = int( dum(1) )
359 maxwrk = 2*m + lwork_zgebrd
360 maxwrk = max( maxwrk, 2*m + lwork_zunmbr )
361 maxwrk = max( maxwrk, 2*m + lwork_zungbr )
362 maxwrk = max( maxwrk, n*nrhs )
363 END IF
364 END IF
365 maxwrk = max( minwrk, maxwrk )
366 END IF
367 work( 1 ) = maxwrk
368
369 IF( lwork.LT.minwrk .AND. .NOT.lquery )
370 $ info = -12
371 END IF
372
373 IF( info.NE.0 ) THEN
374 CALL xerbla(
'ZGELSS', -info )
375 RETURN
376 ELSE IF( lquery ) THEN
377 RETURN
378 END IF
379
380
381
382 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
383 rank = 0
384 RETURN
385 END IF
386
387
388
391 smlnum = sfmin / eps
392 bignum = one / smlnum
393
394
395
396 anrm =
zlange(
'M', m, n, a, lda, rwork )
397 iascl = 0
398 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
399
400
401
402 CALL zlascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
403 iascl = 1
404 ELSE IF( anrm.GT.bignum ) THEN
405
406
407
408 CALL zlascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
409 iascl = 2
410 ELSE IF( anrm.EQ.zero ) THEN
411
412
413
414 CALL zlaset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
415 CALL dlaset(
'F', minmn, 1, zero, zero, s, minmn )
416 rank = 0
417 GO TO 70
418 END IF
419
420
421
422 bnrm =
zlange(
'M', m, nrhs, b, ldb, rwork )
423 ibscl = 0
424 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
425
426
427
428 CALL zlascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
429 $ info )
430 ibscl = 1
431 ELSE IF( bnrm.GT.bignum ) THEN
432
433
434
435 CALL zlascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
436 $ info )
437 ibscl = 2
438 END IF
439
440
441
442 IF( m.GE.n ) THEN
443
444
445
446 mm = m
447 IF( m.GE.mnthr ) THEN
448
449
450
451 mm = n
452 itau = 1
453 iwork = itau + n
454
455
456
457
458
459 CALL zgeqrf( m, n, a, lda, work( itau ), work( iwork ),
460 $ lwork-iwork+1, info )
461
462
463
464
465
466 CALL zunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ),
467 $ b,
468 $ ldb, work( iwork ), lwork-iwork+1, info )
469
470
471
472 IF( n.GT.1 )
473 $
CALL zlaset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
474 $ lda )
475 END IF
476
477 ie = 1
478 itauq = 1
479 itaup = itauq + n
480 iwork = itaup + n
481
482
483
484
485
486 CALL zgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
487 $ work( itaup ), work( iwork ), lwork-iwork+1,
488 $ info )
489
490
491
492
493
494 CALL zunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
495 $ work( itauq ),
496 $ b, ldb, work( iwork ), lwork-iwork+1, info )
497
498
499
500
501
502 CALL zungbr(
'P', n, n, n, a, lda, work( itaup ),
503 $ work( iwork ), lwork-iwork+1, info )
504 irwork = ie + n
505
506
507
508
509
510
511
512 CALL zbdsqr(
'U', n, n, 0, nrhs, s, rwork( ie ), a, lda,
513 $ dum,
514 $ 1, b, ldb, rwork( irwork ), info )
515 IF( info.NE.0 )
516 $ GO TO 70
517
518
519
520 thr = max( rcond*s( 1 ), sfmin )
521 IF( rcond.LT.zero )
522 $ thr = max( eps*s( 1 ), sfmin )
523 rank = 0
524 DO 10 i = 1, n
525 IF( s( i ).GT.thr ) THEN
526 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
527 rank = rank + 1
528 ELSE
529 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
530 $ ldb )
531 END IF
532 10 CONTINUE
533
534
535
536
537
538 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
539 CALL zgemm(
'C',
'N', n, nrhs, n, cone, a, lda, b, ldb,
540 $ czero, work, ldb )
541 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
542 ELSE IF( nrhs.GT.1 ) THEN
543 chunk = lwork / n
544 DO 20 i = 1, nrhs, chunk
545 bl = min( nrhs-i+1, chunk )
546 CALL zgemm(
'C',
'N', n, bl, n, cone, a, lda, b( 1,
547 $ i ),
548 $ ldb, czero, work, n )
549 CALL zlacpy(
'G', n, bl, work, n, b( 1, i ), ldb )
550 20 CONTINUE
551 ELSE IF( nrhs.EQ.1 ) THEN
552 CALL zgemv(
'C', n, n, cone, a, lda, b, 1, czero, work,
553 $ 1 )
554 CALL zcopy( n, work, 1, b, 1 )
555 END IF
556
557 ELSE IF( n.GE.mnthr .AND. lwork.GE.3*m+m*m+max( m, nrhs, n-2*m ) )
558 $ THEN
559
560
561
562
563
564
565 ldwork = m
566 IF( lwork.GE.3*m+m*lda+max( m, nrhs, n-2*m ) )
567 $ ldwork = lda
568 itau = 1
569 iwork = m + 1
570
571
572
573
574
575 CALL zgelqf( m, n, a, lda, work( itau ), work( iwork ),
576 $ lwork-iwork+1, info )
577 il = iwork
578
579
580
581 CALL zlacpy(
'L', m, m, a, lda, work( il ), ldwork )
582 CALL zlaset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
583 $ ldwork )
584 ie = 1
585 itauq = il + ldwork*m
586 itaup = itauq + m
587 iwork = itaup + m
588
589
590
591
592
593 CALL zgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
594 $ work( itauq ), work( itaup ), work( iwork ),
595 $ lwork-iwork+1, info )
596
597
598
599
600
601 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
602 $ work( itauq ), b, ldb, work( iwork ),
603 $ lwork-iwork+1, info )
604
605
606
607
608
609 CALL zungbr(
'P', m, m, m, work( il ), ldwork,
610 $ work( itaup ),
611 $ work( iwork ), lwork-iwork+1, info )
612 irwork = ie + m
613
614
615
616
617
618
619
620 CALL zbdsqr(
'U', m, m, 0, nrhs, s, rwork( ie ), work( il ),
621 $ ldwork, a, lda, b, ldb, rwork( irwork ), info )
622 IF( info.NE.0 )
623 $ GO TO 70
624
625
626
627 thr = max( rcond*s( 1 ), sfmin )
628 IF( rcond.LT.zero )
629 $ thr = max( eps*s( 1 ), sfmin )
630 rank = 0
631 DO 30 i = 1, m
632 IF( s( i ).GT.thr ) THEN
633 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
634 rank = rank + 1
635 ELSE
636 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
637 $ ldb )
638 END IF
639 30 CONTINUE
640 iwork = il + m*ldwork
641
642
643
644
645
646 IF( lwork.GE.ldb*nrhs+iwork-1 .AND. nrhs.GT.1 ) THEN
647 CALL zgemm(
'C',
'N', m, nrhs, m, cone, work( il ),
648 $ ldwork,
649 $ b, ldb, czero, work( iwork ), ldb )
650 CALL zlacpy(
'G', m, nrhs, work( iwork ), ldb, b, ldb )
651 ELSE IF( nrhs.GT.1 ) THEN
652 chunk = ( lwork-iwork+1 ) / m
653 DO 40 i = 1, nrhs, chunk
654 bl = min( nrhs-i+1, chunk )
655 CALL zgemm(
'C',
'N', m, bl, m, cone, work( il ),
656 $ ldwork,
657 $ b( 1, i ), ldb, czero, work( iwork ), m )
658 CALL zlacpy(
'G', m, bl, work( iwork ), m, b( 1, i ),
659 $ ldb )
660 40 CONTINUE
661 ELSE IF( nrhs.EQ.1 ) THEN
662 CALL zgemv(
'C', m, m, cone, work( il ), ldwork, b( 1,
663 $ 1 ), 1, czero, work( iwork ), 1 )
664 CALL zcopy( m, work( iwork ), 1, b( 1, 1 ), 1 )
665 END IF
666
667
668
669 CALL zlaset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
670 $ ldb )
671 iwork = itau + m
672
673
674
675
676
677 CALL zunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
678 $ ldb, work( iwork ), lwork-iwork+1, info )
679
680 ELSE
681
682
683
684 ie = 1
685 itauq = 1
686 itaup = itauq + m
687 iwork = itaup + m
688
689
690
691
692
693 CALL zgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
694 $ work( itaup ), work( iwork ), lwork-iwork+1,
695 $ info )
696
697
698
699
700
701 CALL zunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
702 $ work( itauq ),
703 $ b, ldb, work( iwork ), lwork-iwork+1, info )
704
705
706
707
708
709 CALL zungbr(
'P', m, n, m, a, lda, work( itaup ),
710 $ work( iwork ), lwork-iwork+1, info )
711 irwork = ie + m
712
713
714
715
716
717
718
719 CALL zbdsqr(
'L', m, n, 0, nrhs, s, rwork( ie ), a, lda,
720 $ dum,
721 $ 1, b, ldb, rwork( irwork ), info )
722 IF( info.NE.0 )
723 $ GO TO 70
724
725
726
727 thr = max( rcond*s( 1 ), sfmin )
728 IF( rcond.LT.zero )
729 $ thr = max( eps*s( 1 ), sfmin )
730 rank = 0
731 DO 50 i = 1, m
732 IF( s( i ).GT.thr ) THEN
733 CALL zdrscl( nrhs, s( i ), b( i, 1 ), ldb )
734 rank = rank + 1
735 ELSE
736 CALL zlaset(
'F', 1, nrhs, czero, czero, b( i, 1 ),
737 $ ldb )
738 END IF
739 50 CONTINUE
740
741
742
743
744
745 IF( lwork.GE.ldb*nrhs .AND. nrhs.GT.1 ) THEN
746 CALL zgemm(
'C',
'N', n, nrhs, m, cone, a, lda, b, ldb,
747 $ czero, work, ldb )
748 CALL zlacpy(
'G', n, nrhs, work, ldb, b, ldb )
749 ELSE IF( nrhs.GT.1 ) THEN
750 chunk = lwork / n
751 DO 60 i = 1, nrhs, chunk
752 bl = min( nrhs-i+1, chunk )
753 CALL zgemm(
'C',
'N', n, bl, m, cone, a, lda, b( 1,
754 $ i ),
755 $ ldb, czero, work, n )
756 CALL zlacpy(
'F', n, bl, work, n, b( 1, i ), ldb )
757 60 CONTINUE
758 ELSE IF( nrhs.EQ.1 ) THEN
759 CALL zgemv(
'C', m, n, cone, a, lda, b, 1, czero, work,
760 $ 1 )
761 CALL zcopy( n, work, 1, b, 1 )
762 END IF
763 END IF
764
765
766
767 IF( iascl.EQ.1 ) THEN
768 CALL zlascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
769 $ info )
770 CALL dlascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
771 $ info )
772 ELSE IF( iascl.EQ.2 ) THEN
773 CALL zlascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
774 $ info )
775 CALL dlascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
776 $ info )
777 END IF
778 IF( ibscl.EQ.1 ) THEN
779 CALL zlascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
780 $ info )
781 ELSE IF( ibscl.EQ.2 ) THEN
782 CALL zlascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
783 $ info )
784 END IF
785 70 CONTINUE
786 work( 1 ) = maxwrk
787 RETURN
788
789
790
subroutine xerbla(srname, info)
subroutine zbdsqr(uplo, n, ncvt, nru, ncc, d, e, vt, ldvt, u, ldu, c, ldc, rwork, info)
ZBDSQR
subroutine zcopy(n, zx, incx, zy, incy)
ZCOPY
subroutine zgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
ZGEBRD
subroutine zgelqf(m, n, a, lda, tau, work, lwork, info)
ZGELQF
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
subroutine zgeqrf(m, n, a, lda, tau, work, lwork, info)
ZGEQRF
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
double precision function dlamch(cmach)
DLAMCH
double precision function zlange(norm, m, n, a, lda, work)
ZLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
subroutine zlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
ZLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
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 zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
subroutine zdrscl(n, sa, sx, incx)
ZDRSCL multiplies a vector by the reciprocal of a real scalar.
subroutine zungbr(vect, m, n, k, a, lda, tau, work, lwork, info)
ZUNGBR
subroutine zunmbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMBR
subroutine zunmlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMLQ
subroutine zunmqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
ZUNMQR