Esempio n. 1
0
/* Subroutine */ int zgrqts_(integer *m, integer *p, integer *n,
                             doublecomplex *a, doublecomplex *af, doublecomplex *q, doublecomplex *
                             r__, integer *lda, doublecomplex *taua, doublecomplex *b,
                             doublecomplex *bf, doublecomplex *z__, doublecomplex *t,
                             doublecomplex *bwk, integer *ldb, doublecomplex *taub, doublecomplex *
                             work, integer *lwork, doublereal *rwork, doublereal *result)
{
    /* System generated locals */
    integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, bf_dim1,
            bf_offset, bwk_dim1, bwk_offset, q_dim1, q_offset, r_dim1,
            r_offset, t_dim1, t_offset, z_dim1, z_offset, i__1, i__2;
    doublereal d__1;
    doublecomplex z__1;

    /* Local variables */
    static integer info;
    static doublereal unfl, resid, anorm, bnorm;
    extern /* Subroutine */ int zgemm_(char *, char *, integer *, integer *,
                                       integer *, doublecomplex *, doublecomplex *, integer *,
                                       doublecomplex *, integer *, doublecomplex *, doublecomplex *,
                                       integer *), zherk_(char *, char *, integer *,
                                               integer *, doublereal *, doublecomplex *, integer *, doublereal *,
                                               doublecomplex *, integer *);
    extern doublereal dlamch_(char *), zlange_(char *, integer *,
            integer *, doublecomplex *, integer *, doublereal *),
                    zlanhe_(char *, char *, integer *, doublecomplex *, integer *,
                            doublereal *);
    extern /* Subroutine */ int zggrqf_(integer *, integer *, integer *,
                                        doublecomplex *, integer *, doublecomplex *, doublecomplex *,
                                        integer *, doublecomplex *, doublecomplex *, integer *, integer *)
    , zlacpy_(char *, integer *, integer *, doublecomplex *, integer *
              , doublecomplex *, integer *), zlaset_(char *, integer *,
                      integer *, doublecomplex *, doublecomplex *, doublecomplex *,
                      integer *), zungqr_(integer *, integer *, integer *,
                                          doublecomplex *, integer *, doublecomplex *, doublecomplex *,
                                          integer *, integer *), zungrq_(integer *, integer *, integer *,
                                                  doublecomplex *, integer *, doublecomplex *, doublecomplex *,
                                                  integer *, integer *);
    static doublereal ulp;


#define q_subscr(a_1,a_2) (a_2)*q_dim1 + a_1
#define q_ref(a_1,a_2) q[q_subscr(a_1,a_2)]
#define r___subscr(a_1,a_2) (a_2)*r_dim1 + a_1
#define r___ref(a_1,a_2) r__[r___subscr(a_1,a_2)]
#define z___subscr(a_1,a_2) (a_2)*z_dim1 + a_1
#define z___ref(a_1,a_2) z__[z___subscr(a_1,a_2)]
#define af_subscr(a_1,a_2) (a_2)*af_dim1 + a_1
#define af_ref(a_1,a_2) af[af_subscr(a_1,a_2)]
#define bf_subscr(a_1,a_2) (a_2)*bf_dim1 + a_1
#define bf_ref(a_1,a_2) bf[bf_subscr(a_1,a_2)]


    /*  -- LAPACK test routine (version 3.0) --
           Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
           Courant Institute, Argonne National Lab, and Rice University
           September 30, 1994


        Purpose
        =======

        ZGRQTS tests ZGGRQF, which computes the GRQ factorization of an
        M-by-N matrix A and a P-by-N matrix B: A = R*Q and B = Z*T*Q.

        Arguments
        =========

        M       (input) INTEGER
                The number of rows of the matrix A.  M >= 0.

        P       (input) INTEGER
                The number of rows of the matrix B.  P >= 0.

        N       (input) INTEGER
                The number of columns of the matrices A and B.  N >= 0.

        A       (input) COMPLEX*16 array, dimension (LDA,N)
                The M-by-N matrix A.

        AF      (output) COMPLEX*16 array, dimension (LDA,N)
                Details of the GRQ factorization of A and B, as returned
                by ZGGRQF, see CGGRQF for further details.

        Q       (output) COMPLEX*16 array, dimension (LDA,N)
                The N-by-N unitary matrix Q.

        R       (workspace) COMPLEX*16 array, dimension (LDA,MAX(M,N))

        LDA     (input) INTEGER
                The leading dimension of the arrays A, AF, R and Q.
                LDA >= max(M,N).

        TAUA    (output) COMPLEX*16 array, dimension (min(M,N))
                The scalar factors of the elementary reflectors, as returned
                by DGGQRC.

        B       (input) COMPLEX*16 array, dimension (LDB,N)
                On entry, the P-by-N matrix A.

        BF      (output) COMPLEX*16 array, dimension (LDB,N)
                Details of the GQR factorization of A and B, as returned
                by ZGGRQF, see CGGRQF for further details.

        Z       (output) DOUBLE PRECISION array, dimension (LDB,P)
                The P-by-P unitary matrix Z.

        T       (workspace) COMPLEX*16 array, dimension (LDB,max(P,N))

        BWK     (workspace) COMPLEX*16 array, dimension (LDB,N)

        LDB     (input) INTEGER
                The leading dimension of the arrays B, BF, Z and T.
                LDB >= max(P,N).

        TAUB    (output) COMPLEX*16 array, dimension (min(P,N))
                The scalar factors of the elementary reflectors, as returned
                by DGGRQF.

        WORK    (workspace) COMPLEX*16 array, dimension (LWORK)

        LWORK   (input) INTEGER
                The dimension of the array WORK, LWORK >= max(M,P,N)**2.

        RWORK   (workspace) DOUBLE PRECISION array, dimension (M)

        RESULT  (output) DOUBLE PRECISION array, dimension (4)
                The test ratios:
                  RESULT(1) = norm( R - A*Q' ) / ( MAX(M,N)*norm(A)*ULP)
                  RESULT(2) = norm( T*Q - Z'*B ) / (MAX(P,N)*norm(B)*ULP)
                  RESULT(3) = norm( I - Q'*Q ) / ( N*ULP )
                  RESULT(4) = norm( I - Z'*Z ) / ( P*ULP )

        =====================================================================


           Parameter adjustments */
    r_dim1 = *lda;
    r_offset = 1 + r_dim1 * 1;
    r__ -= r_offset;
    q_dim1 = *lda;
    q_offset = 1 + q_dim1 * 1;
    q -= q_offset;
    af_dim1 = *lda;
    af_offset = 1 + af_dim1 * 1;
    af -= af_offset;
    a_dim1 = *lda;
    a_offset = 1 + a_dim1 * 1;
    a -= a_offset;
    --taua;
    bwk_dim1 = *ldb;
    bwk_offset = 1 + bwk_dim1 * 1;
    bwk -= bwk_offset;
    t_dim1 = *ldb;
    t_offset = 1 + t_dim1 * 1;
    t -= t_offset;
    z_dim1 = *ldb;
    z_offset = 1 + z_dim1 * 1;
    z__ -= z_offset;
    bf_dim1 = *ldb;
    bf_offset = 1 + bf_dim1 * 1;
    bf -= bf_offset;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1 * 1;
    b -= b_offset;
    --taub;
    --work;
    --rwork;
    --result;

    /* Function Body */
    ulp = dlamch_("Precision");
    unfl = dlamch_("Safe minimum");

    /*     Copy the matrix A to the array AF. */

    zlacpy_("Full", m, n, &a[a_offset], lda, &af[af_offset], lda);
    zlacpy_("Full", p, n, &b[b_offset], ldb, &bf[bf_offset], ldb);

    /* Computing MAX */
    d__1 = zlange_("1", m, n, &a[a_offset], lda, &rwork[1]);
    anorm = max(d__1,unfl);
    /* Computing MAX */
    d__1 = zlange_("1", p, n, &b[b_offset], ldb, &rwork[1]);
    bnorm = max(d__1,unfl);

    /*     Factorize the matrices A and B in the arrays AF and BF. */

    zggrqf_(m, p, n, &af[af_offset], lda, &taua[1], &bf[bf_offset], ldb, &
            taub[1], &work[1], lwork, &info);

    /*     Generate the N-by-N matrix Q */

    zlaset_("Full", n, n, &c_b3, &c_b3, &q[q_offset], lda);
    if (*m <= *n) {
        if (*m > 0 && *m < *n) {
            i__1 = *n - *m;
            zlacpy_("Full", m, &i__1, &af[af_offset], lda, &q_ref(*n - *m + 1,
                    1), lda);
        }
        if (*m > 1) {
            i__1 = *m - 1;
            i__2 = *m - 1;
            zlacpy_("Lower", &i__1, &i__2, &af_ref(2, *n - *m + 1), lda, &
                    q_ref(*n - *m + 2, *n - *m + 1), lda);
        }
    } else {
        if (*n > 1) {
            i__1 = *n - 1;
            i__2 = *n - 1;
            zlacpy_("Lower", &i__1, &i__2, &af_ref(*m - *n + 2, 1), lda, &
                    q_ref(2, 1), lda);
        }
    }
    i__1 = min(*m,*n);
    zungrq_(n, n, &i__1, &q[q_offset], lda, &taua[1], &work[1], lwork, &info);

    /*     Generate the P-by-P matrix Z */

    zlaset_("Full", p, p, &c_b3, &c_b3, &z__[z_offset], ldb);
    if (*p > 1) {
        i__1 = *p - 1;
        zlacpy_("Lower", &i__1, n, &bf_ref(2, 1), ldb, &z___ref(2, 1), ldb);
    }
    i__1 = min(*p,*n);
    zungqr_(p, p, &i__1, &z__[z_offset], ldb, &taub[1], &work[1], lwork, &
            info);

    /*     Copy R */

    zlaset_("Full", m, n, &c_b1, &c_b1, &r__[r_offset], lda);
    if (*m <= *n) {
        zlacpy_("Upper", m, m, &af_ref(1, *n - *m + 1), lda, &r___ref(1, *n -
                *m + 1), lda);
    } else {
        i__1 = *m - *n;
        zlacpy_("Full", &i__1, n, &af[af_offset], lda, &r__[r_offset], lda);
        zlacpy_("Upper", n, n, &af_ref(*m - *n + 1, 1), lda, &r___ref(*m - *n
                + 1, 1), lda);
    }

    /*     Copy T */

    zlaset_("Full", p, n, &c_b1, &c_b1, &t[t_offset], ldb);
    zlacpy_("Upper", p, n, &bf[bf_offset], ldb, &t[t_offset], ldb);

    /*     Compute R - A*Q' */

    z__1.r = -1., z__1.i = 0.;
    zgemm_("No transpose", "Conjugate transpose", m, n, n, &z__1, &a[a_offset]
           , lda, &q[q_offset], lda, &c_b2, &r__[r_offset], lda);

    /*     Compute norm( R - A*Q' ) / ( MAX(M,N)*norm(A)*ULP ) . */

    resid = zlange_("1", m, n, &r__[r_offset], lda, &rwork[1]);
    if (anorm > 0.) {
        /* Computing MAX */
        i__1 = max(1,*m);
        result[1] = resid / (doublereal) max(i__1,*n) / anorm / ulp;
    } else {
        result[1] = 0.;
    }

    /*     Compute T*Q - Z'*B */

    zgemm_("Conjugate transpose", "No transpose", p, n, p, &c_b2, &z__[
               z_offset], ldb, &b[b_offset], ldb, &c_b1, &bwk[bwk_offset], ldb);
    z__1.r = -1., z__1.i = 0.;
    zgemm_("No transpose", "No transpose", p, n, n, &c_b2, &t[t_offset], ldb,
           &q[q_offset], lda, &z__1, &bwk[bwk_offset], ldb);

    /*     Compute norm( T*Q - Z'*B ) / ( MAX(P,N)*norm(A)*ULP ) . */

    resid = zlange_("1", p, n, &bwk[bwk_offset], ldb, &rwork[1]);
    if (bnorm > 0.) {
        /* Computing MAX */
        i__1 = max(1,*p);
        result[2] = resid / (doublereal) max(i__1,*m) / bnorm / ulp;
    } else {
        result[2] = 0.;
    }

    /*     Compute I - Q*Q' */

    zlaset_("Full", n, n, &c_b1, &c_b2, &r__[r_offset], lda);
    zherk_("Upper", "No Transpose", n, n, &c_b34, &q[q_offset], lda, &c_b35, &
           r__[r_offset], lda);

    /*     Compute norm( I - Q'*Q ) / ( N * ULP ) . */

    resid = zlanhe_("1", "Upper", n, &r__[r_offset], lda, &rwork[1]);
    result[3] = resid / (doublereal) max(1,*n) / ulp;

    /*     Compute I - Z'*Z */

    zlaset_("Full", p, p, &c_b1, &c_b2, &t[t_offset], ldb);
    zherk_("Upper", "Conjugate transpose", p, p, &c_b34, &z__[z_offset], ldb,
           &c_b35, &t[t_offset], ldb);

    /*     Compute norm( I - Z'*Z ) / ( P*ULP ) . */

    resid = zlanhe_("1", "Upper", p, &t[t_offset], ldb, &rwork[1]);
    result[4] = resid / (doublereal) max(1,*p) / ulp;

    return 0;

    /*     End of ZGRQTS */

} /* zgrqts_ */
Esempio n. 2
0
/* Subroutine */ int zgglse_(integer *m, integer *n, integer *p, 
	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
	doublecomplex *c__, doublecomplex *d__, doublecomplex *x, 
	doublecomplex *work, integer *lwork, integer *info)
{
/*  -- LAPACK driver routine (version 3.0) --   
       Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,   
       Courant Institute, Argonne National Lab, and Rice University   
       June 30, 1999   


    Purpose   
    =======   

    ZGGLSE solves the linear equality-constrained least squares (LSE)   
    problem:   

            minimize || c - A*x ||_2   subject to   B*x = d   

    where A is an M-by-N matrix, B is a P-by-N matrix, c is a given   
    M-vector, and d is a given P-vector. It is assumed that   
    P <= N <= M+P, and   

             rank(B) = P and  rank( ( A ) ) = N.   
                                  ( ( B ) )   

    These conditions ensure that the LSE problem has a unique solution,   
    which is obtained using a GRQ factorization of the matrices B and A.   

    Arguments   
    =========   

    M       (input) INTEGER   
            The number of rows of the matrix A.  M >= 0.   

    N       (input) INTEGER   
            The number of columns of the matrices A and B. N >= 0.   

    P       (input) INTEGER   
            The number of rows of the matrix B. 0 <= P <= N <= M+P.   

    A       (input/output) COMPLEX*16 array, dimension (LDA,N)   
            On entry, the M-by-N matrix A.   
            On exit, A is destroyed.   

    LDA     (input) INTEGER   
            The leading dimension of the array A. LDA >= max(1,M).   

    B       (input/output) COMPLEX*16 array, dimension (LDB,N)   
            On entry, the P-by-N matrix B.   
            On exit, B is destroyed.   

    LDB     (input) INTEGER   
            The leading dimension of the array B. LDB >= max(1,P).   

    C       (input/output) COMPLEX*16 array, dimension (M)   
            On entry, C contains the right hand side vector for the   
            least squares part of the LSE problem.   
            On exit, the residual sum of squares for the solution   
            is given by the sum of squares of elements N-P+1 to M of   
            vector C.   

    D       (input/output) COMPLEX*16 array, dimension (P)   
            On entry, D contains the right hand side vector for the   
            constrained equation.   
            On exit, D is destroyed.   

    X       (output) COMPLEX*16 array, dimension (N)   
            On exit, X is the solution of the LSE problem.   

    WORK    (workspace/output) COMPLEX*16 array, dimension (LWORK)   
            On exit, if INFO = 0, WORK(1) returns the optimal LWORK.   

    LWORK   (input) INTEGER   
            The dimension of the array WORK. LWORK >= max(1,M+N+P).   
            For optimum performance LWORK >= P+min(M,N)+max(M,N)*NB,   
            where NB is an upper bound for the optimal blocksizes for   
            ZGEQRF, CGERQF, ZUNMQR and CUNMRQ.   

            If LWORK = -1, then a workspace query is assumed; the routine   
            only calculates the optimal size of the WORK array, returns   
            this value as the first entry of the WORK array, and no error   
            message related to LWORK is issued by XERBLA.   

    INFO    (output) INTEGER   
            = 0:  successful exit.   
            < 0:  if INFO = -i, the i-th argument had an illegal value.   

    =====================================================================   


       Test the input parameters   

       Parameter adjustments */
    /* Table of constant values */
    static doublecomplex c_b1 = {1.,0.};
    static integer c__1 = 1;
    static integer c_n1 = -1;
    
    /* System generated locals */
    integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3, i__4;
    doublecomplex z__1;
    /* Local variables */
    static integer lopt;
    extern /* Subroutine */ int zgemv_(char *, integer *, integer *, 
	    doublecomplex *, doublecomplex *, integer *, doublecomplex *, 
	    integer *, doublecomplex *, doublecomplex *, integer *), 
	    zcopy_(integer *, doublecomplex *, integer *, doublecomplex *, 
	    integer *), zaxpy_(integer *, doublecomplex *, doublecomplex *, 
	    integer *, doublecomplex *, integer *), ztrmv_(char *, char *, 
	    char *, integer *, doublecomplex *, integer *, doublecomplex *, 
	    integer *), ztrsv_(char *, char *, char *,
	     integer *, doublecomplex *, integer *, doublecomplex *, integer *
	    );
    static integer nb, mn, nr;
    extern /* Subroutine */ int xerbla_(char *, integer *);
    extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
	    integer *, integer *, ftnlen, ftnlen);
    extern /* Subroutine */ int zggrqf_(integer *, integer *, integer *, 
	    doublecomplex *, integer *, doublecomplex *, doublecomplex *, 
	    integer *, doublecomplex *, doublecomplex *, integer *, integer *)
	    ;
    static integer nb1, nb2, nb3, nb4, lwkopt;
    static logical lquery;
    extern /* Subroutine */ int zunmqr_(char *, char *, integer *, integer *, 
	    integer *, doublecomplex *, integer *, doublecomplex *, 
	    doublecomplex *, integer *, doublecomplex *, integer *, integer *), zunmrq_(char *, char *, integer *, integer *, 
	    integer *, doublecomplex *, integer *, doublecomplex *, 
	    doublecomplex *, integer *, doublecomplex *, integer *, integer *);
