331
332
333
334
335
336
337 CHARACTER JOBU1, JOBU2, JOBV1T, JOBV2T, TRANS
338 INTEGER INFO, LDU1, LDU2, LDV1T, LDV2T, LWORK, M, P, Q
339
340
341 DOUBLE PRECISION B11D( * ), B11E( * ), B12D( * ), B12E( * ),
342 $ B21D( * ), B21E( * ), B22D( * ), B22E( * ),
343 $ PHI( * ), THETA( * ), WORK( * )
344 DOUBLE PRECISION U1( LDU1, * ), U2( LDU2, * ), V1T( LDV1T, * ),
345 $ V2T( LDV2T, * )
346
347
348
349
350
351 INTEGER MAXITR
352 parameter( maxitr = 6 )
353 DOUBLE PRECISION HUNDRED, MEIGHTH, ONE, TEN, ZERO
354 parameter( hundred = 100.0d0, meighth = -0.125d0,
355 $ one = 1.0d0, ten = 10.0d0, zero = 0.0d0 )
356 DOUBLE PRECISION NEGONE
357 parameter( negone = -1.0d0 )
358 DOUBLE PRECISION PIOVER2
359 parameter( piover2 = 1.57079632679489661923132169163975144210d0 )
360
361
362 LOGICAL COLMAJOR, LQUERY, RESTART11, RESTART12,
363 $ RESTART21, RESTART22, WANTU1, WANTU2, WANTV1T,
364 $ WANTV2T
365 INTEGER I, IMIN, IMAX, ITER, IU1CS, IU1SN, IU2CS,
366 $ IU2SN, IV1TCS, IV1TSN, IV2TCS, IV2TSN, J,
367 $ LWORKMIN, LWORKOPT, MAXIT, MINI
368 DOUBLE PRECISION B11BULGE, B12BULGE, B21BULGE, B22BULGE, DUMMY,
369 $ EPS, MU, NU, R, SIGMA11, SIGMA21,
370 $ TEMP, THETAMAX, THETAMIN, THRESH, TOL, TOLMUL,
371 $ UNFL, X1, X2, Y1, Y2
372
373
377
378
379 DOUBLE PRECISION DLAMCH
380 LOGICAL LSAME
382
383
384 INTRINSIC abs, atan2, cos, max, min, sin, sqrt
385
386
387
388
389
390 info = 0
391 lquery = lwork .EQ. -1
392 wantu1 =
lsame( jobu1,
'Y' )
393 wantu2 =
lsame( jobu2,
'Y' )
394 wantv1t =
lsame( jobv1t,
'Y' )
395 wantv2t =
lsame( jobv2t,
'Y' )
396 colmajor = .NOT.
lsame( trans,
'T' )
397
398 IF( m .LT. 0 ) THEN
399 info = -6
400 ELSE IF( p .LT. 0 .OR. p .GT. m ) THEN
401 info = -7
402 ELSE IF( q .LT. 0 .OR. q .GT. m ) THEN
403 info = -8
404 ELSE IF( q .GT. p .OR. q .GT. m-p .OR. q .GT. m-q ) THEN
405 info = -8
406 ELSE IF( wantu1 .AND. ldu1 .LT. p ) THEN
407 info = -12
408 ELSE IF( wantu2 .AND. ldu2 .LT. m-p ) THEN
409 info = -14
410 ELSE IF( wantv1t .AND. ldv1t .LT. q ) THEN
411 info = -16
412 ELSE IF( wantv2t .AND. ldv2t .LT. m-q ) THEN
413 info = -18
414 END IF
415
416
417
418 IF( info .EQ. 0 .AND. q .EQ. 0 ) THEN
419 lworkmin = 1
420 work(1) = lworkmin
421 RETURN
422 END IF
423
424
425
426 IF( info .EQ. 0 ) THEN
427 iu1cs = 1
428 iu1sn = iu1cs + q
429 iu2cs = iu1sn + q
430 iu2sn = iu2cs + q
431 iv1tcs = iu2sn + q
432 iv1tsn = iv1tcs + q
433 iv2tcs = iv1tsn + q
434 iv2tsn = iv2tcs + q
435 lworkopt = iv2tsn + q - 1
436 lworkmin = lworkopt
437 work(1) = lworkopt
438 IF( lwork .LT. lworkmin .AND. .NOT. lquery ) THEN
439 info = -28
440 END IF
441 END IF
442
443 IF( info .NE. 0 ) THEN
444 CALL xerbla(
'DBBCSD', -info )
445 RETURN
446 ELSE IF( lquery ) THEN
447 RETURN
448 END IF
449
450
451
453 unfl =
dlamch(
'Safe minimum' )
454 tolmul = max( ten, min( hundred, eps**meighth ) )
455 tol = tolmul*eps
456 thresh = max( tol, maxitr*q*q*unfl )
457
458
459
460 DO i = 1, q
461 IF( theta(i) .LT. thresh ) THEN
462 theta(i) = zero
463 ELSE IF( theta(i) .GT. piover2-thresh ) THEN
464 theta(i) = piover2
465 END IF
466 END DO
467 DO i = 1, q-1
468 IF( phi(i) .LT. thresh ) THEN
469 phi(i) = zero
470 ELSE IF( phi(i) .GT. piover2-thresh ) THEN
471 phi(i) = piover2
472 END IF
473 END DO
474
475
476
477 imax = q
478 DO WHILE( imax .GT. 1 )
479 IF( phi(imax-1) .NE. zero ) THEN
480 EXIT
481 END IF
482 imax = imax - 1
483 END DO
484 imin = imax - 1
485 IF ( imin .GT. 1 ) THEN
486 DO WHILE( phi(imin-1) .NE. zero )
487 imin = imin - 1
488 IF ( imin .LE. 1 ) EXIT
489 END DO
490 END IF
491
492
493
494 maxit = maxitr*q*q
495 iter = 0
496
497
498
499 DO WHILE( imax .GT. 1 )
500
501
502
503 b11d(imin) = cos( theta(imin) )
504 b21d(imin) = -sin( theta(imin) )
505 DO i = imin, imax - 1
506 b11e(i) = -sin( theta(i) ) * sin( phi(i) )
507 b11d(i+1) = cos( theta(i+1) ) * cos( phi(i) )
508 b12d(i) = sin( theta(i) ) * cos( phi(i) )
509 b12e(i) = cos( theta(i+1) ) * sin( phi(i) )
510 b21e(i) = -cos( theta(i) ) * sin( phi(i) )
511 b21d(i+1) = -sin( theta(i+1) ) * cos( phi(i) )
512 b22d(i) = cos( theta(i) ) * cos( phi(i) )
513 b22e(i) = -sin( theta(i+1) ) * sin( phi(i) )
514 END DO
515 b12d(imax) = sin( theta(imax) )
516 b22d(imax) = cos( theta(imax) )
517
518
519
520 IF( iter .GT. maxit ) THEN
521 info = 0
522 DO i = 1, q
523 IF( phi(i) .NE. zero )
524 $ info = info + 1
525 END DO
526 RETURN
527 END IF
528
529 iter = iter + imax - imin
530
531
532
533 thetamax = theta(imin)
534 thetamin = theta(imin)
535 DO i = imin+1, imax
536 IF( theta(i) > thetamax )
537 $ thetamax = theta(i)
538 IF( theta(i) < thetamin )
539 $ thetamin = theta(i)
540 END DO
541
542 IF( thetamax .GT. piover2 - thresh ) THEN
543
544
545
546
547 mu = zero
548 nu = one
549
550 ELSE IF( thetamin .LT. thresh ) THEN
551
552
553
554
555 mu = one
556 nu = zero
557
558 ELSE
559
560
561
562 CALL dlas2( b11d(imax-1), b11e(imax-1), b11d(imax),
563 $ sigma11,
564 $ dummy )
565 CALL dlas2( b21d(imax-1), b21e(imax-1), b21d(imax),
566 $ sigma21,
567 $ dummy )
568
569 IF( sigma11 .LE. sigma21 ) THEN
570 mu = sigma11
571 nu = sqrt( one - mu**2 )
572 IF( mu .LT. thresh ) THEN
573 mu = zero
574 nu = one
575 END IF
576 ELSE
577 nu = sigma21
578 mu = sqrt( 1.0 - nu**2 )
579 IF( nu .LT. thresh ) THEN
580 mu = one
581 nu = zero
582 END IF
583 END IF
584 END IF
585
586
587
588 IF( mu .LE. nu ) THEN
589 CALL dlartgs( b11d(imin), b11e(imin), mu,
590 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1) )
591 ELSE
592 CALL dlartgs( b21d(imin), b21e(imin), nu,
593 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1) )
594 END IF
595
596 temp = work(iv1tcs+imin-1)*b11d(imin) +
597 $ work(iv1tsn+imin-1)*b11e(imin)
598 b11e(imin) = work(iv1tcs+imin-1)*b11e(imin) -
599 $ work(iv1tsn+imin-1)*b11d(imin)
600 b11d(imin) = temp
601 b11bulge = work(iv1tsn+imin-1)*b11d(imin+1)
602 b11d(imin+1) = work(iv1tcs+imin-1)*b11d(imin+1)
603 temp = work(iv1tcs+imin-1)*b21d(imin) +
604 $ work(iv1tsn+imin-1)*b21e(imin)
605 b21e(imin) = work(iv1tcs+imin-1)*b21e(imin) -
606 $ work(iv1tsn+imin-1)*b21d(imin)
607 b21d(imin) = temp
608 b21bulge = work(iv1tsn+imin-1)*b21d(imin+1)
609 b21d(imin+1) = work(iv1tcs+imin-1)*b21d(imin+1)
610
611
612
613 theta( imin ) = atan2( sqrt( b21d(imin)**2+b21bulge**2 ),
614 $ sqrt( b11d(imin)**2+b11bulge**2 ) )
615
616
617
618 IF( b11d(imin)**2+b11bulge**2 .GT. thresh**2 ) THEN
619 CALL dlartgp( b11bulge, b11d(imin), work(iu1sn+imin-1),
620 $ work(iu1cs+imin-1), r )
621 ELSE IF( mu .LE. nu ) THEN
622 CALL dlartgs( b11e( imin ), b11d( imin + 1 ), mu,
623 $ work(iu1cs+imin-1), work(iu1sn+imin-1) )
624 ELSE
625 CALL dlartgs( b12d( imin ), b12e( imin ), nu,
626 $ work(iu1cs+imin-1), work(iu1sn+imin-1) )
627 END IF
628 IF( b21d(imin)**2+b21bulge**2 .GT. thresh**2 ) THEN
629 CALL dlartgp( b21bulge, b21d(imin), work(iu2sn+imin-1),
630 $ work(iu2cs+imin-1), r )
631 ELSE IF( nu .LT. mu ) THEN
632 CALL dlartgs( b21e( imin ), b21d( imin + 1 ), nu,
633 $ work(iu2cs+imin-1), work(iu2sn+imin-1) )
634 ELSE
635 CALL dlartgs( b22d(imin), b22e(imin), mu,
636 $ work(iu2cs+imin-1), work(iu2sn+imin-1) )
637 END IF
638 work(iu2cs+imin-1) = -work(iu2cs+imin-1)
639 work(iu2sn+imin-1) = -work(iu2sn+imin-1)
640
641 temp = work(iu1cs+imin-1)*b11e(imin) +
642 $ work(iu1sn+imin-1)*b11d(imin+1)
643 b11d(imin+1) = work(iu1cs+imin-1)*b11d(imin+1) -
644 $ work(iu1sn+imin-1)*b11e(imin)
645 b11e(imin) = temp
646 IF( imax .GT. imin+1 ) THEN
647 b11bulge = work(iu1sn+imin-1)*b11e(imin+1)
648 b11e(imin+1) = work(iu1cs+imin-1)*b11e(imin+1)
649 END IF
650 temp = work(iu1cs+imin-1)*b12d(imin) +
651 $ work(iu1sn+imin-1)*b12e(imin)
652 b12e(imin) = work(iu1cs+imin-1)*b12e(imin) -
653 $ work(iu1sn+imin-1)*b12d(imin)
654 b12d(imin) = temp
655 b12bulge = work(iu1sn+imin-1)*b12d(imin+1)
656 b12d(imin+1) = work(iu1cs+imin-1)*b12d(imin+1)
657 temp = work(iu2cs+imin-1)*b21e(imin) +
658 $ work(iu2sn+imin-1)*b21d(imin+1)
659 b21d(imin+1) = work(iu2cs+imin-1)*b21d(imin+1) -
660 $ work(iu2sn+imin-1)*b21e(imin)
661 b21e(imin) = temp
662 IF( imax .GT. imin+1 ) THEN
663 b21bulge = work(iu2sn+imin-1)*b21e(imin+1)
664 b21e(imin+1) = work(iu2cs+imin-1)*b21e(imin+1)
665 END IF
666 temp = work(iu2cs+imin-1)*b22d(imin) +
667 $ work(iu2sn+imin-1)*b22e(imin)
668 b22e(imin) = work(iu2cs+imin-1)*b22e(imin) -
669 $ work(iu2sn+imin-1)*b22d(imin)
670 b22d(imin) = temp
671 b22bulge = work(iu2sn+imin-1)*b22d(imin+1)
672 b22d(imin+1) = work(iu2cs+imin-1)*b22d(imin+1)
673
674
675
676
677
678 DO i = imin+1, imax-1
679
680
681
682 x1 = sin(theta(i-1))*b11e(i-1) + cos(theta(i-1))*b21e(i-1)
683 x2 = sin(theta(i-1))*b11bulge + cos(theta(i-1))*b21bulge
684 y1 = sin(theta(i-1))*b12d(i-1) + cos(theta(i-1))*b22d(i-1)
685 y2 = sin(theta(i-1))*b12bulge + cos(theta(i-1))*b22bulge
686
687 phi(i-1) = atan2( sqrt(x1**2+x2**2), sqrt(y1**2+y2**2) )
688
689
690
691
692 restart11 = b11e(i-1)**2 + b11bulge**2 .LE. thresh**2
693 restart21 = b21e(i-1)**2 + b21bulge**2 .LE. thresh**2
694 restart12 = b12d(i-1)**2 + b12bulge**2 .LE. thresh**2
695 restart22 = b22d(i-1)**2 + b22bulge**2 .LE. thresh**2
696
697
698
699
700
701 IF( .NOT. restart11 .AND. .NOT. restart21 ) THEN
702 CALL dlartgp( x2, x1, work(iv1tsn+i-1),
703 $ work(iv1tcs+i-1),
704 $ r )
705 ELSE IF( .NOT. restart11 .AND. restart21 ) THEN
706 CALL dlartgp( b11bulge, b11e(i-1), work(iv1tsn+i-1),
707 $ work(iv1tcs+i-1), r )
708 ELSE IF( restart11 .AND. .NOT. restart21 ) THEN
709 CALL dlartgp( b21bulge, b21e(i-1), work(iv1tsn+i-1),
710 $ work(iv1tcs+i-1), r )
711 ELSE IF( mu .LE. nu ) THEN
712 CALL dlartgs( b11d(i), b11e(i), mu, work(iv1tcs+i-1),
713 $ work(iv1tsn+i-1) )
714 ELSE
715 CALL dlartgs( b21d(i), b21e(i), nu, work(iv1tcs+i-1),
716 $ work(iv1tsn+i-1) )
717 END IF
718 work(iv1tcs+i-1) = -work(iv1tcs+i-1)
719 work(iv1tsn+i-1) = -work(iv1tsn+i-1)
720 IF( .NOT. restart12 .AND. .NOT. restart22 ) THEN
721 CALL dlartgp( y2, y1, work(iv2tsn+i-1-1),
722 $ work(iv2tcs+i-1-1), r )
723 ELSE IF( .NOT. restart12 .AND. restart22 ) THEN
724 CALL dlartgp( b12bulge, b12d(i-1), work(iv2tsn+i-1-1),
725 $ work(iv2tcs+i-1-1), r )
726 ELSE IF( restart12 .AND. .NOT. restart22 ) THEN
727 CALL dlartgp( b22bulge, b22d(i-1), work(iv2tsn+i-1-1),
728 $ work(iv2tcs+i-1-1), r )
729 ELSE IF( nu .LT. mu ) THEN
730 CALL dlartgs( b12e(i-1), b12d(i), nu,
731 $ work(iv2tcs+i-1-1),
732 $ work(iv2tsn+i-1-1) )
733 ELSE
734 CALL dlartgs( b22e(i-1), b22d(i), mu,
735 $ work(iv2tcs+i-1-1),
736 $ work(iv2tsn+i-1-1) )
737 END IF
738
739 temp = work(iv1tcs+i-1)*b11d(i) + work(iv1tsn+i-1)*b11e(i)
740 b11e(i) = work(iv1tcs+i-1)*b11e(i) -
741 $ work(iv1tsn+i-1)*b11d(i)
742 b11d(i) = temp
743 b11bulge = work(iv1tsn+i-1)*b11d(i+1)
744 b11d(i+1) = work(iv1tcs+i-1)*b11d(i+1)
745 temp = work(iv1tcs+i-1)*b21d(i) + work(iv1tsn+i-1)*b21e(i)
746 b21e(i) = work(iv1tcs+i-1)*b21e(i) -
747 $ work(iv1tsn+i-1)*b21d(i)
748 b21d(i) = temp
749 b21bulge = work(iv1tsn+i-1)*b21d(i+1)
750 b21d(i+1) = work(iv1tcs+i-1)*b21d(i+1)
751 temp = work(iv2tcs+i-1-1)*b12e(i-1) +
752 $ work(iv2tsn+i-1-1)*b12d(i)
753 b12d(i) = work(iv2tcs+i-1-1)*b12d(i) -
754 $ work(iv2tsn+i-1-1)*b12e(i-1)
755 b12e(i-1) = temp
756 b12bulge = work(iv2tsn+i-1-1)*b12e(i)
757 b12e(i) = work(iv2tcs+i-1-1)*b12e(i)
758 temp = work(iv2tcs+i-1-1)*b22e(i-1) +
759 $ work(iv2tsn+i-1-1)*b22d(i)
760 b22d(i) = work(iv2tcs+i-1-1)*b22d(i) -
761 $ work(iv2tsn+i-1-1)*b22e(i-1)
762 b22e(i-1) = temp
763 b22bulge = work(iv2tsn+i-1-1)*b22e(i)
764 b22e(i) = work(iv2tcs+i-1-1)*b22e(i)
765
766
767
768 x1 = cos(phi(i-1))*b11d(i) + sin(phi(i-1))*b12e(i-1)
769 x2 = cos(phi(i-1))*b11bulge + sin(phi(i-1))*b12bulge
770 y1 = cos(phi(i-1))*b21d(i) + sin(phi(i-1))*b22e(i-1)
771 y2 = cos(phi(i-1))*b21bulge + sin(phi(i-1))*b22bulge
772
773 theta(i) = atan2( sqrt(y1**2+y2**2), sqrt(x1**2+x2**2) )
774
775
776
777
778 restart11 = b11d(i)**2 + b11bulge**2 .LE. thresh**2
779 restart12 = b12e(i-1)**2 + b12bulge**2 .LE. thresh**2
780 restart21 = b21d(i)**2 + b21bulge**2 .LE. thresh**2
781 restart22 = b22e(i-1)**2 + b22bulge**2 .LE. thresh**2
782
783
784
785
786
787 IF( .NOT. restart11 .AND. .NOT. restart12 ) THEN
788 CALL dlartgp( x2, x1, work(iu1sn+i-1),
789 $ work(iu1cs+i-1),
790 $ r )
791 ELSE IF( .NOT. restart11 .AND. restart12 ) THEN
792 CALL dlartgp( b11bulge, b11d(i), work(iu1sn+i-1),
793 $ work(iu1cs+i-1), r )
794 ELSE IF( restart11 .AND. .NOT. restart12 ) THEN
795 CALL dlartgp( b12bulge, b12e(i-1), work(iu1sn+i-1),
796 $ work(iu1cs+i-1), r )
797 ELSE IF( mu .LE. nu ) THEN
798 CALL dlartgs( b11e(i), b11d(i+1), mu, work(iu1cs+i-1),
799 $ work(iu1sn+i-1) )
800 ELSE
801 CALL dlartgs( b12d(i), b12e(i), nu, work(iu1cs+i-1),
802 $ work(iu1sn+i-1) )
803 END IF
804 IF( .NOT. restart21 .AND. .NOT. restart22 ) THEN
805 CALL dlartgp( y2, y1, work(iu2sn+i-1),
806 $ work(iu2cs+i-1),
807 $ r )
808 ELSE IF( .NOT. restart21 .AND. restart22 ) THEN
809 CALL dlartgp( b21bulge, b21d(i), work(iu2sn+i-1),
810 $ work(iu2cs+i-1), r )
811 ELSE IF( restart21 .AND. .NOT. restart22 ) THEN
812 CALL dlartgp( b22bulge, b22e(i-1), work(iu2sn+i-1),
813 $ work(iu2cs+i-1), r )
814 ELSE IF( nu .LT. mu ) THEN
815 CALL dlartgs( b21e(i), b21e(i+1), nu, work(iu2cs+i-1),
816 $ work(iu2sn+i-1) )
817 ELSE
818 CALL dlartgs( b22d(i), b22e(i), mu, work(iu2cs+i-1),
819 $ work(iu2sn+i-1) )
820 END IF
821 work(iu2cs+i-1) = -work(iu2cs+i-1)
822 work(iu2sn+i-1) = -work(iu2sn+i-1)
823
824 temp = work(iu1cs+i-1)*b11e(i) + work(iu1sn+i-1)*b11d(i+1)
825 b11d(i+1) = work(iu1cs+i-1)*b11d(i+1) -
826 $ work(iu1sn+i-1)*b11e(i)
827 b11e(i) = temp
828 IF( i .LT. imax - 1 ) THEN
829 b11bulge = work(iu1sn+i-1)*b11e(i+1)
830 b11e(i+1) = work(iu1cs+i-1)*b11e(i+1)
831 END IF
832 temp = work(iu2cs+i-1)*b21e(i) + work(iu2sn+i-1)*b21d(i+1)
833 b21d(i+1) = work(iu2cs+i-1)*b21d(i+1) -
834 $ work(iu2sn+i-1)*b21e(i)
835 b21e(i) = temp
836 IF( i .LT. imax - 1 ) THEN
837 b21bulge = work(iu2sn+i-1)*b21e(i+1)
838 b21e(i+1) = work(iu2cs+i-1)*b21e(i+1)
839 END IF
840 temp = work(iu1cs+i-1)*b12d(i) + work(iu1sn+i-1)*b12e(i)
841 b12e(i) = work(iu1cs+i-1)*b12e(i) - work(iu1sn+i-1)*b12d(i)
842 b12d(i) = temp
843 b12bulge = work(iu1sn+i-1)*b12d(i+1)
844 b12d(i+1) = work(iu1cs+i-1)*b12d(i+1)
845 temp = work(iu2cs+i-1)*b22d(i) + work(iu2sn+i-1)*b22e(i)
846 b22e(i) = work(iu2cs+i-1)*b22e(i) - work(iu2sn+i-1)*b22d(i)
847 b22d(i) = temp
848 b22bulge = work(iu2sn+i-1)*b22d(i+1)
849 b22d(i+1) = work(iu2cs+i-1)*b22d(i+1)
850
851 END DO
852
853
854
855 x1 = sin(theta(imax-1))*b11e(imax-1) +
856 $ cos(theta(imax-1))*b21e(imax-1)
857 y1 = sin(theta(imax-1))*b12d(imax-1) +
858 $ cos(theta(imax-1))*b22d(imax-1)
859 y2 = sin(theta(imax-1))*b12bulge + cos(theta(imax-1))*b22bulge
860
861 phi(imax-1) = atan2( abs(x1), sqrt(y1**2+y2**2) )
862
863
864
865 restart12 = b12d(imax-1)**2 + b12bulge**2 .LE. thresh**2
866 restart22 = b22d(imax-1)**2 + b22bulge**2 .LE. thresh**2
867
868 IF( .NOT. restart12 .AND. .NOT. restart22 ) THEN
869 CALL dlartgp( y2, y1, work(iv2tsn+imax-1-1),
870 $ work(iv2tcs+imax-1-1), r )
871 ELSE IF( .NOT. restart12 .AND. restart22 ) THEN
872 CALL dlartgp( b12bulge, b12d(imax-1),
873 $ work(iv2tsn+imax-1-1),
874 $ work(iv2tcs+imax-1-1), r )
875 ELSE IF( restart12 .AND. .NOT. restart22 ) THEN
876 CALL dlartgp( b22bulge, b22d(imax-1),
877 $ work(iv2tsn+imax-1-1),
878 $ work(iv2tcs+imax-1-1), r )
879 ELSE IF( nu .LT. mu ) THEN
880 CALL dlartgs( b12e(imax-1), b12d(imax), nu,
881 $ work(iv2tcs+imax-1-1), work(iv2tsn+imax-1-1) )
882 ELSE
883 CALL dlartgs( b22e(imax-1), b22d(imax), mu,
884 $ work(iv2tcs+imax-1-1), work(iv2tsn+imax-1-1) )
885 END IF
886
887 temp = work(iv2tcs+imax-1-1)*b12e(imax-1) +
888 $ work(iv2tsn+imax-1-1)*b12d(imax)
889 b12d(imax) = work(iv2tcs+imax-1-1)*b12d(imax) -
890 $ work(iv2tsn+imax-1-1)*b12e(imax-1)
891 b12e(imax-1) = temp
892 temp = work(iv2tcs+imax-1-1)*b22e(imax-1) +
893 $ work(iv2tsn+imax-1-1)*b22d(imax)
894 b22d(imax) = work(iv2tcs+imax-1-1)*b22d(imax) -
895 $ work(iv2tsn+imax-1-1)*b22e(imax-1)
896 b22e(imax-1) = temp
897
898
899
900 IF( wantu1 ) THEN
901 IF( colmajor ) THEN
902 CALL dlasr(
'R',
'V',
'F', p, imax-imin+1,
903 $ work(iu1cs+imin-1), work(iu1sn+imin-1),
904 $ u1(1,imin), ldu1 )
905 ELSE
906 CALL dlasr(
'L',
'V',
'F', imax-imin+1, p,
907 $ work(iu1cs+imin-1), work(iu1sn+imin-1),
908 $ u1(imin,1), ldu1 )
909 END IF
910 END IF
911 IF( wantu2 ) THEN
912 IF( colmajor ) THEN
913 CALL dlasr(
'R',
'V',
'F', m-p, imax-imin+1,
914 $ work(iu2cs+imin-1), work(iu2sn+imin-1),
915 $ u2(1,imin), ldu2 )
916 ELSE
917 CALL dlasr(
'L',
'V',
'F', imax-imin+1, m-p,
918 $ work(iu2cs+imin-1), work(iu2sn+imin-1),
919 $ u2(imin,1), ldu2 )
920 END IF
921 END IF
922 IF( wantv1t ) THEN
923 IF( colmajor ) THEN
924 CALL dlasr(
'L',
'V',
'F', imax-imin+1, q,
925 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1),
926 $ v1t(imin,1), ldv1t )
927 ELSE
928 CALL dlasr(
'R',
'V',
'F', q, imax-imin+1,
929 $ work(iv1tcs+imin-1), work(iv1tsn+imin-1),
930 $ v1t(1,imin), ldv1t )
931 END IF
932 END IF
933 IF( wantv2t ) THEN
934 IF( colmajor ) THEN
935 CALL dlasr(
'L',
'V',
'F', imax-imin+1, m-q,
936 $ work(iv2tcs+imin-1), work(iv2tsn+imin-1),
937 $ v2t(imin,1), ldv2t )
938 ELSE
939 CALL dlasr(
'R',
'V',
'F', m-q, imax-imin+1,
940 $ work(iv2tcs+imin-1), work(iv2tsn+imin-1),
941 $ v2t(1,imin), ldv2t )
942 END IF
943 END IF
944
945
946
947 IF( b11e(imax-1)+b21e(imax-1) .GT. 0 ) THEN
948 b11d(imax) = -b11d(imax)
949 b21d(imax) = -b21d(imax)
950 IF( wantv1t ) THEN
951 IF( colmajor ) THEN
952 CALL dscal( q, negone, v1t(imax,1), ldv1t )
953 ELSE
954 CALL dscal( q, negone, v1t(1,imax), 1 )
955 END IF
956 END IF
957 END IF
958
959
960
961 x1 = cos(phi(imax-1))*b11d(imax) +
962 $ sin(phi(imax-1))*b12e(imax-1)
963 y1 = cos(phi(imax-1))*b21d(imax) +
964 $ sin(phi(imax-1))*b22e(imax-1)
965
966 theta(imax) = atan2( abs(y1), abs(x1) )
967
968
969
970
971 IF( b11d(imax)+b12e(imax-1) .LT. 0 ) THEN
972 b12d(imax) = -b12d(imax)
973 IF( wantu1 ) THEN
974 IF( colmajor ) THEN
975 CALL dscal( p, negone, u1(1,imax), 1 )
976 ELSE
977 CALL dscal( p, negone, u1(imax,1), ldu1 )
978 END IF
979 END IF
980 END IF
981 IF( b21d(imax)+b22e(imax-1) .GT. 0 ) THEN
982 b22d(imax) = -b22d(imax)
983 IF( wantu2 ) THEN
984 IF( colmajor ) THEN
985 CALL dscal( m-p, negone, u2(1,imax), 1 )
986 ELSE
987 CALL dscal( m-p, negone, u2(imax,1), ldu2 )
988 END IF
989 END IF
990 END IF
991
992
993
994 IF( b12d(imax)+b22d(imax) .LT. 0 ) THEN
995 IF( wantv2t ) THEN
996 IF( colmajor ) THEN
997 CALL dscal( m-q, negone, v2t(imax,1), ldv2t )
998 ELSE
999 CALL dscal( m-q, negone, v2t(1,imax), 1 )
1000 END IF
1001 END IF
1002 END IF
1003
1004
1005
1006 DO i = imin, imax
1007 IF( theta(i) .LT. thresh ) THEN
1008 theta(i) = zero
1009 ELSE IF( theta(i) .GT. piover2-thresh ) THEN
1010 theta(i) = piover2
1011 END IF
1012 END DO
1013 DO i = imin, imax-1
1014 IF( phi(i) .LT. thresh ) THEN
1015 phi(i) = zero
1016 ELSE IF( phi(i) .GT. piover2-thresh ) THEN
1017 phi(i) = piover2
1018 END IF
1019 END DO
1020
1021
1022
1023 IF (imax .GT. 1) THEN
1024 DO WHILE( phi(imax-1) .EQ. zero )
1025 imax = imax - 1
1026 IF (imax .LE. 1) EXIT
1027 END DO
1028 END IF
1029 IF( imin .GT. imax - 1 )
1030 $ imin = imax - 1
1031 IF (imin .GT. 1) THEN
1032 DO WHILE (phi(imin-1) .NE. zero)
1033 imin = imin - 1
1034 IF (imin .LE. 1) EXIT
1035 END DO
1036 END IF
1037
1038
1039
1040 END DO
1041
1042
1043
1044 DO i = 1, q
1045
1046 mini = i
1047 thetamin = theta(i)
1048 DO j = i+1, q
1049 IF( theta(j) .LT. thetamin ) THEN
1050 mini = j
1051 thetamin = theta(j)
1052 END IF
1053 END DO
1054
1055 IF( mini .NE. i ) THEN
1056 theta(mini) = theta(i)
1057 theta(i) = thetamin
1058 IF( colmajor ) THEN
1059 IF( wantu1 )
1060 $
CALL dswap( p, u1(1,i), 1, u1(1,mini), 1 )
1061 IF( wantu2 )
1062 $
CALL dswap( m-p, u2(1,i), 1, u2(1,mini), 1 )
1063 IF( wantv1t )
1064 $
CALL dswap( q, v1t(i,1), ldv1t, v1t(mini,1),
1065 $ ldv1t )
1066 IF( wantv2t )
1067 $
CALL dswap( m-q, v2t(i,1), ldv2t, v2t(mini,1),
1068 $ ldv2t )
1069 ELSE
1070 IF( wantu1 )
1071 $
CALL dswap( p, u1(i,1), ldu1, u1(mini,1), ldu1 )
1072 IF( wantu2 )
1073 $
CALL dswap( m-p, u2(i,1), ldu2, u2(mini,1), ldu2 )
1074 IF( wantv1t )
1075 $
CALL dswap( q, v1t(1,i), 1, v1t(1,mini), 1 )
1076 IF( wantv2t )
1077 $
CALL dswap( m-q, v2t(1,i), 1, v2t(1,mini), 1 )
1078 END IF
1079 END IF
1080
1081 END DO
1082
1083 RETURN
1084
1085
1086
subroutine xerbla(srname, info)
double precision function dlamch(cmach)
DLAMCH
subroutine dlartgp(f, g, cs, sn, r)
DLARTGP generates a plane rotation so that the diagonal is nonnegative.
subroutine dlartgs(x, y, sigma, cs, sn)
DLARTGS generates a plane rotation designed to introduce a bulge in implicit QR iteration for the bid...
subroutine dlas2(f, g, h, ssmin, ssmax)
DLAS2 computes singular values of a 2-by-2 triangular matrix.
subroutine dlasr(side, pivot, direct, m, n, c, s, a, lda)
DLASR applies a sequence of plane rotations to a general rectangular matrix.
logical function lsame(ca, cb)
LSAME
subroutine dscal(n, da, dx, incx)
DSCAL
subroutine dswap(n, dx, incx, dy, incy)
DSWAP