double ProtoMol::Lapack::dnrm2(int *n, double *x, int *incx) { FAHCheckIn(); #if defined(HAVE_LAPACK) return dnrm2_(n, x, incx); #elif defined(HAVE_SIMTK_LAPACK) return dnrm2_(*n, x, *incx); #elif defined(HAVE_MKL_LAPACK) return DNRM2(n, x, incx); #else THROW(std::string(__func__) + " not supported"); #endif }
void dngeres(int *n, int *nev, int *aptr, int *aind, double *avals, int *bptr, int *bind, double *bvals, double *dr, double *di, double *z, int *ldz, double *res) { int i, first=1, ione=1, j; double md, rnrm, *ax, *bx; ax = (double*)malloc((*n)*sizeof(double)); bx = (double*)malloc((*n)*sizeof(double)); for (i = 0; i<(*nev); i++) { if (di[i] == 0.0) { dmvm_(n, avals, aind, aptr, &z(1,i+1), ax, &ione); dmvm_(n, bvals, bind, bptr, &z(1,i+1), bx, &ione); md = -dr[i]; daxpy_(n, &md, bx, &ione, ax, &ione); res[i] = dnrm2_(n, ax, &ione); res[i] = res[i]/abs(dr[i]); } else if (first) { dmvm_(n, avals, aind, aptr, &z(1,i+1), ax, &ione); dmvm_(n, bvals, bind, bptr, &z(1,i+1), bx, &ione); md = -dr[i]; daxpy_(n, &md, bx, &ione, ax, &ione); dmvm_(n, bvals, bind, bptr, &z(1,i+2), bx, &ione); daxpy_(n, &di[i], bx, &ione, ax, &ione); rnrm = dnrm2_(n, ax, &ione); res[i] = rnrm*rnrm; dmvm_(n, avals, aind, aptr, &z(1,i+2), ax, &ione); dmvm_(n, bvals, bind, bptr, &z(1,i+2), bx, &ione); md = -dr[i]; daxpy_(n, &md, bx, &ione, ax, &ione); dmvm_(n, bvals, bind, bptr, &z(1,i+1), bx, &ione); md = -di[i]; daxpy_(n, &md, bx, &ione, ax, &ione); rnrm = dnrm2_(n, ax, &ione); res[i] = dlapy2_(&res[i], &rnrm); res[i] = res[i]/dlapy2_(&dr[i],&di[i]); res[i+1] = res[i]; first = 0; } else { first = 1; } } free(ax); free(bx); }
/*--------------------------------------------------------- fem_vec_norm - to compute a norm of global vector (in parallel) ---------------------------------------------------------*/ double fem_vec_norm( /* returns: L2 norm of global Vector */ int Solver_id, /* in: solver data structure to be used */ int Level_id, /* in: level number */ int Nrdof, /* in: number of vector components */ double* Vector /* in: local part of global Vector */ ) { int IONE=1; int problem_id; double vec_norm; /*++++++++++++++++ executable statements ++++++++++++++++*/ if(siv_solver[Solver_id].parallel){ problem_id = siv_solver[Solver_id].problem_id; vec_norm = pdr_vec_norm(problem_id, Solver_id, Level_id, Nrdof, Vector); } else { vec_norm = dnrm2_(&Nrdof, Vector, &IONE); } return(vec_norm); }
/** * @param[in] space The list of points in space that need to be iterated. */ void operator() (const pfunc::space_1D& space) const { for (size_t i=space.begin(); i<space.end(); ++i) { EdgeListType edge_list = (*set_map)(i); RandomAccessContainer A (M*edge_list.size()); RandomAccessContainer X (edge_list.size()); /* Response is common across all the vertices */ int response; /* Set up A, X, and R */ EdgeListIteratorType list_iter = edge_list.begin (); int index=0; while (list_iter != edge_list.end()) { edge_type current_entry = (*list_iter); const snp_type snp = (*snp_map)(current_entry.source); response = current_entry.target; const float_type weight = current_entry.weight; /* populate A */ (*materializer)(snp, A.begin()+(index*M)); /* populate X */ X[index] = weight; /* populate R */ int int_M = static_cast<int>(M); double* Y_ptr = const_cast<double*>(&((*Y)[0])+(response*M)); double* R_ptr = const_cast<double*>(&((*R)[0])+(response*M)); dcopy_ (&int_M, Y_ptr, &ONE_STEP, R_ptr, &ONE_STEP); ++list_iter; ++index; } /* Now, compute R = AX-R */ double* A_ptr = &(A[0]); double* X_ptr = &(X[0]); double* R_ptr = &((*R)[0])+(response*M); int LDA = static_cast<int>(M); int LDX = static_cast<int>(edge_list.size()); int LDR = static_cast<int>(M); dgemm_ (&NO_TRANS, &NO_TRANS, &LDR, &ONE_STEP, &LDX, &PLUS_ONE, A_ptr, &LDA, X_ptr, &LDX, &MINUS_ONE, R_ptr, &LDR); (*l2_norm)[response] = dnrm2_(&LDR, R_ptr, &ONE_STEP); } }
/** * @param[in] space The list of points in space that need to be iterated. */ void operator() (const pfunc::space_1D& space) const { double* R_ptr = &((*R)[0]); int LDR = M; /* Loop over each element in the range that is given to us */ for (size_t i=space.begin(); i<space.end(); ++i) (*l2)[i] = dnrm2_ (&LDR, R_ptr+(i*LDR), &ONE_STEP); }
int TRON::trcg(double *g, double *s, double *r, int num_sample, long int *num_data) { int i, inc = 1; int n = fun_obj->get_nr_variable(); double one = 1; double *d = new double[n]; double *Hd = new double[n]; double rTr, rnewTrnew, alpha, beta, cgtol; for (i=0; i<n; i++) { Hd[i] = 0.0; s[i] = 0.0; r[i] = -g[i]; d[i] = r[i]; } cgtol = 0.1*dnrm2_(&n, g, &inc); int cg_iter = 0; rTr = ddot_(&n, r, &inc, r, &inc); while (1) { if (dnrm2_(&n, r, &inc) <= cgtol || cg_iter >= max_cg_iter) break; cg_iter++; fun_obj->sample_Hv(d, Hd, num_data); alpha = rTr/ddot_(&n, d, &inc, Hd, &inc); daxpy_(&n, &alpha, d, &inc, s, &inc); alpha = -alpha; daxpy_(&n, &alpha, Hd, &inc, r, &inc); rnewTrnew = ddot_(&n, r, &inc, r, &inc); beta = rnewTrnew/rTr; dscal_(&n, &beta, d, &inc); daxpy_(&n, &one, r, &inc, d, &inc); rTr = rnewTrnew; } delete[] d; delete[] Hd; return(cg_iter); }
double SPDTensorDL::f(Variable *x) const { const double *xptr = x->ObtainReadData(); /*each slice of Xaj is B alpha_j in [(6), CS15]*/ SharedSpace *Xalpha = new SharedSpace(3, dim, dim, N); double *Xalphaptr = Xalpha->ObtainWriteEntireData(); integer dd = dim * dim, nnum = num, NN = N; /*Xalpha <-- \mathbb{B} alpha*/ dgemm_(GLOBAL::N, GLOBAL::N, &dd, &NN, &nnum, &GLOBAL::DONE, const_cast<double *> (xptr), &dd, alpha, &nnum, &GLOBAL::DZERO, Xalphaptr, &dd); x->AddToTempData("Xalpha", Xalpha); /*compute cholesky decomposition for all slices in Xalpha*/ SPDTensor *Mani = dynamic_cast<SPDTensor *> (Domain); Mani->CholeskyRepresentation(x); const SharedSpace *SharedL = x->ObtainReadTempData("XaL"); const double *L = SharedL->ObtainReadData(); SharedSpace *SharedlogLXL = new SharedSpace(3, dim, dim, N); double *logLXL = SharedlogLXL->ObtainWriteEntireData(); double *Ltmp = new double[dim * dim]; integer length = dim * dim, ddim = dim, info; for (integer i = 0; i < N; i++) { dcopy_(&length, const_cast<double *> (L) + i * length, &GLOBAL::IONE, Ltmp, &GLOBAL::IONE); /*Solve the linear system Ls X = Li, i.e., X = Ls^{-1} Li. The solution X is stored in Li. Note that Li is a lower triangular matrix. Details: http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html */ dtrtrs_(GLOBAL::L, GLOBAL::N, GLOBAL::N, &ddim, &ddim, Ls + dim * dim * i, &ddim, Ltmp, &ddim, &info); if (info != 0) { std::cout << "Warning: Solving linear system in SPDTensorDL::f failed with info:" << info << "!" << std::endl; } dgemm_(GLOBAL::N, GLOBAL::T, &ddim, &ddim, &ddim, &GLOBAL::DONE, Ltmp, &ddim, Ltmp, &ddim, &GLOBAL::DZERO, logLXL + ddim * ddim * i, &ddim); Matrix MMt(logLXL + ddim * ddim * i, ddim, ddim); Matrix::LogSymmetricM(GLOBAL::L, MMt, MMt); } delete[] Ltmp; length = dim * dim * N; double result = dnrm2_(&length, logLXL, &GLOBAL::IONE); x->AddToTempData("logLXL", SharedlogLXL); result *= result; result /= 2.0; /*add \Omega(X) = \sum \tr(X_i)*/ for (integer i = 0; i < num; i++) { for (integer j = 0; j < dim; j++) { result += lambdaX * xptr[i * dim * dim + j * dim + j]; } } return result; };
/*! return its Euclidean norm */ inline double nrm2(const _drovector& vec) { #ifdef CPPL_VERBOSE std::cerr << "# [MARK] nrm2(const _drovector&)" << std::endl; #endif//CPPL_VERBOSE double val( dnrm2_(vec.L, vec.Array, 1) ); vec.destroy(); return val; }
int toScalarR(int code, KDVEC(x), DVEC(r)) { REQUIRES(rn==1,BAD_SIZE); DEBUGMSG("toScalarR"); double res; integer one = 1; integer n = xn; switch(code) { case 0: { res = dnrm2_(&n,xp,&one); break; } case 1: { res = dasum_(&n,xp,&one); break; } case 2: { res = vector_max_index(V(x)); break; } case 3: { res = vector_max(V(x)); break; } case 4: { res = vector_min_index(V(x)); break; } case 5: { res = vector_min(V(x)); break; } default: ERROR(BAD_CODE); } rp[0] = res; OK }
/* Subroutine */ int dlaed3_(integer *k, integer *n, integer *n1, doublereal * d__, doublereal *q, integer *ldq, doublereal *rho, doublereal *dlamda, doublereal *q2, integer *indx, integer *ctot, doublereal *w, doublereal *s, integer *info) { /* -- LAPACK routine (version 3.0) -- Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab, Courant Institute, NAG Ltd., and Rice University June 30, 1999 Purpose ======= DLAED3 finds the roots of the secular equation, as defined by the values in D, W, and RHO, between 1 and K. It makes the appropriate calls to DLAED4 and then updates the eigenvectors by multiplying the matrix of eigenvectors of the pair of eigensystems being combined by the matrix of eigenvectors of the K-by-K system which is solved here. This code makes very mild assumptions about floating point arithmetic. It will work on machines with a guard digit in add/subtract, or on those binary machines without guard digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or Cray-2. It could conceivably fail on hexadecimal or decimal machines without guard digits, but we know of none. Arguments ========= K (input) INTEGER The number of terms in the rational function to be solved by DLAED4. K >= 0. N (input) INTEGER The number of rows and columns in the Q matrix. N >= K (deflation may result in N>K). N1 (input) INTEGER The location of the last eigenvalue in the leading submatrix. min(1,N) <= N1 <= N/2. D (output) DOUBLE PRECISION array, dimension (N) D(I) contains the updated eigenvalues for 1 <= I <= K. Q (output) DOUBLE PRECISION array, dimension (LDQ,N) Initially the first K columns are used as workspace. On output the columns 1 to K contain the updated eigenvectors. LDQ (input) INTEGER The leading dimension of the array Q. LDQ >= max(1,N). RHO (input) DOUBLE PRECISION The value of the parameter in the rank one update equation. RHO >= 0 required. DLAMDA (input/output) DOUBLE PRECISION array, dimension (K) The first K elements of this array contain the old roots of the deflated updating problem. These are the poles of the secular equation. May be changed on output by having lowest order bit set to zero on Cray X-MP, Cray Y-MP, Cray-2, or Cray C-90, as described above. Q2 (input) DOUBLE PRECISION array, dimension (LDQ2, N) The first K columns of this matrix contain the non-deflated eigenvectors for the split problem. INDX (input) INTEGER array, dimension (N) The permutation used to arrange the columns of the deflated Q matrix into three groups (see DLAED2). The rows of the eigenvectors found by DLAED4 must be likewise permuted before the matrix multiply can take place. CTOT (input) INTEGER array, dimension (4) A count of the total number of the various types of columns in Q, as described in INDX. The fourth column type is any column which has been deflated. W (input/output) DOUBLE PRECISION array, dimension (K) The first K elements of this array contain the components of the deflation-adjusted updating vector. Destroyed on output. S (workspace) DOUBLE PRECISION array, dimension (N1 + 1)*K Will contain the eigenvectors of the repaired matrix which will be multiplied by the previously accumulated eigenvectors to update the system. LDS (input) INTEGER The leading dimension of S. LDS >= max(1,K). INFO (output) INTEGER = 0: successful exit. < 0: if INFO = -i, the i-th argument had an illegal value. > 0: if INFO = 1, an eigenvalue did not converge Further Details =============== Based on contributions by Jeff Rutter, Computer Science Division, University of California at Berkeley, USA Modified by Francoise Tisseur, University of Tennessee. ===================================================================== Test the input parameters. Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; static doublereal c_b22 = 1.; static doublereal c_b23 = 0.; /* System generated locals */ integer q_dim1, q_offset, i__1, i__2; doublereal d__1; /* Builtin functions */ double sqrt(doublereal), d_sign(doublereal *, doublereal *); /* Local variables */ static doublereal temp; extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer i__, j; extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *), dcopy_(integer *, doublereal *, integer *, doublereal *, integer *), dlaed4_(integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, integer *); static integer n2; extern doublereal dlamc3_(doublereal *, doublereal *); static integer n12, ii, n23; extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, doublereal *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); static integer iq2; #define q_ref(a_1,a_2) q[(a_2)*q_dim1 + a_1] --d__; q_dim1 = *ldq; q_offset = 1 + q_dim1 * 1; q -= q_offset; --dlamda; --q2; --indx; --ctot; --w; --s; /* Function Body */ *info = 0; if (*k < 0) { *info = -1; } else if (*n < *k) { *info = -2; } else if (*ldq < max(1,*n)) { *info = -6; } if (*info != 0) { i__1 = -(*info); xerbla_("DLAED3", &i__1); return 0; } /* Quick return if possible */ if (*k == 0) { return 0; } /* Modify values DLAMDA(i) to make sure all DLAMDA(i)-DLAMDA(j) can be computed with high relative accuracy (barring over/underflow). This is a problem on machines without a guard digit in add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). The following code replaces DLAMDA(I) by 2*DLAMDA(I)-DLAMDA(I), which on any of these machines zeros out the bottommost bit of DLAMDA(I) if it is 1; this makes the subsequent subtractions DLAMDA(I)-DLAMDA(J) unproblematic when cancellation occurs. On binary machines with a guard digit (almost all machines) it does not change DLAMDA(I) at all. On hexadecimal and decimal machines with a guard digit, it slightly changes the bottommost bits of DLAMDA(I). It does not account for hexadecimal or decimal machines without guard digits (we know of none). We use a subroutine call to compute 2*DLAMBDA(I) to prevent optimizing compilers from eliminating this code. */ i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { dlamda[i__] = dlamc3_(&dlamda[i__], &dlamda[i__]) - dlamda[i__]; /* L10: */ } i__1 = *k; for (j = 1; j <= i__1; ++j) { dlaed4_(k, &j, &dlamda[1], &w[1], &q_ref(1, j), rho, &d__[j], info); /* If the zero finder fails, the computation is terminated. */ if (*info != 0) { goto L120; } /* L20: */ } if (*k == 1) { goto L110; } if (*k == 2) { i__1 = *k; for (j = 1; j <= i__1; ++j) { w[1] = q_ref(1, j); w[2] = q_ref(2, j); ii = indx[1]; q_ref(1, j) = w[ii]; ii = indx[2]; q_ref(2, j) = w[ii]; /* L30: */ } goto L110; } /* Compute updated W. */ dcopy_(k, &w[1], &c__1, &s[1], &c__1); /* Initialize W(I) = Q(I,I) */ i__1 = *ldq + 1; dcopy_(k, &q[q_offset], &i__1, &w[1], &c__1); i__1 = *k; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { w[i__] *= q_ref(i__, j) / (dlamda[i__] - dlamda[j]); /* L40: */ } i__2 = *k; for (i__ = j + 1; i__ <= i__2; ++i__) { w[i__] *= q_ref(i__, j) / (dlamda[i__] - dlamda[j]); /* L50: */ } /* L60: */ } i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = sqrt(-w[i__]); w[i__] = d_sign(&d__1, &s[i__]); /* L70: */ } /* Compute eigenvectors of the modified rank-1 modification. */ i__1 = *k; for (j = 1; j <= i__1; ++j) { i__2 = *k; for (i__ = 1; i__ <= i__2; ++i__) { s[i__] = w[i__] / q_ref(i__, j); /* L80: */ } temp = dnrm2_(k, &s[1], &c__1); i__2 = *k; for (i__ = 1; i__ <= i__2; ++i__) { ii = indx[i__]; q_ref(i__, j) = s[ii] / temp; /* L90: */ } /* L100: */ } /* Compute the updated eigenvectors. */ L110: n2 = *n - *n1; n12 = ctot[1] + ctot[2]; n23 = ctot[2] + ctot[3]; dlacpy_("A", &n23, k, &q_ref(ctot[1] + 1, 1), ldq, &s[1], &n23) ; iq2 = *n1 * n12 + 1; if (n23 != 0) { dgemm_("N", "N", &n2, k, &n23, &c_b22, &q2[iq2], &n2, &s[1], &n23, & c_b23, &q_ref(*n1 + 1, 1), ldq); } else { dlaset_("A", &n2, k, &c_b23, &c_b23, &q_ref(*n1 + 1, 1), ldq); } dlacpy_("A", &n12, k, &q[q_offset], ldq, &s[1], &n12); if (n12 != 0) { dgemm_("N", "N", n1, k, &n12, &c_b22, &q2[1], n1, &s[1], &n12, &c_b23, &q[q_offset], ldq); } else { dlaset_("A", n1, k, &c_b23, &c_b23, &q_ref(1, 1), ldq); } L120: return 0; /* End of DLAED3 */ } /* dlaed3_ */
double dnrm2( int N, double *a, int inca ){ return dnrm2_( &N, a, &inca ); };
/* Subroutine */ int dstein_(integer * n, doublereal * d__, doublereal * e, integer * m, doublereal * w, integer * iblock, integer * isplit, doublereal * z__, integer * ldz, doublereal * work, integer * iwork, integer * ifail, integer * info) { /* System generated locals */ integer z_dim1, z_offset, i__1, i__2, i__3; doublereal d__1, d__2, d__3, d__4, d__5; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static integer jblk, nblk; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); static integer jmax; extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer i__, j; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); static integer iseed[4], gpind, iinfo; extern doublereal dasum_(integer *, doublereal *, integer *); extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); static integer b1; extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *); static integer j1; static doublereal ortol; static integer indrv1, indrv2, indrv3, indrv4, indrv5, bn; extern doublereal dlamch_(char *); extern /* Subroutine */ int dlagtf_(integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, integer *); static doublereal xj; extern integer idamax_(integer *, doublereal *, integer *); extern /* Subroutine */ int xerbla_(char *, integer *), dlagts_( integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, doublereal *, integer *); static integer nrmchk; extern /* Subroutine */ int dlarnv_(integer *, integer *, integer *, doublereal *); static integer blksiz; static doublereal onenrm, dtpcrt, pertol, scl, eps, sep, nrm, tol; static integer its; static doublereal xjm, ztr, eps1; #define z___ref(a_1,a_2) z__[(a_2)*z_dim1 + a_1] /* -- LAPACK routine (instrumented to count operations, version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Common block to return operation count and iteration count ITCNT is initialized to 0, OPS is only incremented Purpose ======= DSTEIN computes the eigenvectors of a real symmetric tridiagonal matrix T corresponding to specified eigenvalues, using inverse iteration. The maximum number of iterations allowed for each eigenvector is specified by an internal parameter MAXITS (currently set to 5). Arguments ========= N (input) INTEGER The order of the matrix. N >= 0. D (input) DOUBLE PRECISION array, dimension (N) The n diagonal elements of the tridiagonal matrix T. E (input) DOUBLE PRECISION array, dimension (N) The (n-1) subdiagonal elements of the tridiagonal matrix T, in elements 1 to N-1. E(N) need not be set. M (input) INTEGER The number of eigenvectors to be found. 0 <= M <= N. W (input) DOUBLE PRECISION array, dimension (N) The first M elements of W contain the eigenvalues for which eigenvectors are to be computed. The eigenvalues should be grouped by split-off block and ordered from smallest to largest within the block. ( The output array W from DSTEBZ with ORDER = 'B' is expected here. ) IBLOCK (input) INTEGER array, dimension (N) The submatrix indices associated with the corresponding eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to the first submatrix from the top, =2 if W(i) belongs to the second submatrix, etc. ( The output array IBLOCK from DSTEBZ is expected here. ) ISPLIT (input) INTEGER array, dimension (N) The splitting points, at which T breaks up into submatrices. The first submatrix consists of rows/columns 1 to ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1 through ISPLIT( 2 ), etc. ( The output array ISPLIT from DSTEBZ is expected here. ) Z (output) DOUBLE PRECISION array, dimension (LDZ, M) The computed eigenvectors. The eigenvector associated with the eigenvalue W(i) is stored in the i-th column of Z. Any vector which fails to converge is set to its current iterate after MAXITS iterations. LDZ (input) INTEGER The leading dimension of the array Z. LDZ >= max(1,N). WORK (workspace) DOUBLE PRECISION array, dimension (5*N) IWORK (workspace) INTEGER array, dimension (N) IFAIL (output) INTEGER array, dimension (M) On normal exit, all elements of IFAIL are zero. If one or more eigenvectors fail to converge after MAXITS iterations, then their indices are stored in array IFAIL. INFO (output) INTEGER = 0: successful exit. < 0: if INFO = -i, the i-th argument had an illegal value > 0: if INFO = i, then i eigenvectors failed to converge in MAXITS iterations. Their indices are stored in array IFAIL. Internal Parameters =================== MAXITS INTEGER, default = 5 The maximum number of iterations performed. EXTRA INTEGER, default = 2 The number of iterations performed after norm growth criterion is satisfied, should be at least 1. ===================================================================== Test the input parameters. Parameter adjustments */ --d__; --e; --w; --iblock; --isplit; z_dim1 = *ldz; z_offset = 1 + z_dim1 * 1; z__ -= z_offset; --work; --iwork; --ifail; /* Function Body */ *info = 0; i__1 = *m; for (i__ = 1; i__ <= i__1; ++i__) { ifail[i__] = 0; /* L10: */ } if (*n < 0) { *info = -1; } else if (*m < 0 || *m > *n) { *info = -4; } else if (*ldz < max(1, *n)) { *info = -9; } else { i__1 = *m; for (j = 2; j <= i__1; ++j) { if (iblock[j] < iblock[j - 1]) { *info = -6; goto L30; } if (iblock[j] == iblock[j - 1] && w[j] < w[j - 1]) { *info = -5; goto L30; } /* L20: */ } L30: ; } if (*info != 0) { i__1 = -(*info); xerbla_("DSTEIN", &i__1); return 0; } /* Initialize iteration count. */ latime_1.itcnt = 0.; /* Quick return if possible */ if (*n == 0 || *m == 0) { return 0; } else if (*n == 1) { z___ref(1, 1) = 1.; return 0; } /* Get machine constants. */ eps = dlamch_("Precision"); /* Initialize seed for random number generator DLARNV. */ for (i__ = 1; i__ <= 4; ++i__) { iseed[i__ - 1] = 1; /* L40: */ } /* Initialize pointers. */ indrv1 = 0; indrv2 = indrv1 + *n; indrv3 = indrv2 + *n; indrv4 = indrv3 + *n; indrv5 = indrv4 + *n; /* Compute eigenvectors of matrix blocks. */ j1 = 1; i__1 = iblock[*m]; for (nblk = 1; nblk <= i__1; ++nblk) { /* Find starting and ending indices of block nblk. */ if (nblk == 1) { b1 = 1; } else { b1 = isplit[nblk - 1] + 1; } bn = isplit[nblk]; blksiz = bn - b1 + 1; if (blksiz == 1) { goto L60; } gpind = b1; /* Compute reorthogonalization criterion and stopping criterion. */ onenrm = (d__1 = d__[b1], abs(d__1)) + (d__2 = e[b1], abs(d__2)); /* Computing MAX */ d__3 = onenrm, d__4 = (d__1 = d__[bn], abs(d__1)) + (d__2 = e[bn - 1], abs(d__2)); onenrm = max(d__3, d__4); i__2 = bn - 1; for (i__ = b1 + 1; i__ <= i__2; ++i__) { /* Computing MAX */ d__4 = onenrm, d__5 = (d__1 = d__[i__], abs(d__1)) + (d__2 = e[i__ - 1], abs (d__2)) + (d__3 = e[i__], abs(d__3)); onenrm = max(d__4, d__5); /* L50: */ } ortol = onenrm * .001; dtpcrt = sqrt(.1 / blksiz); /* Increment opcount for computing criteria. */ latime_1.ops = latime_1.ops + ((bn - b1) << 1) + 3; /* Loop through eigenvalues of block nblk. */ L60: jblk = 0; i__2 = *m; for (j = j1; j <= i__2; ++j) { if (iblock[j] != nblk) { j1 = j; goto L160; } ++jblk; xj = w[j]; /* Skip all the work if the block size is one. */ if (blksiz == 1) { work[indrv1 + 1] = 1.; goto L120; } /* If eigenvalues j and j-1 are too close, add a relatively small perturbation. */ if (jblk > 1) { eps1 = (d__1 = eps * xj, abs(d__1)); pertol = eps1 * 10.; sep = xj - xjm; if (sep < pertol) { xj = xjm + pertol; } } its = 0; nrmchk = 0; /* Get random starting vector. */ dlarnv_(&c__2, iseed, &blksiz, &work[indrv1 + 1]); /* Increment opcount for getting random starting vector. ( DLARND(2,.) requires 9 flops. ) */ latime_1.ops += blksiz * 9; /* Copy the matrix T so it won't be destroyed in factorization. */ dcopy_(&blksiz, &d__[b1], &c__1, &work[indrv4 + 1], &c__1); i__3 = blksiz - 1; dcopy_(&i__3, &e[b1], &c__1, &work[indrv2 + 2], &c__1); i__3 = blksiz - 1; dcopy_(&i__3, &e[b1], &c__1, &work[indrv3 + 1], &c__1); /* Compute LU factors with partial pivoting ( PT = LU ) */ tol = 0.; dlagtf_(&blksiz, &work[indrv4 + 1], &xj, &work[indrv2 + 2], &work[indrv3 + 1], &tol, &work[indrv5 + 1], &iwork[1], &iinfo); /* Increment opcount for computing LU factors. ( DLAGTF(BLKSIZ,...) requires about 8*BLKSIZ flops. ) */ latime_1.ops += blksiz << 3; /* Update iteration count. */ L70: ++its; if (its > 5) { goto L100; } /* Normalize and scale the righthand side vector Pb. Computing MAX */ d__2 = eps, d__3 = (d__1 = work[indrv4 + blksiz], abs(d__1)); scl = blksiz * onenrm * max(d__2, d__3) / dasum_(&blksiz, &work [indrv1 + 1], &c__1); dscal_(&blksiz, &scl, &work[indrv1 + 1], &c__1); /* Solve the system LU = Pb. */ dlagts_(&c_n1, &blksiz, &work[indrv4 + 1], &work[indrv2 + 2], &work[indrv3 + 1], &work[indrv5 + 1], &iwork[1], &work[indrv1 + 1], &tol, &iinfo); /* Increment opcount for scaling and solving linear system. ( DLAGTS(-1,BLKSIZ,...) requires about 8*BLKSIZ flops. ) */ latime_1.ops = latime_1.ops + 3 + blksiz * 10; /* Reorthogonalize by modified Gram-Schmidt if eigenvalues are close enough. */ if (jblk == 1) { goto L90; } if ((d__1 = xj - xjm, abs(d__1)) > ortol) { gpind = j; } if (gpind != j) { i__3 = j - 1; for (i__ = gpind; i__ <= i__3; ++i__) { ztr = -ddot_(&blksiz, &work[indrv1 + 1], &c__1, &z___ref(b1, i__), &c__1); daxpy_(&blksiz, &ztr, &z___ref(b1, i__), &c__1, &work[indrv1 + 1], &c__1); /* L80: */ } /* Increment opcount for reorthogonalizing. */ latime_1.ops += (j - gpind) * blksiz << 2; } /* Check the infinity norm of the iterate. */ L90: jmax = idamax_(&blksiz, &work[indrv1 + 1], &c__1); nrm = (d__1 = work[indrv1 + jmax], abs(d__1)); /* Continue for additional iterations after norm reaches stopping criterion. */ if (nrm < dtpcrt) { goto L70; } ++nrmchk; if (nrmchk < 3) { goto L70; } goto L110; /* If stopping criterion was not satisfied, update info and store eigenvector number in array ifail. */ L100: ++(*info); ifail[*info] = j; /* Accept iterate as jth eigenvector. */ L110: scl = 1. / dnrm2_(&blksiz, &work[indrv1 + 1], &c__1); jmax = idamax_(&blksiz, &work[indrv1 + 1], &c__1); if (work[indrv1 + jmax] < 0.) { scl = -scl; } dscal_(&blksiz, &scl, &work[indrv1 + 1], &c__1); /* Increment opcount for scaling. */ latime_1.ops += blksiz * 3; L120: i__3 = *n; for (i__ = 1; i__ <= i__3; ++i__) { z___ref(i__, j) = 0.; /* L130: */ } i__3 = blksiz; for (i__ = 1; i__ <= i__3; ++i__) { z___ref(b1 + i__ - 1, j) = work[indrv1 + i__]; /* L140: */ } /* Save the shift to check eigenvalue spacing at next iteration. */ xjm = xj; /* L150: */ } L160: ; } return 0; /* End of DSTEIN */ } /* dstein_ */
void TRON::tron(double *w) { // Parameters for updating the iterates. double eta0 = 1e-4, eta1 = 0.25, eta2 = 0.75; // Parameters for updating the trust region size delta. double sigma1 = 0.25, sigma2 = 0.5, sigma3 = 4; Int n = fun_obj->get_nr_variable(); Int i, cg_iter; double delta, snorm, one=1.0; double alpha, f, fnew, prered, actred, gs; Int search = 1, iter = 1, inc = 1; double *s = new double[n]; double *r = new double[n]; double *g = new double[n]; // calculate gradient norm at w=0 for stopping condition. double *w0 = new double[n]; for (i=0; i<n; i++) w0[i] = 0; fun_obj->fun(w0); fun_obj->grad(w0, g); double gnorm0 = dnrm2_(&n, g, &inc); delete [] w0; f = fun_obj->fun(w); fun_obj->grad(w, g); delta = dnrm2_(&n, g, &inc); double gnorm = delta; if (gnorm <= eps*gnorm0) search = 0; iter = 1; double *w_new = new double[n]; while (iter <= max_iter && search) { cg_iter = trcg(delta, g, s, r); memcpy(w_new, w, sizeof(double)*n); daxpy_(&n, &one, s, &inc, w_new, &inc); gs = ddot_(&n, g, &inc, s, &inc); prered = -0.5*(gs-ddot_(&n, s, &inc, r, &inc)); fnew = fun_obj->fun(w_new); // Compute the actual reduction. actred = f - fnew; // On the first iteration, adjust the initial step bound. snorm = dnrm2_(&n, s, &inc); if (iter == 1) delta = min(delta, snorm); // Compute prediction alpha*snorm of the step. if (fnew - f - gs <= 0) alpha = sigma3; else alpha = max(sigma1, -0.5*(gs/(fnew - f - gs))); // Update the trust region bound according to the ratio of actual to predicted reduction. if (actred < eta0*prered) delta = min(max(alpha, sigma1)*snorm, sigma2*delta); else if (actred < eta1*prered) delta = max(sigma1*delta, min(alpha*snorm, sigma2*delta)); else if (actred < eta2*prered) delta = max(sigma1*delta, min(alpha*snorm, sigma3*delta)); else delta = max(delta, min(alpha*snorm, sigma3*delta)); info("iter %2d act %5.3e pre %5.3e delta %5.3e f %5.3e |g| %5.3e CG %3d\n", iter, actred, prered, delta, f, gnorm, cg_iter); if (actred > eta0*prered) { iter++; memcpy(w, w_new, sizeof(double)*n); f = fnew; fun_obj->grad(w, g); gnorm = dnrm2_(&n, g, &inc); if (gnorm <= eps*gnorm0) break; } if (f < -1.0e+32) { info("WARNING: f < -1.0e+32\n"); break; } if (fabs(actred) <= 0 && prered <= 0) { info("WARNING: actred and prered <= 0\n"); break; } if (fabs(actred) <= 1.0e-12*fabs(f) && fabs(prered) <= 1.0e-12*fabs(f)) { info("WARNING: actred and prered too small\n"); break; } } delete[] g; delete[] r; delete[] w_new; delete[] s; }
/* Subroutine */ int dqrt15_(integer *scale, integer *rksel, integer *m, integer *n, integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *s, integer *rank, doublereal *norma, doublereal *normb, integer *iseed, doublereal *work, integer *lwork) { /* System generated locals */ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2; doublereal d__1; /* Local variables */ static integer info; static doublereal temp; extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer j; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *), dlarf_(char *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *), dgemm_(char *, char *, integer *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); extern doublereal dasum_(integer *, doublereal *, integer *); static doublereal dummy[1]; extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); static integer mn; extern /* Subroutine */ int dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *); extern doublereal dlarnd_(integer *, integer *); extern /* Subroutine */ int dlaord_(char *, integer *, doublereal *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); static doublereal bignum; extern /* Subroutine */ int dlaror_(char *, char *, integer *, integer *, doublereal *, integer *, integer *, doublereal *, integer *), dlarnv_(integer *, integer *, integer *, doublereal *); static doublereal smlnum, eps; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] /* -- 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 ======= DQRT15 generates a matrix with full or deficient rank and of various norms. Arguments ========= SCALE (input) INTEGER SCALE = 1: normally scaled matrix SCALE = 2: matrix scaled up SCALE = 3: matrix scaled down RKSEL (input) INTEGER RKSEL = 1: full rank matrix RKSEL = 2: rank-deficient matrix M (input) INTEGER The number of rows of the matrix A. N (input) INTEGER The number of columns of A. NRHS (input) INTEGER The number of columns of B. A (output) DOUBLE PRECISION array, dimension (LDA,N) The M-by-N matrix A. LDA (input) INTEGER The leading dimension of the array A. B (output) DOUBLE PRECISION array, dimension (LDB, NRHS) A matrix that is in the range space of matrix A. LDB (input) INTEGER The leading dimension of the array B. S (output) DOUBLE PRECISION array, dimension MIN(M,N) Singular values of A. RANK (output) INTEGER number of nonzero singular values of A. NORMA (output) DOUBLE PRECISION one-norm of A. NORMB (output) DOUBLE PRECISION one-norm of B. ISEED (input/output) integer array, dimension (4) seed for random number generator. WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) LWORK (input) INTEGER length of work space required. LWORK >= MAX(M+MIN(M,N),NRHS*MIN(M,N),2*N+M) ===================================================================== Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; b_dim1 = *ldb; b_offset = 1 + b_dim1 * 1; b -= b_offset; --s; --iseed; --work; /* Function Body */ mn = min(*m,*n); /* Computing MAX */ i__1 = *m + mn, i__2 = mn * *nrhs, i__1 = max(i__1,i__2), i__2 = (*n << 1) + *m; if (*lwork < max(i__1,i__2)) { xerbla_("DQRT15", &c__16); return 0; } smlnum = dlamch_("Safe minimum"); bignum = 1. / smlnum; eps = dlamch_("Epsilon"); smlnum = smlnum / eps / eps; bignum = 1. / smlnum; /* Determine rank and (unscaled) singular values */ if (*rksel == 1) { *rank = mn; } else if (*rksel == 2) { *rank = mn * 3 / 4; i__1 = mn; for (j = *rank + 1; j <= i__1; ++j) { s[j] = 0.; /* L10: */ } } else { xerbla_("DQRT15", &c__2); } if (*rank > 0) { /* Nontrivial case */ s[1] = 1.; i__1 = *rank; for (j = 2; j <= i__1; ++j) { L20: temp = dlarnd_(&c__1, &iseed[1]); if (temp > .1) { s[j] = abs(temp); } else { goto L20; } /* L30: */ } dlaord_("Decreasing", rank, &s[1], &c__1); /* Generate 'rank' columns of a random orthogonal matrix in A */ dlarnv_(&c__2, &iseed[1], m, &work[1]); d__1 = 1. / dnrm2_(m, &work[1], &c__1); dscal_(m, &d__1, &work[1], &c__1); dlaset_("Full", m, rank, &c_b18, &c_b19, &a[a_offset], lda) ; dlarf_("Left", m, rank, &work[1], &c__1, &c_b22, &a[a_offset], lda, & work[*m + 1]); /* workspace used: m+mn Generate consistent rhs in the range space of A */ i__1 = *rank * *nrhs; dlarnv_(&c__2, &iseed[1], &i__1, &work[1]); dgemm_("No transpose", "No transpose", m, nrhs, rank, &c_b19, &a[ a_offset], lda, &work[1], rank, &c_b18, &b[b_offset], ldb); /* work space used: <= mn *nrhs generate (unscaled) matrix A */ i__1 = *rank; for (j = 1; j <= i__1; ++j) { dscal_(m, &s[j], &a_ref(1, j), &c__1); /* L40: */ } if (*rank < *n) { i__1 = *n - *rank; dlaset_("Full", m, &i__1, &c_b18, &c_b18, &a_ref(1, *rank + 1), lda); } dlaror_("Right", "No initialization", m, n, &a[a_offset], lda, &iseed[ 1], &work[1], &info); } else { /* work space used 2*n+m Generate null matrix and rhs */ i__1 = mn; for (j = 1; j <= i__1; ++j) { s[j] = 0.; /* L50: */ } dlaset_("Full", m, n, &c_b18, &c_b18, &a[a_offset], lda); dlaset_("Full", m, nrhs, &c_b18, &c_b18, &b[b_offset], ldb) ; } /* Scale the matrix */ if (*scale != 1) { *norma = dlange_("Max", m, n, &a[a_offset], lda, dummy); if (*norma != 0.) { if (*scale == 2) { /* matrix scaled up */ dlascl_("General", &c__0, &c__0, norma, &bignum, m, n, &a[ a_offset], lda, &info); dlascl_("General", &c__0, &c__0, norma, &bignum, &mn, &c__1, & s[1], &mn, &info); dlascl_("General", &c__0, &c__0, norma, &bignum, m, nrhs, &b[ b_offset], ldb, &info); } else if (*scale == 3) { /* matrix scaled down */ dlascl_("General", &c__0, &c__0, norma, &smlnum, m, n, &a[ a_offset], lda, &info); dlascl_("General", &c__0, &c__0, norma, &smlnum, &mn, &c__1, & s[1], &mn, &info); dlascl_("General", &c__0, &c__0, norma, &smlnum, m, nrhs, &b[ b_offset], ldb, &info); } else { xerbla_("DQRT15", &c__1); return 0; } } } *norma = dasum_(&mn, &s[1], &c__1); *normb = dlange_("One-norm", m, nrhs, &b[b_offset], ldb, dummy) ; return 0; /* End of DQRT15 */ } /* dqrt15_ */
doublereal dqrt12_(integer *m, integer *n, doublereal *a, integer *lda, doublereal *s, doublereal *work, integer *lwork) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; doublereal ret_val; /* Local variables */ integer i__, j, mn, iscl, info; doublereal anrm; extern doublereal dnrm2_(integer *, doublereal *, integer *), dasum_( integer *, doublereal *, integer *); extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *), dgebd2_(integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, doublereal * , doublereal *, doublereal *, integer *); doublereal dummy[1]; extern /* Subroutine */ int dlabad_(doublereal *, doublereal *); extern doublereal dlamch_(char *), dlange_(char *, integer *, integer *, doublereal *, integer *, doublereal *); extern /* Subroutine */ int dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *), dbdsqr_(char *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *); doublereal bignum, smlnum, nrmsvl; /* -- LAPACK test routine (version 3.1.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* January 2007 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DQRT12 computes the singular values `svlues' of the upper trapezoid */ /* of A(1:M,1:N) and returns the ratio */ /* || s - svlues||/(||svlues||*eps*max(M,N)) */ /* Arguments */ /* ========= */ /* M (input) INTEGER */ /* The number of rows of the matrix A. */ /* N (input) INTEGER */ /* The number of columns of the matrix A. */ /* A (input) DOUBLE PRECISION array, dimension (LDA,N) */ /* The M-by-N matrix A. Only the upper trapezoid is referenced. */ /* LDA (input) INTEGER */ /* The leading dimension of the array A. */ /* S (input) DOUBLE PRECISION array, dimension (min(M,N)) */ /* The singular values of the matrix A. */ /* WORK (workspace) DOUBLE PRECISION array, dimension (LWORK) */ /* LWORK (input) INTEGER */ /* The length of the array WORK. LWORK >= max(M*N + 4*min(M,N) + */ /* max(M,N), M*N+2*MIN( M, N )+4*N). */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ a_dim1 = *lda; a_offset = 1 + a_dim1; a -= a_offset; --s; --work; /* Function Body */ ret_val = 0.; /* Test that enough workspace is supplied */ /* Computing MAX */ i__1 = *m * *n + (min(*m,*n) << 2) + max(*m,*n), i__2 = *m * *n + (min(*m, *n) << 1) + (*n << 2); if (*lwork < max(i__1,i__2)) { xerbla_("DQRT12", &c__7); return ret_val; } /* Quick return if possible */ mn = min(*m,*n); if ((doublereal) mn <= 0.) { return ret_val; } nrmsvl = dnrm2_(&mn, &s[1], &c__1); /* Copy upper triangle of A into work */ dlaset_("Full", m, n, &c_b6, &c_b6, &work[1], m); i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = min(j,*m); for (i__ = 1; i__ <= i__2; ++i__) { work[(j - 1) * *m + i__] = a[i__ + j * a_dim1]; /* L10: */ } /* L20: */ } /* Get machine parameters */ smlnum = dlamch_("S") / dlamch_("P"); bignum = 1. / smlnum; dlabad_(&smlnum, &bignum); /* Scale work if max entry outside range [SMLNUM,BIGNUM] */ anrm = dlange_("M", m, n, &work[1], m, dummy); iscl = 0; if (anrm > 0. && anrm < smlnum) { /* Scale matrix norm up to SMLNUM */ dlascl_("G", &c__0, &c__0, &anrm, &smlnum, m, n, &work[1], m, &info); iscl = 1; } else if (anrm > bignum) { /* Scale matrix norm down to BIGNUM */ dlascl_("G", &c__0, &c__0, &anrm, &bignum, m, n, &work[1], m, &info); iscl = 1; } if (anrm != 0.) { /* Compute SVD of work */ dgebd2_(m, n, &work[1], m, &work[*m * *n + 1], &work[*m * *n + mn + 1] , &work[*m * *n + (mn << 1) + 1], &work[*m * *n + mn * 3 + 1], &work[*m * *n + (mn << 2) + 1], &info); dbdsqr_("Upper", &mn, &c__0, &c__0, &c__0, &work[*m * *n + 1], &work[* m * *n + mn + 1], dummy, &mn, dummy, &c__1, dummy, &mn, &work[ *m * *n + (mn << 1) + 1], &info); if (iscl == 1) { if (anrm > bignum) { dlascl_("G", &c__0, &c__0, &bignum, &anrm, &mn, &c__1, &work[* m * *n + 1], &mn, &info); } if (anrm < smlnum) { dlascl_("G", &c__0, &c__0, &smlnum, &anrm, &mn, &c__1, &work[* m * *n + 1], &mn, &info); } } } else { i__1 = mn; for (i__ = 1; i__ <= i__1; ++i__) { work[*m * *n + i__] = 0.; /* L30: */ } } /* Compare s and singular values of work */ daxpy_(&mn, &c_b33, &s[1], &c__1, &work[*m * *n + 1], &c__1); ret_val = dasum_(&mn, &work[*m * *n + 1], &c__1) / (dlamch_("Epsilon") * (doublereal) max(*m,*n)); if (nrmsvl != 0.) { ret_val /= nrmsvl; } return ret_val; /* End of DQRT12 */ } /* dqrt12_ */
/* Subroutine */ int dlarge_(integer *n, doublereal *a, integer *lda, integer *iseed, doublereal *work, integer *info) { /* System generated locals */ integer a_dim1, a_offset, i__1; doublereal d__1; /* Builtin functions */ double d_sign(doublereal *, doublereal *); /* Local variables */ extern /* Subroutine */ int dger_(integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *); extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer i; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *), dgemv_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); static doublereal wa, wb, wn; extern /* Subroutine */ int xerbla_(char *, integer *), dlarnv_( integer *, integer *, integer *, doublereal *); static doublereal tau; /* -- LAPACK auxiliary test routine (version 2.0) Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University February 29, 1992 Purpose ======= DLARGE pre- and post-multiplies a real general n by n matrix A with a random orthogonal matrix: A = U*D*U'. Arguments ========= N (input) INTEGER The order of the matrix A. N >= 0. A (input/output) DOUBLE PRECISION array, dimension (LDA,N) On entry, the original n by n matrix A. On exit, A is overwritten by U*A*U' for some random orthogonal matrix U. LDA (input) INTEGER The leading dimension of the array A. LDA >= N. ISEED (input/output) INTEGER array, dimension (4) On entry, the seed of the random number generator; the array elements must be between 0 and 4095, and ISEED(4) must be odd. On exit, the seed is updated. WORK (workspace) DOUBLE PRECISION array, dimension (2*N) INFO (output) INTEGER = 0: successful exit < 0: if INFO = -i, the i-th argument had an illegal value ===================================================================== Test the input arguments Parameter adjustments */ a_dim1 = *lda; a_offset = a_dim1 + 1; a -= a_offset; --iseed; --work; /* Function Body */ *info = 0; if (*n < 0) { *info = -1; } else if (*lda < max(1,*n)) { *info = -3; } if (*info < 0) { i__1 = -(*info); xerbla_("DLARGE", &i__1); return 0; } /* pre- and post-multiply A by random orthogonal matrix */ for (i = *n; i >= 1; --i) { /* generate random reflection */ i__1 = *n - i + 1; dlarnv_(&c__3, &iseed[1], &i__1, &work[1]); i__1 = *n - i + 1; wn = dnrm2_(&i__1, &work[1], &c__1); wa = d_sign(&wn, &work[1]); if (wn == 0.) { tau = 0.; } else { wb = work[1] + wa; i__1 = *n - i; d__1 = 1. / wb; dscal_(&i__1, &d__1, &work[2], &c__1); work[1] = 1.; tau = wb / wa; } /* multiply A(i:n,1:n) by random reflection from the left */ i__1 = *n - i + 1; dgemv_("Transpose", &i__1, n, &c_b8, &a[i + a_dim1], lda, &work[1], & c__1, &c_b10, &work[*n + 1], &c__1); i__1 = *n - i + 1; d__1 = -tau; dger_(&i__1, n, &d__1, &work[1], &c__1, &work[*n + 1], &c__1, &a[i + a_dim1], lda); /* multiply A(1:n,i:n) by random reflection from the right */ i__1 = *n - i + 1; dgemv_("No transpose", n, &i__1, &c_b8, &a[i * a_dim1 + 1], lda, & work[1], &c__1, &c_b10, &work[*n + 1], &c__1); i__1 = *n - i + 1; d__1 = -tau; dger_(n, &i__1, &d__1, &work[*n + 1], &c__1, &work[1], &c__1, &a[i * a_dim1 + 1], lda); /* L10: */ } return 0; /* End of DLARGE */ } /* dlarge_ */
/* Subroutine */ int dlaein_(logical *rightv, logical *noinit, integer *n, doublereal *h__, integer *ldh, doublereal *wr, doublereal *wi, doublereal *vr, doublereal *vi, doublereal *b, integer *ldb, doublereal *work, doublereal *eps3, doublereal *smlnum, doublereal * bignum, integer *info) { /* System generated locals */ integer b_dim1, b_offset, h_dim1, h_offset, i__1, i__2, i__3, i__4; doublereal d__1, d__2, d__3, d__4; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__, j; doublereal w, x, y; integer i1, i2, i3; doublereal w1, ei, ej, xi, xr, rec; integer its, ierr; doublereal temp, norm, vmax; extern doublereal dnrm2_(integer *, doublereal *, integer *); extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); doublereal scale; extern doublereal dasum_(integer *, doublereal *, integer *); char trans[1]; doublereal vcrit, rootn, vnorm; extern doublereal dlapy2_(doublereal *, doublereal *); doublereal absbii, absbjj; extern integer idamax_(integer *, doublereal *, integer *); extern /* Subroutine */ int dladiv_(doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *), dlatrs_( char *, char *, char *, char *, integer *, doublereal *, integer * , doublereal *, doublereal *, doublereal *, integer *); char normin[1]; doublereal nrmsml, growto; /* -- LAPACK auxiliary routine (version 3.4.2) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* September 2012 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; --vr; --vi; b_dim1 = *ldb; b_offset = 1 + b_dim1; b -= b_offset; --work; /* Function Body */ *info = 0; /* GROWTO is the threshold used in the acceptance test for an */ /* eigenvector. */ rootn = sqrt((doublereal) (*n)); growto = .1 / rootn; /* Computing MAX */ d__1 = 1.; d__2 = *eps3 * rootn; // , expr subst nrmsml = max(d__1,d__2) * *smlnum; /* Form B = H - (WR,WI)*I (except that the subdiagonal elements and */ /* the imaginary parts of the diagonal elements are not stored). */ i__1 = *n; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { b[i__ + j * b_dim1] = h__[i__ + j * h_dim1]; /* L10: */ } b[j + j * b_dim1] = h__[j + j * h_dim1] - *wr; /* L20: */ } if (*wi == 0.) { /* Real eigenvalue. */ if (*noinit) { /* Set initial vector. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { vr[i__] = *eps3; /* L30: */ } } else { /* Scale supplied initial vector. */ vnorm = dnrm2_(n, &vr[1], &c__1); d__1 = *eps3 * rootn / max(vnorm,nrmsml); dscal_(n, &d__1, &vr[1], &c__1); } if (*rightv) { /* LU decomposition with partial pivoting of B, replacing zero */ /* pivots by EPS3. */ i__1 = *n - 1; for (i__ = 1; i__ <= i__1; ++i__) { ei = h__[i__ + 1 + i__ * h_dim1]; if ((d__1 = b[i__ + i__ * b_dim1], abs(d__1)) < abs(ei)) { /* Interchange rows and eliminate. */ x = b[i__ + i__ * b_dim1] / ei; b[i__ + i__ * b_dim1] = ei; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { temp = b[i__ + 1 + j * b_dim1]; b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - x * temp; b[i__ + j * b_dim1] = temp; /* L40: */ } } else { /* Eliminate without interchange. */ if (b[i__ + i__ * b_dim1] == 0.) { b[i__ + i__ * b_dim1] = *eps3; } x = ei / b[i__ + i__ * b_dim1]; if (x != 0.) { i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { b[i__ + 1 + j * b_dim1] -= x * b[i__ + j * b_dim1] ; /* L50: */ } } } /* L60: */ } if (b[*n + *n * b_dim1] == 0.) { b[*n + *n * b_dim1] = *eps3; } *(unsigned char *)trans = 'N'; } else { /* UL decomposition with partial pivoting of B, replacing zero */ /* pivots by EPS3. */ for (j = *n; j >= 2; --j) { ej = h__[j + (j - 1) * h_dim1]; if ((d__1 = b[j + j * b_dim1], abs(d__1)) < abs(ej)) { /* Interchange columns and eliminate. */ x = b[j + j * b_dim1] / ej; b[j + j * b_dim1] = ej; i__1 = j - 1; for (i__ = 1; i__ <= i__1; ++i__) { temp = b[i__ + (j - 1) * b_dim1]; b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - x * temp; b[i__ + j * b_dim1] = temp; /* L70: */ } } else { /* Eliminate without interchange. */ if (b[j + j * b_dim1] == 0.) { b[j + j * b_dim1] = *eps3; } x = ej / b[j + j * b_dim1]; if (x != 0.) { i__1 = j - 1; for (i__ = 1; i__ <= i__1; ++i__) { b[i__ + (j - 1) * b_dim1] -= x * b[i__ + j * b_dim1]; /* L80: */ } } } /* L90: */ } if (b[b_dim1 + 1] == 0.) { b[b_dim1 + 1] = *eps3; } *(unsigned char *)trans = 'T'; } *(unsigned char *)normin = 'N'; i__1 = *n; for (its = 1; its <= i__1; ++its) { /* Solve U*x = scale*v for a right eigenvector */ /* or U**T*x = scale*v for a left eigenvector, */ /* overwriting x on v. */ dlatrs_("Upper", trans, "Nonunit", normin, n, &b[b_offset], ldb, & vr[1], &scale, &work[1], &ierr); *(unsigned char *)normin = 'Y'; /* Test for sufficient growth in the norm of v. */ vnorm = dasum_(n, &vr[1], &c__1); if (vnorm >= growto * scale) { goto L120; } /* Choose new orthogonal starting vector and try again. */ temp = *eps3 / (rootn + 1.); vr[1] = *eps3; i__2 = *n; for (i__ = 2; i__ <= i__2; ++i__) { vr[i__] = temp; /* L100: */ } vr[*n - its + 1] -= *eps3 * rootn; /* L110: */ } /* Failure to find eigenvector in N iterations. */ *info = 1; L120: /* Normalize eigenvector. */ i__ = idamax_(n, &vr[1], &c__1); d__2 = 1. / (d__1 = vr[i__], abs(d__1)); dscal_(n, &d__2, &vr[1], &c__1); } else { /* Complex eigenvalue. */ if (*noinit) { /* Set initial vector. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { vr[i__] = *eps3; vi[i__] = 0.; /* L130: */ } } else { /* Scale supplied initial vector. */ d__1 = dnrm2_(n, &vr[1], &c__1); d__2 = dnrm2_(n, &vi[1], &c__1); norm = dlapy2_(&d__1, &d__2); rec = *eps3 * rootn / max(norm,nrmsml); dscal_(n, &rec, &vr[1], &c__1); dscal_(n, &rec, &vi[1], &c__1); } if (*rightv) { /* LU decomposition with partial pivoting of B, replacing zero */ /* pivots by EPS3. */ /* The imaginary part of the (i,j)-th element of U is stored in */ /* B(j+1,i). */ b[b_dim1 + 2] = -(*wi); i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { b[i__ + 1 + b_dim1] = 0.; /* L140: */ } i__1 = *n - 1; for (i__ = 1; i__ <= i__1; ++i__) { absbii = dlapy2_(&b[i__ + i__ * b_dim1], &b[i__ + 1 + i__ * b_dim1]); ei = h__[i__ + 1 + i__ * h_dim1]; if (absbii < abs(ei)) { /* Interchange rows and eliminate. */ xr = b[i__ + i__ * b_dim1] / ei; xi = b[i__ + 1 + i__ * b_dim1] / ei; b[i__ + i__ * b_dim1] = ei; b[i__ + 1 + i__ * b_dim1] = 0.; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { temp = b[i__ + 1 + j * b_dim1]; b[i__ + 1 + j * b_dim1] = b[i__ + j * b_dim1] - xr * temp; b[j + 1 + (i__ + 1) * b_dim1] = b[j + 1 + i__ * b_dim1] - xi * temp; b[i__ + j * b_dim1] = temp; b[j + 1 + i__ * b_dim1] = 0.; /* L150: */ } b[i__ + 2 + i__ * b_dim1] = -(*wi); b[i__ + 1 + (i__ + 1) * b_dim1] -= xi * *wi; b[i__ + 2 + (i__ + 1) * b_dim1] += xr * *wi; } else { /* Eliminate without interchanging rows. */ if (absbii == 0.) { b[i__ + i__ * b_dim1] = *eps3; b[i__ + 1 + i__ * b_dim1] = 0.; absbii = *eps3; } ei = ei / absbii / absbii; xr = b[i__ + i__ * b_dim1] * ei; xi = -b[i__ + 1 + i__ * b_dim1] * ei; i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { b[i__ + 1 + j * b_dim1] = b[i__ + 1 + j * b_dim1] - xr * b[i__ + j * b_dim1] + xi * b[j + 1 + i__ * b_dim1]; b[j + 1 + (i__ + 1) * b_dim1] = -xr * b[j + 1 + i__ * b_dim1] - xi * b[i__ + j * b_dim1]; /* L160: */ } b[i__ + 2 + (i__ + 1) * b_dim1] -= *wi; } /* Compute 1-norm of offdiagonal elements of i-th row. */ i__2 = *n - i__; i__3 = *n - i__; work[i__] = dasum_(&i__2, &b[i__ + (i__ + 1) * b_dim1], ldb) + dasum_(&i__3, &b[i__ + 2 + i__ * b_dim1], &c__1); /* L170: */ } if (b[*n + *n * b_dim1] == 0. && b[*n + 1 + *n * b_dim1] == 0.) { b[*n + *n * b_dim1] = *eps3; } work[*n] = 0.; i1 = *n; i2 = 1; i3 = -1; } else { /* UL decomposition with partial pivoting of conjg(B), */ /* replacing zero pivots by EPS3. */ /* The imaginary part of the (i,j)-th element of U is stored in */ /* B(j+1,i). */ b[*n + 1 + *n * b_dim1] = *wi; i__1 = *n - 1; for (j = 1; j <= i__1; ++j) { b[*n + 1 + j * b_dim1] = 0.; /* L180: */ } for (j = *n; j >= 2; --j) { ej = h__[j + (j - 1) * h_dim1]; absbjj = dlapy2_(&b[j + j * b_dim1], &b[j + 1 + j * b_dim1]); if (absbjj < abs(ej)) { /* Interchange columns and eliminate */ xr = b[j + j * b_dim1] / ej; xi = b[j + 1 + j * b_dim1] / ej; b[j + j * b_dim1] = ej; b[j + 1 + j * b_dim1] = 0.; i__1 = j - 1; for (i__ = 1; i__ <= i__1; ++i__) { temp = b[i__ + (j - 1) * b_dim1]; b[i__ + (j - 1) * b_dim1] = b[i__ + j * b_dim1] - xr * temp; b[j + i__ * b_dim1] = b[j + 1 + i__ * b_dim1] - xi * temp; b[i__ + j * b_dim1] = temp; b[j + 1 + i__ * b_dim1] = 0.; /* L190: */ } b[j + 1 + (j - 1) * b_dim1] = *wi; b[j - 1 + (j - 1) * b_dim1] += xi * *wi; b[j + (j - 1) * b_dim1] -= xr * *wi; } else { /* Eliminate without interchange. */ if (absbjj == 0.) { b[j + j * b_dim1] = *eps3; b[j + 1 + j * b_dim1] = 0.; absbjj = *eps3; } ej = ej / absbjj / absbjj; xr = b[j + j * b_dim1] * ej; xi = -b[j + 1 + j * b_dim1] * ej; i__1 = j - 1; for (i__ = 1; i__ <= i__1; ++i__) { b[i__ + (j - 1) * b_dim1] = b[i__ + (j - 1) * b_dim1] - xr * b[i__ + j * b_dim1] + xi * b[j + 1 + i__ * b_dim1]; b[j + i__ * b_dim1] = -xr * b[j + 1 + i__ * b_dim1] - xi * b[i__ + j * b_dim1]; /* L200: */ } b[j + (j - 1) * b_dim1] += *wi; } /* Compute 1-norm of offdiagonal elements of j-th column. */ i__1 = j - 1; i__2 = j - 1; work[j] = dasum_(&i__1, &b[j * b_dim1 + 1], &c__1) + dasum_(& i__2, &b[j + 1 + b_dim1], ldb); /* L210: */ } if (b[b_dim1 + 1] == 0. && b[b_dim1 + 2] == 0.) { b[b_dim1 + 1] = *eps3; } work[1] = 0.; i1 = 1; i2 = *n; i3 = 1; } i__1 = *n; for (its = 1; its <= i__1; ++its) { scale = 1.; vmax = 1.; vcrit = *bignum; /* Solve U*(xr,xi) = scale*(vr,vi) for a right eigenvector, */ /* or U**T*(xr,xi) = scale*(vr,vi) for a left eigenvector, */ /* overwriting (xr,xi) on (vr,vi). */ i__2 = i2; i__3 = i3; for (i__ = i1; i__3 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += i__3) { if (work[i__] > vcrit) { rec = 1. / vmax; dscal_(n, &rec, &vr[1], &c__1); dscal_(n, &rec, &vi[1], &c__1); scale *= rec; vmax = 1.; vcrit = *bignum; } xr = vr[i__]; xi = vi[i__]; if (*rightv) { i__4 = *n; for (j = i__ + 1; j <= i__4; ++j) { xr = xr - b[i__ + j * b_dim1] * vr[j] + b[j + 1 + i__ * b_dim1] * vi[j]; xi = xi - b[i__ + j * b_dim1] * vi[j] - b[j + 1 + i__ * b_dim1] * vr[j]; /* L220: */ } } else { i__4 = i__ - 1; for (j = 1; j <= i__4; ++j) { xr = xr - b[j + i__ * b_dim1] * vr[j] + b[i__ + 1 + j * b_dim1] * vi[j]; xi = xi - b[j + i__ * b_dim1] * vi[j] - b[i__ + 1 + j * b_dim1] * vr[j]; /* L230: */ } } w = (d__1 = b[i__ + i__ * b_dim1], abs(d__1)) + (d__2 = b[i__ + 1 + i__ * b_dim1], abs(d__2)); if (w > *smlnum) { if (w < 1.) { w1 = abs(xr) + abs(xi); if (w1 > w * *bignum) { rec = 1. / w1; dscal_(n, &rec, &vr[1], &c__1); dscal_(n, &rec, &vi[1], &c__1); xr = vr[i__]; xi = vi[i__]; scale *= rec; vmax *= rec; } } /* Divide by diagonal element of B. */ dladiv_(&xr, &xi, &b[i__ + i__ * b_dim1], &b[i__ + 1 + i__ * b_dim1], &vr[i__], &vi[i__]); /* Computing MAX */ d__3 = (d__1 = vr[i__], abs(d__1)) + (d__2 = vi[i__], abs( d__2)); vmax = max(d__3,vmax); vcrit = *bignum / vmax; } else { i__4 = *n; for (j = 1; j <= i__4; ++j) { vr[j] = 0.; vi[j] = 0.; /* L240: */ } vr[i__] = 1.; vi[i__] = 1.; scale = 0.; vmax = 1.; vcrit = *bignum; } /* L250: */ } /* Test for sufficient growth in the norm of (VR,VI). */ vnorm = dasum_(n, &vr[1], &c__1) + dasum_(n, &vi[1], &c__1); if (vnorm >= growto * scale) { goto L280; } /* Choose a new orthogonal starting vector and try again. */ y = *eps3 / (rootn + 1.); vr[1] = *eps3; vi[1] = 0.; i__3 = *n; for (i__ = 2; i__ <= i__3; ++i__) { vr[i__] = y; vi[i__] = 0.; /* L260: */ } vr[*n - its + 1] -= *eps3 * rootn; /* L270: */ } /* Failure to find eigenvector in N iterations */ *info = 1; L280: /* Normalize eigenvector. */ vnorm = 0.; i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MAX */ d__3 = vnorm; d__4 = (d__1 = vr[i__], abs(d__1)) + (d__2 = vi[i__] , abs(d__2)); // , expr subst vnorm = max(d__3,d__4); /* L290: */ } d__1 = 1. / vnorm; dscal_(n, &d__1, &vr[1], &c__1); d__1 = 1. / vnorm; dscal_(n, &d__1, &vi[1], &c__1); } return 0; /* End of DLAEIN */ }
int fgmr(int n, void (*matvec) (double, double[], double, double[]), void (*psolve) (int, double[], double[]), double *rhs, double *sol, double tol, int im, int *itmax, FILE * fits) { /*---------------------------------------------------------------------- | *** Preconditioned FGMRES *** +----------------------------------------------------------------------- | This is a simple version of the ARMS preconditioned FGMRES algorithm. +----------------------------------------------------------------------- | Y. S. Dec. 2000. -- Apr. 2008 +----------------------------------------------------------------------- | on entry: |---------- | | rhs = real vector of length n containing the right hand side. | sol = real vector of length n containing an initial guess to the | solution on input. | tol = tolerance for stopping iteration | im = Krylov subspace dimension | (itmax) = max number of iterations allowed. | fits = NULL: no output | != NULL: file handle to output " resid vs time and its" | | on return: |---------- | fgmr int = 0 --> successful return. | int = 1 --> convergence not achieved in itmax iterations. | sol = contains an approximate solution (upon successful return). | itmax = has changed. It now contains the number of steps required | to converge -- +----------------------------------------------------------------------- | internal work arrays: |---------- | vv = work array of length [im+1][n] (used to store the Arnoldi | basis) | hh = work array of length [im][im+1] (Householder matrix) | z = work array of length [im][n] to store preconditioned vectors +----------------------------------------------------------------------- | subroutines called : | matvec - matrix-vector multiplication operation | psolve - (right) preconditionning operation | psolve can be a NULL pointer (GMRES without preconditioner) +---------------------------------------------------------------------*/ int maxits = *itmax; int i, i1, ii, j, k, k1, its, retval, i_1 = 1; double **hh, *c, *s, *rs, t, t0; double beta, eps1 = 0.0, gam, **vv, **z; its = 0; vv = (double **)SUPERLU_MALLOC((im + 1) * sizeof(double *)); for (i = 0; i <= im; i++) vv[i] = doubleMalloc(n); z = (double **)SUPERLU_MALLOC(im * sizeof(double *)); hh = (double **)SUPERLU_MALLOC(im * sizeof(double *)); for (i = 0; i < im; i++) { hh[i] = doubleMalloc(i + 2); z[i] = doubleMalloc(n); } c = doubleMalloc(im); s = doubleMalloc(im); rs = doubleMalloc(im + 1); /*---- outer loop starts here ----*/ do { /*---- compute initial residual vector ----*/ matvec(1.0, sol, 0.0, vv[0]); for (j = 0; j < n; j++) vv[0][j] = rhs[j] - vv[0][j]; /* vv[0]= initial residual */ beta = dnrm2_(&n, vv[0], &i_1); /*---- print info if fits != null ----*/ if (fits != NULL && its == 0) fprintf(fits, "%8d %10.2e\n", its, beta); /*if ( beta < tol * dnrm2_(&n, rhs, &i_1) )*/ if ( !(beta >= tol * dnrm2_(&n, rhs, &i_1)) ) break; t = 1.0 / beta; /*---- normalize: vv[0] = vv[0] / beta ----*/ for (j = 0; j < n; j++) vv[0][j] = vv[0][j] * t; if (its == 0) eps1 = tol * beta; /*---- initialize 1-st term of rhs of hessenberg system ----*/ rs[0] = beta; for (i = 0; i < im; i++) { its++; i1 = i + 1; /*------------------------------------------------------------ | (Right) Preconditioning Operation z_{j} = M^{-1} v_{j} +-----------------------------------------------------------*/ if (psolve) psolve(n, z[i], vv[i]); else dcopy_(&n, vv[i], &i_1, z[i], &i_1); /*---- matvec operation w = A z_{j} = A M^{-1} v_{j} ----*/ matvec(1.0, z[i], 0.0, vv[i1]); /*------------------------------------------------------------ | modified gram - schmidt... | h_{i,j} = (w,v_{i}) | w = w - h_{i,j} v_{i} +------------------------------------------------------------*/ t0 = dnrm2_(&n, vv[i1], &i_1); for (j = 0; j <= i; j++) { double negt; t = ddot_(&n, vv[j], &i_1, vv[i1], &i_1); hh[i][j] = t; negt = -t; daxpy_(&n, &negt, vv[j], &i_1, vv[i1], &i_1); } /*---- h_{j+1,j} = ||w||_{2} ----*/ t = dnrm2_(&n, vv[i1], &i_1); while (t < 0.5 * t0) { t0 = t; for (j = 0; j <= i; j++) { double negt; t = ddot_(&n, vv[j], &i_1, vv[i1], &i_1); hh[i][j] += t; negt = -t; daxpy_(&n, &negt, vv[j], &i_1, vv[i1], &i_1); } t = dnrm2_(&n, vv[i1], &i_1); } hh[i][i1] = t; if (t != 0.0) { /*---- v_{j+1} = w / h_{j+1,j} ----*/ t = 1.0 / t; for (k = 0; k < n; k++) vv[i1][k] = vv[i1][k] * t; } /*--------------------------------------------------- | done with modified gram schimdt and arnoldi step | now update factorization of hh +--------------------------------------------------*/ /*-------------------------------------------------------- | perform previous transformations on i-th column of h +-------------------------------------------------------*/ for (k = 1; k <= i; k++) { k1 = k - 1; t = hh[i][k1]; hh[i][k1] = c[k1] * t + s[k1] * hh[i][k]; hh[i][k] = -s[k1] * t + c[k1] * hh[i][k]; } gam = sqrt(pow(hh[i][i], 2) + pow(hh[i][i1], 2)); /*--------------------------------------------------- | if gamma is zero then any small value will do | affect only residual estimate +--------------------------------------------------*/ /* if (gam == 0.0) gam = epsmac; */ /*---- get next plane rotation ---*/ if (gam > 0.0) { c[i] = hh[i][i] / gam; s[i] = hh[i][i1] / gam; } else { c[i] = 1.0; s[i] = 0.0; } rs[i1] = -s[i] * rs[i]; rs[i] = c[i] * rs[i]; /*---------------------------------------------------- | determine residual norm and test for convergence +---------------------------------------------------*/ hh[i][i] = c[i] * hh[i][i] + s[i] * hh[i][i1]; beta = fabs(rs[i1]); if (fits != NULL) fprintf(fits, "%8d %10.2e\n", its, beta); if (beta <= eps1 || its >= maxits) break; } if (i == im) i--; /*---- now compute solution. 1st, solve upper triangular system ----*/ rs[i] = rs[i] / hh[i][i]; for (ii = 1; ii <= i; ii++) { k = i - ii; k1 = k + 1; t = rs[k]; for (j = k1; j <= i; j++) t = t - hh[j][k] * rs[j]; rs[k] = t / hh[k][k]; } /*---- linear combination of v[i]'s to get sol. ----*/ for (j = 0; j <= i; j++) { t = rs[j]; for (k = 0; k < n; k++) sol[k] += t * z[j][k]; } /* calculate the residual and output */ matvec(1.0, sol, 0.0, vv[0]); for (j = 0; j < n; j++) vv[0][j] = rhs[j] - vv[0][j]; /* vv[0]= initial residual */ /*---- print info if fits != null ----*/ beta = dnrm2_(&n, vv[0], &i_1); /*---- restart outer loop if needed ----*/ /*if (beta >= eps1 / tol)*/ if ( !(beta < eps1 / tol) ) { its = maxits + 10; break; } if (beta <= eps1) break; } while(its < maxits); retval = (its >= maxits); for (i = 0; i <= im; i++) SUPERLU_FREE(vv[i]); SUPERLU_FREE(vv); for (i = 0; i < im; i++) { SUPERLU_FREE(hh[i]); SUPERLU_FREE(z[i]); } SUPERLU_FREE(hh); SUPERLU_FREE(z); SUPERLU_FREE(c); SUPERLU_FREE(s); SUPERLU_FREE(rs); *itmax = its; return retval; } /*----end of fgmr ----*/
/*! return its Euclidean norm */ inline double nrm2(const _dcovector& vec) { VERBOSE_REPORT; double val( dnrm2_(vec.l, vec.array, 1) ); vec.destroy(); return val; }
/* Subroutine */ int dlaed9_(integer *k, integer *kstart, integer *kstop, integer *n, doublereal *d__, doublereal *q, integer *ldq, doublereal * rho, doublereal *dlamda, doublereal *w, doublereal *s, integer *lds, integer *info) { /* System generated locals */ integer q_dim1, q_offset, s_dim1, s_offset, i__1, i__2; doublereal d__1; /* Builtin functions */ double sqrt(doublereal), d_sign(doublereal *, doublereal *); /* Local variables */ integer i__, j; doublereal temp; extern doublereal dnrm2_(integer *, doublereal *, integer *); extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *), dlaed4_(integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, integer *); extern doublereal dlamc3_(doublereal *, doublereal *); extern /* Subroutine */ int xerbla_(char *, integer *); /* -- LAPACK routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLAED9 finds the roots of the secular equation, as defined by the */ /* values in D, Z, and RHO, between KSTART and KSTOP. It makes the */ /* appropriate calls to DLAED4 and then stores the new matrix of */ /* eigenvectors for use in calculating the next level of Z vectors. */ /* Arguments */ /* ========= */ /* K (input) INTEGER */ /* The number of terms in the rational function to be solved by */ /* DLAED4. K >= 0. */ /* KSTART (input) INTEGER */ /* KSTOP (input) INTEGER */ /* The updated eigenvalues Lambda(I), KSTART <= I <= KSTOP */ /* are to be computed. 1 <= KSTART <= KSTOP <= K. */ /* N (input) INTEGER */ /* The number of rows and columns in the Q matrix. */ /* N >= K (delation may result in N > K). */ /* D (output) DOUBLE PRECISION array, dimension (N) */ /* D(I) contains the updated eigenvalues */ /* for KSTART <= I <= KSTOP. */ /* Q (workspace) DOUBLE PRECISION array, dimension (LDQ,N) */ /* LDQ (input) INTEGER */ /* The leading dimension of the array Q. LDQ >= max( 1, N ). */ /* RHO (input) DOUBLE PRECISION */ /* The value of the parameter in the rank one update equation. */ /* RHO >= 0 required. */ /* DLAMDA (input) DOUBLE PRECISION array, dimension (K) */ /* The first K elements of this array contain the old roots */ /* of the deflated updating problem. These are the poles */ /* of the secular equation. */ /* W (input) DOUBLE PRECISION array, dimension (K) */ /* The first K elements of this array contain the components */ /* of the deflation-adjusted updating vector. */ /* S (output) DOUBLE PRECISION array, dimension (LDS, K) */ /* Will contain the eigenvectors of the repaired matrix which */ /* will be stored for subsequent Z vector calculation and */ /* multiplied by the previously accumulated eigenvectors */ /* to update the system. */ /* LDS (input) INTEGER */ /* The leading dimension of S. LDS >= max( 1, K ). */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* > 0: if INFO = 1, an eigenvalue did not converge */ /* Further Details */ /* =============== */ /* Based on contributions by */ /* Jeff Rutter, Computer Science Division, University of California */ /* at Berkeley, USA */ /* ===================================================================== */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --d__; q_dim1 = *ldq; q_offset = 1 + q_dim1; q -= q_offset; --dlamda; --w; s_dim1 = *lds; s_offset = 1 + s_dim1; s -= s_offset; /* Function Body */ *info = 0; if (*k < 0) { *info = -1; } else if (*kstart < 1 || *kstart > max(1,*k)) { *info = -2; } else if (max(1,*kstop) < *kstart || *kstop > max(1,*k)) { *info = -3; } else if (*n < *k) { *info = -4; } else if (*ldq < max(1,*k)) { *info = -7; } else if (*lds < max(1,*k)) { *info = -12; } if (*info != 0) { i__1 = -(*info); xerbla_("DLAED9", &i__1); return 0; } /* Quick return if possible */ if (*k == 0) { return 0; } /* Modify values DLAMDA(i) to make sure all DLAMDA(i)-DLAMDA(j) can */ /* be computed with high relative accuracy (barring over/underflow). */ /* This is a problem on machines without a guard digit in */ /* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). */ /* The following code replaces DLAMDA(I) by 2*DLAMDA(I)-DLAMDA(I), */ /* which on any of these machines zeros out the bottommost */ /* bit of DLAMDA(I) if it is 1; this makes the subsequent */ /* subtractions DLAMDA(I)-DLAMDA(J) unproblematic when cancellation */ /* occurs. On binary machines with a guard digit (almost all */ /* machines) it does not change DLAMDA(I) at all. On hexadecimal */ /* and decimal machines with a guard digit, it slightly */ /* changes the bottommost bits of DLAMDA(I). It does not account */ /* for hexadecimal or decimal machines without guard digits */ /* (we know of none). We use a subroutine call to compute */ /* 2*DLAMBDA(I) to prevent optimizing compilers from eliminating */ /* this code. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { dlamda[i__] = dlamc3_(&dlamda[i__], &dlamda[i__]) - dlamda[i__]; /* L10: */ } i__1 = *kstop; for (j = *kstart; j <= i__1; ++j) { dlaed4_(k, &j, &dlamda[1], &w[1], &q[j * q_dim1 + 1], rho, &d__[j], info); /* If the zero finder fails, the computation is terminated. */ if (*info != 0) { goto L120; } /* L20: */ } if (*k == 1 || *k == 2) { i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = *k; for (j = 1; j <= i__2; ++j) { s[j + i__ * s_dim1] = q[j + i__ * q_dim1]; /* L30: */ } /* L40: */ } goto L120; } /* Compute updated W. */ dcopy_(k, &w[1], &c__1, &s[s_offset], &c__1); /* Initialize W(I) = Q(I,I) */ i__1 = *ldq + 1; dcopy_(k, &q[q_offset], &i__1, &w[1], &c__1); i__1 = *k; for (j = 1; j <= i__1; ++j) { i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]); /* L50: */ } i__2 = *k; for (i__ = j + 1; i__ <= i__2; ++i__) { w[i__] *= q[i__ + j * q_dim1] / (dlamda[i__] - dlamda[j]); /* L60: */ } /* L70: */ } i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = sqrt(-w[i__]); w[i__] = d_sign(&d__1, &s[i__ + s_dim1]); /* L80: */ } /* Compute eigenvectors of the modified rank-1 modification. */ i__1 = *k; for (j = 1; j <= i__1; ++j) { i__2 = *k; for (i__ = 1; i__ <= i__2; ++i__) { q[i__ + j * q_dim1] = w[i__] / q[i__ + j * q_dim1]; /* L90: */ } temp = dnrm2_(k, &q[j * q_dim1 + 1], &c__1); i__2 = *k; for (i__ = 1; i__ <= i__2; ++i__) { s[i__ + j * s_dim1] = q[i__ + j * q_dim1] / temp; /* L100: */ } /* L110: */ } L120: return 0; /* End of DLAED9 */ } /* dlaed9_ */
Int TRON::trcg(double delta, double *g, double *s, double *r) { Int i, inc = 1; Int n = fun_obj->get_nr_variable(); double one = 1; double *d = new double[n]; double *Hd = new double[n]; double rTr, rnewTrnew, alpha, beta, cgtol; for (i=0; i<n; i++) { s[i] = 0; r[i] = -g[i]; d[i] = r[i]; } cgtol = eps_cg*dnrm2_(&n, g, &inc); Int cg_iter = 0; rTr = ddot_(&n, r, &inc, r, &inc); while (1) { if (dnrm2_(&n, r, &inc) <= cgtol) break; cg_iter++; fun_obj->Hv(d, Hd); alpha = rTr/ddot_(&n, d, &inc, Hd, &inc); daxpy_(&n, &alpha, d, &inc, s, &inc); if (dnrm2_(&n, s, &inc) > delta) { info("cg reaches trust region boundary\n"); alpha = -alpha; daxpy_(&n, &alpha, d, &inc, s, &inc); double std = ddot_(&n, s, &inc, d, &inc); double sts = ddot_(&n, s, &inc, s, &inc); double dtd = ddot_(&n, d, &inc, d, &inc); double dsq = delta*delta; double rad = sqrt(std*std + dtd*(dsq-sts)); if (std >= 0) alpha = (dsq - sts)/(std + rad); else alpha = (rad - std)/dtd; daxpy_(&n, &alpha, d, &inc, s, &inc); alpha = -alpha; daxpy_(&n, &alpha, Hd, &inc, r, &inc); break; } alpha = -alpha; daxpy_(&n, &alpha, Hd, &inc, r, &inc); rnewTrnew = ddot_(&n, r, &inc, r, &inc); beta = rnewTrnew/rTr; dscal_(&n, &beta, d, &inc); daxpy_(&n, &one, r, &inc, d, &inc); rTr = rnewTrnew; } delete[] d; delete[] Hd; return(cg_iter); }
double dnrm2( int n, double *x, int incx) { return dnrm2_(&n, x, &incx); }
/* Subroutine */extern "C" int dlaqp2_(integer *m, integer *n, integer *offset, doublereal *a, integer *lda, integer *jpvt, doublereal *tau, doublereal *vn1, doublereal *vn2, doublereal *work) { /* -- LAPACK auxiliary 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 ======= DLAQP2 computes a QR factorization with column pivoting of the block A(OFFSET+1:M,1:N). The block A(1:OFFSET,1:N) is accordingly pivoted, but not factorized. Arguments ========= M (input) INTEGER The number of rows of the matrix A. M >= 0. N (input) INTEGER The number of columns of the matrix A. N >= 0. OFFSET (input) INTEGER The number of rows of the matrix A that must be pivoted but no factorized. OFFSET >= 0. A (input/output) DOUBLE PRECISION array, dimension (LDA,N) On entry, the M-by-N matrix A. On exit, the upper triangle of block A(OFFSET+1:M,1:N) is the triangular factor obtained; the elements in block A(OFFSET+1:M,1:N) below the diagonal, together with the array TAU, represent the orthogonal matrix Q as a product of elementary reflectors. Block A(1:OFFSET,1:N) has been accordingly pivoted, but no factorized. LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). JPVT (input/output) INTEGER array, dimension (N) On entry, if JPVT(i) .ne. 0, the i-th column of A is permuted to the front of A*P (a leading column); if JPVT(i) = 0, the i-th column of A is a free column. On exit, if JPVT(i) = k, then the i-th column of A*P was the k-th column of A. TAU (output) DOUBLE PRECISION array, dimension (min(M,N)) The scalar factors of the elementary reflectors. VN1 (input/output) DOUBLE PRECISION array, dimension (N) The vector with the partial column norms. VN2 (input/output) DOUBLE PRECISION array, dimension (N) The vector with the exact column norms. WORK (workspace) DOUBLE PRECISION array, dimension (N) Further Details =============== Based on contributions by G. Quintana-Orti, Depto. de Informatica, Universidad Jaime I, Spain X. Sun, Computer Science Dept., Duke University, USA ===================================================================== Parameter adjustments */ /* Table of constant values */ static integer c__1 = 1; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2, i__3; doublereal d__1, d__2; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static doublereal temp; extern doublereal dnrm2_(integer *, doublereal *, integer *); static doublereal temp2; static integer i__, j; extern /* Subroutine */ int dlarf_(char *, integer *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *, doublereal *); static integer offpi, itemp; extern /* Subroutine */ int dswap_(integer *, doublereal *, integer *, doublereal *, integer *); static integer mn; extern /* Subroutine */ int dlarfg_(integer *, doublereal *, doublereal *, integer *, doublereal *); extern integer idamax_(integer *, doublereal *, integer *); static doublereal aii; static integer pvt; #define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1] a_dim1 = *lda; a_offset = 1 + a_dim1 * 1; a -= a_offset; --jpvt; --tau; --vn1; --vn2; --work; /* Function Body Computing MIN */ i__1 = *m - *offset; mn = min(i__1,*n); /* Compute factorization. */ i__1 = mn; for (i__ = 1; i__ <= i__1; ++i__) { offpi = *offset + i__; /* Determine ith pivot column and swap if necessary. */ i__2 = *n - i__ + 1; int ttt =idamax_(&i__2, &vn1[i__], &c__1);//zfm 可删 2003-1-8 pvt = i__ - 1 + idamax_(&i__2, &vn1[i__], &c__1); //pvt的值决定了交换顺序 //zfm 2003-2-8 if (pvt != i__) { dswap_(m, &a_ref(1, pvt), &c__1, &a_ref(1, i__), &c__1); itemp = jpvt[pvt]; jpvt[pvt] = jpvt[i__]; jpvt[i__] = itemp; vn1[pvt] = vn1[i__]; vn2[pvt] = vn2[i__]; } /* Generate elementary reflector H(i). */ if (offpi < *m) { i__2 = *m - offpi + 1; dlarfg_(&i__2, &a_ref(offpi, i__), &a_ref(offpi + 1, i__), &c__1, &tau[i__]); } else { dlarfg_(&c__1, &a_ref(*m, i__), &a_ref(*m, i__), &c__1, &tau[i__]) ; } if (i__ < *n) { /* Apply H(i)' to A(offset+i:m,i+1:n) from the left. */ aii = a_ref(offpi, i__); a_ref(offpi, i__) = 1.; i__2 = *m - offpi + 1; i__3 = *n - i__; dlarf_("Left", &i__2, &i__3, &a_ref(offpi, i__), &c__1, &tau[i__], &a_ref(offpi, i__ + 1), lda, &work[1]); a_ref(offpi, i__) = aii; } /* Update partial column norms. */ i__2 = *n; for (j = i__ + 1; j <= i__2; ++j) { if (vn1[j] != 0.) { /* Computing 2nd power */ d__2 = (d__1 = a_ref(offpi, j), abs(d__1)) / vn1[j]; temp = 1. - d__2 * d__2; temp = max(temp,0.); /* Computing 2nd power */ d__1 = vn1[j] / vn2[j]; temp2 = temp * .05 * (d__1 * d__1) + 1.; if (temp2 == 1.) { if (offpi < *m) { i__3 = *m - offpi; vn1[j] = dnrm2_(&i__3, &a_ref(offpi + 1, j), &c__1); vn2[j] = vn1[j]; } else { vn1[j] = 0.; vn2[j] = 0.; } } else { vn1[j] *= sqrt(temp); } } /* L10: */ } /* L20: */ } return 0; /* End of DLAQP2 */ } /* dlaqp2_ */
void rIO::printLastInfo(int pIteration, rAverageComplementarity& mu, rRatioInitResCurrentRes& theta, rSolveInfo& solveInfo, rStepLength& alpha, rDirectionParameter& beta, rResiduals& currentRes, rPhase & phase, rSolutions& currentPt, double cputime, int nDim, rVector& b, rBlockSparseMatrix& C, rBlockSparseMatrix* A, rComputeTime& com, rParameter& param, FILE* fpout, FILE* Display, bool printTime) { printOneIteration(pIteration,mu,theta,solveInfo,alpha, beta,currentRes, fpout, Display); double mean = (fabs(solveInfo.objValPrimal) + fabs(solveInfo.objValDual)) / 2.0; double PDgap = fabs(solveInfo.objValPrimal - solveInfo.objValDual); // double dominator; double relgap; if (mean < 1.0) { relgap = PDgap; } else { relgap = PDgap/mean; } double gap = mu.current*nDim; double digits = 1000; // 1000 means infinity in this case digits = -log10(fabs(PDgap/mean)); #if DIMACS_PRINT double b1 = 0.0; for (int k=0; k<b.nDim; ++k) { double tmp = fabs(b.ele[k]); if (b1 < tmp) { b1 = tmp; } } double c1 = 0.0; for (int l=0; l<C.nBlock; ++l) { rSparseMatrix& Cl = C.ele[l]; if (Cl.Sp_De_Di == rSparseMatrix::SPARSE) { for (int i=0; i<Cl.NonZeroCount; ++i) { double tmp = fabs(Cl.sp_ele[i]); if (c1 < tmp) { c1 = tmp; } } } else if (Cl.Sp_De_Di == rSparseMatrix::DENSE) { for (int i=0; i<Cl.nRow*Cl.nCol; ++i) { double tmp = fabs(Cl.de_ele[i]); if (c1 < tmp) { c1 = tmp; } } } else if (Cl.Sp_De_Di == rSparseMatrix::DIAGONAL) { for (int i=0; i<Cl.nCol; ++i) { double tmp = fabs(Cl.di_ele[i]); if (c1 < tmp) { c1 = tmp; } } } } double p_norm = dnrm2_(¤tRes.primalVec.nDim, currentRes.primalVec.ele, &IONE); double d_norm = 0.0; for (int l=0; l<currentRes.dualMat.nBlock; ++l) { int size = C.blockStruct[l]; double tmp; if (size < 0) { size = -size; tmp = dnrm2_(&size,currentRes.dualMat.ele[l].di_ele, &IONE); d_norm += tmp; } else { size = size * size; tmp = dnrm2_(&size,currentRes.dualMat.ele[l].de_ele, &IONE); d_norm += tmp; } } currentPt.workMat.copyFrom(currentPt.xMat); double x_min = rAl::getMinEigenValue(currentPt.workMat, currentPt.xzEigenValues, currentPt.workVec); currentPt.workMat.copyFrom(currentPt.zMat); double z_min = rAl::getMinEigenValue(currentPt.workMat, currentPt.xzEigenValues, currentPt.workVec); double ctx = solveInfo.objValPrimal; double bty = solveInfo.objValDual; double xtz = 0.0; rAl::let(xtz,'=',currentPt.xMat,'.',currentPt.zMat); double err1 = p_norm / (1+b1); double err2 = max( 0.0, - x_min / (1+b1)); double err3 = d_norm / (1+c1); double err4 = max( 0.0, - z_min / (1+c1)); double err5 = (ctx - bty) / (1 + fabs(ctx) + fabs(bty)); double err6 = xtz / (1 + fabs(ctx) + fabs(bty)); #endif if (Display) { fprintf(Display, "\n"); phase.display(Display); fprintf(Display, " Iteration = %d\n", pIteration); fprintf(Display, " mu = %4.16e\n", mu.current); fprintf(Display, "relative gap = %4.16e\n", relgap); fprintf(Display, " gap = %4.16e\n", gap); fprintf(Display, " digits = %4.16e\n", digits); #if REVERSE_PRIMAL_DUAL fprintf(Display, "objValPrimal = %10.16e\n", -solveInfo.objValDual); fprintf(Display, "objValDual = %10.16e\n", -solveInfo.objValPrimal); fprintf(Display, "p.feas.error = %10.16e\n", currentRes.normDualMat); fprintf(Display, "d.feas.error = %10.16e\n", currentRes.normPrimalVec); #else fprintf(Display, "objValPrimal = %10.16e\n", solveInfo.objValPrimal); fprintf(Display, "objValDual = %10.16e\n", solveInfo.objValDual); fprintf(Display, "p.feas.error = %10.16e\n", currentRes.normPrimalVec); fprintf(Display, "d.feas.error = %10.16e\n", currentRes.normDualMat); #endif if (printTime == true) { fprintf(Display, "total time = %.3f\n",cputime); } #if DIMACS_PRINT fprintf(Display, "\n"); fprintf(Display, "* DIMACS_ERROS * \n"); fprintf(Display, "err1 = %4.16e [%40s]\n", err1, "||Ax-b|| / (1+||b||_1) "); fprintf(Display, "err2 = %4.16e [%40s]\n", err2, "max(0, -lambda(x) / (1+||b||_1))"); fprintf(Display, "err3 = %4.16e [%40s]\n", err3, "||A^Ty + z - c || / (1+||c||_1) "); fprintf(Display, "err4 = %4.16e [%40s]\n", err4, "max(0, -lambda(z) / (1+||c||_1))"); fprintf(Display, "err5 = %4.16e [%40s]\n", err5,"(<c,x> - by) / (1 + |<c,x>| + |by|)"); fprintf(Display, "err6 = %4.16e [%40s]\n", err6,"<x,z> / (1 + |<c,x>| + |by|)"); fprintf(Display, "\n"); #endif } if (fpout) { fprintf(fpout, "\n"); phase.display(fpout); fprintf(fpout, " Iteration = %d\n", pIteration); fprintf(fpout, " mu = %4.16e\n", mu.current); fprintf(fpout, "relative gap = %4.16e\n", relgap); fprintf(fpout, " gap = %4.16e\n", gap); fprintf(fpout, " digits = %4.16e\n", digits); #if REVERSE_PRIMAL_DUAL fprintf(fpout, "objValPrimal = %10.10e\n", -solveInfo.objValDual); fprintf(fpout, "objValDual = %10.10e\n", -solveInfo.objValPrimal); fprintf(fpout, "p.feas.error = %10.10e\n", currentRes.normDualMat); fprintf(fpout, "d.feas.error = %10.10e\n", currentRes.normPrimalVec); #else fprintf(fpout, "objValPrimal = %10.10e\n", solveInfo.objValPrimal); fprintf(fpout, "objValDual = %10.10e\n", solveInfo.objValDual); fprintf(fpout, "p.feas.error = %10.10e\n", currentRes.normPrimalVec); fprintf(fpout, "d.feas.error = %10.10e\n", currentRes.normDualMat); #endif fprintf(fpout, "total time = %.3f\n",cputime); #if DIMACS_PRINT fprintf(fpout, "\n"); fprintf(fpout, "* DIMACS_ERROS * \n"); fprintf(fpout, "err1 = %4.16e [%40s]\n", err1, "||Ax-b|| / (1+||b||_1) "); fprintf(fpout, "err2 = %4.16e [%40s]\n", err2, "max(0, -lambda(x) / (1+||b||_1))"); fprintf(fpout, "err3 = %4.16e [%40s]\n", err3, "||A^Ty + z - c || / (1+||c||_1) "); fprintf(fpout, "err4 = %4.16e [%40s]\n", err4, "max(0, -lambda(z) / (1+||c||_1))"); fprintf(fpout, "err5 = %4.16e [%40s]\n", err5,"(<c,x> - by) / (1 + |<c,x>| + |by|)"); fprintf(fpout, "err6 = %4.16e [%40s]\n", err6,"<x,z> / (1 + |<c,x>| + |by|)"); fprintf(fpout, "\n"); #endif fprintf(fpout, "\n\nParameters are\n"); param.display(fpout); com.display(fpout); #if 1 #if REVERSE_PRIMAL_DUAL fprintf(fpout,"xVec = \n"); currentPt.yVec.display(fpout,-1.0); fprintf(fpout,"xMat = \n"); currentPt.zMat.display(fpout); fprintf(fpout,"yMat = \n"); currentPt.xMat.display(fpout); #else currentPt.display(fpout); #endif #endif } }
/* Subroutine */ int dlasd8_(integer *icompq, integer *k, doublereal *d__, doublereal *z__, doublereal *vf, doublereal *vl, doublereal *difl, doublereal *difr, integer *lddifr, doublereal *dsigma, doublereal * work, integer *info) { /* System generated locals */ integer difr_dim1, difr_offset, i__1, i__2; doublereal d__1, d__2; /* Builtin functions */ double sqrt(doublereal), d_sign(doublereal *, doublereal *); /* Local variables */ integer i__, j; doublereal dj, rho; integer iwk1, iwk2, iwk3; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); doublereal temp; extern doublereal dnrm2_(integer *, doublereal *, integer *); integer iwk2i, iwk3i; doublereal diflj, difrj, dsigj; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); extern doublereal dlamc3_(doublereal *, doublereal *); extern /* Subroutine */ int dlasd4_(integer *, integer *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, doublereal *, integer *), dlascl_(char *, integer *, integer *, doublereal *, doublereal *, integer *, integer *, doublereal *, integer *, integer *), dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); doublereal dsigjp; /* -- LAPACK auxiliary routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DLASD8 finds the square roots of the roots of the secular equation, */ /* as defined by the values in DSIGMA and Z. It makes the appropriate */ /* calls to DLASD4, and stores, for each element in D, the distance */ /* to its two nearest poles (elements in DSIGMA). It also updates */ /* the arrays VF and VL, the first and last components of all the */ /* right singular vectors of the original bidiagonal matrix. */ /* DLASD8 is called from DLASD6. */ /* Arguments */ /* ========= */ /* ICOMPQ (input) INTEGER */ /* Specifies whether singular vectors are to be computed in */ /* factored form in the calling routine: */ /* = 0: Compute singular values only. */ /* = 1: Compute singular vectors in factored form as well. */ /* K (input) INTEGER */ /* The number of terms in the rational function to be solved */ /* by DLASD4. K >= 1. */ /* D (output) DOUBLE PRECISION array, dimension ( K ) */ /* On output, D contains the updated singular values. */ /* Z (input) DOUBLE PRECISION array, dimension ( K ) */ /* The first K elements of this array contain the components */ /* of the deflation-adjusted updating row vector. */ /* VF (input/output) DOUBLE PRECISION array, dimension ( K ) */ /* On entry, VF contains information passed through DBEDE8. */ /* On exit, VF contains the first K components of the first */ /* components of all right singular vectors of the bidiagonal */ /* matrix. */ /* VL (input/output) DOUBLE PRECISION array, dimension ( K ) */ /* On entry, VL contains information passed through DBEDE8. */ /* On exit, VL contains the first K components of the last */ /* components of all right singular vectors of the bidiagonal */ /* matrix. */ /* DIFL (output) DOUBLE PRECISION array, dimension ( K ) */ /* On exit, DIFL(I) = D(I) - DSIGMA(I). */ /* DIFR (output) DOUBLE PRECISION array, */ /* dimension ( LDDIFR, 2 ) if ICOMPQ = 1 and */ /* dimension ( K ) if ICOMPQ = 0. */ /* On exit, DIFR(I,1) = D(I) - DSIGMA(I+1), DIFR(K,1) is not */ /* defined and will not be referenced. */ /* If ICOMPQ = 1, DIFR(1:K,2) is an array containing the */ /* normalizing factors for the right singular vector matrix. */ /* LDDIFR (input) INTEGER */ /* The leading dimension of DIFR, must be at least K. */ /* DSIGMA (input) DOUBLE PRECISION array, dimension ( K ) */ /* The first K elements of this array contain the old roots */ /* of the deflated updating problem. These are the poles */ /* of the secular equation. */ /* WORK (workspace) DOUBLE PRECISION array, dimension at least 3 * K */ /* INFO (output) INTEGER */ /* = 0: successful exit. */ /* < 0: if INFO = -i, the i-th argument had an illegal value. */ /* > 0: if INFO = 1, an singular value did not converge */ /* Further Details */ /* =============== */ /* Based on contributions by */ /* Ming Gu and Huan Ren, Computer Science Division, University of */ /* California at Berkeley, USA */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Test the input parameters. */ /* Parameter adjustments */ --d__; --z__; --vf; --vl; --difl; difr_dim1 = *lddifr; difr_offset = 1 + difr_dim1; difr -= difr_offset; --dsigma; --work; /* Function Body */ *info = 0; if (*icompq < 0 || *icompq > 1) { *info = -1; } else if (*k < 1) { *info = -2; } else if (*lddifr < *k) { *info = -9; } if (*info != 0) { i__1 = -(*info); xerbla_("DLASD8", &i__1); return 0; } /* Quick return if possible */ if (*k == 1) { d__[1] = abs(z__[1]); difl[1] = d__[1]; if (*icompq == 1) { difl[2] = 1.; difr[(difr_dim1 << 1) + 1] = 1.; } return 0; } /* Modify values DSIGMA(i) to make sure all DSIGMA(i)-DSIGMA(j) can */ /* be computed with high relative accuracy (barring over/underflow). */ /* This is a problem on machines without a guard digit in */ /* add/subtract (Cray XMP, Cray YMP, Cray C 90 and Cray 2). */ /* The following code replaces DSIGMA(I) by 2*DSIGMA(I)-DSIGMA(I), */ /* which on any of these machines zeros out the bottommost */ /* bit of DSIGMA(I) if it is 1; this makes the subsequent */ /* subtractions DSIGMA(I)-DSIGMA(J) unproblematic when cancellation */ /* occurs. On binary machines with a guard digit (almost all */ /* machines) it does not change DSIGMA(I) at all. On hexadecimal */ /* and decimal machines with a guard digit, it slightly */ /* changes the bottommost bits of DSIGMA(I). It does not account */ /* for hexadecimal or decimal machines without guard digits */ /* (we know of none). We use a subroutine call to compute */ /* 2*DSIGMA(I) to prevent optimizing compilers from eliminating */ /* this code. */ i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { dsigma[i__] = dlamc3_(&dsigma[i__], &dsigma[i__]) - dsigma[i__]; /* L10: */ } /* Book keeping. */ iwk1 = 1; iwk2 = iwk1 + *k; iwk3 = iwk2 + *k; iwk2i = iwk2 - 1; iwk3i = iwk3 - 1; /* Normalize Z. */ rho = dnrm2_(k, &z__[1], &c__1); dlascl_("G", &c__0, &c__0, &rho, &c_b8, k, &c__1, &z__[1], k, info); rho *= rho; /* Initialize WORK(IWK3). */ dlaset_("A", k, &c__1, &c_b8, &c_b8, &work[iwk3], k); /* Compute the updated singular values, the arrays DIFL, DIFR, */ /* and the updated Z. */ i__1 = *k; for (j = 1; j <= i__1; ++j) { dlasd4_(k, &j, &dsigma[1], &z__[1], &work[iwk1], &rho, &d__[j], &work[ iwk2], info); /* If the root finder fails, the computation is terminated. */ if (*info != 0) { return 0; } work[iwk3i + j] = work[iwk3i + j] * work[j] * work[iwk2i + j]; difl[j] = -work[j]; difr[j + difr_dim1] = -work[j + 1]; i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { work[iwk3i + i__] = work[iwk3i + i__] * work[i__] * work[iwk2i + i__] / (dsigma[i__] - dsigma[j]) / (dsigma[i__] + dsigma[ j]); /* L20: */ } i__2 = *k; for (i__ = j + 1; i__ <= i__2; ++i__) { work[iwk3i + i__] = work[iwk3i + i__] * work[i__] * work[iwk2i + i__] / (dsigma[i__] - dsigma[j]) / (dsigma[i__] + dsigma[ j]); /* L30: */ } /* L40: */ } /* Compute updated Z. */ i__1 = *k; for (i__ = 1; i__ <= i__1; ++i__) { d__2 = sqrt((d__1 = work[iwk3i + i__], abs(d__1))); z__[i__] = d_sign(&d__2, &z__[i__]); /* L50: */ } /* Update VF and VL. */ i__1 = *k; for (j = 1; j <= i__1; ++j) { diflj = difl[j]; dj = d__[j]; dsigj = -dsigma[j]; if (j < *k) { difrj = -difr[j + difr_dim1]; dsigjp = -dsigma[j + 1]; } work[j] = -z__[j] / diflj / (dsigma[j] + dj); i__2 = j - 1; for (i__ = 1; i__ <= i__2; ++i__) { work[i__] = z__[i__] / (dlamc3_(&dsigma[i__], &dsigj) - diflj) / ( dsigma[i__] + dj); /* L60: */ } i__2 = *k; for (i__ = j + 1; i__ <= i__2; ++i__) { work[i__] = z__[i__] / (dlamc3_(&dsigma[i__], &dsigjp) + difrj) / (dsigma[i__] + dj); /* L70: */ } temp = dnrm2_(k, &work[1], &c__1); work[iwk2i + j] = ddot_(k, &work[1], &c__1, &vf[1], &c__1) / temp; work[iwk3i + j] = ddot_(k, &work[1], &c__1, &vl[1], &c__1) / temp; if (*icompq == 1) { difr[j + (difr_dim1 << 1)] = temp; } /* L80: */ } dcopy_(k, &work[iwk2], &c__1, &vf[1], &c__1); dcopy_(k, &work[iwk3], &c__1, &vl[1], &c__1); return 0; /* End of DLASD8 */ } /* dlasd8_ */
double dnrm2(const int N, const double *X, const int incX) { return dnrm2_(&N, X, &incX); }
/* Subroutine */ int dlaror_(char *side, char *init, integer *m, integer *n, doublereal *a, integer *lda, integer *iseed, doublereal *x, integer * info) { /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; doublereal d__1; /* Builtin functions */ double d_sign(doublereal *, doublereal *); /* Local variables */ static integer kbeg; extern /* Subroutine */ int dger_(integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, integer *); static integer jcol, irow; extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer j; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); extern logical lsame_(char *, char *); extern /* Subroutine */ int dgemv_(char *, integer *, integer *, doublereal *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *, integer *); static integer ixfrm, itype, nxfrm; static doublereal xnorm; extern doublereal dlarnd_(integer *, integer *); extern /* Subroutine */ int dlaset_(char *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *), xerbla_(char *, integer *); static doublereal factor, xnorms; /* -- LAPACK auxiliary test routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University September 30, 1994 Purpose ======= DLAROR pre- or post-multiplies an M by N matrix A by a random orthogonal matrix U, overwriting A. A may optionally be initialized to the identity matrix before multiplying by U. U is generated using the method of G.W. Stewart (SIAM J. Numer. Anal. 17, 1980, 403-409). Arguments ========= SIDE (input) CHARACTER*1 Specifies whether A is multiplied on the left or right by U. = 'L': Multiply A on the left (premultiply) by U = 'R': Multiply A on the right (postmultiply) by U' = 'C' or 'T': Multiply A on the left by U and the right by U' (Here, U' means U-transpose.) INIT (input) CHARACTER*1 Specifies whether or not A should be initialized to the identity matrix. = 'I': Initialize A to (a section of) the identity matrix before applying U. = 'N': No initialization. Apply U to the input matrix A. INIT = 'I' may be used to generate square or rectangular orthogonal matrices: For M = N and SIDE = 'L' or 'R', the rows will be orthogonal to each other, as will the columns. If M < N, SIDE = 'R' produces a dense matrix whose rows are orthogonal and whose columns are not, while SIDE = 'L' produces a matrix whose rows are orthogonal, and whose first M columns are orthogonal, and whose remaining columns are zero. If M > N, SIDE = 'L' produces a dense matrix whose columns are orthogonal and whose rows are not, while SIDE = 'R' produces a matrix whose columns are orthogonal, and whose first M rows are orthogonal, and whose remaining rows are zero. M (input) INTEGER The number of rows of A. N (input) INTEGER The number of columns of A. A (input/output) DOUBLE PRECISION array, dimension (LDA, N) On entry, the array A. On exit, overwritten by U A ( if SIDE = 'L' ), or by A U ( if SIDE = 'R' ), or by U A U' ( if SIDE = 'C' or 'T'). LDA (input) INTEGER The leading dimension of the array A. LDA >= max(1,M). ISEED (input/output) INTEGER array, dimension (4) On entry ISEED specifies the seed of the random number generator. The array elements should be between 0 and 4095; if not they will be reduced mod 4096. Also, ISEED(4) must be odd. The random number generator uses a linear congruential sequence limited to small integers, and so should produce machine independent random numbers. The values of ISEED are changed on exit, and can be used in the next call to DLAROR to continue the same random number sequence. X (workspace) DOUBLE PRECISION array, dimension (3*MAX( M, N )) Workspace of length 2*M + N if SIDE = 'L', 2*N + M if SIDE = 'R', 3*N if SIDE = 'C' or 'T'. INFO (output) INTEGER An error flag. It is set to: = 0: normal return < 0: if INFO = -k, the k-th argument had an illegal value = 1: if the random numbers generated by DLARND are bad. ===================================================================== Parameter adjustments */ a_dim1 = *lda; a_offset = a_dim1 + 1; a -= a_offset; --iseed; --x; /* Function Body */ if (*n == 0 || *m == 0) { return 0; } itype = 0; if (lsame_(side, "L")) { itype = 1; } else if (lsame_(side, "R")) { itype = 2; } else if (lsame_(side, "C") || lsame_(side, "T")) { itype = 3; } /* Check for argument errors. */ *info = 0; if (itype == 0) { *info = -1; } else if (*m < 0) { *info = -3; } else if (*n < 0 || itype == 3 && *n != *m) { *info = -4; } else if (*lda < *m) { *info = -6; } if (*info != 0) { i__1 = -(*info); xerbla_("DLAROR", &i__1); return 0; } if (itype == 1) { nxfrm = *m; } else { nxfrm = *n; } /* Initialize A to the identity matrix if desired */ if (lsame_(init, "I")) { dlaset_("Full", m, n, &c_b9, &c_b10, &a[a_offset], lda); } /* If no rotation possible, multiply by random +/-1 Compute rotation by computing Householder transformations H(2), H(3), ..., H(nhouse) */ i__1 = nxfrm; for (j = 1; j <= i__1; ++j) { x[j] = 0.; /* L10: */ } i__1 = nxfrm; for (ixfrm = 2; ixfrm <= i__1; ++ixfrm) { kbeg = nxfrm - ixfrm + 1; /* Generate independent normal( 0, 1 ) random numbers */ i__2 = nxfrm; for (j = kbeg; j <= i__2; ++j) { x[j] = dlarnd_(&c__3, &iseed[1]); /* L20: */ } /* Generate a Householder transformation from the random vector X */ xnorm = dnrm2_(&ixfrm, &x[kbeg], &c__1); xnorms = d_sign(&xnorm, &x[kbeg]); d__1 = -x[kbeg]; x[kbeg + nxfrm] = d_sign(&c_b10, &d__1); factor = xnorms * (xnorms + x[kbeg]); if (abs(factor) < 1e-20) { *info = 1; xerbla_("DLAROR", info); return 0; } else { factor = 1. / factor; } x[kbeg] += xnorms; /* Apply Householder transformation to A */ if (itype == 1 || itype == 3) { /* Apply H(k) from the left. */ dgemv_("T", &ixfrm, n, &c_b10, &a[kbeg + a_dim1], lda, &x[kbeg], & c__1, &c_b9, &x[(nxfrm << 1) + 1], &c__1); d__1 = -factor; dger_(&ixfrm, n, &d__1, &x[kbeg], &c__1, &x[(nxfrm << 1) + 1], & c__1, &a[kbeg + a_dim1], lda); } if (itype == 2 || itype == 3) { /* Apply H(k) from the right. */ dgemv_("N", m, &ixfrm, &c_b10, &a[kbeg * a_dim1 + 1], lda, &x[ kbeg], &c__1, &c_b9, &x[(nxfrm << 1) + 1], &c__1); d__1 = -factor; dger_(m, &ixfrm, &d__1, &x[(nxfrm << 1) + 1], &c__1, &x[kbeg], & c__1, &a[kbeg * a_dim1 + 1], lda); } /* L30: */ } d__1 = dlarnd_(&c__3, &iseed[1]); x[nxfrm * 2] = d_sign(&c_b10, &d__1); /* Scale the matrix A by D. */ if (itype == 1 || itype == 3) { i__1 = *m; for (irow = 1; irow <= i__1; ++irow) { dscal_(n, &x[nxfrm + irow], &a[irow + a_dim1], lda); /* L40: */ } } if (itype == 2 || itype == 3) { i__1 = *n; for (jcol = 1; jcol <= i__1; ++jcol) { dscal_(m, &x[nxfrm + jcol], &a[jcol * a_dim1 + 1], &c__1); /* L50: */ } } return 0; /* End of DLAROR */ } /* dlaror_ */
/* DECK DBOLSM */ /* Subroutine */ int dbolsm_(doublereal *w, integer *mdw, integer *minput, integer *ncols, doublereal *bl, doublereal *bu, integer *ind, integer *iopt, doublereal *x, doublereal *rnorm, integer *mode, doublereal * rw, doublereal *ww, doublereal *scl, integer *ibasis, integer *ibb) { /* System generated locals */ address a__1[3], a__2[4], a__3[6], a__4[5], a__5[2], a__6[7]; integer w_dim1, w_offset, i__1[3], i__2[4], i__3, i__4[6], i__5[5], i__6[ 2], i__7[7], i__8, i__9, i__10; doublereal d__1, d__2; char ch__1[47], ch__2[50], ch__3[79], ch__4[53], ch__5[94], ch__6[75], ch__7[83], ch__8[92], ch__9[105], ch__10[102], ch__11[61], ch__12[ 110], ch__13[134], ch__14[44], ch__15[76]; /* Local variables */ static integer i__, j; static doublereal t, t1, t2, sc; static integer ip, jp, lp; static doublereal ss, wt, cl1, cl2, cl3, fac, big; static integer lds; static doublereal bou, beta; static integer jbig, jmag, ioff, jcol; static doublereal wbig; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); static doublereal wmag; static integer mval, iter; extern /* Subroutine */ int drot_(integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); static doublereal xnew; extern doublereal dnrm2_(integer *, doublereal *, integer *); static char xern1[8], xern2[8], xern3[16], xern4[16]; static doublereal alpha; static logical found; static integer nsetb; extern /* Subroutine */ int drotg_(doublereal *, doublereal *, doublereal *, doublereal *), dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); static integer igopr, itmax, itemp; extern /* Subroutine */ int dswap_(integer *, doublereal *, integer *, doublereal *, integer *), daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *); static integer lgopr; extern /* Subroutine */ int dmout_(integer *, integer *, integer *, doublereal *, char *, integer *, ftnlen); static integer jdrop; extern doublereal d1mach_(integer *); extern /* Subroutine */ int dvout_(integer *, doublereal *, char *, integer *, ftnlen), ivout_(integer *, integer *, char *, integer * , ftnlen); static integer mrows, jdrop1, jdrop2, jlarge; static doublereal colabv, colblo, wlarge, tolind; extern /* Subroutine */ int xermsg_(char *, char *, char *, integer *, integer *, ftnlen, ftnlen, ftnlen); static integer iprint; static logical constr; static doublereal tolsze; /* Fortran I/O blocks */ static icilist io___2 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___3 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___4 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___6 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___8 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___9 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___10 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___12 = { 0, xern3, 0, "(1PD15.6)", 16, 1 }; static icilist io___14 = { 0, xern4, 0, "(1PD15.6)", 16, 1 }; static icilist io___15 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___16 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___17 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___18 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___31 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___32 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___33 = { 0, xern3, 0, "(1PD15.6)", 16, 1 }; static icilist io___34 = { 0, xern4, 0, "(1PD15.6)", 16, 1 }; static icilist io___35 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___36 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___37 = { 0, xern3, 0, "(1PD15.6)", 16, 1 }; static icilist io___38 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___39 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___40 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___41 = { 0, xern3, 0, "(1PD15.6)", 16, 1 }; static icilist io___42 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___43 = { 0, xern2, 0, "(I8)", 8, 1 }; static icilist io___44 = { 0, xern3, 0, "(1PD15.6)", 16, 1 }; static icilist io___45 = { 0, xern1, 0, "(I8)", 8, 1 }; static icilist io___54 = { 0, xern1, 0, "(I8)", 8, 1 }; /* ***BEGIN PROLOGUE DBOLSM */ /* ***SUBSIDIARY */ /* ***PURPOSE Subsidiary to DBOCLS and DBOLS */ /* ***LIBRARY SLATEC */ /* ***TYPE DOUBLE PRECISION (SBOLSM-S, DBOLSM-D) */ /* ***AUTHOR (UNKNOWN) */ /* ***DESCRIPTION */ /* **** Double Precision Version of SBOLSM **** */ /* **** All INPUT and OUTPUT real variables are DOUBLE PRECISION **** */ /* Solve E*X = F (least squares sense) with bounds on */ /* selected X values. */ /* The user must have DIMENSION statements of the form: */ /* DIMENSION W(MDW,NCOLS+1), BL(NCOLS), BU(NCOLS), */ /* * X(NCOLS+NX), RW(NCOLS), WW(NCOLS), SCL(NCOLS) */ /* INTEGER IND(NCOLS), IOPT(1+NI), IBASIS(NCOLS), IBB(NCOLS) */ /* (Here NX=number of extra locations required for options 1,...,7; */ /* NX=0 for no options; here NI=number of extra locations possibly */ /* required for options 1-7; NI=0 for no options; NI=14 if all the */ /* options are simultaneously in use.) */ /* INPUT */ /* ----- */ /* -------------------- */ /* W(MDW,*),MINPUT,NCOLS */ /* -------------------- */ /* The array W(*,*) contains the matrix [E:F] on entry. The matrix */ /* [E:F] has MINPUT rows and NCOLS+1 columns. This data is placed in */ /* the array W(*,*) with E occupying the first NCOLS columns and the */ /* right side vector F in column NCOLS+1. The row dimension, MDW, of */ /* the array W(*,*) must satisfy the inequality MDW .ge. MINPUT. */ /* Other values of MDW are errors. The values of MINPUT and NCOLS */ /* must be positive. Other values are errors. */ /* ------------------ */ /* BL(*),BU(*),IND(*) */ /* ------------------ */ /* These arrays contain the information about the bounds that the */ /* solution values are to satisfy. The value of IND(J) tells the */ /* type of bound and BL(J) and BU(J) give the explicit values for */ /* the respective upper and lower bounds. */ /* 1. For IND(J)=1, require X(J) .ge. BL(J). */ /* 2. For IND(J)=2, require X(J) .le. BU(J). */ /* 3. For IND(J)=3, require X(J) .ge. BL(J) and */ /* X(J) .le. BU(J). */ /* 4. For IND(J)=4, no bounds on X(J) are required. */ /* The values of BL(*),BL(*) are modified by the subprogram. Values */ /* other than 1,2,3 or 4 for IND(J) are errors. In the case IND(J)=3 */ /* (upper and lower bounds) the condition BL(J) .gt. BU(J) is an */ /* error. */ /* ------- */ /* IOPT(*) */ /* ------- */ /* This is the array where the user can specify nonstandard options */ /* for DBOLSM. Most of the time this feature can be ignored by */ /* setting the input value IOPT(1)=99. Occasionally users may have */ /* needs that require use of the following subprogram options. For */ /* details about how to use the options see below: IOPT(*) CONTENTS. */ /* Option Number Brief Statement of Purpose */ /* ----- ------ ----- --------- -- ------- */ /* 1 Move the IOPT(*) processing pointer. */ /* 2 Change rank determination tolerance. */ /* 3 Change blow-up factor that determines the */ /* size of variables being dropped from active */ /* status. */ /* 4 Reset the maximum number of iterations to use */ /* in solving the problem. */ /* 5 The data matrix is triangularized before the */ /* problem is solved whenever (NCOLS/MINPUT) .lt. */ /* FAC. Change the value of FAC. */ /* 6 Redefine the weighting matrix used for */ /* linear independence checking. */ /* 7 Debug output is desired. */ /* 99 No more options to change. */ /* ---- */ /* X(*) */ /* ---- */ /* This array is used to pass data associated with options 1,2,3 and */ /* 5. Ignore this input parameter if none of these options are used. */ /* Otherwise see below: IOPT(*) CONTENTS. */ /* ---------------- */ /* IBASIS(*),IBB(*) */ /* ---------------- */ /* These arrays must be initialized by the user. The values */ /* IBASIS(J)=J, J=1,...,NCOLS */ /* IBB(J) =1, J=1,...,NCOLS */ /* are appropriate except when using nonstandard features. */ /* ------ */ /* SCL(*) */ /* ------ */ /* This is the array of scaling factors to use on the columns of the */ /* matrix E. These values must be defined by the user. To suppress */ /* any column scaling set SCL(J)=1.0, J=1,...,NCOLS. */ /* OUTPUT */ /* ------ */ /* ---------- */ /* X(*),RNORM */ /* ---------- */ /* The array X(*) contains a solution (if MODE .ge. 0 or .eq. -22) */ /* for the constrained least squares problem. The value RNORM is the */ /* minimum residual vector length. */ /* ---- */ /* MODE */ /* ---- */ /* The sign of mode determines whether the subprogram has completed */ /* normally, or encountered an error condition or abnormal status. */ /* A value of MODE .ge. 0 signifies that the subprogram has completed */ /* normally. The value of MODE (.ge. 0) is the number of variables */ /* in an active status: not at a bound nor at the value ZERO, for */ /* the case of free variables. A negative value of MODE will be one */ /* of the 18 cases -38,-37,...,-22, or -1. Values .lt. -1 correspond */ /* to an abnormal completion of the subprogram. To understand the */ /* abnormal completion codes see below: ERROR MESSAGES for DBOLSM */ /* An approximate solution will be returned to the user only when */ /* maximum iterations is reached, MODE=-22. */ /* ----------- */ /* RW(*),WW(*) */ /* ----------- */ /* These are working arrays each with NCOLS entries. The array RW(*) */ /* contains the working (scaled, nonactive) solution values. The */ /* array WW(*) contains the working (scaled, active) gradient vector */ /* values. */ /* ---------------- */ /* IBASIS(*),IBB(*) */ /* ---------------- */ /* These arrays contain information about the status of the solution */ /* when MODE .ge. 0. The indices IBASIS(K), K=1,...,MODE, show the */ /* nonactive variables; indices IBASIS(K), K=MODE+1,..., NCOLS are */ /* the active variables. The value (IBB(J)-1) is the number of times */ /* variable J was reflected from its upper bound. (Normally the user */ /* can ignore these parameters.) */ /* IOPT(*) CONTENTS */ /* ------- -------- */ /* The option array allows a user to modify internal variables in */ /* the subprogram without recompiling the source code. A central */ /* goal of the initial software design was to do a good job for most */ /* people. Thus the use of options will be restricted to a select */ /* group of users. The processing of the option array proceeds as */ /* follows: a pointer, here called LP, is initially set to the value */ /* 1. The value is updated as the options are processed. At the */ /* pointer position the option number is extracted and used for */ /* locating other information that allows for options to be changed. */ /* The portion of the array IOPT(*) that is used for each option is */ /* fixed; the user and the subprogram both know how many locations */ /* are needed for each option. A great deal of error checking is */ /* done by the subprogram on the contents of the option array. */ /* Nevertheless it is still possible to give the subprogram optional */ /* input that is meaningless. For example, some of the options use */ /* the location X(NCOLS+IOFF) for passing data. The user must manage */ /* the allocation of these locations when more than one piece of */ /* option data is being passed to the subprogram. */ /* 1 */ /* - */ /* Move the processing pointer (either forward or backward) to the */ /* location IOPT(LP+1). The processing pointer is moved to location */ /* LP+2 of IOPT(*) in case IOPT(LP)=-1. For example to skip over */ /* locations 3,...,NCOLS+2 of IOPT(*), */ /* IOPT(1)=1 */ /* IOPT(2)=NCOLS+3 */ /* (IOPT(I), I=3,...,NCOLS+2 are not defined here.) */ /* IOPT(NCOLS+3)=99 */ /* CALL DBOLSM */ /* CAUTION: Misuse of this option can yield some very hard-to-find */ /* bugs. Use it with care. */ /* 2 */ /* - */ /* The algorithm that solves the bounded least squares problem */ /* iteratively drops columns from the active set. This has the */ /* effect of joining a new column vector to the QR factorization of */ /* the rectangular matrix consisting of the partially triangularized */ /* nonactive columns. After triangularizing this matrix a test is */ /* made on the size of the pivot element. The column vector is */ /* rejected as dependent if the magnitude of the pivot element is */ /* .le. TOL* magnitude of the column in components strictly above */ /* the pivot element. Nominally the value of this (rank) tolerance */ /* is TOL = SQRT(R1MACH(4)). To change only the value of TOL, for */ /* example, */ /* X(NCOLS+1)=TOL */ /* IOPT(1)=2 */ /* IOPT(2)=1 */ /* IOPT(3)=99 */ /* CALL DBOLSM */ /* Generally, if LP is the processing pointer for IOPT(*), */ /* X(NCOLS+IOFF)=TOL */ /* IOPT(LP)=2 */ /* IOPT(LP+1)=IOFF */ /* . */ /* CALL DBOLSM */ /* The required length of IOPT(*) is increased by 2 if option 2 is */ /* used; The required length of X(*) is increased by 1. A value of */ /* IOFF .le. 0 is an error. A value of TOL .le. R1MACH(4) gives a */ /* warning message; it is not considered an error. */ /* 3 */ /* - */ /* A solution component is left active (not used) if, roughly */ /* speaking, it seems too large. Mathematically the new component is */ /* left active if the magnitude is .ge.((vector norm of F)/(matrix */ /* norm of E))/BLOWUP. Nominally the factor BLOWUP = SQRT(R1MACH(4)). */ /* To change only the value of BLOWUP, for example, */ /* X(NCOLS+2)=BLOWUP */ /* IOPT(1)=3 */ /* IOPT(2)=2 */ /* IOPT(3)=99 */ /* CALL DBOLSM */ /* Generally, if LP is the processing pointer for IOPT(*), */ /* X(NCOLS+IOFF)=BLOWUP */ /* IOPT(LP)=3 */ /* IOPT(LP+1)=IOFF */ /* . */ /* CALL DBOLSM */ /* The required length of IOPT(*) is increased by 2 if option 3 is */ /* used; the required length of X(*) is increased by 1. A value of */ /* IOFF .le. 0 is an error. A value of BLOWUP .le. 0.0 is an error. */ /* 4 */ /* - */ /* Normally the algorithm for solving the bounded least squares */ /* problem requires between NCOLS/3 and NCOLS drop-add steps to */ /* converge. (this remark is based on examining a small number of */ /* test cases.) The amount of arithmetic for such problems is */ /* typically about twice that required for linear least squares if */ /* there are no bounds and if plane rotations are used in the */ /* solution method. Convergence of the algorithm, while */ /* mathematically certain, can be much slower than indicated. To */ /* avoid this potential but unlikely event ITMAX drop-add steps are */ /* permitted. Nominally ITMAX=5*(MAX(MINPUT,NCOLS)). To change the */ /* value of ITMAX, for example, */ /* IOPT(1)=4 */ /* IOPT(2)=ITMAX */ /* IOPT(3)=99 */ /* CALL DBOLSM */ /* Generally, if LP is the processing pointer for IOPT(*), */ /* IOPT(LP)=4 */ /* IOPT(LP+1)=ITMAX */ /* . */ /* CALL DBOLSM */ /* The value of ITMAX must be .gt. 0. Other values are errors. Use */ /* of this option increases the required length of IOPT(*) by 2. */ /* 5 */ /* - */ /* For purposes of increased efficiency the MINPUT by NCOLS+1 data */ /* matrix [E:F] is triangularized as a first step whenever MINPUT */ /* satisfies FAC*MINPUT .gt. NCOLS. Nominally FAC=0.75. To change the */ /* value of FAC, */ /* X(NCOLS+3)=FAC */ /* IOPT(1)=5 */ /* IOPT(2)=3 */ /* IOPT(3)=99 */ /* CALL DBOLSM */ /* Generally, if LP is the processing pointer for IOPT(*), */ /* X(NCOLS+IOFF)=FAC */ /* IOPT(LP)=5 */ /* IOPT(LP+1)=IOFF */ /* . */ /* CALL DBOLSM */ /* The value of FAC must be nonnegative. Other values are errors. */ /* Resetting FAC=0.0 suppresses the initial triangularization step. */ /* Use of this option increases the required length of IOPT(*) by 2; */ /* The required length of of X(*) is increased by 1. */ /* 6 */ /* - */ /* The norm used in testing the magnitudes of the pivot element */ /* compared to the mass of the column above the pivot line can be */ /* changed. The type of change that this option allows is to weight */ /* the components with an index larger than MVAL by the parameter */ /* WT. Normally MVAL=0 and WT=1. To change both the values MVAL and */ /* WT, where LP is the processing pointer for IOPT(*), */ /* X(NCOLS+IOFF)=WT */ /* IOPT(LP)=6 */ /* IOPT(LP+1)=IOFF */ /* IOPT(LP+2)=MVAL */ /* Use of this option increases the required length of IOPT(*) by 3. */ /* The length of X(*) is increased by 1. Values of MVAL must be */ /* nonnegative and not greater than MINPUT. Other values are errors. */ /* The value of WT must be positive. Any other value is an error. If */ /* either error condition is present a message will be printed. */ /* 7 */ /* - */ /* Debug output, showing the detailed add-drop steps for the */ /* constrained least squares problem, is desired. This option is */ /* intended to be used to locate suspected bugs. */ /* 99 */ /* -- */ /* There are no more options to change. */ /* The values for options are 1,...,7,99, and are the only ones */ /* permitted. Other values are errors. Options -99,-1,...,-7 mean */ /* that the repective options 99,1,...,7 are left at their default */ /* values. An example is the option to modify the (rank) tolerance: */ /* X(NCOLS+1)=TOL */ /* IOPT(1)=-2 */ /* IOPT(2)=1 */ /* IOPT(3)=99 */ /* Error Messages for DBOLSM */ /* ----- -------- --- --------- */ /* -22 MORE THAN ITMAX = ... ITERATIONS SOLVING BOUNDED LEAST */ /* SQUARES PROBLEM. */ /* -23 THE OPTION NUMBER = ... IS NOT DEFINED. */ /* -24 THE OFFSET = ... BEYOND POSTION NCOLS = ... MUST BE POSITIVE */ /* FOR OPTION NUMBER 2. */ /* -25 THE TOLERANCE FOR RANK DETERMINATION = ... IS LESS THAN */ /* MACHINE PRECISION = .... */ /* -26 THE OFFSET = ... BEYOND POSITION NCOLS = ... MUST BE POSTIVE */ /* FOR OPTION NUMBER 3. */ /* -27 THE RECIPROCAL OF THE BLOW-UP FACTOR FOR REJECTING VARIABLES */ /* MUST BE POSITIVE. NOW = .... */ /* -28 THE MAXIMUM NUMBER OF ITERATIONS = ... MUST BE POSITIVE. */ /* -29 THE OFFSET = ... BEYOND POSITION NCOLS = ... MUST BE POSTIVE */ /* FOR OPTION NUMBER 5. */ /* -30 THE FACTOR (NCOLS/MINPUT) WHERE PRETRIANGULARIZING IS */ /* PERFORMED MUST BE NONNEGATIVE. NOW = .... */ /* -31 THE NUMBER OF ROWS = ... MUST BE POSITIVE. */ /* -32 THE NUMBER OF COLUMNS = ... MUST BE POSTIVE. */ /* -33 THE ROW DIMENSION OF W(,) = ... MUST BE .GE. THE NUMBER OF */ /* ROWS = .... */ /* -34 FOR J = ... THE CONSTRAINT INDICATOR MUST BE 1-4. */ /* -35 FOR J = ... THE LOWER BOUND = ... IS .GT. THE UPPER BOUND = */ /* .... */ /* -36 THE INPUT ORDER OF COLUMNS = ... IS NOT BETWEEN 1 AND NCOLS */ /* = .... */ /* -37 THE BOUND POLARITY FLAG IN COMPONENT J = ... MUST BE */ /* POSITIVE. NOW = .... */ /* -38 THE ROW SEPARATOR TO APPLY WEIGHTING (...) MUST LIE BETWEEN */ /* 0 AND MINPUT = .... WEIGHT = ... MUST BE POSITIVE. */ /* ***SEE ALSO DBOCLS, DBOLS */ /* ***ROUTINES CALLED D1MACH, DAXPY, DCOPY, DDOT, DMOUT, DNRM2, DROT, */ /* DROTG, DSWAP, DVOUT, IVOUT, XERMSG */ /* ***REVISION HISTORY (YYMMDD) */ /* 821220 DATE WRITTEN */ /* 891214 Prologue converted to Version 4.0 format. (BAB) */ /* 900328 Added TYPE section. (WRB) */ /* 900510 Convert XERRWV calls to XERMSG calls. (RWC) */ /* 920422 Fixed usage of MINPUT. (WRB) */ /* 901009 Editorial changes, code now reads from top to bottom. (RWC) */ /* ***END PROLOGUE DBOLSM */ /* PURPOSE */ /* ------- */ /* THIS IS THE MAIN SUBPROGRAM THAT SOLVES THE BOUNDED */ /* LEAST SQUARES PROBLEM. THE PROBLEM SOLVED HERE IS: */ /* SOLVE E*X = F (LEAST SQUARES SENSE) */ /* WITH BOUNDS ON SELECTED X VALUES. */ /* TO CHANGE THIS SUBPROGRAM FROM SINGLE TO DOUBLE PRECISION BEGIN */ /* EDITING AT THE CARD 'C++'. */ /* CHANGE THE SUBPROGRAM NAME TO DBOLSM AND THE STRINGS */ /* /SAXPY/ TO /DAXPY/, /SCOPY/ TO /DCOPY/, */ /* /SDOT/ TO /DDOT/, /SNRM2/ TO /DNRM2/, */ /* /SROT/ TO /DROT/, /SROTG/ TO /DROTG/, /R1MACH/ TO /D1MACH/, */ /* /SVOUT/ TO /DVOUT/, /SMOUT/ TO /DMOUT/, */ /* /SSWAP/ TO /DSWAP/, /E0/ TO /D0/, */ /* /REAL / TO /DOUBLE PRECISION/. */ /* ++ */ /* ***FIRST EXECUTABLE STATEMENT DBOLSM */ /* Verify that the problem dimensions are defined properly. */ /* Parameter adjustments */ w_dim1 = *mdw; w_offset = 1 + w_dim1; w -= w_offset; --bl; --bu; --ind; --iopt; --x; --rw; --ww; --scl; --ibasis; --ibb; /* Function Body */ if (*minput <= 0) { s_wsfi(&io___2); do_fio(&c__1, (char *)&(*minput), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 21, a__1[0] = "THE NUMBER OF ROWS = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 18, a__1[2] = " MUST BE POSITIVE."; s_cat(ch__1, a__1, i__1, &c__3, (ftnlen)47); xermsg_("SLATEC", "DBOLSM", ch__1, &c__31, &c__1, (ftnlen)6, (ftnlen) 6, (ftnlen)47); *mode = -31; return 0; } if (*ncols <= 0) { s_wsfi(&io___3); do_fio(&c__1, (char *)&(*ncols), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 24, a__1[0] = "THE NUMBER OF COLUMNS = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 18, a__1[2] = " MUST BE POSITIVE."; s_cat(ch__2, a__1, i__1, &c__3, (ftnlen)50); xermsg_("SLATEC", "DBOLSM", ch__2, &c__32, &c__1, (ftnlen)6, (ftnlen) 6, (ftnlen)50); *mode = -32; return 0; } if (*mdw < *minput) { s_wsfi(&io___4); do_fio(&c__1, (char *)&(*mdw), (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___6); do_fio(&c__1, (char *)&(*minput), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__2[0] = 28, a__2[0] = "THE ROW DIMENSION OF W(,) = "; i__2[1] = 8, a__2[1] = xern1; i__2[2] = 35, a__2[2] = " MUST BE .GE. THE NUMBER OF ROWS = "; i__2[3] = 8, a__2[3] = xern2; s_cat(ch__3, a__2, i__2, &c__4, (ftnlen)79); xermsg_("SLATEC", "DBOLSM", ch__3, &c__33, &c__1, (ftnlen)6, (ftnlen) 6, (ftnlen)79); *mode = -33; return 0; } /* Verify that bound information is correct. */ i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (ind[j] < 1 || ind[j] > 4) { s_wsfi(&io___8); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___9); do_fio(&c__1, (char *)&ind[j], (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 8, a__1[0] = "FOR J = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 37, a__1[2] = " THE CONSTRAINT INDICATOR MUST BE 1-4"; s_cat(ch__4, a__1, i__1, &c__3, (ftnlen)53); xermsg_("SLATEC", "DBOLSM", ch__4, &c__34, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)53); *mode = -34; return 0; } /* L10: */ } i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (ind[j] == 3) { if (bu[j] < bl[j]) { s_wsfi(&io___10); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___12); do_fio(&c__1, (char *)&bl[j], (ftnlen)sizeof(doublereal)); e_wsfi(); s_wsfi(&io___14); do_fio(&c__1, (char *)&bu[j], (ftnlen)sizeof(doublereal)); e_wsfi(); /* Writing concatenation */ i__4[0] = 8, a__3[0] = "FOR J = "; i__4[1] = 8, a__3[1] = xern1; i__4[2] = 19, a__3[2] = " THE LOWER BOUND = "; i__4[3] = 16, a__3[3] = xern3; i__4[4] = 27, a__3[4] = " IS .GT. THE UPPER BOUND = "; i__4[5] = 16, a__3[5] = xern4; s_cat(ch__5, a__3, i__4, &c__6, (ftnlen)94); xermsg_("SLATEC", "DBOLSM", ch__5, &c__35, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)94); *mode = -35; return 0; } } /* L20: */ } /* Check that permutation and polarity arrays have been set. */ i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (ibasis[j] < 1 || ibasis[j] > *ncols) { s_wsfi(&io___15); do_fio(&c__1, (char *)&ibasis[j], (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___16); do_fio(&c__1, (char *)&(*ncols), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__2[0] = 29, a__2[0] = "THE INPUT ORDER OF COLUMNS = "; i__2[1] = 8, a__2[1] = xern1; i__2[2] = 30, a__2[2] = " IS NOT BETWEEN 1 AND NCOLS = "; i__2[3] = 8, a__2[3] = xern2; s_cat(ch__6, a__2, i__2, &c__4, (ftnlen)75); xermsg_("SLATEC", "DBOLSM", ch__6, &c__36, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)75); *mode = -36; return 0; } if (ibb[j] <= 0) { s_wsfi(&io___17); do_fio(&c__1, (char *)&j, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___18); do_fio(&c__1, (char *)&ibb[j], (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__2[0] = 41, a__2[0] = "THE BOUND POLARITY FLAG IN COMPONENT J " "= "; i__2[1] = 8, a__2[1] = xern1; i__2[2] = 26, a__2[2] = " MUST BE POSITIVE.$$NOW = "; i__2[3] = 8, a__2[3] = xern2; s_cat(ch__7, a__2, i__2, &c__4, (ftnlen)83); xermsg_("SLATEC", "DBOLSM", ch__7, &c__37, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)83); *mode = -37; return 0; } /* L30: */ } /* Process the option array. */ fac = .75; tolind = sqrt(d1mach_(&c__4)); tolsze = sqrt(d1mach_(&c__4)); itmax = max(*minput,*ncols) * 5; wt = 1.; mval = 0; iprint = 0; /* Changes to some parameters can occur through the option array, */ /* IOPT(*). Process this array looking carefully for input data */ /* errors. */ lp = 0; lds = 0; /* Test for no more options. */ L590: lp += lds; ip = iopt[lp + 1]; jp = abs(ip); if (ip == 99) { goto L470; } else if (jp == 99) { lds = 1; } else if (jp == 1) { /* Move the IOPT(*) processing pointer. */ if (ip > 0) { lp = iopt[lp + 2] - 1; lds = 0; } else { lds = 2; } } else if (jp == 2) { /* Change tolerance for rank determination. */ if (ip > 0) { ioff = iopt[lp + 2]; if (ioff <= 0) { s_wsfi(&io___31); do_fio(&c__1, (char *)&ioff, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___32); do_fio(&c__1, (char *)&(*ncols), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__5[0] = 13, a__4[0] = "THE OFFSET = "; i__5[1] = 8, a__4[1] = xern1; i__5[2] = 25, a__4[2] = " BEYOND POSITION NCOLS = "; i__5[3] = 8, a__4[3] = xern2; i__5[4] = 38, a__4[4] = " MUST BE POSITIVE FOR OPTION NUMBER" " 2."; s_cat(ch__8, a__4, i__5, &c__5, (ftnlen)92); xermsg_("SLATEC", "DBOLSM", ch__8, &c__24, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)92); *mode = -24; return 0; } tolind = x[*ncols + ioff]; if (tolind < d1mach_(&c__4)) { s_wsfi(&io___33); do_fio(&c__1, (char *)&tolind, (ftnlen)sizeof(doublereal)); e_wsfi(); s_wsfi(&io___34); d__1 = d1mach_(&c__4); do_fio(&c__1, (char *)&d__1, (ftnlen)sizeof(doublereal)); e_wsfi(); /* Writing concatenation */ i__2[0] = 39, a__2[0] = "THE TOLERANCE FOR RANK DETERMINATIO" "N = "; i__2[1] = 16, a__2[1] = xern3; i__2[2] = 34, a__2[2] = " IS LESS THAN MACHINE PRECISION = "; i__2[3] = 16, a__2[3] = xern4; s_cat(ch__9, a__2, i__2, &c__4, (ftnlen)105); xermsg_("SLATEC", "DBOLSM", ch__9, &c__25, &c__0, (ftnlen)6, ( ftnlen)6, (ftnlen)105); *mode = -25; } } lds = 2; } else if (jp == 3) { /* Change blowup factor for allowing variables to become */ /* inactive. */ if (ip > 0) { ioff = iopt[lp + 2]; if (ioff <= 0) { s_wsfi(&io___35); do_fio(&c__1, (char *)&ioff, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___36); do_fio(&c__1, (char *)&(*ncols), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__5[0] = 13, a__4[0] = "THE OFFSET = "; i__5[1] = 8, a__4[1] = xern1; i__5[2] = 25, a__4[2] = " BEYOND POSITION NCOLS = "; i__5[3] = 8, a__4[3] = xern2; i__5[4] = 38, a__4[4] = " MUST BE POSITIVE FOR OPTION NUMBER" " 3."; s_cat(ch__8, a__4, i__5, &c__5, (ftnlen)92); xermsg_("SLATEC", "DBOLSM", ch__8, &c__26, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)92); *mode = -26; return 0; } tolsze = x[*ncols + ioff]; if (tolsze <= 0.) { s_wsfi(&io___37); do_fio(&c__1, (char *)&tolsze, (ftnlen)sizeof(doublereal)); e_wsfi(); /* Writing concatenation */ i__6[0] = 86, a__5[0] = "THE RECIPROCAL OF THE BLOW-UP FACTO" "R FOR REJECTING VARIABLES MUST BE POSITIVE.$$NOW = "; i__6[1] = 16, a__5[1] = xern3; s_cat(ch__10, a__5, i__6, &c__2, (ftnlen)102); xermsg_("SLATEC", "DBOLSM", ch__10, &c__27, &c__1, (ftnlen)6, (ftnlen)6, (ftnlen)102); *mode = -27; return 0; } } lds = 2; } else if (jp == 4) { /* Change the maximum number of iterations allowed. */ if (ip > 0) { itmax = iopt[lp + 2]; if (itmax <= 0) { s_wsfi(&io___38); do_fio(&c__1, (char *)&itmax, (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 35, a__1[0] = "THE MAXIMUM NUMBER OF ITERATIONS = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 18, a__1[2] = " MUST BE POSITIVE."; s_cat(ch__11, a__1, i__1, &c__3, (ftnlen)61); xermsg_("SLATEC", "DBOLSM", ch__11, &c__28, &c__1, (ftnlen)6, (ftnlen)6, (ftnlen)61); *mode = -28; return 0; } } lds = 2; } else if (jp == 5) { /* Change the factor for pretriangularizing the data matrix. */ if (ip > 0) { ioff = iopt[lp + 2]; if (ioff <= 0) { s_wsfi(&io___39); do_fio(&c__1, (char *)&ioff, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___40); do_fio(&c__1, (char *)&(*ncols), (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__5[0] = 13, a__4[0] = "THE OFFSET = "; i__5[1] = 8, a__4[1] = xern1; i__5[2] = 25, a__4[2] = " BEYOND POSITION NCOLS = "; i__5[3] = 8, a__4[3] = xern2; i__5[4] = 38, a__4[4] = " MUST BE POSITIVE FOR OPTION NUMBER" " 5."; s_cat(ch__8, a__4, i__5, &c__5, (ftnlen)92); xermsg_("SLATEC", "DBOLSM", ch__8, &c__29, &c__1, (ftnlen)6, ( ftnlen)6, (ftnlen)92); *mode = -29; return 0; } fac = x[*ncols + ioff]; if (fac < 0.) { s_wsfi(&io___41); do_fio(&c__1, (char *)&fac, (ftnlen)sizeof(doublereal)); e_wsfi(); /* Writing concatenation */ i__6[0] = 94, a__5[0] = "THE FACTOR (NCOLS/MINPUT) WHERE PRE" "-TRIANGULARIZING IS PERFORMED MUST BE NON-NEGATIVE.$" "$NOW = "; i__6[1] = 16, a__5[1] = xern3; s_cat(ch__12, a__5, i__6, &c__2, (ftnlen)110); xermsg_("SLATEC", "DBOLSM", ch__12, &c__30, &c__0, (ftnlen)6, (ftnlen)6, (ftnlen)110); *mode = -30; return 0; } } lds = 2; } else if (jp == 6) { /* Change the weighting factor (from 1.0) to apply to components */ /* numbered .gt. MVAL (initially set to 1.) This trick is needed */ /* for applications of this subprogram to the heavily weighted */ /* least squares problem that come from equality constraints. */ if (ip > 0) { ioff = iopt[lp + 2]; mval = iopt[lp + 3]; wt = x[*ncols + ioff]; } if (mval < 0 || mval > *minput || wt <= 0.) { s_wsfi(&io___42); do_fio(&c__1, (char *)&mval, (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___43); do_fio(&c__1, (char *)&(*minput), (ftnlen)sizeof(integer)); e_wsfi(); s_wsfi(&io___44); do_fio(&c__1, (char *)&wt, (ftnlen)sizeof(doublereal)); e_wsfi(); /* Writing concatenation */ i__7[0] = 38, a__6[0] = "THE ROW SEPARATOR TO APPLY WEIGHTING ("; i__7[1] = 8, a__6[1] = xern1; i__7[2] = 34, a__6[2] = ") MUST LIE BETWEEN 0 AND MINPUT = "; i__7[3] = 8, a__6[3] = xern2; i__7[4] = 12, a__6[4] = ".$$WEIGHT = "; i__7[5] = 16, a__6[5] = xern3; i__7[6] = 18, a__6[6] = " MUST BE POSITIVE."; s_cat(ch__13, a__6, i__7, &c__7, (ftnlen)134); xermsg_("SLATEC", "DBOLSM", ch__13, &c__38, &c__0, (ftnlen)6, ( ftnlen)6, (ftnlen)134); *mode = -38; return 0; } lds = 3; } else if (jp == 7) { /* Turn on debug output. */ if (ip > 0) { iprint = 1; } lds = 2; } else { s_wsfi(&io___45); do_fio(&c__1, (char *)&ip, (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 20, a__1[0] = "THE OPTION NUMBER = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 16, a__1[2] = " IS NOT DEFINED."; s_cat(ch__14, a__1, i__1, &c__3, (ftnlen)44); xermsg_("SLATEC", "DBOLSM", ch__14, &c__23, &c__1, (ftnlen)6, (ftnlen) 6, (ftnlen)44); *mode = -23; return 0; } goto L590; /* Pretriangularize rectangular arrays of certain sizes for */ /* increased efficiency. */ L470: if (fac * *minput > (doublereal) (*ncols)) { i__3 = *ncols + 1; for (j = 1; j <= i__3; ++j) { i__8 = j + mval + 1; for (i__ = *minput; i__ >= i__8; --i__) { drotg_(&w[i__ - 1 + j * w_dim1], &w[i__ + j * w_dim1], &sc, & ss); w[i__ + j * w_dim1] = 0.; i__9 = *ncols - j + 1; drot_(&i__9, &w[i__ - 1 + (j + 1) * w_dim1], mdw, &w[i__ + (j + 1) * w_dim1], mdw, &sc, &ss); /* L480: */ } /* L490: */ } mrows = *ncols + mval + 1; } else { mrows = *minput; } /* Set the X(*) array to zero so all components are defined. */ dcopy_(ncols, &c_b185, &c__0, &x[1], &c__1); /* The arrays IBASIS(*) and IBB(*) are initialized by the calling */ /* program and the column scaling is defined in the calling program. */ /* 'BIG' is plus infinity on this machine. */ big = d1mach_(&c__2); i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (ind[j] == 1) { bu[j] = big; } else if (ind[j] == 2) { bl[j] = -big; } else if (ind[j] == 4) { bl[j] = -big; bu[j] = big; } /* L550: */ } i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (bl[j] <= 0. && 0. <= bu[j] && (d__1 = bu[j], abs(d__1)) < (d__2 = bl[j], abs(d__2)) || bu[j] < 0.) { t = bu[j]; bu[j] = -bl[j]; bl[j] = -t; scl[j] = -scl[j]; i__8 = mrows; for (i__ = 1; i__ <= i__8; ++i__) { w[i__ + j * w_dim1] = -w[i__ + j * w_dim1]; /* L560: */ } } /* Indices in set T(=TIGHT) are denoted by negative values */ /* of IBASIS(*). */ if (bl[j] >= 0.) { ibasis[j] = -ibasis[j]; t = -bl[j]; bu[j] += t; daxpy_(&mrows, &t, &w[j * w_dim1 + 1], &c__1, &w[(*ncols + 1) * w_dim1 + 1], &c__1); } /* L570: */ } nsetb = 0; iter = 0; if (iprint > 0) { i__3 = *ncols + 1; dmout_(&mrows, &i__3, mdw, &w[w_offset], "(' PRETRI. INPUT MATRIX')", &c_n4, (ftnlen)25); dvout_(ncols, &bl[1], "(' LOWER BOUNDS')", &c_n4, (ftnlen)17); dvout_(ncols, &bu[1], "(' UPPER BOUNDS')", &c_n4, (ftnlen)17); } L580: ++iter; if (iter > itmax) { s_wsfi(&io___54); do_fio(&c__1, (char *)&itmax, (ftnlen)sizeof(integer)); e_wsfi(); /* Writing concatenation */ i__1[0] = 18, a__1[0] = "MORE THAN ITMAX = "; i__1[1] = 8, a__1[1] = xern1; i__1[2] = 50, a__1[2] = " ITERATIONS SOLVING BOUNDED LEAST SQUARES P" "ROBLEM."; s_cat(ch__15, a__1, i__1, &c__3, (ftnlen)76); xermsg_("SLATEC", "DBOLSM", ch__15, &c__22, &c__1, (ftnlen)6, (ftnlen) 6, (ftnlen)76); *mode = -22; /* Rescale and translate variables. */ igopr = 1; goto L130; } /* Find a variable to become non-active. */ /* T */ /* Compute (negative) of gradient vector, W = E *(F-E*X). */ dcopy_(ncols, &c_b185, &c__0, &ww[1], &c__1); i__3 = *ncols; for (j = nsetb + 1; j <= i__3; ++j) { jcol = (i__8 = ibasis[j], abs(i__8)); i__8 = mrows - nsetb; /* Computing MIN */ i__9 = nsetb + 1; /* Computing MIN */ i__10 = nsetb + 1; ww[j] = ddot_(&i__8, &w[min(i__9,mrows) + j * w_dim1], &c__1, &w[min( i__10,mrows) + (*ncols + 1) * w_dim1], &c__1) * (d__1 = scl[ jcol], abs(d__1)); /* L200: */ } if (iprint > 0) { dvout_(ncols, &ww[1], "(' GRADIENT VALUES')", &c_n4, (ftnlen)20); ivout_(ncols, &ibasis[1], "(' INTERNAL VARIABLE ORDER')", &c_n4, ( ftnlen)28); ivout_(ncols, &ibb[1], "(' BOUND POLARITY')", &c_n4, (ftnlen)19); } /* If active set = number of total rows, quit. */ L210: if (nsetb == mrows) { found = FALSE_; goto L120; } /* Choose an extremal component of gradient vector for a candidate */ /* to become non-active. */ wlarge = -big; wmag = -big; i__3 = *ncols; for (j = nsetb + 1; j <= i__3; ++j) { t = ww[j]; if (t == big) { goto L220; } itemp = ibasis[j]; jcol = abs(itemp); i__8 = mval - nsetb; /* Computing MIN */ i__9 = nsetb + 1; t1 = dnrm2_(&i__8, &w[min(i__9,mrows) + j * w_dim1], &c__1); if (itemp < 0) { if (ibb[jcol] % 2 == 0) { t = -t; } if (t < 0.) { goto L220; } if (mval > nsetb) { t = t1; } if (t > wlarge) { wlarge = t; jlarge = j; } } else { if (mval > nsetb) { t = t1; } if (abs(t) > wmag) { wmag = abs(t); jmag = j; } } L220: ; } /* Choose magnitude of largest component of gradient for candidate. */ jbig = 0; wbig = 0.; if (wlarge > 0.) { jbig = jlarge; wbig = wlarge; } if (wmag >= wbig) { jbig = jmag; wbig = wmag; } if (jbig == 0) { found = FALSE_; if (iprint > 0) { ivout_(&c__0, &i__, "(' FOUND NO VARIABLE TO ENTER')", &c_n4, ( ftnlen)31); } goto L120; } /* See if the incoming column is sufficiently independent. This */ /* test is made before an elimination is performed. */ if (iprint > 0) { ivout_(&c__1, &jbig, "(' TRY TO BRING IN THIS COL.')", &c_n4, (ftnlen) 30); } if (mval <= nsetb) { cl1 = dnrm2_(&mval, &w[jbig * w_dim1 + 1], &c__1); i__3 = nsetb - mval; /* Computing MIN */ i__8 = mval + 1; cl2 = abs(wt) * dnrm2_(&i__3, &w[min(i__8,mrows) + jbig * w_dim1], & c__1); i__3 = mrows - nsetb; /* Computing MIN */ i__8 = nsetb + 1; cl3 = abs(wt) * dnrm2_(&i__3, &w[min(i__8,mrows) + jbig * w_dim1], & c__1); drotg_(&cl1, &cl2, &sc, &ss); colabv = abs(cl1); colblo = cl3; } else { cl1 = dnrm2_(&nsetb, &w[jbig * w_dim1 + 1], &c__1); i__3 = mval - nsetb; /* Computing MIN */ i__8 = nsetb + 1; cl2 = dnrm2_(&i__3, &w[min(i__8,mrows) + jbig * w_dim1], &c__1); i__3 = mrows - mval; /* Computing MIN */ i__8 = mval + 1; cl3 = abs(wt) * dnrm2_(&i__3, &w[min(i__8,mrows) + jbig * w_dim1], & c__1); colabv = cl1; drotg_(&cl2, &cl3, &sc, &ss); colblo = abs(cl2); } if (colblo <= tolind * colabv) { ww[jbig] = big; if (iprint > 0) { ivout_(&c__0, &i__, "(' VARIABLE IS DEPENDENT, NOT USED.')", & c_n4, (ftnlen)37); } goto L210; } /* Swap matrix columns NSETB+1 and JBIG, plus pointer information, */ /* and gradient values. */ ++nsetb; if (nsetb != jbig) { dswap_(&mrows, &w[nsetb * w_dim1 + 1], &c__1, &w[jbig * w_dim1 + 1], & c__1); dswap_(&c__1, &ww[nsetb], &c__1, &ww[jbig], &c__1); itemp = ibasis[nsetb]; ibasis[nsetb] = ibasis[jbig]; ibasis[jbig] = itemp; } /* Eliminate entries below the pivot line in column NSETB. */ if (mrows > nsetb) { i__3 = nsetb + 1; for (i__ = mrows; i__ >= i__3; --i__) { if (i__ == mval + 1) { goto L230; } drotg_(&w[i__ - 1 + nsetb * w_dim1], &w[i__ + nsetb * w_dim1], & sc, &ss); w[i__ + nsetb * w_dim1] = 0.; i__8 = *ncols - nsetb + 1; drot_(&i__8, &w[i__ - 1 + (nsetb + 1) * w_dim1], mdw, &w[i__ + ( nsetb + 1) * w_dim1], mdw, &sc, &ss); L230: ; } if (mval >= nsetb && mval < mrows) { drotg_(&w[nsetb + nsetb * w_dim1], &w[mval + 1 + nsetb * w_dim1], &sc, &ss); w[mval + 1 + nsetb * w_dim1] = 0.; i__3 = *ncols - nsetb + 1; drot_(&i__3, &w[nsetb + (nsetb + 1) * w_dim1], mdw, &w[mval + 1 + (nsetb + 1) * w_dim1], mdw, &sc, &ss); } } if (w[nsetb + nsetb * w_dim1] == 0.) { ww[nsetb] = big; --nsetb; if (iprint > 0) { ivout_(&c__0, &i__, "(' PIVOT IS ZERO, NOT USED.')", &c_n4, ( ftnlen)29); } goto L210; } /* Check that new variable is moving in the right direction. */ itemp = ibasis[nsetb]; jcol = abs(itemp); xnew = w[nsetb + (*ncols + 1) * w_dim1] / w[nsetb + nsetb * w_dim1] / ( d__1 = scl[jcol], abs(d__1)); if (itemp < 0) { /* IF(WW(NSETB).GE.ZERO.AND.XNEW.LE.ZERO) exit(quit) */ /* IF(WW(NSETB).LE.ZERO.AND.XNEW.GE.ZERO) exit(quit) */ if (ww[nsetb] >= 0. && xnew <= 0. || ww[nsetb] <= 0. && xnew >= 0.) { goto L240; } } found = TRUE_; goto L120; L240: ww[nsetb] = big; --nsetb; if (iprint > 0) { ivout_(&c__0, &i__, "(' VARIABLE HAS BAD DIRECTION, NOT USED.')", & c_n4, (ftnlen)42); } goto L210; /* Solve the triangular system. */ L270: dcopy_(&nsetb, &w[(*ncols + 1) * w_dim1 + 1], &c__1, &rw[1], &c__1); for (j = nsetb; j >= 1; --j) { rw[j] /= w[j + j * w_dim1]; jcol = (i__3 = ibasis[j], abs(i__3)); t = rw[j]; if (ibb[jcol] % 2 == 0) { rw[j] = -rw[j]; } i__3 = j - 1; d__1 = -t; daxpy_(&i__3, &d__1, &w[j * w_dim1 + 1], &c__1, &rw[1], &c__1); rw[j] /= (d__1 = scl[jcol], abs(d__1)); /* L280: */ } if (iprint > 0) { dvout_(&nsetb, &rw[1], "(' SOLN. VALUES')", &c_n4, (ftnlen)17); ivout_(&nsetb, &ibasis[1], "(' COLS. USED')", &c_n4, (ftnlen)15); } if (lgopr == 2) { dcopy_(&nsetb, &rw[1], &c__1, &x[1], &c__1); i__3 = nsetb; for (j = 1; j <= i__3; ++j) { itemp = ibasis[j]; jcol = abs(itemp); if (itemp < 0) { bou = 0.; } else { bou = bl[jcol]; } if (-bou != big) { bou /= (d__1 = scl[jcol], abs(d__1)); } if (x[j] <= bou) { jdrop1 = j; goto L340; } bou = bu[jcol]; if (bou != big) { bou /= (d__1 = scl[jcol], abs(d__1)); } if (x[j] >= bou) { jdrop2 = j; goto L340; } /* L450: */ } goto L340; } /* See if the unconstrained solution (obtained by solving the */ /* triangular system) satisfies the problem bounds. */ alpha = 2.; beta = 2.; x[nsetb] = 0.; i__3 = nsetb; for (j = 1; j <= i__3; ++j) { itemp = ibasis[j]; jcol = abs(itemp); t1 = 2.; t2 = 2.; if (itemp < 0) { bou = 0.; } else { bou = bl[jcol]; } if (-bou != big) { bou /= (d__1 = scl[jcol], abs(d__1)); } if (rw[j] <= bou) { t1 = (x[j] - bou) / (x[j] - rw[j]); } bou = bu[jcol]; if (bou != big) { bou /= (d__1 = scl[jcol], abs(d__1)); } if (rw[j] >= bou) { t2 = (bou - x[j]) / (rw[j] - x[j]); } /* If not, then compute a step length so that the variables remain */ /* feasible. */ if (t1 < alpha) { alpha = t1; jdrop1 = j; } if (t2 < beta) { beta = t2; jdrop2 = j; } /* L310: */ } constr = alpha < 2. || beta < 2.; if (! constr) { /* Accept the candidate because it satisfies the stated bounds */ /* on the variables. */ dcopy_(&nsetb, &rw[1], &c__1, &x[1], &c__1); goto L580; } /* Take a step that is as large as possible with all variables */ /* remaining feasible. */ i__3 = nsetb; for (j = 1; j <= i__3; ++j) { x[j] += min(alpha,beta) * (rw[j] - x[j]); /* L330: */ } if (alpha <= beta) { jdrop2 = 0; } else { jdrop1 = 0; } L340: if (jdrop1 + jdrop2 <= 0 || nsetb <= 0) { goto L580; } /* L350: */ jdrop = jdrop1 + jdrop2; itemp = ibasis[jdrop]; jcol = abs(itemp); if (jdrop2 > 0) { /* Variable is at an upper bound. Subtract multiple of this */ /* column from right hand side. */ t = bu[jcol]; if (itemp > 0) { bu[jcol] = t - bl[jcol]; bl[jcol] = -t; itemp = -itemp; scl[jcol] = -scl[jcol]; i__3 = jdrop; for (i__ = 1; i__ <= i__3; ++i__) { w[i__ + jdrop * w_dim1] = -w[i__ + jdrop * w_dim1]; /* L360: */ } } else { ++ibb[jcol]; if (ibb[jcol] % 2 == 0) { t = -t; } } /* Variable is at a lower bound. */ } else { if ((doublereal) itemp < 0.) { t = 0.; } else { t = -bl[jcol]; bu[jcol] += t; itemp = -itemp; } } daxpy_(&jdrop, &t, &w[jdrop * w_dim1 + 1], &c__1, &w[(*ncols + 1) * w_dim1 + 1], &c__1); /* Move certain columns left to achieve upper Hessenberg form. */ dcopy_(&jdrop, &w[jdrop * w_dim1 + 1], &c__1, &rw[1], &c__1); i__3 = nsetb; for (j = jdrop + 1; j <= i__3; ++j) { ibasis[j - 1] = ibasis[j]; x[j - 1] = x[j]; dcopy_(&j, &w[j * w_dim1 + 1], &c__1, &w[(j - 1) * w_dim1 + 1], &c__1) ; /* L370: */ } ibasis[nsetb] = itemp; w[nsetb * w_dim1 + 1] = 0.; i__3 = mrows - jdrop; dcopy_(&i__3, &w[nsetb * w_dim1 + 1], &c__0, &w[jdrop + 1 + nsetb * w_dim1], &c__1); dcopy_(&jdrop, &rw[1], &c__1, &w[nsetb * w_dim1 + 1], &c__1); /* Transform the matrix from upper Hessenberg form to upper */ /* triangular form. */ --nsetb; i__3 = nsetb; for (i__ = jdrop; i__ <= i__3; ++i__) { /* Look for small pivots and avoid mixing weighted and */ /* nonweighted rows. */ if (i__ == mval) { t = 0.; i__8 = nsetb; for (j = i__; j <= i__8; ++j) { jcol = (i__9 = ibasis[j], abs(i__9)); t1 = (d__1 = w[i__ + j * w_dim1] * scl[jcol], abs(d__1)); if (t1 > t) { jbig = j; t = t1; } /* L380: */ } goto L400; } drotg_(&w[i__ + i__ * w_dim1], &w[i__ + 1 + i__ * w_dim1], &sc, &ss); w[i__ + 1 + i__ * w_dim1] = 0.; i__8 = *ncols - i__ + 1; drot_(&i__8, &w[i__ + (i__ + 1) * w_dim1], mdw, &w[i__ + 1 + (i__ + 1) * w_dim1], mdw, &sc, &ss); /* L390: */ } goto L430; /* The triangularization is completed by giving up the Hessenberg */ /* form and triangularizing a rectangular matrix. */ L400: dswap_(&mrows, &w[i__ * w_dim1 + 1], &c__1, &w[jbig * w_dim1 + 1], &c__1); dswap_(&c__1, &ww[i__], &c__1, &ww[jbig], &c__1); dswap_(&c__1, &x[i__], &c__1, &x[jbig], &c__1); itemp = ibasis[i__]; ibasis[i__] = ibasis[jbig]; ibasis[jbig] = itemp; jbig = i__; i__3 = nsetb; for (j = jbig; j <= i__3; ++j) { i__8 = mrows; for (i__ = j + 1; i__ <= i__8; ++i__) { drotg_(&w[j + j * w_dim1], &w[i__ + j * w_dim1], &sc, &ss); w[i__ + j * w_dim1] = 0.; i__9 = *ncols - j + 1; drot_(&i__9, &w[j + (j + 1) * w_dim1], mdw, &w[i__ + (j + 1) * w_dim1], mdw, &sc, &ss); /* L410: */ } /* L420: */ } /* See if the remaining coefficients are feasible. They should be */ /* because of the way MIN(ALPHA,BETA) was chosen. Any that are not */ /* feasible will be set to their bounds and appropriately translated. */ L430: jdrop1 = 0; jdrop2 = 0; lgopr = 2; goto L270; /* Find a variable to become non-active. */ L120: if (found) { lgopr = 1; goto L270; } /* Rescale and translate variables. */ igopr = 2; L130: dcopy_(&nsetb, &x[1], &c__1, &rw[1], &c__1); dcopy_(ncols, &c_b185, &c__0, &x[1], &c__1); i__3 = nsetb; for (j = 1; j <= i__3; ++j) { jcol = (i__8 = ibasis[j], abs(i__8)); x[jcol] = rw[j] * (d__1 = scl[jcol], abs(d__1)); /* L140: */ } i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (ibb[j] % 2 == 0) { x[j] = bu[j] - x[j]; } /* L150: */ } i__3 = *ncols; for (j = 1; j <= i__3; ++j) { jcol = ibasis[j]; if (jcol < 0) { x[-jcol] = bl[-jcol] + x[-jcol]; } /* L160: */ } i__3 = *ncols; for (j = 1; j <= i__3; ++j) { if (scl[j] < 0.) { x[j] = -x[j]; } /* L170: */ } i__ = max(nsetb,mval); i__3 = mrows - i__; /* Computing MIN */ i__8 = i__ + 1; *rnorm = dnrm2_(&i__3, &w[min(i__8,mrows) + (*ncols + 1) * w_dim1], &c__1) ; if (igopr == 2) { *mode = nsetb; } return 0; } /* dbolsm_ */
/*< SUBROUTINE LPDP(A, MDA, M, N1, N2, PRGOPT, X, WNORM, MODE, WS, IS) >*/ /* Subroutine */ int lpdp_(doublereal *a, integer *mda, integer *m, integer * n1, integer *n2, doublereal *prgopt, doublereal *x, doublereal *wnorm, integer *mode, doublereal *ws, integer *is) { /* Initialized data */ static doublereal zero = 0.; static doublereal one = 1.; static doublereal fac = .1; /* System generated locals */ integer a_dim1, a_offset, i__1, i__2; /* Local variables */ integer i__, j, l, n; doublereal sc; integer iw, ix, np1; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *), dnrm2_(integer *, doublereal *, integer *); extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); integer modew; extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, doublereal *, integer *); doublereal rnorm; extern /* Subroutine */ int wnnls_(doublereal *, integer *, integer *, integer *, integer *, integer *, doublereal *, doublereal *, doublereal *, integer *, integer *, doublereal *); doublereal ynorm; /* THE EDITING REQUIRED TO CONVERT THIS SUBROUTINE FROM SINGLE TO */ /* DOUBLE PRECISION INVOLVES THE FOLLOWING CHARACTER STRING CHANGES. */ /* USE AN EDITING COMMAND (CHANGE) /STRING-1/(TO)STRING-2/. */ /* (START EDITING AT LINE WITH C++ IN COLS. 1-3.) */ /* /REAL (12 BLANKS)/DOUBLE PRECISION/,/DNRM2/DNRM2/,/DDOT/DDOT/, */ /* /DCOPY/DCOPY/,/DSCAL/DSCAL/,/DABS(/DABS(/, DABS/, DABS/,/D0/D0/ */ /* DIMENSION A(MDA,N+1),PRGOPT(*),X(N),WS((M+2)*(N+7)),IS(M+N+1), */ /* WHERE N=N1+N2. THIS IS A SLIGHT OVERESTIMATE FOR WS(*). */ /* WRITTEN BY R. J. HANSON AND K. H. HASKELL, SANDIA LABS */ /* REVISED OCT. 1, 1981. */ /* DETERMINE AN N1-VECTOR W, AND */ /* AN N2-VECTOR Z */ /* WHICH MINIMIZES THE EUCLIDEAN LENGTH OF W */ /* SUBJECT TO G*W+H*Z .GE. Y. */ /* THIS IS THE LEAST PROJECTED DISTANCE PROBLEM, LPDP. */ /* THE MATRICES G AND H ARE OF RESPECTIVE */ /* DIMENSIONS M BY N1 AND M BY N2. */ /* CALLED BY SUBPROGRAM LSI( ). */ /* THE MATRIX */ /* (G H Y) */ /* OCCUPIES ROWS 1,...,M AND COLS 1,...,N1+N2+1 OF A(*,*). */ /* THE SOLUTION (W) IS RETURNED IN X(*). */ /* (Z) */ /* THE VALUE OF MODE INDICATES THE STATUS OF */ /* THE COMPUTATION AFTER RETURNING TO THE USER. */ /* MODE=1 THE SOLUTION WAS SUCCESSFULLY OBTAINED. */ /* MODE=2 THE INEQUALITIES ARE INCONSISTENT. */ /* SUBROUTINES CALLED */ /* WNNLS SOLVES A NONNEGATIVELY CONSTRAINED LINEAR LEAST */ /* SQUARES PROBLEM WITH LINEAR EQUALITY CONSTRAINTS. */ /* PART OF THIS PACKAGE. */ /* ++ */ /* DDOT, SUBROUTINES FROM THE BLAS PACKAGE. */ /* DSCAL,DNRM2, SEE TRANS. MATH. SOFT., VOL. 5, NO. 3, P. 308. */ /* DCOPY */ /*< DOUBLE PRECISION A(MDA,1), PRGOPT(1), WS(1), WNORM, X(1) >*/ /*< INTEGER IS(1) >*/ /*< DOUBLE PRECISION FAC, ONE, RNORM, SC, YNORM, ZERO >*/ /*< DOUBLE PRECISION DDOT, DNRM2, DABS >*/ /*< DATA ZERO, ONE /0.D0,1.D0/, FAC /0.1E0/ >*/ #line 56 "../fortran/lpdp.f" /* Parameter adjustments */ #line 56 "../fortran/lpdp.f" a_dim1 = *mda; #line 56 "../fortran/lpdp.f" a_offset = 1 + a_dim1; #line 56 "../fortran/lpdp.f" a -= a_offset; #line 56 "../fortran/lpdp.f" --prgopt; #line 56 "../fortran/lpdp.f" --x; #line 56 "../fortran/lpdp.f" --ws; #line 56 "../fortran/lpdp.f" --is; #line 56 "../fortran/lpdp.f" #line 56 "../fortran/lpdp.f" /* Function Body */ /*< N = N1 + N2 >*/ #line 57 "../fortran/lpdp.f" n = *n1 + *n2; /*< MODE = 1 >*/ #line 58 "../fortran/lpdp.f" *mode = 1; /*< IF (.NOT.(M.LE.0)) GO TO 20 >*/ #line 59 "../fortran/lpdp.f" if (! (*m <= 0)) { #line 59 "../fortran/lpdp.f" goto L20; #line 59 "../fortran/lpdp.f" } /*< IF (.NOT.(N.GT.0)) GO TO 10 >*/ #line 60 "../fortran/lpdp.f" if (! (n > 0)) { #line 60 "../fortran/lpdp.f" goto L10; #line 60 "../fortran/lpdp.f" } /*< X(1) = ZERO >*/ #line 61 "../fortran/lpdp.f" x[1] = zero; /*< CALL DCOPY(N, X, 0, X, 1) >*/ #line 62 "../fortran/lpdp.f" dcopy_(&n, &x[1], &c__0, &x[1], &c__1); /*< 10 WNORM = ZERO >*/ #line 63 "../fortran/lpdp.f" L10: #line 63 "../fortran/lpdp.f" *wnorm = zero; /*< RETURN >*/ #line 64 "../fortran/lpdp.f" return 0; /*< 20 NP1 = N + 1 >*/ #line 65 "../fortran/lpdp.f" L20: #line 65 "../fortran/lpdp.f" np1 = n + 1; /* SCALE NONZERO ROWS OF INEQUALITY MATRIX TO HAVE LENGTH ONE. */ /*< DO 40 I=1,M >*/ #line 68 "../fortran/lpdp.f" i__1 = *m; #line 68 "../fortran/lpdp.f" for (i__ = 1; i__ <= i__1; ++i__) { /*< SC = DNRM2(N,A(I,1),MDA) >*/ #line 69 "../fortran/lpdp.f" sc = dnrm2_(&n, &a[i__ + a_dim1], mda); /*< IF (.NOT.(SC.NE.ZERO)) GO TO 30 >*/ #line 70 "../fortran/lpdp.f" if (! (sc != zero)) { #line 70 "../fortran/lpdp.f" goto L30; #line 70 "../fortran/lpdp.f" } /*< SC = ONE/SC >*/ #line 71 "../fortran/lpdp.f" sc = one / sc; /*< CALL DSCAL(NP1, SC, A(I,1), MDA) >*/ #line 72 "../fortran/lpdp.f" dscal_(&np1, &sc, &a[i__ + a_dim1], mda); /*< 30 CONTINUE >*/ #line 73 "../fortran/lpdp.f" L30: /*< 40 CONTINUE >*/ #line 74 "../fortran/lpdp.f" /* L40: */ #line 74 "../fortran/lpdp.f" ; #line 74 "../fortran/lpdp.f" } /* SCALE RT.-SIDE VECTOR TO HAVE LENGTH ONE (OR ZERO). */ /*< YNORM = DNRM2(M,A(1,NP1),1) >*/ #line 77 "../fortran/lpdp.f" ynorm = dnrm2_(m, &a[np1 * a_dim1 + 1], &c__1); /*< IF (.NOT.(YNORM.NE.ZERO)) GO TO 50 >*/ #line 78 "../fortran/lpdp.f" if (! (ynorm != zero)) { #line 78 "../fortran/lpdp.f" goto L50; #line 78 "../fortran/lpdp.f" } /*< SC = ONE/YNORM >*/ #line 79 "../fortran/lpdp.f" sc = one / ynorm; /*< CALL DSCAL(M, SC, A(1,NP1), 1) >*/ #line 80 "../fortran/lpdp.f" dscal_(m, &sc, &a[np1 * a_dim1 + 1], &c__1); /* SCALE COLS OF MATRIX H. */ /*< 50 J = N1 + 1 >*/ #line 83 "../fortran/lpdp.f" L50: #line 83 "../fortran/lpdp.f" j = *n1 + 1; /*< 60 IF (.NOT.(J.LE.N)) GO TO 70 >*/ #line 84 "../fortran/lpdp.f" L60: #line 84 "../fortran/lpdp.f" if (! (j <= n)) { #line 84 "../fortran/lpdp.f" goto L70; #line 84 "../fortran/lpdp.f" } /*< SC = DNRM2(M,A(1,J),1) >*/ #line 85 "../fortran/lpdp.f" sc = dnrm2_(m, &a[j * a_dim1 + 1], &c__1); /*< IF (SC.NE.ZERO) SC = ONE/SC >*/ #line 86 "../fortran/lpdp.f" if (sc != zero) { #line 86 "../fortran/lpdp.f" sc = one / sc; #line 86 "../fortran/lpdp.f" } /*< CALL DSCAL(M, SC, A(1,J), 1) >*/ #line 87 "../fortran/lpdp.f" dscal_(m, &sc, &a[j * a_dim1 + 1], &c__1); /*< X(J) = SC >*/ #line 88 "../fortran/lpdp.f" x[j] = sc; /*< J = J + 1 >*/ #line 89 "../fortran/lpdp.f" ++j; /*< GO TO 60 >*/ #line 90 "../fortran/lpdp.f" goto L60; /*< 70 IF (.NOT.(N1.GT.0)) GO TO 130 >*/ #line 91 "../fortran/lpdp.f" L70: #line 91 "../fortran/lpdp.f" if (! (*n1 > 0)) { #line 91 "../fortran/lpdp.f" goto L130; #line 91 "../fortran/lpdp.f" } /* COPY TRANSPOSE OF (H G Y) TO WORK ARRAY WS(*). */ /*< IW = 0 >*/ #line 94 "../fortran/lpdp.f" iw = 0; /*< DO 80 I=1,M >*/ #line 95 "../fortran/lpdp.f" i__1 = *m; #line 95 "../fortran/lpdp.f" for (i__ = 1; i__ <= i__1; ++i__) { /* MOVE COL OF TRANSPOSE OF H INTO WORK ARRAY. */ /*< CALL DCOPY(N2, A(I,N1+1), MDA, WS(IW+1), 1) >*/ #line 98 "../fortran/lpdp.f" dcopy_(n2, &a[i__ + (*n1 + 1) * a_dim1], mda, &ws[iw + 1], &c__1); /*< IW = IW + N2 >*/ #line 99 "../fortran/lpdp.f" iw += *n2; /* MOVE COL OF TRANSPOSE OF G INTO WORK ARRAY. */ /*< CALL DCOPY(N1, A(I,1), MDA, WS(IW+1), 1) >*/ #line 102 "../fortran/lpdp.f" dcopy_(n1, &a[i__ + a_dim1], mda, &ws[iw + 1], &c__1); /*< IW = IW + N1 >*/ #line 103 "../fortran/lpdp.f" iw += *n1; /* MOVE COMPONENT OF VECTOR Y INTO WORK ARRAY. */ /*< WS(IW+1) = A(I,NP1) >*/ #line 106 "../fortran/lpdp.f" ws[iw + 1] = a[i__ + np1 * a_dim1]; /*< IW = IW + 1 >*/ #line 107 "../fortran/lpdp.f" ++iw; /*< 80 CONTINUE >*/ #line 108 "../fortran/lpdp.f" /* L80: */ #line 108 "../fortran/lpdp.f" } /*< WS(IW+1) = ZERO >*/ #line 109 "../fortran/lpdp.f" ws[iw + 1] = zero; /*< CALL DCOPY(N, WS(IW+1), 0, WS(IW+1), 1) >*/ #line 110 "../fortran/lpdp.f" dcopy_(&n, &ws[iw + 1], &c__0, &ws[iw + 1], &c__1); /*< IW = IW + N >*/ #line 111 "../fortran/lpdp.f" iw += n; /*< WS(IW+1) = ONE >*/ #line 112 "../fortran/lpdp.f" ws[iw + 1] = one; /*< IW = IW + 1 >*/ #line 113 "../fortran/lpdp.f" ++iw; /* SOLVE EU=F SUBJECT TO (TRANSPOSE OF H)U=0, U.GE.0. THE */ /* MATRIX E = TRANSPOSE OF (G Y), AND THE (N+1)-VECTOR */ /* F = TRANSPOSE OF (0,...,0,1). */ /*< IX = IW + 1 >*/ #line 118 "../fortran/lpdp.f" ix = iw + 1; /*< IW = IW + M >*/ #line 119 "../fortran/lpdp.f" iw += *m; /* DO NOT CHECK LENGTHS OF WORK ARRAYS IN THIS USAGE OF WNNLS( ). */ /*< IS(1) = 0 >*/ #line 122 "../fortran/lpdp.f" is[1] = 0; /*< IS(2) = 0 >*/ #line 123 "../fortran/lpdp.f" is[2] = 0; /*< >*/ #line 124 "../fortran/lpdp.f" i__1 = np1 - *n2; #line 124 "../fortran/lpdp.f" wnnls_(&ws[1], &np1, n2, &i__1, m, &c__0, &prgopt[1], &ws[ix], &rnorm, & modew, &is[1], &ws[iw + 1]); /* COMPUTE THE COMPONENTS OF THE SOLN DENOTED ABOVE BY W. */ /*< SC = ONE - DDOT(M,A(1,NP1),1,WS(IX),1) >*/ #line 128 "../fortran/lpdp.f" sc = one - ddot_(m, &a[np1 * a_dim1 + 1], &c__1, &ws[ix], &c__1); /*< IF (.NOT.(ONE+FAC*DABS(SC).NE.ONE .AND. RNORM.GT.ZERO)) GO TO 110 >*/ #line 129 "../fortran/lpdp.f" if (! (one + fac * abs(sc) != one && rnorm > zero)) { #line 129 "../fortran/lpdp.f" goto L110; #line 129 "../fortran/lpdp.f" } /*< SC = ONE/SC >*/ #line 130 "../fortran/lpdp.f" sc = one / sc; /*< DO 90 J=1,N1 >*/ #line 131 "../fortran/lpdp.f" i__1 = *n1; #line 131 "../fortran/lpdp.f" for (j = 1; j <= i__1; ++j) { /*< X(J) = SC*DDOT(M,A(1,J),1,WS(IX),1) >*/ #line 132 "../fortran/lpdp.f" x[j] = sc * ddot_(m, &a[j * a_dim1 + 1], &c__1, &ws[ix], &c__1); /*< 90 CONTINUE >*/ #line 133 "../fortran/lpdp.f" /* L90: */ #line 133 "../fortran/lpdp.f" } /* COMPUTE THE VECTOR Q=Y-GW. OVERWRITE Y WITH THIS VECTOR. */ /*< DO 100 I=1,M >*/ #line 136 "../fortran/lpdp.f" i__1 = *m; #line 136 "../fortran/lpdp.f" for (i__ = 1; i__ <= i__1; ++i__) { /*< A(I,NP1) = A(I,NP1) - DDOT(N1,A(I,1),MDA,X,1) >*/ #line 137 "../fortran/lpdp.f" a[i__ + np1 * a_dim1] -= ddot_(n1, &a[i__ + a_dim1], mda, &x[1], & c__1); /*< 100 CONTINUE >*/ #line 138 "../fortran/lpdp.f" /* L100: */ #line 138 "../fortran/lpdp.f" } /*< GO TO 120 >*/ #line 139 "../fortran/lpdp.f" goto L120; /*< 110 MODE = 2 >*/ #line 140 "../fortran/lpdp.f" L110: #line 140 "../fortran/lpdp.f" *mode = 2; /*< RETURN >*/ #line 141 "../fortran/lpdp.f" return 0; /*< 120 CONTINUE >*/ #line 142 "../fortran/lpdp.f" L120: /*< 130 IF (.NOT.(N2.GT.0)) GO TO 180 >*/ #line 143 "../fortran/lpdp.f" L130: #line 143 "../fortran/lpdp.f" if (! (*n2 > 0)) { #line 143 "../fortran/lpdp.f" goto L180; #line 143 "../fortran/lpdp.f" } /* COPY TRANSPOSE OF (H Q) TO WORK ARRAY WS(*). */ /*< IW = 0 >*/ #line 146 "../fortran/lpdp.f" iw = 0; /*< DO 140 I=1,M >*/ #line 147 "../fortran/lpdp.f" i__1 = *m; #line 147 "../fortran/lpdp.f" for (i__ = 1; i__ <= i__1; ++i__) { /*< CALL DCOPY(N2, A(I,N1+1), MDA, WS(IW+1), 1) >*/ #line 148 "../fortran/lpdp.f" dcopy_(n2, &a[i__ + (*n1 + 1) * a_dim1], mda, &ws[iw + 1], &c__1); /*< IW = IW + N2 >*/ #line 149 "../fortran/lpdp.f" iw += *n2; /*< WS(IW+1) = A(I,NP1) >*/ #line 150 "../fortran/lpdp.f" ws[iw + 1] = a[i__ + np1 * a_dim1]; /*< IW = IW + 1 >*/ #line 151 "../fortran/lpdp.f" ++iw; /*< 140 CONTINUE >*/ #line 152 "../fortran/lpdp.f" /* L140: */ #line 152 "../fortran/lpdp.f" } /*< WS(IW+1) = ZERO >*/ #line 153 "../fortran/lpdp.f" ws[iw + 1] = zero; /*< CALL DCOPY(N2, WS(IW+1), 0, WS(IW+1), 1) >*/ #line 154 "../fortran/lpdp.f" dcopy_(n2, &ws[iw + 1], &c__0, &ws[iw + 1], &c__1); /*< IW = IW + N2 >*/ #line 155 "../fortran/lpdp.f" iw += *n2; /*< WS(IW+1) = ONE >*/ #line 156 "../fortran/lpdp.f" ws[iw + 1] = one; /*< IW = IW + 1 >*/ #line 157 "../fortran/lpdp.f" ++iw; /*< IX = IW + 1 >*/ #line 158 "../fortran/lpdp.f" ix = iw + 1; /*< IW = IW + M >*/ #line 159 "../fortran/lpdp.f" iw += *m; /* SOLVE RV=S SUBJECT TO V.GE.0. THE MATRIX R =(TRANSPOSE */ /* OF (H Q)), WHERE Q=Y-GW. THE (N2+1)-VECTOR S =(TRANSPOSE */ /* OF (0,...,0,1)). */ /* DO NOT CHECK LENGTHS OF WORK ARRAYS IN THIS USAGE OF WNNLS( ). */ /*< IS(1) = 0 >*/ #line 166 "../fortran/lpdp.f" is[1] = 0; /*< IS(2) = 0 >*/ #line 167 "../fortran/lpdp.f" is[2] = 0; /*< >*/ #line 168 "../fortran/lpdp.f" i__1 = *n2 + 1; #line 168 "../fortran/lpdp.f" i__2 = *n2 + 1; #line 168 "../fortran/lpdp.f" wnnls_(&ws[1], &i__1, &c__0, &i__2, m, &c__0, &prgopt[1], &ws[ix], &rnorm, &modew, &is[1], &ws[iw + 1]); /* COMPUTE THE COMPONENTS OF THE SOLN DENOTED ABOVE BY Z. */ /*< SC = ONE - DDOT(M,A(1,NP1),1,WS(IX),1) >*/ #line 172 "../fortran/lpdp.f" sc = one - ddot_(m, &a[np1 * a_dim1 + 1], &c__1, &ws[ix], &c__1); /*< IF (.NOT.(ONE+FAC*DABS(SC).NE.ONE .AND. RNORM.GT.ZERO)) GO TO 160 >*/ #line 173 "../fortran/lpdp.f" if (! (one + fac * abs(sc) != one && rnorm > zero)) { #line 173 "../fortran/lpdp.f" goto L160; #line 173 "../fortran/lpdp.f" } /*< SC = ONE/SC >*/ #line 174 "../fortran/lpdp.f" sc = one / sc; /*< DO 150 J=1,N2 >*/ #line 175 "../fortran/lpdp.f" i__1 = *n2; #line 175 "../fortran/lpdp.f" for (j = 1; j <= i__1; ++j) { /*< L = N1 + J >*/ #line 176 "../fortran/lpdp.f" l = *n1 + j; /*< X(L) = SC*DDOT(M,A(1,L),1,WS(IX),1)*X(L) >*/ #line 177 "../fortran/lpdp.f" x[l] = sc * ddot_(m, &a[l * a_dim1 + 1], &c__1, &ws[ix], &c__1) * x[l] ; /*< 150 CONTINUE >*/ #line 178 "../fortran/lpdp.f" /* L150: */ #line 178 "../fortran/lpdp.f" } /*< GO TO 170 >*/ #line 179 "../fortran/lpdp.f" goto L170; /*< 160 MODE = 2 >*/ #line 180 "../fortran/lpdp.f" L160: #line 180 "../fortran/lpdp.f" *mode = 2; /*< RETURN >*/ #line 181 "../fortran/lpdp.f" return 0; /*< 170 CONTINUE >*/ #line 182 "../fortran/lpdp.f" L170: /* ACCOUNT FOR SCALING OF RT.-SIDE VECTOR IN SOLUTION. */ /*< 180 CALL DSCAL(N, YNORM, X, 1) >*/ #line 185 "../fortran/lpdp.f" L180: #line 185 "../fortran/lpdp.f" dscal_(&n, &ynorm, &x[1], &c__1); /*< WNORM = DNRM2(N1,X,1) >*/ #line 186 "../fortran/lpdp.f" *wnorm = dnrm2_(n1, &x[1], &c__1); /*< RETURN >*/ #line 187 "../fortran/lpdp.f" return 0; /*< END >*/ } /* lpdp_ */
/* Subroutine */ int dsvdc_(doublereal *x, integer *ldx, integer *n, integer * p, doublereal *s, doublereal *e, doublereal *u, integer *ldu, doublereal *v, integer *ldv, doublereal *work, integer *job, integer * info) { /* System generated locals */ integer x_dim1, x_offset, u_dim1, u_offset, v_dim1, v_offset, i__1, i__2, i__3; doublereal d__1, d__2, d__3, d__4, d__5, d__6, d__7; /* Builtin functions */ double d_sign(doublereal *, doublereal *), sqrt(doublereal); /* Local variables */ static doublereal b, c__, f, g; static integer i__, j, k, l, m; static doublereal t, t1, el; static integer kk; static doublereal cs; static integer ll, mm, ls; static doublereal sl; static integer lu; static doublereal sm, sn; static integer lm1, mm1, lp1, mp1, nct, ncu, lls, nrt; static doublereal emm1, smm1; static integer kase; extern doublereal ddot_(integer *, doublereal *, integer *, doublereal *, integer *); static integer jobu, iter; extern /* Subroutine */ int drot_(integer *, doublereal *, integer *, doublereal *, integer *, doublereal *, doublereal *); static doublereal test; extern doublereal dnrm2_(integer *, doublereal *, integer *); static integer nctp1, nrtp1; extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, integer *); static doublereal scale, shift; extern /* Subroutine */ int dswap_(integer *, doublereal *, integer *, doublereal *, integer *), drotg_(doublereal *, doublereal *, doublereal *, doublereal *); static integer maxit; extern /* Subroutine */ int daxpy_(integer *, doublereal *, doublereal *, integer *, doublereal *, integer *); static logical wantu, wantv; static doublereal ztest; /* dsvdc is a subroutine to reduce a double precision nxp matrix x */ /* by orthogonal transformations u and v to diagonal form. the */ /* diagonal elements s(i) are the singular values of x. the */ /* columns of u are the corresponding left singular vectors, */ /* and the columns of v the right singular vectors. */ /* on entry */ /* x double precision(ldx,p), where ldx.ge.n. */ /* x contains the matrix whose singular value */ /* decomposition is to be computed. x is */ /* destroyed by dsvdc. */ /* ldx integer. */ /* ldx is the leading dimension of the array x. */ /* n integer. */ /* n is the number of rows of the matrix x. */ /* p integer. */ /* p is the number of columns of the matrix x. */ /* ldu integer. */ /* ldu is the leading dimension of the array u. */ /* (see below). */ /* ldv integer. */ /* ldv is the leading dimension of the array v. */ /* (see below). */ /* work double precision(n). */ /* work is a scratch array. */ /* job integer. */ /* job controls the computation of the singular */ /* vectors. it has the decimal expansion ab */ /* with the following meaning */ /* a.eq.0 do not compute the left singular */ /* vectors. */ /* a.eq.1 return the n left singular vectors */ /* in u. */ /* a.ge.2 return the first min(n,p) singular */ /* vectors in u. */ /* b.eq.0 do not compute the right singular */ /* vectors. */ /* b.eq.1 return the right singular vectors */ /* in v. */ /* on return */ /* s double precision(mm), where mm=min(n+1,p). */ /* the first min(n,p) entries of s contain the */ /* singular values of x arranged in descending */ /* order of magnitude. */ /* e double precision(p), */ /* e ordinarily contains zeros. however see the */ /* discussion of info for exceptions. */ /* u double precision(ldu,k), where ldu.ge.n. if */ /* joba.eq.1 then k.eq.n, if joba.ge.2 */ /* then k.eq.min(n,p). */ /* u contains the matrix of left singular vectors. */ /* u is not referenced if joba.eq.0. if n.le.p */ /* or if joba.eq.2, then u may be identified with x */ /* in the subroutine call. */ /* v double precision(ldv,p), where ldv.ge.p. */ /* v contains the matrix of right singular vectors. */ /* v is not referenced if job.eq.0. if p.le.n, */ /* then v may be identified with x in the */ /* subroutine call. */ /* info integer. */ /* the singular values (and their corresponding */ /* singular vectors) s(info+1),s(info+2),...,s(m) */ /* are correct (here m=min(n,p)). thus if */ /* info.eq.0, all the singular values and their */ /* vectors are correct. in any event, the matrix */ /* b = trans(u)*x*v is the bidiagonal matrix */ /* with the elements of s on its diagonal and the */ /* elements of e on its super-diagonal (trans(u) */ /* is the transpose of u). thus the singular */ /* values of x and b are the same. */ /* linpack. this version dated 08/14/78 . */ /* correction made to shift 2/84. */ /* g.w. stewart, university of maryland, argonne national lab. */ /* dsvdc uses the following functions and subprograms. */ /* external drot */ /* blas daxpy,ddot,dscal,dswap,dnrm2,drotg */ /* fortran dabs,dmax1,max0,min0,mod,dsqrt */ /* internal variables */ /* set the maximum number of iterations. */ /* Parameter adjustments */ x_dim1 = *ldx; x_offset = 1 + x_dim1; x -= x_offset; --s; --e; u_dim1 = *ldu; u_offset = 1 + u_dim1; u -= u_offset; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; --work; /* Function Body */ maxit = 30; /* determine what is to be computed. */ wantu = FALSE_; wantv = FALSE_; jobu = *job % 100 / 10; ncu = *n; if (jobu > 1) { ncu = min(*n,*p); } if (jobu != 0) { wantu = TRUE_; } if (*job % 10 != 0) { wantv = TRUE_; } /* reduce x to bidiagonal form, storing the diagonal elements */ /* in s and the super-diagonal elements in e. */ *info = 0; /* Computing MIN */ i__1 = *n - 1; nct = min(i__1,*p); /* Computing MAX */ /* Computing MIN */ i__3 = *p - 2; i__1 = 0, i__2 = min(i__3,*n); nrt = max(i__1,i__2); lu = max(nct,nrt); if (lu < 1) { goto L170; } i__1 = lu; for (l = 1; l <= i__1; ++l) { lp1 = l + 1; if (l > nct) { goto L20; } /* compute the transformation for the l-th column and */ /* place the l-th diagonal in s(l). */ i__2 = *n - l + 1; s[l] = dnrm2_(&i__2, &x[l + l * x_dim1], &c__1); if (s[l] == 0.) { goto L10; } if (x[l + l * x_dim1] != 0.) { s[l] = d_sign(&s[l], &x[l + l * x_dim1]); } i__2 = *n - l + 1; d__1 = 1. / s[l]; dscal_(&i__2, &d__1, &x[l + l * x_dim1], &c__1); x[l + l * x_dim1] += 1.; L10: s[l] = -s[l]; L20: if (*p < lp1) { goto L50; } i__2 = *p; for (j = lp1; j <= i__2; ++j) { if (l > nct) { goto L30; } if (s[l] == 0.) { goto L30; } /* apply the transformation. */ i__3 = *n - l + 1; t = -ddot_(&i__3, &x[l + l * x_dim1], &c__1, &x[l + j * x_dim1], & c__1) / x[l + l * x_dim1]; i__3 = *n - l + 1; daxpy_(&i__3, &t, &x[l + l * x_dim1], &c__1, &x[l + j * x_dim1], & c__1); L30: /* place the l-th row of x into e for the */ /* subsequent calculation of the row transformation. */ e[j] = x[l + j * x_dim1]; /* L40: */ } L50: if (! wantu || l > nct) { goto L70; } /* place the transformation in u for subsequent back */ /* multiplication. */ i__2 = *n; for (i__ = l; i__ <= i__2; ++i__) { u[i__ + l * u_dim1] = x[i__ + l * x_dim1]; /* L60: */ } L70: if (l > nrt) { goto L150; } /* compute the l-th row transformation and place the */ /* l-th super-diagonal in e(l). */ i__2 = *p - l; e[l] = dnrm2_(&i__2, &e[lp1], &c__1); if (e[l] == 0.) { goto L80; } if (e[lp1] != 0.) { e[l] = d_sign(&e[l], &e[lp1]); } i__2 = *p - l; d__1 = 1. / e[l]; dscal_(&i__2, &d__1, &e[lp1], &c__1); e[lp1] += 1.; L80: e[l] = -e[l]; if (lp1 > *n || e[l] == 0.) { goto L120; } /* apply the transformation. */ i__2 = *n; for (i__ = lp1; i__ <= i__2; ++i__) { work[i__] = 0.; /* L90: */ } i__2 = *p; for (j = lp1; j <= i__2; ++j) { i__3 = *n - l; daxpy_(&i__3, &e[j], &x[lp1 + j * x_dim1], &c__1, &work[lp1], & c__1); /* L100: */ } i__2 = *p; for (j = lp1; j <= i__2; ++j) { i__3 = *n - l; d__1 = -e[j] / e[lp1]; daxpy_(&i__3, &d__1, &work[lp1], &c__1, &x[lp1 + j * x_dim1], & c__1); /* L110: */ } L120: if (! wantv) { goto L140; } /* place the transformation in v for subsequent */ /* back multiplication. */ i__2 = *p; for (i__ = lp1; i__ <= i__2; ++i__) { v[i__ + l * v_dim1] = e[i__]; /* L130: */ } L140: L150: /* L160: */ ; } L170: /* set up the final bidiagonal matrix or order m. */ /* Computing MIN */ i__1 = *p, i__2 = *n + 1; m = min(i__1,i__2); nctp1 = nct + 1; nrtp1 = nrt + 1; if (nct < *p) { s[nctp1] = x[nctp1 + nctp1 * x_dim1]; } if (*n < m) { s[m] = 0.; } if (nrtp1 < m) { e[nrtp1] = x[nrtp1 + m * x_dim1]; } e[m] = 0.; /* if required, generate u. */ if (! wantu) { goto L300; } if (ncu < nctp1) { goto L200; } i__1 = ncu; for (j = nctp1; j <= i__1; ++j) { i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { u[i__ + j * u_dim1] = 0.; /* L180: */ } u[j + j * u_dim1] = 1.; /* L190: */ } L200: if (nct < 1) { goto L290; } i__1 = nct; for (ll = 1; ll <= i__1; ++ll) { l = nct - ll + 1; if (s[l] == 0.) { goto L250; } lp1 = l + 1; if (ncu < lp1) { goto L220; } i__2 = ncu; for (j = lp1; j <= i__2; ++j) { i__3 = *n - l + 1; t = -ddot_(&i__3, &u[l + l * u_dim1], &c__1, &u[l + j * u_dim1], & c__1) / u[l + l * u_dim1]; i__3 = *n - l + 1; daxpy_(&i__3, &t, &u[l + l * u_dim1], &c__1, &u[l + j * u_dim1], & c__1); /* L210: */ } L220: i__2 = *n - l + 1; dscal_(&i__2, &c_b44, &u[l + l * u_dim1], &c__1); u[l + l * u_dim1] += 1.; lm1 = l - 1; if (lm1 < 1) { goto L240; } i__2 = lm1; for (i__ = 1; i__ <= i__2; ++i__) { u[i__ + l * u_dim1] = 0.; /* L230: */ } L240: goto L270; L250: i__2 = *n; for (i__ = 1; i__ <= i__2; ++i__) { u[i__ + l * u_dim1] = 0.; /* L260: */ } u[l + l * u_dim1] = 1.; L270: /* L280: */ ; } L290: L300: /* if it is required, generate v. */ if (! wantv) { goto L350; } i__1 = *p; for (ll = 1; ll <= i__1; ++ll) { l = *p - ll + 1; lp1 = l + 1; if (l > nrt) { goto L320; } if (e[l] == 0.) { goto L320; } i__2 = *p; for (j = lp1; j <= i__2; ++j) { i__3 = *p - l; t = -ddot_(&i__3, &v[lp1 + l * v_dim1], &c__1, &v[lp1 + j * v_dim1], &c__1) / v[lp1 + l * v_dim1]; i__3 = *p - l; daxpy_(&i__3, &t, &v[lp1 + l * v_dim1], &c__1, &v[lp1 + j * v_dim1], &c__1); /* L310: */ } L320: i__2 = *p; for (i__ = 1; i__ <= i__2; ++i__) { v[i__ + l * v_dim1] = 0.; /* L330: */ } v[l + l * v_dim1] = 1.; /* L340: */ } L350: /* main iteration loop for the singular values. */ mm = m; iter = 0; L360: /* quit if all the singular values have been found. */ /* ...exit */ if (m == 0) { goto L620; } /* if too many iterations have been performed, set */ /* flag and return. */ if (iter < maxit) { goto L370; } *info = m; /* ......exit */ goto L620; L370: /* this section of the program inspects for */ /* negligible elements in the s and e arrays. on */ /* completion the variables kase and l are set as follows. */ /* kase = 1 if s(m) and e(l-1) are negligible and l.lt.m */ /* kase = 2 if s(l) is negligible and l.lt.m */ /* kase = 3 if e(l-1) is negligible, l.lt.m, and */ /* s(l), ..., s(m) are not negligible (qr step). */ /* kase = 4 if e(m-1) is negligible (convergence). */ i__1 = m; for (ll = 1; ll <= i__1; ++ll) { l = m - ll; /* ...exit */ if (l == 0) { goto L400; } test = (d__1 = s[l], abs(d__1)) + (d__2 = s[l + 1], abs(d__2)); ztest = test + (d__1 = e[l], abs(d__1)); if (ztest != test) { goto L380; } e[l] = 0.; /* ......exit */ goto L400; L380: /* L390: */ ; } L400: if (l != m - 1) { goto L410; } kase = 4; goto L480; L410: lp1 = l + 1; mp1 = m + 1; i__1 = mp1; for (lls = lp1; lls <= i__1; ++lls) { ls = m - lls + lp1; /* ...exit */ if (ls == l) { goto L440; } test = 0.; if (ls != m) { test += (d__1 = e[ls], abs(d__1)); } if (ls != l + 1) { test += (d__1 = e[ls - 1], abs(d__1)); } ztest = test + (d__1 = s[ls], abs(d__1)); if (ztest != test) { goto L420; } s[ls] = 0.; /* ......exit */ goto L440; L420: /* L430: */ ; } L440: if (ls != l) { goto L450; } kase = 3; goto L470; L450: if (ls != m) { goto L460; } kase = 1; goto L470; L460: kase = 2; l = ls; L470: L480: ++l; /* perform the task indicated by kase. */ switch (kase) { case 1: goto L490; case 2: goto L520; case 3: goto L540; case 4: goto L570; } /* deflate negligible s(m). */ L490: mm1 = m - 1; f = e[m - 1]; e[m - 1] = 0.; i__1 = mm1; for (kk = l; kk <= i__1; ++kk) { k = mm1 - kk + l; t1 = s[k]; drotg_(&t1, &f, &cs, &sn); s[k] = t1; if (k == l) { goto L500; } f = -sn * e[k - 1]; e[k - 1] = cs * e[k - 1]; L500: if (wantv) { drot_(p, &v[k * v_dim1 + 1], &c__1, &v[m * v_dim1 + 1], &c__1, & cs, &sn); } /* L510: */ } goto L610; /* split at negligible s(l). */ L520: f = e[l - 1]; e[l - 1] = 0.; i__1 = m; for (k = l; k <= i__1; ++k) { t1 = s[k]; drotg_(&t1, &f, &cs, &sn); s[k] = t1; f = -sn * e[k]; e[k] = cs * e[k]; if (wantu) { drot_(n, &u[k * u_dim1 + 1], &c__1, &u[(l - 1) * u_dim1 + 1], & c__1, &cs, &sn); } /* L530: */ } goto L610; /* perform one qr step. */ L540: /* calculate the shift. */ /* Computing MAX */ d__6 = (d__1 = s[m], abs(d__1)), d__7 = (d__2 = s[m - 1], abs(d__2)), d__6 = max(d__6,d__7), d__7 = (d__3 = e[m - 1], abs(d__3)), d__6 = max(d__6,d__7), d__7 = (d__4 = s[l], abs(d__4)), d__6 = max(d__6, d__7), d__7 = (d__5 = e[l], abs(d__5)); scale = max(d__6,d__7); sm = s[m] / scale; smm1 = s[m - 1] / scale; emm1 = e[m - 1] / scale; sl = s[l] / scale; el = e[l] / scale; /* Computing 2nd power */ d__1 = emm1; b = ((smm1 + sm) * (smm1 - sm) + d__1 * d__1) / 2.; /* Computing 2nd power */ d__1 = sm * emm1; c__ = d__1 * d__1; shift = 0.; if (b == 0. && c__ == 0.) { goto L550; } /* Computing 2nd power */ d__1 = b; shift = sqrt(d__1 * d__1 + c__); if (b < 0.) { shift = -shift; } shift = c__ / (b + shift); L550: f = (sl + sm) * (sl - sm) + shift; g = sl * el; /* chase zeros. */ mm1 = m - 1; i__1 = mm1; for (k = l; k <= i__1; ++k) { drotg_(&f, &g, &cs, &sn); if (k != l) { e[k - 1] = f; } f = cs * s[k] + sn * e[k]; e[k] = cs * e[k] - sn * s[k]; g = sn * s[k + 1]; s[k + 1] = cs * s[k + 1]; if (wantv) { drot_(p, &v[k * v_dim1 + 1], &c__1, &v[(k + 1) * v_dim1 + 1], & c__1, &cs, &sn); } drotg_(&f, &g, &cs, &sn); s[k] = f; f = cs * e[k] + sn * s[k + 1]; s[k + 1] = -sn * e[k] + cs * s[k + 1]; g = sn * e[k + 1]; e[k + 1] = cs * e[k + 1]; if (wantu && k < *n) { drot_(n, &u[k * u_dim1 + 1], &c__1, &u[(k + 1) * u_dim1 + 1], & c__1, &cs, &sn); } /* L560: */ } e[m - 1] = f; ++iter; goto L610; /* convergence. */ L570: /* make the singular value positive. */ if (s[l] >= 0.) { goto L580; } s[l] = -s[l]; if (wantv) { dscal_(p, &c_b44, &v[l * v_dim1 + 1], &c__1); } L580: /* order the singular value. */ L590: if (l == mm) { goto L600; } /* ...exit */ if (s[l] >= s[l + 1]) { goto L600; } t = s[l]; s[l] = s[l + 1]; s[l + 1] = t; if (wantv && l < *p) { dswap_(p, &v[l * v_dim1 + 1], &c__1, &v[(l + 1) * v_dim1 + 1], &c__1); } if (wantu && l < *n) { dswap_(n, &u[l * u_dim1 + 1], &c__1, &u[(l + 1) * u_dim1 + 1], &c__1); } ++l; goto L590; L600: iter = 0; --m; L610: goto L360; L620: return 0; } /* dsvdc_ */