#define a_subscr(a_1,a_2) (a_2)*a_dim1 + a_1
#define a_ref(a_1,a_2) a[a_subscr(a_1,a_2)]
#define b_subscr(a_1,a_2) (a_2)*b_dim1 + a_1
#define b_ref(a_1,a_2) b[b_subscr(a_1,a_2)]


    a_dim1 = *lda;
    a_offset = 1 + a_dim1 * 1;
    a -= a_offset;
    b_dim1 = *ldb;
    b_offset = 1 + b_dim1 * 1;
    b -= b_offset;
    --c__;
    --d__;
    --x;
    --work;

    /* Function Body */
    *info = 0;
    mn = min(*m,*n);
    nb1 = ilaenv_(&c__1, "ZGEQRF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (
	    ftnlen)1);
    nb2 = ilaenv_(&c__1, "ZGERQF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (
	    ftnlen)1);
    nb3 = ilaenv_(&c__1, "ZUNMQR", " ", m, n, p, &c_n1, (ftnlen)6, (ftnlen)1);
    nb4 = ilaenv_(&c__1, "ZUNMRQ", " ", m, n, p, &c_n1, (ftnlen)6, (ftnlen)1);
/* Computing MAX */
    i__1 = max(nb1,nb2), i__1 = max(i__1,nb3);
    nb = max(i__1,nb4);
    lwkopt = *p + mn + max(*m,*n) * nb;
    work[1].r = (doublereal) lwkopt, work[1].i = 0.;
    lquery = *lwork == -1;
    if (*m < 0) {
	*info = -1;
    } else if (*n < 0) {
	*info = -2;
    } else if (*p < 0 || *p > *n || *p < *n - *m) {
	*info = -3;
    } else if (*lda < max(1,*m)) {
	*info = -5;
    } else if (*ldb < max(1,*p)) {
	*info = -7;
    } else /* if(complicated condition) */ {
/* Computing MAX */
	i__1 = 1, i__2 = *m + *n + *p;
	if (*lwork < max(i__1,i__2) && ! lquery) {
	    *info = -12;
	}
    }
    if (*info != 0) {
	i__1 = -(*info);
	xerbla_("ZGGLSE", &i__1);
	return 0;
    } else if (lquery) {
	return 0;
    }

