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