261
262
263
264
265
266
267 CHARACTER JOBU, JOBVT, RANGE
268 INTEGER IL, INFO, IU, LDA, LDU, LDVT, LWORK, M, N, NS
269 REAL VL, VU
270
271
272 INTEGER IWORK( * )
273 REAL A( LDA, * ), S( * ), U( LDU, * ),
274 $ VT( LDVT, * ), WORK( * )
275
276
277
278
279
280 REAL ZERO, ONE
281 parameter( zero = 0.0e0, one = 1.0e0 )
282
283
284 CHARACTER JOBZ, RNGTGK
285 LOGICAL ALLS, INDS, LQUERY, VALS, WANTU, WANTVT
286 INTEGER I, ID, IE, IERR, ILQF, ILTGK, IQRF, ISCL,
287 $ ITAU, ITAUP, ITAUQ, ITEMP, ITGKZ, IUTGK,
288 $ J, MAXWRK, MINMN, MINWRK, MNTHR
289 REAL ABSTOL, ANRM, BIGNUM, EPS, SMLNUM
290
291
292 REAL DUM( 1 )
293
294
299
300
301 LOGICAL LSAME
302 INTEGER ILAENV
303 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
306
307
308 INTRINSIC max, min, sqrt
309
310
311
312
313
314 ns = 0
315 info = 0
317 lquery = ( lwork.EQ.-1 )
318 minmn = min( m, n )
319
320 wantu =
lsame( jobu,
'V' )
321 wantvt =
lsame( jobvt,
'V' )
322 IF( wantu .OR. wantvt ) THEN
323 jobz = 'V'
324 ELSE
325 jobz = 'N'
326 END IF
327 alls =
lsame( range,
'A' )
328 vals =
lsame( range,
'V' )
329 inds =
lsame( range,
'I' )
330
331 info = 0
332 IF( .NOT.
lsame( jobu,
'V' ) .AND.
333 $ .NOT.
lsame( jobu,
'N' ) )
THEN
334 info = -1
335 ELSE IF( .NOT.
lsame( jobvt,
'V' ) .AND.
336 $ .NOT.
lsame( jobvt,
'N' ) )
THEN
337 info = -2
338 ELSE IF( .NOT.( alls .OR. vals .OR. inds ) ) THEN
339 info = -3
340 ELSE IF( m.LT.0 ) THEN
341 info = -4
342 ELSE IF( n.LT.0 ) THEN
343 info = -5
344 ELSE IF( m.GT.lda ) THEN
345 info = -7
346 ELSE IF( minmn.GT.0 ) THEN
347 IF( vals ) THEN
348 IF( vl.LT.zero ) THEN
349 info = -8
350 ELSE IF( vu.LE.vl ) THEN
351 info = -9
352 END IF
353 ELSE IF( inds ) THEN
354 IF( il.LT.1 .OR. il.GT.max( 1, minmn ) ) THEN
355 info = -10
356 ELSE IF( iu.LT.min( minmn, il ) .OR. iu.GT.minmn ) THEN
357 info = -11
358 END IF
359 END IF
360 IF( info.EQ.0 ) THEN
361 IF( wantu .AND. ldu.LT.m ) THEN
362 info = -15
363 ELSE IF( wantvt ) THEN
364 IF( inds ) THEN
365 IF( ldvt.LT.iu-il+1 ) THEN
366 info = -17
367 END IF
368 ELSE IF( ldvt.LT.minmn ) THEN
369 info = -17
370 END IF
371 END IF
372 END IF
373 END IF
374
375
376
377
378
379
380
381
382 IF( info.EQ.0 ) THEN
383 minwrk = 1
384 maxwrk = 1
385 IF( minmn.GT.0 ) THEN
386 IF( m.GE.n ) THEN
387 mnthr =
ilaenv( 6,
'SGESVD', jobu // jobvt, m, n, 0,
388 $ 0 )
389 IF( m.GE.mnthr ) THEN
390
391
392
393 maxwrk = n +
394 $ n*
ilaenv( 1,
'SGEQRF',
' ', m, n, -1, -1 )
395 maxwrk = max( maxwrk, n*(n+5) + 2*n*
396 $
ilaenv( 1,
'SGEBRD',
' ', n, n, -1, -1 ) )
397 IF (wantu) THEN
398 maxwrk = max(maxwrk,n*(n*3+6)+n*
399 $
ilaenv( 1,
'SORMQR',
' ', n, n, -1, -1 ) )
400 END IF
401 IF (wantvt) THEN
402 maxwrk = max(maxwrk,n*(n*3+6)+n*
403 $
ilaenv( 1,
'SORMLQ',
' ', n, n, -1, -1 ) )
404 END IF
405 minwrk = n*(n*3+20)
406 ELSE
407
408
409
410 maxwrk = 4*n + ( m+n )*
411 $
ilaenv( 1,
'SGEBRD',
' ', m, n, -1, -1 )
412 IF (wantu) THEN
413 maxwrk = max(maxwrk,n*(n*2+5)+n*
414 $
ilaenv( 1,
'SORMQR',
' ', n, n, -1, -1 ) )
415 END IF
416 IF (wantvt) THEN
417 maxwrk = max(maxwrk,n*(n*2+5)+n*
418 $
ilaenv( 1,
'SORMLQ',
' ', n, n, -1, -1 ) )
419 END IF
420 minwrk = max(n*(n*2+19),4*n+m)
421 END IF
422 ELSE
423 mnthr =
ilaenv( 6,
'SGESVD', jobu // jobvt, m, n, 0,
424 $ 0 )
425 IF( n.GE.mnthr ) THEN
426
427
428
429 maxwrk = m +
430 $ m*
ilaenv( 1,
'SGELQF',
' ', m, n, -1, -1 )
431 maxwrk = max( maxwrk, m*(m+5) + 2*m*
432 $
ilaenv( 1,
'SGEBRD',
' ', m, m, -1, -1 ) )
433 IF (wantu) THEN
434 maxwrk = max(maxwrk,m*(m*3+6)+m*
435 $
ilaenv( 1,
'SORMQR',
' ', m, m, -1, -1 ) )
436 END IF
437 IF (wantvt) THEN
438 maxwrk = max(maxwrk,m*(m*3+6)+m*
439 $
ilaenv( 1,
'SORMLQ',
' ', m, m, -1, -1 ) )
440 END IF
441 minwrk = m*(m*3+20)
442 ELSE
443
444
445
446 maxwrk = 4*m + ( m+n )*
447 $
ilaenv( 1,
'SGEBRD',
' ', m, n, -1, -1 )
448 IF (wantu) THEN
449 maxwrk = max(maxwrk,m*(m*2+5)+m*
450 $
ilaenv( 1,
'SORMQR',
' ', m, m, -1, -1 ) )
451 END IF
452 IF (wantvt) THEN
453 maxwrk = max(maxwrk,m*(m*2+5)+m*
454 $
ilaenv( 1,
'SORMLQ',
' ', m, m, -1, -1 ) )
455 END IF
456 minwrk = max(m*(m*2+19),4*m+n)
457 END IF
458 END IF
459 END IF
460 maxwrk = max( maxwrk, minwrk )
462
463 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
464 info = -19
465 END IF
466 END IF
467
468 IF( info.NE.0 ) THEN
469 CALL xerbla(
'SGESVDX', -info )
470 RETURN
471 ELSE IF( lquery ) THEN
472 RETURN
473 END IF
474
475
476
477 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
478 RETURN
479 END IF
480
481
482
483 IF( alls ) THEN
484 rngtgk = 'I'
485 iltgk = 1
486 iutgk = min( m, n )
487 ELSE IF( inds ) THEN
488 rngtgk = 'I'
489 iltgk = il
490 iutgk = iu
491 ELSE
492 rngtgk = 'V'
493 iltgk = 0
494 iutgk = 0
495 END IF
496
497
498
500 smlnum = sqrt(
slamch(
'S' ) ) / eps
501 bignum = one / smlnum
502
503
504
505 anrm =
slange(
'M', m, n, a, lda, dum )
506 iscl = 0
507 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
508 iscl = 1
509 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, info )
510 ELSE IF( anrm.GT.bignum ) THEN
511 iscl = 1
512 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, info )
513 END IF
514
515 IF( m.GE.n ) THEN
516
517
518
519
520
521 IF( m.GE.mnthr ) THEN
522
523
524
525
526
527
528
529
530
531 itau = 1
532 itemp = itau + n
533 CALL sgeqrf( m, n, a, lda, work( itau ), work( itemp ),
534 $ lwork-itemp+1, info )
535
536
537
538
539 iqrf = itemp
540 id = iqrf + n*n
541 ie = id + n
542 itauq = ie + n
543 itaup = itauq + n
544 itemp = itaup + n
545 CALL slacpy(
'U', n, n, a, lda, work( iqrf ), n )
546 CALL slaset(
'L', n-1, n-1, zero, zero, work( iqrf+1 ),
547 $ n )
548 CALL sgebrd( n, n, work( iqrf ), n, work( id ),
549 $ work( ie ),
550 $ work( itauq ), work( itaup ), work( itemp ),
551 $ lwork-itemp+1, info )
552
553
554
555
556 itgkz = itemp
557 itemp = itgkz + n*(n*2+1)
558 CALL sbdsvdx(
'U', jobz, rngtgk, n, work( id ),
559 $ work( ie ),
560 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
561 $ n*2, work( itemp ), iwork, info)
562
563
564
565 IF( wantu ) THEN
566 j = itgkz
567 DO i = 1, ns
568 CALL scopy( n, work( j ), 1, u( 1,i ), 1 )
569 j = j + n*2
570 END DO
571 CALL slaset(
'A', m-n, ns, zero, zero, u( n+1,1 ),
572 $ ldu )
573
574
575
576
577 CALL sormbr(
'Q',
'L',
'N', n, ns, n, work( iqrf ), n,
578 $ work( itauq ), u, ldu, work( itemp ),
579 $ lwork-itemp+1, info )
580
581
582
583
584 CALL sormqr(
'L',
'N', m, ns, n, a, lda,
585 $ work( itau ), u, ldu, work( itemp ),
586 $ lwork-itemp+1, info )
587 END IF
588
589
590
591 IF( wantvt) THEN
592 j = itgkz + n
593 DO i = 1, ns
594 CALL scopy( n, work( j ), 1, vt( i,1 ), ldvt )
595 j = j + n*2
596 END DO
597
598
599
600
601 CALL sormbr(
'P',
'R',
'T', ns, n, n, work( iqrf ), n,
602 $ work( itaup ), vt, ldvt, work( itemp ),
603 $ lwork-itemp+1, info )
604 END IF
605 ELSE
606
607
608
609
610
611
612
613
614
615 id = 1
616 ie = id + n
617 itauq = ie + n
618 itaup = itauq + n
619 itemp = itaup + n
620 CALL sgebrd( m, n, a, lda, work( id ), work( ie ),
621 $ work( itauq ), work( itaup ), work( itemp ),
622 $ lwork-itemp+1, info )
623
624
625
626
627 itgkz = itemp
628 itemp = itgkz + n*(n*2+1)
629 CALL sbdsvdx(
'U', jobz, rngtgk, n, work( id ),
630 $ work( ie ),
631 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
632 $ n*2, work( itemp ), iwork, info)
633
634
635
636 IF( wantu ) THEN
637 j = itgkz
638 DO i = 1, ns
639 CALL scopy( n, work( j ), 1, u( 1,i ), 1 )
640 j = j + n*2
641 END DO
642 CALL slaset(
'A', m-n, ns, zero, zero, u( n+1,1 ),
643 $ ldu )
644
645
646
647
648 CALL sormbr(
'Q',
'L',
'N', m, ns, n, a, lda,
649 $ work( itauq ), u, ldu, work( itemp ),
650 $ lwork-itemp+1, ierr )
651 END IF
652
653
654
655 IF( wantvt) THEN
656 j = itgkz + n
657 DO i = 1, ns
658 CALL scopy( n, work( j ), 1, vt( i,1 ), ldvt )
659 j = j + n*2
660 END DO
661
662
663
664
665 CALL sormbr(
'P',
'R',
'T', ns, n, n, a, lda,
666 $ work( itaup ), vt, ldvt, work( itemp ),
667 $ lwork-itemp+1, ierr )
668 END IF
669 END IF
670 ELSE
671
672
673
674
675 IF( n.GE.mnthr ) THEN
676
677
678
679
680
681
682
683
684
685 itau = 1
686 itemp = itau + m
687 CALL sgelqf( m, n, a, lda, work( itau ), work( itemp ),
688 $ lwork-itemp+1, info )
689
690
691
692
693 ilqf = itemp
694 id = ilqf + m*m
695 ie = id + m
696 itauq = ie + m
697 itaup = itauq + m
698 itemp = itaup + m
699 CALL slacpy(
'L', m, m, a, lda, work( ilqf ), m )
700 CALL slaset(
'U', m-1, m-1, zero, zero, work( ilqf+m ),
701 $ m )
702 CALL sgebrd( m, m, work( ilqf ), m, work( id ),
703 $ work( ie ),
704 $ work( itauq ), work( itaup ), work( itemp ),
705 $ lwork-itemp+1, info )
706
707
708
709
710 itgkz = itemp
711 itemp = itgkz + m*(m*2+1)
712 CALL sbdsvdx(
'U', jobz, rngtgk, m, work( id ),
713 $ work( ie ),
714 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
715 $ m*2, work( itemp ), iwork, info)
716
717
718
719 IF( wantu ) THEN
720 j = itgkz
721 DO i = 1, ns
722 CALL scopy( m, work( j ), 1, u( 1,i ), 1 )
723 j = j + m*2
724 END DO
725
726
727
728
729 CALL sormbr(
'Q',
'L',
'N', m, ns, m, work( ilqf ), m,
730 $ work( itauq ), u, ldu, work( itemp ),
731 $ lwork-itemp+1, info )
732 END IF
733
734
735
736 IF( wantvt) THEN
737 j = itgkz + m
738 DO i = 1, ns
739 CALL scopy( m, work( j ), 1, vt( i,1 ), ldvt )
740 j = j + m*2
741 END DO
742 CALL slaset(
'A', ns, n-m, zero, zero, vt( 1,m+1 ),
743 $ ldvt)
744
745
746
747
748 CALL sormbr(
'P',
'R',
'T', ns, m, m, work( ilqf ), m,
749 $ work( itaup ), vt, ldvt, work( itemp ),
750 $ lwork-itemp+1, info )
751
752
753
754
755 CALL sormlq(
'R',
'N', ns, n, m, a, lda,
756 $ work( itau ), vt, ldvt, work( itemp ),
757 $ lwork-itemp+1, info )
758 END IF
759 ELSE
760
761
762
763
764
765
766
767
768
769 id = 1
770 ie = id + m
771 itauq = ie + m
772 itaup = itauq + m
773 itemp = itaup + m
774 CALL sgebrd( m, n, a, lda, work( id ), work( ie ),
775 $ work( itauq ), work( itaup ), work( itemp ),
776 $ lwork-itemp+1, info )
777
778
779
780
781 itgkz = itemp
782 itemp = itgkz + m*(m*2+1)
783 CALL sbdsvdx(
'L', jobz, rngtgk, m, work( id ),
784 $ work( ie ),
785 $ vl, vu, iltgk, iutgk, ns, s, work( itgkz ),
786 $ m*2, work( itemp ), iwork, info)
787
788
789
790 IF( wantu ) THEN
791 j = itgkz
792 DO i = 1, ns
793 CALL scopy( m, work( j ), 1, u( 1,i ), 1 )
794 j = j + m*2
795 END DO
796
797
798
799
800 CALL sormbr(
'Q',
'L',
'N', m, ns, n, a, lda,
801 $ work( itauq ), u, ldu, work( itemp ),
802 $ lwork-itemp+1, info )
803 END IF
804
805
806
807 IF( wantvt) THEN
808 j = itgkz + m
809 DO i = 1, ns
810 CALL scopy( m, work( j ), 1, vt( i,1 ), ldvt )
811 j = j + m*2
812 END DO
813 CALL slaset(
'A', ns, n-m, zero, zero, vt( 1,m+1 ),
814 $ ldvt)
815
816
817
818
819 CALL sormbr(
'P',
'R',
'T', ns, n, m, a, lda,
820 $ work( itaup ), vt, ldvt, work( itemp ),
821 $ lwork-itemp+1, info )
822 END IF
823 END IF
824 END IF
825
826
827
828 IF( iscl.EQ.1 ) THEN
829 IF( anrm.GT.bignum )
830 $
CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1,
831 $ s, minmn, info )
832 IF( anrm.LT.smlnum )
833 $
CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1,
834 $ s, minmn, info )
835 END IF
836
837
838
840
841 RETURN
842
843
844
subroutine xerbla(srname, info)
subroutine sbdsvdx(uplo, jobz, range, n, d, e, vl, vu, il, iu, ns, s, z, ldz, work, iwork, info)
SBDSVDX
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
subroutine sgebrd(m, n, a, lda, d, e, tauq, taup, work, lwork, info)
SGEBRD
subroutine sgelqf(m, n, a, lda, tau, work, lwork, info)
SGELQF
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
subroutine slacpy(uplo, m, n, a, lda, b, ldb)
SLACPY copies all or part of one two-dimensional array to another.
real function slamch(cmach)
SLAMCH
real function slange(norm, m, n, a, lda, work)
SLANGE returns the value of the 1-norm, Frobenius norm, infinity-norm, or the largest absolute value ...
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.
logical function lsame(ca, cb)
LSAME
real function sroundup_lwork(lwork)
SROUNDUP_LWORK
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR
subroutine sormlq(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMLQ
subroutine sormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMQR