stgsja.c

来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 505 行 · 第 1/2 页

C
505
字号
/*                                                                        */
/*  MAXIT   INTEGER                                                       */
/*          MAXIT specifies the total loops that the iterative procedure  */
/*          may take. If after MAXIT cycles, the routine fails to         */
/*          converge, we return INFO = 1.                                 */
/*                                                                        */
/*  Further Details                                                       */
/*  ===============                                                       */
/*                                                                        */
/*  STGSJA essentially uses a variant of Kogbetliantz algorithm to reduce */
/*  min(L,M-K)-by-L triangular (or trapezoidal) matrix A23 and L-by-L     */
/*  matrix B13 to the form:                                               */
/*                                                                        */
/*           U1'*A13*Q1 = C1*R1; V1'*B13*Q1 = S1*R1,                      */
/*                                                                        */
/*  where U1, V1 and Q1 are orthogonal matrix, and Z' is the transpose    */
/*  of Z.  C1 and S1 are diagonal matrices satisfying                     */
/*                                                                        */
/*                C1**2 + S1**2 = I,                                      */
/*                                                                        */
/*  and R1 is an L-by-L nonsingular upper triangular matrix.              */
/*                                                                        */
/*  ===================================================================== */

/*     Decode and test the input parameters */

    initu = lsame_(jobu, "I");
    wantu = initu || lsame_(jobu, "U");

    initv = lsame_(jobv, "I");
    wantv = initv || lsame_(jobv, "V");

    initq = lsame_(jobq, "I");
    wantq = initq || lsame_(jobq, "Q");

    *info = 0;
    if (! (initu || wantu || lsame_(jobu, "N"))) {
        *info = -1;
    } else if (! (initv || wantv || lsame_(jobv, "N"))) {
        *info = -2;
    } else if (! (initq || wantq || lsame_(jobq, "N"))) {
        *info = -3;
    } else if (*m < 0) {
        *info = -4;
    } else if (*p < 0) {
        *info = -5;
    } else if (*n < 0) {
        *info = -6;
    } else if (*lda < max(1,*m)) {
        *info = -10;
    } else if (*ldb < max(1,*p)) {
        *info = -12;
    } else if (*ldu < 1 || (wantu && *ldu < *m)) {
        *info = -18;
    } else if (*ldv < 1 || (wantv && *ldv < *p)) {
        *info = -20;
    } else if (*ldq < 1 || (wantq && *ldq < *n)) {
        *info = -22;
    }
    if (*info != 0) {
        i__1 = -(*info);
        xerbla_("STGSJA", &i__1);
        return;
    }

/*     Initialize U, V and Q, if necessary */

    if (initu) {
        slaset_("Full", m, m, &c_b13, &c_b14, u, ldu);
    }
    if (initv) {
        slaset_("Full", p, p, &c_b13, &c_b14, v, ldv);
    }
    if (initq) {
        slaset_("Full", n, n, &c_b13, &c_b14, q, ldq);
    }