/*     Quick return if possible */

    if (*n == 0) {
	return 0;
    }

/*     Compute the GRQ factorization of matrices B and A:   

              B*Q' = (  0  T12 ) P   Z'*A*Q' = ( R11 R12 ) N-P   
                       N-P  P                  (  0  R22 ) M+P-N   
                                                 N-P  P   

       where T12 and R11 are upper triangular, and Q and Z are   
       unitary. */

    i__1 = *lwork - *p - mn;
    zggrqf_(p, m, n, &b[b_offset], ldb, &work[1], &a[a_offset], lda, &work[*p 
	    + 1], &work[*p + mn + 1], &i__1, info);
    i__1 = *p + mn + 1;
    lopt = (integer) work[i__1].r;

/*     Update c = Z'*c = ( c1 ) N-P   
                         ( c2 ) M+P-N */

    i__1 = max(1,*m);
    i__2 = *lwork - *p - mn;
    zunmqr_("Left", "Conjugate Transpose", m, &c__1, &mn, &a[a_offset], lda, &
	    work[*p + 1], &c__[1], &i__1, &work[*p + mn + 1], &i__2, info);
/* Computing MAX */
    i__3 = *p + mn + 1;
    i__1 = lopt, i__2 = (integer) work[i__3].r;
    lopt = max(i__1,i__2);

