230 SUBROUTINE dorcsd2by1( JOBU1, JOBU2, JOBV1T, M, P, Q, X11, LDX11,
231 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
232 $ LDV1T, WORK, LWORK, IWORK, INFO )
239 CHARACTER JOBU1, JOBU2, JOBV1T
240 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
244 DOUBLE PRECISION THETA(*)
245 DOUBLE PRECISION U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
246 $ x11(ldx11,*), x21(ldx21,*)
253 DOUBLE PRECISION ONE, ZERO
254 PARAMETER ( ONE = 1.0d0, zero = 0.0d0 )
257 INTEGER , I, IB11D, IB11E, IB12D, IB12E,
258 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
259 $ iorglq, iorgqr, iphi, itaup1, itaup2, itauq1,
260 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
261 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
262 $ lworkmin, lworkopt, r
263 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
266 DOUBLE PRECISION DUM1(1), DUM2(1,1)
285 wantu1 = lsame( jobu1,
'Y' )
286 wantu2 = lsame( jobu2,
'Y' )
287 wantv1t = lsame( jobv1t,
'Y' )
288 lquery = lwork .EQ. -1
292 ELSE IF( p .LT. 0 .OR. p .GT. m )
THEN
294 ELSE IF( q .LT. 0 .OR. q .GT. m )
THEN
296 ELSE IF( ldx11 .LT.
max( 1, p ) )
THEN
298 ELSE IF( ldx21 .LT.
max( 1, m-p ) )
THEN
300 ELSE IF( wantu1 .AND. ldu1 .LT.
max( 1, p
THEN
302 ELSE IF( wantu2 .AND. ldu2 .LT.
max( 1, m - p ) )
THEN
304 ELSE IF( wantv1t .AND. ldv1t .LT.
max( 1, q ) )
THEN
308 r =
min( p, m-p, q, m-q )
329 IF( info .EQ. 0 )
THEN
331 ib11d = iphi +
max( 1, r-1 )
332 ib11e = ib11d +
max( 1, r )
333 ib12d = ib11e +
max( 1, r - 1 )
334 ib12e = ib12d +
max( 1, r )
335 ib21d = ib12e +
max( 1, r - 1 )
336 ib21e = ib21d +
max( 1, r )
337 ib22d = ib21e +
max( 1, r - 1 )
338 ib22e = ib22d +
max( 1, r )
339 ibbcsd = ib22e +
max( 1, r - 1 )
340 itaup1 = iphi +
max( 1, r-1 )
341 itaup2 = itaup1 +
max( 1, p )
342 itauq1 = itaup2 +
max( 1, m-p )
343 iorbdb = itauq1 +
max( 1, q )
344 iorgqr = itauq1 +
max( 1, q )
345 iorglq = itauq1 +
max( 1, q )
351 CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21
352 $ dum1, dum1, dum1, dum1, work,
354 lorbdb = int( work(1) )
355 IF( wantu1 .AND. p .GT. 0 )
THEN
356 CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
358 lorgqrmin =
max( lorgqrmin, p )
359 lorgqropt =
max( lorgqropt, int( work(1) ) )
361IF( wantu2 .AND. m-p .GT. 0 )
THEN
362 CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
364 lorgqrmin =
max( lorgqrmin, m-p )
365 lorgqropt =
max( lorgqropt, int( work(1) ) )
367 IF( wantv1t .AND. q .GT. 0 )
THEN
368 CALL dorglq( q-1, q-1, q-1, v1t, ldv1t,
369 $ dum1, work(1), -1, childinfo )
370 lorglqmin =
max( lorglqmin, q-1 )
371 lorglqopt =
max( lorglqopt, int( work(1) ) )
373 CALL dbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
374 $ dum1, u1, ldu1, u2, ldu2, v1t, ldv1t,
375 $ dum2, 1, dum1, dum1, dum1,
376 $ dum1, dum1, dum1, dum1,
377 $ dum1, work(1), -1, childinfo )
378 lbbcsd = int( work(1) )
379 ELSE IF( r .EQ. p )
THEN
380 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
381 $ dum1, dum1, dum1, dum1,
382 $ work(1), -1, childinfo )
383 lorbdb = int( work(1) )
384 IF( wantu1 .AND. p .GT. 0 )
THEN
385 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, dum1,
386 $ work(1), -1, childinfo )
387 lorgqrmin =
max( lorgqrmin, p-1 )
388 lorgqropt =
max( lorgqropt, int( work(1) ) )
390 IF( wantu2 .AND. m-p .GT. 0 )
THEN
391 CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
393 lorgqrmin =
max( lorgqrmin, m-p )
394 lorgqropt =
max( lorgqropt, int( work(1) ) )
396 IF( wantv1t .AND. q .GT. 0 )
THEN
397 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
399 lorglqmin =
max( lorglqmin, q )
400 lorglqopt =
max( lorglqopt, int( work(1) ) )
402 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
403 $ dum1, v1t, ldv1t, dum2, 1, u1, ldu1,
404 $ u2, ldu2, dum1, dum1, dum1,
405 $ dum1, dum1, dum1, dum1,
406 $ dum1, work(1), -1, childinfo )
407 lbbcsd = int( work(1) )
408 ELSE IF( r .EQ. m-p )
THEN
409 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
410 $ dum1, dum1, dum1, dum1,
411 $ work(1), -1, childinfo )
412 lorbdb = int( work(1) )
413 IF( wantu1 .AND. p .GT. 0 )
THEN
414 CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
416 lorgqrmin =
max( lorgqrmin, p )
417 lorgqropt =
max( lorgqropt, int( work(1) ) )
419 IF( wantu2 .AND. m-p .GT. 0 )
THEN
420 CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
421 $ dum1, work(1), -1, childinfo )
422 lorgqrmin =
max( lorgqrmin, m-p-1 )
423 lorgqropt =
max( lorgqropt, int( work(1) ) )
425 IF( wantv1t .AND. q .GT. 0 )
THEN
426 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
428 lorglqmin =
max( lorglqmin, q )
429 lorglqopt =
max( lorglqopt, int( work(1) ) )
431 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
432 $ theta, dum1, dum2, 1, v1t, ldv1t, u2,
433 $ ldu2, u1, ldu1, dum1, dum1, dum1,
434 $ dum1, dum1, dum1, dum1,
435 $ dum1, work(1), -1, childinfo )
436 lbbcsd = int( work(1) )
438 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
439 $ dum1, dum1, dum1, dum1,
440 $ dum1, work(1), -1, childinfo )
441 lorbdb = m + int( work(1) )
442 IF( wantu1 .AND. p .GT. 0 )
THEN
443 CALL dorgqr( p, p, m-q, u1, ldu1, dum1, work(1), -1,
445 lorgqrmin =
max( lorgqrmin, p )
446 lorgqropt =
max( lorgqropt, int( work(1) ) )
448 IF( wantu2 .AND. m-p .GT. 0 )
THEN
449 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1),
451 lorgqrmin =
max( lorgqrmin, m-p )
452 lorgqropt =
max( lorgqropt, int( work(1) ) )
454 IF( wantv1t .AND. q .GT. 0 )
THEN
455 CALL dorglq( q, q, q, v1t, ldv1t, dum1, work(1), -1,
457 lorglqmin =
max( lorglqmin, q )
458 lorglqopt =
max( lorglqopt, int( work(1) ) )
460 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
461 $ theta, dum1, u2, ldu2, u1, ldu1, dum2,
462 $ 1, v1t, ldv1t, dum1, dum1, dum1,
463 $ dum1, dum1, dum1, dum1,
464 $ dum1, work(1), -1, childinfo )
465 lbbcsd = int( work(1) )
467 lworkmin =
max( iorbdb+lorbdb-1,
468 $ iorgqr+lorgqrmin-1,
469 $ iorglq+lorglqmin-1,
471 lworkopt =
max( iorbdb+lorbdb-1,
472 $ iorgqr+lorgqropt-1,
473 $ iorglq+lorglqopt-1,
476 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
480 IF( info .NE. 0 )
THEN
481 CALL xerbla(
'DORCSD2BY1', -info )
483 ELSE IF( lquery )
THEN
486 lorgqr = lwork-iorgqr+1
487 lorglq = lwork-iorglq+1
498 CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
499 $ work(iphi), work(itaup1), work(itaup2),
500 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
504 IF( wantu1 .AND. p .GT. 0 )
THEN
505 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
506 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
507 $ lorgqr, childinfo )
509 IF( wantu2 .AND. m-p .GT. 0 )
THEN
510 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
511 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
512 $ work(iorgqr), lorgqr, childinfo )
514 IF( wantv1t .AND. q .GT. 0 )
THEN
520 CALL dlacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
522 CALL dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t, work(itauq1),
523 $ work(iorglq), lorglq, childinfo )
528 CALL dbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
530 $ dum2, 1, work(ib11d), work(ib11e),
531 $ work(ib12d), work(ib12e), work
532 $ work(ib21e), work(ib22d), work(ib22e),
533 $ work(ibbcsd), lbbcsd, childinfo )
538 IF( q .GT. 0 .AND. wantu2 )
THEN
540 iwork(i) = m - p - q + i
545 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
547 ELSE IF( r .EQ. p )
THEN
553 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
554 $ work(iphi), work(itaup1), work(itaup2),
555 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
559 IF( wantu1 .AND. p .GT. 0 )
THEN
565 CALL dlacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2), ldu1 )
566 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
567 $ work(iorgqr), lorgqr, childinfo )
569 IF( wantu2 .AND. m-p .GT. 0 )
THEN
570 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
571 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
572 $ work(iorgqr), lorgqr, childinfo )
574 IF( wantv1t .AND. q .GT. 0 )
THEN
575 CALL dlacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
576 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
577 $ work(iorglq), lorglq, childinfo )
582 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
583 $ work(iphi), v1t, ldv1t, dum2, 1, u1, ldu1, u2,
584 $ ldu2, work(ib11d), work(ib11e), work(ib12d),
585 $ work(ib12e), work(ib21d), work(ib21e),
586 $ work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,
592 IF( q .GT. 0 .AND. wantu2 )
THEN
594 iwork(i) = m - p - q + i
599 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
601 ELSE IF( r .EQ. m-p )
THEN
607 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
608 $ work(iphi), work(itaup1), work(itaup2),
609 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
613 IF( wantu1 .AND. p .GT. 0 )
THEN
614 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
615 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1), work(iorgqr),
616 $ lorgqr, childinfo )
618 IF( wantu2 .AND. m-p .GT. 0 )
THEN
624 CALL dlacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
626 CALL dorgqr( m-p-1, m-p-1, m-p
627 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
629 IF( wantv1t .AND. q .GT. 0 )
THEN
630 CALL dlacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
631 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
632 $ work(iorglq), lorglq, childinfo )
637 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
638 $ theta, work(iphi), dum2, 1, v1t, ldv1t, u2,
639 $ ldu2, u1, ldu1, work(ib11d), work(ib11e),
640 $ work(ib12d), work(ib12e), work(ib21d),
641 $ work(ib21e), work(ib22d), work(ib22e),
642 $ work(ibbcsd), lbbcsd, childinfo )
655 CALL dlapmt( .false., p, q, u1, ldu1, iwork )
658 CALL dlapmr( .false., q, q, v1t, ldv1t, iwork )
667 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
668 $ work(iphi), work(itaup1), work(itaup2),
669 $ work(itauq1), work(iorbdb), work(iorbdb+m),
670 $ lorbdb-m, childinfo )
674 IF( wantu2 .AND. m-p .GT. 0 )
THEN
675 CALL dcopy( m-p, work(iorbdb+p), 1, u2, 1 )
677 IF( wantu1 .AND. p .GT. 0 )
THEN
678 CALL dcopy( p, work(iorbdb), 1, u1, 1 )
682 CALL dlacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
684 CALL dorgqr( p, p, m-q, u1, ldu1, work(itaup1),
685 $ work(iorgqr), lorgqr, childinfo )
687 IF( wantu2 .AND. m-p .GT. 0 )
THEN
691 CALL dlacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
693 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
694 $ work(iorgqr), lorgqr, childinfo )
696 IF( wantv1t .AND. q .GT. 0 )
THEN
697 CALL dlacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
698 CALL dlacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1), ldx11,
699 $ v1t(m-q+1,m-q+1), ldv1t )
700 CALL dlacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
701 $ v1t(p+1,p+1), ldv1t )
702 CALL dorglq( q, q, q, v1t, ldv1t, work(itauq1),
703 $ work(iorglq), lorglq, childinfo )
708 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
709 $ theta, work(iphi), u2, ldu2, u1, ldu1, dum2,
710 $ 1, v1t, ldv1t, work(ib11d), work(ib11e),
711 $ work(ib12d), work(ib12e), work(ib21d),
712 $ work(ib21e), work(ib22d), work(ib22e),
713 $ work(ibbcsd), lbbcsd, childinfo )
726 CALL dlapmt( .false., p, p, u1, ldu1, iwork )
729 CALL dlapmr( .false., p, q, v1t, ldv1t, iwork )