dlatrs.c

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

C
742
字号
            jinc = 1;
        } else {
            jfirst = *n;
            jlast = 1;
            jinc = -1;
        }

        if (tscal != 1.) {
            grow = 0.;
            goto L80;
        }

        if (nounit) {

/*           A is non-unit triangular. */

/*           Compute GROW = 1/G(j) and XBND = 1/M(j). */
/*           Initially, M(0) = max{x(i), i=1,...,n}. */

            grow = 1. / max(xbnd,smlnum);
            xbnd = grow;
            i__1 = jlast;
            i__2 = jinc;
            for (j = jfirst; i__2 < 0 ? j >= i__1 : j <= i__1; j += i__2) {

/*              Exit the loop if the growth factor is too small. */

                if (grow <= smlnum) {
                    goto L80;
                }

/*              G(j) = max( G(j-1), M(j-1)*( 1 + CNORM(j) ) ) */

                xj = cnorm[j] + 1.;
                grow = min(grow, xbnd / xj);

/*              M(j) = M(j-1)*( 1 + CNORM(j) ) / abs(A(j,j)) */

                tjj = abs(a[j + j * a_dim1]);
                if (xj > tjj) {
                    xbnd *= tjj / xj;
                }
            }
            grow = min(grow,xbnd);
        } else {

/*           A is unit triangular. */

/*           Compute GROW = 1/G(j), where G(0) = max{x(i), i=1,...,n}. */

            grow = min(1., 1./max(xbnd,smlnum));
            i__2 = jlast;
            i__1 = jinc;
            for (j = jfirst; i__1 < 0 ? j >= i__2 : j <= i__2; j += i__1) {

/*              Exit the loop if the growth factor is too small. */

                if (grow <= smlnum) {
                    goto L80;
                }

/*              G(j) = ( 1 + CNORM(j) )*G(j-1) */

                xj = cnorm[j] + 1.;
                grow /= xj;
            }
        }
