230 $ X21, LDX21, THETA, U1, LDU1, U2, LDU2, V1T,
231 $ LDV1T, WORK, LWORK, IWORK, INFO )
238 CHARACTER JOBU1, JOBU2, JOBV1T
239 INTEGER INFO, LDU1, LDU2, LDV1T, LWORK, LDX11, LDX21,
243 DOUBLE PRECISION THETA(*)
244 DOUBLE PRECISION U1(LDU1,*), U2(LDU2,*), V1T(LDV1T,*), WORK(*),
245 $ X11(LDX11,*), X21(LDX21,*)
252 DOUBLE PRECISION ONE, ZERO
253 PARAMETER ( ONE = 1.0d0, zero = 0.0d0 )
256 INTEGER CHILDINFO, I, IB11D, IB11E, IB12D, IB12E,
257 $ IB21D, IB21E, IB22D, IB22E, IBBCSD, IORBDB,
258 $ IORGLQ, IORGQR, IPHI, ITAUP1, ITAUP2, ITAUQ1,
259 $ j, lbbcsd, lorbdb, lorglq, lorglqmin,
260 $ lorglqopt, lorgqr, lorgqrmin, lorgqropt,
261 $ lworkmin, lworkopt, r
262 LOGICAL LQUERY, WANTU1, WANTU2, WANTV1T
265 DOUBLE PRECISION DUM1(1), DUM2(1,1)
278 INTRINSIC int, max, min
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, theta,
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) ) )
361 IF( 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,
375 $ dum1, u1, ldu1, u2, ldu2, v1t, ldv1t,
376 $ dum2, 1, dum1, dum1, dum1,
377 $ dum1, dum1, dum1, dum1,
378 $ dum1, work(1), -1, childinfo )
379 lbbcsd = int( work(1) )
380 ELSE IF( r .EQ. p )
THEN
381 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
382 $ dum1, dum1, dum1, dum1,
383 $ work(1), -1, childinfo )
384 lorbdb = int( work(1) )
385 IF( wantu1 .AND. p .GT. 0 )
THEN
386 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, dum1,
387 $ work(1), -1, childinfo )
388 lorgqrmin = max( lorgqrmin, p-1 )
389 lorgqropt = max( lorgqropt, int( work(1) ) )
391 IF( wantu2 .AND. m-p .GT. 0 )
THEN
392 CALL dorgqr( m-p, m-p, q, u2, ldu2, dum1, work(1),
394 lorgqrmin = max( lorgqrmin, m-p )
395 lorgqropt = max( lorgqropt, int( work(1) ) )
397 IF( wantv1t .AND. q .GT. 0 )
THEN
398 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
400 lorglqmin = max( lorglqmin, q )
401 lorglqopt = max( lorglqopt, int( work(1) ) )
403 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p,
405 $ dum1, v1t, ldv1t, dum2, 1, u1, ldu1,
406 $ u2, ldu2, dum1, dum1, dum1,
407 $ dum1, dum1, dum1, dum1,
408 $ dum1, work(1), -1, childinfo )
409 lbbcsd = int( work(1) )
410 ELSE IF( r .EQ. m-p )
THEN
411 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
412 $ dum1, dum1, dum1, dum1,
413 $ work(1), -1, childinfo )
414 lorbdb = int( work(1) )
415 IF( wantu1 .AND. p .GT. 0 )
THEN
416 CALL dorgqr( p, p, q, u1, ldu1, dum1, work(1), -1,
418 lorgqrmin = max( lorgqrmin, p )
419 lorgqropt = max( lorgqropt, int( work(1) ) )
421 IF( wantu2 .AND. m-p .GT. 0 )
THEN
422 CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
423 $ dum1, work(1), -1, childinfo )
424 lorgqrmin = max( lorgqrmin, m-p-1 )
425 lorgqropt = max( lorgqropt, int( work(1) ) )
427 IF( wantv1t .AND. q .GT. 0 )
THEN
428 CALL dorglq( q, q, r, v1t, ldv1t, dum1, work(1), -1,
430 lorglqmin = max( lorglqmin, q )
431 lorglqopt = max( lorglqopt, int( work(1) ) )
433 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
434 $ theta, dum1, dum2, 1, v1t, ldv1t, u2,
435 $ ldu2, u1, ldu1, dum1, dum1, dum1,
436 $ dum1, dum1, dum1, dum1,
437 $ dum1, work(1), -1, childinfo )
438 lbbcsd = int( work(1) )
440 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
441 $ dum1, dum1, dum1, dum1,
442 $ dum1, work(1), -1, childinfo )
443 lorbdb = m + int( work(1) )
444 IF( wantu1 .AND. p .GT. 0 )
THEN
445 CALL dorgqr( p, p, m-q, u1, ldu1, dum1, work(1), -1,
447 lorgqrmin = max( lorgqrmin, p )
448 lorgqropt = max( lorgqropt, int( work(1) ) )
450 IF( wantu2 .AND. m-p .GT. 0 )
THEN
451 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, dum1, work(1),
453 lorgqrmin = max( lorgqrmin, m-p )
454 lorgqropt = max( lorgqropt, int( work(1) ) )
456 IF( wantv1t .AND. q .GT. 0 )
THEN
457 CALL dorglq( q, q, q, v1t, ldv1t, dum1, work(1), -1,
459 lorglqmin = max( lorglqmin, q )
460 lorglqopt = max( lorglqopt, int( work(1) ) )
462 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
463 $ theta, dum1, u2, ldu2, u1, ldu1, dum2,
464 $ 1, v1t, ldv1t, dum1, dum1, dum1,
465 $ dum1, dum1, dum1, dum1,
466 $ dum1, work(1), -1, childinfo )
467 lbbcsd = int( work(1) )
469 lworkmin = max( iorbdb+lorbdb-1,
470 $ iorgqr+lorgqrmin-1,
471 $ iorglq+lorglqmin-1,
473 lworkopt = max( iorbdb+lorbdb-1,
474 $ iorgqr+lorgqropt-1,
475 $ iorglq+lorglqopt-1,
478 IF( lwork .LT. lworkmin .AND. .NOT.lquery )
THEN
482 IF( info .NE. 0 )
THEN
483 CALL xerbla(
'DORCSD2BY1', -info )
485 ELSE IF( lquery )
THEN
488 lorgqr = lwork-iorgqr+1
489 lorglq = lwork-iorglq+1
500 CALL dorbdb1( m, p, q, x11, ldx11, x21, ldx21, theta,
501 $ work(iphi), work(itaup1), work(itaup2),
502 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
506 IF( wantu1 .AND. p .GT. 0 )
THEN
507 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
508 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1),
510 $ lorgqr, childinfo )
512 IF( wantu2 .AND. m-p .GT. 0 )
THEN
513 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
514 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
515 $ work(iorgqr), lorgqr, childinfo )
517 IF( wantv1t .AND. q .GT. 0 )
THEN
523 CALL dlacpy(
'U', q-1, q-1, x21(1,2), ldx21, v1t(2,2),
525 CALL dorglq( q-1, q-1, q-1, v1t(2,2), ldv1t,
527 $ work(iorglq), lorglq, childinfo )
532 CALL dbbcsd( jobu1, jobu2, jobv1t,
'N',
'N', m, p, q, theta,
533 $ work(iphi), u1, ldu1, u2, ldu2, v1t, ldv1t,
534 $ dum2, 1, work(ib11d), work(ib11e),
535 $ work(ib12d), work(ib12e), work(ib21d),
536 $ work(ib21e), work(ib22d), work(ib22e),
537 $ work(ibbcsd), lbbcsd, childinfo )
542 IF( q .GT. 0 .AND. wantu2 )
THEN
544 iwork(i) = m - p - q + i
549 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
551 ELSE IF( r .EQ. p )
THEN
557 CALL dorbdb2( m, p, q, x11, ldx11, x21, ldx21, theta,
558 $ work(iphi), work(itaup1), work(itaup2),
559 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
563 IF( wantu1 .AND. p .GT. 0 )
THEN
569 CALL dlacpy(
'L', p-1, p-1, x11(2,1), ldx11, u1(2,2),
571 CALL dorgqr( p-1, p-1, p-1, u1(2,2), ldu1, work(itaup1),
572 $ work(iorgqr), lorgqr, childinfo )
574 IF( wantu2 .AND. m-p .GT. 0 )
THEN
575 CALL dlacpy(
'L', m-p, q, x21, ldx21, u2, ldu2 )
576 CALL dorgqr( m-p, m-p, q, u2, ldu2, work(itaup2),
577 $ work(iorgqr), lorgqr, childinfo )
579 IF( wantv1t .AND. q .GT. 0 )
THEN
580 CALL dlacpy(
'U', p, q, x11, ldx11, v1t, ldv1t )
581 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
582 $ work(iorglq), lorglq, childinfo )
587 CALL dbbcsd( jobv1t,
'N', jobu1, jobu2,
'T', m, q, p, theta,
588 $ work(iphi), v1t, ldv1t, dum1, 1, u1, ldu1, u2,
589 $ ldu2, work(ib11d), work(ib11e), work(ib12d),
590 $ work(ib12e), work(ib21d), work(ib21e),
591 $ work(ib22d), work(ib22e), work(ibbcsd), lbbcsd,
597 IF( q .GT. 0 .AND. wantu2 )
THEN
599 iwork(i) = m - p - q + i
604 CALL dlapmt( .false., m-p, m-p, u2, ldu2, iwork )
606 ELSE IF( r .EQ. m-p )
THEN
612 CALL dorbdb3( m, p, q, x11, ldx11, x21, ldx21, theta,
613 $ work(iphi), work(itaup1), work(itaup2),
614 $ work(itauq1), work(iorbdb), lorbdb, childinfo )
618 IF( wantu1 .AND. p .GT. 0 )
THEN
619 CALL dlacpy(
'L', p, q, x11, ldx11, u1, ldu1 )
620 CALL dorgqr( p, p, q, u1, ldu1, work(itaup1),
622 $ lorgqr, childinfo )
624 IF( wantu2 .AND. m-p .GT. 0 )
THEN
630 CALL dlacpy(
'L', m-p-1, m-p-1, x21(2,1), ldx21, u2(2,2),
632 CALL dorgqr( m-p-1, m-p-1, m-p-1, u2(2,2), ldu2,
633 $ work(itaup2), work(iorgqr), lorgqr, childinfo )
635 IF( wantv1t .AND. q .GT. 0 )
THEN
636 CALL dlacpy(
'U', m-p, q, x21, ldx21, v1t, ldv1t )
637 CALL dorglq( q, q, r, v1t, ldv1t, work(itauq1),
638 $ work(iorglq), lorglq, childinfo )
643 CALL dbbcsd(
'N', jobv1t, jobu2, jobu1,
'T', m, m-q, m-p,
644 $ theta, work(iphi), dum1, 1, v1t, ldv1t, u2,
645 $ ldu2, u1, ldu1, work(ib11d), work(ib11e),
646 $ work(ib12d), work(ib12e), work(ib21d),
647 $ work(ib21e), work(ib22d), work(ib22e),
648 $ work(ibbcsd), lbbcsd, childinfo )
661 CALL dlapmt( .false., p, q, u1, ldu1, iwork )
664 CALL dlapmr( .false., q, q, v1t, ldv1t, iwork )
673 CALL dorbdb4( m, p, q, x11, ldx11, x21, ldx21, theta,
674 $ work(iphi), work(itaup1), work(itaup2),
675 $ work(itauq1), work(iorbdb), work(iorbdb+m),
676 $ lorbdb-m, childinfo )
680 IF( wantu2 .AND. m-p .GT. 0 )
THEN
681 CALL dcopy( m-p, work(iorbdb+p), 1, u2, 1 )
683 IF( wantu1 .AND. p .GT. 0 )
THEN
684 CALL dcopy( p, work(iorbdb), 1, u1, 1 )
688 CALL dlacpy(
'L', p-1, m-q-1, x11(2,1), ldx11, u1(2,2),
690 CALL dorgqr( p, p, m-q, u1, ldu1, work(itaup1),
691 $ work(iorgqr), lorgqr, childinfo )
693 IF( wantu2 .AND. m-p .GT. 0 )
THEN
697 CALL dlacpy(
'L', m-p-1, m-q-1, x21(2,1), ldx21, u2(2,2),
699 CALL dorgqr( m-p, m-p, m-q, u2, ldu2, work(itaup2),
700 $ work(iorgqr), lorgqr, childinfo )
702 IF( wantv1t .AND. q .GT. 0 )
THEN
703 CALL dlacpy(
'U', m-q, q, x21, ldx21, v1t, ldv1t )
704 CALL dlacpy(
'U', p-(m-q), q-(m-q), x11(m-q+1,m-q+1),
706 $ v1t(m-q+1,m-q+1), ldv1t )
707 CALL dlacpy(
'U', -p+q, q-p, x21(m-q+1,p+1), ldx21,
708 $ v1t(p+1,p+1), ldv1t )
709 CALL dorglq( q, q, q, v1t, ldv1t, work(itauq1),
710 $ work(iorglq), lorglq, childinfo )
715 CALL dbbcsd( jobu2, jobu1,
'N', jobv1t,
'N', m, m-p, m-q,
716 $ theta, work(iphi), u2, ldu2, u1, ldu1, dum1,
717 $ 1, v1t, ldv1t, work(ib11d), work(ib11e),
718 $ work(ib12d), work(ib12e), work(ib21d),
719 $ work(ib21e), work(ib22d), work(ib22e),
720 $ work(ibbcsd), lbbcsd, childinfo )
733 CALL dlapmt( .false., p, p, u1, ldu1, iwork )
736 CALL dlapmr( .false., p, q, v1t, ldv1t, iwork )