/*     Loop until convergence */

    upper = FALSE_;
    for (kcycle = 1; kcycle <= 40; ++kcycle) {
        upper = ! upper;
        for (i = 0; i < *l; ++i) {
            for (j = i + 1; j < *l; ++j) {
                a1 = a2 = a3 = 0.f;
                if (*k + i < *m) {
                    a1 = a[*k + i + (*n - *l + i) * *lda];
                }
                if (*k + j < *m) {
                    a3 = a[*k + j + (*n - *l + j) * *lda];
                }

                b1 = b[i + (*n - *l + i) * *ldb];
                b3 = b[j + (*n - *l + j) * *ldb];

                if (upper) {
                    if (*k + i < *m) {
                        a2 = a[*k + i + (*n - *l + j) * *lda];
                    }
                    b2 = b[i + (*n - *l + j) * *ldb];
                } else {
                    if (*k + j < *m) {
                        a2 = a[*k + j + (*n - *l + i) * *lda];
                    }
                    b2 = b[j + (*n - *l + i) * *ldb];
                }

                slags2_(&upper, &a1, &a2, &a3, &b1, &b2, &b3, &csu, &snu, &csv, &snv, &csq, &snq);

/*              Update (K+I)-th and (K+J)-th rows of matrix A: U'*A */

                if (*k + j < *m) {
                    srot_(l, &a[*k + j + (*n - *l) * *lda], lda, &a[*k + i + (*n - *l) * *lda], lda, &csu, &snu);
                }

/*              Update I-th and J-th rows of matrix B: V'*B */

                srot_(l, &b[j + (*n - *l) * *ldb], ldb, &b[i + (*n - *l) * *ldb], ldb, &csv, &snv);

/*              Update (N-L+I)-th and (N-L+J)-th columns of matrices */
/*              A and B: A*Q and B*Q */

                i__1 = min(*k + *l,*m);
                srot_(&i__1, &a[(*n - *l + j) * *lda], &c__1, &a[(*n - *l + i) * *lda], &c__1, &csq, &snq);
                srot_(l, &b[(*n - *l + j) * *ldb], &c__1, &b[(*n - *l + i) * *ldb], &c__1, &csq, &snq);

                if (upper) {
                    if (*k + i < *m) {
                        a[*k + i + (*n - *l + j) * *lda] = 0.f;
                    }
                    b[i + (*n - *l + j) * *ldb] = 0.f;
                } else {
                    if (*k + j < *m) {
                        a[*k + j + (*n - *l + i) * *lda] = 0.f;
                    }
                    b[j + (*n - *l + i) * *ldb] = 0.f;
                }

/*              Update orthogonal matrices U, V, Q, if desired. */

                if (wantu && *k + j < *m) {
                    srot_(m, &u[(*k + j) * *ldu], &c__1, &u[(*k + i) * *ldu], &c__1, &csu, &snu);
                }

                if (wantv) {
                    srot_(p, &v[j * *ldv], &c__1, &v[i * *ldv], &c__1, &csv, &snv);
                }

                if (wantq) {
                    srot_(n, &q[(*n - *l + j) * *ldq], &c__1, &q[(*n - *l + i) * *ldq], &c__1, &csq, &snq);
                }
            }
        }

        if (! upper) {

/*           The matrices A13 and B13 were lower triangular at the start */
/*           of the cycle, and are now upper triangular. */

/*           Convergence test: test the parallelism of the corresponding */
/*           rows of A and B. */

            error = 0.f;
            for (i = 0; i < min(*l,*m - *k); ++i) {
                i__1 = *l - i;
                scopy_(&i__1, &a[*k + i + (*n - *l + i) * *lda], lda, work, &c__1);
                scopy_(&i__1, &b[i + (*n - *l + i) * *ldb], ldb, &work[*l], &c__1);
                slapll_(&i__1, work, &c__1, &work[*l], &c__1, &ssmin);
                error = max(error,ssmin);
            }

            if (abs(error) <= (real) (*n) * min(*tola,*tolb)) {
                goto L50;
            }
        }
/*        End of cycle loop */
    }

/*     The algorithm has not converged after MAXIT cycles. */

    *info = 1;
    *ncycle = kcycle;
    return;

L50:

/*     If ERROR <= N*MIN(TOLA,TOLB), then the algorithm has converged. */
/*     Compute the generalized singular value pairs (ALPHA, BETA), and */
/*     set the triangular matrix R to array A. */

    for (i = 0; i < *k; ++i) {
        alpha[i] = 1.f;
        beta[i] = 0.f;
    }

    for (i = 0; i < min(*l,*m - *k); ++i) {
        a1 = a[*k + i + (*n - *l + i) * *lda];
        b1 = b[i + (*n - *l + i) * *ldb];

        if (a1 != 0.f) {
            gamma = b1 / a1;

/*           change sign if necessary */

            if (gamma < 0.f) {
                i__1 = *l - i;
                sscal_(&i__1, &c_b43, &b[i + (*n - *l + i) * *ldb], ldb);
                if (wantv) {
                    sscal_(p, &c_b43, &v[i * *ldv], &c__1);
                }
            }

            r__1 = abs(gamma);
            slartg_(&r__1, &c_b14, &beta[*k + i], &alpha[*k + i], &rwk);

            if (alpha[*k + i] >= beta[*k + i]) {
                i__1 = *l - i;
                r__1 = 1.f / alpha[*k + i];
                sscal_(&i__1, &r__1, &a[*k + i + (*n - *l + i) * *lda], lda);
            } else {
                i__1 = *l - i;
                r__1 = 1.f / beta[*k + i];
                sscal_(&i__1, &r__1, &b[i + (*n - *l + i) * *ldb], ldb);
                scopy_(&i__1, &b[i + (*n - *l + i) * *ldb], ldb, &a[*k + i + (*n - *l + i) * *lda], lda);
            }
        } else {
            alpha[*k + i] = 0.f;
            beta[*k + i] = 1.f;
            i__1 = *l - i;
            scopy_(&i__1, &b[i + (*n - *l + i) * *ldb], ldb, &a[*k + i + (*n - *l + i) * *lda], lda);
        }
    }

/*     Post-assignment */

    for (i = *m; i < *k + *l; ++i) {
        alpha[i] = 0.f;
        beta[i] = 1.f;
    }

    if (*k + *l < *n) {
        for (i = *k + *l; i < *n; ++i) {
            alpha[i] = 0.f;
            beta[i] = 0.f;
        }
    }

    *ncycle = kcycle;
    return;

} /* stgsja_ */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?