L80:
        ;
    }

    if (grow * tscal > smlnum) {

/*        Use the Level 2 BLAS solve if the reciprocal of the bound on */
/*        elements of X is not too small. */

        dtrsv_(uplo, trans, diag, n, &a[a_offset], lda, &x[1], &c__1);
    } else {

/*        Use a Level 1 BLAS solve, scaling intermediate results. */

        if (xmax > bignum) {

/*           Scale X so that its components are less than or equal to */
/*           BIGNUM in absolute value. */

            *scale = bignum / xmax;
            dscal_(n, scale, &x[1], &c__1);
            xmax = bignum;
        }

        if (notran) {

/*           Solve A * x = b */

            i__1 = jlast;
            i__2 = jinc;
            for (j = jfirst; i__2 < 0 ? j >= i__1 : j <= i__1; j += i__2) {

/*              Compute x(j) = b(j) / A(j,j), scaling x if necessary. */

                xj = abs(x[j]);
                if (nounit) {
                    tjjs = a[j + j * a_dim1] * tscal;
                } else {
                    tjjs = tscal;
                    if (tscal == 1.) {
                        goto L100;
                    }
                }
                tjj = abs(tjjs);
                if (tjj > smlnum) {

/*                    abs(A(j,j)) > SMLNUM: */

                    if (tjj < 1.) {
                        if (xj > tjj * bignum) {

/*                          Scale x by 1/b(j). */

                            rec = 1. / xj;
                            dscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                    }
                    x[j] /= tjjs;
                    xj = abs(x[j]);
                } else if (tjj > 0.) {

/*                    0 < abs(A(j,j)) <= SMLNUM: */

                    if (xj > tjj * bignum) {

/*                       Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM */
/*                       to avoid overflow when dividing by A(j,j). */

                        rec = tjj * bignum / xj;
                        if (cnorm[j] > 1.) {

/*                          Scale by 1/CNORM(j) to avoid overflow when */
/*                          multiplying x(j) times column j. */

                            rec /= cnorm[j];
                        }
                        dscal_(n, &rec, &x[1], &c__1);
                        *scale *= rec;
                        xmax *= rec;
                    }
                    x[j] /= tjjs;
                    xj = abs(x[j]);
                } else {

/*                    A(j,j) = 0:  Set x(1:n) = 0, x(j) = 1, and */
/*                    scale = 0, and compute a solution to A*x = 0. */

                    i__3 = *n;
                    for (i = 1; i <= i__3; ++i) {
                        x[i] = 0.;
                    }
                    x[j] = 1.;
                    xj = 1.;
                    *scale = 0.;
                    xmax = 0.;
                }
L100:

/*              Scale x if necessary to avoid overflow when adding a */
/*              multiple of column j of A. */

                if (xj > 1.) {
                    rec = 1. / xj;
                    if (cnorm[j] > (bignum - xmax) * rec) {

/*                    Scale x by 1/(2*abs(x(j))). */

                        rec *= .5;
                        dscal_(n, &rec, &x[1], &c__1);
                        *scale *= rec;
                    }
                } else if (xj * cnorm[j] > bignum - xmax) {

/*                 Scale x by 1/2. */

                    dscal_(n, &c_b36, &x[1], &c__1);
                    *scale *= .5;
                }

                if (upper) {
                    if (j > 1) {

/*                    Compute the update */
/*                       x(1:j-1) := x(1:j-1) - x(j) * A(1:j-1,j) */

                        i__3 = j - 1;
                        d__1 = -x[j] * tscal;
                        daxpy_(&i__3, &d__1, &a[j * a_dim1 + 1], &c__1, &x[1], &c__1);
                        i__3 = j - 1;
                        i = idamax_(&i__3, &x[1], &c__1);
                        xmax = abs(x[i]);
                    }
                } else {
                    if (j < *n) {

/*                    Compute the update */
/*                       x(j+1:n) := x(j+1:n) - x(j) * A(j+1:n,j) */

                        i__3 = *n - j;
                        d__1 = -x[j] * tscal;
                        daxpy_(&i__3, &d__1, &a[j + 1 + j * a_dim1], &c__1, &x[j + 1], &c__1);
                        i__3 = *n - j;
                        i = j + idamax_(&i__3, &x[j + 1], &c__1);
                        xmax = abs(x[i]);
                    }
                }
            }

        } else {

/*           Solve A' * x = b */

            i__2 = jlast;
            i__1 = jinc;
            for (j = jfirst; i__1 < 0 ? j >= i__2 : j <= i__2; j += i__1) {

/*              Compute x(j) = b(j) - sum A(k,j)*x(k). */
/*                                    k<>j */

                xj = abs(x[j]);
                uscal = tscal;
                rec = 1. / max(xmax,1.);
                if (cnorm[j] > (bignum - xj) * rec) {

/*                 If x(j) could overflow, scale x by 1/(2*XMAX). */

                    rec *= .5;
                    if (nounit) {
                        tjjs = a[j + j * a_dim1] * tscal;
                    } else {
                        tjjs = tscal;
                    }
                    tjj = abs(tjjs);
                    if (tjj > 1.) {

/*                       Divide by A(j,j) when scaling x if A(j,j) > 1. */

                        rec = min(1., rec * tjj);
                        uscal /= tjjs;
                    }
                    if (rec < 1.) {
                        dscal_(n, &rec, &x[1], &c__1);
                        *scale *= rec;
                        xmax *= rec;
                    }
                }

                sumj = 0.;
                if (uscal == 1.) {

/*                 If the scaling needed for A in the dot product is 1, */
/*                 call DDOT to perform the dot product. */

                    if (upper) {
                        i__3 = j - 1;
                        sumj = ddot_(&i__3, &a[j * a_dim1 + 1], &c__1, &x[1], &c__1);
                    } else if (j < *n) {
                        i__3 = *n - j;
                        sumj = ddot_(&i__3, &a[j + 1 + j * a_dim1], &c__1, &x[j + 1], &c__1);
                    }
                } else {

/*                 Otherwise, use in-line code for the dot product. */

                    if (upper) {
                        i__3 = j - 1;
                        for (i = 1; i <= i__3; ++i) {
                            sumj += a[i + j * a_dim1] * uscal * x[i];
                        }
                    } else if (j < *n) {
                        i__3 = *n;
                        for (i = j + 1; i <= i__3; ++i) {
                            sumj += a[i + j * a_dim1] * uscal * x[i];
                        }
                    }
                }

                if (uscal == tscal) {

/*                 Compute x(j) := ( x(j) - sumj ) / A(j,j) if 1/A(j,j) */
/*                 was not used to scale the dotproduct. */

                    x[j] -= sumj;
                    xj = abs(x[j]);
                    if (nounit) {
                        tjjs = a[j + j * a_dim1] * tscal;
                    } else {
                        tjjs = tscal;
                        if (tscal == 1.) {
                            goto L150;
                        }
                    }

/*                    Compute x(j) = x(j) / A(j,j), scaling if necessary. */

                    tjj = abs(tjjs);
                    if (tjj > smlnum) {

/*                       abs(A(j,j)) > SMLNUM: */

                        if (tjj < 1.) {
                            if (xj > tjj * bignum) {

/*                             Scale X by 1/abs(x(j)). */

                                rec = 1. / xj;
                                dscal_(n, &rec, &x[1], &c__1);
                                *scale *= rec;
                                xmax *= rec;
                            }
                        }
                        x[j] /= tjjs;
                    } else if (tjj > 0.) {

/*                       0 < abs(A(j,j)) <= SMLNUM: */

                        if (xj > tjj * bignum) {

/*                          Scale x by (1/abs(x(j)))*abs(A(j,j))*BIGNUM. */

                            rec = tjj * bignum / xj;
                            dscal_(n, &rec, &x[1], &c__1);
                            *scale *= rec;
                            xmax *= rec;
                        }
                        x[j] /= tjjs;
                    } else {

/*                       A(j,j) = 0:  Set x(1:n) = 0, x(j) = 1, and */
/*                       scale = 0, and compute a solution to A'*x = 0. */

                        i__3 = *n;
                        for (i = 1; i <= i__3; ++i) {
                            x[i] = 0.;
                        }
                        x[j] = 1.;
                        *scale = 0.;
                        xmax = 0.;
                    }
L150:
                    ;
                } else {

/*                 Compute x(j) := x(j) / A(j,j)  - sumj if the dot */
/*                 product has already been divided by 1/A(j,j). */

                    x[j] = x[j] / tjjs - sumj;
                }
                xmax = max(xmax, abs(x[j]));
            }
        }
        *scale /= tscal;
    }

/*     Scale the column norms by 1/TSCAL for return. */

    if (tscal != 1.) {
        d__1 = 1. / tscal;
        dscal_(n, &d__1, &cnorm[1], &c__1);
    }
} /* dlatrs_ */

⌨️ 快捷键说明

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