217
218
219
220
221
222
223 INTEGER INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
224 REAL RCOND
225
226
227 INTEGER IWORK( * )
228 REAL RWORK( * ), S( * )
229 COMPLEX A( LDA, * ), B( LDB, * ), WORK( * )
230
231
232
233
234
235 REAL ZERO, ONE, TWO
236 parameter( zero = 0.0e+0, one = 1.0e+0, two = 2.0e+0 )
237 COMPLEX CZERO
238 parameter( czero = ( 0.0e+0, 0.0e+0 ) )
239
240
241 LOGICAL LQUERY
242 INTEGER IASCL, IBSCL, IE, IL, ITAU, ITAUP, ITAUQ,
243 $ LDWORK, LIWORK, LRWORK, MAXMN, MAXWRK, MINMN,
244 $ MINWRK, MM, MNTHR, NLVL, NRWORK, NWORK, SMLSIZ
245 REAL ANRM, BIGNUM, BNRM, EPS, SFMIN, SMLNUM
246
247
252
253
254 INTEGER ILAENV
255 REAL CLANGE, SLAMCH, SROUNDUP_LWORK
258
259
260 INTRINSIC int, log, max, min, real
261
262
263
264
265
266 info = 0
267 minmn = min( m, n )
268 maxmn = max( m, n )
269 lquery = ( lwork.EQ.-1 )
270 IF( m.LT.0 ) THEN
271 info = -1
272 ELSE IF( n.LT.0 ) THEN
273 info = -2
274 ELSE IF( nrhs.LT.0 ) THEN
275 info = -3
276 ELSE IF( lda.LT.max( 1, m ) ) THEN
277 info = -5
278 ELSE IF( ldb.LT.max( 1, maxmn ) ) THEN
279 info = -7
280 END IF
281
282
283
284
285
286
287
288
289 IF( info.EQ.0 ) THEN
290 minwrk = 1
291 maxwrk = 1
292 liwork = 1
293 lrwork = 1
294 IF( minmn.GT.0 ) THEN
295 smlsiz =
ilaenv( 9,
'CGELSD',
' ', 0, 0, 0, 0 )
296 mnthr =
ilaenv( 6,
'CGELSD',
' ', m, n, nrhs, -1 )
297 nlvl = max( int( log( real( minmn ) / real( smlsiz + 1 ) ) /
298 $ log( two ) ) + 1, 0 )
299 liwork = 3*minmn*nlvl + 11*minmn
300 mm = m
301 IF( m.GE.n .AND. m.GE.mnthr ) THEN
302
303
304
305
306 mm = n
307 maxwrk = max( maxwrk, n*
ilaenv( 1,
'CGEQRF',
' ', m,
308 $ n,
309 $ -1, -1 ) )
310 maxwrk = max( maxwrk, nrhs*
ilaenv( 1,
'CUNMQR',
'LC',
311 $ m,
312 $ nrhs, n, -1 ) )
313 END IF
314 IF( m.GE.n ) THEN
315
316
317
318 lrwork = 10*n + 2*n*smlsiz + 8*n*nlvl + 3*smlsiz*nrhs +
319 $ max( (smlsiz+1)**2, n*(1+nrhs) + 2*nrhs )
320 maxwrk = max( maxwrk, 2*n + ( mm + n )*
ilaenv( 1,
321 $ 'CGEBRD', ' ', mm, n, -1, -1 ) )
322 maxwrk = max( maxwrk, 2*n + nrhs*
ilaenv( 1,
'CUNMBR',
323 $ 'QLC', mm, nrhs, n, -1 ) )
324 maxwrk = max( maxwrk, 2*n + ( n - 1 )*
ilaenv( 1,
325 $ 'CUNMBR', 'PLN', n, nrhs, n, -1 ) )
326 maxwrk = max( maxwrk, 2*n + n*nrhs )
327 minwrk = max( 2*n + mm, 2*n + n*nrhs )
328 END IF
329 IF( n.GT.m ) THEN
330 lrwork = 10*m + 2*m*smlsiz + 8*m*nlvl + 3*smlsiz*nrhs +
331 $ max( (smlsiz+1)**2, n*(1+nrhs) + 2*nrhs )
332 IF( n.GE.mnthr ) THEN
333
334
335
336
337 maxwrk = m + m*
ilaenv( 1,
'CGELQF',
' ', m, n, -1,
338 $ -1 )
339 maxwrk = max( maxwrk, m*m + 4*m + 2*m*
ilaenv( 1,
340 $ 'CGEBRD', ' ', m, m, -1, -1 ) )
341 maxwrk = max( maxwrk, m*m + 4*m + nrhs*
ilaenv( 1,
342 $ 'CUNMBR', 'QLC', m, nrhs, m, -1 ) )
343 maxwrk = max( maxwrk,
344 $ m*m + 4*m + ( m - 1 )*
ilaenv( 1,
345 $ 'CUNMLQ', 'LC', n, nrhs, m, -1 ) )
346 IF( nrhs.GT.1 ) THEN
347 maxwrk = max( maxwrk, m*m + m + m*nrhs )
348 ELSE
349 maxwrk = max( maxwrk, m*m + 2*m )
350 END IF
351 maxwrk = max( maxwrk, m*m + 4*m + m*nrhs )
352
353
354 maxwrk = max( maxwrk,
355 $ 4*m+m*m+max( m, 2*m-4, nrhs, n-3*m ) )
356 ELSE
357
358
359
360 maxwrk = 2*m + ( n + m )*
ilaenv( 1,
'CGEBRD',
' ',
361 $ m,
362 $ n, -1, -1 )
363 maxwrk = max( maxwrk, 2*m + nrhs*
ilaenv( 1,
364 $ 'CUNMBR',
365 $ 'QLC', m, nrhs, m, -1 ) )
366 maxwrk = max( maxwrk, 2*m + m*
ilaenv( 1,
'CUNMBR',
367 $ 'PLN', n, nrhs, m, -1 ) )
368 maxwrk = max( maxwrk, 2*m + m*nrhs )
369 END IF
370 minwrk = max( 2*m + n, 2*m + m*nrhs )
371 END IF
372 END IF
373 minwrk = min( minwrk, maxwrk )
375 iwork( 1 ) = liwork
376 rwork( 1 ) = real( lrwork )
377
378 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
379 info = -12
380 END IF
381 END IF
382
383 IF( info.NE.0 ) THEN
384 CALL xerbla(
'CGELSD', -info )
385 RETURN
386 ELSE IF( lquery ) THEN
387 RETURN
388 END IF
389
390
391
392 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
393 rank = 0
394 RETURN
395 END IF
396
397
398
401 smlnum = sfmin / eps
402 bignum = one / smlnum
403
404
405
406 anrm =
clange(
'M', m, n, a, lda, rwork )
407 iascl = 0
408 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
409
410
411
412 CALL clascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
413 iascl = 1
414 ELSE IF( anrm.GT.bignum ) THEN
415
416
417
418 CALL clascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
419 iascl = 2
420 ELSE IF( anrm.EQ.zero ) THEN
421
422
423
424 CALL claset(
'F', max( m, n ), nrhs, czero, czero, b, ldb )
425 CALL slaset(
'F', minmn, 1, zero, zero, s, 1 )
426 rank = 0
427 GO TO 10
428 END IF
429
430
431
432 bnrm =
clange(
'M', m, nrhs, b, ldb, rwork )
433 ibscl = 0
434 IF( bnrm.GT.zero .AND. bnrm.LT.smlnum ) THEN
435
436
437
438 CALL clascl(
'G', 0, 0, bnrm, smlnum, m, nrhs, b, ldb,
439 $ info )
440 ibscl = 1
441 ELSE IF( bnrm.GT.bignum ) THEN
442
443
444
445 CALL clascl(
'G', 0, 0, bnrm, bignum, m, nrhs, b, ldb,
446 $ info )
447 ibscl = 2
448 END IF
449
450
451
452 IF( m.LT.n )
453 $
CALL claset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
454 $ ldb )
455
456
457
458 IF( m.GE.n ) THEN
459
460
461
462 mm = m
463 IF( m.GE.mnthr ) THEN
464
465
466
467 mm = n
468 itau = 1
469 nwork = itau + n
470
471
472
473
474
475 CALL cgeqrf( m, n, a, lda, work( itau ), work( nwork ),
476 $ lwork-nwork+1, info )
477
478
479
480
481
482 CALL cunmqr(
'L',
'C', m, nrhs, n, a, lda, work( itau ),
483 $ b,
484 $ ldb, work( nwork ), lwork-nwork+1, info )
485
486
487
488 IF( n.GT.1 ) THEN
489 CALL claset(
'L', n-1, n-1, czero, czero, a( 2, 1 ),
490 $ lda )
491 END IF
492 END IF
493
494 itauq = 1
495 itaup = itauq + n
496 nwork = itaup + n
497 ie = 1
498 nrwork = ie + n
499
500
501
502
503
504 CALL cgebrd( mm, n, a, lda, s, rwork( ie ), work( itauq ),
505 $ work( itaup ), work( nwork ), lwork-nwork+1,
506 $ info )
507
508
509
510
511 CALL cunmbr(
'Q',
'L',
'C', mm, nrhs, n, a, lda,
512 $ work( itauq ),
513 $ b, ldb, work( nwork ), lwork-nwork+1, info )
514
515
516
517 CALL clalsd(
'U', smlsiz, n, nrhs, s, rwork( ie ), b, ldb,
518 $ rcond, rank, work( nwork ), rwork( nrwork ),
519 $ iwork, info )
520 IF( info.NE.0 ) THEN
521 GO TO 10
522 END IF
523
524
525
526 CALL cunmbr(
'P',
'L',
'N', n, nrhs, n, a, lda,
527 $ work( itaup ),
528 $ b, ldb, work( nwork ), lwork-nwork+1, info )
529
530 ELSE IF( n.GE.mnthr .AND. lwork.GE.4*m+m*m+
531 $ max( m, 2*m-4, nrhs, n-3*m ) ) THEN
532
533
534
535
536 ldwork = m
537 IF( lwork.GE.max( 4*m+m*lda+max( m, 2*m-4, nrhs, n-3*m ),
538 $ m*lda+m+m*nrhs ) )ldwork = lda
539 itau = 1
540 nwork = m + 1
541
542
543
544
545 CALL cgelqf( m, n, a, lda, work( itau ), work( nwork ),
546 $ lwork-nwork+1, info )
547 il = nwork
548
549
550
551 CALL clacpy(
'L', m, m, a, lda, work( il ), ldwork )
552 CALL claset(
'U', m-1, m-1, czero, czero, work( il+ldwork ),
553 $ ldwork )
554 itauq = il + ldwork*m
555 itaup = itauq + m
556 nwork = itaup + m
557 ie = 1
558 nrwork = ie + m
559
560
561
562
563
564 CALL cgebrd( m, m, work( il ), ldwork, s, rwork( ie ),
565 $ work( itauq ), work( itaup ), work( nwork ),
566 $ lwork-nwork+1, info )
567
568
569
570
571 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, m, work( il ), ldwork,
572 $ work( itauq ), b, ldb, work( nwork ),
573 $ lwork-nwork+1, info )
574
575
576
577 CALL clalsd(
'U', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,
578 $ rcond, rank, work( nwork ), rwork( nrwork ),
579 $ iwork, info )
580 IF( info.NE.0 ) THEN
581 GO TO 10
582 END IF
583
584
585
586 CALL cunmbr(
'P',
'L',
'N', m, nrhs, m, work( il ), ldwork,
587 $ work( itaup ), b, ldb, work( nwork ),
588 $ lwork-nwork+1, info )
589
590
591
592 CALL claset(
'F', n-m, nrhs, czero, czero, b( m+1, 1 ),
593 $ ldb )
594 nwork = itau + m
595
596
597
598
599 CALL cunmlq(
'L',
'C', n, nrhs, m, a, lda, work( itau ), b,
600 $ ldb, work( nwork ), lwork-nwork+1, info )
601
602 ELSE
603
604
605
606 itauq = 1
607 itaup = itauq + m
608 nwork = itaup + m
609 ie = 1
610 nrwork = ie + m
611
612
613
614
615
616 CALL cgebrd( m, n, a, lda, s, rwork( ie ), work( itauq ),
617 $ work( itaup ), work( nwork ), lwork-nwork+1,
618 $ info )
619
620
621
622
623 CALL cunmbr(
'Q',
'L',
'C', m, nrhs, n, a, lda,
624 $ work( itauq ),
625 $ b, ldb, work( nwork ), lwork-nwork+1, info )
626
627
628
629 CALL clalsd(
'L', smlsiz, m, nrhs, s, rwork( ie ), b, ldb,
630 $ rcond, rank, work( nwork ), rwork( nrwork ),
631 $ iwork, info )
632 IF( info.NE.0 ) THEN
633 GO TO 10
634 END IF
635
636
637
638 CALL cunmbr(
'P',
'L',
'N', n, nrhs, m, a, lda,
639 $ work( itaup ),
640 $ b, ldb, work( nwork ), lwork-nwork+1, info )
641
642 END IF
643
644
645
646 IF( iascl.EQ.1 ) THEN
647 CALL clascl(
'G', 0, 0, anrm, smlnum, n, nrhs, b, ldb,
648 $ info )
649 CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
650 $ info )
651 ELSE IF( iascl.EQ.2 ) THEN
652 CALL clascl(
'G', 0, 0, anrm, bignum, n, nrhs, b, ldb,
653 $ info )
654 CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
655 $ info )
656 END IF
657 IF( ibscl.EQ.1 ) THEN
658 CALL clascl(
'G', 0, 0, smlnum, bnrm, n, nrhs, b, ldb,
659 $ info )
660 ELSE IF( ibscl.EQ.2 ) THEN
661 CALL clascl(
'G', 0, 0, bignum, bnrm, n, nrhs, b, ldb,
662 $ info )
663 END IF
664
665 10 CONTINUE
667 iwork( 1 ) = liwork
668 rwork( 1 ) = real( lrwork )
669 RETURN
670
671
672
subroutine xerbla(srname, info)
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 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.
subroutine clalsd(uplo, smlsiz, n, nrhs, d, e, b, ldb, rcond, rank, work, rwork, iwork, info)
CLALSD uses the singular value decomposition of A to solve the least squares problem.
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 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