/*     Solve T12*x2 = d for x2 */

    ztrsv_("Upper", "No transpose", "Non unit", p, &b_ref(1, *n - *p + 1), 
	    ldb, &d__[1], &c__1);

/*     Update c1 */

    i__1 = *n - *p;
    z__1.r = -1., z__1.i = 0.;
    zgemv_("No transpose", &i__1, p, &z__1, &a_ref(1, *n - *p + 1), lda, &d__[
	    1], &c__1, &c_b1, &c__[1], &c__1);

/*     Sovle R11*x1 = c1 for x1 */

    i__1 = *n - *p;
    ztrsv_("Upper", "No transpose", "Non unit", &i__1, &a[a_offset], lda, &
	    c__[1], &c__1);

/*     Put the solutions in X */

    i__1 = *n - *p;
    zcopy_(&i__1, &c__[1], &c__1, &x[1], &c__1);
    zcopy_(p, &d__[1], &c__1, &x[*n - *p + 1], &c__1);

/*     Compute the residual vector: */

    if (*m < *n) {
	nr = *m + *p - *n;
	i__1 = *n - *m;
	z__1.r = -1., z__1.i = 0.;
	zgemv_("No transpose", &nr, &i__1, &z__1, &a_ref(*n - *p + 1, *m + 1),
		 lda, &d__[nr + 1], &c__1, &c_b1, &c__[*n - *p + 1], &c__1);
    } else {
	nr = *p;
    }
    ztrmv_("Upper", "No transpose", "Non unit", &nr, &a_ref(*n - *p + 1, *n - 
	    *p + 1), lda, &d__[1], &c__1);
    z__1.r = -1., z__1.i = 0.;
    zaxpy_(&nr, &z__1, &d__[1], &c__1, &c__[*n - *p + 1], &c__1);

/*     Backward transformation x = Q'*x */

    i__1 = *lwork - *p - mn;
    zunmrq_("Left", "Conjugate Transpose", n, &c__1, p, &b[b_offset], ldb, &
	    work[1], &x[1], n, &work[*p + mn + 1], &i__1, info);
/* Computing MAX */
    i__4 = *p + mn + 1;
    i__2 = lopt, i__3 = (integer) work[i__4].r;
    i__1 = *p + mn + max(i__2,i__3);
    work[1].r = (doublereal) i__1, work[1].i = 0.;

    return 0;

/*     End of ZGGLSE */

} /* zgglse_ */