#include "blaswrap.h" /* sgsvts.f -- translated by f2c (version 20061008). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" /* Table of constant values */ static real c_b17 = 1.f; static real c_b18 = 0.f; static real c_b44 = -1.f; static integer c__1 = 1; /* Subroutine */ int sgsvts_(integer *m, integer *p, integer *n, real *a, real *af, integer *lda, real *b, real *bf, integer *ldb, real *u, integer *ldu, real *v, integer *ldv, real *q, integer *ldq, real * alpha, real *beta, real *r__, integer *ldr, integer *iwork, real * work, integer *lwork, real *rwork, real *result) { /* System generated locals */ integer a_dim1, a_offset, af_dim1, af_offset, b_dim1, b_offset, bf_dim1, bf_offset, q_dim1, q_offset, r_dim1, r_offset, u_dim1, u_offset, v_dim1, v_offset, i__1, i__2; real r__1; /* Local variables */ static integer i__, j, k, l; static real ulp; static integer info; static real unfl, temp, resid; extern /* Subroutine */ int sgemm_(char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *); static real anorm, bnorm; extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, integer *), ssyrk_(char *, char *, integer *, integer *, real *, real *, integer *, real *, real *, integer *); extern doublereal slamch_(char *), slange_(char *, integer *, integer *, real *, integer *, real *); extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), sggsvd_( char *, char *, char *, integer *, integer *, integer *, integer * , integer *, real *, integer *, real *, integer *, real *, real *, real *, integer *, real *, integer *, real *, integer *, real *, integer *, integer *); extern doublereal slansy_(char *, char *, integer *, real *, integer *, real *); static real ulpinv; /* -- LAPACK test routine (version 3.1) -- Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. November 2006 Purpose ======= SGSVTS tests SGGSVD, which computes the GSVD of an M-by-N matrix A and a P-by-N matrix B: U'*A*Q = D1*R and V'*B*Q = D2*R. 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) REAL array, dimension (LDA,M) The M-by-N matrix A. AF (output) REAL array, dimension (LDA,N) Details of the GSVD of A and B, as returned by SGGSVD, see SGGSVD for further details. LDA (input) INTEGER The leading dimension of the arrays A and AF. LDA >= max( 1,M ). B (input) REAL array, dimension (LDB,P) On entry, the P-by-N matrix B. BF (output) REAL array, dimension (LDB,N) Details of the GSVD of A and B, as returned by SGGSVD, see SGGSVD for further details. LDB (input) INTEGER The leading dimension of the arrays B and BF. LDB >= max(1,P). U (output) REAL array, dimension(LDU,M) The M by M orthogonal matrix U. LDU (input) INTEGER The leading dimension of the array U. LDU >= max(1,M). V (output) REAL array, dimension(LDV,M) The P by P orthogonal matrix V. LDV (input) INTEGER The leading dimension of the array V. LDV >= max(1,P). Q (output) REAL array, dimension(LDQ,N) The N by N orthogonal matrix Q. LDQ (input) INTEGER The leading dimension of the array Q. LDQ >= max(1,N). ALPHA (output) REAL array, dimension (N) BETA (output) REAL array, dimension (N) The generalized singular value pairs of A and B, the ``diagonal'' matrices D1 and D2 are constructed from ALPHA and BETA, see subroutine SGGSVD for details. R (output) REAL array, dimension(LDQ,N) The upper triangular matrix R. LDR (input) INTEGER The leading dimension of the array R. LDR >= max(1,N). IWORK (workspace) INTEGER array, dimension (N) WORK (workspace) REAL array, dimension (LWORK) LWORK (input) INTEGER The dimension of the array WORK, LWORK >= max(M,P,N)*max(M,P,N). RWORK (workspace) REAL array, dimension (max(M,P,N)) RESULT (output) REAL array, dimension (6) The test ratios: RESULT(1) = norm( U'*A*Q - D1*R ) / ( MAX(M,N)*norm(A)*ULP) RESULT(2) = norm( V'*B*Q - D2*R ) / ( MAX(P,N)*norm(B)*ULP) RESULT(3) = norm( I - U'*U ) / ( M*ULP ) RESULT(4) = norm( I - V'*V ) / ( P*ULP ) RESULT(5) = norm( I - Q'*Q ) / ( N*ULP ) RESULT(6) = 0 if ALPHA is in decreasing order; = ULPINV otherwise. ===================================================================== Parameter adjustments */ af_dim1 = *lda; af_offset = 1 + af_dim1; af -= af_offset; a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; bf_dim1 = *ldb; bf_offset = 1 + bf_dim1; bf -= bf_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; u_dim1 = *ldu; u_offset = 1 + u_dim1; u -= u_offset; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; q_dim1 = *ldq; q_offset = 1 + q_dim1; q -= q_offset; --alpha; --beta; r_dim1 = *ldr; r_offset = 1 + r_dim1; r__ -= r_offset; --iwork; --work; --rwork; --result; /* Function Body */ ulp = slamch_("Precision"); ulpinv = 1.f / ulp; unfl = slamch_("Safe minimum"); /* Copy the matrix A to the array AF. */ slacpy_("Full", m, n, &a[a_offset], lda, &af[af_offset], lda); slacpy_("Full", p, n, &b[b_offset], ldb, &bf[bf_offset], ldb); /* Computing MAX */ r__1 = slange_("1", m, n, &a[a_offset], lda, &rwork[1]); anorm = dmax(r__1,unfl); /* Computing MAX */ r__1 = slange_("1", p, n, &b[b_offset], ldb, &rwork[1]); bnorm = dmax(r__1,unfl); /* Factorize the matrices A and B in the arrays AF and BF. */ sggsvd_("U", "V", "Q", m, n, p, &k, &l, &af[af_offset], lda, &bf[ bf_offset], ldb, &alpha[1], &beta[1], &u[u_offset], ldu, &v[ v_offset], ldv, &q[q_offset], ldq, &work[1], &iwork[1], &info); /* Copy R Computing MIN */ i__2 = k + l; i__1 = min(i__2,*m); for (i__ = 1; i__ <= i__1; ++i__) { i__2 = k + l; for (j = i__; j <= i__2; ++j) { r__[i__ + j * r_dim1] = af[i__ + (*n - k - l + j) * af_dim1]; /* L10: */ } /* L20: */ } if (*m - k - l < 0) { i__1 = k + l; for (i__ = *m + 1; i__ <= i__1; ++i__) { i__2 = k + l; for (j = i__; j <= i__2; ++j) { r__[i__ + j * r_dim1] = bf[i__ - k + (*n - k - l + j) * bf_dim1]; /* L30: */ } /* L40: */ } } /* Compute A:= U'*A*Q - D1*R */ sgemm_("No transpose", "No transpose", m, n, n, &c_b17, &a[a_offset], lda, &q[q_offset], ldq, &c_b18, &work[1], lda) ; sgemm_("Transpose", "No transpose", m, n, m, &c_b17, &u[u_offset], ldu, & work[1], lda, &c_b18, &a[a_offset], lda); i__1 = k; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = k + l; for (j = i__; j <= i__2; ++j) { a[i__ + (*n - k - l + j) * a_dim1] -= r__[i__ + j * r_dim1]; /* L50: */ } /* L60: */ } /* Computing MIN */ i__2 = k + l; i__1 = min(i__2,*m); for (i__ = k + 1; i__ <= i__1; ++i__) { i__2 = k + l; for (j = i__; j <= i__2; ++j) { a[i__ + (*n - k - l + j) * a_dim1] -= alpha[i__] * r__[i__ + j * r_dim1]; /* L70: */ } /* L80: */ } /* Compute norm( U'*A*Q - D1*R ) / ( MAX(1,M,N)*norm(A)*ULP ) . */ resid = slange_("1", m, n, &a[a_offset], lda, &rwork[1]); if (anorm > 0.f) { /* Computing MAX */ i__1 = max(1,*m); result[1] = resid / (real) max(i__1,*n) / anorm / ulp; } else { result[1] = 0.f; } /* Compute B := V'*B*Q - D2*R */ sgemm_("No transpose", "No transpose", p, n, n, &c_b17, &b[b_offset], ldb, &q[q_offset], ldq, &c_b18, &work[1], ldb) ; sgemm_("Transpose", "No transpose", p, n, p, &c_b17, &v[v_offset], ldv, & work[1], ldb, &c_b18, &b[b_offset], ldb); i__1 = l; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = l; for (j = i__; j <= i__2; ++j) { b[i__ + (*n - l + j) * b_dim1] -= beta[k + i__] * r__[k + i__ + ( k + j) * r_dim1]; /* L90: */ } /* L100: */ } /* Compute norm( V'*B*Q - D2*R ) / ( MAX(P,N)*norm(B)*ULP ) . */ resid = slange_("1", p, n, &b[b_offset], ldb, &rwork[1]); if (bnorm > 0.f) { /* Computing MAX */ i__1 = max(1,*p); result[2] = resid / (real) max(i__1,*n) / bnorm / ulp; } else { result[2] = 0.f; } /* Compute I - U'*U */ slaset_("Full", m, m, &c_b18, &c_b17, &work[1], ldq); ssyrk_("Upper", "Transpose", m, m, &c_b44, &u[u_offset], ldu, &c_b17, & work[1], ldu); /* Compute norm( I - U'*U ) / ( M * ULP ) . */ resid = slansy_("1", "Upper", m, &work[1], ldu, &rwork[1]); result[3] = resid / (real) max(1,*m) / ulp; /* Compute I - V'*V */ slaset_("Full", p, p, &c_b18, &c_b17, &work[1], ldv); ssyrk_("Upper", "Transpose", p, p, &c_b44, &v[v_offset], ldv, &c_b17, & work[1], ldv); /* Compute norm( I - V'*V ) / ( P * ULP ) . */ resid = slansy_("1", "Upper", p, &work[1], ldv, &rwork[1]); result[4] = resid / (real) max(1,*p) / ulp; /* Compute I - Q'*Q */ slaset_("Full", n, n, &c_b18, &c_b17, &work[1], ldq); ssyrk_("Upper", "Transpose", n, n, &c_b44, &q[q_offset], ldq, &c_b17, & work[1], ldq); /* Compute norm( I - Q'*Q ) / ( N * ULP ) . */ resid = slansy_("1", "Upper", n, &work[1], ldq, &rwork[1]); result[5] = resid / (real) max(1,*n) / ulp; /* Check sorting */ scopy_(n, &alpha[1], &c__1, &work[1], &c__1); /* Computing MIN */ i__2 = k + l; i__1 = min(i__2,*m); for (i__ = k + 1; i__ <= i__1; ++i__) { j = iwork[i__]; if (i__ != j) { temp = work[i__]; work[i__] = work[j]; work[j] = temp; } /* L110: */ } result[6] = 0.f; /* Computing MIN */ i__2 = k + l; i__1 = min(i__2,*m) - 1; for (i__ = k + 1; i__ <= i__1; ++i__) { if (work[i__] < work[i__ + 1]) { result[6] = ulpinv; } /* L120: */ } return 0; /* End of SGSVTS */ } /* sgsvts_ */