📄 sggsvd.c
字号:
/* dimension (max(3*N,M,P)+N) */
/* IWORK (workspace/output) INTEGER array, dimension (N) */
/* On exit, IWORK stores the sorting information. More */
/* precisely, the following loop will sort ALPHA */
/* for I = K+1, min(M,K+L) */
/* swap ALPHA(I) and ALPHA(IWORK(I)) */
/* endfor */
/* such that ALPHA(1) >= ALPHA(2) >= ... >= ALPHA(N). */
/* INFO (output)INTEGER */
/* = 0: successful exit */
/* < 0: if INFO = -i, the i-th argument had an illegal value. */
/* > 0: if INFO = 1, the Jacobi-type procedure failed to */
/* converge. For further details, see subroutine STGSJA. */
/* Internal Parameters */
/* =================== */
/* TOLA REAL */
/* TOLB REAL */
/* TOLA and TOLB are the thresholds to determine the effective */
/* rank of (A',B')'. Generally, they are set to */
/* TOLA = MAX(M,N)*norm(A)*MACHEPS, */
/* TOLB = MAX(P,N)*norm(B)*MACHEPS. */
/* The size of TOLA and TOLB may affect the size of backward */
/* errors of the decomposition. */
/* Further Details */
/* =============== */
/* 2-96 Based on modifications by */
/* Ming Gu and Huan Ren, Computer Science Division, University of */
/* California at Berkeley, USA */
/* ===================================================================== */
/* .. Local Scalars .. */
/*< LOGICAL WANTQ, WANTU, WANTV >*/
/*< INTEGER I, IBND, ISUB, J, NCYCLE >*/
/*< REAL ANORM, BNORM, SMAX, TEMP, TOLA, TOLB, ULP, UNFL >*/
/* .. */
/* .. External Functions .. */
/*< LOGICAL LSAME >*/
/*< REAL SLAMCH, SLANGE >*/
/*< EXTERNAL LSAME, SLAMCH, SLANGE >*/
/* .. */
/* .. External Subroutines .. */
/*< EXTERNAL SCOPY, SGGSVP, STGSJA, XERBLA >*/
/* .. */
/* .. Intrinsic Functions .. */
/*< INTRINSIC MAX, MIN >*/
/* .. */
/* .. Executable Statements .. */
/* Test the input parameters */
/*< WANTU = LSAME( JOBU, 'U' ) >*/
/* Parameter adjustments */
a_dim1 = *lda;
a_offset = 1 + a_dim1;
a -= a_offset;
b_dim1 = *ldb;
b_offset = 1 + b_dim1;
b -= b_offset;
--alpha;
--beta;
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;
--work;
--iwork;
/* Function Body */
wantu = lsame_(jobu, "U", (ftnlen)1, (ftnlen)1);
/*< WANTV = LSAME( JOBV, 'V' ) >*/
wantv = lsame_(jobv, "V", (ftnlen)1, (ftnlen)1);
/*< WANTQ = LSAME( JOBQ, 'Q' ) >*/
wantq = lsame_(jobq, "Q", (ftnlen)1, (ftnlen)1);
/*< INFO = 0 >*/
*info = 0;
/*< IF( .NOT.( WANTU .OR. LSAME( JOBU, 'N' ) ) ) THEN >*/
if (! (wantu || lsame_(jobu, "N", (ftnlen)1, (ftnlen)1))) {
/*< INFO = -1 >*/
*info = -1;
/*< ELSE IF( .NOT.( WANTV .OR. LSAME( JOBV, 'N' ) ) ) THEN >*/
} else if (! (wantv || lsame_(jobv, "N", (ftnlen)1, (ftnlen)1))) {
/*< INFO = -2 >*/
*info = -2;
/*< ELSE IF( .NOT.( WANTQ .OR. LSAME( JOBQ, 'N' ) ) ) THEN >*/
} else if (! (wantq || lsame_(jobq, "N", (ftnlen)1, (ftnlen)1))) {
/*< INFO = -3 >*/
*info = -3;
/*< ELSE IF( M.LT.0 ) THEN >*/
} else if (*m < 0) {
/*< INFO = -4 >*/
*info = -4;
/*< ELSE IF( N.LT.0 ) THEN >*/
} else if (*n < 0) {
/*< INFO = -5 >*/
*info = -5;
/*< ELSE IF( P.LT.0 ) THEN >*/
} else if (*p < 0) {
/*< INFO = -6 >*/
*info = -6;
/*< ELSE IF( LDA.LT.MAX( 1, M ) ) THEN >*/
} else if (*lda < max(1,*m)) {
/*< INFO = -10 >*/
*info = -10;
/*< ELSE IF( LDB.LT.MAX( 1, P ) ) THEN >*/
} else if (*ldb < max(1,*p)) {
/*< INFO = -12 >*/
*info = -12;
/*< ELSE IF( LDU.LT.1 .OR. ( WANTU .AND. LDU.LT.M ) ) THEN >*/
} else if (*ldu < 1 || (wantu && *ldu < *m)) {
/*< INFO = -16 >*/
*info = -16;
/*< ELSE IF( LDV.LT.1 .OR. ( WANTV .AND. LDV.LT.P ) ) THEN >*/
} else if (*ldv < 1 || (wantv && *ldv < *p)) {
/*< INFO = -18 >*/
*info = -18;
/*< ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THEN >*/
} else if (*ldq < 1 || (wantq && *ldq < *n)) {
/*< INFO = -20 >*/
*info = -20;
/*< END IF >*/
}
/*< IF( INFO.NE.0 ) THEN >*/
if (*info != 0) {
/*< CALL XERBLA( 'SGGSVD', -INFO ) >*/
i__1 = -(*info);
xerbla_("SGGSVD", &i__1, (ftnlen)6);
/*< RETURN >*/
return 0;
/*< END IF >*/
}
/* Compute the Frobenius norm of matrices A and B */
/*< ANORM = SLANGE( '1', M, N, A, LDA, WORK ) >*/
anorm = slange_("1", m, n, &a[a_offset], lda, &work[1], (ftnlen)1);
/*< BNORM = SLANGE( '1', P, N, B, LDB, WORK ) >*/
bnorm = slange_("1", p, n, &b[b_offset], ldb, &work[1], (ftnlen)1);
/* Get machine precision and set up threshold for determining */
/* the effective numerical rank of the matrices A and B. */
/*< ULP = SLAMCH( 'Precision' ) >*/
ulp = slamch_("Precision", (ftnlen)9);
/*< UNFL = SLAMCH( 'Safe Minimum' ) >*/
unfl = slamch_("Safe Minimum", (ftnlen)12);
/*< TOLA = MAX( M, N )*MAX( ANORM, UNFL )*ULP >*/
tola = max(*m,*n) * dmax(anorm,unfl) * ulp;
/*< TOLB = MAX( P, N )*MAX( BNORM, UNFL )*ULP >*/
tolb = max(*p,*n) * dmax(bnorm,unfl) * ulp;
/* Preprocessing */
/*< >*/
sggsvp_(jobu, jobv, jobq, m, p, n, &a[a_offset], lda, &b[b_offset], ldb, &
tola, &tolb, k, l, &u[u_offset], ldu, &v[v_offset], ldv, &q[
q_offset], ldq, &iwork[1], &work[1], &work[*n + 1], info, (ftnlen)
1, (ftnlen)1, (ftnlen)1);
/* Compute the GSVD of two upper "triangular" matrices */
/*< >*/
stgsja_(jobu, jobv, jobq, m, p, n, k, l, &a[a_offset], lda, &b[b_offset],
ldb, &tola, &tolb, &alpha[1], &beta[1], &u[u_offset], ldu, &v[
v_offset], ldv, &q[q_offset], ldq, &work[1], &ncycle, info, (
ftnlen)1, (ftnlen)1, (ftnlen)1);
/* Sort the singular values and store the pivot indices in IWORK */
/* Copy ALPHA to WORK, then sort ALPHA in WORK */
/*< CALL SCOPY( N, ALPHA, 1, WORK, 1 ) >*/
scopy_(n, &alpha[1], &c__1, &work[1], &c__1);
/*< IBND = MIN( L, M-K ) >*/
/* Computing MIN */
i__1 = *l, i__2 = *m - *k;
ibnd = min(i__1,i__2);
/*< DO 20 I = 1, IBND >*/
i__1 = ibnd;
for (i__ = 1; i__ <= i__1; ++i__) {
/* Scan for largest ALPHA(K+I) */
/*< ISUB = I >*/
isub = i__;
/*< SMAX = WORK( K+I ) >*/
smax = work[*k + i__];
/*< DO 10 J = I + 1, IBND >*/
i__2 = ibnd;
for (j = i__ + 1; j <= i__2; ++j) {
/*< TEMP = WORK( K+J ) >*/
temp = work[*k + j];
/*< IF( TEMP.GT.SMAX ) THEN >*/
if (temp > smax) {
/*< ISUB = J >*/
isub = j;
/*< SMAX = TEMP >*/
smax = temp;
/*< END IF >*/
}
/*< 10 CONTINUE >*/
/* L10: */
}
/*< IF( ISUB.NE.I ) THEN >*/
if (isub != i__) {
/*< WORK( K+ISUB ) = WORK( K+I ) >*/
work[*k + isub] = work[*k + i__];
/*< WORK( K+I ) = SMAX >*/
work[*k + i__] = smax;
/*< IWORK( K+I ) = K + ISUB >*/
iwork[*k + i__] = *k + isub;
/*< ELSE >*/
} else {
/*< IWORK( K+I ) = K + I >*/
iwork[*k + i__] = *k + i__;
/*< END IF >*/
}
/*< 20 CONTINUE >*/
/* L20: */
}
/*< RETURN >*/
return 0;
/* End of SGGSVD */
/*< END >*/
} /* sggsvd_ */
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -