213 implicit none
214
215
216
217
218
219
220 CHARACTER JOBZ
221 INTEGER INFO, LDA, LDU, LDVT, LWORK, M, N
222
223
224 INTEGER IWORK( * )
225 REAL A( LDA, * ), S( * ), U( LDU, * ),
226 $ VT( LDVT, * ), WORK( * )
227
228
229
230
231
232 REAL ZERO, ONE
233 parameter( zero = 0.0e0, one = 1.0e0 )
234
235
236 LOGICAL LQUERY, WNTQA, WNTQAS, WNTQN, WNTQO, WNTQS
237 INTEGER BDSPAC, BLK, CHUNK, I, IE, IERR, IL,
238 $ IR, ISCL, ITAU, ITAUP, ITAUQ, IU, IVT, LDWKVT,
239 $ LDWRKL, LDWRKR, LDWRKU, MAXWRK, MINMN, MINWRK,
240 $ MNTHR, NWORK, WRKBL
241 INTEGER LWORK_SGEBRD_MN, LWORK_SGEBRD_MM,
242 $ LWORK_SGEBRD_NN, LWORK_SGELQF_MN,
243 $ LWORK_SGEQRF_MN,
244 $ LWORK_SORGBR_P_MM, LWORK_SORGBR_Q_NN,
245 $ LWORK_SORGLQ_MN, LWORK_SORGLQ_NN,
246 $ LWORK_SORGQR_MM, LWORK_SORGQR_MN,
247 $ LWORK_SORMBR_PRT_MM, LWORK_SORMBR_QLN_MM,
248 $ LWORK_SORMBR_PRT_MN, LWORK_SORMBR_QLN_MN,
249 $ LWORK_SORMBR_PRT_NN, LWORK_SORMBR_QLN_NN
250 REAL ANRM, BIGNUM, EPS, SMLNUM
251
252
253 INTEGER IDUM( 1 )
254 REAL DUM( 1 )
255
256
260
261
262 LOGICAL LSAME, SISNAN
263 REAL SLAMCH, SLANGE, SROUNDUP_LWORK
266
267
268 INTRINSIC int, max, min, sqrt
269
270
271
272
273
274 info = 0
275 minmn = min( m, n )
276 wntqa =
lsame( jobz,
'A' )
277 wntqs =
lsame( jobz,
'S' )
278 wntqas = wntqa .OR. wntqs
279 wntqo =
lsame( jobz,
'O' )
280 wntqn =
lsame( jobz,
'N' )
281 lquery = ( lwork.EQ.-1 )
282
283 IF( .NOT.( wntqa .OR. wntqs .OR. wntqo .OR. wntqn ) ) THEN
284 info = -1
285 ELSE IF( m.LT.0 ) THEN
286 info = -2
287 ELSE IF( n.LT.0 ) THEN
288 info = -3
289 ELSE IF( lda.LT.max( 1, m ) ) THEN
290 info = -5
291 ELSE IF( ldu.LT.1 .OR. ( wntqas .AND. ldu.LT.m ) .OR.
292 $ ( wntqo .AND. m.LT.n .AND. ldu.LT.m ) ) THEN
293 info = -8
294 ELSE IF( ldvt.LT.1 .OR. ( wntqa .AND. ldvt.LT.n ) .OR.
295 $ ( wntqs .AND. ldvt.LT.minmn ) .OR.
296 $ ( wntqo .AND. m.GE.n .AND. ldvt.LT.n ) ) THEN
297 info = -10
298 END IF
299
300
301
302
303
304
305
306
307 IF( info.EQ.0 ) THEN
308 minwrk = 1
309 maxwrk = 1
310 bdspac = 0
311 mnthr = int( minmn*11.0e0 / 6.0e0 )
312 IF( m.GE.n .AND. minmn.GT.0 ) THEN
313
314
315
316 IF( wntqn ) THEN
317
318
319 bdspac = 7*n
320 ELSE
321 bdspac = 3*n*n + 4*n
322 END IF
323
324
325 CALL sgebrd( m, n, dum(1), m, dum(1), dum(1), dum(1),
326 $ dum(1), dum(1), -1, ierr )
327 lwork_sgebrd_mn = int( dum(1) )
328
329 CALL sgebrd( n, n, dum(1), n, dum(1), dum(1), dum(1),
330 $ dum(1), dum(1), -1, ierr )
331 lwork_sgebrd_nn = int( dum(1) )
332
333 CALL sgeqrf( m, n, dum(1), m, dum(1), dum(1), -1, ierr )
334 lwork_sgeqrf_mn = int( dum(1) )
335
336 CALL sorgbr(
'Q', n, n, n, dum(1), n, dum(1), dum(1), -1,
337 $ ierr )
338 lwork_sorgbr_q_nn = int( dum(1) )
339
340 CALL sorgqr( m, m, n, dum(1), m, dum(1), dum(1), -1, ierr )
341 lwork_sorgqr_mm = int( dum(1) )
342
343 CALL sorgqr( m, n, n, dum(1), m, dum(1), dum(1), -1, ierr )
344 lwork_sorgqr_mn = int( dum(1) )
345
346 CALL sormbr(
'P',
'R',
'T', n, n, n, dum(1), n,
347 $ dum(1), dum(1), n, dum(1), -1, ierr )
348 lwork_sormbr_prt_nn = int( dum(1) )
349
350 CALL sormbr(
'Q',
'L',
'N', n, n, n, dum(1), n,
351 $ dum(1), dum(1), n, dum(1), -1, ierr )
352 lwork_sormbr_qln_nn = int( dum(1) )
353
354 CALL sormbr(
'Q',
'L',
'N', m, n, n, dum(1), m,
355 $ dum(1), dum(1), m, dum(1), -1, ierr )
356 lwork_sormbr_qln_mn = int( dum(1) )
357
358 CALL sormbr(
'Q',
'L',
'N', m, m, n, dum(1), m,
359 $ dum(1), dum(1), m, dum(1), -1, ierr )
360 lwork_sormbr_qln_mm = int( dum(1) )
361
362 IF( m.GE.mnthr ) THEN
363 IF( wntqn ) THEN
364
365
366
367 wrkbl = n + lwork_sgeqrf_mn
368 wrkbl = max( wrkbl, 3*n + lwork_sgebrd_nn )
369 maxwrk = max( wrkbl, bdspac + n )
370 minwrk = bdspac + n
371 ELSE IF( wntqo ) THEN
372
373
374
375 wrkbl = n + lwork_sgeqrf_mn
376 wrkbl = max( wrkbl, n + lwork_sorgqr_mn )
377 wrkbl = max( wrkbl, 3*n + lwork_sgebrd_nn )
378 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_nn )
379 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
380 wrkbl = max( wrkbl, 3*n + bdspac )
381 maxwrk = wrkbl + 2*n*n
382 minwrk = bdspac + 2*n*n + 3*n
383 ELSE IF( wntqs ) THEN
384
385
386
387 wrkbl = n + lwork_sgeqrf_mn
388 wrkbl = max( wrkbl, n + lwork_sorgqr_mn )
389 wrkbl = max( wrkbl, 3*n + lwork_sgebrd_nn )
390 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_nn )
391 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
392 wrkbl = max( wrkbl, 3*n + bdspac )
393 maxwrk = wrkbl + n*n
394 minwrk = bdspac + n*n + 3*n
395 ELSE IF( wntqa ) THEN
396
397
398
399 wrkbl = n + lwork_sgeqrf_mn
400 wrkbl = max( wrkbl, n + lwork_sorgqr_mm )
401 wrkbl = max( wrkbl, 3*n + lwork_sgebrd_nn )
402 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_nn )
403 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
404 wrkbl = max( wrkbl, 3*n + bdspac )
405 maxwrk = wrkbl + n*n
406 minwrk = n*n + max( 3*n + bdspac, n + m )
407 END IF
408 ELSE
409
410
411
412 wrkbl = 3*n + lwork_sgebrd_mn
413 IF( wntqn ) THEN
414
415 maxwrk = max( wrkbl, 3*n + bdspac )
416 minwrk = 3*n + max( m, bdspac )
417 ELSE IF( wntqo ) THEN
418
419 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
420 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_mn )
421 wrkbl = max( wrkbl, 3*n + bdspac )
422 maxwrk = wrkbl + m*n
423 minwrk = 3*n + max( m, n*n + bdspac )
424 ELSE IF( wntqs ) THEN
425
426 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_mn )
427 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
428 maxwrk = max( wrkbl, 3*n + bdspac )
429 minwrk = 3*n + max( m, bdspac )
430 ELSE IF( wntqa ) THEN
431
432 wrkbl = max( wrkbl, 3*n + lwork_sormbr_qln_mm )
433 wrkbl = max( wrkbl, 3*n + lwork_sormbr_prt_nn )
434 maxwrk = max( wrkbl, 3*n + bdspac )
435 minwrk = 3*n + max( m, bdspac )
436 END IF
437 END IF
438 ELSE IF( minmn.GT.0 ) THEN
439
440
441
442 IF( wntqn ) THEN
443
444
445 bdspac = 7*m
446 ELSE
447 bdspac = 3*m*m + 4*m
448 END IF
449
450
451 CALL sgebrd( m, n, dum(1), m, dum(1), dum(1), dum(1),
452 $ dum(1), dum(1), -1, ierr )
453 lwork_sgebrd_mn = int( dum(1) )
454
455 CALL sgebrd( m, m, a, m, s, dum(1), dum(1),
456 $ dum(1), dum(1), -1, ierr )
457 lwork_sgebrd_mm = int( dum(1) )
458
459 CALL sgelqf( m, n, a, m, dum(1), dum(1), -1, ierr )
460 lwork_sgelqf_mn = int( dum(1) )
461
462 CALL sorglq( n, n, m, dum(1), n, dum(1), dum(1), -1, ierr )
463 lwork_sorglq_nn = int( dum(1) )
464
465 CALL sorglq( m, n, m, a, m, dum(1), dum(1), -1, ierr )
466 lwork_sorglq_mn = int( dum(1) )
467
468 CALL sorgbr(
'P', m, m, m, a, n, dum(1), dum(1), -1, ierr )
469 lwork_sorgbr_p_mm = int( dum(1) )
470
471 CALL sormbr(
'P',
'R',
'T', m, m, m, dum(1), m,
472 $ dum(1), dum(1), m, dum(1), -1, ierr )
473 lwork_sormbr_prt_mm = int( dum(1) )
474
475 CALL sormbr(
'P',
'R',
'T', m, n, m, dum(1), m,
476 $ dum(1), dum(1), m, dum(1), -1, ierr )
477 lwork_sormbr_prt_mn = int( dum(1) )
478
479 CALL sormbr(
'P',
'R',
'T', n, n, m, dum(1), n,
480 $ dum(1), dum(1), n, dum(1), -1, ierr )
481 lwork_sormbr_prt_nn = int( dum(1) )
482
483 CALL sormbr(
'Q',
'L',
'N', m, m, m, dum(1), m,
484 $ dum(1), dum(1), m, dum(1), -1, ierr )
485 lwork_sormbr_qln_mm = int( dum(1) )
486
487 IF( n.GE.mnthr ) THEN
488 IF( wntqn ) THEN
489
490
491
492 wrkbl = m + lwork_sgelqf_mn
493 wrkbl = max( wrkbl, 3*m + lwork_sgebrd_mm )
494 maxwrk = max( wrkbl, bdspac + m )
495 minwrk = bdspac + m
496 ELSE IF( wntqo ) THEN
497
498
499
500 wrkbl = m + lwork_sgelqf_mn
501 wrkbl = max( wrkbl, m + lwork_sorglq_mn )
502 wrkbl = max( wrkbl, 3*m + lwork_sgebrd_mm )
503 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
504 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_mm )
505 wrkbl = max( wrkbl, 3*m + bdspac )
506 maxwrk = wrkbl + 2*m*m
507 minwrk = bdspac + 2*m*m + 3*m
508 ELSE IF( wntqs ) THEN
509
510
511
512 wrkbl = m + lwork_sgelqf_mn
513 wrkbl = max( wrkbl, m + lwork_sorglq_mn )
514 wrkbl = max( wrkbl, 3*m + lwork_sgebrd_mm )
515 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
516 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_mm )
517 wrkbl = max( wrkbl, 3*m + bdspac )
518 maxwrk = wrkbl + m*m
519 minwrk = bdspac + m*m + 3*m
520 ELSE IF( wntqa ) THEN
521
522
523
524 wrkbl = m + lwork_sgelqf_mn
525 wrkbl = max( wrkbl, m + lwork_sorglq_nn )
526 wrkbl = max( wrkbl, 3*m + lwork_sgebrd_mm )
527 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
528 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_mm )
529 wrkbl = max( wrkbl, 3*m + bdspac )
530 maxwrk = wrkbl + m*m
531 minwrk = m*m + max( 3*m + bdspac, m + n )
532 END IF
533 ELSE
534
535
536
537 wrkbl = 3*m + lwork_sgebrd_mn
538 IF( wntqn ) THEN
539
540 maxwrk = max( wrkbl, 3*m + bdspac )
541 minwrk = 3*m + max( n, bdspac )
542 ELSE IF( wntqo ) THEN
543
544 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
545 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_mn )
546 wrkbl = max( wrkbl, 3*m + bdspac )
547 maxwrk = wrkbl + m*n
548 minwrk = 3*m + max( n, m*m + bdspac )
549 ELSE IF( wntqs ) THEN
550
551 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
552 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_mn )
553 maxwrk = max( wrkbl, 3*m + bdspac )
554 minwrk = 3*m + max( n, bdspac )
555 ELSE IF( wntqa ) THEN
556
557 wrkbl = max( wrkbl, 3*m + lwork_sormbr_qln_mm )
558 wrkbl = max( wrkbl, 3*m + lwork_sormbr_prt_nn )
559 maxwrk = max( wrkbl, 3*m + bdspac )
560 minwrk = 3*m + max( n, bdspac )
561 END IF
562 END IF
563 END IF
564
565 maxwrk = max( maxwrk, minwrk )
567
568 IF( lwork.LT.minwrk .AND. .NOT.lquery ) THEN
569 info = -12
570 END IF
571 END IF
572
573 IF( info.NE.0 ) THEN
574 CALL xerbla(
'SGESDD', -info )
575 RETURN
576 ELSE IF( lquery ) THEN
577 RETURN
578 END IF
579
580
581
582 IF( m.EQ.0 .OR. n.EQ.0 ) THEN
583 RETURN
584 END IF
585
586
587
589 smlnum = sqrt(
slamch(
'S' ) ) / eps
590 bignum = one / smlnum
591
592
593
594 anrm =
slange(
'M', m, n, a, lda, dum )
596 info = -4
597 RETURN
598 END IF
599 iscl = 0
600 IF( anrm.GT.zero .AND. anrm.LT.smlnum ) THEN
601 iscl = 1
602 CALL slascl(
'G', 0, 0, anrm, smlnum, m, n, a, lda, ierr )
603 ELSE IF( anrm.GT.bignum ) THEN
604 iscl = 1
605 CALL slascl(
'G', 0, 0, anrm, bignum, m, n, a, lda, ierr )
606 END IF
607
608 IF( m.GE.n ) THEN
609
610
611
612
613
614 IF( m.GE.mnthr ) THEN
615
616 IF( wntqn ) THEN
617
618
619
620
621 itau = 1
622 nwork = itau + n
623
624
625
626
627
628 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
629 $ lwork - nwork + 1, ierr )
630
631
632
633 CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
634 ie = 1
635 itauq = ie + n
636 itaup = itauq + n
637 nwork = itaup + n
638
639
640
641
642
643 CALL sgebrd( n, n, a, lda, s, work( ie ), work( itauq ),
644 $ work( itaup ), work( nwork ), lwork-nwork+1,
645 $ ierr )
646 nwork = ie + n
647
648
649
650
651 CALL sbdsdc(
'U',
'N', n, s, work( ie ), dum, 1, dum, 1,
652 $ dum, idum, work( nwork ), iwork, info )
653
654 ELSE IF( wntqo ) THEN
655
656
657
658
659
660 ir = 1
661
662
663
664 IF( lwork .GE. lda*n + n*n + 3*n + bdspac ) THEN
665 ldwrkr = lda
666 ELSE
667 ldwrkr = ( lwork - n*n - 3*n - bdspac ) / n
668 END IF
669 itau = ir + ldwrkr*n
670 nwork = itau + n
671
672
673
674
675
676 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
677 $ lwork - nwork + 1, ierr )
678
679
680
681 CALL slacpy(
'U', n, n, a, lda, work( ir ), ldwrkr )
682 CALL slaset(
'L', n - 1, n - 1, zero, zero, work(ir+1),
683 $ ldwrkr )
684
685
686
687
688
689 CALL sorgqr( m, n, n, a, lda, work( itau ),
690 $ work( nwork ), lwork - nwork + 1, ierr )
691 ie = itau
692 itauq = ie + n
693 itaup = itauq + n
694 nwork = itaup + n
695
696
697
698
699
700 CALL sgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),
701 $ work( itauq ), work( itaup ), work( nwork ),
702 $ lwork - nwork + 1, ierr )
703
704
705
706 iu = nwork
707 nwork = iu + n*n
708
709
710
711
712
713
714 CALL sbdsdc(
'U',
'I', n, s, work( ie ), work( iu ), n,
715 $ vt, ldvt, dum, idum, work( nwork ), iwork,
716 $ info )
717
718
719
720
721
722
723 CALL sormbr(
'Q',
'L',
'N', n, n, n, work( ir ), ldwrkr,
724 $ work( itauq ), work( iu ), n, work( nwork ),
725 $ lwork - nwork + 1, ierr )
726 CALL sormbr(
'P',
'R',
'T', n, n, n, work( ir ), ldwrkr,
727 $ work( itaup ), vt, ldvt, work( nwork ),
728 $ lwork - nwork + 1, ierr )
729
730
731
732
733
734
735 DO 10 i = 1, m, ldwrkr
736 chunk = min( m - i + 1, ldwrkr )
737 CALL sgemm(
'N',
'N', chunk, n, n, one, a( i, 1 ),
738 $ lda, work( iu ), n, zero, work( ir ),
739 $ ldwrkr )
740 CALL slacpy(
'F', chunk, n, work( ir ), ldwrkr,
741 $ a( i, 1 ), lda )
742 10 CONTINUE
743
744 ELSE IF( wntqs ) THEN
745
746
747
748
749
750 ir = 1
751
752
753
754 ldwrkr = n
755 itau = ir + ldwrkr*n
756 nwork = itau + n
757
758
759
760
761
762 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
763 $ lwork - nwork + 1, ierr )
764
765
766
767 CALL slacpy(
'U', n, n, a, lda, work( ir ), ldwrkr )
768 CALL slaset(
'L', n - 1, n - 1, zero, zero, work(ir+1),
769 $ ldwrkr )
770
771
772
773
774
775 CALL sorgqr( m, n, n, a, lda, work( itau ),
776 $ work( nwork ), lwork - nwork + 1, ierr )
777 ie = itau
778 itauq = ie + n
779 itaup = itauq + n
780 nwork = itaup + n
781
782
783
784
785
786 CALL sgebrd( n, n, work( ir ), ldwrkr, s, work( ie ),
787 $ work( itauq ), work( itaup ), work( nwork ),
788 $ lwork - nwork + 1, ierr )
789
790
791
792
793
794
795 CALL sbdsdc(
'U',
'I', n, s, work( ie ), u, ldu, vt,
796 $ ldvt, dum, idum, work( nwork ), iwork,
797 $ info )
798
799
800
801
802
803
804 CALL sormbr(
'Q',
'L',
'N', n, n, n, work( ir ), ldwrkr,
805 $ work( itauq ), u, ldu, work( nwork ),
806 $ lwork - nwork + 1, ierr )
807
808 CALL sormbr(
'P',
'R',
'T', n, n, n, work( ir ), ldwrkr,
809 $ work( itaup ), vt, ldvt, work( nwork ),
810 $ lwork - nwork + 1, ierr )
811
812
813
814
815
816 CALL slacpy(
'F', n, n, u, ldu, work( ir ), ldwrkr )
817 CALL sgemm(
'N',
'N', m, n, n, one, a, lda, work( ir ),
818 $ ldwrkr, zero, u, ldu )
819
820 ELSE IF( wntqa ) THEN
821
822
823
824
825
826 iu = 1
827
828
829
830 ldwrku = n
831 itau = iu + ldwrku*n
832 nwork = itau + n
833
834
835
836
837
838 CALL sgeqrf( m, n, a, lda, work( itau ), work( nwork ),
839 $ lwork - nwork + 1, ierr )
840 CALL slacpy(
'L', m, n, a, lda, u, ldu )
841
842
843
844
845 CALL sorgqr( m, m, n, u, ldu, work( itau ),
846 $ work( nwork ), lwork - nwork + 1, ierr )
847
848
849
850 CALL slaset(
'L', n-1, n-1, zero, zero, a( 2, 1 ), lda )
851 ie = itau
852 itauq = ie + n
853 itaup = itauq + n
854 nwork = itaup + n
855
856
857
858
859
860 CALL sgebrd( n, n, a, lda, s, work( ie ), work( itauq ),
861 $ work( itaup ), work( nwork ), lwork-nwork+1,
862 $ ierr )
863
864
865
866
867
868
869 CALL sbdsdc(
'U',
'I', n, s, work( ie ), work( iu ), n,
870 $ vt, ldvt, dum, idum, work( nwork ), iwork,
871 $ info )
872
873
874
875
876
877
878 CALL sormbr(
'Q',
'L',
'N', n, n, n, a, lda,
879 $ work( itauq ), work( iu ), ldwrku,
880 $ work( nwork ), lwork - nwork + 1, ierr )
881 CALL sormbr(
'P',
'R',
'T', n, n, n, a, lda,
882 $ work( itaup ), vt, ldvt, work( nwork ),
883 $ lwork - nwork + 1, ierr )
884
885
886
887
888
889 CALL sgemm(
'N',
'N', m, n, n, one, u, ldu, work( iu ),
890 $ ldwrku, zero, a, lda )
891
892
893
894 CALL slacpy(
'F', m, n, a, lda, u, ldu )
895
896 END IF
897
898 ELSE
899
900
901
902
903
904
905 ie = 1
906 itauq = ie + n
907 itaup = itauq + n
908 nwork = itaup + n
909
910
911
912
913
914 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
915 $ work( itaup ), work( nwork ), lwork-nwork+1,
916 $ ierr )
917 IF( wntqn ) THEN
918
919
920
921
922
923 CALL sbdsdc(
'U',
'N', n, s, work( ie ), dum, 1, dum, 1,
924 $ dum, idum, work( nwork ), iwork, info )
925 ELSE IF( wntqo ) THEN
926
927 iu = nwork
928 IF( lwork .GE. m*n + 3*n + bdspac ) THEN
929
930
931
932 ldwrku = m
933 nwork = iu + ldwrku*n
934 CALL slaset(
'F', m, n, zero, zero, work( iu ),
935 $ ldwrku )
936
937 ir = -1
938 ELSE
939
940
941
942 ldwrku = n
943 nwork = iu + ldwrku*n
944
945
946
947 ir = nwork
948 ldwrkr = ( lwork - n*n - 3*n ) / n
949 END IF
950 nwork = iu + ldwrku*n
951
952
953
954
955
956
957 CALL sbdsdc(
'U',
'I', n, s, work( ie ), work( iu ),
958 $ ldwrku, vt, ldvt, dum, idum, work( nwork ),
959 $ iwork, info )
960
961
962
963
964
965 CALL sormbr(
'P',
'R',
'T', n, n, n, a, lda,
966 $ work( itaup ), vt, ldvt, work( nwork ),
967 $ lwork - nwork + 1, ierr )
968
969 IF( lwork .GE. m*n + 3*n + bdspac ) THEN
970
971
972
973
974
975
976 CALL sormbr(
'Q',
'L',
'N', m, n, n, a, lda,
977 $ work( itauq ), work( iu ), ldwrku,
978 $ work( nwork ), lwork - nwork + 1, ierr )
979
980
981
982 CALL slacpy(
'F', m, n, work( iu ), ldwrku, a, lda )
983 ELSE
984
985
986
987
988
989
990 CALL sorgbr(
'Q', m, n, n, a, lda, work( itauq ),
991 $ work( nwork ), lwork - nwork + 1, ierr )
992
993
994
995
996
997
998
999 DO 20 i = 1, m, ldwrkr
1000 chunk = min( m - i + 1, ldwrkr )
1001 CALL sgemm(
'N',
'N', chunk, n, n, one, a( i, 1 ),
1002 $ lda, work( iu ), ldwrku, zero,
1003 $ work( ir ), ldwrkr )
1004 CALL slacpy(
'F', chunk, n, work( ir ), ldwrkr,
1005 $ a( i, 1 ), lda )
1006 20 CONTINUE
1007 END IF
1008
1009 ELSE IF( wntqs ) THEN
1010
1011
1012
1013
1014
1015
1016
1017 CALL slaset(
'F', m, n, zero, zero, u, ldu )
1018 CALL sbdsdc(
'U',
'I', n, s, work( ie ), u, ldu, vt,
1019 $ ldvt, dum, idum, work( nwork ), iwork,
1020 $ info )
1021
1022
1023
1024
1025
1026
1027 CALL sormbr(
'Q',
'L',
'N', m, n, n, a, lda,
1028 $ work( itauq ), u, ldu, work( nwork ),
1029 $ lwork - nwork + 1, ierr )
1030 CALL sormbr(
'P',
'R',
'T', n, n, n, a, lda,
1031 $ work( itaup ), vt, ldvt, work( nwork ),
1032 $ lwork - nwork + 1, ierr )
1033 ELSE IF( wntqa ) THEN
1034
1035
1036
1037
1038
1039
1040
1041 CALL slaset(
'F', m, m, zero, zero, u, ldu )
1042 CALL sbdsdc(
'U',
'I', n, s, work( ie ), u, ldu, vt,
1043 $ ldvt, dum, idum, work( nwork ), iwork,
1044 $ info )
1045
1046
1047
1048 IF( m.GT.n ) THEN
1049 CALL slaset(
'F', m - n, m - n, zero, one, u(n+1,n+1),
1050 $ ldu )
1051 END IF
1052
1053
1054
1055
1056
1057
1058 CALL sormbr(
'Q',
'L',
'N', m, m, n, a, lda,
1059 $ work( itauq ), u, ldu, work( nwork ),
1060 $ lwork - nwork + 1, ierr )
1061 CALL sormbr(
'P',
'R',
'T', n, n, m, a, lda,
1062 $ work( itaup ), vt, ldvt, work( nwork ),
1063 $ lwork - nwork + 1, ierr )
1064 END IF
1065
1066 END IF
1067
1068 ELSE
1069
1070
1071
1072
1073
1074 IF( n.GE.mnthr ) THEN
1075
1076 IF( wntqn ) THEN
1077
1078
1079
1080
1081 itau = 1
1082 nwork = itau + m
1083
1084
1085
1086
1087
1088 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
1089 $ lwork - nwork + 1, ierr )
1090
1091
1092
1093 CALL slaset(
'U', m-1, m-1, zero, zero, a( 1, 2 ), lda )
1094 ie = 1
1095 itauq = ie + m
1096 itaup = itauq + m
1097 nwork = itaup + m
1098
1099
1100
1101
1102
1103 CALL sgebrd( m, m, a, lda, s, work( ie ), work( itauq ),
1104 $ work( itaup ), work( nwork ), lwork-nwork+1,
1105 $ ierr )
1106 nwork = ie + m
1107
1108
1109
1110
1111 CALL sbdsdc(
'U',
'N', m, s, work( ie ), dum, 1, dum, 1,
1112 $ dum, idum, work( nwork ), iwork, info )
1113
1114 ELSE IF( wntqo ) THEN
1115
1116
1117
1118
1119
1120 ivt = 1
1121
1122
1123
1124
1125 il = ivt + m*m
1126 IF( lwork .GE. m*n + m*m + 3*m + bdspac ) THEN
1127 ldwrkl = m
1128 chunk = n
1129 ELSE
1130 ldwrkl = m
1131 chunk = ( lwork - m*m ) / m
1132 END IF
1133 itau = il + ldwrkl*m
1134 nwork = itau + m
1135
1136
1137
1138
1139
1140 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
1141 $ lwork - nwork + 1, ierr )
1142
1143
1144
1145 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwrkl )
1146 CALL slaset(
'U', m - 1, m - 1, zero, zero,
1147 $ work( il + ldwrkl ), ldwrkl )
1148
1149
1150
1151
1152
1153 CALL sorglq( m, n, m, a, lda, work( itau ),
1154 $ work( nwork ), lwork - nwork + 1, ierr )
1155 ie = itau
1156 itauq = ie + m
1157 itaup = itauq + m
1158 nwork = itaup + m
1159
1160
1161
1162
1163
1164 CALL sgebrd( m, m, work( il ), ldwrkl, s, work( ie ),
1165 $ work( itauq ), work( itaup ), work( nwork ),
1166 $ lwork - nwork + 1, ierr )
1167
1168
1169
1170
1171
1172
1173 CALL sbdsdc(
'U',
'I', m, s, work( ie ), u, ldu,
1174 $ work( ivt ), m, dum, idum, work( nwork ),
1175 $ iwork, info )
1176
1177
1178
1179
1180
1181
1182 CALL sormbr(
'Q',
'L',
'N', m, m, m, work( il ), ldwrkl,
1183 $ work( itauq ), u, ldu, work( nwork ),
1184 $ lwork - nwork + 1, ierr )
1185 CALL sormbr(
'P',
'R',
'T', m, m, m, work( il ), ldwrkl,
1186 $ work( itaup ), work( ivt ), m,
1187 $ work( nwork ), lwork - nwork + 1, ierr )
1188
1189
1190
1191
1192
1193
1194
1195 DO 30 i = 1, n, chunk
1196 blk = min( n - i + 1, chunk )
1197 CALL sgemm(
'N',
'N', m, blk, m, one, work( ivt ), m,
1198 $ a( 1, i ), lda, zero, work( il ), ldwrkl )
1199 CALL slacpy(
'F', m, blk, work( il ), ldwrkl,
1200 $ a( 1, i ), lda )
1201 30 CONTINUE
1202
1203 ELSE IF( wntqs ) THEN
1204
1205
1206
1207
1208
1209 il = 1
1210
1211
1212
1213 ldwrkl = m
1214 itau = il + ldwrkl*m
1215 nwork = itau + m
1216
1217
1218
1219
1220
1221 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
1222 $ lwork - nwork + 1, ierr )
1223
1224
1225
1226 CALL slacpy(
'L', m, m, a, lda, work( il ), ldwrkl )
1227 CALL slaset(
'U', m - 1, m - 1, zero, zero,
1228 $ work( il + ldwrkl ), ldwrkl )
1229
1230
1231
1232
1233
1234 CALL sorglq( m, n, m, a, lda, work( itau ),
1235 $ work( nwork ), lwork - nwork + 1, ierr )
1236 ie = itau
1237 itauq = ie + m
1238 itaup = itauq + m
1239 nwork = itaup + m
1240
1241
1242
1243
1244
1245 CALL sgebrd( m, m, work( il ), ldwrkl, s, work( ie ),
1246 $ work( itauq ), work( itaup ), work( nwork ),
1247 $ lwork - nwork + 1, ierr )
1248
1249
1250
1251
1252
1253
1254 CALL sbdsdc(
'U',
'I', m, s, work( ie ), u, ldu, vt,
1255 $ ldvt, dum, idum, work( nwork ), iwork,
1256 $ info )
1257
1258
1259
1260
1261
1262
1263 CALL sormbr(
'Q',
'L',
'N', m, m, m, work( il ), ldwrkl,
1264 $ work( itauq ), u, ldu, work( nwork ),
1265 $ lwork - nwork + 1, ierr )
1266 CALL sormbr(
'P',
'R',
'T', m, m, m, work( il ), ldwrkl,
1267 $ work( itaup ), vt, ldvt, work( nwork ),
1268 $ lwork - nwork + 1, ierr )
1269
1270
1271
1272
1273
1274 CALL slacpy(
'F', m, m, vt, ldvt, work( il ), ldwrkl )
1275 CALL sgemm(
'N',
'N', m, n, m, one, work( il ), ldwrkl,
1276 $ a, lda, zero, vt, ldvt )
1277
1278 ELSE IF( wntqa ) THEN
1279
1280
1281
1282
1283
1284 ivt = 1
1285
1286
1287
1288 ldwkvt = m
1289 itau = ivt + ldwkvt*m
1290 nwork = itau + m
1291
1292
1293
1294
1295
1296 CALL sgelqf( m, n, a, lda, work( itau ), work( nwork ),
1297 $ lwork - nwork + 1, ierr )
1298 CALL slacpy(
'U', m, n, a, lda, vt, ldvt )
1299
1300
1301
1302
1303
1304 CALL sorglq( n, n, m, vt, ldvt, work( itau ),
1305 $ work( nwork ), lwork - nwork + 1, ierr )
1306
1307
1308
1309 CALL slaset(
'U', m-1, m-1, zero, zero, a( 1, 2 ), lda )
1310 ie = itau
1311 itauq = ie + m
1312 itaup = itauq + m
1313 nwork = itaup + m
1314
1315
1316
1317
1318
1319 CALL sgebrd( m, m, a, lda, s, work( ie ), work( itauq ),
1320 $ work( itaup ), work( nwork ), lwork-nwork+1,
1321 $ ierr )
1322
1323
1324
1325
1326
1327
1328 CALL sbdsdc(
'U',
'I', m, s, work( ie ), u, ldu,
1329 $ work( ivt ), ldwkvt, dum, idum,
1330 $ work( nwork ), iwork, info )
1331
1332
1333
1334
1335
1336
1337 CALL sormbr(
'Q',
'L',
'N', m, m, m, a, lda,
1338 $ work( itauq ), u, ldu, work( nwork ),
1339 $ lwork - nwork + 1, ierr )
1340 CALL sormbr(
'P',
'R',
'T', m, m, m, a, lda,
1341 $ work( itaup ), work( ivt ), ldwkvt,
1342 $ work( nwork ), lwork - nwork + 1, ierr )
1343
1344
1345
1346
1347
1348 CALL sgemm(
'N',
'N', m, n, m, one, work( ivt ), ldwkvt,
1349 $ vt, ldvt, zero, a, lda )
1350
1351
1352
1353 CALL slacpy(
'F', m, n, a, lda, vt, ldvt )
1354
1355 END IF
1356
1357 ELSE
1358
1359
1360
1361
1362
1363
1364 ie = 1
1365 itauq = ie + m
1366 itaup = itauq + m
1367 nwork = itaup + m
1368
1369
1370
1371
1372
1373 CALL sgebrd( m, n, a, lda, s, work( ie ), work( itauq ),
1374 $ work( itaup ), work( nwork ), lwork-nwork+1,
1375 $ ierr )
1376 IF( wntqn ) THEN
1377
1378
1379
1380
1381
1382 CALL sbdsdc(
'L',
'N', m, s, work( ie ), dum, 1, dum, 1,
1383 $ dum, idum, work( nwork ), iwork, info )
1384 ELSE IF( wntqo ) THEN
1385
1386 ldwkvt = m
1387 ivt = nwork
1388 IF( lwork .GE. m*n + 3*m + bdspac ) THEN
1389
1390
1391
1392 CALL slaset(
'F', m, n, zero, zero, work( ivt ),
1393 $ ldwkvt )
1394 nwork = ivt + ldwkvt*n
1395
1396 il = -1
1397 ELSE
1398
1399
1400
1401 nwork = ivt + ldwkvt*m
1402 il = nwork
1403
1404
1405
1406 chunk = ( lwork - m*m - 3*m ) / m
1407 END IF
1408
1409
1410
1411
1412
1413
1414 CALL sbdsdc(
'L',
'I', m, s, work( ie ), u, ldu,
1415 $ work( ivt ), ldwkvt, dum, idum,
1416 $ work( nwork ), iwork, info )
1417
1418
1419
1420
1421
1422 CALL sormbr(
'Q',
'L',
'N', m, m, n, a, lda,
1423 $ work( itauq ), u, ldu, work( nwork ),
1424 $ lwork - nwork + 1, ierr )
1425
1426 IF( lwork .GE. m*n + 3*m + bdspac ) THEN
1427
1428
1429
1430
1431
1432
1433 CALL sormbr(
'P',
'R',
'T', m, n, m, a, lda,
1434 $ work( itaup ), work( ivt ), ldwkvt,
1435 $ work( nwork ), lwork - nwork + 1, ierr )
1436
1437
1438
1439 CALL slacpy(
'F', m, n, work( ivt ), ldwkvt, a, lda )
1440 ELSE
1441
1442
1443
1444
1445
1446
1447 CALL sorgbr(
'P', m, n, m, a, lda, work( itaup ),
1448 $ work( nwork ), lwork - nwork + 1, ierr )
1449
1450
1451
1452
1453
1454
1455
1456 DO 40 i = 1, n, chunk
1457 blk = min( n - i + 1, chunk )
1458 CALL sgemm(
'N',
'N', m, blk, m, one, work( ivt ),
1459 $ ldwkvt, a( 1, i ), lda, zero,
1460 $ work( il ), m )
1461 CALL slacpy(
'F', m, blk, work( il ), m, a( 1, i ),
1462 $ lda )
1463 40 CONTINUE
1464 END IF
1465 ELSE IF( wntqs ) THEN
1466
1467
1468
1469
1470
1471
1472
1473 CALL slaset(
'F', m, n, zero, zero, vt, ldvt )
1474 CALL sbdsdc(
'L',
'I', m, s, work( ie ), u, ldu, vt,
1475 $ ldvt, dum, idum, work( nwork ), iwork,
1476 $ info )
1477
1478
1479
1480
1481
1482
1483 CALL sormbr(
'Q',
'L',
'N', m, m, n, a, lda,
1484 $ work( itauq ), u, ldu, work( nwork ),
1485 $ lwork - nwork + 1, ierr )
1486 CALL sormbr(
'P',
'R',
'T', m, n, m, a, lda,
1487 $ work( itaup ), vt, ldvt, work( nwork ),
1488 $ lwork - nwork + 1, ierr )
1489 ELSE IF( wntqa ) THEN
1490
1491
1492
1493
1494
1495
1496
1497 CALL slaset(
'F', n, n, zero, zero, vt, ldvt )
1498 CALL sbdsdc(
'L',
'I', m, s, work( ie ), u, ldu, vt,
1499 $ ldvt, dum, idum, work( nwork ), iwork,
1500 $ info )
1501
1502
1503
1504 IF( n.GT.m ) THEN
1505 CALL slaset(
'F', n-m, n-m, zero, one, vt(m+1,m+1),
1506 $ ldvt )
1507 END IF
1508
1509
1510
1511
1512
1513
1514 CALL sormbr(
'Q',
'L',
'N', m, m, n, a, lda,
1515 $ work( itauq ), u, ldu, work( nwork ),
1516 $ lwork - nwork + 1, ierr )
1517 CALL sormbr(
'P',
'R',
'T', n, n, m, a, lda,
1518 $ work( itaup ), vt, ldvt, work( nwork ),
1519 $ lwork - nwork + 1, ierr )
1520 END IF
1521
1522 END IF
1523
1524 END IF
1525
1526
1527
1528 IF( iscl.EQ.1 ) THEN
1529 IF( anrm.GT.bignum )
1530 $
CALL slascl(
'G', 0, 0, bignum, anrm, minmn, 1, s, minmn,
1531 $ ierr )
1532 IF( anrm.LT.smlnum )
1533 $
CALL slascl(
'G', 0, 0, smlnum, anrm, minmn, 1, s, minmn,
1534 $ ierr )
1535 END IF
1536
1537
1538
1540
1541 RETURN
1542
1543
1544
subroutine xerbla(srname, info)
subroutine sbdsdc(uplo, compq, n, d, e, u, ldu, vt, ldvt, q, iq, work, iwork, info)
SBDSDC
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 sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
SGEMM
subroutine sgeqrf(m, n, a, lda, tau, work, lwork, info)
SGEQRF
logical function sisnan(sin)
SISNAN tests input for NaN.
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 sorgbr(vect, m, n, k, a, lda, tau, work, lwork, info)
SORGBR
subroutine sorglq(m, n, k, a, lda, tau, work, lwork, info)
SORGLQ
subroutine sorgqr(m, n, k, a, lda, tau, work, lwork, info)
SORGQR
subroutine sormbr(vect, side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork, info)
SORMBR